diff --git a/.flowconfig b/.flowconfig index 2baa79d4e4..4a97d9ec9e 100644 --- a/.flowconfig +++ b/.flowconfig @@ -86,4 +86,4 @@ untyped-import untyped-type-import [version] -^0.125.0 +^0.126.1 diff --git a/.flowconfig.android b/.flowconfig.android index 0e766ae9d8..0a2ba4482f 100644 --- a/.flowconfig.android +++ b/.flowconfig.android @@ -89,4 +89,4 @@ untyped-import untyped-type-import [version] -^0.125.0 +^0.126.1 diff --git a/.flowconfig.macos b/.flowconfig.macos index e03d7fb76c..12781b008c 100644 --- a/.flowconfig.macos +++ b/.flowconfig.macos @@ -89,4 +89,4 @@ untyped-import untyped-type-import [version] -^0.125.0 +^0.126.1 diff --git a/Libraries/Animated/src/AnimatedImplementation.js b/Libraries/Animated/src/AnimatedImplementation.js index 5045ed398f..12b225abab 100644 --- a/Libraries/Animated/src/AnimatedImplementation.js +++ b/Libraries/Animated/src/AnimatedImplementation.js @@ -6,7 +6,6 @@ * * @flow * @format - * @preventMunge */ 'use strict'; diff --git a/Libraries/BatchedBridge/MessageQueue.js b/Libraries/BatchedBridge/MessageQueue.js index 3756b083fb..d68f2fd2ce 100644 --- a/Libraries/BatchedBridge/MessageQueue.js +++ b/Libraries/BatchedBridge/MessageQueue.js @@ -112,13 +112,6 @@ class MessageQueue { return this.flushedQueue(); } - // Deprecated. T61834641: Remove me once native clients have updated - callFunctionReturnResultAndFlushedQueue( - module: string, - method: string, - args: any[], - ): void {} - invokeCallbackAndReturnFlushedQueue( cbID: number, args: any[], diff --git a/Libraries/Blob/NativeBlobModule.js b/Libraries/Blob/NativeBlobModule.js index ab2572bd0e..d58aeeab6e 100644 --- a/Libraries/Blob/NativeBlobModule.js +++ b/Libraries/Blob/NativeBlobModule.js @@ -23,4 +23,38 @@ export interface Spec extends TurboModule { +release: (blobId: string) => void; } -export default (TurboModuleRegistry.get('BlobModule'): ?Spec); +const NativeModule = TurboModuleRegistry.get('BlobModule'); + +let constants = null; +let NativeBlobModule = null; + +if (NativeModule != null) { + NativeBlobModule = { + getConstants(): {|BLOB_URI_SCHEME: ?string, BLOB_URI_HOST: ?string|} { + if (constants == null) { + constants = NativeModule.getConstants(); + } + return constants; + }, + addNetworkingHandler(): void { + NativeModule.addNetworkingHandler(); + }, + addWebSocketHandler(id: number): void { + NativeModule.addWebSocketHandler(id); + }, + removeWebSocketHandler(id: number): void { + NativeModule.removeWebSocketHandler(id); + }, + sendOverSocket(blob: Object, socketID: number): void { + NativeModule.sendOverSocket(blob, socketID); + }, + createFromParts(parts: Array, withId: string): void { + NativeModule.createFromParts(parts, withId); + }, + release(blobId: string): void { + NativeModule.release(blobId); + }, + }; +} + +export default (NativeBlobModule: ?Spec); diff --git a/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid.js b/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid.js index 9bcb1b9cdd..7dc9f9b751 100644 --- a/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid.js +++ b/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid.js @@ -31,6 +31,40 @@ export interface Spec extends TurboModule { +setHidden: (hidden: boolean) => void; } -export default (TurboModuleRegistry.getEnforcing( - 'StatusBarManager', -): Spec); +const NativeModule = TurboModuleRegistry.getEnforcing('StatusBarManager'); +let constants = null; + +const NativeStatusBarManager = { + getConstants(): {| + +HEIGHT: number, + +DEFAULT_BACKGROUND_COLOR?: number, + |} { + if (constants == null) { + constants = NativeModule.getConstants(); + } + return constants; + }, + + setColor(color: number, animated: boolean): void { + NativeModule.setColor(color, animated); + }, + + setTranslucent(translucent: boolean): void { + NativeModule.setTranslucent(translucent); + }, + + /** + * - statusBarStyles can be: + * - 'default' + * - 'dark-content' + */ + setStyle(statusBarStyle?: ?string): void { + NativeModule.setStyle(statusBarStyle); + }, + + setHidden(hidden: boolean): void { + NativeModule.setHidden(hidden); + }, +}; + +export default NativeStatusBarManager; diff --git a/Libraries/Components/StatusBar/NativeStatusBarManagerIOS.js b/Libraries/Components/StatusBar/NativeStatusBarManagerIOS.js index ecb6d0329c..9840e3da2d 100644 --- a/Libraries/Components/StatusBar/NativeStatusBarManagerIOS.js +++ b/Libraries/Components/StatusBar/NativeStatusBarManagerIOS.js @@ -38,6 +38,53 @@ export interface Spec extends TurboModule { +setHidden: (hidden: boolean, withAnimation: string) => void; } -export default (TurboModuleRegistry.getEnforcing( - 'StatusBarManager', -): Spec); +const NativeModule = TurboModuleRegistry.getEnforcing('StatusBarManager'); +let constants = null; + +const NativeStatusBarManager = { + getConstants(): {| + +HEIGHT: number, + +DEFAULT_BACKGROUND_COLOR?: number, + |} { + if (constants == null) { + constants = NativeModule.getConstants(); + } + return constants; + }, + + // TODO(T47754272) Can we remove this method? + getHeight(callback: (result: {|height: number|}) => void): void { + NativeModule.getHeight(callback); + }, + + setNetworkActivityIndicatorVisible(visible: boolean): void { + NativeModule.setNetworkActivityIndicatorVisible(visible); + }, + + addListener(eventType: string): void { + NativeModule.addListener(eventType); + }, + + removeListeners(count: number): void { + NativeModule.removeListeners(count); + }, + + /** + * - statusBarStyles can be: + * - 'default' + * - 'dark-content' + * - 'light-content' + */ + setStyle(statusBarStyle?: ?string, animated: boolean): void { + NativeModule.setStyle(statusBarStyle, animated); + }, + + /** + * - withAnimation can be: 'none' | 'fade' | 'slide' + */ + setHidden(hidden: boolean, withAnimation: string): void { + NativeModule.setHidden(hidden, withAnimation); + }, +}; + +export default NativeStatusBarManager; diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 034ce9b700..ebab3b4e1f 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -1133,8 +1133,7 @@ function InternalTextInput(props: Props): React.Node { const style = [props.style]; const autoCapitalize = props.autoCapitalize || 'sentences'; let children = props.children; - let childCount = 0; - React.Children.forEach(children, () => ++childCount); + const childCount = React.Children.count(children); invariant( !(props.value && childCount), 'Cannot specify both value and children.', diff --git a/Libraries/Components/ToastAndroid/ToastAndroid.android.js b/Libraries/Components/ToastAndroid/ToastAndroid.android.js index 6d95ae8779..eb4374c2e4 100644 --- a/Libraries/Components/ToastAndroid/ToastAndroid.android.js +++ b/Libraries/Components/ToastAndroid/ToastAndroid.android.js @@ -32,14 +32,16 @@ import NativeToastAndroid from './NativeToastAndroid'; * ``` */ +const ToastAndroidConstants = NativeToastAndroid.getConstants(); + const ToastAndroid = { // Toast duration constants - SHORT: (NativeToastAndroid.getConstants().SHORT: number), - LONG: (NativeToastAndroid.getConstants().LONG: number), + SHORT: (ToastAndroidConstants.SHORT: number), + LONG: (ToastAndroidConstants.LONG: number), // Toast gravity constants - TOP: (NativeToastAndroid.getConstants().TOP: number), - BOTTOM: (NativeToastAndroid.getConstants().BOTTOM: number), - CENTER: (NativeToastAndroid.getConstants().CENTER: number), + TOP: (ToastAndroidConstants.TOP: number), + BOTTOM: (ToastAndroidConstants.BOTTOM: number), + CENTER: (ToastAndroidConstants.CENTER: number), show: function(message: string, duration: number): void { NativeToastAndroid.show(message, duration); diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index f52819de34..58670863b4 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -278,18 +278,6 @@ type AndroidViewProps = $ReadOnly<{| */ renderToHardwareTextureAndroid?: ?boolean, - /** - * Views that are only used to layout their children or otherwise don't draw - * anything may be automatically removed from the native hierarchy as an - * optimization. Set this property to `false` to disable this optimization and - * ensure that this `View` exists in the native view hierarchy. - * - * @platform android - * - * See https://reactnative.dev/docs/view.html#collapsable - */ - collapsable?: ?boolean, - /** * Whether this `View` needs to rendered offscreen and composited with an * alpha in order to preserve 100% correct colors and blending behavior. @@ -508,6 +496,19 @@ export type ViewProps = $ReadOnly<{| */ accessibilityActions?: ?$ReadOnlyArray, + /** + * Views that are only used to layout their children or otherwise don't draw + * anything may be automatically removed from the native hierarchy as an + * optimization. Set this property to `false` to disable this optimization and + * ensure that this `View` exists in the native view hierarchy. + * + * @platform android + * In Fabric, this prop is used in ios as well. + * + * See https://reactnative.dev/docs/view.html#collapsable + */ + collapsable?: ?boolean, + /** * Used to locate this view in end-to-end tests. * diff --git a/Libraries/Core/ExceptionsManager.js b/Libraries/Core/ExceptionsManager.js index a151d26c5d..b1abe891f1 100644 --- a/Libraries/Core/ExceptionsManager.js +++ b/Libraries/Core/ExceptionsManager.js @@ -11,7 +11,6 @@ 'use strict'; import type {ExtendedError} from './Devtools/parseErrorStack'; -import * as LogBoxData from '../LogBox/Data/LogBoxData'; import type {ExceptionData} from './NativeExceptionsManager'; class SyntheticError extends Error { @@ -104,7 +103,8 @@ function reportException( console.error(data.message); } - if (isHandledByLogBox) { + if (__DEV__ && isHandledByLogBox) { + const LogBoxData = require('../LogBox/Data/LogBoxData'); LogBoxData.addException({ ...data, isComponentError: !!e.isComponentError, diff --git a/Libraries/Inspector/InspectorOverlay.js b/Libraries/Inspector/InspectorOverlay.js index 51a1ce5560..c2ad184abc 100644 --- a/Libraries/Inspector/InspectorOverlay.js +++ b/Libraries/Inspector/InspectorOverlay.js @@ -56,6 +56,7 @@ class InspectorOverlay extends React.Component { {content} diff --git a/Libraries/LogBox/LogBox.js b/Libraries/LogBox/LogBox.js index 913dfa8daa..e2754504c1 100644 --- a/Libraries/LogBox/LogBox.js +++ b/Libraries/LogBox/LogBox.js @@ -12,8 +12,6 @@ import Platform from '../Utilities/Platform'; import RCTLog from '../Utilities/RCTLog'; -import * as LogBoxData from './Data/LogBoxData'; -import {parseLogBoxLog, parseInterpolation} from './Data/parseLogBoxLog'; import type {IgnorePattern} from './Data/LogBoxData'; @@ -23,6 +21,9 @@ let LogBox; * LogBox displays logs in the app. */ if (__DEV__) { + const LogBoxData = require('./Data/LogBoxData'); + const {parseLogBoxLog, parseInterpolation} = require('./Data/parseLogBoxLog'); + // LogBox needs to insert itself early, // in order to access the component stacks appended by React DevTools. const {error, warn} = console; diff --git a/Libraries/Modal/Modal.js b/Libraries/Modal/Modal.js index c25cb8ff98..de52591c90 100644 --- a/Libraries/Modal/Modal.js +++ b/Libraries/Modal/Modal.js @@ -11,6 +11,7 @@ 'use strict'; const AppContainer = require('../ReactNative/AppContainer'); +const {RootTagContext} = require('../ReactNative/RootTag'); const I18nManager = require('../ReactNative/I18nManager'); const NativeEventEmitter = require('../EventEmitter/NativeEventEmitter'); import NativeModalManager from './NativeModalManager'; @@ -21,6 +22,7 @@ const ScrollView = require('../Components/ScrollView/ScrollView'); const StyleSheet = require('../StyleSheet/StyleSheet'); const View = require('../Components/View/View'); +import type {RootTag} from '../ReactNative/RootTag'; import type {ViewProps} from '../Components/View/ViewPropTypes'; import type {DirectEventHandler} from '../Types/CodegenTypes'; import type EmitterSubscription from '../vendor/emitter/EmitterSubscription'; @@ -156,9 +158,7 @@ class Modal extends React.Component { hardwareAccelerated: false, }; - static contextTypes: any | {|rootTag: React$PropType$Primitive|} = { - rootTag: PropTypes.number, - }; + static contextType: React.Context = RootTagContext; _identifier: number; _eventSubscription: ?EmitterSubscription; @@ -224,9 +224,7 @@ class Modal extends React.Component { } const innerChildren = __DEV__ ? ( - - {this.props.children} - + {this.props.children} ) : ( this.props.children ); diff --git a/Libraries/NativeModules/specs/NativeSourceCode.js b/Libraries/NativeModules/specs/NativeSourceCode.js index 7bcd16bdf8..903123c94d 100644 --- a/Libraries/NativeModules/specs/NativeSourceCode.js +++ b/Libraries/NativeModules/specs/NativeSourceCode.js @@ -19,4 +19,19 @@ export interface Spec extends TurboModule { |}; } -export default (TurboModuleRegistry.getEnforcing('SourceCode'): Spec); +const NativeModule = TurboModuleRegistry.getEnforcing('SourceCode'); +let constants = null; + +const NativeSourceCode = { + getConstants(): {| + scriptURL: string, + |} { + if (constants == null) { + constants = NativeModule.getConstants(); + } + + return constants; + }, +}; + +export default NativeSourceCode; diff --git a/Libraries/Types/CoreEventTypes.js b/Libraries/Types/CoreEventTypes.js index f5abe51bb7..b7e509aca1 100644 --- a/Libraries/Types/CoreEventTypes.js +++ b/Libraries/Types/CoreEventTypes.js @@ -91,7 +91,7 @@ export type PressEvent = ResponderSyntheticEvent< button?: ?number, // TODO(macOS GH#774) changedTouches: $ReadOnlyArray<$PropertyType>, ctrlKey?: ?boolean, // TODO(macOS GH#774) - force: number, + force?: number, identifier: number, locationX: number, locationY: number, diff --git a/Libraries/Utilities/NativeDeviceInfo.js b/Libraries/Utilities/NativeDeviceInfo.js index b29b68e0cd..e1f2a6625d 100644 --- a/Libraries/Utilities/NativeDeviceInfo.js +++ b/Libraries/Utilities/NativeDeviceInfo.js @@ -43,7 +43,18 @@ export interface Spec extends TurboModule { } const NativeModule: Spec = TurboModuleRegistry.getEnforcing('DeviceInfo'); +let constants = null; -const NativeDeviceInfo = NativeModule; +const NativeDeviceInfo = { + getConstants(): {| + +Dimensions: DimensionsPayload, + +isIPhoneX_deprecated?: boolean, + |} { + if (constants == null) { + constants = NativeModule.getConstants(); + } + return constants; + }, +}; export default NativeDeviceInfo; diff --git a/RNTester/Podfile.lock b/RNTester/Podfile.lock index 600a713031..c412112d0c 100644 --- a/RNTester/Podfile.lock +++ b/RNTester/Podfile.lock @@ -251,6 +251,7 @@ PODS: - glog - RCT-Folly (= 2020.01.13.00) - React-callinvoker (= 1000.0.0) + - React-jsi (= 1000.0.0) - React-jsinspector (= 1000.0.0) - React-perflogger (= 1000.0.0) - React-runtimeexecutor (= 1000.0.0) @@ -523,8 +524,8 @@ SPEC CHECKSUMS: CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845 CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f DoubleConversion: 2b45d0f8e156a5b02354c8a4062de64d41ccb4e0 - FBLazyVector: 612364849df0026a8fdea446ac929d32f9f0a423 - FBReactNativeSpec: 30d621de10913f14a0a5905ce088ea18b85c2dbb + FBLazyVector: 473624d6d8a95dddea531181b5fe074296b849d4 + FBReactNativeSpec: aa5face1bbc5054a321b7a71a7a9f63fb9b9ed7f Flipper: be611d4b742d8c87fbae2ca5f44603a02539e365 Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41 Flipper-Folly: c12092ea368353b58e992843a990a3225d4533c3 @@ -535,34 +536,34 @@ SPEC CHECKSUMS: glog: 789873d01e4b200777d0a09bc23d548446758699 OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355 RCT-Folly: 55d0039b24e192081ec0b2257f7bd9f42e382fb7 - RCTRequired: 6d90ba4846a58d45539e8118ebf7a06d2db379cc - RCTTypeSafety: 9e0a77a9f2c4e0688c985ec1243307d6777805ab - React: 7070d4f9baf939baedfcd1358acdaf0a259b023d - React-ART: 531f0b78884eecc02b0088330e1b820ca7ef186f - React-callinvoker: 94940d7aa248934637b2a6020aab6c1de893e5c7 - React-Core: 84250af569c182909120182e89914ae17be2b6ed - React-CoreModules: 2c51a966aa8dfb075c85caee7fdc0f1a02062f8a - React-cxxreact: f5a570f0eeea78b7eabf322dc01ed7c54b092320 - React-jsi: f63877d063edf2a614d67f454ea68825953079ff - React-jsiexecutor: ba971320209048169e0d9e7b0d1d25758e266a2f - React-jsinspector: 9a3e9449f88a9abe091b13f6b8a214dd26465b26 - React-perflogger: 0fad4dd40022e77107f74a593204945d78b52876 - React-RCTActionSheet: 5890411c18dcd860bd792882fb20b81f22f25bc4 - React-RCTAnimation: ae52c02def54ee24f7522088bffbe33874265ca8 - React-RCTBlob: 6bfe0eab854c0ea95dea90a9f2d9b555502503e0 - React-RCTImage: 16232a23bdb07d5a06705f95b3b40ee28ba3054c - React-RCTLinking: 3d4dcd2e7f15dd11bb18861bdf7b4781f76d4d64 - React-RCTNetwork: 0cbd4b96fcf726438f9814631e447cfe4db714c9 - React-RCTPushNotification: 61f472384037a2d15fa3c76e069ccde9979c8a89 - React-RCTSettings: a9952a40a7d89e4f3aec025185f197e58a1a22a2 - React-RCTTest: b86c663b9dc6b0dccd6b37a794b6a7d8c164c4f3 - React-RCTText: ee61e09fc11975b5669bcddc36549ee848ad3b83 - React-RCTVibration: 37bb78ecacc0cfeb619b3b46a436b31246b8fcb1 - React-runtimeexecutor: a0adc3b14832a771a58bdee656a775a096be3d7a + RCTRequired: c2b55a638af545470baa7e1953525cbdd249f071 + RCTTypeSafety: 6f8075941c3b0a18fe2dc4b343aea938d0bad5e2 + React: 8ebf7e7f105fbcea86199badd55a6bb67a5b8afa + React-ART: a75138364a2681f5189fe24af2a645a4f9069353 + React-callinvoker: 497cecd63f6e72c269c808e8529b36e31816175f + React-Core: 21186234ce1a0dfdd68bb885f36953f03f6ad595 + React-CoreModules: 20deecbc9727971b94d8b7e36addba9ee5b3df7b + React-cxxreact: 78dadb6f1c308aac81c14cc5fa55eee1bf4e509a + React-jsi: 04aa49b53eb6627f22a208b7a453b7c695c23f13 + React-jsiexecutor: 68b861e21c43a19980374229f98003860e389eb7 + React-jsinspector: b75196b3c0ed12a6608798366cd627fd93d8aef5 + React-perflogger: 1e95f386e69d2531429be35018b9e3a7e7319f0d + React-RCTActionSheet: 2f5024fba47f6bbae7cd7035bcfe3a2a9ceab828 + React-RCTAnimation: c5daba3acc6601ed49befc73314f3a4a3dffac7e + React-RCTBlob: e88442441bf43cb1733faf5ee0369cb77ef9a9c5 + React-RCTImage: 0d6613af0b99b24bb2f10d951c36d682b15ba90f + React-RCTLinking: b47cd2eda4ad15424f1ad02f4eb9ff027f212f6c + React-RCTNetwork: 1bdb44306b36686fcdf51fb353cd5bea1910c9dc + React-RCTPushNotification: 0d9ef4d1acc93d00828de47763834ef9f7e825c7 + React-RCTSettings: 606a93f1f422bb1e33e8178715edcbeb00ef0e29 + React-RCTTest: 61a59b3db0d728bd3f2e4c477aa39f5308f58d3d + React-RCTText: 377bcb96f1626badf03d4e7cb08efc1e49ca8654 + React-RCTVibration: a68e8de67fd7d6fe24f027965291dff20a7e1ecf + React-runtimeexecutor: b5c501cbb838fb190272567117469ba89ca4095c React-TurboModuleCxx-RNW: 18bb71af41fe34c8b12a56bef60aae7ee32b0817 - React-TurboModuleCxx-WinRTPort: c5ee8d0f7fd49453996a980a8646afb251339acb - ReactCommon: 37c88457c9e4896daaa6a7aa699f9d54ae5e148e - Yoga: 8838387cf620983b4e0e6e6c0486c6041b3faee3 + React-TurboModuleCxx-WinRTPort: bbf5afaa8aa712919a56b270bee8a83a74d7c6f5 + ReactCommon: d4fccf43589bf37d7e3b94c32ce3722a0889d98c + Yoga: 4fec242f984a794825ad52bc24af3c0c91da2d7d YogaKit: f782866e155069a2cca2517aafea43200b01fd5a PODFILE CHECKSUM: 7d43a928a9b9ad27329da110adbfadd923a39ba8 diff --git a/RNTester/RNTester-macOS/AppDelegate.mm b/RNTester/RNTester-macOS/AppDelegate.mm index 7951d625e5..002c372f1c 100644 --- a/RNTester/RNTester-macOS/AppDelegate.mm +++ b/RNTester/RNTester-macOS/AppDelegate.mm @@ -115,7 +115,10 @@ NSString *kBundleNameJS = @"RNTesterApp"; } __typeof(self) strongSelf = weakSelf; if (strongSelf) { - [strongSelf->_turboModuleManager installJSBindingWithRuntime:&runtime]; + facebook::react::RuntimeExecutor syncRuntimeExecutor = [&](std::function &&callback) { + callback(runtime); + }; + [strongSelf->_turboModuleManager installJSBindingWithRuntimeExecutor:syncRuntimeExecutor]; } }) ); diff --git a/RNTester/RNTester/AppDelegate.mm b/RNTester/RNTester/AppDelegate.mm index df27fa1add..d8bd2807b2 100644 --- a/RNTester/RNTester/AppDelegate.mm +++ b/RNTester/RNTester/AppDelegate.mm @@ -178,7 +178,10 @@ } __typeof(self) strongSelf = weakSelf; if (strongSelf) { - [strongSelf->_turboModuleManager installJSBindingWithRuntime:&runtime]; + facebook::react::RuntimeExecutor syncRuntimeExecutor = [&](std::function &&callback) { + callback(runtime); + }; + [strongSelf->_turboModuleManager installJSBindingWithRuntimeExecutor:syncRuntimeExecutor]; } }) ); diff --git a/RNTester/RNTesterUnitTests/RCTBundleURLProviderTests.m b/RNTester/RNTesterUnitTests/RCTBundleURLProviderTests.m index 386565f6d2..e54e943510 100644 --- a/RNTester/RNTesterUnitTests/RCTBundleURLProviderTests.m +++ b/RNTester/RNTesterUnitTests/RCTBundleURLProviderTests.m @@ -20,12 +20,24 @@ static NSURL *mainBundleURL() static NSURL *localhostBundleURL() { - return [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:8081/%@.bundle?platform=%@&dev=true&minify=false&app=com.apple.dt.xctest.tool", testFile, kRCTPlatformName]]; // TODO(macOS ISS#3536887) + return [NSURL + URLWithString: + [NSString + stringWithFormat: + @"http://localhost:8081/%@.bundle?platform=%@&dev=true&minify=false&modulesOnly=false&runMdoule=true&app=com.apple.dt.xctest.tool", + testFile, + kRCTPlatformName]]; // TODO(macOS GH#774) } static NSURL *ipBundleURL() { - return [NSURL URLWithString:[NSString stringWithFormat:@"http://192.168.1.1:8081/%@.bundle?platform=%@&dev=true&minify=false&app=com.apple.dt.xctest.tool", testFile, kRCTPlatformName]]; // TODO(macOS ISS#3536887) + return [NSURL + URLWithString: + [NSString + stringWithFormat: + @"http://192.168.1.1:8081/%@.bundle?platform=%@&dev=true&minify=false&modulesOnly=false&runMdoule=true&app=com.apple.dt.xctest.tool", + testFile, + kRCTPlatformName]]; // TODO(macOS GH#774) } @implementation NSBundle (RCTBundleURLProviderTests) @@ -50,16 +62,14 @@ static NSURL *ipBundleURL() { [super setUp]; - RCTSwapInstanceMethods([NSBundle class], - @selector(URLForResource:withExtension:), - @selector(RCT_URLForResource:withExtension:)); + RCTSwapInstanceMethods( + [NSBundle class], @selector(URLForResource:withExtension:), @selector(RCT_URLForResource:withExtension:)); } - (void)tearDown { - RCTSwapInstanceMethods([NSBundle class], - @selector(URLForResource:withExtension:), - @selector(RCT_URLForResource:withExtension:)); + RCTSwapInstanceMethods( + [NSBundle class], @selector(URLForResource:withExtension:), @selector(RCT_URLForResource:withExtension:)); [super tearDown]; } diff --git a/RNTester/js/examples/Pressable/PressableExample.js b/RNTester/js/examples/Pressable/PressableExample.js index e57f632009..9a67af10f6 100644 --- a/RNTester/js/examples/Pressable/PressableExample.js +++ b/RNTester/js/examples/Pressable/PressableExample.js @@ -167,7 +167,7 @@ function ForceTouchExample() { style={styles.wrapper} testID="pressable_3dtouch_button" onStartShouldSetResponder={() => true} - onResponderMove={event => setForce(event.nativeEvent.force)} + onResponderMove={event => setForce(event.nativeEvent?.force || 1)} onResponderRelease={event => setForce(0)}> Press Me diff --git a/React/Base/RCTBundleURLProvider.h b/React/Base/RCTBundleURLProvider.h index cb9dc6f88a..4256186549 100644 --- a/React/Base/RCTBundleURLProvider.h +++ b/React/Base/RCTBundleURLProvider.h @@ -47,6 +47,11 @@ extern NSString *const kRCTPlatformName; // TODO(macOS GH#774) */ - (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot fallbackURLProvider:(NSURL * (^)(void))fallbackURLProvider; +/** + * Returns the jsBundleURL for a given split bundle entrypoint in development + */ +- (NSURL *)jsBundleURLForSplitBundleRoot:(NSString *)bundleRoot; + /** * Returns the jsBundleURL for a given bundle entrypoint and * the fallback offline JS bundle if the packager is not running. @@ -91,15 +96,30 @@ extern NSString *const kRCTPlatformName; // TODO(macOS GH#774) + (instancetype)sharedSettings; /** - Given a hostname for the packager and a bundle root, returns the URL to the js bundle. Generally you should use the - instance method -jsBundleURLForBundleRoot:fallbackResource: which includes logic to guess if the packager is running - and fall back to a pre-packaged bundle if it is not. + * Given a hostname for the packager and a bundle root, returns the URL to the js bundle. Generally you should use the + * instance method -jsBundleURLForBundleRoot:fallbackResource: which includes logic to guess if the packager is running + * and fall back to a pre-packaged bundle if it is not. + * + * The options here mirror some of Metro's Bundling Options: + * - enableDev: Whether to keep or remove `__DEV__` blocks from the bundle. + * - enableMinification: Enables or disables minification. Usually production bundles are minified and development + * bundles are not. + * - modulesOnly: When true, will only send module definitions without polyfills and without the require-runtime. + * - runModule: When true, will run the main module after defining all modules. This is used in the main bundle but not + * in split bundles. */ + (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot packagerHost:(NSString *)packagerHost enableDev:(BOOL)enableDev enableMinification:(BOOL)enableMinification; ++ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot + packagerHost:(NSString *)packagerHost + enableDev:(BOOL)enableDev + enableMinification:(BOOL)enableMinification + modulesOnly:(BOOL)modulesOnly + runModule:(BOOL)runModule; + /** * Given a hostname for the packager and a resource path (including "/"), return the URL to the resource. * In general, please use the instance method to decide if the packager is running and fallback to the pre-packaged diff --git a/React/Base/RCTBundleURLProvider.m b/React/Base/RCTBundleURLProvider.m index c4a0684d4d..fd02477c4f 100644 --- a/React/Base/RCTBundleURLProvider.m +++ b/React/Base/RCTBundleURLProvider.m @@ -151,6 +151,16 @@ static NSURL *serverRootWithHostPort(NSString *hostPort) } } +- (NSURL *)jsBundleURLForSplitBundleRoot:(NSString *)bundleRoot +{ + return [RCTBundleURLProvider jsBundleURLForBundleRoot:bundleRoot + packagerHost:[self packagerServerHost] + enableDev:[self enableDev] + enableMinification:[self enableMinification] + modulesOnly:YES + runModule:NO]; +} + - (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot fallbackResource:(NSString *)resourceName fallbackExtension:(NSString *)extension @@ -192,13 +202,31 @@ static NSURL *serverRootWithHostPort(NSString *hostPort) packagerHost:(NSString *)packagerHost enableDev:(BOOL)enableDev enableMinification:(BOOL)enableMinification + +{ + return [self jsBundleURLForBundleRoot:bundleRoot + packagerHost:packagerHost + enableDev:enableDev + enableMinification:enableMinification + modulesOnly:NO + runModule:YES]; +} + ++ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot + packagerHost:(NSString *)packagerHost + enableDev:(BOOL)enableDev + enableMinification:(BOOL)enableMinification + modulesOnly:(BOOL)modulesOnly + runModule:(BOOL)runModule { NSString *path = [NSString stringWithFormat:@"/%@.bundle", bundleRoot]; // When we support only iOS 8 and above, use queryItems for a better API. - NSString *query = [NSString stringWithFormat:@"platform=%@&dev=%@&minify=%@", + NSString *query = [NSString stringWithFormat:@"platform=%@&dev=%@&minify=%@&modulesOnly=%@&runMdoule=%@", kRCTPlatformName, // TODO(macOS GH#774) enableDev ? @"true" : @"false", - enableMinification ? @"true" : @"false"]; + enableMinification ? @"true" : @"false", + modulesOnly ? @"true" : @"false", + runModule ? @"true" : @"false"]; NSString *bundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey]; if (bundleID) { query = [NSString stringWithFormat:@"%@&app=%@", query, bundleID]; diff --git a/React/Base/RCTModuleData.h b/React/Base/RCTModuleData.h index 398c0a2b9f..04d6271eee 100644 --- a/React/Base/RCTModuleData.h +++ b/React/Base/RCTModuleData.h @@ -8,6 +8,7 @@ #import #import +#import "RCTDefines.h" @protocol RCTBridgeMethod; @protocol RCTBridgeModule; @@ -94,3 +95,6 @@ typedef id (^RCTBridgeModuleProvider)(void); @property (nonatomic, assign, readonly) BOOL implementsPartialBatchDidFlush; @end + +RCT_EXTERN void RCTSetIsMainQueueExecutionOfConstantsToExportDisabled(BOOL val); +RCT_EXTERN BOOL RCTIsMainQueueExecutionOfConstantsToExportDisabled(); diff --git a/React/Base/RCTModuleData.mm b/React/Base/RCTModuleData.mm index 14251ee6d5..c9c2ac7949 100644 --- a/React/Base/RCTModuleData.mm +++ b/React/Base/RCTModuleData.mm @@ -29,6 +29,17 @@ int32_t getUniqueId() return counter++; } } +static BOOL isMainQueueExecutionOfConstantToExportDisabled = NO; + +void RCTSetIsMainQueueExecutionOfConstantsToExportDisabled(BOOL val) +{ + isMainQueueExecutionOfConstantToExportDisabled = val; +} + +BOOL RCTIsMainQueueExecutionOfConstantsToExportDisabled() +{ + return isMainQueueExecutionOfConstantToExportDisabled; +} @implementation RCTModuleData { NSDictionary *_constantsToExport; @@ -389,7 +400,8 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init); * require. */ BridgeNativeModulePerfLogger::moduleJSRequireEndingStart([moduleName UTF8String]); - if (_requiresMainQueueSetup) { + + if (!RCTIsMainQueueExecutionOfConstantsToExportDisabled() && _requiresMainQueueSetup) { if (!RCTIsMainQueue()) { RCTLogWarn(@"Required dispatch_sync to load constants for %@. This may lead to deadlocks", _moduleClass); } @@ -400,6 +412,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init); } else { _constantsToExport = [_instance constantsToExport] ?: @{}; } + RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @""); } else { /** diff --git a/React/CoreModules/RCTAppState.mm b/React/CoreModules/RCTAppState.mm index e949171941..6f17715e14 100644 --- a/React/CoreModules/RCTAppState.mm +++ b/React/CoreModules/RCTAppState.mm @@ -67,9 +67,14 @@ RCT_EXPORT_MODULE() - (facebook::react::ModuleConstants)getConstants { - return facebook::react::typedConstants({ - .initialAppState = RCTCurrentAppState(), + __block facebook::react::ModuleConstants constants; + RCTUnsafeExecuteOnMainQueueSync(^{ + constants = facebook::react::typedConstants({ + .initialAppState = RCTCurrentAppState(), + }); }); + + return constants; } #pragma mark - Lifecycle diff --git a/React/CoreModules/RCTDeviceInfo.mm b/React/CoreModules/RCTDeviceInfo.mm index 73b61fac82..8bf767a71a 100644 --- a/React/CoreModules/RCTDeviceInfo.mm +++ b/React/CoreModules/RCTDeviceInfo.mm @@ -138,18 +138,23 @@ NSDictionary *RCTExportedDimensions(RCTPlatformView *rootView) - (NSDictionary *)getConstants { - return @{ + __block NSDictionary *constants; + RCTUnsafeExecuteOnMainQueueSync(^{ + constants = @{ #if !TARGET_OS_OSX // TODO(macOS GH#774) - @"Dimensions" : RCTExportedDimensions(_bridge), + @"Dimensions" : RCTExportedDimensions(self->_bridge), #else // [TODO(macOS GH#774) - @"Dimensions": RCTExportedDimensions(nil), + @"Dimensions": RCTExportedDimensions(nil), #endif // ]TODO(macOS GH#774) - // Note: - // This prop is deprecated and will be removed in a future release. - // Please use this only for a quick and temporary solution. - // Use instead. - @"isIPhoneX_deprecated" : @(RCTIsIPhoneX()), - }; + // Note: + // This prop is deprecated and will be removed in a future release. + // Please use this only for a quick and temporary solution. + // Use instead. + @"isIPhoneX_deprecated" : @(RCTIsIPhoneX()), + }; + }); + + return constants; } - (void)didReceiveNewContentSizeMultiplier diff --git a/React/CoreModules/RCTPlatform.mm b/React/CoreModules/RCTPlatform.mm index b5952272c7..96a2127ca0 100644 --- a/React/CoreModules/RCTPlatform.mm +++ b/React/CoreModules/RCTPlatform.mm @@ -58,22 +58,27 @@ RCT_EXPORT_MODULE(PlatformConstants) - (ModuleConstants)getConstants { - UIDevice *device = [UIDevice currentDevice]; - auto versions = RCTGetReactNativeVersion(); - return typedConstants({ - .forceTouchAvailable = RCTForceTouchAvailable() ? true : false, - .osVersion = [device systemVersion], - .systemName = [device systemName], - .interfaceIdiom = interfaceIdiom([device userInterfaceIdiom]), - .isTesting = RCTRunningInTestEnvironment() ? true : false, - .reactNativeVersion = JS::NativePlatformConstantsIOS::ConstantsReactNativeVersion::Builder( - {.minor = [versions[@"minor"] doubleValue], - .major = [versions[@"major"] doubleValue], - .patch = [versions[@"patch"] doubleValue], - .prerelease = [versions[@"prerelease"] isKindOfClass:[NSNull class]] - ? folly::Optional{} - : [versions[@"prerelease"] doubleValue]}), + __block ModuleConstants constants; + RCTUnsafeExecuteOnMainQueueSync(^{ + UIDevice *device = [UIDevice currentDevice]; + auto versions = RCTGetReactNativeVersion(); + constants = typedConstants({ + .forceTouchAvailable = RCTForceTouchAvailable() ? true : false, + .osVersion = [device systemVersion], + .systemName = [device systemName], + .interfaceIdiom = interfaceIdiom([device userInterfaceIdiom]), + .isTesting = RCTRunningInTestEnvironment() ? true : false, + .reactNativeVersion = JS::NativePlatformConstantsIOS::ConstantsReactNativeVersion::Builder( + {.minor = [versions[@"minor"] doubleValue], + .major = [versions[@"major"] doubleValue], + .patch = [versions[@"patch"] doubleValue], + .prerelease = [versions[@"prerelease"] isKindOfClass:[NSNull class]] + ? folly::Optional{} + : [versions[@"prerelease"] doubleValue]}), + }); }); + + return constants; } - (std::shared_ptr)getTurboModule:(const ObjCTurboModule::InitParams &)params diff --git a/React/CoreModules/RCTStatusBarManager.mm b/React/CoreModules/RCTStatusBarManager.mm index 000ccd80af..0af98f96fb 100644 --- a/React/CoreModules/RCTStatusBarManager.mm +++ b/React/CoreModules/RCTStatusBarManager.mm @@ -185,10 +185,15 @@ RCT_EXPORT_METHOD(setNetworkActivityIndicatorVisible : (BOOL)visible) - (facebook::react::ModuleConstants)getConstants { - return facebook::react::typedConstants({ - .HEIGHT = RCTSharedApplication().statusBarFrame.size.height, - .DEFAULT_BACKGROUND_COLOR = folly::none, + __block facebook::react::ModuleConstants constants; + RCTUnsafeExecuteOnMainQueueSync(^{ + constants = facebook::react::typedConstants({ + .HEIGHT = RCTSharedApplication().statusBarFrame.size.height, + .DEFAULT_BACKGROUND_COLOR = folly::none, + }); }); + + return constants; } - (facebook::react::ModuleConstants)constantsToExport diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index b2501d62d6..85e579d1f0 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -265,10 +265,24 @@ struct RCTInstanceCallback : public InstanceCallback { _moduleDataByID = [NSMutableArray new]; [RCTBridge setCurrentBridge:self]; + +#if !TARGET_OS_OSX // TODO(macOS GH#774) + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleMemoryWarning) + name:UIApplicationDidReceiveMemoryWarningNotification + object:nil]; +#endif // TODO(macOS GH#774) } return self; } +- (void)dealloc +{ +#if !TARGET_OS_OSX // TODO(macOS GH#774) + [[NSNotificationCenter defaultCenter] removeObserver:self]; +#endif // TODO9macOS GH#774) +} + + (void)runRunLoop { @autoreleasepool { @@ -302,6 +316,20 @@ struct RCTInstanceCallback : public InstanceCallback { } } +- (void)handleMemoryWarning +{ + if (!_valid || !_loading) { + return; + } + + // We need to hold a local retaining pointer to react instance + // in case if some other tread resets it. + auto reactInstance = _reactInstance; + if (reactInstance) { + reactInstance->handleMemoryPressure(15 /* TRIM_MEMORY_RUNNING_CRITICAL */); + } +} + /** * Ensure block is run on the JS thread. If we're already on the JS thread, the block will execute synchronously. * If we're not on the JS thread, the block is dispatched to that thread. Any errors encountered while executing @@ -911,7 +939,9 @@ struct RCTInstanceCallback : public InstanceCallback { if (self.valid && ![moduleData.moduleClass isSubclassOfClass:[RCTCxxModule class]]) { [self->_performanceLogger appendStartForTag:RCTPLNativeModuleMainThread]; (void)[moduleData instance]; - [moduleData gatherConstants]; + if (!RCTIsMainQueueExecutionOfConstantsToExportDisabled()) { + [moduleData gatherConstants]; + } [self->_performanceLogger appendStopForTag:RCTPLNativeModuleMainThread]; } }; diff --git a/React/Fabric/RCTScheduler.mm b/React/Fabric/RCTScheduler.mm index d89af23b38..67afffa3b0 100644 --- a/React/Fabric/RCTScheduler.mm +++ b/React/Fabric/RCTScheduler.mm @@ -114,7 +114,7 @@ class LayoutAnimationDelegateProxy : public LayoutAnimationStatusDelegate, publi if (_layoutAnimationsEnabled) { _layoutAnimationDelegateProxy = std::make_shared((__bridge void *)self); - _animationDriver = std::make_unique(_layoutAnimationDelegateProxy.get()); + _animationDriver = std::make_shared(_layoutAnimationDelegateProxy.get()); _uiRunLoopObserver = toolbox.mainRunLoopObserverFactory(RunLoopObserver::Activity::BeforeWaiting, _layoutAnimationDelegateProxy); _uiRunLoopObserver->setDelegate(_layoutAnimationDelegateProxy.get()); @@ -152,12 +152,7 @@ class LayoutAnimationDelegateProxy : public LayoutAnimationStatusDelegate, publi auto props = convertIdToFollyDynamic(initialProps); _scheduler->startSurface( - surfaceId, - RCTStringFromNSString(moduleName), - props, - layoutConstraints, - layoutContext, - (_animationDriver ? _animationDriver.get() : nullptr)); + surfaceId, RCTStringFromNSString(moduleName), props, layoutConstraints, layoutContext, _animationDriver); _scheduler->renderTemplateToSurface( surfaceId, props.getDefault("navigationConfig").getDefault("initialUITemplate", "").getString()); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 63ac2ec11d..46ce038b40 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -655,9 +655,9 @@ public class ReactInstanceManager { } } - /** Temporary: due to T62192299, log sources of destroy calls. TODO T62192299: delete */ + /** Temporary: due to T67035147, log sources of destroy calls. TODO T67035147: delete */ private void logOnDestroy() { - FLog.e( + FLog.d( TAG, "ReactInstanceManager.destroy called", new RuntimeException("ReactInstanceManager.destroy called")); @@ -669,7 +669,6 @@ public class ReactInstanceManager { UiThreadUtil.assertOnUiThread(); PrinterHolder.getPrinter().logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: Destroy"); - // TODO T62192299: remove when investigation is complete logOnDestroy(); if (mHasStartedDestroying) { @@ -1134,8 +1133,7 @@ public class ReactInstanceManager { } private void attachRootViewToInstance(final ReactRoot reactRoot) { - // TODO: downgrade back to FLog.d once T62192299 is resolved. - FLog.e(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()"); + FLog.d(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()"); Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "attachRootViewToInstance"); @Nullable @@ -1281,39 +1279,15 @@ public class ReactInstanceManager { reactContext.initializeWithInstance(catalystInstance); - if (ReactFeatureFlags.enableTurboModuleDebugLogs) { - // TODO(T46487253): Remove after task is closed - FLog.e( - ReactConstants.TAG, - "ReactInstanceManager.createReactContext: mJSIModulePackage " - + (mJSIModulePackage != null ? "not null" : "null")); - } - if (mJSIModulePackage != null) { catalystInstance.addJSIModules( mJSIModulePackage.getJSIModules( reactContext, catalystInstance.getJavaScriptContextHolder())); - if (ReactFeatureFlags.enableTurboModuleDebugLogs) { - // TODO(T46487253): Remove after task is closed - FLog.e( - ReactConstants.TAG, - "ReactInstanceManager.createReactContext: ReactFeatureFlags.useTurboModules == " - + (ReactFeatureFlags.useTurboModules == false ? "false" : "true")); - } - if (ReactFeatureFlags.useTurboModules) { JSIModule turboModuleManager = catalystInstance.getJSIModule(JSIModuleType.TurboModuleManager); - if (ReactFeatureFlags.enableTurboModuleDebugLogs) { - // TODO(T46487253): Remove after task is closed - FLog.e( - ReactConstants.TAG, - "ReactInstanceManager.createReactContext: TurboModuleManager " - + (turboModuleManager == null ? "not created" : "created")); - } - catalystInstance.setTurboModuleManager(turboModuleManager); TurboModuleRegistry registry = (TurboModuleRegistry) turboModuleManager; diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java index 7c82dd1539..c124747172 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java @@ -523,8 +523,6 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot { mShouldLogContentAppeared = true; - // TODO T62192299: remove this - FLog.e(TAG, "runApplication: call AppRegistry.runApplication"); catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams); } finally { Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java index e67723c7b1..1c05e52b92 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java @@ -10,7 +10,6 @@ package com.facebook.react.animated; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; -import com.facebook.common.logging.FLog; import com.facebook.fbreact.specs.NativeAnimatedModuleSpec; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.Arguments; @@ -21,7 +20,6 @@ import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.UIManager; import com.facebook.react.bridge.UIManagerListener; import com.facebook.react.bridge.WritableMap; -import com.facebook.react.common.ReactConstants; import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.modules.core.DeviceEventManagerModule; @@ -108,23 +106,23 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec protected void doFrameGuarded(final long frameTimeNanos) { try { NativeAnimatedNodesManager nodesManager = getNodesManager(); - if (nodesManager.hasActiveAnimations()) { + if (nodesManager != null && nodesManager.hasActiveAnimations()) { nodesManager.runUpdates(frameTimeNanos); } + // This is very unlikely to ever be hit. + if (nodesManager == null && mReactChoreographer == null) { + return; + } // TODO: Would be great to avoid adding this callback in case there are no active - // animations - // and no outstanding tasks on the operations queue. Apparently frame callbacks can - // only - // be posted from the UI thread and therefore we cannot schedule them directly from - // @Override + // animations and no outstanding tasks on the operations queue. Apparently frame + // callbacks can only be posted from the UI thread and therefore we cannot schedule + // them directly from other threads. Assertions.assertNotNull(mReactChoreographer) .postFrameCallback( ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mAnimatedFrameCallback); } catch (Exception ex) { - // TODO T57341690 remove this when T57341690 is resolved - FLog.e(ReactConstants.TAG, "Exception while executing animated frame callback.", ex); throw new RuntimeException(ex); } } @@ -246,7 +244,8 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec @Override public void onHostDestroy() { - // do nothing + // Is it possible for onHostDestroy to be called without a corresponding onHostPause? + clearFrameCallback(); } @Override @@ -254,6 +253,13 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec return NAME; } + /** + * Returns a {@link NativeAnimatedNodesManager}, either the existing instance or a new one. Will + * return null if and only if the {@link ReactApplicationContext} is also null. + * + * @return {@link NativeAnimatedNodesManager} + */ + @Nullable private NativeAnimatedNodesManager getNodesManager() { if (mNodesManager == null) { ReactApplicationContext reactApplicationContext = getReactApplicationContextIfActiveOrWarn(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java index 62cdb8a6cd..0a9e52b8f9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java @@ -582,16 +582,6 @@ public class CatalystInstanceImpl implements CatalystInstance { public NativeModule getNativeModule(String moduleName) { if (getTurboModuleRegistry() != null) { TurboModule turboModule = getTurboModuleRegistry().getModule(moduleName); - - if (ReactFeatureFlags.enableTurboModuleDebugLogs) { - // TODO(T46487253): Remove after task is closed - FLog.e( - ReactConstants.TAG, - "CatalystInstanceImpl.getNativeModule: TurboModule " - + moduleName - + (turboModule == null ? " not" : "") - + " found"); - } if (turboModule != null) { return (NativeModule) turboModule; } @@ -724,9 +714,6 @@ public class CatalystInstanceImpl implements CatalystInstance { } private void onNativeException(Exception e) { - // TODO T62192299: remove this after investigation - FLog.e(ReactConstants.TAG, "CatalystInstanceImpl caught native exception", e); - mNativeModuleCallExceptionHandler.handleException(e); mReactQueueConfiguration .getUIQueueThread() diff --git a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index c06d0e0c35..26025c3b4a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -23,9 +23,6 @@ public class ReactFeatureFlags { */ public static volatile boolean useTurboModules = false; - /** Should we output debug logs to debug the TurboModule infra? */ - public static volatile boolean enableTurboModuleDebugLogs = false; - /* * This feature flag enables logs for Fabric */ @@ -89,4 +86,7 @@ public class ReactFeatureFlags { /** Feature flag to configure initialization of Fabric surfaces. */ public static boolean enableFabricStartSurfaceWithLayoutMetrics = true; + + /** Feature flag to have FabricUIManager teardown stop all active surfaces. */ + public static boolean enableFabricStopAllSurfacesOnTeardown = false; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DisabledDevSupportManager.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DisabledDevSupportManager.java index 5c6331c99b..df0ca843ba 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DisabledDevSupportManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DisabledDevSupportManager.java @@ -9,7 +9,6 @@ package com.facebook.react.devsupport; import android.view.View; import androidx.annotation.Nullable; -import com.facebook.common.logging.FLog; import com.facebook.react.bridge.DefaultNativeModuleCallExceptionHandler; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReadableArray; @@ -158,9 +157,6 @@ public class DisabledDevSupportManager implements DevSupportManager { @Override public void handleException(Exception e) { - // TODO T62192299: remove this after investigation - FLog.e("DisabledDevSupportManager", "Caught exception", e); - mDefaultNativeModuleCallExceptionHandler.handleException(e); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java index d0abc11e6d..c88b867df2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java @@ -13,6 +13,7 @@ import com.facebook.jni.HybridData; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.JavaScriptContextHolder; import com.facebook.react.bridge.NativeMap; +import com.facebook.react.bridge.RuntimeExecutor; import com.facebook.react.bridge.queue.MessageQueueThread; import com.facebook.react.fabric.events.EventBeatManager; import com.facebook.react.uimanager.PixelUtil; @@ -35,6 +36,7 @@ public class Binding { private native void installFabricUIManager( long jsContextNativePointer, + RuntimeExecutor runtimeExecutor, Object uiManager, EventBeatManager eventBeatManager, MessageQueueThread jsMessageQueueThread, @@ -72,8 +74,10 @@ public class Binding { public native void driveCxxAnimations(); + // TODO (T67721598) Remove the jsContext param once we've migrated to using RuntimeExecutor public void register( @NonNull JavaScriptContextHolder jsContext, + @NonNull RuntimeExecutor runtimeExecutor, @NonNull FabricUIManager fabricUIManager, @NonNull EventBeatManager eventBeatManager, @NonNull MessageQueueThread jsMessageQueueThread, @@ -82,6 +86,7 @@ public class Binding { fabricUIManager.setBinding(this); installFabricUIManager( jsContext.get(), + runtimeExecutor, fabricUIManager, eventBeatManager, jsMessageQueueThread, diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java index 62e020c711..8b5b7263fc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java @@ -74,8 +74,10 @@ public class FabricJSIModuleProvider implements JSIModuleProvider { .getCatalystInstance() .getReactQueueConfiguration() .getJSQueueThread(); + binding.register( mJSContext, + mReactApplicationContext.getCatalystInstance().getRuntimeExecutor(), uiManager, eventBeatManager, jsMessageQueueThread, diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index b80ee9f25c..4c863b7020 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -244,6 +244,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener { @ThreadConfined(ANY) public void stopSurface(int surfaceID) { mBinding.stopSurface(surfaceID); + mReactContextForRootTag.remove(surfaceID); } @Override @@ -286,6 +287,15 @@ public class FabricUIManager implements UIManager, LifecycleEventListener { // memory immediately. mDispatchUIFrameCallback.stop(); + // Stop all attached surfaces + if (ReactFeatureFlags.enableFabricStopAllSurfacesOnTeardown) { + FLog.e(TAG, "stop all attached surfaces"); + for (int surfaceId : mReactContextForRootTag.keySet()) { + FLog.e(TAG, "stop attached surface: " + surfaceId); + stopSurface(surfaceId); + } + } + mBinding.unregister(); mBinding = null; @@ -421,8 +431,9 @@ public class FabricUIManager implements UIManager, LifecycleEventListener { @SuppressWarnings("unused") @AnyThread @ThreadConfined(ANY) - private MountItem createBatchMountItem(MountItem[] items, int size, int commitNumber) { - return new BatchMountItem(items, size, commitNumber); + private MountItem createBatchMountItem( + int rootTag, MountItem[] items, int size, int commitNumber) { + return new BatchMountItem(rootTag, items, size, commitNumber); } @DoNotStrip @@ -483,16 +494,21 @@ public class FabricUIManager implements UIManager, LifecycleEventListener { @ThreadConfined(UI) public void synchronouslyUpdateViewOnUIThread(int reactTag, @NonNull ReadableMap props) { UiThreadUtil.assertOnUiThread(); - long time = SystemClock.uptimeMillis(); + int commitNumber = mCurrentSynchronousCommitNumber++; + + // We are on the UI thread so this is safe to call. We try to flush any existing + // mount instructions that are queued. + tryDispatchMountItems(); + try { ReactMarker.logFabricMarker( ReactMarkerConstants.FABRIC_UPDATE_UI_MAIN_THREAD_START, null, commitNumber); if (ENABLE_FABRIC_LOGS) { FLog.d(TAG, "SynchronouslyUpdateViewOnUIThread for tag %d", reactTag); } - scheduleMountItem( - updatePropsMountItem(reactTag, props), commitNumber, time, 0, 0, 0, 0, 0, 0); + + updatePropsMountItem(reactTag, props).execute(mMountingManager); } catch (Exception ex) { // TODO T42943890: Fix animations in Fabric and remove this try/catch ReactSoftException.logSoftException( @@ -771,6 +787,22 @@ public class FabricUIManager implements UIManager, LifecycleEventListener { } } + // Make sure surface associated with this MountItem has been started, and not stopped. + // TODO T68118357: clean up this logic and simplify this method overall + if (mountItem instanceof BatchMountItem) { + BatchMountItem batchMountItem = (BatchMountItem) mountItem; + int rootTag = batchMountItem.getRootTag(); + if (mReactContextForRootTag.get(rootTag) == null) { + ReactSoftException.logSoftException( + TAG, + new ReactNoCrashSoftException( + "dispatchMountItems: skipping batched item: surface not available [" + + rootTag + + "]")); + continue; + } + } + // TODO: if early ViewCommand dispatch ships 100% as a feature, this can be removed. // This try/catch catches Retryable errors that can only be thrown by ViewCommands, which // won't be executed here in Early Dispatch mode. diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp index 025d035502..46a91c3776 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp @@ -73,10 +73,6 @@ std::shared_ptr Binding::getScheduler() { return scheduler_; } -LayoutAnimationDriver *Binding::getAnimationDriver() { - return (animationDriver_ ? animationDriver_.get() : nullptr); -} - void Binding::startSurface( jint surfaceId, jni::alias_ref moduleName, @@ -97,7 +93,7 @@ void Binding::startSurface( initialProps->consume(), {}, context, - getAnimationDriver()); + animationDriver_); } void Binding::startSurfaceWithConstraints( @@ -144,7 +140,7 @@ void Binding::startSurfaceWithConstraints( initialProps->consume(), constraints, context, - getAnimationDriver()); + animationDriver_); } void Binding::renderTemplateToSurface(jint surfaceId, jstring uiTemplate) { @@ -214,6 +210,7 @@ void Binding::setConstraints( void Binding::installFabricUIManager( jlong jsContextNativePointer, + jni::alias_ref runtimeExecutorHolder, jni::alias_ref javaUIManager, EventBeatManager *eventBeatManager, jni::alias_ref jsMessageQueueThread, @@ -247,15 +244,23 @@ void Binding::installFabricUIManager( auto sharedJSMessageQueueThread = std::make_shared(jsMessageQueueThread); - Runtime *runtime = (Runtime *)jsContextNativePointer; - RuntimeExecutor runtimeExecutor = - [runtime, sharedJSMessageQueueThread]( - std::function &&callback) { - sharedJSMessageQueueThread->runOnQueue( - [runtime, callback = std::move(callback)]() { - callback(*runtime); - }); - }; + bool useRuntimeExecutor = + config->getBool("react_fabric:use_shared_runtime_executor_android"); + + RuntimeExecutor runtimeExecutor; + if (useRuntimeExecutor) { + runtimeExecutor = runtimeExecutorHolder->cthis()->get(); + } else { + Runtime *runtime = (Runtime *)jsContextNativePointer; + runtimeExecutor = + [runtime, sharedJSMessageQueueThread]( + std::function &&callback) { + sharedJSMessageQueueThread->runOnQueue( + [runtime, callback = std::move(callback)]() { + callback(*runtime); + }); + }; + } // TODO: T31905686 Create synchronous Event Beat jni::global_ref localJavaUIManager = javaUIManager_; @@ -297,9 +302,10 @@ void Binding::installFabricUIManager( toolbox.asynchronousEventBeatFactory = asynchronousBeatFactory; if (enableLayoutAnimations_) { - animationDriver_ = std::make_unique(this); + animationDriver_ = std::make_shared(this); } - scheduler_ = std::make_shared(toolbox, getAnimationDriver(), this); + scheduler_ = std::make_shared( + toolbox, (animationDriver_ ? animationDriver_.get() : nullptr), this); } void Binding::uninstallFabricUIManager() { @@ -844,11 +850,15 @@ void Binding::schedulerDidFinishTransaction( static auto createMountItemsBatchContainer = jni::findClassStatic(UIManagerJavaDescriptor) ->getMethod( - jtypeArray, jint, jint)>( + jint, jtypeArray, jint, jint)>( "createBatchMountItem"); auto batch = createMountItemsBatchContainer( - localJavaUIManager, mountItemsArray.get(), position, commitNumber); + localJavaUIManager, + surfaceId, + mountItemsArray.get(), + position, + commitNumber); static auto scheduleMountItem = jni::findClassStatic(UIManagerJavaDescriptor) ->getMethod #include #include +#include #include #include #include @@ -50,6 +51,7 @@ class Binding : public jni::HybridClass, void installFabricUIManager( jlong jsContextNativePointer, + jni::alias_ref runtimeExecutorHolder, jni::alias_ref javaUIManager, EventBeatManager *eventBeatManager, jni::alias_ref jsMessageQueueThread, @@ -110,7 +112,7 @@ class Binding : public jni::HybridClass, virtual void onAnimationStarted() override; virtual void onAllAnimationsComplete() override; LayoutAnimationDriver *getAnimationDriver(); - std::unique_ptr animationDriver_; + std::shared_ptr animationDriver_; std::shared_ptr scheduler_; std::mutex schedulerMutex_; diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/BatchMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/BatchMountItem.java index 4588c7fb8f..85034aa043 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/BatchMountItem.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/BatchMountItem.java @@ -26,13 +26,14 @@ import com.facebook.systrace.Systrace; @DoNotStrip public class BatchMountItem implements MountItem { + private final int mRootTag; @NonNull private final MountItem[] mMountItems; private final int mSize; private final int mCommitNumber; - public BatchMountItem(MountItem[] items, int size, int commitNumber) { + public BatchMountItem(int rootTag, MountItem[] items, int size, int commitNumber) { if (items == null) { throw new NullPointerException(); } @@ -40,6 +41,7 @@ public class BatchMountItem implements MountItem { throw new IllegalArgumentException( "Invalid size received by parameter size: " + size + " items.size = " + items.length); } + mRootTag = rootTag; mMountItems = items; mSize = size; mCommitNumber = commitNumber; @@ -68,6 +70,10 @@ public class BatchMountItem implements MountItem { Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); } + public int getRootTag() { + return mRootTag; + } + @Override public String toString() { StringBuilder s = new StringBuilder(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/camera/CameraRollManager.java b/ReactAndroid/src/main/java/com/facebook/react/modules/camera/CameraRollManager.java index 05746f4f50..7220d67a96 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/camera/CameraRollManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/camera/CameraRollManager.java @@ -16,6 +16,7 @@ import android.media.MediaMetadataRetriever; import android.media.MediaScannerConnection; import android.net.Uri; import android.os.AsyncTask; +import android.os.Build; import android.os.Environment; import android.provider.MediaStore; import android.provider.MediaStore.Images; @@ -47,6 +48,7 @@ import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; // TODO #6015104: rename to something less iOSish @@ -68,22 +70,33 @@ public class CameraRollManager extends NativeCameraRollManagerSpec { private static final String ASSET_TYPE_VIDEOS = "Videos"; private static final String ASSET_TYPE_ALL = "All"; - private static final String[] PROJECTION = { - Images.Media._ID, - Images.Media.MIME_TYPE, - Images.Media.BUCKET_DISPLAY_NAME, - Images.Media.DATE_TAKEN, - MediaStore.MediaColumns.WIDTH, - MediaStore.MediaColumns.HEIGHT, - Images.Media.LONGITUDE, - Images.Media.LATITUDE, - MediaStore.MediaColumns.DATA - }; - private static final String SELECTION_BUCKET = Images.Media.BUCKET_DISPLAY_NAME + " = ?"; private static final String SELECTION_DATE_TAKEN = Images.Media.DATE_TAKEN + " < ?"; private static final String SELECTION_MEDIA_SIZE = Images.Media.SIZE + " < ?"; + private static final int IMAGES_MEDIA_LATITUDE_LONGITUDE_DEPRECATED_API_LEVEL = 29; + private static final String[] PROJECTION_LIST; + + static { + ArrayList projection_list = + new ArrayList<>( + Arrays.asList( + Images.Media._ID, + Images.Media.MIME_TYPE, + Images.Media.BUCKET_DISPLAY_NAME, + Images.Media.DATE_TAKEN, + MediaStore.MediaColumns.WIDTH, + MediaStore.MediaColumns.HEIGHT, + MediaStore.MediaColumns.DATA)); + if (Build.VERSION.SDK_INT < IMAGES_MEDIA_LATITUDE_LONGITUDE_DEPRECATED_API_LEVEL) { + projection_list.add(Images.Media.LATITUDE); + projection_list.add(Images.Media.LONGITUDE); + PROJECTION_LIST = projection_list.toArray(new String[0]); + } else { + PROJECTION_LIST = projection_list.toArray(new String[0]); + } + } + public CameraRollManager(ReactApplicationContext reactContext) { super(reactContext); } @@ -351,7 +364,7 @@ public class CameraRollManager extends NativeCameraRollManagerSpec { Cursor media = resolver.query( MediaStore.Files.getContentUri("external"), - PROJECTION, + PROJECTION_LIST, selection.toString(), selectionArgs.toArray(new String[selectionArgs.size()]), Images.Media.DATE_TAKEN @@ -413,7 +426,9 @@ public class CameraRollManager extends NativeCameraRollManagerSpec { resolver, media, node, idIndex, widthIndex, heightIndex, dataIndex, mimeTypeIndex); if (imageInfoSuccess) { putBasicNodeInfo(media, node, mimeTypeIndex, groupNameIndex, dateTakenIndex); - putLocationInfo(media, node, longitudeIndex, latitudeIndex); + if (Build.VERSION.SDK_INT < IMAGES_MEDIA_LATITUDE_LONGITUDE_DEPRECATED_API_LEVEL) { + putLocationInfo(media, node, longitudeIndex, latitudeIndex); + } edge.putMap("node", node); edges.pushMap(edge); diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManager.java b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManager.java index 6b01a20083..bf1db2e647 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManager.java @@ -19,7 +19,6 @@ import com.facebook.react.bridge.JSIModule; import com.facebook.react.bridge.JavaScriptContextHolder; import com.facebook.react.bridge.NativeModule; import com.facebook.react.common.ReactConstants; -import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder; import com.facebook.react.turbomodule.core.interfaces.TurboModule; import com.facebook.react.turbomodule.core.interfaces.TurboModuleRegistry; @@ -142,15 +141,6 @@ public class TurboModuleManager implements JSIModule, TurboModuleRegistry { /* * Always return null after cleanup has started, so that getModule(moduleName) returns null. */ - - if (ReactFeatureFlags.enableTurboModuleDebugLogs) { - // TODO(T46487253): Remove after task is closed - FLog.e( - ReactConstants.TAG, - "TurboModuleManager.getOrMaybeCreateTurboModuleHolder: Tried to require TurboModule " - + moduleName - + " after cleanup initiated"); - } return null; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.java index ab6d1739b0..92b4e414d2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.java @@ -104,8 +104,8 @@ public class DisplayMetricsHolder { } public static Map> getDisplayMetricsMap(double fontScale) { - Assertions.assertNotNull( - sWindowDisplayMetrics != null || sScreenDisplayMetrics != null, + Assertions.assertCondition( + sWindowDisplayMetrics != null && sScreenDisplayMetrics != null, "DisplayMetricsHolder must be initialized with initDisplayMetricsIfNotInitialized or initDisplayMetrics"); final Map> result = new HashMap<>(); result.put("windowPhysicalPixels", getPhysicalPixelsMap(sWindowDisplayMetrics, fontScale)); @@ -114,8 +114,8 @@ public class DisplayMetricsHolder { } public static WritableNativeMap getDisplayMetricsNativeMap(double fontScale) { - Assertions.assertNotNull( - sWindowDisplayMetrics != null || sScreenDisplayMetrics != null, + Assertions.assertCondition( + sWindowDisplayMetrics != null && sScreenDisplayMetrics != null, "DisplayMetricsHolder must be initialized with initDisplayMetricsIfNotInitialized or initDisplayMetrics"); final WritableNativeMap result = new WritableNativeMap(); result.putMap( diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java index 1cc148fe0d..ff5da0ccb6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java @@ -73,6 +73,10 @@ public class ReactSliderManager extends SimpleViewManager YogaMeasureMode heightMode) { if (!mMeasured) { SeekBar reactSlider = new ReactSlider(getThemedContext(), null, STYLE); + // reactSlider is used for measurements purposes, it is not necessary to set a + // StateListAnimator. + // It is not safe to access StateListAnimator from a background thread. + reactSlider.setStateListAnimator(null); final int spec = View.MeasureSpec.makeMeasureSpec( ViewGroup.LayoutParams.WRAP_CONTENT, View.MeasureSpec.UNSPECIFIED); diff --git a/ReactAndroid/src/main/jni/react/jni/JReactMarker.cpp b/ReactAndroid/src/main/jni/react/jni/JReactMarker.cpp index 0f7159f31e..2af23e9d96 100644 --- a/ReactAndroid/src/main/jni/react/jni/JReactMarker.cpp +++ b/ReactAndroid/src/main/jni/react/jni/JReactMarker.cpp @@ -41,16 +41,12 @@ void JReactMarker::logPerfMarker( const char *tag) { switch (markerId) { case ReactMarker::RUN_JS_BUNDLE_START: - LOG(ERROR) << "logMarker RUN_JS_BUNDLE_START"; // TODO T62192299: delete JReactMarker::logMarker("RUN_JS_BUNDLE_START", tag); break; case ReactMarker::RUN_JS_BUNDLE_STOP: - LOG(ERROR) << "logMarker RUN_JS_BUNDLE_END"; // TODO T62192299: delete JReactMarker::logMarker("RUN_JS_BUNDLE_END", tag); break; case ReactMarker::CREATE_REACT_CONTEXT_STOP: - LOG(ERROR) - << "logMarker CREATE_REACT_CONTEXT_END"; // TODO T62192299: delete JReactMarker::logMarker("CREATE_REACT_CONTEXT_END"); break; case ReactMarker::JS_BUNDLE_STRING_CONVERT_START: diff --git a/ReactCommon/cxxreact/BUCK b/ReactCommon/cxxreact/BUCK index 36d242b889..0db1caf436 100644 --- a/ReactCommon/cxxreact/BUCK +++ b/ReactCommon/cxxreact/BUCK @@ -149,6 +149,7 @@ rn_xplat_cxx_library( "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", + "//xplat/jsi:jsi", react_native_xplat_target("callinvoker:callinvoker"), react_native_xplat_target("jsinspector:jsinspector"), react_native_xplat_target("microprofiler:microprofiler"), diff --git a/ReactCommon/cxxreact/Instance.cpp b/ReactCommon/cxxreact/Instance.cpp index d5b4af5e51..2f2dc5d448 100644 --- a/ReactCommon/cxxreact/Instance.cpp +++ b/ReactCommon/cxxreact/Instance.cpp @@ -222,7 +222,11 @@ ModuleRegistry &Instance::getModuleRegistry() { } void Instance::handleMemoryPressure(int pressureLevel) { - nativeToJsBridge_->handleMemoryPressure(pressureLevel); + if (nativeToJsBridge_) { + // This class resets `nativeToJsBridge_` only in the destructor, + // hence a race is not possible there. + nativeToJsBridge_->handleMemoryPressure(pressureLevel); + } } std::shared_ptr Instance::getJSCallInvoker() { diff --git a/ReactCommon/cxxreact/NativeToJsBridge.cpp b/ReactCommon/cxxreact/NativeToJsBridge.cpp index 45651ac12d..58e99c9922 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.cpp +++ b/ReactCommon/cxxreact/NativeToJsBridge.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "Instance.h" @@ -337,19 +338,37 @@ std::shared_ptr NativeToJsBridge::getDecoratedNativeCallInvoker( } RuntimeExecutor NativeToJsBridge::getRuntimeExecutor() { - auto runtimeExecutor = - [this, isDestroyed = m_destroyed]( - std::function &&callback) { - if (*isDestroyed) { - return; + auto runtimeExecutor = [this, isDestroyed = m_destroyed]( + std::function + &&callback) { + if (*isDestroyed) { + return; + } + runOnExecutorQueue([callback = std::move(callback)](JSExecutor *executor) { + jsi::Runtime *runtime = (jsi::Runtime *)executor->getJavaScriptContext(); + try { + callback(*runtime); + } catch (jsi::JSError &originalError) { + auto errorUtils = runtime->global().getProperty(*runtime, "ErrorUtils"); + if (errorUtils.isUndefined() || !errorUtils.isObject() || + !errorUtils.getObject(*runtime).hasProperty( + *runtime, "reportFatalError")) { + // ErrorUtils was not set up. This probably means the bundle didn't + // load properly. + throw jsi::JSError( + *runtime, + "ErrorUtils is not set up properly. Something probably went wrong trying to load the JS bundle. Trying to report error " + + originalError.getMessage(), + originalError.getStack()); } - runOnExecutorQueue( - [callback = std::move(callback)](JSExecutor *executor) { - jsi::Runtime *runtime = - (jsi::Runtime *)executor->getJavaScriptContext(); - callback(*runtime); - }); - }; + // TODO(janzer): Rewrite this function to return the processed error + // instead of just reporting it through the native module + auto func = errorUtils.asObject(*runtime).getPropertyAsFunction( + *runtime, "reportFatalError"); + func.call(*runtime, originalError.value(), jsi::Value(true)); + } + }); + }; return runtimeExecutor; } diff --git a/ReactCommon/cxxreact/React-cxxreact.podspec b/ReactCommon/cxxreact/React-cxxreact.podspec index bea5ad31d3..095c987503 100644 --- a/ReactCommon/cxxreact/React-cxxreact.podspec +++ b/ReactCommon/cxxreact/React-cxxreact.podspec @@ -44,4 +44,5 @@ Pod::Spec.new do |s| s.dependency "React-callinvoker", version s.dependency "React-runtimeexecutor", version s.dependency "React-perflogger", version + s.dependency "React-jsi", version end diff --git a/ReactCommon/fabric/components/view/ViewProps.cpp b/ReactCommon/fabric/components/view/ViewProps.cpp index be9e8db543..f391c70949 100644 --- a/ReactCommon/fabric/components/view/ViewProps.cpp +++ b/ReactCommon/fabric/components/view/ViewProps.cpp @@ -92,7 +92,9 @@ ViewProps::ViewProps(ViewProps const &sourceProps, RawProps const &rawProps) rawProps, "collapsable", sourceProps.collapsable, - true)){}; + true)), + elevation( + convertRawProp(rawProps, "elevation", sourceProps.elevation, {})){}; #pragma mark - Convenience Methods diff --git a/ReactCommon/fabric/components/view/ViewProps.h b/ReactCommon/fabric/components/view/ViewProps.h index a14a3610ae..f1db61f0ff 100644 --- a/ReactCommon/fabric/components/view/ViewProps.h +++ b/ReactCommon/fabric/components/view/ViewProps.h @@ -59,6 +59,8 @@ class ViewProps : public YogaStylableProps, public AccessibilityProps { bool collapsable{true}; + int elevation{}; + #pragma mark - Convenience Methods BorderMetrics resolveBorderMetrics(LayoutMetrics const &layoutMetrics) const; diff --git a/ReactCommon/fabric/components/view/ViewShadowNode.cpp b/ReactCommon/fabric/components/view/ViewShadowNode.cpp index b503bb2986..024318662f 100644 --- a/ReactCommon/fabric/components/view/ViewShadowNode.cpp +++ b/ReactCommon/fabric/components/view/ViewShadowNode.cpp @@ -43,6 +43,7 @@ void ViewShadowNode::initialize() noexcept { viewProps.pointerEvents == PointerEventsMode::None || !viewProps.nativeId.empty() || viewProps.accessible || viewProps.opacity != 1.0 || viewProps.transform != Transform{} || + viewProps.elevation != 0 || (viewProps.zIndex != 0 && viewProps.yogaStyle.positionType() == YGPositionTypeAbsolute) || viewProps.getClipsContentToBounds() || diff --git a/ReactCommon/fabric/mounting/MountingCoordinator.cpp b/ReactCommon/fabric/mounting/MountingCoordinator.cpp index ad1552f156..ee6b7440fe 100644 --- a/ReactCommon/fabric/mounting/MountingCoordinator.cpp +++ b/ReactCommon/fabric/mounting/MountingCoordinator.cpp @@ -21,7 +21,7 @@ namespace react { MountingCoordinator::MountingCoordinator( ShadowTreeRevision baseRevision, - MountingOverrideDelegate *delegate) + std::weak_ptr delegate) : surfaceId_(baseRevision.getRootShadowNode().getSurfaceId()), baseRevision_(baseRevision), mountingOverrideDelegate_(delegate) { @@ -115,8 +115,10 @@ better::optional MountingCoordinator::pullTransaction() const { std::lock_guard lock(mutex_); - bool shouldOverridePullTransaction = mountingOverrideDelegate_ != nullptr && - mountingOverrideDelegate_->shouldOverridePullTransaction(); + auto mountingOverrideDelegate = mountingOverrideDelegate_.lock(); + + bool shouldOverridePullTransaction = mountingOverrideDelegate && + mountingOverrideDelegate->shouldOverridePullTransaction(); if (!shouldOverridePullTransaction && !lastRevision_.has_value()) { return {}; @@ -143,7 +145,7 @@ better::optional MountingCoordinator::pullTransaction() // even if there's no `lastRevision_`. Consider cases of animation frames // in between React tree updates. if (shouldOverridePullTransaction) { - transaction = mountingOverrideDelegate_->pullTransaction( + transaction = mountingOverrideDelegate->pullTransaction( surfaceId_, number_, telemetry, std::move(diffMutations)); } else if (lastRevision_.hasValue()) { transaction = MountingTransaction{ diff --git a/ReactCommon/fabric/mounting/MountingCoordinator.h b/ReactCommon/fabric/mounting/MountingCoordinator.h index 6976f35f48..556258ef2e 100644 --- a/ReactCommon/fabric/mounting/MountingCoordinator.h +++ b/ReactCommon/fabric/mounting/MountingCoordinator.h @@ -40,7 +40,7 @@ class MountingCoordinator final { */ MountingCoordinator( ShadowTreeRevision baseRevision, - MountingOverrideDelegate *delegate); + std::weak_ptr delegate); /* * Returns the id of the surface that the coordinator belongs to. @@ -102,7 +102,7 @@ class MountingCoordinator final { mutable better::optional lastRevision_{}; mutable MountingTransaction::Number number_{0}; mutable std::condition_variable signal_; - mutable MountingOverrideDelegate *mountingOverrideDelegate_{nullptr}; + std::weak_ptr mountingOverrideDelegate_; #ifdef RN_SHADOW_TREE_INTROSPECTION void validateTransactionAgainstStubViewTree( diff --git a/ReactCommon/fabric/mounting/ShadowTree.cpp b/ReactCommon/fabric/mounting/ShadowTree.cpp index d6a40be917..a834310e1d 100644 --- a/ReactCommon/fabric/mounting/ShadowTree.cpp +++ b/ReactCommon/fabric/mounting/ShadowTree.cpp @@ -222,7 +222,7 @@ ShadowTree::ShadowTree( LayoutContext const &layoutContext, RootComponentDescriptor const &rootComponentDescriptor, ShadowTreeDelegate const &delegate, - MountingOverrideDelegate *mountingOverrideDelegate) + std::weak_ptr mountingOverrideDelegate) : surfaceId_(surfaceId), delegate_(delegate) { const auto noopEventEmitter = std::make_shared( nullptr, -1, std::shared_ptr()); diff --git a/ReactCommon/fabric/mounting/ShadowTree.h b/ReactCommon/fabric/mounting/ShadowTree.h index a4606ba9a8..5090aeafd7 100644 --- a/ReactCommon/fabric/mounting/ShadowTree.h +++ b/ReactCommon/fabric/mounting/ShadowTree.h @@ -40,7 +40,7 @@ class ShadowTree final { LayoutContext const &layoutContext, RootComponentDescriptor const &rootComponentDescriptor, ShadowTreeDelegate const &delegate, - MountingOverrideDelegate *mountingOverrideDelegate); + std::weak_ptr mountingOverrideDelegate); ~ShadowTree(); diff --git a/ReactCommon/fabric/mounting/tests/StateReconciliationTest.cpp b/ReactCommon/fabric/mounting/tests/StateReconciliationTest.cpp index 665f18bcf6..eb6129f5bf 100644 --- a/ReactCommon/fabric/mounting/tests/StateReconciliationTest.cpp +++ b/ReactCommon/fabric/mounting/tests/StateReconciliationTest.cpp @@ -104,7 +104,7 @@ TEST(StateReconciliationTest, testStateReconciliation) { LayoutContext{}, rootComponentDescriptor, shadowTreeDelegate, - nullptr}; + {}}; shadowTree.commit( [&](RootShadowNode::Shared const &oldRootShadowNode) { diff --git a/ReactCommon/fabric/scheduler/Scheduler.cpp b/ReactCommon/fabric/scheduler/Scheduler.cpp index d4dafd716b..14a4f77086 100644 --- a/ReactCommon/fabric/scheduler/Scheduler.cpp +++ b/ReactCommon/fabric/scheduler/Scheduler.cpp @@ -127,6 +127,7 @@ Scheduler::~Scheduler() { // The thread-safety of this operation is guaranteed by this requirement. uiManager_->setDelegate(nullptr); + uiManager_->setAnimationDelegate(nullptr); // Then, let's verify that the requirement was satisfied. auto surfaceIds = std::vector{}; @@ -173,7 +174,8 @@ void Scheduler::startSurface( const folly::dynamic &initialProps, const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext, - MountingOverrideDelegate *mountingOverrideDelegate) const { + std::weak_ptr mountingOverrideDelegate) + const { SystraceSection s("Scheduler::startSurface"); auto shadowTree = std::make_unique( diff --git a/ReactCommon/fabric/scheduler/Scheduler.h b/ReactCommon/fabric/scheduler/Scheduler.h index 9ee114ec21..2693b82193 100644 --- a/ReactCommon/fabric/scheduler/Scheduler.h +++ b/ReactCommon/fabric/scheduler/Scheduler.h @@ -46,7 +46,8 @@ class Scheduler final : public UIManagerDelegate { const folly::dynamic &initialProps, const LayoutConstraints &layoutConstraints = {}, const LayoutContext &layoutContext = {}, - MountingOverrideDelegate *mountingOverrideDelegate = nullptr) const; + std::weak_ptr mountingOverrideDelegate = + {}) const; void renderTemplateToSurface( SurfaceId surfaceId, diff --git a/ReactCommon/fabric/uimanager/UIManager.cpp b/ReactCommon/fabric/uimanager/UIManager.cpp index b4910cee67..f7172002c4 100644 --- a/ReactCommon/fabric/uimanager/UIManager.cpp +++ b/ReactCommon/fabric/uimanager/UIManager.cpp @@ -318,8 +318,7 @@ void UIManager::shadowTreeDidFinishTransaction( #pragma mark - UIManagerAnimationDelegate -void UIManager::setAnimationDelegate( - UIManagerAnimationDelegate *delegate) const { +void UIManager::setAnimationDelegate(UIManagerAnimationDelegate *delegate) { animationDelegate_ = delegate; } diff --git a/ReactCommon/fabric/uimanager/UIManager.h b/ReactCommon/fabric/uimanager/UIManager.h index 543bf97cfa..ab6fdbcca6 100644 --- a/ReactCommon/fabric/uimanager/UIManager.h +++ b/ReactCommon/fabric/uimanager/UIManager.h @@ -46,7 +46,7 @@ class UIManager final : public ShadowTreeDelegate { * The delegate is stored as a raw pointer, so the owner must null * the pointer before being destroyed. */ - void setAnimationDelegate(UIManagerAnimationDelegate *delegate) const; + void setAnimationDelegate(UIManagerAnimationDelegate *delegate); void animationTick(); @@ -140,7 +140,7 @@ class UIManager final : public ShadowTreeDelegate { SharedComponentDescriptorRegistry componentDescriptorRegistry_; UIManagerDelegate *delegate_; - mutable UIManagerAnimationDelegate *animationDelegate_{nullptr}; + UIManagerAnimationDelegate *animationDelegate_{nullptr}; UIManagerBinding *uiManagerBinding_; ShadowTreeRegistry shadowTreeRegistry_{}; }; diff --git a/ReactCommon/jsi/jsi/jsi.cpp b/ReactCommon/jsi/jsi/jsi.cpp index 388f122c17..e4a7e431fc 100644 --- a/ReactCommon/jsi/jsi/jsi.cpp +++ b/ReactCommon/jsi/jsi/jsi.cpp @@ -401,32 +401,63 @@ JSError::JSError(std::string what, Runtime& rt, Value&& value) } void JSError::setValue(Runtime& rt, Value&& value) { - value_ = std::make_shared(std::move(value)); + value_ = std::make_shared(std::move(value)); try { if ((message_.empty() || stack_.empty()) && value_->isObject()) { auto obj = value_->getObject(rt); if (message_.empty()) { - jsi::Value message = obj.getProperty(rt, "message"); - if (!message.isUndefined()) { - message_ = - callGlobalFunction(rt, "String", message).getString(rt).utf8(rt); + try { + Value message = obj.getProperty(rt, "message"); + if (!message.isUndefined() && !message.isString()) { + message = callGlobalFunction(rt, "String", message); + } + if (message.isString()) { + message_ = message.getString(rt).utf8(rt); + } else if (!message.isUndefined()) { + message_ = "String(e.message) is a " + kindToString(message, &rt); + } + } catch (const std::exception& ex) { + message_ = std::string("[Exception while creating message string: ") + + ex.what() + "]"; } } if (stack_.empty()) { - jsi::Value stack = obj.getProperty(rt, "stack"); - if (!stack.isUndefined()) { - stack_ = - callGlobalFunction(rt, "String", stack).getString(rt).utf8(rt); + try { + Value stack = obj.getProperty(rt, "stack"); + if (!stack.isUndefined() && !stack.isString()) { + stack = callGlobalFunction(rt, "String", stack); + } + if (stack.isString()) { + stack_ = stack.getString(rt).utf8(rt); + } else if (!stack.isUndefined()) { + stack_ = "String(e.stack) is a " + kindToString(stack, &rt); + } + } catch (const std::exception& ex) { + message_ = std::string("[Exception while creating stack string: ") + + ex.what() + "]"; } } } if (message_.empty()) { - message_ = - callGlobalFunction(rt, "String", *value_).getString(rt).utf8(rt); + try { + if (value_->isString()) { + message_ = value_->getString(rt).utf8(rt); + } else { + Value message = callGlobalFunction(rt, "String", *value_); + if (message.isString()) { + message_ = message.getString(rt).utf8(rt); + } else { + message_ = "String(e) is a " + kindToString(message, &rt); + } + } + } catch (const std::exception& ex) { + message_ = std::string("[Exception while creating message string: ") + + ex.what() + "]"; + } } if (stack_.empty()) { @@ -436,13 +467,6 @@ void JSError::setValue(Runtime& rt, Value&& value) { if (what_.empty()) { what_ = message_ + "\n\n" + stack_; } - } catch (const std::exception& ex) { - message_ = std::string("[Exception while creating message string: ") + - ex.what() + "]"; - stack_ = std::string("Exception while creating stack string: ") + - ex.what() + "]"; - what_ = - std::string("Exception while getting value fields: ") + ex.what() + "]"; } catch (...) { message_ = "[Exception caught creating message string]"; stack_ = "[Exception caught creating stack string]"; diff --git a/ReactCommon/jsi/jsi/test/testlib.cpp b/ReactCommon/jsi/jsi/test/testlib.cpp index a8573d6ebb..996c2cb614 100644 --- a/ReactCommon/jsi/jsi/test/testlib.cpp +++ b/ReactCommon/jsi/jsi/test/testlib.cpp @@ -981,19 +981,6 @@ TEST_P(JSITest, JSErrorsCanBeConstructedWithStack) { } TEST_P(JSITest, JSErrorDoesNotInfinitelyRecurse) { - Value globalString = rt.global().getProperty(rt, "String"); - rt.global().setProperty(rt, "String", Value::undefined()); - try { - eval("throw Error('whoops')"); - FAIL() << "expected exception"; - } catch (const JSError& ex) { - EXPECT_EQ( - ex.getMessage(), - "[Exception while creating message string: callGlobalFunction: " - "JS global property 'String' is undefined, expected a Function]"); - } - rt.global().setProperty(rt, "String", globalString); - Value globalError = rt.global().getProperty(rt, "Error"); rt.global().setProperty(rt, "Error", Value::undefined()); try { @@ -1272,6 +1259,70 @@ TEST_P(JSITest, SymbolTest) { EXPECT_FALSE(Value::strictEquals(rt, eval("Symbol('a')"), eval("'a'"))); } +TEST_P(JSITest, JSErrorTest) { + // JSError creation can lead to further errors. Make sure these + // cases are handled and don't cause weird crashes or other issues. + // + // Getting message property can throw + + EXPECT_THROW( + eval("var GetMessageThrows = {get message() { throw Error('ex'); }};" + "throw GetMessageThrows;"), + JSIException); + + EXPECT_THROW( + eval("var GetMessageThrows = {get message() { throw GetMessageThrows; }};" + "throw GetMessageThrows;"), + JSIException); + + // Converting exception message to String can throw + + EXPECT_THROW( + eval( + "Object.defineProperty(" + " globalThis, 'String', {configurable:true, get() { var e = Error(); e.message = 23; throw e; }});" + "var e = Error();" + "e.message = 17;" + "throw e;"), + JSIException); + + EXPECT_THROW( + eval( + "var e = Error();" + "Object.defineProperty(" + " e, 'message', {configurable:true, get() { throw Error('getter'); }});" + "throw e;"), + JSIException); + + EXPECT_THROW( + eval("var e = Error();" + "String = function() { throw Error('ctor'); };" + "throw e;"), + JSIException); + + // Converting an exception message to String can return a non-String + + EXPECT_THROW( + eval("String = function() { return 42; };" + "var e = Error();" + "e.message = 17;" + "throw e;"), + JSIException); + + // Exception can be non-Object + + EXPECT_THROW(eval("throw 17;"), JSIException); + + EXPECT_THROW(eval("throw undefined;"), JSIException); + + // Converting exception with no message or stack property to String can throw + + EXPECT_THROW( + eval("var e = {toString() { throw new Error('errstr'); }};" + "throw e;"), + JSIException); +} + //---------------------------------------------------------------------- // Test that multiple levels of delegation in DecoratedHostObjects works. diff --git a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.h b/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.h index 42dfd28592..abf072a2b7 100644 --- a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.h +++ b/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.h @@ -40,7 +40,6 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { id instance; std::shared_ptr jsInvoker; std::shared_ptr nativeInvoker; - // Does the NativeModule dispatch async methods to the JS thread? bool isSyncModule; }; @@ -61,16 +60,20 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { void setMethodArgConversionSelector(NSString *methodName, int argIndex, NSString *fnName); private: + // Does the NativeModule dispatch async methods to the JS thread? + const bool isSyncModule_; + /** * TODO(ramanpreet): * Investigate an optimization that'll let us get rid of this NSMutableDictionary. */ NSMutableDictionary *methodArgConversionSelectors_; NSDictionary *> *methodArgumentTypeNames_; - const bool isSyncModule_; - bool isMethodSync(TurboModuleMethodValueKind returnType); - NSString *getArgumentTypeName(NSString *methodName, int argIndex); + bool isMethodSync(TurboModuleMethodValueKind returnType); + BOOL hasMethodArgConversionSelector(NSString *methodName, int argIndex); + SEL getMethodArgConversionSelector(NSString *methodName, int argIndex); + NSString *getArgumentTypeName(NSString *methodName, int argIndex); NSInvocation *getMethodInvocation( jsi::Runtime &runtime, TurboModuleMethodValueKind returnType, @@ -86,9 +89,6 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { NSInvocation *inv, NSMutableArray *retainedObjectsForInvocation); - BOOL hasMethodArgConversionSelector(NSString *methodName, int argIndex); - SEL getMethodArgConversionSelector(NSString *methodName, int argIndex); - using PromiseInvocationBlock = void (^)(RCTPromiseResolveBlock resolveWrapper, RCTPromiseRejectBlock rejectWrapper); jsi::Value createPromise(jsi::Runtime &runtime, std::shared_ptr jsInvoker, PromiseInvocationBlock invoke); diff --git a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.mm b/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.mm index b44010d030..4e5cdc8a4e 100644 --- a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.mm +++ b/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.mm @@ -361,7 +361,7 @@ jsi::Value ObjCTurboModule::performMethodInvocation( }; if (wasMethodSync) { - nativeInvoker_->invokeSync([block]() -> void { block(); }); + block(); } else { asyncCallCounter = getUniqueId(); TurboModulePerfLogger::asyncMethodCallDispatch(moduleName, methodName); diff --git a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.h b/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.h index 87c0c96f07..7edc90ca38 100644 --- a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.h +++ b/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.h @@ -11,6 +11,8 @@ #import "RCTTurboModule.h" +#import + @protocol RCTTurboModuleManagerDelegate // TODO: Move to xplat codegen. @@ -45,7 +47,7 @@ delegate:(id)delegate jsInvoker:(std::shared_ptr)jsInvoker; -- (void)installJSBindingWithRuntime:(facebook::jsi::Runtime *)runtime; +- (void)installJSBindingWithRuntimeExecutor:(facebook::react::RuntimeExecutor)runtimeExecutor; - (void)invalidate; diff --git a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm b/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm index accd2a2fd4..ce61d802a7 100644 --- a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm +++ b/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm @@ -21,6 +21,7 @@ #import #import #import +#import #import #import #import @@ -147,7 +148,6 @@ static Class getFallbackClassFromName(const char *name) } @implementation RCTTurboModuleManager { - jsi::Runtime *_runtime; std::shared_ptr _jsInvoker; __weak id _delegate; __weak RCTBridge *_bridge; @@ -640,18 +640,15 @@ static Class getFallbackClassFromName(const char *name) return requiresMainQueueSetup; } -- (void)installJSBindingWithRuntime:(jsi::Runtime *)runtime +- (void)installJSBindingWithRuntimeExecutor:(facebook::react::RuntimeExecutor)runtimeExecutor { - _runtime = runtime; - - if (!_runtime) { + if (!runtimeExecutor) { // jsi::Runtime doesn't exist when attached to Chrome debugger. return; } __weak __typeof(self) weakSelf = self; - - TurboModuleBinding::install(*_runtime, [weakSelf](const std::string &name) -> std::shared_ptr { + auto turboModuleProvider = [weakSelf](const std::string &name) -> std::shared_ptr { if (!weakSelf) { return nullptr; } @@ -686,6 +683,10 @@ static Class getFallbackClassFromName(const char *name) } return turboModule; + }; + + runtimeExecutor([turboModuleProvider = std::move(turboModuleProvider)](jsi::Runtime &runtime) { + react::TurboModuleBinding::install(runtime, std::move(turboModuleProvider)); }); } diff --git a/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboModule.mm b/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboModule.mm index 5ecd7aefda..8439949dfa 100644 --- a/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboModule.mm +++ b/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboModule.mm @@ -8,6 +8,7 @@ #import "RCTSampleTurboModule.h" #import // TODO(macOS GH#774) +#import using namespace facebook::react; @@ -45,19 +46,24 @@ RCT_EXPORT_MODULE() - (NSDictionary *)getConstants { + __block NSDictionary *constants; + RCTUnsafeExecuteOnMainQueueSync(^{ #if !TARGET_OS_OSX // TODO(macOS GH#774) - UIScreen *mainScreen = UIScreen.mainScreen; - CGSize screenSize = mainScreen.bounds.size; + UIScreen *mainScreen = UIScreen.mainScreen; + CGSize screenSize = mainScreen.bounds.size; #else // [TODO(macOS GH#774) - NSScreen *mainScreen = NSScreen.mainScreen; - CGSize screenSize = mainScreen.frame.size; + NSScreen *mainScreen = NSScreen.mainScreen; + CGSize screenSize = mainScreen.frame.size; #endif // ]TODO(macOS GH#774) - return @{ - @"const1" : @YES, - @"const2" : @(screenSize.width), - @"const3" : @"something", - }; + constants = @{ + @"const1" : @YES, + @"const2" : @(screenSize.width), + @"const3" : @"something", + }; + }); + + return constants; } // TODO: Remove once fully migrated to TurboModule. diff --git a/package.json b/package.json index e6042c7e61..368655dfb4 100644 --- a/package.json +++ b/package.json @@ -144,7 +144,7 @@ "eslint-plugin-react-hooks": "^3.0.0", "eslint-plugin-react-native": "3.8.1", "eslint-plugin-relay": "1.7.1", - "flow-bin": "^0.125.1", + "flow-bin": "^0.126.1", "flow-remove-types": "1.2.3", "hermes-engine-darwin": "~0.5.0", "jest": "^26.0.1", diff --git a/template/_flowconfig b/template/_flowconfig index 24b28ccc0e..b3d4c2fbf0 100644 --- a/template/_flowconfig +++ b/template/_flowconfig @@ -69,4 +69,4 @@ untyped-import untyped-type-import [version] -^0.125.0 +^0.126.1 diff --git a/yarn.lock b/yarn.lock index 1d21951945..7dbddb4061 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1950,6 +1950,14 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + caller-callsite@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" @@ -2514,7 +2522,7 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" -define-properties@^1.1.2: +define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== @@ -2694,6 +2702,29 @@ errorhandler@^1.5.0: accepts "~1.3.7" escape-html "~1.0.3" +es-abstract@^1.10.0: + version "1.18.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.5.tgz#9b10de7d4c206a3581fd5b2124233e04db49ae19" + integrity sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + is-callable "^1.2.3" + is-negative-zero "^2.0.1" + is-regex "^1.1.3" + is-string "^1.0.6" + object-inspect "^1.11.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.1" + es-abstract@^1.11.0: version "1.13.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" @@ -2726,6 +2757,15 @@ es-to-primitive@^1.1.1, es-to-primitive@^1.2.0: is-date-object "^1.0.1" is-symbol "^1.0.2" +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -3279,10 +3319,10 @@ flat-cache@^1.2.1: rimraf "~2.6.2" write "^0.2.1" -flow-bin@^0.125.1: - version "0.125.1" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.125.1.tgz#7edbc71e7dc39ddef18086ef75c714bbf1c5917f" - integrity sha512-jEury9NTXylxQEOAXLWEE945BjBwYcMwwKVnb+5XORNwMQE7i5hQYF0ysYfsaaYOa7rW/U16rHBfwLuaZfWV7A== +flow-bin@^0.126.1: + version "0.126.1" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.126.1.tgz#2726595e1891dc35b379b5994627432df4ead52c" + integrity sha512-RI05x7rVzruRVJQN3M4vLEjZMwUHJKhGz9FmL8HN7WiSo66/131EyJS6Vo8PkKyM2pgT9GRWfGP/tXlqS54XUg== flow-parser@0.*: version "0.89.0" @@ -3419,6 +3459,15 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-port@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/get-port/-/get-port-2.1.0.tgz#8783f9dcebd1eea495a334e1a6a251e78887ab1a" @@ -3560,6 +3609,11 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" +has-bigints@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -3575,6 +3629,18 @@ has-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= +has-symbols@^1.0.1, has-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -3776,6 +3842,15 @@ inquirer@^5.2.0: strip-ansi "^4.0.0" through "^2.3.6" +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + interpret@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" @@ -3817,6 +3892,21 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -3827,6 +3917,11 @@ is-callable@^1.1.3, is-callable@^1.1.4: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-callable@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -3910,6 +4005,18 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.0.0.tgz#038c31b774709641bda678b1f06a4e3227c10b3e" integrity sha512-elzyIdM7iKoFHzcrndIqjYomImhxrFRnGP3galODoII4TB9gI7mZ+FnlLQmmjf27SxHS2gKEeyhX5/+YRS6H9g== +is-negative-zero@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== + +is-number-object@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" + integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== + dependencies: + has-tostringtag "^1.0.0" + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -3946,6 +4053,14 @@ is-regex@^1.0.4: dependencies: has "^1.0.1" +is-regex@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + is-resolvable@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" @@ -3961,6 +4076,13 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== +is-string@^1.0.5, is-string@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + is-symbol@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" @@ -3968,6 +4090,13 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.0" +is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -5671,7 +5800,12 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-keys@^1.0.11: +object-inspect@^1.11.0, object-inspect@^1.9.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" + integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== + +object-keys@^1.0.11, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -5698,6 +5832,16 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" +object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + object.fromentries@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.0.tgz#49a543d92151f8277b3ac9600f1e930b189d30ab" @@ -6348,6 +6492,14 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexp.prototype.flags@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" + integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + regexpp@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" @@ -6809,6 +6961,15 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" @@ -7098,6 +7259,22 @@ string.prototype.matchall@^2.0.0: has-symbols "^1.0.0" regexp.prototype.flags "^1.2.0" +string.prototype.trimend@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string.prototype.trimstart@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -7487,6 +7664,16 @@ ultron@~1.1.0: resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== +unbox-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" + integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== + dependencies: + function-bind "^1.1.1" + has-bigints "^1.0.1" + has-symbols "^1.0.2" + which-boxed-primitive "^1.0.2" + unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" @@ -7695,6 +7882,17 @@ whatwg-url@^8.0.0: tr46 "^2.0.0" webidl-conversions "^5.0.0" +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"