mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
79
Commits
+2
-1
@@ -44,6 +44,7 @@ packages/react-native/flow/
|
||||
|
||||
[options]
|
||||
enums=true
|
||||
as_const=true
|
||||
casting_syntax=both
|
||||
|
||||
emoji=true
|
||||
@@ -95,4 +96,4 @@ untyped-import
|
||||
untyped-type-import
|
||||
|
||||
[version]
|
||||
^0.254.2
|
||||
^0.255.0
|
||||
|
||||
+382
@@ -1,5 +1,387 @@
|
||||
# Changelog
|
||||
|
||||
## v0.77.0-rc.0
|
||||
|
||||
### Breaking
|
||||
|
||||
- Bridgeless: Make NativeModules.foo load turbomodules (unset turboModuleProxy in bridgeless). ([cc5f17d5a2](https://github.com/facebook/react-native/commit/cc5f17d5a2b185de1e7dec2a56a97b088e4c7a81) by [@RSNara](https://github.com/RSNara))
|
||||
- dev-middleware: Frameworks should specify `serverBaseUrl` relative to the middleware host. ([acf384a72e](https://github.com/facebook/react-native/commit/acf384a72e599691e4c9d53043f1801da01c58fd) by [@robhogan](https://github.com/robhogan))
|
||||
- `position` of sticky headers on `ScrollView` will now be taken into account ([cbab004eb9](https://github.com/facebook/react-native/commit/cbab004eb94f8312e9b10dae1502d3ca8632a006) by [@joevilches](https://github.com/joevilches))
|
||||
- Remove ReactFabricInternals module ([0c21db360c](https://github.com/facebook/react-native/commit/0c21db360cecc6a3265eea50d628106c58b67af8) by [@huntie](https://github.com/huntie))
|
||||
- Make ReactDebugOverlayTags, DebugOverlayTags, Printer, PrinterHolder, NoopPrinter internal ([623d481991](https://github.com/facebook/react-native/commit/623d4819915e7e6fafb8006c8e3b3b796e394974) by [@cortinico](https://github.com/cortinico))
|
||||
- More spec compliant absolute positioning ([0a2dec175e](https://github.com/facebook/react-native/commit/0a2dec175e92185943907f3e1f6073bae6cd663d) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- Native looping animation will not send React state update every time it finishes. ([4b035d820d](https://github.com/facebook/react-native/commit/4b035d820d3f1c3c9a98ce4f55bcc95a7ab064bf) by [@dmytrorykun](https://github.com/dmytrorykun))
|
||||
|
||||
#### Android specific
|
||||
|
||||
- Removed ReactViewGroup.getBackgroundColor() ([6a472c5cf2](https://github.com/facebook/react-native/commit/6a472c5cf25d72f72ec7e261282d611a5ab0a662) by Thomas Nardone)
|
||||
- ReadableArray non-primitive getters are now correctly typed as optional ([145c72f816](https://github.com/facebook/react-native/commit/145c72f8163048f0eee30d5ce850911f5dad865c) by [@javache](https://github.com/javache))
|
||||
- Remove jsBundleLoader from DefaultReactHost.getDefaultReactHost() ([fbe4c0ed34](https://github.com/facebook/react-native/commit/fbe4c0ed347156a7ea24da29e09083a499c80cf5) by [@mdvacca](https://github.com/mdvacca))
|
||||
- Reduce visibility of TaskCompletionSource class ([4f55161132](https://github.com/facebook/react-native/commit/4f551611326d63b6fb5cd53e63d536c2c6f04647) by [@mdvacca](https://github.com/mdvacca))
|
||||
- Stable API - Make ImageStoreManager internal ([846c4b1ea2](https://github.com/facebook/react-native/commit/846c4b1ea2d139e3f3cbafa2f8ddbf159e3322e4) by [@arushikesarwani94](https://github.com/arushikesarwani94))
|
||||
- Stable API - Make SwipeRefreshLayoutManager internal ([d02da992a4](https://github.com/facebook/react-native/commit/d02da992a4c0893313b9f059a8be228f43fffa7a) by Thomas Nardone)
|
||||
- Undo breaking change of UiManager.eventDispatcher return type ([7817ab5de2](https://github.com/facebook/react-native/commit/7817ab5de2ce324df734a5dfd705f2454937328f) by [@cortinico](https://github.com/cortinico))
|
||||
- Stable API - Make classes inside `com.facebook.react.views.progressbar` internal ([46526fc2fe](https://github.com/facebook/react-native/commit/46526fc2fe1dd0ce937fad35469b64b9fb05eaa2) by [@cortinico](https://github.com/cortinico))
|
||||
- Undo breaking change of UiManager.eventDispatcher return type ([dbe509a23a](https://github.com/facebook/react-native/commit/dbe509a23a974f16804aefea055a24c06910b259) by [@cortinico](https://github.com/cortinico))
|
||||
- Stable API - Make OkHttpCallUtil internal ([abd118a719](https://github.com/facebook/react-native/commit/abd118a719fe0aeb13f980729ff9ce5fb8358b83) by [@arushikesarwani94](https://github.com/arushikesarwani94))
|
||||
- Stable API - Make SimpleSettableFuture internal ([3dec672398](https://github.com/facebook/react-native/commit/3dec672398729cd668aff92249f1fdde231fb928) by [@arushikesarwani94](https://github.com/arushikesarwani94))
|
||||
- Stable API - Make `ClipboardModule` internal ([10f6d5adb5](https://github.com/facebook/react-native/commit/10f6d5adb538a9b20043312fc09b192759100d63) by [@cortinico](https://github.com/cortinico))
|
||||
- Reduce visibility of ReactVirtualTextShadowNode to internal ([496b0a8729](https://github.com/facebook/react-native/commit/496b0a8729b41266683fdd84de5618b23d06ce3d) by [@mdvacca](https://github.com/mdvacca))
|
||||
- Reduce visibility of ReactVirtualTextViewManager to internal ([4a119c4c3a](https://github.com/facebook/react-native/commit/4a119c4c3ac9bf4b234e2942a27a6efd68a801cc) by [@mdvacca](https://github.com/mdvacca))
|
||||
- Stable API - Make classes in `com.facebook.react.views.safeareaview` internal ([39dfbadd5d](https://github.com/facebook/react-native/commit/39dfbadd5d3468d079bf3b039401237c6e7f363c) by [@cortinico](https://github.com/cortinico))
|
||||
- Stable API - Make ClipboardModule internal ([a72c35f98c](https://github.com/facebook/react-native/commit/a72c35f98ccd1a49d367678b46a29c814ad5de43) by [@cortinico](https://github.com/cortinico))
|
||||
- Undo a breaking change on ReactViewGroup constructor ([bbe714e487](https://github.com/facebook/react-native/commit/bbe714e487fb51c61820fdc5d89c9782da79b657) by [@cortinico](https://github.com/cortinico))
|
||||
- Stable API - Make NativeModulePerfLogger internal ([d7d5de9f96](https://github.com/facebook/react-native/commit/d7d5de9f9630e7dcd0194830d7ccb32f167b619c) by [@cortinico](https://github.com/cortinico))
|
||||
- Make `DevLoadingModule` internal ([8c50bf0beb](https://github.com/facebook/react-native/commit/8c50bf0beb17ced7fdafeae7a734edfc03e6e0b2) by [@cortinico](https://github.com/cortinico))
|
||||
- Stable API - Convert to Kotlin and make internal `NotThreadSafeViewHierarchyUpdateDebugListener` ([287e200332](https://github.com/facebook/react-native/commit/287e20033207df5e59d199a347b7ae2b4cd7a59e) by [@cortinico](https://github.com/cortinico))
|
||||
- Rename DevSupportManagerBase.getCurrentContext() -> getCurrentReactContext() ([0e7ba9094e](https://github.com/facebook/react-native/commit/0e7ba9094ea573d1512b2dc71e46f55b24201b7a) by [@RSNara](https://github.com/RSNara))
|
||||
- Make DevSupportManagerBase.getCurrentReactContext() public ([5a6a42c7d0](https://github.com/facebook/react-native/commit/5a6a42c7d029d44799cb907c0ca3c8aa38fa1770) by [@RSNara](https://github.com/RSNara))
|
||||
- Reduce visibility of ReactUnimplementedViewManager to internal ([fe656be26e](https://github.com/facebook/react-native/commit/fe656be26e0d71bf2505032578dbea54af36b2c5) by [@mdvacca](https://github.com/mdvacca))
|
||||
- Stable API - Make InteropModuleRegistry internal ([cba1d4bae7](https://github.com/facebook/react-native/commit/cba1d4bae7285ba160b05f31ca18cfa0b91e9ef5) by [@cortinico](https://github.com/cortinico))
|
||||
- Stable API - Make ReactDevToolsSettingsManagerModule and ReactDevToolsRuntimeSettingsModule internal ([d7550293a2](https://github.com/facebook/react-native/commit/d7550293a2530f02f75b4249b7e6003edaf28ac9) by [@cortinico](https://github.com/cortinico))
|
||||
- Added JSBundleLoader as parameter of DefaultReactHost ([143b9d172c](https://github.com/facebook/react-native/commit/143b9d172ca755e2457e8dfc6009eeef2475a4a1) by [@mdvacca](https://github.com/mdvacca))
|
||||
- Deleting deprecated CompositeReactPackage ([2cb5198f1b](https://github.com/facebook/react-native/commit/2cb5198f1b589a57a4cfd3cc40a9ed6224fc5d75) by [@mdvacca](https://github.com/mdvacca))
|
||||
- Make ReactHost.createSurface() method non nullable ([70c7616535](https://github.com/facebook/react-native/commit/70c761653564653bdfcb77a8c5ef3608dafcf5d7) by [@mdvacca](https://github.com/mdvacca))
|
||||
- Stable API - Make AppStateModule internal ([dbf09fbe58](https://github.com/facebook/react-native/commit/dbf09fbe5823d77556b451317c14f833735067d9) by [@cortinico](https://github.com/cortinico))
|
||||
- Undo breaking change on UIManager eventDispatcher accessor ([dc1a498d39](https://github.com/facebook/react-native/commit/dc1a498d3974680f2257efd8ff9ec3f989204c68) by [@cortinico](https://github.com/cortinico))
|
||||
- Make `AccessibilityInfoModule` internal ([7168a9d1a2](https://github.com/facebook/react-native/commit/7168a9d1a2ed7459ebb056ebe45d86de791013e3) by [@cortinico](https://github.com/cortinico))
|
||||
- Undo breaking change on ViewManagerDelegate.kt String params ([2d2bb9c588](https://github.com/facebook/react-native/commit/2d2bb9c58824af34392bda196fbf0be17498cc05) by [@cortinico](https://github.com/cortinico))
|
||||
- Add 3 methods to ReactInstanceDevHelper ([c867aba2f3](https://github.com/facebook/react-native/commit/c867aba2f3dd7773be9d2ee0827bcd69481a394e) by [@cortinico](https://github.com/cortinico))
|
||||
- Add test case for set opacity in new arch examples ([848471b69f](https://github.com/facebook/react-native/commit/848471b69f59094780ace25c6963e480d94ec5c3) by [@poonamjain96](https://github.com/poonamjain96))
|
||||
- Add test for Console.log measure in new-arch-examples ([8cf27e8b6f](https://github.com/facebook/react-native/commit/8cf27e8b6f112d646111ddaba0b5036cafac3299) by [@poonamjain96](https://github.com/poonamjain96))
|
||||
- Remove Deprecated DefaultDevSupportManagerFactory.create() ([f25abe51ce](https://github.com/facebook/react-native/commit/f25abe51ce93b97ef1fe97af5fc76f13a5a6ff03) by [@cortinico](https://github.com/cortinico))
|
||||
- Remove BaseViewManagerInterface ([7fb3d830be](https://github.com/facebook/react-native/commit/7fb3d830beae3daf431ac90e9326b744ff8300a1) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- Chore: test case added for Image ([d0e5053528](https://github.com/facebook/react-native/commit/d0e50535287088030e60e131691c8d9ed1d57989) by [@sarthak-d11](https://github.com/sarthak-d11))
|
||||
- Remove ReactNativeFlipper object, deprecated in 0.75 ([d1a256f51a](https://github.com/facebook/react-native/commit/d1a256f51a43f465823bdfb8a70fae5f92473d7c) by [@cortinico](https://github.com/cortinico))
|
||||
- Add test for background color and border width in text.yml ([fa62b7e1ed](https://github.com/facebook/react-native/commit/fa62b7e1ed00c69819d85819c6209fb42bedb233) by [@muskan27797](https://github.com/muskan27797))
|
||||
- Added Submit Application test to button.yml ([699f73a6b0](https://github.com/facebook/react-native/commit/699f73a6b0734fe716b01d263e9579bca38c4652) by [@shubhamguptadream11](https://github.com/shubhamguptadream11))
|
||||
- Use BackgroundStyleApplicator when setting background color in BaseViewManager ([309cdea337](https://github.com/facebook/react-native/commit/309cdea337101cfe2212cfb6abebf1e783e43282) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- Delete useTurboModules, enableFabricRenderer and enableBridgelessArchitecture fields from ReactFeatureFlags class ([10a33e0479](https://github.com/facebook/react-native/commit/10a33e04793befbeab6ae82d4068b1ebd7fdffd0) by [@mdvacca](https://github.com/mdvacca))
|
||||
- Remove ReactViewBackgroundManager and ReactViewBackgroundDrawable ([51673e41ae](https://github.com/facebook/react-native/commit/51673e41ae12f06b2b378e048094ad39ca30c317) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
|
||||
#### iOS specific
|
||||
|
||||
- Use the RCTDependencyProvider in the RCTAppDelegate, breaking the dependency with Codegen ([b91626af26](https://github.com/facebook/react-native/commit/b91626af2626bf611958b1e7d0dd0b7338ccc29e) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Delete experimental API RCTConstants.RCTGetMemoryPressureUnloadLevel ([d79dc48abd](https://github.com/facebook/react-native/commit/d79dc48abd2e65e4d203e488f99eb554c473a1fc) by [@mdvacca](https://github.com/mdvacca))
|
||||
- ([6fc500ee99](https://github.com/facebook/react-native/commit/6fc500ee9942e51519545c1ba1026bacad03dc61) by [@philIip](https://github.com/philIip))
|
||||
- ([538bff710f](https://github.com/facebook/react-native/commit/538bff710f7afb4afa7ce91f20074668ad5c739d) by [@philIip](https://github.com/philIip))
|
||||
- Replace uses of `CGColorRef` with UIColor to avoid manual memory management ([b70709dbc2](https://github.com/facebook/react-native/commit/b70709dbc27c75c69e9fd2b082ffa27e7e8db7fd) by [@Saadnajmi](https://github.com/Saadnajmi))
|
||||
- Cocoapods decide the C++ version for iOS pods ([bd50c4a460](https://github.com/facebook/react-native/commit/bd50c4a460a01dad3cd7cade8191273563675d24) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Delete partialBatchDidFlush ([a777a8937e](https://github.com/facebook/react-native/commit/a777a8937ee165993d7d9b35c7c981fe6698f9dc) by [@philIip](https://github.com/philIip))
|
||||
- We deprecated RCTRuntimeExecutor in 0.76, so let's get rid of the code now. ([cf8d09b279](https://github.com/facebook/react-native/commit/cf8d09b279c4bd667d96f9445c1c0b9acb0a0dfc) by [@philIip](https://github.com/philIip))
|
||||
- Unbreak `RCTHermesInstance` constructor breaking change ([aec6666bfa](https://github.com/facebook/react-native/commit/aec6666bfabf93cde70fa869b3eea68590998dee) by [@tido64](https://github.com/tido64))
|
||||
|
||||
### Added
|
||||
|
||||
- Add FuseboxPerfettoDataSource to emit Fusebox traces using Perfetto ([ef0ea4d834](https://github.com/facebook/react-native/commit/ef0ea4d834ec61c5deede487b46a787a363f6a64) by Benoit Girard)
|
||||
- Add support for `rn_rootThreshold` in Intersection Observer ([a77d8d9d50](https://github.com/facebook/react-native/commit/a77d8d9d50e69a6a4563737c2ce68d26204eda7f) by [@lunaleaps](https://github.com/lunaleaps))
|
||||
- Codegen: Support negative values in enums ([177bf4d043](https://github.com/facebook/react-native/commit/177bf4d043ce862911e477e0f0039214d8541cfd) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
- Use the TypeScript key in syntax to restrict permissions and types of results ([0244710c4b](https://github.com/facebook/react-native/commit/0244710c4b1e5016069ec9f7b8e7116ff51f59f1) by [@qnnp-me](https://github.com/qnnp-me))
|
||||
- Image `resizeMode` and `objectFit` support for `'none'`. ([d8cfd98070](https://github.com/facebook/react-native/commit/d8cfd98070cbccc5e8a49446d76bdc2cb0c6939f) by [@mateoguzmana](https://github.com/mateoguzmana))
|
||||
- Add NumberLiteralTypeAnnotation support ([dd472101b7](https://github.com/facebook/react-native/commit/dd472101b76a964b7a64f0bb84d967f702500cad) by [@elicwhite](https://github.com/elicwhite))
|
||||
- Eliminate usage of more than 1-arg `React.AbstractComponent` in React codebase ([6205aad81e](https://github.com/facebook/react-native/commit/6205aad81ef8154a106fa253a1f4b00aee568650) by [@SamChou19815](https://github.com/SamChou19815))
|
||||
- Added support for `display: contents` ([e7a3f479fe](https://github.com/facebook/react-native/commit/e7a3f479fe37a5d503770bafc03c80b1c2dcb8f7) by [@j-piasecki](https://github.com/j-piasecki))
|
||||
- Added the missing `announceForAccessibilityWithOptions` function mock in the `packages/react-native/jest/setup.js` file. ([4ae999b90b](https://github.com/facebook/react-native/commit/4ae999b90b2a67233890d30a8bff0dbdd58364f2) by [@ChrisMattew](https://github.com/ChrisMattew))
|
||||
- Add support for reload-to-profile in Fusebox (Part 2 of 2: JS) ([4df224ca6d](https://github.com/facebook/react-native/commit/4df224ca6df9dc593ab7090520578f27c520f361) by [@EdmondChuiHW](https://github.com/EdmondChuiHW))
|
||||
- Add JS layer for new text content type cellular EID and cellular IMEI ([118c1f7035](https://github.com/facebook/react-native/commit/118c1f7035cfcadb567b1ccd40d85c751dd65162) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Add support for reload-to-profile in Fusebox. (Part 1 of 2: native) ([91a40a28de](https://github.com/facebook/react-native/commit/91a40a28de3f74a389c6e6ad05fb917d58fc072d) by [@EdmondChuiHW](https://github.com/EdmondChuiHW))
|
||||
- Add cli --help details to combine-js-toschema-cli.js ([e4814b0d6d](https://github.com/facebook/react-native/commit/e4814b0d6d981cf96eef2803e8f20548263ea0e4) by [@blakef](https://github.com/blakef))
|
||||
- Codegen for Native Modules now supports string literals ([d2f3f06826](https://github.com/facebook/react-native/commit/d2f3f06826e2287ad5f5dc4e27201fc5dc9fcd5c) by [@elicwhite](https://github.com/elicwhite))
|
||||
- Codegen now supports Union Types in NativeModules ([3af126b562](https://github.com/facebook/react-native/commit/3af126b562cf7e0828906a4fe0ac79a886b557e6) by [@elicwhite](https://github.com/elicwhite))
|
||||
- Updated FlatList setNativeProps type ([b0ac99b477](https://github.com/facebook/react-native/commit/b0ac99b47781e3b68bee2ff737b109f58eeeba78) by [@JDMathew](https://github.com/JDMathew))
|
||||
- Added Jest mocks for `NativeAnimatedModule` ([fd355308fa](https://github.com/facebook/react-native/commit/fd355308faa2da30d4e0d68ae9b4d136d2a5f1c3) by [@yungsters](https://github.com/yungsters))
|
||||
- Added `HostInstance` type to represent the instance of a `HostComponent<T>`. ([e24f9917c2](https://github.com/facebook/react-native/commit/e24f9917c25ed8c32c6e01d50a5fa49fe66a6ee1) by [@yungsters](https://github.com/yungsters))
|
||||
- Export `DevMenu` from `react-native` ([e12c0d9551](https://github.com/facebook/react-native/commit/e12c0d95516924b5e6ca4f0d5ebcadb42bb19f30) by [@frankcalise](https://github.com/frankcalise))
|
||||
- Removed `experimental` prefix and fully released `mixBlendMode` prop ([d2c48f3b1a](https://github.com/facebook/react-native/commit/d2c48f3b1a2a15e9832ea3240c19aea5186ceb24) by [@jorge-cab](https://github.com/jorge-cab))
|
||||
- Add Playground to RNTester for testing out features & submitting reproducers. ([256adcab7b](https://github.com/facebook/react-native/commit/256adcab7b02e8a80227d44b76d1a74d8c4973de) by [@shwanton](https://github.com/shwanton))
|
||||
- Add color formatting to codegen output ([1747f57c67](https://github.com/facebook/react-native/commit/1747f57c6708ffa59ea511f9fbbacf37364fde72) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
- Added overlayColor prop to modal component for customisable background overlay ([4e1d7015c1](https://github.com/facebook/react-native/commit/4e1d7015c1d4e2703133b1347ed97a0cc93b1318) by [@shubhamguptadream11](https://github.com/shubhamguptadream11))
|
||||
- Created an experimental optimization to improve memoization within `Animated` to improve product performance ([dc84d00db6](https://github.com/facebook/react-native/commit/dc84d00db64b78234e91c2b73f4d4fce8782cd02) by [@yungsters](https://github.com/yungsters))
|
||||
- Expose missing text content type to JS ([d3d48cb357](https://github.com/facebook/react-native/commit/d3d48cb357e55b1f2ae0042a5960451fbe5ff5c7) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Created an experimental (unstable) method for allowlisting props when using `Animated` ([f3f652daab](https://github.com/facebook/react-native/commit/f3f652daabc4a1d374190165ac38715ad31a5214) by [@yungsters](https://github.com/yungsters))
|
||||
- Upgrade Flow to 0.245.2 ([1f65bf9545](https://github.com/facebook/react-native/commit/1f65bf9545cd84bbf1be7a7a91cb0b4f8b4b47ba) by [@SamChou19815](https://github.com/SamChou19815))
|
||||
|
||||
#### Android specific
|
||||
|
||||
- Image `force-cache` caching control option ([a0be88fd72](https://github.com/facebook/react-native/commit/a0be88fd727898d4626ca51876d0bfb4e50dcb77) by [@mateoguzmana](https://github.com/mateoguzmana))
|
||||
- Add overlapping radii resolution logic preventing incorrect rendering ([451ff70da4](https://github.com/facebook/react-native/commit/451ff70da422beefccfff5b87024145003bb49ff) by [@jorge-cab](https://github.com/jorge-cab))
|
||||
- Marked ReactPackage#getModule as stable. ([8fba7ebb5e](https://github.com/facebook/react-native/commit/8fba7ebb5e874d001dc5c16eb4229054a2ef4812) by [@javache](https://github.com/javache))
|
||||
- ReactDelegate and ReactActivityDelegate#getCurrentReactContext can be used to access the current context ([fe8cc62824](https://github.com/facebook/react-native/commit/fe8cc62824372229d90445b2769fed9c08604a7e) by [@javache](https://github.com/javache))
|
||||
- Add exceptionHandler as a parameter of DefaultReactHost.getDefaultReactHost() method ([7a5a10c95c](https://github.com/facebook/react-native/commit/7a5a10c95ce6af1964ce5bd273c0c6513fb78a1e) by [@mdvacca](https://github.com/mdvacca))
|
||||
- Logic to check for grayscale mode on android ([e70202e606](https://github.com/facebook/react-native/commit/e70202e606be3101da33d28f5403443c3e84749e) by [@oddlyspaced](https://github.com/oddlyspaced))
|
||||
- TextTransform ktx ([7794d7af43](https://github.com/facebook/react-native/commit/7794d7af43b90b581574361af102f67ad7961a5e) by Thomas Nardone)
|
||||
- Add navigationBarTranslucent prop to Modal component ([7a6c7a462a](https://github.com/facebook/react-native/commit/7a6c7a462a7898e13327438a6603d83a39147abb) by [@zoontek](https://github.com/zoontek))
|
||||
- Trigger Java GC on app reload ([de3c1ee097](https://github.com/facebook/react-native/commit/de3c1ee097f7041d6f9754a55a45cea80fd25813) by [@mrousavy](https://github.com/mrousavy))
|
||||
- Add cmake arguments to support 16KB page size for native libraries ([65cdd5b82c](https://github.com/facebook/react-native/commit/65cdd5b82ce7652630b1920fa3a48c8f256c7983) by [@alanleedev](https://github.com/alanleedev))
|
||||
- Enabling basic `Image` cache control for Android ([e5dd7d68bf](https://github.com/facebook/react-native/commit/e5dd7d68bf264669fc5c4ce5e69b24249d28558b) by [@mateoguzmana](https://github.com/mateoguzmana))
|
||||
- Add OnLayoutChange API for scroll views ([d825a4d712](https://github.com/facebook/react-native/commit/d825a4d712a1ba53c0f4209c9da5d51578209a6d) by Thomas Nardone)
|
||||
- React Activity exposes ReactHost ([d78cb78b15](https://github.com/facebook/react-native/commit/d78cb78b15a520f3bebcdf00b82b26bf120f4180) by [@shwanton](https://github.com/shwanton))
|
||||
- Added PixelUtil extensions for Int and Long ([9406a09f87](https://github.com/facebook/react-native/commit/9406a09f871d3efa66e3d10237a6d1fd08ddee0b) by Thomas Nardone)
|
||||
- Add boxShadow support to BaseViewManager ([b69a92e2c9](https://github.com/facebook/react-native/commit/b69a92e2c95990fcfa95a6ab7b7260ac492f942c) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- Test: pressable test cases ([3102a58df3](https://github.com/facebook/react-native/commit/3102a58df38d96f3dacef0530e4dbb399037fcd2) by [@deepanshushuklad11](https://github.com/deepanshushuklad11))
|
||||
- Added showcase for Android `resizeMethod` options when applied to a large image ([768a1d8664](https://github.com/facebook/react-native/commit/768a1d86649e391964d404a15733c227c57c0d38) by [@Abbondanzo](https://github.com/Abbondanzo))
|
||||
- Adds a new `resizeMethod`, `none`, which disables downsampling for an image ([6202319ed5](https://github.com/facebook/react-native/commit/6202319ed544e4d23f1f327ff5334c480af3819d) by [@Abbondanzo](https://github.com/Abbondanzo))
|
||||
- Add Modal Testing to modal.yml ([1a2532b1fc](https://github.com/facebook/react-native/commit/1a2532b1fc32ec989e05576121b5e669697d29af) by [@ahmedbilal008](https://github.com/ahmedbilal008))
|
||||
- Add a new Fresco decoder for XML resource types ([118b7c18a6](https://github.com/facebook/react-native/commit/118b7c18a6f827dabb00522bbd6a2416e1bf99da) by [@Abbondanzo](https://github.com/Abbondanzo))
|
||||
- Added `isHighTextContrastEnabled()` to `AccessibilityInfo` to read `ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED` setting value ([d4ea147b41](https://github.com/facebook/react-native/commit/d4ea147b41e4d22253f80be8b74731dcf0439302) by Ariel Lin)
|
||||
- Outline properties `outline-width`, `outline-color`, `outline-style` & `outline-offset` ([17faac4170](https://github.com/facebook/react-native/commit/17faac417035f2cc5f12ec60a46270991be0989a) by [@jorge-cab](https://github.com/jorge-cab))
|
||||
- Flag in ReactFragment to allow unmounting a surface without destroying ReactHost. ([bb3ec4d6c3](https://github.com/facebook/react-native/commit/bb3ec4d6c342d3afcb109e8c65f99e7693c962b5) by [@rozele](https://github.com/rozele))
|
||||
- ReactDelegate `unloadApp` methods for unmounting surfaces without destroying ReactHost ([38593c440e](https://github.com/facebook/react-native/commit/38593c440e949a9b52df0a6821b80ac47b19a693) by [@rozele](https://github.com/rozele))
|
||||
- New feature flag for line height calculation ([f338e7c0a1](https://github.com/facebook/react-native/commit/f338e7c0a1072974b5ac76567c8d1d06f5b7c1e2) by [@mellyeliu](https://github.com/mellyeliu))
|
||||
- Adds support for importing XML assets as images ([2e80f5acf1](https://github.com/facebook/react-native/commit/2e80f5acf11cd9726921a00a58700cab9e0bb0a7) by [@Abbondanzo](https://github.com/Abbondanzo))
|
||||
|
||||
#### iOS specific
|
||||
|
||||
- Image `only-if-cached` cache control option ([dc9db01665](https://github.com/facebook/react-native/commit/dc9db01665308ac931967326abfc86deb9ae7e2a) by [@mateoguzmana](https://github.com/mateoguzmana))
|
||||
- TextInput `inputAccessoryViewButtonLabel` prop ([32931466ed](https://github.com/facebook/react-native/commit/32931466ed7e3d8d9eeeb65f12ce146e123870ba) by [@mateoguzmana](https://github.com/mateoguzmana))
|
||||
- Fix: Correct Layout Behavior for Combined align-content and align-items ([73a2be1243](https://github.com/facebook/react-native/commit/73a2be12437c93bbd138e0d63cd45d834529a3c4) by [@phuccvx12](https://github.com/phuccvx12))
|
||||
- Extract RCTAppDependencyProvider in the ReactAppDependencyProvider pod ([102062fbc7](https://github.com/facebook/react-native/commit/102062fbc7d6a5c81192562c3ccb87bc4222a0cf) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Pass the `RCTAppDependencyProvider` to the `RCTAppDelegate` ([95fc906930](https://github.com/facebook/react-native/commit/95fc906930ece9b30482eb1f0924d7e8614af7c6) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Introduce the RCTAppDependencyProvider to minimize the changes required y the users ([41c2502b36](https://github.com/facebook/react-native/commit/41c2502b3650e238b0a5d86b5044abcb538b76e3) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Add RCTDependencyProvider protocol ([f2b3716426](https://github.com/facebook/react-native/commit/f2b371642684682916522dc82adee93464ba31fe) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Added `disabledButtonTintColor` prop to ActionSheetIOS ([089c87e22e](https://github.com/facebook/react-native/commit/089c87e22e9f431d0e7f35292dce2e36fa86d09a) by [@henninghall](https://github.com/henninghall))
|
||||
- Scroll the cursor into view when text input is focused ([e021e50d53](https://github.com/facebook/react-native/commit/e021e50d537884a55a9f5bea931adb19e9069dd6) by [@dominictb](https://github.com/dominictb))
|
||||
- Introduce RCTArchConfiguratorProtocol ([ec0dbb729d](https://github.com/facebook/react-native/commit/ec0dbb729d3774184dee83efbff5f9beebce72ce) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
- Introduce RCTUIConfiguratorProtocol ([8850736188](https://github.com/facebook/react-native/commit/8850736188321f13c7bdeadedeed15c759ad72c1) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
- TvOS support for Hermes artifacts ([f673759c83](https://github.com/facebook/react-native/commit/f673759c83fed130964ea7dfe677c04608b8e64d) by [@douglowder](https://github.com/douglowder))
|
||||
- Add `CallInvoker` to `BindingsInstaller` ([87bae7f734](https://github.com/facebook/react-native/commit/87bae7f7349976cfc269b25584330c4d3d897d79) by [@mrousavy](https://github.com/mrousavy))
|
||||
- Added `isDarkerSystemColorsEnabled()` to `AccessibilityInfo` to read "Increase Contrast" setting value ([af3bee6511](https://github.com/facebook/react-native/commit/af3bee6511fe72fda7415bf974f937012b3eefec) by Ariel Lin)
|
||||
- Expose RCT_NEW_ARCH_ENABLED to Swift ([d24507611d](https://github.com/facebook/react-native/commit/d24507611de7fefc71286fd54b2c909d98a4bf27) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
- Add `systemCyan` and `systemMint` colors on iOS ([4caf548a9f](https://github.com/facebook/react-native/commit/4caf548a9f2e485aef9cbaeeb0a666cf9b9d3e59) by [@EvanBacon](https://github.com/EvanBacon))
|
||||
- Outline properties `outline-width`, `outline-color`, `outline-style` & `outline-offset` ([1288e38423](https://github.com/facebook/react-native/commit/1288e38423f93ed57737dd9b40ad55696494d6f4) by [@jorge-cab](https://github.com/jorge-cab))
|
||||
- Declare supportedInterfaceOrientations only on iOS ([40c5e6b64a](https://github.com/facebook/react-native/commit/40c5e6b64a1d82b5b481717b9086340eca2aaef9) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
- New text content type cellular EID and cellular IMEI ([14e0d0dffb](https://github.com/facebook/react-native/commit/14e0d0dffb9ee8b1d41d60ccbcfd63d53bfe4d48) by [@pasc0al](https://github.com/pasc0al))
|
||||
- User-configurable BUNDLE_NAME when building bundles ([f8287e25e1](https://github.com/facebook/react-native/commit/f8287e25e11d56beb66ace414ca5f8a6a32405a9) by [@fivecar](https://github.com/fivecar))
|
||||
- Line break mode for TextInput components. **This includes JS APIs for the new mode.** ([ce2d34f194](https://github.com/facebook/react-native/commit/ce2d34f19451c91a90f0bd820064208912c86092) by [@shubhamguptadream11](https://github.com/shubhamguptadream11))
|
||||
|
||||
### Changed
|
||||
|
||||
- Fixed a typo in the README file. ([30e75a51f3](https://github.com/facebook/react-native/commit/30e75a51f3af7fbad83e4b002526b69bba021753) by [@Aryan2727-debug](https://github.com/Aryan2727-debug))
|
||||
- Fix unnececary rerenders of VirtualizedListCells with strictMode={true} ([aafe696453](https://github.com/facebook/react-native/commit/aafe696453186d0e87ae96d0bca4c6650234d222) by [@Tom910](https://github.com/Tom910))
|
||||
- The `AnimatedNode` graph will not occur during the insertion effect phase, which means animations can now be reliably started during layout effects. ([316170ce8d](https://github.com/facebook/react-native/commit/316170ce8d0aac1df3261c792b9f768665d134c5) by [@yungsters](https://github.com/yungsters))
|
||||
- AttributedString `appendFragment` and `prependFragment` take an rval instead of a const ref; append/prependAttributedString have been removed ([2c31fe99e1](https://github.com/facebook/react-native/commit/2c31fe99e1cc5bfdb393d4f5c70231a042ea67ef) by [@javache](https://github.com/javache))
|
||||
- Improved AttributedText generation for raw text nodes. ([2f7957f2fd](https://github.com/facebook/react-native/commit/2f7957f2fd424fdaa980d99a4ff05eb3237d662e) by [@javache](https://github.com/javache))
|
||||
- Callbacks passed to `animation.start(<callback>)` will be scheduled for execution in a microtask. Previously, there were certain scenarios in which the callback could be synchronously executed by `start`. ([090501d26d](https://github.com/facebook/react-native/commit/090501d26d83be5c5d2df885c60d05ec133d7a54) by [@yungsters](https://github.com/yungsters))
|
||||
- Optimized the performance of updating `Animated` components. ([f0ffcd4f5d](https://github.com/facebook/react-native/commit/f0ffcd4f5dfeab794fbfa3257bb9a8fd793ff2bc) by [@yungsters](https://github.com/yungsters))
|
||||
- Bump serve-static to 1.16.2 to fix CVE-2024-43800 ([50e38cc9f1](https://github.com/facebook/react-native/commit/50e38cc9f1e6713228a91ad50f426c4f65e65e1a) by [@cortinico](https://github.com/cortinico))
|
||||
- Bump Folly to 2024.10.14.00 ([37375d8aba](https://github.com/facebook/react-native/commit/37375d8aba0869531567426466478b0de9a1aea3) by [@alanleedev](https://github.com/alanleedev))
|
||||
- `useMergeRefs` and components using it (e.g. `Pressable`) now support ref cleanup functions. ([01e210fd28](https://github.com/facebook/react-native/commit/01e210fd28bc961e8c1b5fa454b3c947adda296c) by [@yungsters](https://github.com/yungsters))
|
||||
- : Update Metro to 0.81.0 ([0902b0af75](https://github.com/facebook/react-native/commit/0902b0af75ba30ec9d4abeda71769d0685637afa) by [@robhogan](https://github.com/robhogan))
|
||||
- Animations started with incompatible `useNativeDriver` and `AnimatedValue` configurations will now synchronously fail. Previously, spring and timing animations with non-zero delays would throw the error asynchronously. ([fd8cf19625](https://github.com/facebook/react-native/commit/fd8cf1962585aa49e8921475d89c1a5c2423c51c) by [@yungsters](https://github.com/yungsters))
|
||||
- The `Animation` superclass no longer exposes `__onEnd` as a property. Subclasses must instead invoke `super.start(…)` in their `start()` implementation. ([b3fe06b268](https://github.com/facebook/react-native/commit/b3fe06b2685e526fe2bc420a902a3ccd4e1381df) by [@yungsters](https://github.com/yungsters))
|
||||
- Simplified Flow types to use `HostInstance` (which changing nominal types). ([177697f539](https://github.com/facebook/react-native/commit/177697f539ec68a47cbb8f57260cebe701589ef1) by [@yungsters](https://github.com/yungsters))
|
||||
- Upgrade React DevTools to 6.0.0. ([ed4f6d6891](https://github.com/facebook/react-native/commit/ed4f6d68910677ab050e3fef5aaa87e42d582fe0) by [@hoxyq](https://github.com/hoxyq))
|
||||
- Fix: use public instance in Fiber renderer and expose it from getInspectorDataForViewAtPoint (#31068) ([633ad4933e](https://github.com/facebook/react-native/commit/633ad4933e9514d4168d6dcdb7e56c9a1859482a) by [@hoxyq](https://github.com/hoxyq))
|
||||
- Get react-native package name from package.json in codegen script ([65575e8399](https://github.com/facebook/react-native/commit/65575e8399a08841a0ccbc5b28cafeee6d41714c) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
- Bring back shouldSkipStateUpdatesForLoopingAnimations feature flag ([6e0e712c2a](https://github.com/facebook/react-native/commit/6e0e712c2a680cf4b4de1ee5fb25cc5282b242c5) by [@dmytrorykun](https://github.com/dmytrorykun))
|
||||
- AnimatedNode (and its subclasses) once again implement `toJSON()`. ([7bd4a54968](https://github.com/facebook/react-native/commit/7bd4a5496815943b031b68ca46792560d8d798d8) by [@yungsters](https://github.com/yungsters))
|
||||
- Do not print Bridgeless Mode is enabled on console anymore ([f3a969f38d](https://github.com/facebook/react-native/commit/f3a969f38d7a2c74bf63ee05c4c819c0873059a9) by [@cortinico](https://github.com/cortinico))
|
||||
- Bump main to 0.77-main ([120558c0cd](https://github.com/facebook/react-native/commit/120558c0cd6ae50156d2f7b958d3a29fd7ae4623) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Improved the performance of unmounting (and updating, when an enclosing Activity becomes hidden) Animated components ([46abda55b9](https://github.com/facebook/react-native/commit/46abda55b9749dc171e0fec551ba83c027818eb7) by Royi Hagigi)
|
||||
- AnimatedNode (and its subclasses) no longer implement `toJSON()`. ([fe6228512e](https://github.com/facebook/react-native/commit/fe6228512e076820c9c11869cfe24b19d1abfb58) by [@yungsters](https://github.com/yungsters))
|
||||
- Animated now resolves `style` to the original prop value if it contains no `AnimatedNode` instances. Previously, it would resolve to a flattened style object. ([ca234ba10e](https://github.com/facebook/react-native/commit/ca234ba10e8d06630da7ea00aac515b222137645) by [@yungsters](https://github.com/yungsters))
|
||||
- Bump Metro dependencies to 0.81.0-alpha.0 ([40f98b5eee](https://github.com/facebook/react-native/commit/40f98b5eeef18bb9c20a9a2762d0b1d648c4ae91) by [@robhogan](https://github.com/robhogan))
|
||||
|
||||
#### Android specific
|
||||
|
||||
- Consolidated ReactViewGroup add/remove overrides ([0b22b955f1](https://github.com/facebook/react-native/commit/0b22b955f1494f0e7441a01dd19b3fdf5e20c3dc) by Thomas Nardone)
|
||||
- Migrated systeminfo module code from Java to Kotlin ([8dc2c90ce5](https://github.com/facebook/react-native/commit/8dc2c90ce5f4b30f4729560aed2412e6d29f39fa) by [@oddlyspaced](https://github.com/oddlyspaced))
|
||||
- Updating targetSdk to 35 (apps can still choose their own targetSdk regardless of RN version) ([48ea6867a9](https://github.com/facebook/react-native/commit/48ea6867a96bd16dc7aed9af5a8e9ce12a487c22) by [@alanleedev](https://github.com/alanleedev))
|
||||
- Invocations to JS will now invoke their callbacks immediately if the instance is ready. Surface starts will not wait for the main thread to become available to dispatch the work in JS. ([9fa4845136](https://github.com/facebook/react-native/commit/9fa4845136969ec95ce5615b7ea78feaf0f7f109) by [@javache](https://github.com/javache))
|
||||
- TurboModules marked as requiring eager init will now be constructed on the mqt_native thread to increase concurrency in React Native init. ([663b5f9d19](https://github.com/facebook/react-native/commit/663b5f9d19a905520bd0aef62cda890f76ef9b6e) by [@javache](https://github.com/javache))
|
||||
- Reduce visibility of Continuation to internal, although this interface wasn't being exposed in any public API ([7b21b9e69c](https://github.com/facebook/react-native/commit/7b21b9e69c6176c7f66af0e479623ed1c2be0d62) by [@mdvacca](https://github.com/mdvacca))
|
||||
- Update documentation for ReactHost.destroy() APIs ([443bc32dc4](https://github.com/facebook/react-native/commit/443bc32dc49a86534fce1d6ec0e31c97b8f33053) by [@mdvacca](https://github.com/mdvacca))
|
||||
- Deprecate CatalystInstance in old architecture ([3e27ef1f6e](https://github.com/facebook/react-native/commit/3e27ef1f6e024bba8725a3bd64e2648ffd6af496) by [@mdvacca](https://github.com/mdvacca))
|
||||
- Deprecate BridgelessCatalystInstance class ([72bd840dd3](https://github.com/facebook/react-native/commit/72bd840dd3dc7b6e3e88a74ac9ddb000a0cb3a60) by [@mdvacca](https://github.com/mdvacca))
|
||||
- AGP to 8.7.2 ([e1a1cead43](https://github.com/facebook/react-native/commit/e1a1cead434a6856b2b018274876b9ba8eab706a) by [@cortinico](https://github.com/cortinico))
|
||||
- Migrate ReactFeatureFlags to Kotlin ([4076dbfc86](https://github.com/facebook/react-native/commit/4076dbfc8651fcd193b886bf63b23728fad466d7) by [@mdvacca](https://github.com/mdvacca))
|
||||
- Android NDK to 27.1 ([ba061a5d18](https://github.com/facebook/react-native/commit/ba061a5d18176fd455c3aa6350127506dac05211) by [@alanleedev](https://github.com/alanleedev))
|
||||
- Migrate MainReactPackage to Kotlin (and make it final) ([7bbac8ee27](https://github.com/facebook/react-native/commit/7bbac8ee27daf092b580b57c2c7ee46d2723cd09) by [@cortinico](https://github.com/cortinico))
|
||||
- Bump fbjni to 0.7.0 ([1c002c7b4e](https://github.com/facebook/react-native/commit/1c002c7b4ea4f22729920e54a9032402247ea350) by [@alanleedev](https://github.com/alanleedev))
|
||||
- Fresco to 3.4.0 ([091025e18b](https://github.com/facebook/react-native/commit/091025e18b1dc5212031e3ed06bfb6c450e788e2) by [@cortinico](https://github.com/cortinico))
|
||||
- Bump Kotlin 1.9.x to 2.0.x ([972c2c864c](https://github.com/facebook/react-native/commit/972c2c864c0b563163a36080a13908d1c0a3fb87) by [@cortinico](https://github.com/cortinico))
|
||||
- Fix: change opacity logic from random to decrement by -0.20 ([af4907025e](https://github.com/facebook/react-native/commit/af4907025ef358c312d469118a52699dcf14507d) by [@sarthak-d11](https://github.com/sarthak-d11))
|
||||
- Bump Android Gradle Plugin (AGP) to 8.7.0 ([cbc0978bb6](https://github.com/facebook/react-native/commit/cbc0978bb65dcfd2a18a54201c845785a626b1b3) by [@cortinico](https://github.com/cortinico))
|
||||
- Improve FpsDebugFrameCallback.getTotalTimeMS() accuracy ([d54c25fdae](https://github.com/facebook/react-native/commit/d54c25fdaee4d2642cdbca812b61c6973d3f203d) by [@aamagda](https://github.com/aamagda))
|
||||
- Update Fresco from 3.2.0 to 3.3.0 ([86d92e41d2](https://github.com/facebook/react-native/commit/86d92e41d2e129d12589848f75dfe2b2db09ed1a) by [@Abbondanzo](https://github.com/Abbondanzo))
|
||||
- Disabling `outline` props on Android to stay consistent with iOS ([7ab0002799](https://github.com/facebook/react-native/commit/7ab0002799d52a876a8cdd32f25ebef6d431650e) by [@jorge-cab](https://github.com/jorge-cab))
|
||||
- Gradle to 8.10.1 ([90f89a830a](https://github.com/facebook/react-native/commit/90f89a830acced9e6b8e80ef58aefd7e2c9666a8) by [@cortinico](https://github.com/cortinico))
|
||||
|
||||
#### iOS specific
|
||||
|
||||
- Make `prefetchImageWithMetadata`'s `queryRootName` nullable in the spec ([4dd60acb7d](https://github.com/facebook/react-native/commit/4dd60acb7ddc2811453e84e3567c1a114fa5e6f9) by [@TheRogue76](https://github.com/TheRogue76))
|
||||
- Change how components automatically register ([8becc2514d](https://github.com/facebook/react-native/commit/8becc2514d484c99b51ea76f479f06a8fcdd8265) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Stop generating the RCTThirdPartyLibraryComponentProvider ([60b9d3d89e](https://github.com/facebook/react-native/commit/60b9d3d89eba90a945070646c6220b3c03b3aeba) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- `RCTSurfaceHostingProxyRootView` no longer has different behavior (whether it calls `start` on the provided *surface*) depending on which initializer is used. Call `start` yourself on the *surface* instead. ([13b93cfdda](https://github.com/facebook/react-native/commit/13b93cfddaa559697968ac1c19e55f7aaa053070) by Nolan O'Brien)
|
||||
- Use `newArchEnabled` flag in RCTAppDelegate and RCTRootViewFactory ([7e1674fc59](https://github.com/facebook/react-native/commit/7e1674fc59abeeb70d946ee082a829fae4c671b7) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
- Do not move to the main queue synchronously when starting a new surface ([ab2c47be28](https://github.com/facebook/react-native/commit/ab2c47be285fde99a77d189fd04220ef8ad0933a) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Rename `RCTUIGraphicsImageRenderer` to `RCTMakeUIGraphicsImageRenderer` ([6a09fc09af](https://github.com/facebook/react-native/commit/6a09fc09af8eedbf409ab870d5714e44892b2a16) by [@Saadnajmi](https://github.com/Saadnajmi))
|
||||
- Refactor RCTDevLoadingView to use constraints ([fbda60e657](https://github.com/facebook/react-native/commit/fbda60e65783d9a3f257cd427cbffc1c9b2cc01b) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
|
||||
### Deprecated
|
||||
|
||||
|
||||
|
||||
#### Android specific
|
||||
|
||||
- Deprecated shadows for ReadableNative[Map|Array].[Readable|Writable] ([d424bb9d7c](https://github.com/facebook/react-native/commit/d424bb9d7cf101dc5609e8f787ba8af2a33d0262) by [@javache](https://github.com/javache))
|
||||
- ReactContext.getFabricUIManager() method ([fb737ca7d3](https://github.com/facebook/react-native/commit/fb737ca7d34b636a3aa337a0935bf9a5a10c641d) by [@mdvacca](https://github.com/mdvacca))
|
||||
|
||||
#### iOS specific
|
||||
|
||||
- Deprecating RCTBridgeModule batchDidComplete and adding configuration to disable it ([731bd95c43](https://github.com/facebook/react-native/commit/731bd95c430c752126aaaa34e4911ba2b87b382f) by [@philIip](https://github.com/philIip))
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove `BackHandler.removeEventListener` ([44d619414c](https://github.com/facebook/react-native/commit/44d619414c1de3dbf17a421afa8dbcec7cdab025) by [@retyui](https://github.com/retyui))
|
||||
- Removed type for useConcurrentRoot from AppRegistry, as it was already ignored ([2ec547ad28](https://github.com/facebook/react-native/commit/2ec547ad28ca914c17e276abb91174dfa0dc87b2) by [@javache](https://github.com/javache))
|
||||
- Remove "run on iOS" and "run on Android" from the dev server key commands ([19b971ff94](https://github.com/facebook/react-native/commit/19b971ff94a0fe353f82363e788c13f86815663b) by [@huntie](https://github.com/huntie))
|
||||
- Removed `refs` property from `NativeMethods` TypeScript definition. ([223e98cc4b](https://github.com/facebook/react-native/commit/223e98cc4b656b94b48c88940114bfdc025f8ddf) by [@yungsters](https://github.com/yungsters))
|
||||
|
||||
#### Android specific
|
||||
|
||||
- Removed hasConstants constructor from ReactModuleInfo ([aec7a66ae8](https://github.com/facebook/react-native/commit/aec7a66ae84bd7689d902686711db8eabc21c1f1) by [@javache](https://github.com/javache))
|
||||
- Removed TurboReactPackage, which was replaced by BaseReactPackage ([bf5c98cf5e](https://github.com/facebook/react-native/commit/bf5c98cf5e1ce5c041d3d9321a0ba2fd3c755b46) by [@javache](https://github.com/javache))
|
||||
- DevToolsReactPerfLogger stats gathering now uses an internal API ([f503fe3f10](https://github.com/facebook/react-native/commit/f503fe3f100d96a31fc56451d7846d80ce5c342f) by [@javache](https://github.com/javache))
|
||||
- BindingImpl is no longer part of the public interface ([18faf68b48](https://github.com/facebook/react-native/commit/18faf68b4825118253cf247572084c4da8f6366e) by [@javache](https://github.com/javache))
|
||||
- FabricComponents is removed from public API ([300db67b27](https://github.com/facebook/react-native/commit/300db67b270a5d6fc85d27188d0d1089675f89c0) by [@javache](https://github.com/javache))
|
||||
|
||||
#### iOS specific
|
||||
|
||||
- Remove available for RCTKeyWindow check ([e98c221e5e](https://github.com/facebook/react-native/commit/e98c221e5e54e79c25acd06f14e7d01221823305) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Hermes: revert Intl removal ([4cffff35e0](https://github.com/facebook/react-native/commit/4cffff35e030f256c32bf69c5971dfee4e60723f) by [@robhogan](https://github.com/robhogan))
|
||||
- Fix the nodes' owners not being updated when `display: contents` is used ([aa53bde21b](https://github.com/facebook/react-native/commit/aa53bde21b8952533cf17ffee234b273766f2133) by [@j-piasecki](https://github.com/j-piasecki))
|
||||
- dev-middleware: Rewrite URLs in the inspector proxy to cover all configurations, not just Android emulators. ([74995bc90a](https://github.com/facebook/react-native/commit/74995bc90aa039b880e4875ad356d3bce324d902) by [@robhogan](https://github.com/robhogan))
|
||||
- Fix C++ bridging template compatibility with MSVC ([e6848ba5ba](https://github.com/facebook/react-native/commit/e6848ba5ba997d102cbaf6181c7c8c73e25a0827) by [@acoates-ms](https://github.com/acoates-ms))
|
||||
- Accessing KeyboardAvoidingEvent event in onLayout handler ([68db74205a](https://github.com/facebook/react-native/commit/68db74205afdd190304eb73ef71710781fa580b9) by [@mhoran](https://github.com/mhoran))
|
||||
- dev-middleware: Fix URL rewriting where device and debugger reach the server on different ports/protocols. ([5da7ebf99a](https://github.com/facebook/react-native/commit/5da7ebf99ae317c104d8e4bfbf36d3d89f66b5c9) by [@robhogan](https://github.com/robhogan))
|
||||
- dev-middleware: Regex-escape IP addresses in urlRegex replacements ([aae3e03e57](https://github.com/facebook/react-native/commit/aae3e03e57096c3dc51589a3de240d49a8b9fadf) by [@robhogan](https://github.com/robhogan))
|
||||
- Fixed jest error from Appearance.js ([ce838a4bcf](https://github.com/facebook/react-native/commit/ce838a4bcfb1c08728b637a9addd24cc6e3477e0) by [@Kudo](https://github.com/Kudo))
|
||||
- When using Babel with plain JavaScript files, support for additional user syntax plugins should be fixed (now uses Babel's parser instead of hermes-parser). There is no change for JS files annotated with `flow`, where extended JS syntax remains unsupported. ([3de9892353](https://github.com/facebook/react-native/commit/3de989235365504468d2b6c0bb194e944bf1ce8e) by [@huntie](https://github.com/huntie))
|
||||
- Fix `Appearance.setColorScheme(null)` not resetting color scheme value ([7d63235086](https://github.com/facebook/react-native/commit/7d63235086352d8c424d634c7039551f0a5025dc) by [@sangonz193](https://github.com/sangonz193))
|
||||
- Fix text not taking full width ([550b0c0ed1](https://github.com/facebook/react-native/commit/550b0c0ed16a64ce58102f15d4657abe92aac71c) by [@s77rt](https://github.com/s77rt))
|
||||
- Linear gradient start and end point algorithm. ([221d1eceda](https://github.com/facebook/react-native/commit/221d1eceda0e5ab870e96dcdd26e22ab17a3870c) by [@intergalacticspacehighway](https://github.com/intergalacticspacehighway))
|
||||
- Codegen: Support nested objects in arrays ([13780126d3](https://github.com/facebook/react-native/commit/13780126d3cb17ad00c2954f9830a3623812dc3e) by [@tvanlaerhoven](https://github.com/tvanlaerhoven))
|
||||
- RN DevTools: Don't assume 10.0.2.2 is an alias for localhost unless it's used to establish a connection to the server ([69400be4fc](https://github.com/facebook/react-native/commit/69400be4fc0abd38072f6586f3e7d5b6c33e54be) by [@robhogan](https://github.com/robhogan))
|
||||
- Do not discard props in the patch when they are not null while using `useNativeProps` ([4c3112c8d8](https://github.com/facebook/react-native/commit/4c3112c8d8685d6c34be9acf07b18871b3cee5b2) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- : dev-middleware: Remove URL.canParse, restore compat with Node < 18.17 ([99767d43b0](https://github.com/facebook/react-native/commit/99767d43b04e41c83e3bcbfebe267d6fdc284549) by [@robhogan](https://github.com/robhogan))
|
||||
- RN DevTools: Fix fetching sources and source maps when the dev-server is remote and not tunnelled via the same port+protocol. ([d1b0e9a30b](https://github.com/facebook/react-native/commit/d1b0e9a30b3afc56b9355453cf7f6e690bdd8aff) by [@robhogan](https://github.com/robhogan))
|
||||
- Fix npm react-native start when cli-server-api isn't installed ([e0be2efe4e](https://github.com/facebook/react-native/commit/e0be2efe4e80edf99f96a2ae6a25856f6df5e0ca) by [@blakef](https://github.com/blakef))
|
||||
- AnsiHighlight style in RTL layout ([9a3958a619](https://github.com/facebook/react-native/commit/9a3958a619fddb75ed3c6eddebd94f11c0d00e9f) by [@hexboy](https://github.com/hexboy))
|
||||
- Fixes typo in ReactHostImpl ([e3f03269c5](https://github.com/facebook/react-native/commit/e3f03269c5cea28977e44ddf5c5125968336b0e6) by [@rozele](https://github.com/rozele))
|
||||
- TextTransform: capitalize better reflects the web behaviour ([dc2000c875](https://github.com/facebook/react-native/commit/dc2000c8750f42b2f01bdad75455750814d567c6) by [@javache](https://github.com/javache))
|
||||
- Fix for nodes with `display: contents` not being cleaned in some cases ([a88ddcecc9](https://github.com/facebook/react-native/commit/a88ddcecc93a9fa2d231907439d02b11bac8a944) by [@j-piasecki](https://github.com/j-piasecki))
|
||||
- Microtasks are now correctly executed after the code evaluation in Console panel of DevTools. ([3dfe22bd27](https://github.com/facebook/react-native/commit/3dfe22bd27429a43b4648c597b71f7965f31ca65) by [@hoxyq](https://github.com/hoxyq))
|
||||
- Passed height and width as native props to support cases where source is an array. ([45b177f50d](https://github.com/facebook/react-native/commit/45b177f50de624eefcb66bb2d8bc1ffb00855863) by [@shubhamguptadream11](https://github.com/shubhamguptadream11))
|
||||
- `PerformanceEntryReporter::reportMark` and `PerformanceEntryReporter::reportMeasaure` now return created performance entries. ([32f7b3b4e0](https://github.com/facebook/react-native/commit/32f7b3b4e0b8be1d1138f43c46b3c86d9a64c29a) by [@robik](https://github.com/robik))
|
||||
- Make Codegen work with local modules ([7b6e8e7765](https://github.com/facebook/react-native/commit/7b6e8e776574e683821133f0c814969d74c4de61) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Fix KeyboardAvoidingView not aware of the keyboard closing it is unmounted ([08bd8ac47d](https://github.com/facebook/react-native/commit/08bd8ac47da60121225e7b281bbf566e2c5a291e) by [@QichenZhu](https://github.com/QichenZhu))
|
||||
- Fix onEndReached not being called when getItemLayout is present and we scroll past render window ([3485e9ed87](https://github.com/facebook/react-native/commit/3485e9ed871886b3e7408f90d623da5c018da493) by YunPeng Chong)
|
||||
- Fix cast and control paths errors on windows ([0794fa909b](https://github.com/facebook/react-native/commit/0794fa909b2e06fad5c40dce402c5f14a24bb946) by [@TatianaKapos](https://github.com/TatianaKapos))
|
||||
- Plumbing to get boxSizing prop to Yoga round 2 ([3ca796edc3](https://github.com/facebook/react-native/commit/3ca796edc327c5287533dcc8f4394033d5398c2d) by [@joevilches](https://github.com/joevilches))
|
||||
- Fix onEndReached not being called when getItemLayout is present and we scroll past render window ([62b7396bf4](https://github.com/facebook/react-native/commit/62b7396bf45c04bd47e74fe4c1e5b5e59918244d) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- TurboModule::get is now a final method, override `create` to customize property lookup ([5b5e150eaf](https://github.com/facebook/react-native/commit/5b5e150eaff015540720225b9e61acb306e1d107) by [@javache](https://github.com/javache))
|
||||
- Improved types for AnimatedProps ([390925ea39](https://github.com/facebook/react-native/commit/390925ea39eb469768f21cf7069b8f75ccdec09d) by [@javache](https://github.com/javache))
|
||||
- Upgrade Codegen dependency `jscodeshift@17.0.0` to resolve outdated dependencies ([39c98fb8f8](https://github.com/facebook/react-native/commit/39c98fb8f8af98aa40dc89a1580d6c1901fa86cf) by [@byCedric](https://github.com/byCedric))
|
||||
- Fixed issues with W3C PointerEvents testsx ([1dcaf823f5](https://github.com/facebook/react-native/commit/1dcaf823f5e7d9b114dd803ce3181aa0b8f827ad) by [@rozele](https://github.com/rozele))
|
||||
- Fixed issue with W3C PointerEvents tests ([68a6b69b27](https://github.com/facebook/react-native/commit/68a6b69b27275998b4083797942f3e26a92d3adb) by [@rozele](https://github.com/rozele))
|
||||
- Fix setImmediate/clearTimeout mismatch in NativeAnimatedHelper that could clear an unrelated setTimeout. ([a5dd1be889](https://github.com/facebook/react-native/commit/a5dd1be889be21f8daefbc609702989ec7c156cf) by Benoit Girard)
|
||||
- Improved error message when no view config is found. ([bca232ad90](https://github.com/facebook/react-native/commit/bca232ad90692da7a87be5e37ee2680380f94bef) by [@javache](https://github.com/javache))
|
||||
- : Order of operations related to platformConfig propagation in NativeAnimated ([a64183b0c6](https://github.com/facebook/react-native/commit/a64183b0c6a56e9d482c7b8b0f80965493ed87af) by [@rozele](https://github.com/rozele))
|
||||
- Rename overlayColor prop in Modal to backdropColor ([7aeff18970](https://github.com/facebook/react-native/commit/7aeff18970a2b47cbb3fffc1408e4bb21eec6fed) by [@alanleedev](https://github.com/alanleedev))
|
||||
- Fix source mapping for codegenNativeCommands ([8fba154b66](https://github.com/facebook/react-native/commit/8fba154b6655b5d87609d7c9f136997141ea5e99) by [@vzaidman](https://github.com/vzaidman))
|
||||
- Fixed accuracy of FlatList estimations to determine what elements are visible in the rendering window. ([40aaeb7181](https://github.com/facebook/react-native/commit/40aaeb71814a1987482d97fd3170af0add55bc6a) by [@rubennorte](https://github.com/rubennorte))
|
||||
- Fix type conversion error in react native windows build. ([13db1cb88b](https://github.com/facebook/react-native/commit/13db1cb88bdd454cf19be358d6f0cd62f5a6d0cc) by [@marlenecota](https://github.com/marlenecota))
|
||||
- Correctly pass down isLooping in parallel animation ([4014aa4528](https://github.com/facebook/react-native/commit/4014aa4528d43e905246850c83007a635938d7cb) by [@zeyap](https://github.com/zeyap))
|
||||
|
||||
#### Android specific
|
||||
|
||||
- Yoga: Fix YogaConfig getting garbage collected #1678 ([7dcb10b6e7](https://github.com/facebook/react-native/commit/7dcb10b6e7e226034a496eaed5351601ae0a1ae2) by [@michaeltroger](https://github.com/michaeltroger))
|
||||
- Enable mix-blend-mode on ReactRootView so blending works with app background ([24b0ded3cf](https://github.com/facebook/react-native/commit/24b0ded3cf715bb0e849d9f7ca8cd2d4d42cbf90) by [@jorge-cab](https://github.com/jorge-cab))
|
||||
- RN DevTools: Fix source loading when using an Android emulator connecting to a dev server on the host. ([ca9c56329f](https://github.com/facebook/react-native/commit/ca9c56329fe548b6631934afee0c9be63e1752a1) by [@robhogan](https://github.com/robhogan))
|
||||
- Fixes some deadlocks when doing commits and state updates synchronously from the UI thread (e.g.: from reanimated). ([3986eefed1](https://github.com/facebook/react-native/commit/3986eefed1733f305db5410737a96b635f0159e7) by [@rubennorte](https://github.com/rubennorte))
|
||||
- Ensure setSelection in onAttachedToWindow is within text range ([08759121cd](https://github.com/facebook/react-native/commit/08759121cda3785e4d7ee1f1c82011a3e3a955a9) by [@zeyap](https://github.com/zeyap))
|
||||
- Fixed crash in legacy ReactFontManager ([3da23f7093](https://github.com/facebook/react-native/commit/3da23f7093730e10aeda6b58f4934a381e226dd2) by [@javache](https://github.com/javache))
|
||||
- Dispatch onMomentumScrollEnd after programmatic scrolling ([c69e330324](https://github.com/facebook/react-native/commit/c69e330324724a1e363f4786b2b03ee7ff4b35c5) by [@Biki-das](https://github.com/Biki-das))
|
||||
- RNGP - Do not attempt to substring to 1024 while logging ([e64513bf4e](https://github.com/facebook/react-native/commit/e64513bf4ecce60aff5c04e3bed91b203429d12f) by [@cortinico](https://github.com/cortinico))
|
||||
- Missing isInvertColorsEnabled implementation for Android ([cc1d2853fb](https://github.com/facebook/react-native/commit/cc1d2853fb2b64adfb884cb30c8d22ce0260be15) by [@oddlyspaced](https://github.com/oddlyspaced))
|
||||
- Addressed race condition in surface start. ([6ba7cb3102](https://github.com/facebook/react-native/commit/6ba7cb310273a0ecce6a168bf3aae45fb85bf955) by [@javache](https://github.com/javache))
|
||||
- The definition of ts of resizeMethod attribute is none. ([758892a7d8](https://github.com/facebook/react-native/commit/758892a7d89cc1e316984f8f522738021410f530) by [@nianxiongdi](https://github.com/nianxiongdi))
|
||||
- Reimplement Android lineHeight positioning/determination ([41265bac6b](https://github.com/facebook/react-native/commit/41265bac6b83ee0bb92d645ace81e314065bf5e0) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- Fix legacy arch RTL horizontal ScrollView regression ([bfca7cfe7a](https://github.com/facebook/react-native/commit/bfca7cfe7a8e0da10fdb776100fbc706233c0d8d) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- Fix RTL ScrollView position when content smaller than container ([0df59d4f03](https://github.com/facebook/react-native/commit/0df59d4f03f79c0fcb9ede2d21bf4d49c97c21ef) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- Avoid null reference exception in bridgeless ReactDelegate ([0d664100bb](https://github.com/facebook/react-native/commit/0d664100bbf608550a5c42a4e9b02c6c5bd0f5b8) by [@rozele](https://github.com/rozele))
|
||||
- Fix generating empty line at the end of multiline text view when `textAlign` is set to `justify` ([08e8f6adfd](https://github.com/facebook/react-native/commit/08e8f6adfdcdfec59002f34bb7acf35bb842b331) by [@coado](https://github.com/coado))
|
||||
- Fix Frame Callback not being called after Host Resume ([e8f8ee3c0f](https://github.com/facebook/react-native/commit/e8f8ee3c0f28b8c5751ffaef495adea0b8daf1eb) by [@s77rt](https://github.com/s77rt))
|
||||
- Fix crash in getViewState when using suspense fallbacks. ([bd133b5dd5](https://github.com/facebook/react-native/commit/bd133b5dd57b18140eae51c6d7aaab02874455c1) by [@javache](https://github.com/javache))
|
||||
- Text without explicit font styles was potentially cut-off. ([95a5d1c628](https://github.com/facebook/react-native/commit/95a5d1c6287c7301265207d1962ba8b50d178b20) by [@javache](https://github.com/javache))
|
||||
- Merge Android ViewNativeComponent ViewConfig into BaseViewConfig ([0ba00fc998](https://github.com/facebook/react-native/commit/0ba00fc99891a333d3625db15d9dd832ca7eac88) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- Fixed styling on alert dialog titles to wrap two lines and retain bold appearance ([c54b23ff9e](https://github.com/facebook/react-native/commit/c54b23ff9ed7a6bfbb52c081c5afe4b3911d0dd2) by [@Abbondanzo](https://github.com/Abbondanzo))
|
||||
- Prevent ArrayIndexOutOfBoundsException in permission check ([6aeca53b3e](https://github.com/facebook/react-native/commit/6aeca53b3ed4530e57a31d7a5593ae16b550b985) by [@antFrancon](https://github.com/antFrancon))
|
||||
- Account for items dynamically scaling with the container when using `maintainVisibleContentPosition` in virtualized lists ([6c19996e10](https://github.com/facebook/react-native/commit/6c19996e10eda97a3501f53a68da246d1f122d01) by [@fabriziocucci](https://github.com/fabriziocucci))
|
||||
- Apps will no longer fatally crash when trying to draw large images ([483b928224](https://github.com/facebook/react-native/commit/483b92822496fa2e6339f75049a33be1e9567f52) by [@Abbondanzo](https://github.com/Abbondanzo))
|
||||
- Add missing BaseViewManager props to BaseViewManagerDelegate ([6741fd94ad](https://github.com/facebook/react-native/commit/6741fd94ad26012938caa65a5129f0eca6f2246e) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- Fix TextInput caret moving to the beginning when attached to window ([ca0abd1b9e](https://github.com/facebook/react-native/commit/ca0abd1b9ea164a566b39cb9090eaa75647aad5a) by [@QichenZhu](https://github.com/QichenZhu))
|
||||
- Fix issue where `onDropViewInstance` cleanup was not being handled after `ReactRootView.unmountReactApplication` ([0449630612](https://github.com/facebook/react-native/commit/04496306123c46730b46accb2cd6239531e51fef) by [@rozele](https://github.com/rozele))
|
||||
- Fix issues with Modals and lifecycle events in multi-surface apps ([1ffef5669c](https://github.com/facebook/react-native/commit/1ffef5669c21f4b2c5fec6bc58a85f95518cf10e) by [@rozele](https://github.com/rozele))
|
||||
- Fix mising `ANTI_ALIAS_FLAG` when resetting Text Paint ([276e3a7df7](https://github.com/facebook/react-native/commit/276e3a7df7de1b04dec0891fa7ed72917568ee7b) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- Fix some cases where we override setBackgroundColor on View-level instead of VM level ([0b0ac81fbe](https://github.com/facebook/react-native/commit/0b0ac81fbeebf819e744b6ecc19d549aaab8406d) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- Avoid blocking the main thread when decompressing drawable resources ([420229d669](https://github.com/facebook/react-native/commit/420229d66946320f06485c5a3d3c167eae1a407e) by [@Abbondanzo](https://github.com/Abbondanzo))
|
||||
- Reenable `setAndroidLayoutDirection` by default ([6cf0cfb5a4](https://github.com/facebook/react-native/commit/6cf0cfb5a47a437b8a17b50b4c70460be15ee1cd) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- Properly fix measurement of trailing newlines ([060c594457](https://github.com/facebook/react-native/commit/060c59445740f9b92188d2193623b36c3d859ba7) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- Fix crash for Modal not attached to window manager ([eaa780de1c](https://github.com/facebook/react-native/commit/eaa780de1c799bf35fded2914d27b1953b093340) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Fix NPE on ReactTextInputManager.setTextDecorationLine ([41c6ad5597](https://github.com/facebook/react-native/commit/41c6ad55978184cad1a32ec63c2d1f07e8282d5e) by [@cortinico](https://github.com/cortinico))
|
||||
- BoxShadow now supports platformColor. ([4ede9205a0](https://github.com/facebook/react-native/commit/4ede9205a0559fcaf7ac58a3d70bc902eb23fcb6) by [@javache](https://github.com/javache))
|
||||
- MixBlendMode now properly does state updates ([fae572d815](https://github.com/facebook/react-native/commit/fae572d815c7fb9684fc6c3b7f001de35ea8fb69) by [@jorge-cab](https://github.com/jorge-cab))
|
||||
- Fix interactions between removeClippedSubviews and RTL ([513e9669e7](https://github.com/facebook/react-native/commit/513e9669e78a4bfd9b0380335c61f581343c4009) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- LayoutAnimations work on full new architecture ([43af902693](https://github.com/facebook/react-native/commit/43af902693f0befde802a7f684e26b19ec7126c8) by [@javache](https://github.com/javache))
|
||||
- Fix: ReactDelegate/ReactFragment crashing on New Architecture apps ([12dda31bc1](https://github.com/facebook/react-native/commit/12dda31bc12f4a04ec9df70d30328b1001bb2cec) by [@cortinico](https://github.com/cortinico))
|
||||
- ReactFragment should properly instantiate ReactDelegate on Bridgeless ([7176d11ce4](https://github.com/facebook/react-native/commit/7176d11ce468ca37e9cbe8afcc1f6344c250dd0c) by [@cortinico](https://github.com/cortinico))
|
||||
- Fixed text being measured incorrectly when ending with an empty line on the new architecture ([bd323929dc](https://github.com/facebook/react-native/commit/bd323929dc5be5666ee36043babec7d981a095dc) by [@j-piasecki](https://github.com/j-piasecki))
|
||||
- Linear gradient with platform colors ([6866968a79](https://github.com/facebook/react-native/commit/6866968a79d44518884965959760983acdadc17c) by [@intergalacticspacehighway](https://github.com/intergalacticspacehighway))
|
||||
- ARG_DISABLE_HOST_LIFECYCLE_EVENTS in ReactFragment to allow unmounting a surface without destroying ReactHost. ([40c875deca](https://github.com/facebook/react-native/commit/40c875decabaa56d6dd45ce03b22e8b3931781ac) by [@vincenzovitale](https://github.com/vincenzovitale))
|
||||
- Fixed incorrect scroll event/position for scroll views when doing a smooth scroll animation. ([b4c41ec768](https://github.com/facebook/react-native/commit/b4c41ec7685da6e8ef35c41c30aa402639bc42c1) by [@rubennorte](https://github.com/rubennorte))
|
||||
- Use appropriate Nullable attribute for ReactRootView field in ReactDelegate ([cbddcfc691](https://github.com/facebook/react-native/commit/cbddcfc6911101608df36f2a8d047768296c63b2) by [@rozele](https://github.com/rozele))
|
||||
- Hover events were dispatched incorrectly when multiple ReactRoots were layered. ([533ef2ca37](https://github.com/facebook/react-native/commit/533ef2ca37d3b19fc909315f183e3f30dbf4b93d) by [@javache](https://github.com/javache))
|
||||
- Improve text line height calculation ([65d8f66b50](https://github.com/facebook/react-native/commit/65d8f66b50471d2fb4ddd5e63e17fcc808623110) by [@mellyeliu](https://github.com/mellyeliu))
|
||||
|
||||
#### iOS specific
|
||||
|
||||
- Fix possible NSRangeException when updating typing attributes in response to new text content ([6e06a810f0](https://github.com/facebook/react-native/commit/6e06a810f0ab1002f1d10351bc878babde36b1f1) by [@NickGerleman](https://github.com/NickGerleman))
|
||||
- Ensure artifacts directory exists when building Hermes from local source ([c3091ccfed](https://github.com/facebook/react-native/commit/c3091ccfed4440d7f0b906a7eb954718656b71b2) by [@kraenhansen](https://github.com/kraenhansen))
|
||||
- "Reconnect DevTools" button not working sometimes ([8507204b53](https://github.com/facebook/react-native/commit/8507204b533cf87d1e4345a9c062cd10cf0022c1) by [@EdmondChuiHW](https://github.com/EdmondChuiHW))
|
||||
- Fixed use of view commands from layout effects ([6f1c2a512e](https://github.com/facebook/react-native/commit/6f1c2a512e44d25edefea53e864f688018745c07) by [@sammy-SC](https://github.com/sammy-SC))
|
||||
- Fix `r` & `d` not working from Metro sometimes ([9a60038a40](https://github.com/facebook/react-native/commit/9a60038a40e16925ea1adeb3e3c937c22a615485) by [@EdmondChuiHW](https://github.com/EdmondChuiHW))
|
||||
- Resolve deprecated function prototype warning in RCTAppearance.h ([594c9d9a46](https://github.com/facebook/react-native/commit/594c9d9a46623016abb6bbd0d8f2982bf68bdc34) by [@eli-front](https://github.com/eli-front))
|
||||
- Fixes rn-tester bundled images examples ([8cbc7c3357](https://github.com/facebook/react-native/commit/8cbc7c3357ac4043e6c423261c090a1bf656f68e) by [@zhongwuzw](https://github.com/zhongwuzw))
|
||||
- Fixed `onMomentumScrollBegin` event not firing on command-driven scroll events ([5b609cca09](https://github.com/facebook/react-native/commit/5b609cca099b3b0d4fc66d4cf50f69d3c5b7fc8e) by [@Abbondanzo](https://github.com/Abbondanzo))
|
||||
- Typo in spm.rb ([5e18f7f788](https://github.com/facebook/react-native/commit/5e18f7f788ccbea60e96b8e7deab29d423ccf1a6) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
- Add png extension only if file exist when load local image ([44f2a08371](https://github.com/facebook/react-native/commit/44f2a083716205b7560bef2f09d25830e29cd0c5) by [@zhongwuzw](https://github.com/zhongwuzw))
|
||||
- FIxes CornerRadiiAreEqualAndSymmetrical error when check topLeftHorizontal == topLeftVertical ([af384a914a](https://github.com/facebook/react-native/commit/af384a914a4e9ef6a5d25b00bc14b0483e5af879) by [@zhongwuzw](https://github.com/zhongwuzw))
|
||||
- Fix numerous class interfaces having incorrect designated initializer patterns ([b98846c2e3](https://github.com/facebook/react-native/commit/b98846c2e37c3ec895536ab942978d7701f51a5e) by Nolan O'Brien)
|
||||
- AutomaticallyAdjustKeyboardInsets not shifting scrollview content ([2d9933e616](https://github.com/facebook/react-native/commit/2d9933e616c3efe57ed0ca141277638182a69d9c) by [@zhongwuzw](https://github.com/zhongwuzw))
|
||||
- Fix launching App Clips with nullish URLs. ([043e2fe14a](https://github.com/facebook/react-native/commit/043e2fe14a6f13885a552211f17d61292001fa76) by [@EvanBacon](https://github.com/EvanBacon))
|
||||
- Fixes scrollIndicatorInsets not work in old arch ([c1178ac208](https://github.com/facebook/react-native/commit/c1178ac2085e073afb07453eefc9095a1f5d530f) by [@zhongwuzw](https://github.com/zhongwuzw))
|
||||
- Silenced 'set but unused variable' warning. ([f7b28e86aa](https://github.com/facebook/react-native/commit/f7b28e86aaded58f76978179d8d83f11e913b026) by [@nlutsenko](https://github.com/nlutsenko))
|
||||
- Fixed crash on promise rejection handler in iOS 18. ([26d8d490e4](https://github.com/facebook/react-native/commit/26d8d490e47bd3fa46dc4a3b8e66e9ec35c15cf7) by David Rickard)
|
||||
- Fixed scroll view ([ab8f3ff3e9](https://github.com/facebook/react-native/commit/ab8f3ff3e9e6445fa9961467e965792908d4c2bd) by [@coado](https://github.com/coado))
|
||||
- Fixes missing char mode of linebreakmode ([77889afa1c](https://github.com/facebook/react-native/commit/77889afa1c9d0bdb966102860a5d1d1d91187ae8) by [@zhongwuzw](https://github.com/zhongwuzw))
|
||||
- Removed usage of set but unused variable. ([d386dfc804](https://github.com/facebook/react-native/commit/d386dfc804842ed36565966da5aed15d9df7960e) by [@nlutsenko](https://github.com/nlutsenko))
|
||||
- Cast the UIScene to UIWindowScene only if the scene respond to the selector ([fdee0ebbcb](https://github.com/facebook/react-native/commit/fdee0ebbcb88f40c23b92b07792fbb9d1041c546) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Move RCTNotifyEventDispatcherObserversOfEvent_DEPRECATED to const ([a1ec345e2a](https://github.com/facebook/react-native/commit/a1ec345e2a2cdb4ccf255293616ed5e90f519e40) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
- Fixes the exported synchronous method not being called on the method queue when it's the main queue ([8bfd7e1039](https://github.com/facebook/react-native/commit/8bfd7e10393e649554c7246df430019c4f78d5e0) by [@zhongwuzw](https://github.com/zhongwuzw))
|
||||
- Make sure that the Increment and Decrement accessibility actions works on iOS ([303e0ed764](https://github.com/facebook/react-native/commit/303e0ed7641409acf2d852c077f6be426afd7a0c) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Subscribe to orientation changes in RCTUIManager only on iOS ([2f5adc3874](https://github.com/facebook/react-native/commit/2f5adc3874bcdfc8d7d2c3cd5293eefec63a91f8) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
- Fix ActionSheetIOS crash `attempt to insert nil object from objects` ([bebd6531b5](https://github.com/facebook/react-native/commit/bebd6531b5f4ef0300aa5a4b6f9d23e60b57a25e) by [@RodolfoGS](https://github.com/RodolfoGS))
|
||||
- Allow pods mixte type settings on post-install ([1e59f2e3f8](https://github.com/facebook/react-native/commit/1e59f2e3f8f0ab3ee4173bddaa089bbecf61d1eb) by [@MasGaNo](https://github.com/MasGaNo))
|
||||
- Fallback to old resolve mechanism when node require fails to resolve react native path ([3cbaddbc16](https://github.com/facebook/react-native/commit/3cbaddbc164b9dc326b2a7ddc0b35ce885bc7d9d) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
- Fixed warnings when validating SVC ([de39a204c3](https://github.com/facebook/react-native/commit/de39a204c3588a3c02dc2e72464174c75b3a6749) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Solved SVC warnings for RNTester ([fad4a0783b](https://github.com/facebook/react-native/commit/fad4a0783b0a0478c147d9bde2ef9ab082a08297) by [@cipolleschi](https://github.com/cipolleschi))
|
||||
- Don't reference PrivacyInfo.xcprivacy twice for new projects ([cadd41b1a2](https://github.com/facebook/react-native/commit/cadd41b1a2e16b1c77a8d3022f4ccbdbd5ea295f) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
|
||||
## v0.76.3
|
||||
|
||||
### Fixed
|
||||
|
||||
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
declare module 'jest-diff' {
|
||||
import type {CompareKeys} from 'pretty-format';
|
||||
|
||||
declare export type DiffOptionsColor = (arg: string) => string; // subset of Chalk type
|
||||
|
||||
declare export type DiffOptions = {
|
||||
aAnnotation?: string,
|
||||
aColor?: DiffOptionsColor,
|
||||
aIndicator?: string,
|
||||
bAnnotation?: string,
|
||||
bColor?: DiffOptionsColor,
|
||||
bIndicator?: string,
|
||||
changeColor?: DiffOptionsColor,
|
||||
changeLineTrailingSpaceColor?: DiffOptionsColor,
|
||||
commonColor?: DiffOptionsColor,
|
||||
commonIndicator?: string,
|
||||
commonLineTrailingSpaceColor?: DiffOptionsColor,
|
||||
contextLines?: number,
|
||||
emptyFirstOrLastLinePlaceholder?: string,
|
||||
expand?: boolean,
|
||||
includeChangeCounts?: boolean,
|
||||
omitAnnotationLines?: boolean,
|
||||
patchColor?: DiffOptionsColor,
|
||||
compareKeys?: CompareKeys,
|
||||
};
|
||||
|
||||
declare export function diff(
|
||||
a: mixed,
|
||||
b: mixed,
|
||||
options?: DiffOptions,
|
||||
): string | null;
|
||||
}
|
||||
+4
-1
@@ -19,7 +19,6 @@ declare type Colors = {
|
||||
tag: {close: string, open: string},
|
||||
value: {close: string, open: string},
|
||||
};
|
||||
declare type CompareKeys = ((a: string, b: string) => number) | null | void;
|
||||
|
||||
declare type PrettyFormatPlugin =
|
||||
| {
|
||||
@@ -38,6 +37,10 @@ declare type PrettyFormatPlugin =
|
||||
};
|
||||
|
||||
declare module 'pretty-format' {
|
||||
declare export type CompareKeys =
|
||||
| ((a: string, b: string) => number)
|
||||
| null
|
||||
| void;
|
||||
declare export function format(
|
||||
value: mixed,
|
||||
options?: ?{
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -25,4 +25,5 @@ module.exports = {
|
||||
transformIgnorePatterns: ['.*'],
|
||||
testRunner: './jest/integration/runner/index.js',
|
||||
watchPathIgnorePatterns: ['<rootDir>/jest/integration/build/'],
|
||||
globalSetup: './jest/integration/runner/warmup/index.js',
|
||||
};
|
||||
|
||||
@@ -12,25 +12,29 @@
|
||||
import type {TestSuiteResult} from '../runtime/setup';
|
||||
|
||||
import entrypointTemplate from './entrypoint-template';
|
||||
import {spawnSync} from 'child_process';
|
||||
import crypto from 'crypto';
|
||||
import {
|
||||
getBuckModeForPlatform,
|
||||
getDebugInfoFromCommandResult,
|
||||
getFantomTestConfig,
|
||||
getShortHash,
|
||||
runBuck2,
|
||||
symbolicateStackTrace,
|
||||
} from './utils';
|
||||
import fs from 'fs';
|
||||
// $FlowExpectedError[untyped-import]
|
||||
import {formatResultsErrors} from 'jest-message-util';
|
||||
import Metro from 'metro';
|
||||
import nullthrows from 'nullthrows';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
const BUILD_OUTPUT_PATH = path.resolve(__dirname, '..', 'build');
|
||||
|
||||
const ENABLE_OPTIMIZED_MODE: false = false;
|
||||
const PRINT_FANTOM_OUTPUT: false = false;
|
||||
|
||||
function parseRNTesterCommandResult(
|
||||
commandArgs: $ReadOnlyArray<string>,
|
||||
result: ReturnType<typeof spawnSync>,
|
||||
): {logs: string, testResult: TestSuiteResult} {
|
||||
function parseRNTesterCommandResult(result: ReturnType<typeof runBuck2>): {
|
||||
logs: string,
|
||||
testResult: TestSuiteResult,
|
||||
} {
|
||||
const stdout = result.stdout.toString();
|
||||
|
||||
const outputArray = stdout
|
||||
@@ -46,51 +50,26 @@ function parseRNTesterCommandResult(
|
||||
testResult = JSON.parse(nullthrows(testResultJSON));
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
[
|
||||
'Failed to parse test results from RN tester binary result. Full output:',
|
||||
'buck2 ' + commandArgs.join(' '),
|
||||
'stdout:',
|
||||
stdout,
|
||||
'stderr:',
|
||||
result.stderr.toString(),
|
||||
].join('\n'),
|
||||
'Failed to parse test results from RN tester binary result.\n' +
|
||||
getDebugInfoFromCommandResult(result),
|
||||
);
|
||||
}
|
||||
|
||||
return {logs: outputArray.join('\n'), testResult};
|
||||
}
|
||||
|
||||
function getBuckModeForPlatform() {
|
||||
const mode = ENABLE_OPTIMIZED_MODE ? 'opt' : 'dev';
|
||||
|
||||
switch (os.platform()) {
|
||||
case 'linux':
|
||||
return `@//arvr/mode/linux/${mode}`;
|
||||
case 'darwin':
|
||||
return os.arch() === 'arm64'
|
||||
? `@//arvr/mode/mac-arm/${mode}`
|
||||
: `@//arvr/mode/mac/${mode}`;
|
||||
case 'win32':
|
||||
return `@//arvr/mode/win/${mode}`;
|
||||
default:
|
||||
throw new Error(`Unsupported platform: ${os.platform()}`);
|
||||
}
|
||||
}
|
||||
|
||||
function getShortHash(contents: string): string {
|
||||
return crypto.createHash('md5').update(contents).digest('hex').slice(0, 8);
|
||||
}
|
||||
|
||||
function generateBytecodeBundle({
|
||||
sourcePath,
|
||||
bytecodePath,
|
||||
isOptimizedMode,
|
||||
}: {
|
||||
sourcePath: string,
|
||||
bytecodePath: string,
|
||||
isOptimizedMode: boolean,
|
||||
}): void {
|
||||
const hermesCompilerCommandArgs = [
|
||||
const hermesCompilerCommandResult = runBuck2([
|
||||
'run',
|
||||
getBuckModeForPlatform(),
|
||||
getBuckModeForPlatform(isOptimizedMode),
|
||||
'//xplat/hermes/tools/hermesc:hermesc',
|
||||
'--',
|
||||
'-emit-binary',
|
||||
@@ -100,33 +79,10 @@ function generateBytecodeBundle({
|
||||
'-out',
|
||||
bytecodePath,
|
||||
sourcePath,
|
||||
];
|
||||
|
||||
const hermesCompilerCommandResult = spawnSync(
|
||||
'buck2',
|
||||
hermesCompilerCommandArgs,
|
||||
{
|
||||
encoding: 'utf8',
|
||||
env: {
|
||||
...process.env,
|
||||
PATH: `/usr/local/bin:${process.env.PATH ?? ''}`,
|
||||
},
|
||||
},
|
||||
);
|
||||
]);
|
||||
|
||||
if (hermesCompilerCommandResult.status !== 0) {
|
||||
throw new Error(
|
||||
[
|
||||
'Failed to run Hermes compiler. Full output:',
|
||||
'buck2 ' + hermesCompilerCommandArgs.join(' '),
|
||||
'stdout:',
|
||||
hermesCompilerCommandResult.stdout,
|
||||
'stderr:',
|
||||
hermesCompilerCommandResult.stderr,
|
||||
'error:',
|
||||
hermesCompilerCommandResult.error,
|
||||
].join('\n'),
|
||||
);
|
||||
throw new Error(getDebugInfoFromCommandResult(hermesCompilerCommandResult));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +95,9 @@ module.exports = async function runTest(
|
||||
): mixed {
|
||||
const startTime = Date.now();
|
||||
|
||||
const isOptimizedMode = ENABLE_OPTIMIZED_MODE;
|
||||
const testConfig = getFantomTestConfig(testPath);
|
||||
|
||||
const isOptimizedMode = testConfig.mode === 'opt';
|
||||
|
||||
const metroConfig = await Metro.loadConfig({
|
||||
config: path.resolve(__dirname, '..', 'config', 'metro.config.js'),
|
||||
@@ -163,76 +121,54 @@ module.exports = async function runTest(
|
||||
fs.mkdirSync(path.dirname(entrypointPath), {recursive: true});
|
||||
fs.writeFileSync(entrypointPath, entrypointContents, 'utf8');
|
||||
|
||||
const sourceMapPath = path.join(
|
||||
path.dirname(testJSBundlePath),
|
||||
path.basename(testJSBundlePath, '.js') + '.map',
|
||||
);
|
||||
|
||||
await Metro.runBuild(metroConfig, {
|
||||
entry: entrypointPath,
|
||||
out: testJSBundlePath,
|
||||
platform: 'android',
|
||||
minify: isOptimizedMode,
|
||||
dev: !isOptimizedMode,
|
||||
sourceMap: true,
|
||||
sourceMapUrl: sourceMapPath,
|
||||
});
|
||||
|
||||
if (isOptimizedMode) {
|
||||
generateBytecodeBundle({
|
||||
sourcePath: testJSBundlePath,
|
||||
bytecodePath: testBytecodeBundlePath,
|
||||
isOptimizedMode,
|
||||
});
|
||||
}
|
||||
|
||||
const rnTesterCommandArgs = [
|
||||
const rnTesterCommandResult = runBuck2([
|
||||
'run',
|
||||
getBuckModeForPlatform(),
|
||||
getBuckModeForPlatform(isOptimizedMode),
|
||||
'//xplat/ReactNative/react-native-cxx/samples/tester:tester',
|
||||
'--',
|
||||
'--bundlePath',
|
||||
testBundlePath,
|
||||
];
|
||||
const rnTesterCommandResult = spawnSync('buck2', rnTesterCommandArgs, {
|
||||
encoding: 'utf8',
|
||||
env: {
|
||||
...process.env,
|
||||
PATH: `/usr/local/bin:${process.env.PATH ?? ''}`,
|
||||
},
|
||||
});
|
||||
]);
|
||||
|
||||
if (rnTesterCommandResult.status !== 0) {
|
||||
throw new Error(
|
||||
[
|
||||
'Failed to run test in RN tester binary. Full output:',
|
||||
'buck2 ' + rnTesterCommandArgs.join(' '),
|
||||
'stdout:',
|
||||
rnTesterCommandResult.stdout,
|
||||
'stderr:',
|
||||
rnTesterCommandResult.stderr,
|
||||
'error:',
|
||||
rnTesterCommandResult.error,
|
||||
].join('\n'),
|
||||
);
|
||||
throw new Error(getDebugInfoFromCommandResult(rnTesterCommandResult));
|
||||
}
|
||||
|
||||
if (PRINT_FANTOM_OUTPUT) {
|
||||
console.log(
|
||||
[
|
||||
'RN tester binary. Full output:',
|
||||
'buck2 ' + rnTesterCommandArgs.join(' '),
|
||||
'stdout:',
|
||||
rnTesterCommandResult.stdout,
|
||||
'stderr:',
|
||||
rnTesterCommandResult.stderr,
|
||||
'error:',
|
||||
rnTesterCommandResult.error,
|
||||
].join('\n'),
|
||||
);
|
||||
console.log(getDebugInfoFromCommandResult(rnTesterCommandResult));
|
||||
}
|
||||
|
||||
const rnTesterParsedOutput = parseRNTesterCommandResult(
|
||||
rnTesterCommandArgs,
|
||||
rnTesterCommandResult,
|
||||
);
|
||||
|
||||
const testResultError = rnTesterParsedOutput.testResult.error;
|
||||
if (testResultError) {
|
||||
const error = new Error(testResultError.message);
|
||||
error.stack = testResultError.stack;
|
||||
error.stack = symbolicateStackTrace(sourceMapPath, testResultError.stack);
|
||||
throw error;
|
||||
}
|
||||
|
||||
@@ -248,6 +184,9 @@ module.exports = async function runTest(
|
||||
failureDetails: [] as Array<string>,
|
||||
testFilePath: testPath,
|
||||
...testResult,
|
||||
failureMessages: testResult.failureMessages.map(maybeStackTrace =>
|
||||
symbolicateStackTrace(sourceMapPath, maybeStackTrace),
|
||||
),
|
||||
})) ?? [];
|
||||
|
||||
return {
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import {spawnSync} from 'child_process';
|
||||
import crypto from 'crypto';
|
||||
import fs from 'fs';
|
||||
// $FlowExpectedError[untyped-import]
|
||||
import {extract, parse} from 'jest-docblock';
|
||||
import os from 'os';
|
||||
// $FlowExpectedError[untyped-import]
|
||||
import {SourceMapConsumer} from 'source-map';
|
||||
|
||||
type DocblockPragmas = {[key: string]: string | string[]};
|
||||
type FantomTestMode = 'dev' | 'opt';
|
||||
type FantomTestConfig = {
|
||||
mode: FantomTestMode,
|
||||
};
|
||||
|
||||
const DEFAULT_MODE: FantomTestMode = 'dev';
|
||||
|
||||
/**
|
||||
* Extracts the Fantom configuration from the test file, specified as part of
|
||||
* the docblock comment. E.g.:
|
||||
*
|
||||
* ```
|
||||
* /**
|
||||
* * @flow strict-local
|
||||
* * @fantom mode:opt
|
||||
* *
|
||||
* ```
|
||||
*
|
||||
* So far the only supported option is `mode`, which can be 'dev' or 'opt'.
|
||||
*/
|
||||
export function getFantomTestConfig(testPath: string): FantomTestConfig {
|
||||
const docblock = extract(fs.readFileSync(testPath, 'utf8'));
|
||||
const pragmas = parse(docblock) as DocblockPragmas;
|
||||
|
||||
const config = {
|
||||
mode: DEFAULT_MODE,
|
||||
};
|
||||
|
||||
const maybeMode = pragmas.fantom_mode;
|
||||
|
||||
if (maybeMode != null) {
|
||||
if (Array.isArray(maybeMode)) {
|
||||
throw new Error('Expected a single value for @fantom_mode');
|
||||
}
|
||||
|
||||
const mode = maybeMode;
|
||||
|
||||
if (mode === 'dev' || mode === 'opt') {
|
||||
config.mode = mode;
|
||||
} else {
|
||||
throw new Error(`Invalid Fantom mode: ${mode}`);
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
export function getBuckModeForPlatform(enableRelease: boolean = false): string {
|
||||
const mode = enableRelease ? 'opt' : 'dev';
|
||||
|
||||
switch (os.platform()) {
|
||||
case 'linux':
|
||||
return `@//arvr/mode/linux/${mode}`;
|
||||
case 'darwin':
|
||||
return os.arch() === 'arm64'
|
||||
? `@//arvr/mode/mac-arm/${mode}`
|
||||
: `@//arvr/mode/mac/${mode}`;
|
||||
case 'win32':
|
||||
return `@//arvr/mode/win/${mode}`;
|
||||
default:
|
||||
throw new Error(`Unsupported platform: ${os.platform()}`);
|
||||
}
|
||||
}
|
||||
|
||||
type SpawnResultWithOriginalCommand = {
|
||||
...ReturnType<typeof spawnSync>,
|
||||
originalCommand: string,
|
||||
...
|
||||
};
|
||||
|
||||
export function runBuck2(args: Array<string>): SpawnResultWithOriginalCommand {
|
||||
const result = spawnSync('buck2', args, {
|
||||
encoding: 'utf8',
|
||||
env: {
|
||||
...process.env,
|
||||
PATH: `/usr/local/bin:${process.env.PATH ?? ''}`,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
...result,
|
||||
originalCommand: `buck2 ${args.join(' ')}`,
|
||||
};
|
||||
}
|
||||
|
||||
export function getDebugInfoFromCommandResult(
|
||||
commandResult: SpawnResultWithOriginalCommand,
|
||||
): string {
|
||||
const logLines = [
|
||||
`Command ${commandResult.status === 0 ? 'succeeded' : 'failed'}: ${commandResult.originalCommand}`,
|
||||
'',
|
||||
'stdout:',
|
||||
commandResult.stdout,
|
||||
'',
|
||||
'stderr:',
|
||||
commandResult.stderr,
|
||||
];
|
||||
|
||||
if (commandResult.error) {
|
||||
logLines.push('', 'error:', String(commandResult.error));
|
||||
}
|
||||
|
||||
return logLines.join('\n');
|
||||
}
|
||||
|
||||
export function getShortHash(contents: string): string {
|
||||
return crypto.createHash('md5').update(contents).digest('hex').slice(0, 8);
|
||||
}
|
||||
|
||||
export function symbolicateStackTrace(
|
||||
sourceMapPath: string,
|
||||
stackTrace: string,
|
||||
): string {
|
||||
const sourceMapData = JSON.parse(fs.readFileSync(sourceMapPath, 'utf8'));
|
||||
const consumer = new SourceMapConsumer(sourceMapData);
|
||||
|
||||
return stackTrace
|
||||
.split('\n')
|
||||
.map(line => {
|
||||
const match = line.match(/at (.*) \((.*):(\d+):(\d+)\)/);
|
||||
if (match) {
|
||||
const functionName = match[1];
|
||||
// const fileName = match[2];
|
||||
const lineNumber = parseInt(match[3], 10);
|
||||
const columnNumber = parseInt(match[4], 10);
|
||||
// Get the original position
|
||||
const originalPosition = consumer.originalPositionFor({
|
||||
line: lineNumber,
|
||||
column: columnNumber,
|
||||
});
|
||||
return `at ${originalPosition.name ?? functionName} (${originalPosition.source}:${originalPosition.line}:${originalPosition.column})`;
|
||||
} else {
|
||||
return line;
|
||||
}
|
||||
})
|
||||
.join('\n');
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
require('../../../../scripts/build/babel-register').registerForMonorepo();
|
||||
|
||||
module.exports = require('./warmup');
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import {
|
||||
getBuckModeForPlatform,
|
||||
getDebugInfoFromCommandResult,
|
||||
runBuck2,
|
||||
} from '../utils';
|
||||
// $FlowExpectedError[untyped-import]
|
||||
import fs from 'fs';
|
||||
import Metro from 'metro';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
export default async function warmUp(
|
||||
globalConfig: {...},
|
||||
projectConfig: {...},
|
||||
): Promise<void> {
|
||||
try {
|
||||
warmUpHermesCompiler();
|
||||
warmUpRNTesterCLI();
|
||||
await warmUpMetro();
|
||||
} catch (e) {
|
||||
// Sandcastle fails to parse the test output if we log stuff to stdout/stderr.
|
||||
if ((process.env.SANDCASTLE ?? '') !== '') {
|
||||
console.error(
|
||||
'Global warmup failed. Tests will continue to run but will likely fail. Details:\n',
|
||||
e,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function warmUpMetro(): Promise<void> {
|
||||
const metroConfig = await Metro.loadConfig({
|
||||
config: path.resolve(__dirname, '..', '..', 'config', 'metro.config.js'),
|
||||
});
|
||||
|
||||
const entrypointPath = path.resolve(
|
||||
__dirname,
|
||||
'..',
|
||||
'..',
|
||||
'runtime',
|
||||
'WarmUpEntryPoint.js',
|
||||
);
|
||||
|
||||
const bundlePath = path.join(
|
||||
os.tmpdir(),
|
||||
`fantom-warmup-bundle-${Date.now()}.js`,
|
||||
);
|
||||
|
||||
await Metro.runBuild(metroConfig, {
|
||||
entry: entrypointPath,
|
||||
out: bundlePath,
|
||||
platform: 'android',
|
||||
minify: false,
|
||||
dev: true,
|
||||
});
|
||||
|
||||
try {
|
||||
fs.unlinkSync(bundlePath);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function warmUpHermesCompiler(): void {
|
||||
const buildHermesCompilerCommandResult = runBuck2([
|
||||
'build',
|
||||
getBuckModeForPlatform(),
|
||||
'//xplat/hermes/tools/hermesc:hermesc',
|
||||
]);
|
||||
|
||||
if (buildHermesCompilerCommandResult.status !== 0) {
|
||||
throw new Error(
|
||||
getDebugInfoFromCommandResult(buildHermesCompilerCommandResult),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function warmUpRNTesterCLI(): void {
|
||||
const buildRNTesterCommandResult = runBuck2([
|
||||
'build',
|
||||
getBuckModeForPlatform(),
|
||||
'//xplat/ReactNative/react-native-cxx/samples/tester:tester',
|
||||
]);
|
||||
|
||||
if (buildRNTesterCommandResult.status !== 0) {
|
||||
throw new Error(getDebugInfoFromCommandResult(buildRNTesterCommandResult));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is just an entrypoint to warm up the Metro cache before the tests run.
|
||||
*/
|
||||
|
||||
import 'react-native/Libraries/Core/InitializeCore.js';
|
||||
import 'react-native/src/private/__tests__/ReactNativeTester';
|
||||
import './setup';
|
||||
@@ -175,6 +175,41 @@ function createMockFunction<TArgs: $ReadOnlyArray<mixed>, TReturn>(
|
||||
|
||||
// flowlint unsafe-getters-setters:off
|
||||
|
||||
class ErrorWithCustomBlame extends Error {
|
||||
// Initially 5 to ignore all the frames from Babel helpers to instantiate this
|
||||
// custom error class.
|
||||
#ignoredFrameCount: number = 5;
|
||||
#cachedProcessedStack: ?string;
|
||||
|
||||
blameToPreviousFrame(): this {
|
||||
this.#ignoredFrameCount++;
|
||||
return this;
|
||||
}
|
||||
|
||||
get stack(): string {
|
||||
if (this.#cachedProcessedStack == null) {
|
||||
const originalStack = super.stack;
|
||||
|
||||
if (originalStack == null) {
|
||||
this.#cachedProcessedStack = originalStack;
|
||||
} else {
|
||||
const lines = originalStack.split('\n');
|
||||
const index = lines.findIndex(line =>
|
||||
/at (.*) \((.*):(\d+):(\d+)\)/.test(line),
|
||||
);
|
||||
lines.splice(index > -1 ? index : 1, this.#ignoredFrameCount);
|
||||
this.#cachedProcessedStack = lines.join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
return this.#cachedProcessedStack;
|
||||
}
|
||||
|
||||
set stack(value: string) {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
class Expect {
|
||||
#received: mixed;
|
||||
#isNot: boolean = false;
|
||||
@@ -191,27 +226,27 @@ class Expect {
|
||||
toEqual(expected: mixed): void {
|
||||
const pass = deepEqual(this.#received, expected, {strict: true});
|
||||
if (!this.#isExpectedResult(pass)) {
|
||||
throw new Error(
|
||||
throw new ErrorWithCustomBlame(
|
||||
`Expected${this.#maybeNotLabel()} to equal ${String(expected)} but received ${String(this.#received)}.`,
|
||||
);
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
}
|
||||
|
||||
toBe(expected: mixed): void {
|
||||
const pass = this.#received === expected;
|
||||
if (!this.#isExpectedResult(pass)) {
|
||||
throw new Error(
|
||||
throw new ErrorWithCustomBlame(
|
||||
`Expected${this.#maybeNotLabel()} ${String(expected)} but received ${String(this.#received)}.`,
|
||||
);
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
}
|
||||
|
||||
toBeInstanceOf(expected: Class<mixed>): void {
|
||||
const pass = this.#received instanceof expected;
|
||||
if (!this.#isExpectedResult(pass)) {
|
||||
throw new Error(
|
||||
throw new ErrorWithCustomBlame(
|
||||
`expected ${String(this.#received)}${this.#maybeNotLabel()} to be an instance of ${String(expected)}`,
|
||||
);
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,26 +254,26 @@ class Expect {
|
||||
const pass =
|
||||
Math.abs(expected - Number(this.#received)) < Math.pow(10, -precision);
|
||||
if (!this.#isExpectedResult(pass)) {
|
||||
throw new Error(
|
||||
throw new ErrorWithCustomBlame(
|
||||
`Expected ${String(this.#received)}${this.#maybeNotLabel()} to be close to ${expected}`,
|
||||
);
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
}
|
||||
|
||||
toBeNull(): void {
|
||||
const pass = this.#received == null;
|
||||
if (!this.#isExpectedResult(pass)) {
|
||||
throw new Error(
|
||||
throw new ErrorWithCustomBlame(
|
||||
`Expected ${String(this.#received)}${this.#maybeNotLabel()} to be null`,
|
||||
);
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
}
|
||||
|
||||
toThrow(expected?: string): void {
|
||||
if (expected != null && typeof expected !== 'string') {
|
||||
throw new Error(
|
||||
throw new ErrorWithCustomBlame(
|
||||
'toThrow() implementation only accepts strings as arguments.',
|
||||
);
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
|
||||
let pass = false;
|
||||
@@ -249,9 +284,9 @@ class Expect {
|
||||
pass = expected != null ? error.message === expected : true;
|
||||
}
|
||||
if (!this.#isExpectedResult(pass)) {
|
||||
throw new Error(
|
||||
throw new ErrorWithCustomBlame(
|
||||
`Expected ${String(this.#received)}${this.#maybeNotLabel()} to throw`,
|
||||
);
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,9 +294,9 @@ class Expect {
|
||||
const mock = this.#requireMock();
|
||||
const pass = mock.calls.length > 0;
|
||||
if (!this.#isExpectedResult(pass)) {
|
||||
throw new Error(
|
||||
throw new ErrorWithCustomBlame(
|
||||
`Expected ${String(this.#received)}${this.#maybeNotLabel()} to have been called, but it was${this.#isNot ? '' : "n't"}`,
|
||||
);
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,9 +304,51 @@ class Expect {
|
||||
const mock = this.#requireMock();
|
||||
const pass = mock.calls.length === times;
|
||||
if (!this.#isExpectedResult(pass)) {
|
||||
throw new Error(
|
||||
throw new ErrorWithCustomBlame(
|
||||
`Expected ${String(this.#received)}${this.#maybeNotLabel()} to have been called ${times} times, but it was called ${mock.calls.length} times`,
|
||||
);
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
}
|
||||
|
||||
toBeGreaterThanOrEqual(expected: number): void {
|
||||
if (typeof this.#received !== 'number') {
|
||||
throw new ErrorWithCustomBlame(
|
||||
`Expected ${String(this.#received)} to be a number but it was a ${typeof this.#received}`,
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
|
||||
if (typeof expected !== 'number') {
|
||||
throw new ErrorWithCustomBlame(
|
||||
`Expected ${String(expected)} to be a number but it was a ${typeof expected}`,
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
|
||||
const pass = this.#received >= expected;
|
||||
if (!this.#isExpectedResult(pass)) {
|
||||
throw new ErrorWithCustomBlame(
|
||||
`Expected ${String(this.#received)}${this.#maybeNotLabel()} to be greater than or equal to ${expected}`,
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
}
|
||||
|
||||
toBeLessThanOrEqual(expected: number): void {
|
||||
if (typeof this.#received !== 'number') {
|
||||
throw new ErrorWithCustomBlame(
|
||||
`Expected ${String(this.#received)} to be a number but it was a ${typeof this.#received}`,
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
|
||||
if (typeof expected !== 'number') {
|
||||
throw new ErrorWithCustomBlame(
|
||||
`Expected ${String(expected)} to be a number but it was a ${typeof expected}`,
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
|
||||
const pass = this.#received <= expected;
|
||||
if (!this.#isExpectedResult(pass)) {
|
||||
throw new ErrorWithCustomBlame(
|
||||
`Expected ${String(this.#received)}${this.#maybeNotLabel()} to be less than or equal to ${expected}`,
|
||||
).blameToPreviousFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,9 +363,11 @@ class Expect {
|
||||
#requireMock(): JestMockFn<$ReadOnlyArray<mixed>, mixed>['mock'] {
|
||||
// $FlowExpectedError[incompatible-use]
|
||||
if (!this.#received?.[MOCK_FN_TAG]) {
|
||||
throw new Error(
|
||||
throw new ErrorWithCustomBlame(
|
||||
`Expected ${String(this.#received)} to be a mock function, but it wasn't`,
|
||||
);
|
||||
)
|
||||
.blameToPreviousFrame()
|
||||
.blameToPreviousFrame();
|
||||
}
|
||||
|
||||
// $FlowExpectedError[incompatible-use]
|
||||
@@ -346,7 +425,9 @@ function executeTests() {
|
||||
result.status = status;
|
||||
result.duration = Date.now() - start;
|
||||
result.failureMessages =
|
||||
status === 'failed' && error ? [error.message] : [];
|
||||
status === 'failed' && error
|
||||
? [error.stack ?? error.message ?? String(error)]
|
||||
: [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -77,12 +77,13 @@
|
||||
"eslint-plugin-redundant-undefined": "^0.4.0",
|
||||
"eslint-plugin-relay": "^1.8.3",
|
||||
"flow-api-translator": "0.25.1",
|
||||
"flow-bin": "^0.254.2",
|
||||
"flow-bin": "^0.255.0",
|
||||
"glob": "^7.1.1",
|
||||
"hermes-eslint": "0.25.1",
|
||||
"hermes-transform": "0.25.1",
|
||||
"inquirer": "^7.1.0",
|
||||
"jest": "^29.6.3",
|
||||
"jest-diff": "^29.7.0",
|
||||
"jest-junit": "^10.0.0",
|
||||
"jscodeshift": "^0.14.0",
|
||||
"metro-babel-register": "^0.81.0",
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
"metro": "^0.81.0",
|
||||
"metro-config": "^0.81.0",
|
||||
"metro-core": "^0.81.0",
|
||||
"node-fetch": "^2.2.0",
|
||||
"readline": "^1.3.0",
|
||||
"semver": "^7.1.3"
|
||||
},
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
import type TerminalReporter from 'metro/src/lib/TerminalReporter';
|
||||
|
||||
import chalk from 'chalk';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
type PageDescription = $ReadOnly<{
|
||||
id: string,
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
*/
|
||||
|
||||
import net from 'net';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
/**
|
||||
* Determine whether we can run the dev server.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@generated SignedSource<<6b92b66e59525cef52902139f863f175>>
|
||||
Git revision: b61aae3ccc6e2684dfbf1e2a06b0f985b459f11f
|
||||
@generated SignedSource<<cecad43da3fd917e15322ee3efbed875>>
|
||||
Git revision: 486803f6bf272e0629297265dee8048a2f1269dd
|
||||
Built with --nohooks: false
|
||||
Is local checkout: false
|
||||
Remote URL: https://github.com/facebookexperimental/rn-chrome-devtools-frontend
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -42,7 +42,7 @@ import*as e from"../../ui/legacy/legacy.js";import*as t from"../../core/host/hos
|
||||
<p>${d(a.docsDebuggingBasicsDetail)}</p>
|
||||
</div>
|
||||
</button>
|
||||
<button class="rn-welcome-docsfeed-item" type="button" role="link" @click=${this.#o.bind(this,"https://reactnative.dev/docs/react-devtools")} title=${d(a.docsReactNativeDevTools)}>
|
||||
<button class="rn-welcome-docsfeed-item" type="button" role="link" @click=${this.#o.bind(this,"https://reactnative.dev/docs/react-native-devtools")} title=${d(a.docsReactNativeDevTools)}>
|
||||
<div class="rn-welcome-image" style="background-image: url('${c}')"></div>
|
||||
<div>
|
||||
<p class="devtools-link">${d(a.docsReactNativeDevTools)}</p>
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -11,7 +11,7 @@
|
||||
|
||||
import type {CreateCustomMessageHandlerFn} from './inspector-proxy/CustomMessageHandler';
|
||||
import type {BrowserLauncher} from './types/BrowserLauncher';
|
||||
import type {EventReporter} from './types/EventReporter';
|
||||
import type {EventReporter, ReportableEvent} from './types/EventReporter';
|
||||
import type {Experiments, ExperimentsConfig} from './types/Experiments';
|
||||
import type {Logger} from './types/Logger';
|
||||
import type {NextHandleFunction} from 'connect';
|
||||
@@ -81,11 +81,15 @@ export default function createDevMiddleware({
|
||||
unstable_customInspectorMessageHandler,
|
||||
}: Options): DevMiddlewareAPI {
|
||||
const experiments = getExperiments(experimentConfig);
|
||||
const eventReporter = createWrappedEventReporter(
|
||||
unstable_eventReporter,
|
||||
logger,
|
||||
);
|
||||
|
||||
const inspectorProxy = new InspectorProxy(
|
||||
projectRoot,
|
||||
serverBaseUrl,
|
||||
unstable_eventReporter,
|
||||
eventReporter,
|
||||
experiments,
|
||||
unstable_customInspectorMessageHandler,
|
||||
);
|
||||
@@ -97,7 +101,7 @@ export default function createDevMiddleware({
|
||||
serverBaseUrl,
|
||||
inspectorProxy,
|
||||
browserLauncher: unstable_browserLauncher,
|
||||
eventReporter: unstable_eventReporter,
|
||||
eventReporter,
|
||||
experiments,
|
||||
logger,
|
||||
}),
|
||||
@@ -129,3 +133,26 @@ function getExperiments(config: ExperimentsConfig): Experiments {
|
||||
enableNetworkInspector: config.enableNetworkInspector ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wrapped EventReporter that locally intercepts events to
|
||||
* log to the terminal.
|
||||
*/
|
||||
function createWrappedEventReporter(
|
||||
reporter: ?EventReporter,
|
||||
logger: ?Logger,
|
||||
): EventReporter {
|
||||
return {
|
||||
logEvent(event: ReportableEvent) {
|
||||
switch (event.type) {
|
||||
case 'profiling_target_registered':
|
||||
logger?.info(
|
||||
`Profiling build target "${event.appId}" registered for debugging`,
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
reporter?.logEvent(event);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ export type DeviceOptions = $ReadOnly<{
|
||||
createMessageMiddleware: ?CreateCustomMessageHandlerFn,
|
||||
deviceRelativeBaseUrl: URL,
|
||||
serverRelativeBaseUrl: URL,
|
||||
isProfilingBuild: boolean,
|
||||
}>;
|
||||
|
||||
/**
|
||||
@@ -140,6 +141,7 @@ export default class Device {
|
||||
createMessageMiddleware,
|
||||
serverRelativeBaseUrl,
|
||||
deviceRelativeBaseUrl,
|
||||
isProfilingBuild,
|
||||
}: DeviceOptions) {
|
||||
this.#id = id;
|
||||
this.#name = name;
|
||||
@@ -157,6 +159,10 @@ export default class Device {
|
||||
: null;
|
||||
this.#createCustomMessageHandler = createMessageMiddleware;
|
||||
|
||||
if (isProfilingBuild) {
|
||||
this.#deviceEventReporter?.logProfilingTargetRegistered();
|
||||
}
|
||||
|
||||
// $FlowFixMe[incompatible-call]
|
||||
this.#deviceSocket.on('message', (message: string) => {
|
||||
this.#messageFromDeviceQueue = this.#messageFromDeviceQueue
|
||||
|
||||
@@ -145,6 +145,17 @@ class DeviceEventReporter {
|
||||
});
|
||||
}
|
||||
|
||||
logProfilingTargetRegistered() {
|
||||
this.#eventReporter.logEvent({
|
||||
type: 'profiling_target_registered',
|
||||
status: 'success',
|
||||
appId: this.#metadata.appId,
|
||||
deviceName: this.#metadata.deviceName,
|
||||
deviceId: this.#metadata.deviceId,
|
||||
pageId: null,
|
||||
});
|
||||
}
|
||||
|
||||
logConnection(
|
||||
connectedEntity: 'debugger',
|
||||
metadata: $ReadOnly<{
|
||||
|
||||
@@ -225,6 +225,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
|
||||
const deviceId = query.device || fallbackDeviceId;
|
||||
const deviceName = query.name || 'Unknown';
|
||||
const appName = query.app || 'Unknown';
|
||||
const isProfilingBuild = query.profiling === 'true';
|
||||
|
||||
const deviceRelativeBaseUrl =
|
||||
getBaseUrlFromRequest(req) ?? this.#serverBaseUrl;
|
||||
@@ -242,6 +243,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
|
||||
createMessageMiddleware: this.#customMessageHandler,
|
||||
deviceRelativeBaseUrl,
|
||||
serverRelativeBaseUrl: this.#serverBaseUrl,
|
||||
isProfilingBuild,
|
||||
};
|
||||
|
||||
if (oldDevice) {
|
||||
|
||||
@@ -77,6 +77,11 @@ export type ReportableEvent =
|
||||
| 'PROTOCOL_ERROR',
|
||||
>,
|
||||
}
|
||||
| {
|
||||
type: 'profiling_target_registered',
|
||||
status: 'success',
|
||||
...DebuggerSessionIDs,
|
||||
}
|
||||
| {
|
||||
type: 'proxy_error',
|
||||
status: 'error',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
+7
-3
@@ -12,6 +12,7 @@ import com.facebook.react.utils.detectOSAwareHermesCommand
|
||||
import com.facebook.react.utils.moveTo
|
||||
import com.facebook.react.utils.windowsAwareCommandLine
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.ConfigurableFileTree
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
@@ -19,6 +20,7 @@ import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.process.ExecOperations
|
||||
|
||||
abstract class BundleHermesCTask : DefaultTask() {
|
||||
|
||||
@@ -26,6 +28,8 @@ abstract class BundleHermesCTask : DefaultTask() {
|
||||
group = "react"
|
||||
}
|
||||
|
||||
@get:Inject abstract val execOperations: ExecOperations
|
||||
|
||||
@get:Internal abstract val root: DirectoryProperty
|
||||
|
||||
@get:InputFiles
|
||||
@@ -127,9 +131,9 @@ abstract class BundleHermesCTask : DefaultTask() {
|
||||
File(jsIntermediateSourceMapsDir.get().asFile, "$bundleAssetName.compiler.map")
|
||||
|
||||
private fun runCommand(command: List<Any>) {
|
||||
project.exec {
|
||||
it.workingDir(root.get().asFile)
|
||||
it.commandLine(command)
|
||||
execOperations.exec { exec ->
|
||||
exec.workingDir(root.get().asFile)
|
||||
exec.commandLine(command)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ abstract class BuildCodegenCLITask : Exec() {
|
||||
}
|
||||
|
||||
override fun exec() {
|
||||
val logfile = "${project.layout.buildDirectory}/build-cli.log"
|
||||
val logfile = "${project.layout.buildDirectory.getAsFile().get()}/build-cli.log"
|
||||
File(logfile).apply {
|
||||
parentFile.mkdirs()
|
||||
if (exists()) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
+1
-1
@@ -327,7 +327,7 @@ export interface NativeModuleBooleanTypeAnnotation {
|
||||
|
||||
export type NativeModuleEnumMember = {
|
||||
readonly name: string;
|
||||
readonly value: string | number;
|
||||
readonly value: NativeModuleStringLiteralTypeAnnotation | NativeModuleNumberLiteralTypeAnnotation,
|
||||
};
|
||||
|
||||
export type NativeModuleEnumMemberType =
|
||||
|
||||
+1
-1
@@ -311,7 +311,7 @@ export type NativeModuleNumberTypeAnnotation = $ReadOnly<{
|
||||
|
||||
export type NativeModuleEnumMember = {
|
||||
name: string,
|
||||
value: string | number,
|
||||
value: StringLiteralTypeAnnotation | NumberLiteralTypeAnnotation,
|
||||
};
|
||||
|
||||
export type NativeModuleEnumMemberType =
|
||||
|
||||
@@ -96,7 +96,7 @@ function combineSchemasInFileListAndWriteToFile(
|
||||
exclude: ?RegExp,
|
||||
): void {
|
||||
const combined = combineSchemasInFileList(fileList, platform, exclude);
|
||||
const formattedSchema = JSON.stringify(combined, null, 2);
|
||||
const formattedSchema = JSON.stringify(combined);
|
||||
fs.writeFileSync(outfile, formattedSchema);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,4 +84,4 @@ for (const file of schemaFiles) {
|
||||
}
|
||||
}
|
||||
|
||||
fs.writeFileSync(output, JSON.stringify({modules}, null, 2));
|
||||
fs.writeFileSync(output, JSON.stringify({modules}));
|
||||
|
||||
@@ -406,6 +406,14 @@ struct Bridging<${enumName}> {
|
||||
};`;
|
||||
};
|
||||
|
||||
function getMemberValueAppearance(member: NativeModuleEnumMember['value']) {
|
||||
if (member.type === 'StringLiteralTypeAnnotation') {
|
||||
return `"${member.value}"`;
|
||||
} else {
|
||||
return member.value;
|
||||
}
|
||||
}
|
||||
|
||||
function generateEnum(
|
||||
hasteModuleName: string,
|
||||
origEnumName: string,
|
||||
@@ -417,9 +425,6 @@ function generateEnum(
|
||||
const nativeEnumMemberType: NativeEnumMemberValueType =
|
||||
memberType === 'StringTypeAnnotation' ? 'std::string' : 'int32_t';
|
||||
|
||||
const getMemberValueAppearance = (value: string | number) =>
|
||||
memberType === 'StringTypeAnnotation' ? `"${value}"` : `${value}`;
|
||||
|
||||
const fromCases =
|
||||
members
|
||||
.map(
|
||||
|
||||
+61
-16
@@ -163,11 +163,17 @@ const SIMPLE_NATIVE_MODULES: SchemaType = {
|
||||
members: [
|
||||
{
|
||||
name: 'ONE',
|
||||
value: '1',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'TWO',
|
||||
value: '2',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 2,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -178,15 +184,24 @@ const SIMPLE_NATIVE_MODULES: SchemaType = {
|
||||
members: [
|
||||
{
|
||||
name: 'POINT_ZERO',
|
||||
value: '0.0',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 0.0,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'POINT_ONE',
|
||||
value: '0.1',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 0.1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'POINT_TWO',
|
||||
value: '0.2',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 0.2,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -197,11 +212,17 @@ const SIMPLE_NATIVE_MODULES: SchemaType = {
|
||||
members: [
|
||||
{
|
||||
name: 'HELLO',
|
||||
value: 'hello',
|
||||
value: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: 'hello',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'GoodBye',
|
||||
value: 'goodbye',
|
||||
value: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: 'goodbye',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -1926,11 +1947,17 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = {
|
||||
members: [
|
||||
{
|
||||
name: 'IA',
|
||||
value: '23',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 23,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'IB',
|
||||
value: '42',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 42,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -1941,11 +1968,17 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = {
|
||||
members: [
|
||||
{
|
||||
name: 'FA',
|
||||
value: '1.23',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 1.23,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'FB',
|
||||
value: '4.56',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 4.56,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -1956,11 +1989,17 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = {
|
||||
members: [
|
||||
{
|
||||
name: 'NA',
|
||||
value: 'NA',
|
||||
value: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: 'NA',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'NB',
|
||||
value: 'NB',
|
||||
value: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: 'NB',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -1971,11 +2010,17 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = {
|
||||
members: [
|
||||
{
|
||||
name: 'SA',
|
||||
value: 's---a',
|
||||
value: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: 's---a',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'SB',
|
||||
value: 's---b',
|
||||
value: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: 's---b',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -2673,7 +2718,7 @@ const UNION_MODULE: SchemaType = {
|
||||
},
|
||||
};
|
||||
|
||||
const STRING_LITERALS = {
|
||||
const STRING_LITERALS: SchemaType = {
|
||||
modules: {
|
||||
NativeSampleTurboModule: {
|
||||
type: 'NativeModule',
|
||||
|
||||
+2
-2
@@ -2047,7 +2047,7 @@ template <>
|
||||
struct Bridging<NativeSampleTurboModuleFloatEnum> {
|
||||
static NativeSampleTurboModuleFloatEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) {
|
||||
double value = (double)rawValue.asNumber();
|
||||
if (value == 0.0) {
|
||||
if (value == 0) {
|
||||
return NativeSampleTurboModuleFloatEnum::POINT_ZERO;
|
||||
} else if (value == 0.1) {
|
||||
return NativeSampleTurboModuleFloatEnum::POINT_ONE;
|
||||
@@ -2060,7 +2060,7 @@ struct Bridging<NativeSampleTurboModuleFloatEnum> {
|
||||
|
||||
static jsi::Value toJs(jsi::Runtime &rt, NativeSampleTurboModuleFloatEnum value) {
|
||||
if (value == NativeSampleTurboModuleFloatEnum::POINT_ZERO) {
|
||||
return bridging::toJs(rt, 0.0);
|
||||
return bridging::toJs(rt, 0);
|
||||
} else if (value == NativeSampleTurboModuleFloatEnum::POINT_ONE) {
|
||||
return bridging::toJs(rt, 0.1);
|
||||
} else if (value == NativeSampleTurboModuleFloatEnum::POINT_TWO) {
|
||||
|
||||
+16
-4
@@ -478,11 +478,17 @@ describe('typeEnumResolution', () => {
|
||||
members: [
|
||||
{
|
||||
name: 'Hello',
|
||||
value: 'hello',
|
||||
value: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: 'hello',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Goodbye',
|
||||
value: 'goodbye',
|
||||
value: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: 'goodbye',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -521,11 +527,17 @@ describe('typeEnumResolution', () => {
|
||||
members: [
|
||||
{
|
||||
name: 'On',
|
||||
value: '1',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Off',
|
||||
value: '0',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
+60
-15
@@ -147,11 +147,17 @@ exports[`RN Codegen Flow Parser can generate fixture CXX_ONLY_NATIVE_MODULE 1`]
|
||||
'members': [
|
||||
{
|
||||
'name': 'SD',
|
||||
'value': 'SD'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'SD'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'HD',
|
||||
'value': 'HD'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'HD'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -162,15 +168,24 @@ exports[`RN Codegen Flow Parser can generate fixture CXX_ONLY_NATIVE_MODULE 1`]
|
||||
'members': [
|
||||
{
|
||||
'name': 'Corrupted',
|
||||
'value': -1
|
||||
'value': {
|
||||
'type': 'NumberLiteralTypeAnnotation',
|
||||
'value': -1
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Low',
|
||||
'value': 720
|
||||
'value': {
|
||||
'type': 'NumberLiteralTypeAnnotation',
|
||||
'value': 720
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'High',
|
||||
'value': 1080
|
||||
'value': {
|
||||
'type': 'NumberLiteralTypeAnnotation',
|
||||
'value': 1080
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -181,15 +196,24 @@ exports[`RN Codegen Flow Parser can generate fixture CXX_ONLY_NATIVE_MODULE 1`]
|
||||
'members': [
|
||||
{
|
||||
'name': 'One',
|
||||
'value': 'one'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'one'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Two',
|
||||
'value': 'two'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'two'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Three',
|
||||
'value': 'three'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'three'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -471,11 +495,17 @@ exports[`RN Codegen Flow Parser can generate fixture IOS_ONLY_NATIVE_MODULE 1`]
|
||||
'members': [
|
||||
{
|
||||
'name': 'SD',
|
||||
'value': 'SD'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'SD'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'HD',
|
||||
'value': 'HD'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'HD'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -486,11 +516,17 @@ exports[`RN Codegen Flow Parser can generate fixture IOS_ONLY_NATIVE_MODULE 1`]
|
||||
'members': [
|
||||
{
|
||||
'name': 'Low',
|
||||
'value': 720
|
||||
'value': {
|
||||
'type': 'NumberLiteralTypeAnnotation',
|
||||
'value': 720
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'High',
|
||||
'value': 1080
|
||||
'value': {
|
||||
'type': 'NumberLiteralTypeAnnotation',
|
||||
'value': 1080
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -501,15 +537,24 @@ exports[`RN Codegen Flow Parser can generate fixture IOS_ONLY_NATIVE_MODULE 1`]
|
||||
'members': [
|
||||
{
|
||||
'name': 'One',
|
||||
'value': 'one'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'one'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Two',
|
||||
'value': 'two'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'two'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Three',
|
||||
'value': 'three'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'three'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+22
-4
@@ -230,10 +230,28 @@ class FlowParser implements Parser {
|
||||
parseEnumMembers(
|
||||
typeAnnotation: $FlowFixMe,
|
||||
): $ReadOnlyArray<NativeModuleEnumMember> {
|
||||
return typeAnnotation.members.map(member => ({
|
||||
name: member.id.name,
|
||||
value: member.init?.value ?? member.id.name,
|
||||
}));
|
||||
return typeAnnotation.members.map(member => {
|
||||
const value =
|
||||
typeof member.init?.value === 'number'
|
||||
? {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: member.init.value,
|
||||
}
|
||||
: typeof member.init?.value === 'string'
|
||||
? {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: member.init.value,
|
||||
}
|
||||
: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: member.id.name,
|
||||
};
|
||||
|
||||
return {
|
||||
name: member.id.name,
|
||||
value: value,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
isModuleInterface(node: $FlowFixMe): boolean {
|
||||
|
||||
+16
-4
@@ -175,21 +175,33 @@ export class MockedParser implements Parser {
|
||||
? [
|
||||
{
|
||||
name: 'Hello',
|
||||
value: 'hello',
|
||||
value: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: 'hello',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Goodbye',
|
||||
value: 'goodbye',
|
||||
value: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: 'goodbye',
|
||||
},
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
name: 'On',
|
||||
value: '1',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Off',
|
||||
value: '0',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
+60
-15
@@ -134,11 +134,17 @@ exports[`RN Codegen TypeScript Parser can generate fixture CXX_ONLY_NATIVE_MODUL
|
||||
'members': [
|
||||
{
|
||||
'name': 'SD',
|
||||
'value': 'SD'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'SD'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'HD',
|
||||
'value': 'HD'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'HD'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -149,15 +155,24 @@ exports[`RN Codegen TypeScript Parser can generate fixture CXX_ONLY_NATIVE_MODUL
|
||||
'members': [
|
||||
{
|
||||
'name': 'Corrupted',
|
||||
'value': -1
|
||||
'value': {
|
||||
'type': 'NumberLiteralTypeAnnotation',
|
||||
'value': -1
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Low',
|
||||
'value': 720
|
||||
'value': {
|
||||
'type': 'NumberLiteralTypeAnnotation',
|
||||
'value': 720
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'High',
|
||||
'value': 1080
|
||||
'value': {
|
||||
'type': 'NumberLiteralTypeAnnotation',
|
||||
'value': 1080
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -168,15 +183,24 @@ exports[`RN Codegen TypeScript Parser can generate fixture CXX_ONLY_NATIVE_MODUL
|
||||
'members': [
|
||||
{
|
||||
'name': 'One',
|
||||
'value': 'one'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'one'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Two',
|
||||
'value': 'two'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'two'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Three',
|
||||
'value': 'three'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'three'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -458,11 +482,17 @@ exports[`RN Codegen TypeScript Parser can generate fixture IOS_ONLY_NATIVE_MODUL
|
||||
'members': [
|
||||
{
|
||||
'name': 'SD',
|
||||
'value': 'SD'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'SD'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'HD',
|
||||
'value': 'HD'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'HD'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -473,11 +503,17 @@ exports[`RN Codegen TypeScript Parser can generate fixture IOS_ONLY_NATIVE_MODUL
|
||||
'members': [
|
||||
{
|
||||
'name': 'Low',
|
||||
'value': 720
|
||||
'value': {
|
||||
'type': 'NumberLiteralTypeAnnotation',
|
||||
'value': 720
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'High',
|
||||
'value': 1080
|
||||
'value': {
|
||||
'type': 'NumberLiteralTypeAnnotation',
|
||||
'value': 1080
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -488,15 +524,24 @@ exports[`RN Codegen TypeScript Parser can generate fixture IOS_ONLY_NATIVE_MODUL
|
||||
'members': [
|
||||
{
|
||||
'name': 'One',
|
||||
'value': 'one'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'one'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Two',
|
||||
'value': 'two'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'two'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Three',
|
||||
'value': 'three'
|
||||
'value': {
|
||||
'type': 'StringLiteralTypeAnnotation',
|
||||
'value': 'three'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+35
-5
@@ -124,9 +124,27 @@ describe('TypeScript Module Parser', () => {
|
||||
|
||||
expect(parser).not.toThrow();
|
||||
expect(parser().enumMap.MyEnum.members).toEqual([
|
||||
{name: 'ZERO', value: 0},
|
||||
{name: 'POSITIVE', value: 1},
|
||||
{name: 'NEGATIVE', value: -1},
|
||||
{
|
||||
name: 'ZERO',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'POSITIVE',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'NEGATIVE',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: -1,
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -147,8 +165,20 @@ describe('TypeScript Module Parser', () => {
|
||||
|
||||
expect(parser).not.toThrow();
|
||||
expect(parser().enumMap.MyEnum.members).toEqual([
|
||||
{name: 'ZERO', value: 0},
|
||||
{name: 'POSITIVE', value: 1},
|
||||
{
|
||||
name: 'ZERO',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'POSITIVE',
|
||||
value: {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: 1,
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -250,17 +250,30 @@ class TypeScriptParser implements Parser {
|
||||
typeAnnotation: $FlowFixMe,
|
||||
): $ReadOnlyArray<NativeModuleEnumMember> {
|
||||
return typeAnnotation.members.map(member => {
|
||||
// Handle negative values
|
||||
if (member.initializer?.operator === '-') {
|
||||
return {
|
||||
name: member.id.name,
|
||||
value: -member.initializer?.argument?.value ?? member.id.name,
|
||||
};
|
||||
}
|
||||
const value =
|
||||
member.initializer?.operator === '-'
|
||||
? {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: -1 * member.initializer?.argument?.value,
|
||||
}
|
||||
: typeof member.initializer?.value === 'number'
|
||||
? {
|
||||
type: 'NumberLiteralTypeAnnotation',
|
||||
value: member.initializer?.value,
|
||||
}
|
||||
: typeof member.initializer?.value === 'string'
|
||||
? {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: member.initializer?.value,
|
||||
}
|
||||
: {
|
||||
type: 'StringLiteralTypeAnnotation',
|
||||
value: member.id.name,
|
||||
};
|
||||
|
||||
return {
|
||||
name: member.id.name,
|
||||
value: member.initializer?.value ?? member.id.name,
|
||||
value,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -106,17 +106,17 @@ export function allowTransformProp(prop: string): void {
|
||||
}
|
||||
|
||||
export function isSupportedColorStyleProp(prop: string): boolean {
|
||||
return Object.hasOwn(SUPPORTED_COLOR_STYLES, prop);
|
||||
return SUPPORTED_COLOR_STYLES.hasOwnProperty(prop);
|
||||
}
|
||||
|
||||
export function isSupportedInterpolationParam(param: string): boolean {
|
||||
return Object.hasOwn(SUPPORTED_INTERPOLATION_PARAMS, param);
|
||||
return SUPPORTED_INTERPOLATION_PARAMS.hasOwnProperty(param);
|
||||
}
|
||||
|
||||
export function isSupportedStyleProp(prop: string): boolean {
|
||||
return Object.hasOwn(SUPPORTED_STYLES, prop);
|
||||
return SUPPORTED_STYLES.hasOwnProperty(prop);
|
||||
}
|
||||
|
||||
export function isSupportedTransformProp(prop: string): boolean {
|
||||
return Object.hasOwn(SUPPORTED_TRANSFORMS, prop);
|
||||
return SUPPORTED_TRANSFORMS.hasOwnProperty(prop);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ function createAnimatedProps(
|
||||
const key = keys[ii];
|
||||
const value = inputProps[key];
|
||||
|
||||
if (allowlist == null || Object.hasOwn(allowlist, key)) {
|
||||
if (allowlist == null || hasOwn(allowlist, key)) {
|
||||
let node;
|
||||
if (key === 'style') {
|
||||
node = AnimatedStyle.from(value, allowlist?.style);
|
||||
@@ -271,3 +271,11 @@ export default class AnimatedProps extends AnimatedNode {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Supported versions of JSC do not implement the newer Object.hasOwn. Remove
|
||||
// this shim when they do.
|
||||
// $FlowIgnore[method-unbinding]
|
||||
const _hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
const hasOwn: (obj: $ReadOnly<{...}>, prop: string) => boolean =
|
||||
// $FlowIgnore[method-unbinding]
|
||||
Object.hasOwn ?? ((obj, prop) => _hasOwnProp.call(obj, prop));
|
||||
|
||||
@@ -35,7 +35,7 @@ function createAnimatedStyle(
|
||||
const key = keys[ii];
|
||||
const value = inputStyle[key];
|
||||
|
||||
if (allowlist == null || Object.hasOwn(allowlist, key)) {
|
||||
if (allowlist == null || hasOwn(allowlist, key)) {
|
||||
let node;
|
||||
if (value != null && key === 'transform') {
|
||||
node = ReactNativeFeatureFlags.shouldUseAnimatedObjectForTransform()
|
||||
@@ -241,3 +241,11 @@ export default class AnimatedStyle extends AnimatedWithChildren {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Supported versions of JSC do not implement the newer Object.hasOwn. Remove
|
||||
// this shim when they do.
|
||||
// $FlowIgnore[method-unbinding]
|
||||
const _hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
const hasOwn: (obj: $ReadOnly<{...}>, prop: string) => boolean =
|
||||
// $FlowIgnore[method-unbinding]
|
||||
Object.hasOwn ?? ((obj, prop) => _hasOwnProp.call(obj, prop));
|
||||
|
||||
@@ -121,7 +121,7 @@ const Presets = {
|
||||
'opacity',
|
||||
): LayoutAnimationConfig),
|
||||
linear: (create(500, 'linear', 'opacity'): LayoutAnimationConfig),
|
||||
spring: {
|
||||
spring: ({
|
||||
duration: 700,
|
||||
create: {
|
||||
type: 'linear',
|
||||
@@ -135,7 +135,7 @@ const Presets = {
|
||||
type: 'linear',
|
||||
property: 'opacity',
|
||||
},
|
||||
},
|
||||
}: LayoutAnimationConfig),
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+11
-3
@@ -28,6 +28,15 @@ type FormDataPart =
|
||||
...
|
||||
};
|
||||
|
||||
/**
|
||||
* Encode a FormData filename compliant with RFC 2183
|
||||
*
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#directives
|
||||
*/
|
||||
function encodeFilename(filename: string): string {
|
||||
return encodeURIComponent(filename.replace(/\//g, '_'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Polyfill for XMLHttpRequest2 FormData API, allowing multipart POST requests
|
||||
* with mixed data (string, native files) to be submitted via XMLHttpRequest.
|
||||
@@ -82,9 +91,8 @@ class FormData {
|
||||
// content type (cf. web Blob interface.)
|
||||
if (typeof value === 'object' && !Array.isArray(value) && value) {
|
||||
if (typeof value.name === 'string') {
|
||||
headers['content-disposition'] += `; filename="${
|
||||
value.name
|
||||
}"; filename*=utf-8''${encodeURI(value.name)}`;
|
||||
headers['content-disposition'] +=
|
||||
`; filename="${encodeFilename(value.name)}"`;
|
||||
}
|
||||
if (typeof value.type === 'string') {
|
||||
headers['content-type'] = value.type;
|
||||
|
||||
@@ -48,8 +48,7 @@ describe('FormData', function () {
|
||||
type: 'image/jpeg',
|
||||
name: 'photo.jpg',
|
||||
headers: {
|
||||
'content-disposition':
|
||||
'form-data; name="photo"; filename="photo.jpg"; filename*=utf-8\'\'photo.jpg',
|
||||
'content-disposition': 'form-data; name="photo"; filename="photo.jpg"',
|
||||
'content-type': 'image/jpeg',
|
||||
},
|
||||
fieldName: 'photo',
|
||||
@@ -70,7 +69,7 @@ describe('FormData', function () {
|
||||
name: '测试photo.jpg',
|
||||
headers: {
|
||||
'content-disposition':
|
||||
'form-data; name="photo"; filename="测试photo.jpg"; filename*=utf-8\'\'%E6%B5%8B%E8%AF%95photo.jpg',
|
||||
'form-data; name="photo"; filename="%E6%B5%8B%E8%AF%95photo.jpg"',
|
||||
'content-type': 'image/jpeg',
|
||||
},
|
||||
fieldName: 'photo',
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import setUpReactFabricPublicInstanceFantomTests from './setUpReactFabricPublicInstanceFantomTests';
|
||||
|
||||
setUpReactFabricPublicInstanceFantomTests({isModern: false});
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import './setUpFeatureFlags';
|
||||
import setUpReactFabricPublicInstanceFantomTests from './setUpReactFabricPublicInstanceFantomTests';
|
||||
|
||||
setUpReactFabricPublicInstanceFantomTests({isModern: true});
|
||||
packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/__tests__/setUpFeatureFlags.js
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import * as ReactNativeFeatureFlags from '../../../../src/private/featureflags/ReactNativeFeatureFlags';
|
||||
|
||||
ReactNativeFeatureFlags.override({
|
||||
enableAccessToHostTreeInFabric: () => true,
|
||||
});
|
||||
+365
@@ -0,0 +1,365 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import '../../../Core/InitializeCore.js';
|
||||
|
||||
import * as ReactNativeTester from '../../../../src/private/__tests__/ReactNativeTester';
|
||||
import ReactNativeElement from '../../../../src/private/webapis/dom/nodes/ReactNativeElement';
|
||||
import TextInputState from '../../../Components/TextInput/TextInputState';
|
||||
import View from '../../../Components/View/View';
|
||||
import ReactFabricHostComponent from '../ReactFabricHostComponent';
|
||||
import nullthrows from 'nullthrows';
|
||||
import * as React from 'react';
|
||||
|
||||
export default function setUpTests({isModern}: {isModern: boolean}) {
|
||||
// TODO: move these tests to the test file for `ReactNativeElement` when the legacy implementation is removed.
|
||||
describe(`ReactFabricPublicInstance (${isModern ? 'modern' : 'legacy'})`, () => {
|
||||
it('should provide instances of the right class as refs in host components', () => {
|
||||
let node;
|
||||
|
||||
const root = ReactNativeTester.createRoot();
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<View
|
||||
ref={receivedNode => {
|
||||
node = receivedNode;
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(node).toBeInstanceOf(
|
||||
isModern ? ReactNativeElement : ReactFabricHostComponent,
|
||||
);
|
||||
});
|
||||
|
||||
describe('blur', () => {
|
||||
test('blur() invokes TextInputState', () => {
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
let maybeNode;
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<View
|
||||
ref={node => {
|
||||
maybeNode = node;
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
const node = nullthrows(maybeNode);
|
||||
|
||||
const blurTextInput = jest.fn();
|
||||
|
||||
// We don't support view commands in Fantom yet, so we have to mock this.
|
||||
TextInputState.blurTextInput = blurTextInput;
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
node.blur();
|
||||
});
|
||||
|
||||
expect(blurTextInput).toHaveBeenCalledTimes(1);
|
||||
expect(blurTextInput.mock.calls).toEqual([[node]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('focus', () => {
|
||||
test('focus() invokes TextInputState', () => {
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
let maybeNode;
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<View
|
||||
ref={node => {
|
||||
maybeNode = node;
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
const node = nullthrows(maybeNode);
|
||||
|
||||
const focusTextInput = jest.fn();
|
||||
|
||||
// We don't support view commands in Fantom yet, so we have to mock this.
|
||||
TextInputState.focusTextInput = focusTextInput;
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
node.focus();
|
||||
});
|
||||
|
||||
expect(focusTextInput).toHaveBeenCalledTimes(1);
|
||||
expect(focusTextInput.mock.calls).toEqual([[node]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('measure', () => {
|
||||
it('component.measure(...) invokes callback', () => {
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
let maybeNode;
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<View
|
||||
style={{width: 100, height: 100, left: 10, top: 10}}
|
||||
ref={node => {
|
||||
maybeNode = node;
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
const node = nullthrows(maybeNode);
|
||||
|
||||
const callback = jest.fn();
|
||||
node.measure(callback);
|
||||
|
||||
expect(callback).toHaveBeenCalledTimes(1);
|
||||
expect(callback.mock.calls).toEqual([[10, 10, 100, 100, 10, 10]]);
|
||||
});
|
||||
|
||||
it('unmounted.measure(...) does nothing', () => {
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
let maybeNode;
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<View
|
||||
style={{width: 100, height: 100, left: 10, top: 10}}
|
||||
ref={node => {
|
||||
maybeNode = node;
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
const node = nullthrows(maybeNode);
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(<></>);
|
||||
});
|
||||
|
||||
const callback = jest.fn();
|
||||
node.measure(callback);
|
||||
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('measureInWindow', () => {
|
||||
it('component.measureInWindow(...) invokes callback', () => {
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
let maybeNode;
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<View
|
||||
style={{width: 100, height: 100, left: 10, top: 10}}
|
||||
ref={node => {
|
||||
maybeNode = node;
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
const node = nullthrows(maybeNode);
|
||||
|
||||
const callback = jest.fn();
|
||||
node.measureInWindow(callback);
|
||||
|
||||
expect(callback).toHaveBeenCalledTimes(1);
|
||||
expect(callback.mock.calls).toEqual([[10, 10, 100, 100]]);
|
||||
});
|
||||
|
||||
it('unmounted.measureInWindow(...) does nothing', () => {
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
let maybeNode;
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<View
|
||||
style={{width: 100, height: 100, left: 10, top: 10}}
|
||||
ref={node => {
|
||||
maybeNode = node;
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
const node = nullthrows(maybeNode);
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(<></>);
|
||||
});
|
||||
|
||||
const callback = jest.fn();
|
||||
node.measureInWindow(callback);
|
||||
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('measureLayout', () => {
|
||||
it('component.measureLayout(component, ...) invokes callback', () => {
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
let maybeParentNode;
|
||||
let maybeChildNode;
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<View
|
||||
style={{width: 100, height: 100, left: 10, top: 10}}
|
||||
ref={node => {
|
||||
maybeParentNode = node;
|
||||
}}>
|
||||
<View
|
||||
style={{width: 10, height: 10, left: 20, top: 20}}
|
||||
ref={node => {
|
||||
maybeChildNode = node;
|
||||
}}
|
||||
/>
|
||||
</View>,
|
||||
);
|
||||
});
|
||||
|
||||
const parentNode = nullthrows(maybeParentNode);
|
||||
const childNode = nullthrows(maybeChildNode);
|
||||
|
||||
const callback = jest.fn();
|
||||
childNode.measureLayout(parentNode, callback);
|
||||
|
||||
expect(callback).toHaveBeenCalledTimes(1);
|
||||
expect(callback.mock.calls).toEqual([[20, 20, 10, 10]]);
|
||||
});
|
||||
|
||||
it('unmounted.measureLayout(component, ...) does nothing', () => {
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
let maybeParentNode;
|
||||
let maybeChildNode;
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<View
|
||||
style={{width: 100, height: 100, left: 10, top: 10}}
|
||||
ref={node => {
|
||||
maybeParentNode = node;
|
||||
}}>
|
||||
<View
|
||||
style={{width: 10, height: 10, left: 20, top: 20}}
|
||||
ref={node => {
|
||||
maybeChildNode = node;
|
||||
}}
|
||||
/>
|
||||
</View>,
|
||||
);
|
||||
});
|
||||
|
||||
const parentNode = nullthrows(maybeParentNode);
|
||||
const childNode = nullthrows(maybeChildNode);
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<View style={{width: 100, height: 100, left: 10, top: 10}} />,
|
||||
);
|
||||
});
|
||||
|
||||
const callback = jest.fn();
|
||||
childNode.measureLayout(parentNode, callback);
|
||||
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('component.measureLayout(unmounted, ...) does nothing', () => {
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
let maybeParentNode;
|
||||
let maybeChildNode;
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<View
|
||||
style={{width: 100, height: 100, left: 10, top: 10}}
|
||||
ref={node => {
|
||||
maybeParentNode = node;
|
||||
}}>
|
||||
<View
|
||||
style={{width: 10, height: 10, left: 20, top: 20}}
|
||||
ref={node => {
|
||||
maybeChildNode = node;
|
||||
}}
|
||||
/>
|
||||
</View>,
|
||||
);
|
||||
});
|
||||
|
||||
const parentNode = nullthrows(maybeParentNode);
|
||||
const childNode = nullthrows(maybeChildNode);
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<View style={{width: 100, height: 100, left: 10, top: 10}} />,
|
||||
);
|
||||
});
|
||||
|
||||
const callback = jest.fn();
|
||||
parentNode.measureLayout(childNode, callback);
|
||||
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('unmounted.measureLayout(unmounted, ...) does nothing', () => {
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
let maybeParentNode;
|
||||
let maybeChildNode;
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<View
|
||||
style={{width: 100, height: 100, left: 10, top: 10}}
|
||||
ref={node => {
|
||||
maybeParentNode = node;
|
||||
}}>
|
||||
<View
|
||||
style={{width: 10, height: 10, left: 20, top: 20}}
|
||||
ref={node => {
|
||||
maybeChildNode = node;
|
||||
}}
|
||||
/>
|
||||
</View>,
|
||||
);
|
||||
});
|
||||
|
||||
const parentNode = nullthrows(maybeParentNode);
|
||||
const childNode = nullthrows(maybeChildNode);
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(<></>);
|
||||
});
|
||||
|
||||
const callback = jest.fn();
|
||||
childNode.measureLayout(parentNode, callback);
|
||||
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import useColorScheme from '../useColorScheme';
|
||||
|
||||
describe('useColorScheme', () => {
|
||||
it('should return a mocked light theme by default', () => {
|
||||
expect(jest.isMockFunction(useColorScheme)).toBe(true);
|
||||
expect(useColorScheme()).toBe('light');
|
||||
});
|
||||
|
||||
it('should have console.error when not using mock', () => {
|
||||
const useColorSchemeActual = jest.requireActual<{
|
||||
default: typeof useColorScheme,
|
||||
}>('../useColorScheme').default;
|
||||
const spy = jest.spyOn(console, 'error').mockImplementationOnce(() => {
|
||||
// Simulate LogBox console.error() call to throw an error and stop the further execution
|
||||
throw new Error('console.error() was called');
|
||||
});
|
||||
|
||||
expect(() => {
|
||||
useColorSchemeActual();
|
||||
}).toThrow();
|
||||
|
||||
expect(spy).toHaveBeenCalledWith(
|
||||
expect.stringMatching(
|
||||
/Invalid hook call. Hooks can only be called inside of the body of a function component./,
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -5609,12 +5609,7 @@ declare function create(
|
||||
declare const Presets: {
|
||||
easeInEaseOut: LayoutAnimationConfig,
|
||||
linear: LayoutAnimationConfig,
|
||||
spring: {
|
||||
duration: 700,
|
||||
create: { type: \\"linear\\", property: \\"opacity\\" },
|
||||
update: { type: \\"spring\\", springDamping: 0.4 },
|
||||
delete: { type: \\"linear\\", property: \\"opacity\\" },
|
||||
},
|
||||
spring: LayoutAnimationConfig,
|
||||
};
|
||||
declare const LayoutAnimation: {
|
||||
configureNext: configureNext,
|
||||
|
||||
@@ -468,8 +468,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init);
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
if (_bridge.valid) {
|
||||
id instance = self.instance;
|
||||
RCTAssert(_methodQueue != nullptr, @"Module %@ has no methodQueue (instance: %@)", self, instance);
|
||||
RCTAssert(_methodQueue != nullptr, @"Module %@ has no methodQueue (instance: %@)", self, self.instance);
|
||||
}
|
||||
return _methodQueue;
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
/**
|
||||
* UIView class for root <ModalHostView> component.
|
||||
*/
|
||||
@interface RCTModalHostViewComponentView : RCTViewComponentView
|
||||
@interface RCTModalHostViewComponentView : RCTViewComponentView <UIAdaptivePresentationControllerDelegate>
|
||||
|
||||
/**
|
||||
* Subclasses may override this method and present the modal on different view controller.
|
||||
|
||||
+12
@@ -149,6 +149,8 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
||||
{
|
||||
BOOL shouldBePresented = !_isPresented && _shouldPresent && self.window;
|
||||
if (shouldBePresented) {
|
||||
self.viewController.presentationController.delegate = self;
|
||||
|
||||
_isPresented = YES;
|
||||
[self presentViewController:self.viewController
|
||||
animated:_shouldAnimatePresentation
|
||||
@@ -274,6 +276,16 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
||||
[childComponentView removeFromSuperview];
|
||||
}
|
||||
|
||||
#pragma mark - UIAdaptivePresentationControllerDelegate
|
||||
|
||||
- (void)presentationControllerDidAttemptToDismiss:(UIPresentationController *)controller
|
||||
{
|
||||
auto eventEmitter = [self modalEventEmitter];
|
||||
if (eventEmitter) {
|
||||
eventEmitter->onRequestClose({});
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
+40
-11
@@ -67,28 +67,52 @@
|
||||
* ScrollView, we force it to be centered, but when you zoom or the content otherwise
|
||||
* becomes larger than the ScrollView, there is no padding around the content but it
|
||||
* can still fill the whole view.
|
||||
* This implementation is based on https://petersteinberger.com/blog/2013/how-to-center-uiscrollview/.
|
||||
*/
|
||||
- (void)centerContentIfNeeded
|
||||
{
|
||||
if (!_centerContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
CGSize contentSize = self.contentSize;
|
||||
CGSize boundsSize = self.bounds.size;
|
||||
if (CGSizeEqualToSize(contentSize, CGSizeZero) || CGSizeEqualToSize(boundsSize, CGSizeZero)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CGFloat top = 0, left = 0;
|
||||
if (contentSize.width < boundsSize.width) {
|
||||
left = (boundsSize.width - contentSize.width) * 0.5f;
|
||||
}
|
||||
if (contentSize.height < boundsSize.height) {
|
||||
top = (boundsSize.height - contentSize.height) * 0.5f;
|
||||
}
|
||||
self.contentInset = UIEdgeInsetsMake(top, left, top, left);
|
||||
}
|
||||
|
||||
- (void)setContentOffset:(CGPoint)contentOffset
|
||||
{
|
||||
if (_isSetContentOffsetDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_centerContent && !CGSizeEqualToSize(self.contentSize, CGSizeZero)) {
|
||||
CGSize scrollViewSize = self.bounds.size;
|
||||
if (self.contentSize.width <= scrollViewSize.width) {
|
||||
contentOffset.x = -(scrollViewSize.width - self.contentSize.width) / 2.0;
|
||||
}
|
||||
if (self.contentSize.height <= scrollViewSize.height) {
|
||||
contentOffset.y = -(scrollViewSize.height - self.contentSize.height) / 2.0;
|
||||
}
|
||||
}
|
||||
|
||||
super.contentOffset = CGPointMake(
|
||||
RCTSanitizeNaNValue(contentOffset.x, @"scrollView.contentOffset.x"),
|
||||
RCTSanitizeNaNValue(contentOffset.y, @"scrollView.contentOffset.y"));
|
||||
}
|
||||
|
||||
- (void)setFrame:(CGRect)frame
|
||||
{
|
||||
[super setFrame:frame];
|
||||
[self centerContentIfNeeded];
|
||||
}
|
||||
|
||||
- (void)didAddSubview:(UIView *)subview
|
||||
{
|
||||
[super didAddSubview:subview];
|
||||
[self centerContentIfNeeded];
|
||||
}
|
||||
|
||||
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
|
||||
{
|
||||
if ([_overridingDelegate respondsToSelector:@selector(touchesShouldCancelInContentView:)]) {
|
||||
@@ -258,6 +282,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)scrollViewDidZoom:(__unused UIScrollView *)scrollView
|
||||
{
|
||||
[self centerContentIfNeeded];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (BOOL)isHorizontal:(UIScrollView *)scrollView
|
||||
|
||||
@@ -121,8 +121,8 @@ using namespace facebook::react;
|
||||
auto &props = *sharedProps;
|
||||
props.layoutConstraints = LayoutConstraints{{0, 0}, {500, 500}};
|
||||
auto &yogaStyle = props.yogaStyle;
|
||||
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(200));
|
||||
return sharedProps;
|
||||
})
|
||||
.children({
|
||||
@@ -136,8 +136,8 @@ using namespace facebook::react;
|
||||
yogaStyle.setPositionType(yoga::PositionType::Absolute);
|
||||
yogaStyle.setPosition(yoga::Edge::Left, yoga::StyleLength::points(0));
|
||||
yogaStyle.setPosition(yoga::Edge::Top, yoga::StyleLength::points(0));
|
||||
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(200));
|
||||
return sharedProps;
|
||||
})
|
||||
.children({
|
||||
@@ -216,8 +216,8 @@ using namespace facebook::react;
|
||||
yogaStyle.setPositionType(yoga::PositionType::Absolute);
|
||||
yogaStyle.setPosition(yoga::Edge::Left, yoga::StyleLength::points(0));
|
||||
yogaStyle.setPosition(yoga::Edge::Top, yoga::StyleLength::points(30));
|
||||
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(50));
|
||||
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(50));
|
||||
return sharedProps;
|
||||
})
|
||||
.children({
|
||||
@@ -260,8 +260,8 @@ using namespace facebook::react;
|
||||
yogaStyle.setPositionType(yoga::PositionType::Absolute);
|
||||
yogaStyle.setPosition(yoga::Edge::Left, yoga::StyleLength::points(0));
|
||||
yogaStyle.setPosition(yoga::Edge::Top, yoga::StyleLength::points(90));
|
||||
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(50));
|
||||
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(50));
|
||||
return sharedProps;
|
||||
})
|
||||
.children({
|
||||
@@ -418,8 +418,8 @@ static ParagraphShadowNode::ConcreteState::Shared stateWithShadowNode(
|
||||
auto &props = *sharedProps;
|
||||
props.layoutConstraints = LayoutConstraints{{0, 0}, {500, 500}};
|
||||
auto &yogaStyle = props.yogaStyle;
|
||||
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(200));
|
||||
return sharedProps;
|
||||
})
|
||||
.children({
|
||||
@@ -434,8 +434,8 @@ static ParagraphShadowNode::ConcreteState::Shared stateWithShadowNode(
|
||||
yogaStyle.setPositionType(yoga::PositionType::Absolute);
|
||||
yogaStyle.setPosition(yoga::Edge::Left, yoga::StyleLength::points(0));
|
||||
yogaStyle.setPosition(yoga::Edge::Top, yoga::StyleLength::points(90));
|
||||
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(20));
|
||||
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(200));
|
||||
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(20));
|
||||
return sharedProps;
|
||||
})
|
||||
.children({
|
||||
|
||||
@@ -87,6 +87,9 @@ CGFloat RCTCoreGraphicsFloatFromYogaValue(YGValue value, CGFloat baseFloatValue)
|
||||
return RCTCoreGraphicsFloatFromYogaFloat(value.value) * baseFloatValue;
|
||||
case YGUnitAuto:
|
||||
case YGUnitUndefined:
|
||||
case YGUnitMaxContent:
|
||||
case YGUnitFitContent:
|
||||
case YGUnitStretch:
|
||||
return baseFloatValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,9 @@ typedef NS_ENUM(unsigned int, meta_prop_t) {
|
||||
#define RCT_SET_YGVALUE(ygvalue, setter, ...) \
|
||||
switch (ygvalue.unit) { \
|
||||
case YGUnitAuto: \
|
||||
case YGUnitMaxContent: \
|
||||
case YGUnitFitContent: \
|
||||
case YGUnitStretch: \
|
||||
case YGUnitUndefined: \
|
||||
setter(__VA_ARGS__, YGUndefined); \
|
||||
break; \
|
||||
@@ -88,6 +91,35 @@ typedef NS_ENUM(unsigned int, meta_prop_t) {
|
||||
case YGUnitPercent: \
|
||||
setter##Percent(__VA_ARGS__, ygvalue.value); \
|
||||
break; \
|
||||
case YGUnitMaxContent: \
|
||||
case YGUnitFitContent: \
|
||||
case YGUnitStretch: \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define RCT_SET_YGVALUE_AUTO_INTRINSIC(ygvalue, setter, ...) \
|
||||
switch (ygvalue.unit) { \
|
||||
case YGUnitAuto: \
|
||||
setter##Auto(__VA_ARGS__); \
|
||||
break; \
|
||||
case YGUnitMaxContent: \
|
||||
setter##MaxContent(__VA_ARGS__); \
|
||||
break; \
|
||||
case YGUnitFitContent: \
|
||||
setter##FitContent(__VA_ARGS__); \
|
||||
break; \
|
||||
case YGUnitStretch: \
|
||||
setter##Stretch(__VA_ARGS__); \
|
||||
break; \
|
||||
case YGUnitUndefined: \
|
||||
setter(__VA_ARGS__, YGUndefined); \
|
||||
break; \
|
||||
case YGUnitPoint: \
|
||||
setter(__VA_ARGS__, ygvalue.value); \
|
||||
break; \
|
||||
case YGUnitPercent: \
|
||||
setter##Percent(__VA_ARGS__, ygvalue.value); \
|
||||
break; \
|
||||
}
|
||||
|
||||
static void RCTProcessMetaPropsPadding(const YGValue metaProps[META_PROP_COUNT], YGNodeRef node)
|
||||
@@ -483,14 +515,14 @@ RCT_BORDER_PROPERTY(Start, START)
|
||||
RCT_BORDER_PROPERTY(End, END)
|
||||
|
||||
// Dimensions
|
||||
#define RCT_DIMENSION_PROPERTY(setProp, getProp, cssProp) \
|
||||
-(void)set##setProp : (YGValue)value \
|
||||
{ \
|
||||
RCT_SET_YGVALUE_AUTO(value, YGNodeStyleSet##cssProp, _yogaNode); \
|
||||
} \
|
||||
-(YGValue)getProp \
|
||||
{ \
|
||||
return YGNodeStyleGet##cssProp(_yogaNode); \
|
||||
#define RCT_DIMENSION_PROPERTY(setProp, getProp, cssProp) \
|
||||
-(void)set##setProp : (YGValue)value \
|
||||
{ \
|
||||
RCT_SET_YGVALUE_AUTO_INTRINSIC(value, YGNodeStyleSet##cssProp, _yogaNode); \
|
||||
} \
|
||||
-(YGValue)getProp \
|
||||
{ \
|
||||
return YGNodeStyleGet##cssProp(_yogaNode); \
|
||||
}
|
||||
|
||||
#define RCT_MIN_MAX_DIMENSION_PROPERTY(setProp, getProp, cssProp) \
|
||||
@@ -634,7 +666,7 @@ RCTShadowViewMeasure(YGNodeConstRef node, float width, YGMeasureMode widthMode,
|
||||
|
||||
- (void)setFlexBasis:(YGValue)value
|
||||
{
|
||||
RCT_SET_YGVALUE_AUTO(value, YGNodeStyleSetFlexBasis, _yogaNode);
|
||||
RCT_SET_YGVALUE_AUTO_INTRINSIC(value, YGNodeStyleSetFlexBasis, _yogaNode);
|
||||
}
|
||||
|
||||
- (YGValue)flexBasis
|
||||
|
||||
@@ -159,26 +159,8 @@
|
||||
return !shouldDisableScrollInteraction;
|
||||
}
|
||||
|
||||
/*
|
||||
* Automatically centers the content such that if the content is smaller than the
|
||||
* ScrollView, we force it to be centered, but when you zoom or the content otherwise
|
||||
* becomes larger than the ScrollView, there is no padding around the content but it
|
||||
* can still fill the whole view.
|
||||
*/
|
||||
- (void)setContentOffset:(CGPoint)contentOffset
|
||||
{
|
||||
UIView *contentView = [self contentView];
|
||||
if (contentView && _centerContent && !CGSizeEqualToSize(contentView.frame.size, CGSizeZero)) {
|
||||
CGSize subviewSize = contentView.frame.size;
|
||||
CGSize scrollViewSize = self.bounds.size;
|
||||
if (subviewSize.width <= scrollViewSize.width) {
|
||||
contentOffset.x = -(scrollViewSize.width - subviewSize.width) / 2.0;
|
||||
}
|
||||
if (subviewSize.height <= scrollViewSize.height) {
|
||||
contentOffset.y = -(scrollViewSize.height - subviewSize.height) / 2.0;
|
||||
}
|
||||
}
|
||||
|
||||
super.contentOffset = CGPointMake(
|
||||
RCTSanitizeNaNValue(contentOffset.x, @"scrollView.contentOffset.x"),
|
||||
RCTSanitizeNaNValue(contentOffset.y, @"scrollView.contentOffset.y"));
|
||||
@@ -433,6 +415,12 @@ static inline void RCTApplyTransformationAccordingLayoutDirection(
|
||||
// Does nothing
|
||||
}
|
||||
|
||||
- (void)setFrame:(CGRect)frame
|
||||
{
|
||||
[super setFrame:frame];
|
||||
[self centerContentIfNeeded];
|
||||
}
|
||||
|
||||
- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex
|
||||
{
|
||||
[super insertReactSubview:view atIndex:atIndex];
|
||||
@@ -450,6 +438,8 @@ static inline void RCTApplyTransformationAccordingLayoutDirection(
|
||||
RCTApplyTransformationAccordingLayoutDirection(_contentView, self.reactLayoutDirection);
|
||||
[_scrollView addSubview:view];
|
||||
}
|
||||
|
||||
[self centerContentIfNeeded];
|
||||
}
|
||||
|
||||
- (void)removeReactSubview:(UIView *)subview
|
||||
@@ -658,9 +648,45 @@ static inline void RCTApplyTransformationAccordingLayoutDirection(
|
||||
}
|
||||
|
||||
RCT_SCROLL_EVENT_HANDLER(scrollViewWillBeginDecelerating, onMomentumScrollBegin)
|
||||
RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, onScroll)
|
||||
RCT_SCROLL_EVENT_HANDLER(scrollViewDidScrollToTop, onScrollToTop)
|
||||
|
||||
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
|
||||
{
|
||||
[self centerContentIfNeeded];
|
||||
|
||||
RCT_SEND_SCROLL_EVENT(onScroll, nil);
|
||||
RCT_FORWARD_SCROLL_EVENT(scrollViewDidZoom : scrollView);
|
||||
}
|
||||
|
||||
/*
|
||||
* Automatically centers the content such that if the content is smaller than the
|
||||
* ScrollView, we force it to be centered, but when you zoom or the content otherwise
|
||||
* becomes larger than the ScrollView, there is no padding around the content but it
|
||||
* can still fill the whole view.
|
||||
* This implementation is based on https://petersteinberger.com/blog/2013/how-to-center-uiscrollview/.
|
||||
*/
|
||||
- (void)centerContentIfNeeded
|
||||
{
|
||||
if (!_scrollView.centerContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
CGSize contentSize = self.contentSize;
|
||||
CGSize boundsSize = self.bounds.size;
|
||||
if (CGSizeEqualToSize(contentSize, CGSizeZero) || CGSizeEqualToSize(boundsSize, CGSizeZero)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CGFloat top = 0, left = 0;
|
||||
if (contentSize.width < boundsSize.width) {
|
||||
left = (boundsSize.width - contentSize.width) * 0.5f;
|
||||
}
|
||||
if (contentSize.height < boundsSize.height) {
|
||||
top = (boundsSize.height - contentSize.height) * 0.5f;
|
||||
}
|
||||
_scrollView.contentInset = UIEdgeInsetsMake(top, left, top, left);
|
||||
}
|
||||
|
||||
- (void)addScrollListener:(NSObject<UIScrollViewDelegate> *)scrollListener
|
||||
{
|
||||
[_scrollListeners addObject:scrollListener];
|
||||
@@ -939,6 +965,7 @@ RCT_SCROLL_EVENT_HANDLER(scrollViewDidScrollToTop, onScrollToTop)
|
||||
CGSize contentSize = self.contentSize;
|
||||
if (!CGSizeEqualToSize(_scrollView.contentSize, contentSize)) {
|
||||
_scrollView.contentSize = contentSize;
|
||||
[self centerContentIfNeeded];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -426,6 +426,10 @@ public abstract interface class com/facebook/react/ReactRootView$ReactRootViewEv
|
||||
public abstract fun onAttachedToReactInstance (Lcom/facebook/react/ReactRootView;)V
|
||||
}
|
||||
|
||||
public abstract class com/facebook/react/TurboReactPackage : com/facebook/react/BaseReactPackage {
|
||||
public fun <init> ()V
|
||||
}
|
||||
|
||||
public abstract interface class com/facebook/react/ViewManagerOnDemandReactPackage {
|
||||
public abstract fun createViewManager (Lcom/facebook/react/bridge/ReactApplicationContext;Ljava/lang/String;)Lcom/facebook/react/uimanager/ViewManager;
|
||||
public abstract fun getViewManagerNames (Lcom/facebook/react/bridge/ReactApplicationContext;)Ljava/util/Collection;
|
||||
@@ -776,16 +780,6 @@ public abstract class com/facebook/react/bridge/GuardedAsyncTask : android/os/As
|
||||
protected abstract fun doInBackgroundGuarded ([Ljava/lang/Object;)V
|
||||
}
|
||||
|
||||
public abstract class com/facebook/react/bridge/GuardedResultAsyncTask : android/os/AsyncTask {
|
||||
protected fun <init> (Lcom/facebook/react/bridge/JSExceptionHandler;)V
|
||||
protected fun <init> (Lcom/facebook/react/bridge/ReactContext;)V
|
||||
protected synthetic fun doInBackground ([Ljava/lang/Object;)Ljava/lang/Object;
|
||||
protected final fun doInBackground ([Ljava/lang/Void;)Ljava/lang/Object;
|
||||
protected abstract fun doInBackgroundGuarded ()Ljava/lang/Object;
|
||||
protected final fun onPostExecute (Ljava/lang/Object;)V
|
||||
protected abstract fun onPostExecuteGuarded (Ljava/lang/Object;)V
|
||||
}
|
||||
|
||||
public abstract class com/facebook/react/bridge/GuardedRunnable : java/lang/Runnable {
|
||||
public fun <init> (Lcom/facebook/react/bridge/JSExceptionHandler;)V
|
||||
public fun <init> (Lcom/facebook/react/bridge/ReactContext;)V
|
||||
@@ -2036,9 +2030,9 @@ public final class com/facebook/react/defaults/DefaultReactHost {
|
||||
public static final field INSTANCE Lcom/facebook/react/defaults/DefaultReactHost;
|
||||
public static final fun getDefaultReactHost (Landroid/content/Context;Lcom/facebook/react/ReactNativeHost;)Lcom/facebook/react/ReactHost;
|
||||
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;)Lcom/facebook/react/ReactHost;
|
||||
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;Lkotlin/jvm/functions/Function1;)Lcom/facebook/react/ReactHost;
|
||||
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;Lkotlin/jvm/functions/Function1;Lcom/facebook/react/runtime/BindingsInstaller;)Lcom/facebook/react/ReactHost;
|
||||
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
|
||||
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
|
||||
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;Lkotlin/jvm/functions/Function1;Lcom/facebook/react/runtime/BindingsInstaller;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
|
||||
}
|
||||
|
||||
public abstract class com/facebook/react/defaults/DefaultReactNativeHost : com/facebook/react/ReactNativeHost {
|
||||
@@ -2219,6 +2213,7 @@ public abstract interface class com/facebook/react/devsupport/HMRClient : com/fa
|
||||
public final class com/facebook/react/devsupport/InspectorFlags {
|
||||
public static final field INSTANCE Lcom/facebook/react/devsupport/InspectorFlags;
|
||||
public static final fun getFuseboxEnabled ()Z
|
||||
public static final fun getIsProfilingBuild ()Z
|
||||
}
|
||||
|
||||
public class com/facebook/react/devsupport/InspectorPackagerConnection : com/facebook/react/devsupport/IInspectorPackagerConnection {
|
||||
@@ -2760,6 +2755,7 @@ public class com/facebook/react/fabric/mounting/MountingManager {
|
||||
public fun attachRootView (ILandroid/view/View;Lcom/facebook/react/uimanager/ThemedReactContext;)V
|
||||
public fun clearJSResponder ()V
|
||||
public fun enqueuePendingEvent (IILjava/lang/String;ZLcom/facebook/react/bridge/WritableMap;I)V
|
||||
public fun experimental_prefetchResource (Lcom/facebook/react/bridge/ReactContext;Ljava/lang/String;IILcom/facebook/react/common/mapbuffer/MapBuffer;)V
|
||||
public fun getEventEmitter (II)Lcom/facebook/react/fabric/events/EventEmitterWrapper;
|
||||
public fun getSurfaceManager (I)Lcom/facebook/react/fabric/mounting/SurfaceMountingManager;
|
||||
public fun getSurfaceManagerEnforced (ILjava/lang/String;)Lcom/facebook/react/fabric/mounting/SurfaceMountingManager;
|
||||
@@ -4089,10 +4085,6 @@ public abstract class com/facebook/react/uimanager/BaseViewManagerDelegate : com
|
||||
public fun setProperty (Landroid/view/View;Ljava/lang/String;Ljava/lang/Object;)V
|
||||
}
|
||||
|
||||
public abstract interface class com/facebook/react/uimanager/ComponentNameResolver {
|
||||
public abstract fun getComponentNames ()[Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class com/facebook/react/uimanager/DisplayMetricsHolder {
|
||||
public static final field INSTANCE Lcom/facebook/react/uimanager/DisplayMetricsHolder;
|
||||
public static final fun getDisplayMetricsWritableMap (D)Lcom/facebook/react/bridge/WritableMap;
|
||||
@@ -4104,22 +4096,6 @@ public final class com/facebook/react/uimanager/DisplayMetricsHolder {
|
||||
public static final fun setWindowDisplayMetrics (Landroid/util/DisplayMetrics;)V
|
||||
}
|
||||
|
||||
public class com/facebook/react/uimanager/FabricViewStateManager {
|
||||
public fun <init> ()V
|
||||
public fun getStateData ()Lcom/facebook/react/bridge/ReadableMap;
|
||||
public fun hasStateWrapper ()Z
|
||||
public fun setState (Lcom/facebook/react/uimanager/FabricViewStateManager$StateUpdateCallback;)V
|
||||
public fun setStateWrapper (Lcom/facebook/react/uimanager/StateWrapper;)V
|
||||
}
|
||||
|
||||
public abstract interface class com/facebook/react/uimanager/FabricViewStateManager$HasFabricViewStateManager {
|
||||
public abstract fun getFabricViewStateManager ()Lcom/facebook/react/uimanager/FabricViewStateManager;
|
||||
}
|
||||
|
||||
public abstract interface class com/facebook/react/uimanager/FabricViewStateManager$StateUpdateCallback {
|
||||
public abstract fun getStateUpdate ()Lcom/facebook/react/bridge/WritableMap;
|
||||
}
|
||||
|
||||
public final class com/facebook/react/uimanager/FloatUtil {
|
||||
public static final field INSTANCE Lcom/facebook/react/uimanager/FloatUtil;
|
||||
public static final fun floatsEqual (FF)Z
|
||||
@@ -5281,6 +5257,8 @@ public abstract class com/facebook/react/uimanager/ViewManager : com/facebook/re
|
||||
public fun createView (ILcom/facebook/react/uimanager/ThemedReactContext;Lcom/facebook/react/uimanager/ReactStylesDiffMap;Lcom/facebook/react/uimanager/StateWrapper;Lcom/facebook/react/touch/JSResponderHandler;)Landroid/view/View;
|
||||
protected fun createViewInstance (ILcom/facebook/react/uimanager/ThemedReactContext;Lcom/facebook/react/uimanager/ReactStylesDiffMap;Lcom/facebook/react/uimanager/StateWrapper;)Landroid/view/View;
|
||||
protected abstract fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Landroid/view/View;
|
||||
protected fun experimental_isPrefetchingEnabled ()Z
|
||||
public fun experimental_prefetchResource (Lcom/facebook/react/bridge/ReactContext;IILcom/facebook/react/common/mapbuffer/MapBuffer;)V
|
||||
public fun getCommandsMap ()Ljava/util/Map;
|
||||
protected fun getDelegate ()Lcom/facebook/react/uimanager/ViewManagerDelegate;
|
||||
public fun getExportedCustomBubblingEventTypeConstants ()Ljava/util/Map;
|
||||
@@ -7133,45 +7111,6 @@ public final class com/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout
|
||||
public fun setRefreshing (Z)V
|
||||
}
|
||||
|
||||
public class com/facebook/react/views/switchview/ReactSwitchManager : com/facebook/react/uimanager/SimpleViewManager, com/facebook/react/viewmanagers/AndroidSwitchManagerInterface {
|
||||
public static final field REACT_CLASS Ljava/lang/String;
|
||||
public fun <init> ()V
|
||||
protected synthetic fun addEventEmitters (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)V
|
||||
protected fun addEventEmitters (Lcom/facebook/react/uimanager/ThemedReactContext;Lcom/facebook/react/views/switchview/ReactSwitch;)V
|
||||
public fun createShadowNodeInstance ()Lcom/facebook/react/uimanager/LayoutShadowNode;
|
||||
public synthetic fun createShadowNodeInstance ()Lcom/facebook/react/uimanager/ReactShadowNode;
|
||||
protected synthetic fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Landroid/view/View;
|
||||
protected fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Lcom/facebook/react/views/switchview/ReactSwitch;
|
||||
protected fun getDelegate ()Lcom/facebook/react/uimanager/ViewManagerDelegate;
|
||||
public fun getName ()Ljava/lang/String;
|
||||
public fun getShadowNodeClass ()Ljava/lang/Class;
|
||||
public fun measure (Landroid/content/Context;Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/ReadableMap;FLcom/facebook/yoga/YogaMeasureMode;FLcom/facebook/yoga/YogaMeasureMode;[F)J
|
||||
public synthetic fun receiveCommand (Landroid/view/View;Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V
|
||||
public fun receiveCommand (Lcom/facebook/react/views/switchview/ReactSwitch;Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V
|
||||
public synthetic fun setBackgroundColor (Landroid/view/View;I)V
|
||||
public fun setBackgroundColor (Lcom/facebook/react/views/switchview/ReactSwitch;I)V
|
||||
public synthetic fun setDisabled (Landroid/view/View;Z)V
|
||||
public fun setDisabled (Lcom/facebook/react/views/switchview/ReactSwitch;Z)V
|
||||
public synthetic fun setEnabled (Landroid/view/View;Z)V
|
||||
public fun setEnabled (Lcom/facebook/react/views/switchview/ReactSwitch;Z)V
|
||||
public synthetic fun setNativeValue (Landroid/view/View;Z)V
|
||||
public fun setNativeValue (Lcom/facebook/react/views/switchview/ReactSwitch;Z)V
|
||||
public synthetic fun setOn (Landroid/view/View;Z)V
|
||||
public fun setOn (Lcom/facebook/react/views/switchview/ReactSwitch;Z)V
|
||||
public synthetic fun setThumbColor (Landroid/view/View;Ljava/lang/Integer;)V
|
||||
public fun setThumbColor (Lcom/facebook/react/views/switchview/ReactSwitch;Ljava/lang/Integer;)V
|
||||
public synthetic fun setThumbTintColor (Landroid/view/View;Ljava/lang/Integer;)V
|
||||
public fun setThumbTintColor (Lcom/facebook/react/views/switchview/ReactSwitch;Ljava/lang/Integer;)V
|
||||
public synthetic fun setTrackColorForFalse (Landroid/view/View;Ljava/lang/Integer;)V
|
||||
public fun setTrackColorForFalse (Lcom/facebook/react/views/switchview/ReactSwitch;Ljava/lang/Integer;)V
|
||||
public synthetic fun setTrackColorForTrue (Landroid/view/View;Ljava/lang/Integer;)V
|
||||
public fun setTrackColorForTrue (Lcom/facebook/react/views/switchview/ReactSwitch;Ljava/lang/Integer;)V
|
||||
public synthetic fun setTrackTintColor (Landroid/view/View;Ljava/lang/Integer;)V
|
||||
public fun setTrackTintColor (Lcom/facebook/react/views/switchview/ReactSwitch;Ljava/lang/Integer;)V
|
||||
public synthetic fun setValue (Landroid/view/View;Z)V
|
||||
public fun setValue (Lcom/facebook/react/views/switchview/ReactSwitch;Z)V
|
||||
}
|
||||
|
||||
public final class com/facebook/react/views/text/DefaultStyleValuesUtil {
|
||||
public static final field INSTANCE Lcom/facebook/react/views/text/DefaultStyleValuesUtil;
|
||||
public static final fun getDefaultTextColor (Landroid/content/Context;)Landroid/content/res/ColorStateList;
|
||||
|
||||
@@ -591,7 +591,8 @@ android {
|
||||
"src/main/res/shell",
|
||||
"src/main/res/views/alert",
|
||||
"src/main/res/views/modal",
|
||||
"src/main/res/views/uimanager"))
|
||||
"src/main/res/views/uimanager",
|
||||
"src/main/res/views/view"))
|
||||
java.exclude("com/facebook/react/processing")
|
||||
java.exclude("com/facebook/react/module/processing")
|
||||
}
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react
|
||||
|
||||
@Deprecated(
|
||||
message = "Use BaseReactPackage instead",
|
||||
replaceWith = ReplaceWith(expression = "BaseReactPackage"))
|
||||
public abstract class TurboReactPackage : BaseReactPackage() {}
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.bridge;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
/**
|
||||
* Abstract base for a AsyncTask with result support that should have any RuntimeExceptions it
|
||||
* throws handled by the {@link JSExceptionHandler} registered if the app is in dev mode.
|
||||
*/
|
||||
public abstract class GuardedResultAsyncTask<Result> extends AsyncTask<Void, Void, Result> {
|
||||
|
||||
private final JSExceptionHandler mExceptionHandler;
|
||||
|
||||
protected GuardedResultAsyncTask(ReactContext reactContext) {
|
||||
this(reactContext.getExceptionHandler());
|
||||
}
|
||||
|
||||
protected GuardedResultAsyncTask(JSExceptionHandler exceptionHandler) {
|
||||
mExceptionHandler = exceptionHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Result doInBackground(Void... params) {
|
||||
try {
|
||||
return doInBackgroundGuarded();
|
||||
} catch (RuntimeException e) {
|
||||
mExceptionHandler.handleException(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void onPostExecute(Result result) {
|
||||
try {
|
||||
onPostExecuteGuarded(result);
|
||||
} catch (RuntimeException e) {
|
||||
mExceptionHandler.handleException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Result doInBackgroundGuarded();
|
||||
|
||||
protected abstract void onPostExecuteGuarded(Result result);
|
||||
}
|
||||
+11
-5
@@ -16,6 +16,7 @@ import com.facebook.react.bridge.ReactContext
|
||||
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
||||
import com.facebook.react.common.build.ReactBuildConfig
|
||||
import com.facebook.react.fabric.ComponentFactory
|
||||
import com.facebook.react.runtime.BindingsInstaller
|
||||
import com.facebook.react.runtime.JSCInstance
|
||||
import com.facebook.react.runtime.ReactHostImpl
|
||||
import com.facebook.react.runtime.cxxreactpackage.CxxReactPackage
|
||||
@@ -42,11 +43,12 @@ public object DefaultReactHost {
|
||||
* `index.<platform>`
|
||||
* @param jsBundleAssetPath the path to the JS bundle relative to the assets directory. Will be
|
||||
* composed in a `asset://...` URL
|
||||
* @param jsBundleFilePath the path to the JS bundle on the filesystem. Will be composed in a
|
||||
* `file://...` URL
|
||||
* @param isHermesEnabled whether to use Hermes as the JS engine, default to true.
|
||||
* @param useDevSupport whether to enable dev support, default to ReactBuildConfig.DEBUG.
|
||||
* @param cxxReactPackageProviders a list of cxxreactpackage providers (to register c++ turbo
|
||||
* modules)
|
||||
* @param jsBundleLoader a [JSBundleLoader] to use for creating the [ReactHost]
|
||||
*
|
||||
* TODO(T186951312): Should this be @UnstableReactNativeAPI?
|
||||
*/
|
||||
@@ -70,9 +72,9 @@ public object DefaultReactHost {
|
||||
jsBundleFilePath,
|
||||
isHermesEnabled,
|
||||
useDevSupport,
|
||||
cxxReactPackageProviders) {
|
||||
throw it
|
||||
}
|
||||
cxxReactPackageProviders,
|
||||
{ throw it },
|
||||
null)
|
||||
|
||||
/**
|
||||
* Util function to create a default [ReactHost] to be used in your application. This method is
|
||||
@@ -84,13 +86,15 @@ public object DefaultReactHost {
|
||||
* `index.<platform>`
|
||||
* @param jsBundleAssetPath the path to the JS bundle relative to the assets directory. Will be
|
||||
* composed in a `asset://...` URL
|
||||
* @param jsBundleFilePath the path to the JS bundle on the filesystem. Will be composed in a
|
||||
* `file://...` URL
|
||||
* @param isHermesEnabled whether to use Hermes as the JS engine, default to true.
|
||||
* @param useDevSupport whether to enable dev support, default to ReactBuildConfig.DEBUG.
|
||||
* @param cxxReactPackageProviders a list of cxxreactpackage providers (to register c++ turbo
|
||||
* modules)
|
||||
* @param jsBundleLoader a [JSBundleLoader] to use for creating the [ReactHost]
|
||||
* @param exceptionHandler Callback that can be used by React Native host applications to react to
|
||||
* exceptions thrown by the internals of React Native.
|
||||
* @param bindingsInstaller that can be used for installing bindings.
|
||||
*
|
||||
* TODO(T186951312): Should this be @UnstableReactNativeAPI?
|
||||
*/
|
||||
@@ -106,6 +110,7 @@ public object DefaultReactHost {
|
||||
useDevSupport: Boolean = ReactBuildConfig.DEBUG,
|
||||
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage> = emptyList(),
|
||||
exceptionHandler: (Exception) -> Unit = { throw it },
|
||||
bindingsInstaller: BindingsInstaller? = null,
|
||||
): ReactHost {
|
||||
if (reactHost == null) {
|
||||
|
||||
@@ -128,6 +133,7 @@ public object DefaultReactHost {
|
||||
jsBundleLoader = bundleLoader,
|
||||
reactPackages = packageList,
|
||||
jsRuntimeFactory = jsRuntimeFactory,
|
||||
bindingsInstaller = bindingsInstaller,
|
||||
turboModuleManagerDelegateBuilder = defaultTmmDelegateBuilder,
|
||||
exceptionHandler = exceptionHandler)
|
||||
val componentFactory = ComponentFactory()
|
||||
|
||||
+6
-1
@@ -9,6 +9,7 @@ package com.facebook.react.devsupport
|
||||
|
||||
import android.content.Context
|
||||
import com.facebook.react.common.SurfaceDelegateFactory
|
||||
import com.facebook.react.common.build.ReactBuildConfig
|
||||
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener
|
||||
import com.facebook.react.devsupport.interfaces.DevLoadingViewManager
|
||||
import com.facebook.react.devsupport.interfaces.DevSupportManager
|
||||
@@ -101,7 +102,11 @@ public class DefaultDevSupportManagerFactory : DevSupportManagerFactory {
|
||||
useDevSupport: Boolean
|
||||
): DevSupportManager =
|
||||
if (!useDevSupport) {
|
||||
ReleaseDevSupportManager()
|
||||
if (ReactBuildConfig.UNSTABLE_ENABLE_FUSEBOX_RELEASE) {
|
||||
PerftestDevSupportManager(applicationContext)
|
||||
} else {
|
||||
ReleaseDevSupportManager()
|
||||
}
|
||||
} else {
|
||||
BridgelessDevSupportManager(
|
||||
applicationContext,
|
||||
|
||||
+3
-2
@@ -325,11 +325,12 @@ public class DevServerHelper {
|
||||
private String getInspectorDeviceUrl() {
|
||||
return String.format(
|
||||
Locale.US,
|
||||
"http://%s/inspector/device?name=%s&app=%s&device=%s",
|
||||
"http://%s/inspector/device?name=%s&app=%s&device=%s&profiling=%b",
|
||||
mPackagerConnectionSettings.getDebugServerHost(),
|
||||
Uri.encode(AndroidInfoHelpers.getFriendlyDeviceName()),
|
||||
Uri.encode(mPackageName),
|
||||
Uri.encode(getInspectorDeviceId()));
|
||||
Uri.encode(getInspectorDeviceId()),
|
||||
InspectorFlags.getIsProfilingBuild());
|
||||
}
|
||||
|
||||
public void downloadBundleFromURL(
|
||||
|
||||
+2
@@ -17,4 +17,6 @@ public object InspectorFlags {
|
||||
}
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun getFuseboxEnabled(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun getIsProfilingBuild(): Boolean
|
||||
}
|
||||
|
||||
+8
-2
@@ -445,12 +445,18 @@ public class FabricUIManager
|
||||
|
||||
@Override
|
||||
public void markActiveTouchForTag(int surfaceId, int reactTag) {
|
||||
mMountingManager.getSurfaceManager(surfaceId).markActiveTouchForTag(reactTag);
|
||||
SurfaceMountingManager surfaceMountingManager = mMountingManager.getSurfaceManager(surfaceId);
|
||||
if (surfaceMountingManager != null) {
|
||||
surfaceMountingManager.markActiveTouchForTag(reactTag);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sweepActiveTouchForTag(int surfaceId, int reactTag) {
|
||||
mMountingManager.getSurfaceManager(surfaceId).sweepActiveTouchForTag(reactTag);
|
||||
SurfaceMountingManager surfaceMountingManager = mMountingManager.getSurfaceManager(surfaceId);
|
||||
if (surfaceMountingManager != null) {
|
||||
surfaceMountingManager.sweepActiveTouchForTag(reactTag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+22
@@ -427,6 +427,28 @@ public class MountingManager {
|
||||
attachmentsPositions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated THIS PREFETCH METHOD IS EXPERIMENTAL, DO NOT USE IT FOR PRODUCTION CODE. IT WILL
|
||||
* MOST LIKELY CHANGE OR BE REMOVED IN THE FUTURE.
|
||||
* @param reactContext
|
||||
* @param componentName
|
||||
* @param surfaceId {@link int} surface ID
|
||||
* @param reactTag reactTag that should be set as ID of the view instance
|
||||
* @param params {@link MapBuffer} prefetch request params defined in C++
|
||||
*/
|
||||
@AnyThread
|
||||
@Deprecated
|
||||
public void experimental_prefetchResource(
|
||||
ReactContext reactContext,
|
||||
String componentName,
|
||||
int surfaceId,
|
||||
int reactTag,
|
||||
MapBuffer params) {
|
||||
mViewManagerRegistry
|
||||
.get(componentName)
|
||||
.experimental_prefetchResource(reactContext, surfaceId, reactTag, params);
|
||||
}
|
||||
|
||||
public void enqueuePendingEvent(
|
||||
int surfaceId,
|
||||
int reactTag,
|
||||
|
||||
+7
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<b1ad8179cf22c2e97f623435bf152aab>>
|
||||
* @generated SignedSource<<6d8d8f4b81d7be882b315d0960499dcb>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -130,6 +130,12 @@ public object ReactNativeFeatureFlags {
|
||||
@JvmStatic
|
||||
public fun enableIOSViewClipToPaddingBox(): Boolean = accessor.enableIOSViewClipToPaddingBox()
|
||||
|
||||
/**
|
||||
* When enabled, Andoid will build and initiate image prefetch requests on ImageShadowNode::layout
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun enableImagePrefetchingAndroid(): Boolean = accessor.enableImagePrefetchingAndroid()
|
||||
|
||||
/**
|
||||
* When enabled, LayoutAnimations API will animate state changes on Android.
|
||||
*/
|
||||
|
||||
+11
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<7dd21b62dfe429aecdbd179cb482fb26>>
|
||||
* @generated SignedSource<<031fce8e8b4c20a3e3d6dbecf94d138a>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -37,6 +37,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
|
||||
private var enableFixForViewCommandRaceCache: Boolean? = null
|
||||
private var enableGranularShadowTreeStateReconciliationCache: Boolean? = null
|
||||
private var enableIOSViewClipToPaddingBoxCache: Boolean? = null
|
||||
private var enableImagePrefetchingAndroidCache: Boolean? = null
|
||||
private var enableLayoutAnimationsOnAndroidCache: Boolean? = null
|
||||
private var enableLayoutAnimationsOnIOSCache: Boolean? = null
|
||||
private var enableLongTaskAPICache: Boolean? = null
|
||||
@@ -219,6 +220,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableImagePrefetchingAndroid(): Boolean {
|
||||
var cached = enableImagePrefetchingAndroidCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.enableImagePrefetchingAndroid()
|
||||
enableImagePrefetchingAndroidCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableLayoutAnimationsOnAndroid(): Boolean {
|
||||
var cached = enableLayoutAnimationsOnAndroidCache
|
||||
if (cached == null) {
|
||||
|
||||
+3
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<fcfded14a5fe05501892993c1f58f3ed>>
|
||||
* @generated SignedSource<<35811667ac2543e1f64e27bbdb483ec1>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -62,6 +62,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableIOSViewClipToPaddingBox(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableImagePrefetchingAndroid(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableLayoutAnimationsOnAndroid(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableLayoutAnimationsOnIOS(): Boolean
|
||||
|
||||
+3
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<86d8dd894e80a788af7f47172d30d33c>>
|
||||
* @generated SignedSource<<9d829c58e49164a0b2b6b66bc0ce088a>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -57,6 +57,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
|
||||
|
||||
override fun enableIOSViewClipToPaddingBox(): Boolean = false
|
||||
|
||||
override fun enableImagePrefetchingAndroid(): Boolean = false
|
||||
|
||||
override fun enableLayoutAnimationsOnAndroid(): Boolean = false
|
||||
|
||||
override fun enableLayoutAnimationsOnIOS(): Boolean = true
|
||||
|
||||
+12
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<4bb5173b9ba1d3e620f3a7d613b27ac7>>
|
||||
* @generated SignedSource<<0121e113410a5b0e14eaf74a3076df2f>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -41,6 +41,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
|
||||
private var enableFixForViewCommandRaceCache: Boolean? = null
|
||||
private var enableGranularShadowTreeStateReconciliationCache: Boolean? = null
|
||||
private var enableIOSViewClipToPaddingBoxCache: Boolean? = null
|
||||
private var enableImagePrefetchingAndroidCache: Boolean? = null
|
||||
private var enableLayoutAnimationsOnAndroidCache: Boolean? = null
|
||||
private var enableLayoutAnimationsOnIOSCache: Boolean? = null
|
||||
private var enableLongTaskAPICache: Boolean? = null
|
||||
@@ -240,6 +241,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableImagePrefetchingAndroid(): Boolean {
|
||||
var cached = enableImagePrefetchingAndroidCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.enableImagePrefetchingAndroid()
|
||||
accessedFeatureFlags.add("enableImagePrefetchingAndroid")
|
||||
enableImagePrefetchingAndroidCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableLayoutAnimationsOnAndroid(): Boolean {
|
||||
var cached = enableLayoutAnimationsOnAndroidCache
|
||||
if (cached == null) {
|
||||
|
||||
+3
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<2217f2b9992c9424c3d1d221bdfa2236>>
|
||||
* @generated SignedSource<<2787d9027695dd14ec6b917a32a1a6de>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -57,6 +57,8 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun enableIOSViewClipToPaddingBox(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableImagePrefetchingAndroid(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableLayoutAnimationsOnAndroid(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableLayoutAnimationsOnIOS(): Boolean
|
||||
|
||||
+8
-5
@@ -13,6 +13,7 @@ import androidx.appcompat.app.AppCompatDelegate
|
||||
import com.facebook.fbreact.specs.NativeAppearanceSpec
|
||||
import com.facebook.react.bridge.Arguments
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.bridge.UiThreadUtil
|
||||
import com.facebook.react.module.annotations.ReactModule
|
||||
|
||||
/** Module that exposes the user's preferred color scheme. */
|
||||
@@ -58,11 +59,13 @@ constructor(
|
||||
}
|
||||
|
||||
public override fun setColorScheme(style: String) {
|
||||
when (style) {
|
||||
"dark" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
|
||||
"light" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
||||
"unspecified" ->
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||
UiThreadUtil.runOnUiThread {
|
||||
when (style) {
|
||||
"dark" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
|
||||
"light" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
||||
"unspecified" ->
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -60,9 +60,9 @@ internal class ReactOkHttpNetworkFetcher(private val okHttpClient: OkHttpClient)
|
||||
val headers = OkHttpCompat.getHeadersFromMap(requestHeaders)
|
||||
val request =
|
||||
Request.Builder()
|
||||
.headers(headers)
|
||||
.cacheControl(cacheControlBuilder.build())
|
||||
.url(uri.toString())
|
||||
.headers(headers)
|
||||
.get()
|
||||
.build()
|
||||
fetchWithRequest(fetchState, callback, request)
|
||||
|
||||
+1
-1
@@ -194,7 +194,7 @@ public class ReactHostImpl implements ReactHost {
|
||||
mUIExecutor = uiExecutor;
|
||||
mMemoryPressureRouter = new MemoryPressureRouter(context);
|
||||
mAllowPackagerServerAccess = allowPackagerServerAccess;
|
||||
mUseDevSupport = useDevSupport || ReactBuildConfig.UNSTABLE_ENABLE_FUSEBOX_RELEASE;
|
||||
mUseDevSupport = useDevSupport;
|
||||
if (devSupportManagerFactory == null) {
|
||||
devSupportManagerFactory = new DefaultDevSupportManagerFactory();
|
||||
}
|
||||
|
||||
+1
-3
@@ -130,9 +130,7 @@ final class ReactInstance {
|
||||
mQueueConfiguration.getNativeModulesQueueThread();
|
||||
|
||||
ReactChoreographer.initialize(AndroidChoreographerProvider.getInstance());
|
||||
if (useDevSupport) {
|
||||
devSupportManager.startInspector();
|
||||
}
|
||||
devSupportManager.startInspector();
|
||||
|
||||
JSTimerExecutor jsTimerExecutor = createJSTimerExecutor();
|
||||
mJavaTimerManager =
|
||||
|
||||
+4
@@ -298,6 +298,10 @@ public object BackgroundStyleApplicator {
|
||||
val borderInsets = compositeBackgroundDrawable.borderInsets
|
||||
val borderRadius = compositeBackgroundDrawable.borderRadius
|
||||
|
||||
/**
|
||||
* z-ordering of user-provided shadow-list is opposite direction of LayerDrawable z-ordering
|
||||
* https://drafts.csswg.org/css-backgrounds/#shadow-layers
|
||||
*/
|
||||
for (boxShadow in shadows.asReversed()) {
|
||||
val offsetX = boxShadow.offsetX
|
||||
val offsetY = boxShadow.offsetY
|
||||
|
||||
+1
@@ -84,6 +84,7 @@ public abstract class BaseViewManager<T extends View, C extends LayoutShadowNode
|
||||
view.setTag(R.id.accessibility_actions, null);
|
||||
view.setTag(R.id.accessibility_value, null);
|
||||
view.setTag(R.id.accessibility_state_expanded, null);
|
||||
view.setTag(R.id.view_clipped, null);
|
||||
|
||||
// This indirectly calls (and resets):
|
||||
// setTranslationX
|
||||
|
||||
+4
-5
@@ -5,13 +5,12 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.uimanager;
|
||||
package com.facebook.react.uimanager
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStripAny;
|
||||
import com.facebook.proguard.annotations.DoNotStripAny
|
||||
|
||||
@DoNotStripAny
|
||||
public interface ComponentNameResolver {
|
||||
|
||||
internal interface ComponentNameResolver {
|
||||
/* returns a list of all the component names that are registered in React Native. */
|
||||
String[] getComponentNames();
|
||||
public val componentNames: Array<String>?
|
||||
}
|
||||
-98
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.uimanager;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.infer.annotation.Nullsafe;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
|
||||
/**
|
||||
* This is a helper base class for ViewGroups that use Fabric State.
|
||||
*
|
||||
* <p>Reason to use this: UpdateState calls from the View layer to the Fabric core can fail, and
|
||||
* optionally Fabric will call a "failure callback" if that happens. This class abstracts that and
|
||||
* makes it easier ensure that State in Fabric is always up-to-date.
|
||||
*
|
||||
* <p>1. Whenever ViewManager.updateState is called, call View.setStateWrapper. 2. Instead of
|
||||
* calling StateWrapper.updateState directly, call View.setState and it will automatically keep
|
||||
* retrying the UpdateState call until it succeeds; or you call setState again; or the View layer is
|
||||
* updated with a newer StateWrapper.
|
||||
*/
|
||||
@Nullsafe(Nullsafe.Mode.LOCAL)
|
||||
@Deprecated(
|
||||
since =
|
||||
"Deprecated class since v0.73.0, please use com.facebook.react.uimanager.StateWrapper"
|
||||
+ " instead.",
|
||||
forRemoval = true)
|
||||
public class FabricViewStateManager {
|
||||
private static final String TAG = "FabricViewStateManager";
|
||||
|
||||
@Deprecated
|
||||
public interface HasFabricViewStateManager {
|
||||
FabricViewStateManager getFabricViewStateManager();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public interface StateUpdateCallback {
|
||||
WritableMap getStateUpdate();
|
||||
}
|
||||
|
||||
@Nullable private StateWrapper mStateWrapper = null;
|
||||
|
||||
@Deprecated
|
||||
public void setStateWrapper(StateWrapper stateWrapper) {
|
||||
mStateWrapper = stateWrapper;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean hasStateWrapper() {
|
||||
return mStateWrapper != null;
|
||||
}
|
||||
|
||||
private void setState(
|
||||
@Nullable final StateWrapper stateWrapper,
|
||||
final StateUpdateCallback stateUpdateCallback,
|
||||
final int numTries) {
|
||||
// The StateWrapper will change, breaking the async loop, whenever the UpdateState MountItem
|
||||
// is executed.
|
||||
// The caller is responsible for detecting if data is up-to-date, and doing nothing, or
|
||||
// detecting if state is stale and calling setState again.
|
||||
if (stateWrapper == null) {
|
||||
FLog.e(TAG, "setState called without a StateWrapper");
|
||||
return;
|
||||
}
|
||||
if (stateWrapper != mStateWrapper) {
|
||||
return;
|
||||
}
|
||||
// We bail out after an arbitrary number of tries. In practice this should never go higher
|
||||
// than 2 or 3, but there's nothing guaranteeing that.
|
||||
if (numTries > 60) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Nullable WritableMap stateUpdate = stateUpdateCallback.getStateUpdate();
|
||||
if (stateUpdate == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: State update cannot fail; remove `failureRunnable` and custom retrying logic.
|
||||
stateWrapper.updateState(stateUpdate);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setState(final StateUpdateCallback stateUpdateCallback) {
|
||||
setState(mStateWrapper, stateUpdateCallback, 0);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public @Nullable ReadableMap getStateData() {
|
||||
return mStateWrapper != null ? mStateWrapper.getStateData() : null;
|
||||
}
|
||||
}
|
||||
+22
@@ -14,6 +14,7 @@ import androidx.annotation.Nullable;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.bridge.BaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.common.mapbuffer.MapBuffer;
|
||||
@@ -488,4 +489,25 @@ public abstract class ViewManager<T extends View, C extends ReactShadowNode>
|
||||
mRecyclableViews = new HashMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated THIS PREFETCH METHOD IS EXPERIMENTAL, DO NOT USE IT FOR PRODUCTION CODE, MOST
|
||||
* LIKELY IT WILL CHANGE OR BE REMOVED IN THE FUTURE.
|
||||
* <p>Subclasses can override this method to implement custom resource prefetching for the
|
||||
* ViewManager.
|
||||
* @param reactContext {@link com.facebook.react.bridge.ReactContext} used for the view.
|
||||
* @param surfaceId {@link int} surface ID
|
||||
* @param reactTag reactTag that should be set as ID of the view instance
|
||||
* @param params {@link MapBuffer} prefetch request params defined in C++
|
||||
*/
|
||||
@Deprecated
|
||||
public void experimental_prefetchResource(
|
||||
ReactContext reactContext, int surfaceId, int reactTag, MapBuffer params) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected boolean experimental_isPrefetchingEnabled() {
|
||||
return ReactNativeFeatureFlags.enableImagePrefetchingAndroid();
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -138,7 +138,7 @@ internal class BorderDrawable(
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun getOpacity(): Int {
|
||||
val maxBorderAlpha =
|
||||
minOf(
|
||||
maxOf(
|
||||
(Color.alpha(multiplyColorAlpha(computedBorderColors.left, borderAlpha))),
|
||||
(Color.alpha(multiplyColorAlpha(computedBorderColors.top, borderAlpha))),
|
||||
(Color.alpha(multiplyColorAlpha(computedBorderColors.right, borderAlpha))),
|
||||
@@ -675,10 +675,10 @@ internal class BorderDrawable(
|
||||
|
||||
val borderWidth = computeBorderInsets()
|
||||
|
||||
// Clip border ONLY if its color is non transparent
|
||||
if (Color.alpha(computedBorderColors.left) != 0 &&
|
||||
Color.alpha(computedBorderColors.top) != 0 &&
|
||||
Color.alpha(computedBorderColors.right) != 0 &&
|
||||
// Clip border ONLY if at least one edge is non-transparent
|
||||
if (Color.alpha(computedBorderColors.left) != 0 ||
|
||||
Color.alpha(computedBorderColors.top) != 0 ||
|
||||
Color.alpha(computedBorderColors.right) != 0 ||
|
||||
Color.alpha(computedBorderColors.bottom) != 0) {
|
||||
innerClipTempRectForBorderRadius?.top =
|
||||
innerClipTempRectForBorderRadius?.top?.plus(borderWidth.top) ?: 0f
|
||||
|
||||
+5
-5
@@ -646,13 +646,13 @@ public class CSSBackgroundDrawable extends Drawable {
|
||||
colorTop = colorBlockStart;
|
||||
}
|
||||
|
||||
// Clip border ONLY if its color is non transparent
|
||||
// Clip border ONLY if at least one edge is non-transparent
|
||||
float pathAdjustment = 0f;
|
||||
if (Color.alpha(colorLeft) != 0
|
||||
&& Color.alpha(colorTop) != 0
|
||||
&& Color.alpha(colorRight) != 0
|
||||
&& Color.alpha(colorBottom) != 0
|
||||
&& Color.alpha(borderColor) != 0) {
|
||||
|| Color.alpha(colorTop) != 0
|
||||
|| Color.alpha(colorRight) != 0
|
||||
|| Color.alpha(colorBottom) != 0
|
||||
|| Color.alpha(borderColor) != 0) {
|
||||
|
||||
mInnerClipTempRectForBorderRadius.top += borderWidth.top;
|
||||
mInnerClipTempRectForBorderRadius.bottom -= borderWidth.bottom;
|
||||
|
||||
+3
-3
@@ -5,10 +5,10 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.uimanager.events;
|
||||
package com.facebook.react.uimanager.events
|
||||
|
||||
public interface BatchEventDispatchedListener {
|
||||
public fun interface BatchEventDispatchedListener {
|
||||
|
||||
/** Called after a batch of low priority events has been dispatched. */
|
||||
void onBatchEventDispatched();
|
||||
public fun onBatchEventDispatched()
|
||||
}
|
||||
+16
-17
@@ -178,33 +178,32 @@ public data class BorderRadiusStyle(
|
||||
width: Float,
|
||||
height: Float
|
||||
): ComputedBorderRadius {
|
||||
val leftInset = topLeft.horizontal + bottomLeft.horizontal
|
||||
val topInset = topLeft.vertical + topRight.vertical
|
||||
val rightInset = topRight.horizontal + bottomRight.horizontal
|
||||
val bottomInset = bottomLeft.vertical + bottomRight.vertical
|
||||
val leftEdgeRadii = topLeft.vertical + bottomLeft.vertical
|
||||
val topEdgeRadii = topLeft.horizontal + topRight.horizontal
|
||||
val rightEdgeRadii = topRight.vertical + bottomRight.vertical
|
||||
val bottomEdgeRadii = bottomLeft.horizontal + bottomRight.horizontal
|
||||
|
||||
val leftInsetScale = if (leftInset > 0) minOf(1.0f, height / leftInset) else 0f
|
||||
val topInsetScale = if (topInset > 0) minOf(1.0f, width / topInset) else 0f
|
||||
val rightInsetScale = if (rightInset > 0) minOf(1.0f, height / rightInset) else 0f
|
||||
val bottomInsetScale = if (bottomInset > 0) minOf(1.0f, width / bottomInset) else 0f
|
||||
val leftEdgeRadiiScale = if (leftEdgeRadii > 0) minOf(height / leftEdgeRadii, 1f) else 0f
|
||||
val topEdgeRadiiScale = if (topEdgeRadii > 0) minOf(width / topEdgeRadii, 1f) else 0f
|
||||
val rightEdgeRadiiScale = if (rightEdgeRadii > 0) minOf(height / rightEdgeRadii, 1f) else 0f
|
||||
val bottomEdgeRadiiScale = if (bottomEdgeRadii > 0) minOf(width / bottomEdgeRadii, 1f) else 0f
|
||||
|
||||
return ComputedBorderRadius(
|
||||
topLeft =
|
||||
CornerRadii(
|
||||
topLeft.horizontal * minOf(topInsetScale, leftInsetScale),
|
||||
topLeft.vertical * minOf(topInsetScale, leftInsetScale)),
|
||||
topLeft.horizontal * minOf(topEdgeRadiiScale, leftEdgeRadiiScale),
|
||||
topLeft.vertical * minOf(topEdgeRadiiScale, leftEdgeRadiiScale)),
|
||||
topRight =
|
||||
CornerRadii(
|
||||
topRight.horizontal * minOf(topInsetScale, rightInsetScale),
|
||||
topRight.vertical * minOf(topInsetScale, rightInsetScale)),
|
||||
topRight.horizontal * minOf(rightEdgeRadiiScale, topEdgeRadiiScale),
|
||||
topRight.vertical * minOf(rightEdgeRadiiScale, topEdgeRadiiScale)),
|
||||
bottomLeft =
|
||||
CornerRadii(
|
||||
bottomLeft.horizontal * minOf(bottomInsetScale, leftInsetScale),
|
||||
bottomLeft.vertical * minOf(bottomInsetScale, leftInsetScale)),
|
||||
bottomLeft.horizontal * minOf(bottomEdgeRadiiScale, leftEdgeRadiiScale),
|
||||
bottomLeft.vertical * minOf(bottomEdgeRadiiScale, leftEdgeRadiiScale)),
|
||||
bottomRight =
|
||||
CornerRadii(
|
||||
bottomRight.horizontal * minOf(bottomInsetScale, rightInsetScale),
|
||||
bottomRight.vertical * minOf(bottomInsetScale, rightInsetScale)),
|
||||
)
|
||||
bottomRight.horizontal * minOf(bottomEdgeRadiiScale, rightEdgeRadiiScale),
|
||||
bottomRight.vertical * minOf(bottomEdgeRadiiScale, rightEdgeRadiiScale)))
|
||||
}
|
||||
}
|
||||
|
||||
-232
@@ -1,232 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// switchview because switch is a keyword
|
||||
package com.facebook.react.views.switchview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||
import com.facebook.react.uimanager.PixelUtil;
|
||||
import com.facebook.react.uimanager.SimpleViewManager;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.UIManagerHelper;
|
||||
import com.facebook.react.uimanager.ViewManagerDelegate;
|
||||
import com.facebook.react.uimanager.ViewProps;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.react.viewmanagers.AndroidSwitchManagerDelegate;
|
||||
import com.facebook.react.viewmanagers.AndroidSwitchManagerInterface;
|
||||
import com.facebook.yoga.YogaMeasureFunction;
|
||||
import com.facebook.yoga.YogaMeasureMode;
|
||||
import com.facebook.yoga.YogaMeasureOutput;
|
||||
import com.facebook.yoga.YogaNode;
|
||||
|
||||
/** View manager for {@link ReactSwitch} components. */
|
||||
public class ReactSwitchManager extends SimpleViewManager<ReactSwitch>
|
||||
implements AndroidSwitchManagerInterface<ReactSwitch> {
|
||||
|
||||
public static final String REACT_CLASS = "AndroidSwitch";
|
||||
|
||||
static class ReactSwitchShadowNode extends LayoutShadowNode implements YogaMeasureFunction {
|
||||
|
||||
private int mWidth;
|
||||
private int mHeight;
|
||||
private boolean mMeasured;
|
||||
|
||||
private ReactSwitchShadowNode() {
|
||||
initMeasureFunction();
|
||||
}
|
||||
|
||||
private void initMeasureFunction() {
|
||||
setMeasureFunction(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long measure(
|
||||
YogaNode node,
|
||||
float width,
|
||||
YogaMeasureMode widthMode,
|
||||
float height,
|
||||
YogaMeasureMode heightMode) {
|
||||
if (!mMeasured) {
|
||||
// Create a switch with the default config and measure it; since we don't (currently)
|
||||
// support setting custom switch text, this is fine, as all switches will measure the same
|
||||
// on a specific device/theme/locale combination.
|
||||
ReactSwitch reactSwitch = new ReactSwitch(getThemedContext());
|
||||
reactSwitch.setShowText(false);
|
||||
final int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
|
||||
reactSwitch.measure(spec, spec);
|
||||
mWidth = reactSwitch.getMeasuredWidth();
|
||||
mHeight = reactSwitch.getMeasuredHeight();
|
||||
mMeasured = true;
|
||||
}
|
||||
|
||||
return YogaMeasureOutput.make(mWidth, mHeight);
|
||||
}
|
||||
}
|
||||
|
||||
private static final CompoundButton.OnCheckedChangeListener ON_CHECKED_CHANGE_LISTENER =
|
||||
new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
ReactContext reactContext = (ReactContext) buttonView.getContext();
|
||||
|
||||
int reactTag = buttonView.getId();
|
||||
UIManagerHelper.getEventDispatcherForReactTag(reactContext, reactTag)
|
||||
.dispatchEvent(
|
||||
new ReactSwitchEvent(
|
||||
UIManagerHelper.getSurfaceId(reactContext), reactTag, isChecked));
|
||||
}
|
||||
};
|
||||
|
||||
private final ViewManagerDelegate<ReactSwitch> mDelegate;
|
||||
|
||||
public ReactSwitchManager() {
|
||||
mDelegate = new AndroidSwitchManagerDelegate<>(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return REACT_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayoutShadowNode createShadowNodeInstance() {
|
||||
return new ReactSwitchShadowNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getShadowNodeClass() {
|
||||
return ReactSwitchShadowNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ReactSwitch createViewInstance(ThemedReactContext context) {
|
||||
ReactSwitch view = new ReactSwitch(context);
|
||||
view.setShowText(false);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundColor(ReactSwitch view, @ColorInt int backgroundColor) {
|
||||
view.setBackgroundColor(backgroundColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ReactProp(name = "disabled", defaultBoolean = false)
|
||||
public void setDisabled(ReactSwitch view, boolean disabled) {
|
||||
view.setEnabled(!disabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ReactProp(name = ViewProps.ENABLED, defaultBoolean = true)
|
||||
public void setEnabled(ReactSwitch view, boolean enabled) {
|
||||
view.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ReactProp(name = ViewProps.ON)
|
||||
public void setOn(ReactSwitch view, boolean on) {
|
||||
setValueInternal(view, on);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ReactProp(name = "value")
|
||||
public void setValue(ReactSwitch view, boolean value) {
|
||||
setValueInternal(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ReactProp(name = "thumbTintColor", customType = "Color")
|
||||
public void setThumbTintColor(ReactSwitch view, @Nullable Integer color) {
|
||||
this.setThumbColor(view, color);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ReactProp(name = "thumbColor", customType = "Color")
|
||||
public void setThumbColor(ReactSwitch view, @Nullable Integer color) {
|
||||
view.setThumbColor(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ReactProp(name = "trackColorForFalse", customType = "Color")
|
||||
public void setTrackColorForFalse(ReactSwitch view, @Nullable Integer color) {
|
||||
view.setTrackColorForFalse(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ReactProp(name = "trackColorForTrue", customType = "Color")
|
||||
public void setTrackColorForTrue(ReactSwitch view, @Nullable Integer color) {
|
||||
view.setTrackColorForTrue(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ReactProp(name = "trackTintColor", customType = "Color")
|
||||
public void setTrackTintColor(ReactSwitch view, @Nullable Integer color) {
|
||||
view.setTrackColor(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNativeValue(ReactSwitch view, boolean value) {
|
||||
setValueInternal(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveCommand(
|
||||
@NonNull ReactSwitch view, String commandId, @Nullable ReadableArray args) {
|
||||
switch (commandId) {
|
||||
case "setNativeValue":
|
||||
setValueInternal(view, args != null && args.getBoolean(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addEventEmitters(final ThemedReactContext reactContext, final ReactSwitch view) {
|
||||
view.setOnCheckedChangeListener(ON_CHECKED_CHANGE_LISTENER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ViewManagerDelegate<ReactSwitch> getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long measure(
|
||||
Context context,
|
||||
ReadableMap localData,
|
||||
ReadableMap props,
|
||||
ReadableMap state,
|
||||
float width,
|
||||
YogaMeasureMode widthMode,
|
||||
float height,
|
||||
YogaMeasureMode heightMode,
|
||||
@Nullable float[] attachmentsPositions) {
|
||||
ReactSwitch view = new ReactSwitch(context);
|
||||
view.setShowText(false);
|
||||
int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
|
||||
view.measure(measureSpec, measureSpec);
|
||||
return YogaMeasureOutput.make(
|
||||
PixelUtil.toDIPFromPixel(view.getMeasuredWidth()),
|
||||
PixelUtil.toDIPFromPixel(view.getMeasuredHeight()));
|
||||
}
|
||||
|
||||
private static void setValueInternal(ReactSwitch view, boolean value) {
|
||||
// we set the checked change listener to null and then restore it so that we don't fire an
|
||||
// onChange event to JS when JS itself is updating the value of the switch
|
||||
view.setOnCheckedChangeListener(null);
|
||||
view.setOn(value);
|
||||
view.setOnCheckedChangeListener(ON_CHECKED_CHANGE_LISTENER);
|
||||
}
|
||||
}
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.views.switchview
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.widget.CompoundButton
|
||||
import androidx.annotation.ColorInt
|
||||
import com.facebook.react.bridge.ReactContext
|
||||
import com.facebook.react.bridge.ReadableArray
|
||||
import com.facebook.react.bridge.ReadableMap
|
||||
import com.facebook.react.uimanager.BaseViewManager
|
||||
import com.facebook.react.uimanager.PixelUtil
|
||||
import com.facebook.react.uimanager.ThemedReactContext
|
||||
import com.facebook.react.uimanager.UIManagerHelper
|
||||
import com.facebook.react.uimanager.ViewManagerDelegate
|
||||
import com.facebook.react.uimanager.ViewProps
|
||||
import com.facebook.react.uimanager.annotations.ReactProp
|
||||
import com.facebook.react.viewmanagers.AndroidSwitchManagerDelegate
|
||||
import com.facebook.react.viewmanagers.AndroidSwitchManagerInterface
|
||||
import com.facebook.yoga.YogaMeasureMode
|
||||
import com.facebook.yoga.YogaMeasureOutput
|
||||
|
||||
internal class ReactSwitchManager :
|
||||
BaseViewManager<ReactSwitch, ReactSwitchShadowNode>(),
|
||||
AndroidSwitchManagerInterface<ReactSwitch> {
|
||||
|
||||
private val delegate: ViewManagerDelegate<ReactSwitch> = AndroidSwitchManagerDelegate(this)
|
||||
|
||||
override fun getName(): String = REACT_CLASS
|
||||
|
||||
override fun createShadowNodeInstance(): ReactSwitchShadowNode = ReactSwitchShadowNode()
|
||||
|
||||
override fun getShadowNodeClass(): Class<ReactSwitchShadowNode> =
|
||||
ReactSwitchShadowNode::class.java
|
||||
|
||||
override fun createViewInstance(context: ThemedReactContext): ReactSwitch =
|
||||
ReactSwitch(context).apply { showText = false }
|
||||
|
||||
override fun setBackgroundColor(view: ReactSwitch, @ColorInt backgroundColor: Int) {
|
||||
view.setBackgroundColor(backgroundColor)
|
||||
}
|
||||
|
||||
@ReactProp(name = "disabled", defaultBoolean = false)
|
||||
override fun setDisabled(view: ReactSwitch, disabled: Boolean) {
|
||||
view.isEnabled = !disabled
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.ENABLED, defaultBoolean = true)
|
||||
override fun setEnabled(view: ReactSwitch, enabled: Boolean) {
|
||||
view.isEnabled = enabled
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.ON)
|
||||
override fun setOn(view: ReactSwitch, on: Boolean) {
|
||||
setValueInternal(view, on)
|
||||
}
|
||||
|
||||
@ReactProp(name = "value")
|
||||
override fun setValue(view: ReactSwitch, value: Boolean) {
|
||||
setValueInternal(view, value)
|
||||
}
|
||||
|
||||
@ReactProp(name = "thumbTintColor", customType = "Color")
|
||||
override fun setThumbTintColor(view: ReactSwitch, color: Int?) {
|
||||
setThumbColor(view, color)
|
||||
}
|
||||
|
||||
@ReactProp(name = "thumbColor", customType = "Color")
|
||||
override fun setThumbColor(view: ReactSwitch, color: Int?) {
|
||||
view.setThumbColor(color)
|
||||
}
|
||||
|
||||
@ReactProp(name = "trackColorForFalse", customType = "Color")
|
||||
override fun setTrackColorForFalse(view: ReactSwitch, color: Int?) {
|
||||
view.setTrackColorForFalse(color)
|
||||
}
|
||||
|
||||
@ReactProp(name = "trackColorForTrue", customType = "Color")
|
||||
override fun setTrackColorForTrue(view: ReactSwitch, color: Int?) {
|
||||
view.setTrackColorForTrue(color)
|
||||
}
|
||||
|
||||
@ReactProp(name = "trackTintColor", customType = "Color")
|
||||
override fun setTrackTintColor(view: ReactSwitch, color: Int?) {
|
||||
view.setTrackColor(color)
|
||||
}
|
||||
|
||||
override fun setNativeValue(view: ReactSwitch, value: Boolean) {
|
||||
setValueInternal(view, value)
|
||||
}
|
||||
|
||||
override fun receiveCommand(view: ReactSwitch, commandId: String, args: ReadableArray?) {
|
||||
when (commandId) {
|
||||
"setNativeValue" -> setValueInternal(view, args?.getBoolean(0) ?: false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun addEventEmitters(reactContext: ThemedReactContext, view: ReactSwitch) {
|
||||
view.setOnCheckedChangeListener(ON_CHECKED_CHANGE_LISTENER)
|
||||
}
|
||||
|
||||
override fun updateExtraData(root: ReactSwitch, extraData: Any) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
override fun getDelegate(): ViewManagerDelegate<ReactSwitch> = delegate
|
||||
|
||||
override fun measure(
|
||||
context: Context,
|
||||
localData: ReadableMap?,
|
||||
props: ReadableMap?,
|
||||
state: ReadableMap?,
|
||||
width: Float,
|
||||
widthMode: YogaMeasureMode,
|
||||
height: Float,
|
||||
heightMode: YogaMeasureMode,
|
||||
attachmentsPositions: FloatArray?
|
||||
): Long {
|
||||
val view = ReactSwitch(context).apply { showText = false }
|
||||
val measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
|
||||
view.measure(measureSpec, measureSpec)
|
||||
return YogaMeasureOutput.make(
|
||||
PixelUtil.toDIPFromPixel(view.measuredWidth.toFloat()),
|
||||
PixelUtil.toDIPFromPixel(view.measuredHeight.toFloat()))
|
||||
}
|
||||
|
||||
private fun setValueInternal(view: ReactSwitch, value: Boolean) {
|
||||
// Temporarily remove the listener to avoid triggering JS events
|
||||
view.setOnCheckedChangeListener(null)
|
||||
view.setOn(value)
|
||||
view.setOnCheckedChangeListener(ON_CHECKED_CHANGE_LISTENER)
|
||||
}
|
||||
|
||||
internal companion object {
|
||||
public const val REACT_CLASS: String = "AndroidSwitch"
|
||||
|
||||
private val ON_CHECKED_CHANGE_LISTENER =
|
||||
CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
|
||||
val reactContext = buttonView.context as ReactContext
|
||||
val reactTag = buttonView.id
|
||||
UIManagerHelper.getEventDispatcherForReactTag(reactContext, reactTag)
|
||||
?.dispatchEvent(
|
||||
ReactSwitchEvent(UIManagerHelper.getSurfaceId(reactContext), reactTag, isChecked))
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user