diff --git a/.ado/templates/apple-job-javascript.yml b/.ado/templates/apple-job-javascript.yml index ccdf9a3ce1f2c8..2568873ba8f318 100644 --- a/.ado/templates/apple-job-javascript.yml +++ b/.ado/templates/apple-job-javascript.yml @@ -12,10 +12,6 @@ steps: slice_name: ${{ parameters.slice_name }} xcode_version: ${{ parameters.xcode_version }} - - template: apple-droid-node-patching.yml - parameters: - apply_office_patches: $(apply_office_patches) - - script: 'yarn install' displayName: 'yarn install' diff --git a/.ado/templates/apple-job-react-native.yml b/.ado/templates/apple-job-react-native.yml index c74069067a08e4..b0ece761841b4f 100644 --- a/.ado/templates/apple-job-react-native.yml +++ b/.ado/templates/apple-job-react-native.yml @@ -24,10 +24,6 @@ steps: slice_name: ${{ parameters.slice_name }} xcode_version: ${{ parameters.xcode_version }} - - template: apple-droid-node-patching.yml - parameters: - apply_office_patches: $(apply_office_patches) - - task: CmdLine@2 displayName: yarn install inputs: diff --git a/.eslintignore b/.eslintignore index 479b10a7655330..a2034a6d58600b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -14,3 +14,4 @@ pr-inactivity-bookmarklet.js question-bookmarklet.js bots/node_modules android-patches/ +packages/react-native-codegen/lib diff --git a/.flowconfig b/.flowconfig index 4f2c3a82108575..4af17e66aefe84 100644 --- a/.flowconfig +++ b/.flowconfig @@ -90,4 +90,4 @@ untyped-import untyped-type-import [version] -^0.123.0 +^0.124.0 diff --git a/.flowconfig.android b/.flowconfig.android index 4094bb40f10b78..db4bff3b3cfbc9 100644 --- a/.flowconfig.android +++ b/.flowconfig.android @@ -93,4 +93,4 @@ untyped-import untyped-type-import [version] -^0.123.0 +^0.124.0 diff --git a/.flowconfig.macos b/.flowconfig.macos index f681b53b53182d..9cf5a7d0dcb5bd 100644 --- a/.flowconfig.macos +++ b/.flowconfig.macos @@ -89,4 +89,4 @@ untyped-import untyped-type-import [version] -^0.123.0 +^0.124.0 diff --git a/.gitignore b/.gitignore index b316422451ca77..4459b963e4d744 100644 --- a/.gitignore +++ b/.gitignore @@ -102,9 +102,14 @@ RNTester/Pods/* !RNTester/Pods/__offline_mirrors # react-native-codegen +/packages/react-native-codegen/lib /ReactCommon/fabric/components/rncore/ +/schema-native-modules.json /schema-rncore.json # Visual studio .vscode .vs + +# Android memory profiler files +*.hprof diff --git a/Libraries/ART/ARTGroup.m b/Libraries/ART/ARTGroup.m index 692d03035bcfcb..8a863f74c2a6c0 100644 --- a/Libraries/ART/ARTGroup.m +++ b/Libraries/ART/ARTGroup.m @@ -11,13 +11,19 @@ @implementation ARTGroup - (void)renderLayerTo:(CGContextRef)context { - if (!CGRectIsEmpty(self.clipping)) { CGContextClipToRect(context, self.clipping); } - for (ARTNode *node in self.subviews) { - [node renderTo:context]; + for (RCTPlatformView *subview in self.subviews) { // TODO(macOS GH#774) + if ([subview respondsToSelector:@selector(renderTo:)]) { + [(ARTNode *)subview renderTo:context]; + } else { + // This is needed for legacy interop layer. Legacy interop layer + // is superview of the view that it is bridging, that's why we need + // to grab its first subview. + [(ARTNode *)subview.subviews.firstObject renderTo:context]; + } } } diff --git a/Libraries/ART/ARTNode.m b/Libraries/ART/ARTNode.m index f94e87c8e9c85c..9b96d16bcc1938 100644 --- a/Libraries/ART/ARTNode.m +++ b/Libraries/ART/ARTNode.m @@ -43,8 +43,10 @@ - (void)setTransform:(CGAffineTransform)transform - (void)invalidate { - id container = (id)self.superview; - [container invalidate]; + if ([self.superview respondsToSelector:@selector(invalidate)]) { + id container = (id)self.superview; + [container invalidate]; + } } - (void)renderTo:(CGContextRef)context diff --git a/Libraries/ART/ARTSurfaceView.m b/Libraries/ART/ARTSurfaceView.m index 2e557b948103fa..92c8836b57ceb0 100644 --- a/Libraries/ART/ARTSurfaceView.m +++ b/Libraries/ART/ARTSurfaceView.m @@ -49,8 +49,15 @@ - (void)drawRect:(CGRect)rect { [super drawRect:rect]; CGContextRef context = UIGraphicsGetCurrentContext(); - for (ARTNode *node in self.subviews) { - [node renderTo:context]; + for (RCTPlatformView *subview in self.subviews) { + if ([subview respondsToSelector:@selector(renderTo:)]) { + [(ARTNode *)subview renderTo:context]; + } else { + // This is needed for legacy interop layer. Legacy interop layer + // is superview of the view that it is bridging, that's why we need + // to grab its first subview. + [(ARTNode *)subview.subviews.firstObject renderTo:context]; + } } } diff --git a/Libraries/Animated/src/Animated.js b/Libraries/Animated/src/Animated.js index 450fc1c0264f13..0891d75a3f3649 100644 --- a/Libraries/Animated/src/Animated.js +++ b/Libraries/Animated/src/Animated.js @@ -11,38 +11,37 @@ 'use strict'; import Platform from '../../Utilities/Platform'; -const View = require('../../Components/View/View'); -const React = require('react'); -import type {AnimatedComponentType} from './createAnimatedComponent'; +import typeof AnimatedFlatList from './components/AnimatedFlatList'; +import typeof AnimatedImage from './components/AnimatedImage'; +import typeof AnimatedScrollView from './components/AnimatedScrollView'; +import typeof AnimatedSectionList from './components/AnimatedSectionList'; +import typeof AnimatedText from './components/AnimatedText'; +import typeof AnimatedView from './components/AnimatedView'; const AnimatedMock = require('./AnimatedMock'); const AnimatedImplementation = require('./AnimatedImplementation'); -//TODO(T57411659): Remove the bridgeless check when Animated perf regressions are fixed. -const Animated = ((Platform.isTesting || global.RN$Bridgeless +const Animated = ((Platform.isTesting ? AnimatedMock : AnimatedImplementation): typeof AnimatedMock); module.exports = { - get FlatList(): any { + get FlatList(): AnimatedFlatList { return require('./components/AnimatedFlatList'); }, - get Image(): any { + get Image(): AnimatedImage { return require('./components/AnimatedImage'); }, - get ScrollView(): any { + get ScrollView(): AnimatedScrollView { return require('./components/AnimatedScrollView'); }, - get SectionList(): any { + get SectionList(): AnimatedSectionList { return require('./components/AnimatedSectionList'); }, - get Text(): any { + get Text(): AnimatedText { return require('./components/AnimatedText'); }, - get View(): AnimatedComponentType< - React.ElementConfig, - React.ElementRef, - > { + get View(): AnimatedView { return require('./components/AnimatedView'); }, ...Animated, diff --git a/Libraries/Components/DatePicker/RCTDatePickerNativeComponent.js b/Libraries/Components/DatePicker/RCTDatePickerNativeComponent.js index b569ae2bea5515..99e5d92c051e17 100644 --- a/Libraries/Components/DatePicker/RCTDatePickerNativeComponent.js +++ b/Libraries/Components/DatePicker/RCTDatePickerNativeComponent.js @@ -56,5 +56,5 @@ export const Commands: NativeCommands = codegenNativeCommands({ export default (codegenNativeComponent('DatePicker', { paperComponentName: 'RCTDatePicker', - excludedPlatform: 'android', + excludedPlatforms: ['android'], }): HostComponent); diff --git a/Libraries/Components/RefreshControl/PullToRefreshViewNativeComponent.js b/Libraries/Components/RefreshControl/PullToRefreshViewNativeComponent.js index adf8ba966db1bf..7f97db35b6120f 100644 --- a/Libraries/Components/RefreshControl/PullToRefreshViewNativeComponent.js +++ b/Libraries/Components/RefreshControl/PullToRefreshViewNativeComponent.js @@ -61,5 +61,5 @@ export const Commands: NativeCommands = codegenNativeCommands({ export default (codegenNativeComponent('PullToRefreshView', { paperComponentName: 'RCTRefreshControl', - excludedPlatform: 'android', + excludedPlatforms: ['android'], }): HostComponent); diff --git a/Libraries/Components/Switch/SwitchNativeComponent.js b/Libraries/Components/Switch/SwitchNativeComponent.js index 89f757b87db64b..06c89a9a7bae1b 100644 --- a/Libraries/Components/Switch/SwitchNativeComponent.js +++ b/Libraries/Components/Switch/SwitchNativeComponent.js @@ -55,5 +55,5 @@ export const Commands: NativeCommands = codegenNativeCommands({ export default (codegenNativeComponent('Switch', { paperComponentName: 'RCTSwitch', - excludedPlatform: 'android', + excludedPlatforms: ['android'], }): ComponentType); diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 874046ba7f27e4..dd82eaf0a7027f 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -1092,6 +1092,10 @@ function InternalTextInput(props: Props): React.Node { // This is a hack to let Flow know we want an exact object |} = {...null}; + // The default value for `blurOnSubmit` is true for single-line fields and + // false for multi-line fields. + const blurOnSubmit = props.blurOnSubmit ?? !props.multiline; + if ( Platform.OS === 'ios' || Platform.OS === 'macos' /* TODO(macOS GH#774) */ @@ -1111,6 +1115,7 @@ function InternalTextInput(props: Props): React.Node { 0 || t > 0 || w > 0 || h > 0 || globalX > 0 || globalY > 0)) { return; } this.state.touchable.positionOnActivate && diff --git a/Libraries/Components/Touchable/TouchableBounce.js b/Libraries/Components/Touchable/TouchableBounce.js index d2365d977e3dc8..ab76580a76f912 100644 --- a/Libraries/Components/Touchable/TouchableBounce.js +++ b/Libraries/Components/Touchable/TouchableBounce.js @@ -246,4 +246,4 @@ class TouchableBounce extends React.Component { module.exports = (React.forwardRef((props, hostRef) => ( -)): React.ComponentType<$ReadOnly<$Diff>>); +)): React.AbstractComponent<$ReadOnly<$Diff>>); diff --git a/Libraries/Components/Touchable/TouchableHighlight.js b/Libraries/Components/Touchable/TouchableHighlight.js index f4c85089a0904d..71a21f7045de6f 100644 --- a/Libraries/Components/Touchable/TouchableHighlight.js +++ b/Libraries/Components/Touchable/TouchableHighlight.js @@ -413,4 +413,4 @@ class TouchableHighlight extends React.Component { module.exports = (React.forwardRef((props, hostRef) => ( -)): React.ComponentType<$ReadOnly<$Diff>>); +)): React.AbstractComponent<$ReadOnly<$Diff>>); diff --git a/Libraries/Components/Touchable/TouchableOpacity.js b/Libraries/Components/Touchable/TouchableOpacity.js index 98aadf8d225516..44d5ff2cc9dd44 100644 --- a/Libraries/Components/Touchable/TouchableOpacity.js +++ b/Libraries/Components/Touchable/TouchableOpacity.js @@ -359,4 +359,4 @@ class TouchableOpacity extends React.Component { module.exports = (React.forwardRef((props, hostRef) => ( -)): React.ComponentType<$ReadOnly<$Diff>>); +)): React.AbstractComponent<$ReadOnly<$Diff>>); diff --git a/Libraries/Image/NativeImageEditor.js b/Libraries/Image/NativeImageEditor.js new file mode 100644 index 00000000000000..ff334b897771a2 --- /dev/null +++ b/Libraries/Image/NativeImageEditor.js @@ -0,0 +1,51 @@ +/** + * (c) Facebook, Inc. and its affiliates. Confidential and proprietary. + * + * @flow strict-local + * @format + */ + +'use strict'; + +import type {TurboModule} from '../TurboModule/RCTExport'; +import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; + +type Options = {| + +offset: {| + +x: number, + +y: number, + |}, + +size: {| + +width: number, + +height: number, + |}, + +displaySize?: ?{| + +width: number, + +height: number, + |}, + /** + * Enum with potential values: + * - cover + * - contain + * - stretch + * - center + * - repeat + */ + +resizeMode?: ?string, + +allowExternalStorage?: boolean, +|}; + +export interface Spec extends TurboModule { + +getConstants: () => {||}; + +cropImage: ( + uri: string, + // eslint-disable-next-line lint/react-native-modules + cropData: Options, + successCallback: (uri: string) => void, + errorCallback: (error: string) => void, + ) => void; +} + +export default (TurboModuleRegistry.getEnforcing( + 'ImageEditingManager', +): Spec); diff --git a/Libraries/Image/NativeImageStore.js b/Libraries/Image/NativeImageStore.js new file mode 100644 index 00000000000000..196b328f7464e6 --- /dev/null +++ b/Libraries/Image/NativeImageStore.js @@ -0,0 +1,41 @@ +/** + * (c) Facebook, Inc. and its affiliates. Confidential and proprietary. + * + * @flow strict-local + * @format + */ + +'use strict'; + +import type {TurboModule} from '../TurboModule/RCTExport'; +import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + +getConstants: () => {||}; + // Common + +getBase64ForTag: ( + uri: string, + successCallback: (base64ImageData: string) => void, + + /** + * On Android, the failure callback is called with a string. + * On iOS, the failure callback is called with an error object. + * + * TODO(T47527939) Unify this inconsistency + */ + errorCallback: (error: {|message: string|} | string) => void, + ) => void; + + // iOS-only + +hasImageForTag: (uri: string, callback: (hasImage: boolean) => void) => void; + +removeImageForTag: (uri: string) => void; + +addImageFromBase64: ( + base64ImageData: string, + successCallback: (uri: string) => void, + errorCallback: (error: {|message: string|}) => void, + ) => void; +} + +export default (TurboModuleRegistry.getEnforcing( + 'ImageStoreManager', +): Spec); diff --git a/Libraries/Image/RCTImageLoader.mm b/Libraries/Image/RCTImageLoader.mm index ecde0c638fd44e..88ed783c52c1e7 100644 --- a/Libraries/Image/RCTImageLoader.mm +++ b/Libraries/Image/RCTImageLoader.mm @@ -635,7 +635,7 @@ - (RCTImageURLLoaderRequest *)_loadImageOrDataWithURLRequest:(NSURLRequest *)req } } }); - + return [[RCTImageURLLoaderRequest alloc] initWithRequestId:requestId imageURL:request.URL cancellationBlock:^{ BOOL alreadyCancelled = atomic_fetch_or(cancelled.get(), 1); if (alreadyCancelled) { @@ -856,6 +856,7 @@ - (void)trackURLImageContentDidSetForRequest:(RCTImageURLLoaderRequest *)loaderR return; } + // This delegate method is Fabric-only id loadHandler = [self imageURLLoaderForURL:loaderRequest.imageURL]; if ([loadHandler respondsToSelector:@selector(trackURLImageContentDidSetForRequest:)]) { [(id)loadHandler trackURLImageContentDidSetForRequest:loaderRequest]; @@ -879,6 +880,7 @@ - (void)trackURLImageDidDestroy:(RCTImageURLLoaderRequest *)loaderRequest if (!loaderRequest) { return; } + id loadHandler = [self imageURLLoaderForURL:loaderRequest.imageURL]; if ([loadHandler respondsToSelector:@selector(trackURLImageDidDestroy:)]) { [(id)loadHandler trackURLImageDidDestroy:loaderRequest]; diff --git a/Libraries/Image/RCTImageView.mm b/Libraries/Image/RCTImageView.mm index 3f5fc18b310479..e41c45cc10cbb4 100644 --- a/Libraries/Image/RCTImageView.mm +++ b/Libraries/Image/RCTImageView.mm @@ -114,6 +114,9 @@ @implementation RCTImageView // Weak reference back to the bridge, for image loading __weak RCTBridge *_bridge; + // Weak reference back to the active image loader. + __weak id _imageLoader; + // The image source that's currently displayed RCTImageSource *_imageSource; @@ -123,9 +126,6 @@ @implementation RCTImageView // Size of the image loaded / being loaded, so we can determine when to issue a reload to accommodate a changing size. CGSize _targetSize; - // A block that can be invoked to cancel the most recent call to -reloadImage, if any - RCTImageLoaderCancellationBlock _reloadImageCancellationBlock; - // Whether the latest change of props requires the image to be reloaded BOOL _needsReload; @@ -135,6 +135,8 @@ @implementation RCTImageView // Whether observing changes to the window's backing scale BOOL _subscribedToWindowBackingNotifications; #endif // [TODO(macOS GH#774) + + RCTImageURLLoaderRequest *_loaderRequest; } - (instancetype)initWithBridge:(RCTBridge *)bridge @@ -317,12 +319,11 @@ - (void)setResizeMode:(RCTResizeMode)resizeMode - (void)cancelImageLoad { - RCTImageLoaderCancellationBlock previousCancellationBlock = _reloadImageCancellationBlock; - if (previousCancellationBlock) { - previousCancellationBlock(); - _reloadImageCancellationBlock = nil; + if (_loaderRequest.cancellationBlock) { + _loaderRequest.cancellationBlock(); } + _loaderRequest = nil; _pendingImageSource = nil; } @@ -440,11 +441,13 @@ - (void)reloadImage [weakSelf imageLoaderLoadedImage:loadedImage error:error forImageSource:source partial:NO]; }; - id imageLoader = [_bridge moduleForName:@"ImageLoader" - lazilyLoadIfNecessary:YES]; - RCTImageURLLoaderRequest *loaderRequest = [imageLoader loadImageWithURLRequest:source.request - size:imageSize - scale:imageScale + if (!_imageLoader) { + _imageLoader = [_bridge moduleForName:@"ImageLoader" lazilyLoadIfNecessary:YES]; + } + + RCTImageURLLoaderRequest *loaderRequest = [_imageLoader loadImageWithURLRequest:source.request + size:imageSize + scale:imageScale clipped:NO resizeMode:_resizeMode priority:RCTImageLoaderPriorityImmediate @@ -455,7 +458,7 @@ - (void)reloadImage progressBlock:progressHandler partialLoadBlock:partialLoadHandler completionBlock:completionHandler]; - _reloadImageCancellationBlock = loaderRequest.cancellationBlock; + _loaderRequest = loaderRequest; } else { [self clearImage]; } @@ -653,4 +656,9 @@ - (void)setTintColor:(NSColor *)tintColor } } #endif // ]TODO(macOS GH#774) + +- (void)dealloc { + [_imageLoader trackURLImageDidDestroy:_loaderRequest]; +} + @end diff --git a/Libraries/Image/RCTUIImageViewAnimated.m b/Libraries/Image/RCTUIImageViewAnimated.m index ade3659a0fcd58..40661daf6531b7 100644 --- a/Libraries/Image/RCTUIImageViewAnimated.m +++ b/Libraries/Image/RCTUIImageViewAnimated.m @@ -187,9 +187,18 @@ - (void)displayDidRefresh:(CADisplayLink *)displayLink { #if TARGET_OS_UIKITFORMAC // TODO: `displayLink.frameInterval` is not available on UIKitForMac - NSTimeInterval duration = displayLink.duration; + NSTimeInterval durationToNextRefresh = displayLink.duration; #else - NSTimeInterval duration = displayLink.duration * displayLink.preferredFramesPerSecond; + // displaylink.duration -- time interval between frames, assuming maximumFramesPerSecond + // displayLink.preferredFramesPerSecond (>= iOS 10) -- Set to 30 for displayDidRefresh to be called at 30 fps + // displayLink.frameInterval (< iOS 10) -- # of frames that must pass before each displayDidRefresh. After iOS 10, when this is set to 2, preferredFramesPerSecond becomes 30 fps. + // durationToNextRefresh -- Time interval to the next time displayDidRefresh is called + NSTimeInterval durationToNextRefresh; + if (@available(iOS 10.0, *)) { + durationToNextRefresh = displayLink.targetTimestamp - displayLink.timestamp; + } else { + durationToNextRefresh = displayLink.duration * displayLink.frameInterval; + } #endif NSUInteger totalFrameCount = self.totalFrameCount; NSUInteger currentFrameIndex = self.currentFrameIndex; @@ -197,13 +206,14 @@ - (void)displayDidRefresh:(CADisplayLink *)displayLink // Check if we have the frame buffer firstly to improve performance if (!self.bufferMiss) { // Then check if timestamp is reached - self.currentTime += duration; + self.currentTime += durationToNextRefresh; NSTimeInterval currentDuration = [self.animatedImage animatedImageDurationAtIndex:currentFrameIndex]; if (self.currentTime < currentDuration) { // Current frame timestamp not reached, return return; } self.currentTime -= currentDuration; + // nextDuration - duration to wait before displaying next image NSTimeInterval nextDuration = [self.animatedImage animatedImageDurationAtIndex:nextFrameIndex]; if (self.currentTime > nextDuration) { // Do not skip frame diff --git a/Libraries/LayoutAnimation/LayoutAnimation.js b/Libraries/LayoutAnimation/LayoutAnimation.js index ba4632eb712404..159b2b96c785ad 100644 --- a/Libraries/LayoutAnimation/LayoutAnimation.js +++ b/Libraries/LayoutAnimation/LayoutAnimation.js @@ -11,52 +11,45 @@ 'use strict'; const UIManager = require('../ReactNative/UIManager'); +import type {Spec as FabricUIManagerSpec} from '../ReactNative/FabricUIManager'; +import type { + LayoutAnimationConfig as LayoutAnimationConfig_, + LayoutAnimationType, + LayoutAnimationProperty, +} from '../Renderer/shims/ReactNativeTypes'; import Platform from '../Utilities/Platform'; -type Type = - | 'spring' - | 'linear' - | 'easeInEaseOut' - | 'easeIn' - | 'easeOut' - | 'keyboard'; - -type Property = 'opacity' | 'scaleX' | 'scaleY' | 'scaleXY'; - -type AnimationConfig = $ReadOnly<{| - duration?: number, - delay?: number, - springDamping?: number, - initialVelocity?: number, - type?: Type, - property?: Property, -|}>; - -export type LayoutAnimationConfig = $ReadOnly<{| - duration: number, - create?: AnimationConfig, - update?: AnimationConfig, - delete?: AnimationConfig, -|}>; +// Reexport type +export type LayoutAnimationConfig = LayoutAnimationConfig_; function configureNext( config: LayoutAnimationConfig, onAnimationDidEnd?: Function, ) { if (!Platform.isTesting) { - UIManager.configureNextLayoutAnimation( - config, - onAnimationDidEnd ?? function() {}, - function() {} /* unused onError */, - ); + if (UIManager?.configureNextLayoutAnimation) { + UIManager.configureNextLayoutAnimation( + config, + onAnimationDidEnd ?? function() {}, + function() {} /* unused onError */, + ); + } + const FabricUIManager: FabricUIManagerSpec = global?.nativeFabricUIManager; + if (FabricUIManager?.configureNextLayoutAnimation) { + global?.nativeFabricUIManager?.configureNextLayoutAnimation( + config, + onAnimationDidEnd ?? function() {}, + function() {} /* unused onError */, + ); + } } } function create( duration: number, - type: Type, - property: Property, + type: LayoutAnimationType, + property: LayoutAnimationProperty, ): LayoutAnimationConfig { return { duration, diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 84228d4dcece4d..dcc524da53ca06 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -13,8 +13,6 @@ const Batchinator = require('../Interaction/Batchinator'); const FillRateHelper = require('./FillRateHelper'); const Platform = require('../Utilities/Platform'); // TODO(macOS GH#774) -const PropTypes = require('prop-types'); -const React = require('react'); const ReactNative = require('../Renderer/shims/ReactNative'); const RefreshControl = require('../Components/RefreshControl/RefreshControl'); const ScrollView = require('../Components/ScrollView/ScrollView'); @@ -29,6 +27,7 @@ const warning = require('fbjs/lib/warning'); const {computeWindowedRenderLimits} = require('./VirtualizeUtils'); +import * as React from 'react'; import type {ScrollResponderType} from '../Components/ScrollView/ScrollView'; import type {ViewStyleProp} from '../StyleSheet/StyleSheet'; import type { @@ -37,6 +36,13 @@ import type { ViewabilityConfigCallbackPair, } from './ViewabilityHelper'; import type {ScrollEvent} from '../Types/CoreEventTypes'; // TODO(macOS GH#774) +import { + VirtualizedListCellContextProvider, + VirtualizedListContext, + VirtualizedListContextProvider, + type ChildListState, + type ListDebugInfo, +} from './VirtualizedListContext.js'; type Item = any; @@ -351,21 +357,6 @@ type DefaultProps = {| let _usedIndexForKey = false; let _keylessItemComponentName: string = ''; -type Frame = { - offset: number, - length: number, - index: number, - inLayout: boolean, - ... -}; - -type ChildListState = { - first: number, - last: number, - frames: {[key: number]: Frame, ...}, - ... -}; - type State = { first: number, last: number, @@ -373,18 +364,6 @@ type State = { ... }; -// Data propagated through nested lists (regardless of orientation) that is -// useful for producing diagnostics for usage errors involving nesting (e.g -// missing/duplicate keys). -type ListDebugInfo = { - cellKey: string, - listKey: string, - parent: ?ListDebugInfo, - // We include all ancestors regardless of orientation, so this is not always - // identical to the child's orientation. - horizontal: boolean, -}; - /** * Base implementation for the more convenient [``](https://reactnative.dev/docs/flatlist.html) * and [``](https://reactnative.dev/docs/sectionlist.html) components, which are also better @@ -414,7 +393,7 @@ type ListDebugInfo = { * */ class VirtualizedList extends React.PureComponent { - props: Props; + static contextType: typeof VirtualizedListContext = VirtualizedListContext; // scrollToEnd may be janky without getItemLayout prop scrollToEnd(params?: ?{animated?: ?boolean, ...}) { @@ -464,8 +443,18 @@ class VirtualizedList extends React.PureComponent { } = this.props; const {animated, index, viewOffset, viewPosition} = params; invariant( - index >= 0 && index < getItemCount(data), - `scrollToIndex out of range: requested index ${index} but maximum is ${getItemCount( + index >= 0, + `scrollToIndex out of range: requested index ${index} but minimum is 0`, + ); + invariant( + getItemCount(data) >= 1, + `scrollToIndex out of range: item length ${getItemCount( + data, + )} but minimum is 1`, + ); + invariant( + index < getItemCount(data), + `scrollToIndex out of range: requested index ${index} is out of 0 to ${getItemCount( data, ) - 1}`, ); @@ -655,111 +644,8 @@ class VirtualizedList extends React.PureComponent { windowSize: 21, // multiples of length }; - static contextTypes: - | any - | {| - virtualizedCell: {| - cellKey: React$PropType$Primitive, - |}, - virtualizedList: {| - getScrollMetrics: React$PropType$Primitive, - horizontal: React$PropType$Primitive, - getOutermostParentListRef: React$PropType$Primitive, - getNestedChildState: React$PropType$Primitive, - registerAsNestedChild: React$PropType$Primitive, - unregisterAsNestedChild: React$PropType$Primitive, - debugInfo: {| - listKey: React$PropType$Primitive, - cellKey: React$PropType$Primitive, - |}, - |}, - |} = { - virtualizedCell: PropTypes.shape({ - cellKey: PropTypes.string, - }), - virtualizedList: PropTypes.shape({ - getScrollMetrics: PropTypes.func, - horizontal: PropTypes.bool, - getOutermostParentListRef: PropTypes.func, - getNestedChildState: PropTypes.func, - registerAsNestedChild: PropTypes.func, - unregisterAsNestedChild: PropTypes.func, - debugInfo: PropTypes.shape({ - listKey: PropTypes.string, - cellKey: PropTypes.string, - }), - }), - }; - - static childContextTypes: - | any - | {| - getScrollMetrics: React$PropType$Primitive, - horizontal: React$PropType$Primitive, - getOutermostParentListRef: React$PropType$Primitive, - getNestedChildState: React$PropType$Primitive, - registerAsNestedChild: React$PropType$Primitive, - unregisterAsNestedChild: React$PropType$Primitive, - |} = { - virtualizedList: PropTypes.shape({ - getScrollMetrics: PropTypes.func, - horizontal: PropTypes.bool, - getOutermostParentListRef: PropTypes.func, - getNestedChildState: PropTypes.func, - registerAsNestedChild: PropTypes.func, - unregisterAsNestedChild: PropTypes.func, - }), - }; - - getChildContext(): {| - virtualizedList: { - getScrollMetrics: () => { - contentLength: number, - dOffset: number, - dt: number, - offset: number, - timestamp: number, - velocity: number, - visibleLength: number, - ... - }, - horizontal: ?boolean, - getOutermostParentListRef: Function, - getNestedChildState: string => ?ChildListState, - registerAsNestedChild: ({ - cellKey: string, - key: string, - ref: VirtualizedList, - parentDebugInfo: ListDebugInfo, - ... - }) => ?ChildListState, - unregisterAsNestedChild: ({ - key: string, - state: ChildListState, - ... - }) => void, - debugInfo: ListDebugInfo, - ... - }, - |} { - return { - virtualizedList: { - getScrollMetrics: this._getScrollMetrics, - horizontal: this.props.horizontal, - getOutermostParentListRef: this._getOutermostParentListRef, - getNestedChildState: this._getNestedChildState, - registerAsNestedChild: this._registerAsNestedChild, - unregisterAsNestedChild: this._unregisterAsNestedChild, - debugInfo: this._getDebugInfo(), - }, - }; - } - _getCellKey(): string { - return ( - (this.context.virtualizedCell && this.context.virtualizedCell.cellKey) || - 'rootList' - ); + return this.context?.cellKey || 'rootList'; } _getListKey(): string { @@ -771,9 +657,7 @@ class VirtualizedList extends React.PureComponent { listKey: this._getListKey(), cellKey: this._getCellKey(), horizontal: !!this.props.horizontal, - parent: this.context.virtualizedList - ? this.context.virtualizedList.debugInfo - : null, + parent: this.context?.debugInfo, }; } @@ -787,7 +671,7 @@ class VirtualizedList extends React.PureComponent { _getOutermostParentListRef = () => { if (this._isNestedWithSameOrientation()) { - return this.context.virtualizedList.getOutermostParentListRef(); + return this.context.getOutermostParentListRef(); } else { return this; } @@ -847,8 +731,8 @@ class VirtualizedList extends React.PureComponent { state: State; - constructor(props: Props, context: Object) { - super(props, context); + constructor(props: Props) { + super(props); invariant( // $FlowFixMe !props.onScroll || !props.onScroll.__isNative, @@ -892,9 +776,7 @@ class VirtualizedList extends React.PureComponent { }; if (this._isNestedWithSameOrientation()) { - const storedState = this.context.virtualizedList.getNestedChildState( - this._getListKey(), - ); + const storedState = this.context.getNestedChildState(this._getListKey()); if (storedState) { initialState = storedState; this.state = storedState; @@ -907,7 +789,7 @@ class VirtualizedList extends React.PureComponent { componentDidMount() { if (this._isNestedWithSameOrientation()) { - this.context.virtualizedList.registerAsNestedChild({ + this.context.registerAsNestedChild({ cellKey: this._getCellKey(), key: this._getListKey(), ref: this, @@ -915,14 +797,14 @@ class VirtualizedList extends React.PureComponent { // the parent's props. This is why we explicitly propagate debugInfo // "down" via context and "up" again via this method call on the // parent. - parentDebugInfo: this.context.virtualizedList.debugInfo, + parentDebugInfo: this.context.debugInfo, }); } } componentWillUnmount() { if (this._isNestedWithSameOrientation()) { - this.context.virtualizedList.unregisterAsNestedChild({ + this.context.unregisterAsNestedChild({ key: this._getListKey(), state: { first: this.state.first, @@ -1022,7 +904,7 @@ class VirtualizedList extends React.PureComponent { } _isNestedWithSameOrientation(): boolean { - const nestedContext = this.context.virtualizedList; + const nestedContext = this.context; return !!( nestedContext && !!nestedContext.horizontal === !!this.props.horizontal ); @@ -1063,7 +945,7 @@ class VirtualizedList extends React.PureComponent { ); cells.push( - { element } - , + , ); } const itemCount = this.props.getItemCount(data); @@ -1218,7 +1100,7 @@ class VirtualizedList extends React.PureComponent { ); cells.push( - { element } - , + , ); } const scrollProps = { @@ -1257,14 +1139,29 @@ class VirtualizedList extends React.PureComponent { this._hasMore = this.state.last < this.props.getItemCount(this.props.data) - 1; - const innerRet = React.cloneElement( - (this.props.renderScrollComponent || this._defaultRenderScrollComponent)( - scrollProps, - ), - { - ref: this._captureScrollRef, - }, - cells, + const innerRet = ( + + {React.cloneElement( + ( + this.props.renderScrollComponent || + this._defaultRenderScrollComponent + )(scrollProps), + { + ref: this._captureScrollRef, + }, + cells, + )} + ); let ret = innerRet; if (__DEV__) { @@ -1275,7 +1172,7 @@ class VirtualizedList extends React.PureComponent { scrollContext != null && !scrollContext.horizontal === !this.props.horizontal && !this._hasWarned.nesting && - this.context.virtualizedList == null + this.context == null ) { // TODO (T46547044): use React.warn once 16.9 is sync'd: https://github.com/facebook/react/pull/15170 console.warn( @@ -1499,7 +1396,7 @@ class VirtualizedList extends React.PureComponent { // We are assuming that getOutermostParentListRef().getScrollRef() // is a non-null reference to a ScrollView this._scrollRef.measureLayout( - this.context.virtualizedList.getOutermostParentListRef().getScrollRef(), + this.context.getOutermostParentListRef().getScrollRef(), (x, y, width, height) => { this._offsetFromParentVirtualizedList = this._selectOffset({x, y}); this._scrollMetrics.contentLength = this._selectLength({ @@ -1507,7 +1404,7 @@ class VirtualizedList extends React.PureComponent { height, }); const scrollMetrics = this._convertParentScrollMetrics( - this.context.virtualizedList.getScrollMetrics(), + this.context.getScrollMetrics(), ); this._scrollMetrics.visibleLength = scrollMetrics.visibleLength; this._scrollMetrics.offset = scrollMetrics.offset; @@ -2077,19 +1974,6 @@ class VirtualizedList extends React.PureComponent { if (!frame || frame.index !== index) { if (getItemLayout) { frame = getItemLayout(data, index); - if (__DEV__) { - const frameType = PropTypes.shape({ - length: PropTypes.number.isRequired, - offset: PropTypes.number.isRequired, - index: PropTypes.number.isRequired, - }).isRequired; - PropTypes.checkPropTypes( - {frame: frameType}, - {frame}, - 'frame', - 'VirtualizedList.getItemLayout', - ); - } } } /* $FlowFixMe(>=0.63.0 site=react_native_fb) This comment suppresses an @@ -2167,12 +2051,6 @@ class CellRenderer extends React.Component< }, }; - static childContextTypes = { - virtualizedCell: PropTypes.shape({ - cellKey: PropTypes.string, - }), - }; - static getDerivedStateFromProps( props: CellRendererProps, prevState: CellRendererState, @@ -2185,14 +2063,6 @@ class CellRenderer extends React.Component< }; } - getChildContext() { - return { - virtualizedCell: { - cellKey: this.props.cellKey, - }, - }; - } - // TODO: consider factoring separator stuff out of VirtualizedList into FlatList since it's not // reused by SectionList and we can keep VirtualizedList simpler. _separators = { @@ -2307,18 +2177,15 @@ class CellRenderer extends React.Component< : horizontal ? [styles.row, inversionStyle] : inversionStyle; - if (!CellRendererComponent) { - return ( - /* $FlowFixMe(>=0.89.0 site=react_native_fb) This comment suppresses an - * error found when Flow v0.89 was deployed. To see the error, delete - * this comment and run Flow. */ - - {element} - {itemSeparator} - - ); - } - return ( + const result = !CellRendererComponent ? ( + /* $FlowFixMe(>=0.89.0 site=react_native_fb) This comment suppresses an + * error found when Flow v0.89 was deployed. To see the error, delete + * this comment and run Flow. */ + + {element} + {itemSeparator} + + ) : ( ); - } -} - -class VirtualizedCellWrapper extends React.Component<{ - cellKey: string, - children: React.Node, - ... -}> { - static childContextTypes = { - virtualizedCell: PropTypes.shape({ - cellKey: PropTypes.string, - }), - }; - getChildContext() { - return { - virtualizedCell: { - cellKey: this.props.cellKey, - }, - }; - } - - render() { - return this.props.children; + return ( + + {result} + + ); } } diff --git a/Libraries/Lists/VirtualizedListContext.js b/Libraries/Lists/VirtualizedListContext.js new file mode 100644 index 00000000000000..130315a1b08d57 --- /dev/null +++ b/Libraries/Lists/VirtualizedListContext.js @@ -0,0 +1,152 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +'use strict'; + +import type VirtualizedList from './VirtualizedList.js'; +import * as React from 'react'; +import {useMemo, useContext} from 'react'; + +type Frame = $ReadOnly<{ + offset: number, + length: number, + index: number, + inLayout: boolean, +}>; + +export type ChildListState = $ReadOnly<{ + first: number, + last: number, + frames: {[key: number]: Frame}, +}>; + +// Data propagated through nested lists (regardless of orientation) that is +// useful for producing diagnostics for usage errors involving nesting (e.g +// missing/duplicate keys). +export type ListDebugInfo = $ReadOnly<{ + cellKey: string, + listKey: string, + parent: ?ListDebugInfo, + // We include all ancestors regardless of orientation, so this is not always + // identical to the child's orientation. + horizontal: boolean, +}>; + +type Context = $ReadOnly<{ + cellKey: ?string, + getScrollMetrics: () => { + contentLength: number, + dOffset: number, + dt: number, + offset: number, + timestamp: number, + velocity: number, + visibleLength: number, + }, + horizontal: ?boolean, + getOutermostParentListRef: () => VirtualizedList, + getNestedChildState: string => ?ChildListState, + registerAsNestedChild: ({ + cellKey: string, + key: string, + ref: VirtualizedList, + parentDebugInfo: ListDebugInfo, + }) => ?ChildListState, + unregisterAsNestedChild: ({ + key: string, + state: ChildListState, + }) => void, + debugInfo: ListDebugInfo, +}>; + +export const VirtualizedListContext: React.Context = React.createContext( + null, +); + +/** + * Resets the context. Intended for use by portal-like components (e.g. Modal). + */ +export function VirtualizedListContextResetter({ + children, +}: { + children: React.Node, +}): React.Node { + return ( + + {children} + + ); +} + +/** + * Sets the context with memoization. Intended to be used by `VirtualizedList`. + */ +export function VirtualizedListContextProvider({ + children, + value, +}: { + children: React.Node, + value: Context, +}): React.Node { + // Avoid setting a newly created context object if the values are identical. + const context = useMemo( + () => ({ + cellKey: null, + getScrollMetrics: value.getScrollMetrics, + horizontal: value.horizontal, + getOutermostParentListRef: value.getOutermostParentListRef, + getNestedChildState: value.getNestedChildState, + registerAsNestedChild: value.registerAsNestedChild, + unregisterAsNestedChild: value.unregisterAsNestedChild, + debugInfo: { + cellKey: value.debugInfo.cellKey, + horizontal: value.debugInfo.horizontal, + listKey: value.debugInfo.listKey, + parent: value.debugInfo.parent, + }, + }), + [ + value.getScrollMetrics, + value.horizontal, + value.getOutermostParentListRef, + value.getNestedChildState, + value.registerAsNestedChild, + value.unregisterAsNestedChild, + value.debugInfo.cellKey, + value.debugInfo.horizontal, + value.debugInfo.listKey, + value.debugInfo.parent, + ], + ); + return ( + + {children} + + ); +} + +/** + * Sets the `cellKey`. Intended to be used by `VirtualizedList` for each cell. + */ +export function VirtualizedListCellContextProvider({ + cellKey, + children, +}: { + cellKey: string, + children: React.Node, +}): React.Node { + const context = useContext(VirtualizedListContext); + return ( + + {children} + + ); +} diff --git a/Libraries/Lists/__tests__/VirtualizedList-test.js b/Libraries/Lists/__tests__/VirtualizedList-test.js index e99215a2d867d1..271fad276fe55e 100644 --- a/Libraries/Lists/__tests__/VirtualizedList-test.js +++ b/Libraries/Lists/__tests__/VirtualizedList-test.js @@ -456,4 +456,52 @@ describe('VirtualizedList', () => { console.error.mockRestore(); } }); + + it('throws if using scrollToIndex with index less than 0', () => { + const component = ReactTestRenderer.create( + } + getItem={(data, index) => data[index]} + getItemCount={data => data.length} + />, + ); + const instance = component.getInstance(); + + expect(() => instance.scrollToIndex({index: -1})).toThrow( + 'scrollToIndex out of range: requested index -1 but minimum is 0', + ); + }); + + it('throws if using scrollToIndex when item length is less than 1', () => { + const component = ReactTestRenderer.create( + } + getItem={(data, index) => data[index]} + getItemCount={data => data.length} + />, + ); + const instance = component.getInstance(); + + expect(() => instance.scrollToIndex({index: 1})).toThrow( + 'scrollToIndex out of range: item length 0 but minimum is 1', + ); + }); + + it('throws if using scrollToIndex when requested index is bigger than or equal to item length', () => { + const component = ReactTestRenderer.create( + } + getItem={(data, index) => data[index]} + getItemCount={data => data.length} + />, + ); + const instance = component.getInstance(); + + expect(() => instance.scrollToIndex({index: 3})).toThrow( + 'scrollToIndex out of range: requested index 3 is out of 0 to 2', + ); + }); }); diff --git a/Libraries/LogBox/Data/LogBoxData.js b/Libraries/LogBox/Data/LogBoxData.js index 1076d26661f448..9d35132a490f3a 100644 --- a/Libraries/LogBox/Data/LogBoxData.js +++ b/Libraries/LogBox/Data/LogBoxData.js @@ -135,17 +135,15 @@ function handleUpdate(): void { } function appendNewLog(newLog) { - // We don't want to store these logs because they trigger a - // state update whenever we add them to the store, which is - // expensive to noisy logs. If we later want to display these - // we will store them in a different state object. + // Don't want store these logs because they trigger a + // state update when we add them to the store. if (isMessageIgnored(newLog.message.content)) { return; } // If the next log has the same category as the previous one - // then we want to roll it up into the last log in the list - // by incrementing the count (simar to how Chrome does it). + // then roll it up into the last log in the list by incrementing + // the count (similar to how Chrome does it). const lastLog = Array.from(logs).pop(); if (lastLog && lastLog.category === newLog.category) { lastLog.incrementCount(); @@ -161,7 +159,7 @@ function appendNewLog(newLog) { let addPendingLog = () => { logs.add(newLog); - if (_selectedIndex <= 0) { + if (_selectedIndex < 0) { setSelectedLog(logs.size - 1); } else { handleUpdate(); diff --git a/Libraries/LogBox/Data/__tests__/LogBoxData-test.js b/Libraries/LogBox/Data/__tests__/LogBoxData-test.js index bd5e0c99056177..b0dfc3074aa079 100644 --- a/Libraries/LogBox/Data/__tests__/LogBoxData-test.js +++ b/Libraries/LogBox/Data/__tests__/LogBoxData-test.js @@ -275,7 +275,7 @@ describe('LogBoxData', () => { expect(selectedLogIndex()).toBe(-1); }); - it('sets the selectedLogIndex to the last fatal error (after symbolication)', () => { + it('sets the selectedLogIndex to the first fatal error (after symbolication)', () => { addFatalErrors(['A']); // Order maters for symbolication before timeout. @@ -291,10 +291,14 @@ describe('LogBoxData', () => { flushLogs(); jest.runAllTimers(); - expect(selectedLogIndex()).toBe(2); + // This should still be 0 (the first fatal exception) + // becuase it is the most likely source of the error. + // If there are more exceptions after this, they + // are likely caused by this original exception. + expect(selectedLogIndex()).toBe(0); }); - it('sets the selectedLogIndex to the last fatal error (hitting timeout limit)', () => { + it('sets the selectedLogIndex to the first fatal error (hitting timeout limit)', () => { addFatalErrors(['A']); // Order maters for timeout before symbolication. @@ -310,7 +314,11 @@ describe('LogBoxData', () => { jest.runAllTimers(); flushLogs(); - expect(selectedLogIndex()).toBe(2); + // This should still be 0 (the first fatal exception) + // becuase it is the most likely source of the error. + // If there are more exceptions after this, they + // are likely caused by this original exception. + expect(selectedLogIndex()).toBe(0); }); it('sets the selectedLogIndex to the last syntax error', () => { diff --git a/Libraries/LogBox/UI/LogBoxInspector.js b/Libraries/LogBox/UI/LogBoxInspector.js index 9c2983264b04b7..68c591f11e37de 100644 --- a/Libraries/LogBox/UI/LogBoxInspector.js +++ b/Libraries/LogBox/UI/LogBoxInspector.js @@ -87,11 +87,11 @@ function LogBoxInspector(props: Props): React.Node { } const headerTitleMap = { - warn: 'Warning', - error: 'Error', - fatal: 'Exception', + warn: 'Console Warning', + error: 'Console Error', + fatal: 'Uncaught Error', syntax: 'Syntax Error', - component: 'Component Exception', + component: 'Render Error', }; function LogBoxInspectorBody(props) { diff --git a/Libraries/Modal/Modal.js b/Libraries/Modal/Modal.js index 0dfe53ab1db7bf..c25cb8ff986eb3 100644 --- a/Libraries/Modal/Modal.js +++ b/Libraries/Modal/Modal.js @@ -25,6 +25,7 @@ import type {ViewProps} from '../Components/View/ViewPropTypes'; import type {DirectEventHandler} from '../Types/CodegenTypes'; import type EmitterSubscription from '../vendor/emitter/EmitterSubscription'; import RCTModalHostView from './RCTModalHostViewNativeComponent'; +import {VirtualizedListContextResetter} from '../Lists/VirtualizedListContext.js'; const ModalEventEmitter = Platform.OS === 'ios' && NativeModalManager != null @@ -168,20 +169,6 @@ class Modal extends React.Component { this._identifier = uniqueModalIdentifier++; } - static childContextTypes: - | any - | {|virtualizedList: React$PropType$Primitive|} = { - virtualizedList: PropTypes.object, - }; - - getChildContext(): {|virtualizedList: null|} { - // Reset the context so VirtualizedList doesn't get confused by nesting - // in the React tree that doesn't reflect the native component hierarchy. - return { - virtualizedList: null, - }; - } - componentDidMount() { if (ModalEventEmitter) { this._eventSubscription = ModalEventEmitter.addListener( @@ -258,11 +245,15 @@ class Modal extends React.Component { onStartShouldSetResponder={this._shouldSetResponder} supportedOrientations={this.props.supportedOrientations} onOrientationChange={this.props.onOrientationChange}> - - - {innerChildren} - - + + + + {innerChildren} + + + ); } diff --git a/Libraries/Pressability/Pressability.js b/Libraries/Pressability/Pressability.js index ad1259af343380..38ebe26f2a515a 100644 --- a/Libraries/Pressability/Pressability.js +++ b/Libraries/Pressability/Pressability.js @@ -787,7 +787,16 @@ export default class Pressability { } _measureCallback = (left, top, width, height, pageX, pageY) => { - if (!left && !top && !width && !height && !pageX && !pageY) { + if ( + !( + left > 0 || + top > 0 || + width > 0 || + height > 0 || + pageX > 0 || + pageY > 0 + ) + ) { return; } this._responderRegion = { diff --git a/Libraries/ReactNative/AppContainer.js b/Libraries/ReactNative/AppContainer.js index 93c83fba66350b..2c2b0fc157fd94 100644 --- a/Libraries/ReactNative/AppContainer.js +++ b/Libraries/ReactNative/AppContainer.js @@ -24,6 +24,7 @@ type Props = $ReadOnly<{| children?: React.Node, fabric?: boolean, rootTag: number, + initialProps?: {...}, showArchitectureIndicator?: boolean, WrapperComponent?: ?React.ComponentType, internal_excludeLogBox?: ?boolean, @@ -119,6 +120,7 @@ class AppContainer extends React.Component { if (Wrapper != null) { innerView = ( ; type NodeProps = {...}; type InstanceHandle = {...}; -type Spec = {| +export type Spec = {| +createNode: ( reactTag: number, viewName: string, @@ -49,6 +50,13 @@ type Spec = {| onFail: () => void, onSuccess: MeasureLayoutOnSuccessCallback, ) => void, + +configureNextLayoutAnimation: ( + config: LayoutAnimationConfig, + callback: () => void, // check what is returned here + // This error isn't currently called anywhere, so the `error` object is really not defined + // $FlowFixMe + errorCallback: (error: Object) => void, + ) => void, |}; const FabricUIManager: ?Spec = global.nativeFabricUIManager; diff --git a/Libraries/ReactNative/renderApplication.js b/Libraries/ReactNative/renderApplication.js index c5bd0e024cdd85..7d7b3b4409b1f7 100644 --- a/Libraries/ReactNative/renderApplication.js +++ b/Libraries/ReactNative/renderApplication.js @@ -41,6 +41,7 @@ function renderApplication( fabric={fabric} showArchitectureIndicator={showArchitectureIndicator} WrapperComponent={WrapperComponent} + initialProps={initialProps ?? Object.freeze({})} internal_excludeLogBox={isLogBox}> diff --git a/Libraries/Renderer/shims/ReactNativeTypes.js b/Libraries/Renderer/shims/ReactNativeTypes.js index ec68139ab57208..f6b9e3c2b91829 100644 --- a/Libraries/Renderer/shims/ReactNativeTypes.js +++ b/Libraries/Renderer/shims/ReactNativeTypes.js @@ -213,3 +213,36 @@ export type ReactFaricEvent = { target: number, ... }; + +// +// Imperative LayoutAnimation API types +// +export type LayoutAnimationType = + | 'spring' + | 'linear' + | 'easeInEaseOut' + | 'easeIn' + | 'easeOut' + | 'keyboard'; + +export type LayoutAnimationProperty = + | 'opacity' + | 'scaleX' + | 'scaleY' + | 'scaleXY'; + +export type LayoutAnimationAnimationConfig = $ReadOnly<{| + duration?: number, + delay?: number, + springDamping?: number, + initialVelocity?: number, + type?: LayoutAnimationType, + property?: LayoutAnimationProperty, +|}>; + +export type LayoutAnimationConfig = $ReadOnly<{| + duration: number, + create?: LayoutAnimationAnimationConfig, + update?: LayoutAnimationAnimationConfig, + delete?: LayoutAnimationAnimationConfig, +|}>; diff --git a/Libraries/TimePickerAndroid/NativeTimePickerAndroid.js b/Libraries/TimePickerAndroid/NativeTimePickerAndroid.js new file mode 100644 index 00000000000000..46594ffdc3196e --- /dev/null +++ b/Libraries/TimePickerAndroid/NativeTimePickerAndroid.js @@ -0,0 +1,31 @@ +/** + * (c) Facebook, Inc. and its affiliates. Confidential and proprietary. + * + * @flow strict-local + * @format + */ + +'use strict'; + +import type {TurboModule} from '../TurboModule/RCTExport'; +import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; + +export type TimePickerOptions = {| + hour?: number, + minute?: number, + is24Hour?: boolean, + mode?: string, +|}; + +export type TimePickerResult = {| + action: string, + hour: number, + minute: number, +|}; + +export interface Spec extends TurboModule { + // eslint-disable-next-line lint/react-native-modules + +open: (options: TimePickerOptions) => Promise; +} + +export default (TurboModuleRegistry.get('TimePickerAndroid'): ?Spec); diff --git a/Libraries/Utilities/LoadingView.ios.js b/Libraries/Utilities/LoadingView.ios.js index e8f7d133f5caf3..ad2caad48310ea 100644 --- a/Libraries/Utilities/LoadingView.ios.js +++ b/Libraries/Utilities/LoadingView.ios.js @@ -16,20 +16,19 @@ import NativeDevLoadingView from './NativeDevLoadingView'; module.exports = { showMessage(message: string, type: 'load' | 'refresh') { if (NativeDevLoadingView) { - const green = processColor('#005a00'); - const blue = processColor('#2584e8'); + const loadColor = processColor('#404040'); + const refreshColor = processColor('#2584e8'); const white = processColor('#ffffff'); NativeDevLoadingView.showMessage( message, - // Use same colors as iOS "Personal Hotspot" bar. typeof white === 'number' ? white : null, type && type === 'load' - ? typeof green === 'number' - ? green + ? typeof loadColor === 'number' + ? loadColor : null - : typeof blue === 'number' - ? blue + : typeof refreshColor === 'number' + ? refreshColor : null, ); } diff --git a/Libraries/Utilities/codegenNativeComponent.js b/Libraries/Utilities/codegenNativeComponent.js index 8c1a9d0b4d66ab..c790495c5e41c6 100644 --- a/Libraries/Utilities/codegenNativeComponent.js +++ b/Libraries/Utilities/codegenNativeComponent.js @@ -20,7 +20,7 @@ type Options = $ReadOnly<{| interfaceOnly?: boolean, paperComponentName?: string, paperComponentNameDeprecated?: string, - excludedPlatform?: 'iOS' | 'android', + excludedPlatforms?: $ReadOnlyArray<'iOS' | 'android'>, |}>; export type NativeComponentType = HostComponent; diff --git a/RNTester/Podfile.lock b/RNTester/Podfile.lock index f1cc9b2f5fd073..a5767ec8323f91 100644 --- a/RNTester/Podfile.lock +++ b/RNTester/Podfile.lock @@ -236,6 +236,7 @@ PODS: - RCT-Folly (= 2020.01.13.00) - React-callinvoker (= 1000.0.0) - React-jsinspector (= 1000.0.0) + - React-runtimeexecutor (= 1000.0.0) - React-jsi (1000.0.0): - boost-for-react-native (= 1.63.0) - DoubleConversion @@ -318,6 +319,8 @@ PODS: - React-Core/RCTVibrationHeaders (= 1000.0.0) - React-jsi (= 1000.0.0) - ReactCommon/turbomodule/core (= 1000.0.0) + - React-runtimeexecutor (1000.0.0): + - React-jsi (= 1000.0.0) - React-TurboModuleCxx-RNW (1000.0.0): - RCT-Folly (= 2020.01.13.00) - React-callinvoker (= 1000.0.0) @@ -402,6 +405,7 @@ DEPENDENCIES: - React-RCTTest (from `./RCTTest`) - React-RCTText (from `../Libraries/Text`) - React-RCTVibration (from `../Libraries/Vibration`) + - React-runtimeexecutor (from `../ReactCommon/runtimeexecutor`) - React-TurboModuleCxx-RNW (from `../ReactTurboModuleCxx/React-TurboModuleCxx-RNW.podspec`) - React-TurboModuleCxx-WinRTPort (from `../ReactTurboModuleCxx`) - ReactCommon/turbomodule/core (from `../ReactCommon`) @@ -479,6 +483,8 @@ EXTERNAL SOURCES: :path: "../Libraries/Text" React-RCTVibration: :path: "../Libraries/Vibration" + React-runtimeexecutor: + :path: "../ReactCommon/runtimeexecutor" React-TurboModuleCxx-RNW: :podspec: "../ReactTurboModuleCxx/React-TurboModuleCxx-RNW.podspec" React-TurboModuleCxx-WinRTPort: @@ -493,8 +499,8 @@ SPEC CHECKSUMS: CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845 CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f DoubleConversion: 2b45d0f8e156a5b02354c8a4062de64d41ccb4e0 - FBLazyVector: 2a6caf53223741f5f28ef26a4af1b6e8300ce387 - FBReactNativeSpec: 62c59cc87734b32894837cf83de694fa3875783d + FBLazyVector: 98b5ed9e2c8215c32630adabb6c6ae8fd88b4808 + FBReactNativeSpec: a5a59afb795ccab0596667e248b5cdcb05cf86e2 Flipper: be611d4b742d8c87fbae2ca5f44603a02539e365 Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41 Flipper-Folly: c12092ea368353b58e992843a990a3225d4533c3 @@ -505,32 +511,33 @@ SPEC CHECKSUMS: glog: 789873d01e4b200777d0a09bc23d548446758699 OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355 RCT-Folly: 55d0039b24e192081ec0b2257f7bd9f42e382fb7 - RCTRequired: 37458b93b9cd9fba3ab51dd2e458dbb9cb47520d - RCTTypeSafety: 519c014f622af9b169ecfa216bedfab393ff5912 - React: 4fd7e473044e7648f405920f016929540d34e982 - React-ART: bcf223c5eff9012d960831ff1e769bb122b4f885 - React-callinvoker: 5b05b9e59fb30f90bc0725d4af7e1192ba26c481 - React-Core: 11c6182b2c0f066654cb15aa79cbded57491d6d6 - React-CoreModules: 3ee9b5c78248c356a40d1756848ff3e54643d507 - React-cxxreact: aa5a9272ad44004b38e168e23c89d3975ee89f8c - React-jsi: 2168becebc7c1f9da7db0e87128441ce5658276a - React-jsiexecutor: 910d40b16b39c7bf016ce531ecebe96775dc66df - React-jsinspector: f372dd2f90f35ca9f4ed414f02155cc32f092f21 - React-RCTActionSheet: d732c93288db766d84e9050b503fc573b20d4f0f - React-RCTAnimation: 82920521aa45e1d1497e4d8c489ecee47a7daf90 - React-RCTBlob: 075b73cf6d1d45d90ab49656234d5dc8de9de2ed - React-RCTImage: e13823a64d4dbdda8e6f995dd0e9f49cdd5441e7 - React-RCTLinking: f235950225543ebcdda86caa8fa4d9c61ac568b6 - React-RCTNetwork: 740884e7e2bad762f1678799c9d00805f562e333 - React-RCTPushNotification: 937bbbe82f700cbeaa1d5a3b1e9b13df48145c96 - React-RCTSettings: d79eaace2fed3bf317df17fa97355222cca052c5 - React-RCTTest: 66c38e03b6e5aa3c2721b0b1f5ff3e3895d2ede9 - React-RCTText: 8df41e7b83bbce2a8a55594b3e1663c177954eb1 - React-RCTVibration: 1c1755a5ed06d469f100d32c4cd28789b92f0a3c + RCTRequired: cd124a69447b4db403af1f4dc1d7c7cb617185a0 + RCTTypeSafety: 83da012f103c272792343e635da1b72936067b96 + React: e7aaeceb4fee9ffc841301330e753a1bd3e57437 + React-ART: 114994073be3e1257406f49d629222d94f5361bd + React-callinvoker: ebde245fca99f1f324793be8783dd6def592627c + React-Core: 4775366e8e941f063ee8463f86bf41613ec1a7b2 + React-CoreModules: ca9df8e2a54ccbaad588ffa772f71fbc8ba19279 + React-cxxreact: cfba7c9e9bd2d23b97af6467d5ecf390e932676d + React-jsi: b0857c300ffbf312d1b15e60a060ad7f5a2f978d + React-jsiexecutor: 93e0bb19579e3002775bc3efc0cbd81f20943be8 + React-jsinspector: 3526475c50fc3d942d6cdc02618f72a5f5510935 + React-RCTActionSheet: 23ed110450142634ede6b88ccbd2fb69aa892c52 + React-RCTAnimation: 383e388d729b39d0087b4986f0ebb728bac7eb02 + React-RCTBlob: 53fcb292e073976d7f6867841eee402770bfbf84 + React-RCTImage: 3ea30c5c2fd33f042aa768e6a1688046bbf59bda + React-RCTLinking: cb77eeacb78c1b3cd1c579c6597ea2bbe424945e + React-RCTNetwork: a34eabaa807c9163af30d4e4623b20e3136659bc + React-RCTPushNotification: 9f0a55cbaeccb9a10252d468fa73c7281aef680c + React-RCTSettings: 149f8ea51af3afb60f4a3a262698b94a0a9209aa + React-RCTTest: 7d56585d7cc88320631522ae29ffba082e12c377 + React-RCTText: 9b42805a9082c6e6df5b0deab2bdba14f1db0e3a + React-RCTVibration: c834fb5115f6d341b68a9595905bf253b617ab1d + React-runtimeexecutor: 576ce90cf13a65e00b35c3cbcdbe65aaddea8351 React-TurboModuleCxx-RNW: 18bb71af41fe34c8b12a56bef60aae7ee32b0817 - React-TurboModuleCxx-WinRTPort: c1adb8fead6510128bd0203ab4a39ac9b14d9242 - ReactCommon: 94af7b71fd77b1f670215637147f79872ec95835 - Yoga: 190421d13b42fd56a19bea15f2a5b03f98e21911 + React-TurboModuleCxx-WinRTPort: d4886bfcdff8fb04d407e6a3b7ee8feb7cc2ad40 + ReactCommon: 4ae7a0aa58b93673a204fdd12ff4f8b079baf20e + Yoga: dd900352619ba7f891e6e505ceee59afc0012115 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a PODFILE CHECKSUM: 7d43a928a9b9ad27329da110adbfadd923a39ba8 diff --git a/RNTester/RNTesterPods.xcodeproj/project.pbxproj b/RNTester/RNTesterPods.xcodeproj/project.pbxproj index 825f54b636aa8e..b7a8859d7683d5 100644 --- a/RNTester/RNTesterPods.xcodeproj/project.pbxproj +++ b/RNTester/RNTesterPods.xcodeproj/project.pbxproj @@ -847,7 +847,7 @@ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1130; + LastUpgradeCheck = 1140; ORGANIZATIONNAME = Facebook; TargetAttributes = { 387847D0245631D80035033A = { @@ -1511,6 +1511,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 98233960D1D6A1977D1C7EAF /* Pods-RNTester.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_CXX_LANGUAGE_STANDARD = "c++14"; CODE_SIGN_ENTITLEMENTS = RNTester/RNTester.entitlements; diff --git a/RNTester/RNTesterPods.xcodeproj/xcshareddata/xcschemes/RNTester.xcscheme b/RNTester/RNTesterPods.xcodeproj/xcshareddata/xcschemes/RNTester.xcscheme index aa5eb07b7a0e40..938a25682dbd5c 100644 --- a/RNTester/RNTesterPods.xcodeproj/xcshareddata/xcschemes/RNTester.xcscheme +++ b/RNTester/RNTesterPods.xcodeproj/xcshareddata/xcschemes/RNTester.xcscheme @@ -1,6 +1,6 @@ { }; _onChangeScrollToIndex = text => { - this._listRef - .getNode() - .scrollToIndex({viewPosition: 0.5, index: Number(text)}); + this._listRef.scrollToIndex({viewPosition: 0.5, index: Number(text)}); }; _scrollPos = new Animated.Value(0); @@ -97,7 +95,7 @@ class FlatListExample extends React.PureComponent { ); componentDidUpdate() { - this._listRef.getNode().recordInteraction(); // e.g. flipping logViewable switch + this._listRef.recordInteraction(); // e.g. flipping logViewable switch } render(): React.Node { @@ -249,7 +247,7 @@ class FlatListExample extends React.PureComponent { } }; _pressItem = (key: string) => { - this._listRef.getNode().recordInteraction(); + this._listRef && this._listRef.recordInteraction(); pressItem(this, key); }; _listRef: React.ElementRef; diff --git a/RNTester/js/examples/PushNotificationIOS/PushNotificationIOSExample.js b/RNTester/js/examples/PushNotificationIOS/PushNotificationIOSExample.js index 93127afb755999..c32bacefef2cc8 100644 --- a/RNTester/js/examples/PushNotificationIOS/PushNotificationIOSExample.js +++ b/RNTester/js/examples/PushNotificationIOS/PushNotificationIOSExample.js @@ -196,7 +196,7 @@ class NotificationPermissionExample extends React.Component< ); this._checkPermissions(); }, - (onReject?) => { + () => { this._showAlert('Error requesting permissions'); this._checkPermissions(); }, diff --git a/RNTester/js/examples/SectionList/SectionListExample.js b/RNTester/js/examples/SectionList/SectionListExample.js index d3b895e6362950..56d7067550c1ff 100644 --- a/RNTester/js/examples/SectionList/SectionListExample.js +++ b/RNTester/js/examples/SectionList/SectionListExample.js @@ -92,13 +92,14 @@ class SectionListExample extends React.PureComponent<{...}, $FlowFixMeState> { {useNativeDriver: true}, ); - _sectionListRef: React.ElementRef; + _sectionListRef: ?React.ElementRef = null; _captureRef = ref => { this._sectionListRef = ref; }; _scrollToLocation(sectionIndex: number, itemIndex: number) { - this._sectionListRef.getNode().scrollToLocation({sectionIndex, itemIndex}); + this._sectionListRef && + this._sectionListRef.scrollToLocation({sectionIndex, itemIndex}); } render(): React.Node { diff --git a/React/Base/RCTJavaScriptLoader.mm b/React/Base/RCTJavaScriptLoader.mm index 8c8e5fad02ff17..d15738c549eabe 100755 --- a/React/Base/RCTJavaScriptLoader.mm +++ b/React/Base/RCTJavaScriptLoader.mm @@ -50,10 +50,14 @@ @implementation RCTLoadingProgress - (NSString *)description { NSMutableString *desc = [NSMutableString new]; - [desc appendString:_status ?: @"Loading"]; + [desc appendString:_status ?: @"Bundling"]; - if ([_total integerValue] > 0) { - [desc appendFormat:@" %ld%% (%@/%@)", (long)(100 * [_done integerValue] / [_total integerValue]), _done, _total]; + if ([_total integerValue] > 0 && [_done integerValue] > [_total integerValue]) { + [desc appendFormat:@" %ld%%", (long)100]; + } else if ([_total integerValue] > 0) { + [desc appendFormat:@" %ld%%", (long)(100 * [_done integerValue] / [_total integerValue])]; + } else { + [desc appendFormat:@" %ld%%", (long)0]; } [desc appendString:@"\u2026"]; return desc; @@ -346,7 +350,7 @@ static void attemptAsynchronousLoadOfBundleAtURL( static RCTLoadingProgress *progressEventFromDownloadProgress(NSNumber *total, NSNumber *done) { RCTLoadingProgress *progress = [RCTLoadingProgress new]; - progress.status = @"Downloading JavaScript bundle"; + progress.status = @"Downloading"; // Progress values are in bytes transform them to kilobytes for smaller numbers. progress.done = done != nil ? @([done integerValue] / 1024) : nil; progress.total = total != nil ? @([total integerValue] / 1024) : nil; diff --git a/React/CoreModules/RCTDevLoadingView.mm b/React/CoreModules/RCTDevLoadingView.mm index 88a385c3275bae..da8c928f315da1 100644 --- a/React/CoreModules/RCTDevLoadingView.mm +++ b/React/CoreModules/RCTDevLoadingView.mm @@ -39,6 +39,8 @@ @implementation RCTDevLoadingView { NSTextField *_label; #endif // ]TODO(macOS GH#774) NSDate *_showDate; + BOOL _hiding; + dispatch_block_t _initialMessageBlock; } @synthesize bridge = _bridge; @@ -73,9 +75,54 @@ - (void)setBridge:(RCTBridge *)bridge } } +- (void)clearInitialMessageDelay +{ + if (self->_initialMessageBlock != nil) { + dispatch_block_cancel(self->_initialMessageBlock); + self->_initialMessageBlock = nil; + } +} + +- (void)showInitialMessageDelayed:(void (^)())initialMessage +{ + self->_initialMessageBlock = dispatch_block_create(static_cast(0), initialMessage); + + // We delay the initial loading message to prevent flashing it + // when loading progress starts quickly. To do that, we + // schedule the message to be shown in a block, and cancel + // the block later when the progress starts coming in. + // If the progress beats this timer, this message is not shown. + dispatch_after( + dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC), dispatch_get_main_queue(), self->_initialMessageBlock); +} + +#if 0 // TODO(macOS GH#774) +// Blocked out because -[(NS|UI)Color getHue:saturation:brightness:alpha:] has +// different return values on macOS and iOS. +// The call to dimColor: was removed with f0dfd35108dd3f092d46b65e77560c35477bf6ba, +// and we don't use it anywhere else, so we should probably remove this upstream too. +- (RCTUIColor *)dimColor:(RCTUIColor *)c +{ + // Given a color, return a slightly lighter or darker color for dim effect. + CGFloat h, s, b, a; + if ([c getHue:&h saturation:&s brightness:&b alpha:&a]) + return [RCTUIColor colorWithHue:h saturation:s brightness:b < 0.5 ? b * 1.25 : b * 0.75 alpha:a]; + return nil; +} +#endif // TODO(macOS GH#774) + +- (NSString *)getTextForHost +{ + if (self->_bridge.bundleURL == nil || self->_bridge.bundleURL.fileURL) { + return @"React Native"; + } + + return [NSString stringWithFormat:@"%@:%@", self->_bridge.bundleURL.host, self->_bridge.bundleURL.port]; +} + - (void)showMessage:(NSString *)message color:(RCTUIColor *)color backgroundColor:(RCTUIColor *)backgroundColor // TODO(OSS Candidate ISS#2710739) { - if (!RCTDevLoadingViewGetEnabled()) { + if (!RCTDevLoadingViewGetEnabled() || self->_hiding) { return; } @@ -88,18 +135,16 @@ - (void)showMessage:(NSString *)message color:(RCTUIColor *)color backgroundColo if (@available(iOS 11.0, *)) { UIWindow *window = RCTSharedApplication().keyWindow; self->_window = - [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, screenSize.width, window.safeAreaInsets.top + 30)]; - self->_label = [[UILabel alloc] initWithFrame:CGRectMake(0, window.safeAreaInsets.top, screenSize.width, 30)]; + [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, screenSize.width, window.safeAreaInsets.top + 10)]; + self->_label = + [[UILabel alloc] initWithFrame:CGRectMake(0, window.safeAreaInsets.top - 10, screenSize.width, 20)]; } else { - self->_window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, screenSize.width, 22)]; + self->_window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, screenSize.width, 20)]; self->_label = [[UILabel alloc] initWithFrame:self->_window.bounds]; } [self->_window addSubview:self->_label]; -#if TARGET_OS_TV - self->_window.windowLevel = UIWindowLevelNormal + 1; -#else + self->_window.windowLevel = UIWindowLevelStatusBar + 1; -#endif // set a root VC so rotation is supported self->_window.rootViewController = [UIViewController new]; @@ -129,6 +174,7 @@ - (void)showMessage:(NSString *)message color:(RCTUIColor *)color backgroundColo #if !TARGET_OS_OSX // TODO(macOS GH#774) self->_label.text = message; self->_label.textColor = color; + self->_window.backgroundColor = backgroundColor; self->_window.hidden = NO; #else // [TODO(macOS GH#774) @@ -162,7 +208,11 @@ - (void)showMessage:(NSString *)message color:(RCTUIColor *)color backgroundColo return; } + // Cancel the initial message block so it doesn't display later and get stuck. + [self clearInitialMessageDelay]; + dispatch_async(dispatch_get_main_queue(), ^{ + self->_hiding = true; const NSTimeInterval MIN_PRESENTED_TIME = 0.6; NSTimeInterval presentedTime = [[NSDate date] timeIntervalSinceDate:self->_showDate]; NSTimeInterval delay = MAX(0, MIN_PRESENTED_TIME - presentedTime); @@ -178,6 +228,7 @@ - (void)showMessage:(NSString *)message color:(RCTUIColor *)color backgroundColo self->_window.frame = windowFrame; self->_window.hidden = YES; self->_window = nil; + self->_hiding = false; }]; #elif TARGET_OS_OSX // [TODO(macOS GH#774) dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ @@ -198,20 +249,23 @@ - (void)showWithURL:(NSURL *)URL RCTUIColor *backgroundColor; // TODO(macOS GH#774) NSString *message; if (URL.fileURL) { - // If dev mode is not enabled, we don't want to show this kind of notification + // If dev mode is not enabled, we don't want to show this kind of notification. #if !RCT_DEV return; #endif color = [RCTUIColor whiteColor]; //TODO(OSS Candidate ISS#2710739) UIColor -> RCTUIColor backgroundColor = [RCTUIColor blackColor]; // TODO(OSS Candidate ISS#2710739) message = [NSString stringWithFormat:@"Connect to %@ to develop JavaScript.", RCT_PACKAGER_NAME]; + [self showMessage:message color:color backgroundColor:backgroundColor]; } else { color = [RCTUIColor whiteColor]; // TODO(OSS Candidate ISS#2710739) - backgroundColor = [RCTUIColor colorWithHue:1. / 3 saturation:1 brightness:.35 alpha:1]; // TODO(OSS Candidate ISS#2710739) - message = [NSString stringWithFormat:@"Loading from %@:%@...", URL.host, URL.port]; - } + backgroundColor = [RCTUIColor colorWithHue:105 saturation:0 brightness:.25 alpha:1]; // TODO(OSS Candidate ISS#2710739) + message = [NSString stringWithFormat:@"Loading from %@\u2026", RCT_PACKAGER_NAME]; - [self showMessage:message color:color backgroundColor:backgroundColor]; + [self showInitialMessageDelayed:^{ + [self showMessage:message color:color backgroundColor:backgroundColor]; + }]; + } } - (void)updateProgress:(RCTLoadingProgress *)progress @@ -219,12 +273,27 @@ - (void)updateProgress:(RCTLoadingProgress *)progress if (!progress) { return; } + + // Cancel the initial message block so it's not flashed before progress. + [self clearInitialMessageDelay]; + dispatch_async(dispatch_get_main_queue(), ^{ + if (self->_window == nil) { + // If we didn't show the initial message, then there's no banner window. + // We need to create it here so that the progress is actually displayed. + RCTUIColor *color = [RCTUIColor whiteColor]; + RCTUIColor *backgroundColor = [RCTUIColor colorWithHue:105 saturation:0 brightness:.25 alpha:1]; + [self showMessage:[progress description] color:color backgroundColor:backgroundColor]; + } else { + // This is an optimization. Since the progress can come in quickly, + // we want to do the minimum amount of work to update the UI, + // which is to only update the label text. #if !TARGET_OS_OSX // TODO(macOS GH#774) - self->_label.text = [progress description]; + self->_label.text = [progress description]; #else // [TODO(macOS GH#774) - self->_label.stringValue = [progress description]; + self->_label.stringValue = [progress description]; #endif // ]TODO(macOS GH#774) + } }); } diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index d860fc0bf495ff..a996fda0b6fab9 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -258,10 +258,24 @@ - (instancetype)initWithParentBridge:(RCTBridge *)bridge _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; } +#if !TARGET_OS_OSX // TODO(macOS GH#774) +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} +#endif // TODO(macOS GH#774) + + (void)runRunLoop { @autoreleasepool { @@ -295,6 +309,13 @@ - (void)_tryAndHandleError:(dispatch_block_t)block } } +- (void)handleMemoryWarning +{ + 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 @@ -514,6 +535,11 @@ - (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoa } // Module may not be loaded yet, so attempt to force load it here. + // Do this only if the bridge is still valid. + if (_didInvalidate) { + return nil; + } + const BOOL result = [self.delegate respondsToSelector:@selector(bridge:didNotFindModule:)] && [self.delegate bridge:self didNotFindModule:moduleName]; if (result) { diff --git a/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceShadowNode.cpp b/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceShadowNode.cpp deleted file mode 100644 index cbb3c1998abae5..00000000000000 --- a/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceShadowNode.cpp +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -namespace facebook { -namespace react { - -extern const char RCTARTSurfaceViewComponentName[] = "ARTSurfaceView"; - -} // namespace react -} // namespace facebook diff --git a/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceShadowNode.h b/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceShadowNode.h deleted file mode 100644 index 3a26257acc5f7a..00000000000000 --- a/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceShadowNode.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include "RCTARTSurfaceViewProps.h" - -namespace facebook { -namespace react { - -extern const char RCTARTSurfaceViewComponentName[]; - -/* - * `ShadowNode` for component. - */ -using RCTARTSurfaceShadowNode = ConcreteViewShadowNode< - RCTARTSurfaceViewComponentName, - RCTARTSurfaceViewProps, - ViewEventEmitter>; - -} // namespace react -} // namespace facebook diff --git a/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentView.h b/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentView.h deleted file mode 100644 index 30a6ab992fa7b8..00000000000000 --- a/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentView.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -/** - * UIView class for root component. - */ -@interface RCTARTSurfaceViewComponentView : RCTViewComponentView - -@end diff --git a/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentView.mm deleted file mode 100644 index f8a26d871f6bf8..00000000000000 --- a/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentView.mm +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "RCTARTSurfaceViewComponentView.h" -#import -#import "RCTARTSurfaceViewComponentDescriptor.h" - -#import "FBRCTFabricComponentsPlugins.h" - -using namespace facebook::react; - -@implementation RCTARTSurfaceViewComponentView { -} - -- (instancetype)initWithFrame:(CGRect)frame -{ - if (self = [super initWithFrame:frame]) { - static const auto defaultProps = std::make_shared(); - _props = defaultProps; - } - - return self; -} - -#pragma mark - RCTComponentViewProtocol - -+ (ComponentDescriptorProvider)componentDescriptorProvider -{ - return concreteComponentDescriptorProvider(); -} - -@end - -Class RCTARTSurfaceViewCls(void) -{ - return RCTARTSurfaceViewComponentView.class; -} diff --git a/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewProps.cpp b/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewProps.cpp deleted file mode 100644 index fd94a7c0d8f73d..00000000000000 --- a/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewProps.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include "RCTARTSurfaceViewProps.h" - -#include - -namespace facebook { -namespace react { - -RCTARTSurfaceViewProps::RCTARTSurfaceViewProps( - const RCTARTSurfaceViewProps &sourceProps, - const RawProps &rawProps) - : ViewProps(sourceProps, rawProps) {} - -} // namespace react -} // namespace facebook diff --git a/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewProps.h b/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewProps.h deleted file mode 100644 index cbebf7c4de82d5..00000000000000 --- a/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewProps.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -namespace facebook { -namespace react { - -class RCTARTSurfaceViewProps final : public ViewProps { - public: - RCTARTSurfaceViewProps() = default; - RCTARTSurfaceViewProps( - const RCTARTSurfaceViewProps &sourceProps, - const RawProps &rawProps); - -#pragma mark - Props -}; - -} // namespace react -} // namespace facebook diff --git a/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm b/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm index e393dae3dabd51..4e87e202fab898 100644 --- a/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm @@ -7,6 +7,7 @@ #import "RCTImageComponentView.h" +#import #import #import #import @@ -41,6 +42,8 @@ - (instancetype)initWithFrame:(CGRect)frame _imageView = [[UIImageView alloc] initWithFrame:self.bounds]; _imageView.clipsToBounds = YES; _imageView.contentMode = (UIViewContentMode)RCTResizeModeFromImageResizeMode(defaultProps->resizeMode); + _imageView.layer.minificationFilter = kCAFilterTrilinear; + _imageView.layer.magnificationFilter = kCAFilterTrilinear; _imageResponseObserverProxy = RCTImageResponseObserverProxy(self); @@ -161,17 +164,30 @@ - (void)didReceiveImage:(UIImage *)image fromObserver:(void const *)observer resizingMode:UIImageResizingModeStretch]; } - self->_imageView.image = image; - - // Apply trilinear filtering to smooth out mis-sized images. - self->_imageView.layer.minificationFilter = kCAFilterTrilinear; - self->_imageView.layer.magnificationFilter = kCAFilterTrilinear; - - auto data = _state->getData(); - auto instrumentation = std::static_pointer_cast( - data.getImageRequest().getSharedImageInstrumentation()); - if (instrumentation) { - instrumentation->didSetImage(); + void (^didSetImage)() = ^() { + if (!self->_state) { + return; + } + auto data = self->_state->getData(); + auto instrumentation = std::static_pointer_cast( + data.getImageRequest().getSharedImageInstrumentation()); + if (instrumentation) { + instrumentation->didSetImage(); + } + }; + + if (imageProps.blurRadius > __FLT_EPSILON__) { + // Blur on a background thread to avoid blocking interaction. + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + UIImage *blurredImage = RCTBlurredImageWithRadius(image, imageProps.blurRadius); + RCTExecuteOnMainQueue(^{ + self->_imageView.image = blurredImage; + didSetImage(); + }); + }); + } else { + self->_imageView.image = image; + didSetImage(); } } diff --git a/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm b/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm index fc689ca35c324e..9da0483fad089a 100644 --- a/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm @@ -36,8 +36,16 @@ - (instancetype)initWithFrame:(CGRect)frame + (NSMutableSet *)supportedViewManagers { - static NSMutableSet *supported = - [NSMutableSet setWithObjects:@"Picker", @"DatePicker", @"ProgressView", @"SegmentedControl", @"MaskedView", nil]; + static NSMutableSet *supported = [NSMutableSet setWithObjects:@"Picker", + @"DatePicker", + @"ProgressView", + @"SegmentedControl", + @"MaskedView", + @"ARTSurfaceView", + @"ARTText", + @"ARTShape", + @"ARTGroup", + nil]; return supported; } diff --git a/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h b/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h index 3bf14b7394b3c7..60f9dca7efafd3 100644 --- a/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h +++ b/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h @@ -37,7 +37,6 @@ Class RCTSliderCls(void) __attribute__((used)); Class RCTSwitchCls(void) __attribute__((used)); Class RCTUnimplementedNativeViewCls(void) __attribute__((used)); Class RCTModalHostViewCls(void) __attribute__((used)); -Class RCTARTSurfaceViewCls(void) __attribute__((used)); Class RCTImageCls(void) __attribute__((used)); #ifdef __cplusplus diff --git a/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm b/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm index ccb07bcbb8e28a..f56ec907d8467a 100644 --- a/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm +++ b/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm @@ -26,7 +26,6 @@ {"Switch", RCTSwitchCls}, {"UnimplementedNativeView", RCTUnimplementedNativeViewCls}, {"ModalHostView", RCTModalHostViewCls}, - {"ARTSurfaceView", RCTARTSurfaceViewCls}, {"Image", RCTImageCls}, }; diff --git a/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.mm index 00a1cb35a02ef8..982f63d5037a1a 100644 --- a/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.mm @@ -86,6 +86,12 @@ - (void)updateState:(facebook::react::State::Shared const &)state [self _updateStateIfNecessary]; } +- (void)prepareForRecycle +{ + [super prepareForRecycle]; + _state.reset(); +} + + (ComponentDescriptorProvider)componentDescriptorProvider { return concreteComponentDescriptorProvider(); diff --git a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm index 05b8f7ac3f7238..1e7b92a2d104bb 100644 --- a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm @@ -42,6 +42,16 @@ @implementation RCTTextInputComponentView { * textInputDidChange]` call. */ BOOL _ignoreNextTextInputCall; + + /* + * A flag that when set to true, `_mostRecentEventCount` won't be incremented when `[self _updateState]` + * and delegate methods `textInputDidChange` and `textInputDidChangeSelection` will exit early. + * + * Setting `_backedTextInputView.attributedText` triggers delegate methods `textInputDidChange` and + * `textInputDidChangeSelection` for multiline text input only. + * In multiline text input this is undesirable as we don't want to be sending events for changes that JS triggered. + */ + BOOL _comingFromJS; } - (instancetype)initWithFrame:(CGRect)frame @@ -55,6 +65,7 @@ - (instancetype)initWithFrame:(CGRect)frame _backedTextInputView.frame = self.bounds; _backedTextInputView.textInputDelegate = self; _ignoreNextTextInputCall = NO; + _comingFromJS = NO; [self addSubview:_backedTextInputView]; } @@ -185,7 +196,9 @@ - (void)updateState:(State::Shared const &)state oldState:(State::Shared const & if (_mostRecentEventCount == _state->getData().mostRecentEventCount) { auto data = _state->getData(); + _comingFromJS = YES; [self _setAttributedString:RCTNSAttributedStringFromAttributedStringBox(data.attributedStringBox)]; + _comingFromJS = NO; } } @@ -204,11 +217,6 @@ - (void)_setAttributedString:(NSAttributedString *)attributedString { UITextRange *selectedRange = [_backedTextInputView selectedTextRange]; _backedTextInputView.attributedText = attributedString; - // Calling `[_backedTextInputView setAttributedText]` results - // in `textInputDidChangeSelection` being called but not `textInputDidChange`. - // For `_ignoreNextTextInputCall` to have correct value, these calls - // need to be balanced, that's why we manually set the flag here. - _ignoreNextTextInputCall = NO; if (_lastStringStateWasUpdatedWith.length == attributedString.length) { // Calling `[_backedTextInputView setAttributedText]` moves caret // to the end of text input field. This cancels any selection as well @@ -225,6 +233,7 @@ - (void)prepareForRecycle _backedTextInputView.attributedText = [[NSAttributedString alloc] init]; _mostRecentEventCount = 0; _state.reset(); + _comingFromJS = NO; _lastStringStateWasUpdatedWith = nil; _ignoreNextTextInputCall = NO; } @@ -334,10 +343,15 @@ - (BOOL)textInputShouldChangeTextInRange:(NSRange)range replacementText:(NSStrin - (void)textInputDidChange { + if (_comingFromJS) { + return; + } + if (_ignoreNextTextInputCall) { _ignoreNextTextInputCall = NO; return; } + [self _updateState]; if (_eventEmitter) { @@ -347,6 +361,9 @@ - (void)textInputDidChange - (void)textInputDidChangeSelection { + if (_comingFromJS) { + return; + } auto const &props = *std::static_pointer_cast(_props); if (props.traits.multiline && ![_lastStringStateWasUpdatedWith isEqual:_backedTextInputView.attributedText]) { [self textInputDidChange]; @@ -379,7 +396,7 @@ - (void)_updateState auto data = _state->getData(); _lastStringStateWasUpdatedWith = attributedString; data.attributedStringBox = RCTAttributedStringBoxFromNSAttributedString(attributedString); - _mostRecentEventCount += 1; + _mostRecentEventCount += _comingFromJS ? 0 : 1; data.mostRecentEventCount = _mostRecentEventCount; _state->updateState(std::move(data)); } @@ -419,8 +436,8 @@ - (void)setTextAndSelection:(NSInteger)eventCount if (_mostRecentEventCount != eventCount) { return; } - - if (value) { + _comingFromJS = YES; + if (![value isEqualToString:_backedTextInputView.attributedText.string]) { NSMutableAttributedString *mutableString = [[NSMutableAttributedString alloc] initWithAttributedString:_backedTextInputView.attributedText]; [mutableString replaceCharactersInRange:NSMakeRange(0, _backedTextInputView.attributedText.length) @@ -438,6 +455,7 @@ - (void)setTextAndSelection:(NSInteger)eventCount UITextRange *range = [_backedTextInputView textRangeFromPosition:startPosition toPosition:endPosition]; [_backedTextInputView setSelectedTextRange:range notifyDelegate:NO]; } + _comingFromJS = NO; } @end diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 2fba022371ee5a..a0f8d7af169061 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -48,6 +48,7 @@ - (void)setContentView:(UIView *)contentView if (_contentView) { [self addSubview:_contentView]; + _contentView.frame = RCTCGRectFromRect(_layoutMetrics.getContentFrame()); } } diff --git a/React/Fabric/RCTSurfacePresenter.h b/React/Fabric/RCTSurfacePresenter.h index e23e9a39ac227c..38538abc99730b 100644 --- a/React/Fabric/RCTSurfacePresenter.h +++ b/React/Fabric/RCTSurfacePresenter.h @@ -10,8 +10,8 @@ #import #import #import +#import #import -#import NS_ASSUME_NONNULL_BEGIN diff --git a/React/Fabric/RCTSurfacePresenterBridgeAdapter.mm b/React/Fabric/RCTSurfacePresenterBridgeAdapter.mm index 3a97f969a20ef5..307e6aff299acd 100644 --- a/React/Fabric/RCTSurfacePresenterBridgeAdapter.mm +++ b/React/Fabric/RCTSurfacePresenterBridgeAdapter.mm @@ -17,9 +17,9 @@ #import #import +#import #import #import -#import using namespace facebook::react; diff --git a/React/Fabric/Utils/MainRunLoopEventBeat.h b/React/Fabric/Utils/MainRunLoopEventBeat.h index 055728e322b37f..eeb2aeea4538e7 100644 --- a/React/Fabric/Utils/MainRunLoopEventBeat.h +++ b/React/Fabric/Utils/MainRunLoopEventBeat.h @@ -9,8 +9,8 @@ #include #include +#include #include -#include namespace facebook { namespace react { diff --git a/React/Fabric/Utils/RuntimeEventBeat.h b/React/Fabric/Utils/RuntimeEventBeat.h index bc95c141ea9b09..d55980f40c604f 100644 --- a/React/Fabric/Utils/RuntimeEventBeat.h +++ b/React/Fabric/Utils/RuntimeEventBeat.h @@ -7,8 +7,8 @@ #include #include +#include #include -#include namespace facebook { namespace react { diff --git a/React/Views/ScrollView/RCTScrollViewManager.m b/React/Views/ScrollView/RCTScrollViewManager.m index 26801ca0165306..cabd0ccd224886 100644 --- a/React/Views/ScrollView/RCTScrollViewManager.m +++ b/React/Views/ScrollView/RCTScrollViewManager.m @@ -151,7 +151,6 @@ - (RCTPlatformView *)view // TODO(macOS GH#774) addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { RCTScrollView *view = viewRegistry[reactTag]; if (!view || ![view isKindOfClass:[RCTScrollView class]]) { - RCTLogError(@"Cannot find RCTScrollView with tag #%@", reactTag); return; } diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/network/BUCK b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/network/BUCK index f5842dcae00118..ebfebaf7fe9f4e 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/network/BUCK +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/network/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "network", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/ReactNativeTestRule.java b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/ReactNativeTestRule.java index 1dd5b381a79bc7..8d6252f28b8c88 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/ReactNativeTestRule.java +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/ReactNativeTestRule.java @@ -95,6 +95,11 @@ public void run() { public void onReactContextInitialized(ReactContext reactContext) { final UIManagerModule uiManagerModule = reactContext.getCatalystInstance().getNativeModule(UIManagerModule.class); + + if (uiManagerModule == null) { + return; + } + uiManagerModule .getUIImplementation() .setLayoutUpdateListener( diff --git a/ReactAndroid/src/main/java/com/facebook/debug/holder/BUCK b/ReactAndroid/src/main/java/com/facebook/debug/holder/BUCK index 9212d5990f14dd..c1ee4ded0329dd 100644 --- a/ReactAndroid/src/main/java/com/facebook/debug/holder/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/debug/holder/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "holder", srcs = glob(["*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/debug/tags/BUCK b/ReactAndroid/src/main/java/com/facebook/debug/tags/BUCK index 1442e63d2acfdf..876be9f2ba6753 100644 --- a/ReactAndroid/src/main/java/com/facebook/debug/tags/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/debug/tags/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "tags", srcs = glob(["*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/BUCK b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/BUCK index 9c844d1b75b321..cec027de58b101 100644 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "IS_OSS_BU rn_android_library( name = "FBReactNativeSpec", srcs = glob(["*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = ["PUBLIC"], deps = [ react_native_dep("third-party/java/jsr-305:jsr-305"), diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/BUCK b/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/BUCK index aacd3e0fe2899b..3b4ea04dbfdff0 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/BUCK @@ -11,6 +11,7 @@ rn_android_library( rn_android_library( name = "hermes_samplingprofiler", srcs = ["HermesSamplingProfiler.java"], + labels = ["supermodule:android/default/public.react_native.infra"], visibility = ["PUBLIC"], deps = [ react_native_dep("java/com/facebook/proguard/annotations:annotations"), @@ -29,6 +30,7 @@ rn_xplat_cxx_library( headers = ["HermesSamplingProfiler.h"], header_namespace = "", compiler_flags = ["-fexceptions"], + labels = ["supermodule:android/default/public.react_native.infra"], platforms = ANDROID, soname = "libjsijniprofiler.$(ext)", visibility = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 17eae9a95057da..59ccbbedefb4b8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -470,7 +470,9 @@ public void onBackPressed() { } else { DeviceEventManagerModule deviceEventManagerModule = reactContext.getNativeModule(DeviceEventManagerModule.class); - deviceEventManagerModule.emitHardwareBackPressed(); + if (deviceEventManagerModule != null) { + deviceEventManagerModule.emitHardwareBackPressed(); + } } } @@ -497,7 +499,9 @@ public void onNewIntent(Intent intent) { || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action))) { DeviceEventManagerModule deviceEventManagerModule = currentContext.getNativeModule(DeviceEventManagerModule.class); - deviceEventManagerModule.emitNewIntentReceived(uri); + if (deviceEventManagerModule != null) { + deviceEventManagerModule.emitNewIntentReceived(uri); + } } currentContext.onNewIntent(mCurrentActivity, intent); } @@ -775,9 +779,12 @@ public void onConfigurationChanged(Context updatedContext, @Nullable Configurati ReactContext currentReactContext = getCurrentReactContext(); if (currentReactContext != null) { - currentReactContext - .getNativeModule(AppearanceModule.class) - .onConfigurationChanged(updatedContext); + AppearanceModule appearanceModule = + currentReactContext.getNativeModule(AppearanceModule.class); + + if (appearanceModule != null) { + appearanceModule.onConfigurationChanged(updatedContext); + } } } @@ -1143,21 +1150,29 @@ private void attachRootViewToInstance(final ReactRoot reactRoot) { @Nullable Bundle initialProperties = reactRoot.getAppProperties(); - final int rootTag = - uiManager.addRootView( - reactRoot.getRootViewGroup(), - initialProperties == null - ? new WritableNativeMap() - : Arguments.fromBundle(initialProperties), - reactRoot.getInitialUITemplate()); - reactRoot.setRootViewTag(rootTag); + final int rootTag; + if (reactRoot.getUIManagerType() == FABRIC) { - // Fabric requires to call updateRootLayoutSpecs before starting JS Application, - // this ensures the root will hace the correct pointScaleFactor. - uiManager.updateRootLayoutSpecs( - rootTag, reactRoot.getWidthMeasureSpec(), reactRoot.getHeightMeasureSpec()); + rootTag = + uiManager.startSurface( + reactRoot.getRootViewGroup(), + reactRoot.getJSModuleName(), + initialProperties == null + ? new WritableNativeMap() + : Arguments.fromBundle(initialProperties), + reactRoot.getWidthMeasureSpec(), + reactRoot.getHeightMeasureSpec()); + reactRoot.setRootViewTag(rootTag); reactRoot.setShouldLogContentAppeared(true); } else { + rootTag = + uiManager.addRootView( + reactRoot.getRootViewGroup(), + initialProperties == null + ? new WritableNativeMap() + : Arguments.fromBundle(initialProperties), + reactRoot.getInitialUITemplate()); + reactRoot.setRootViewTag(rootTag); reactRoot.runApplication(); } Systrace.beginAsyncSection( @@ -1245,32 +1260,38 @@ private ReactApplicationContext createReactContext( reactContext.initializeWithInstance(catalystInstance); - // TODO(T46487253): Remove after task is closed - FLog.e( - ReactConstants.TAG, - "ReactInstanceManager.createReactContext: mJSIModulePackage " - + (mJSIModulePackage != null ? "not null" : "null")); + 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())); - // TODO(T46487253): Remove after task is closed - FLog.e( - ReactConstants.TAG, - "ReactInstanceManager.createReactContext: ReactFeatureFlags.useTurboModules == " - + (ReactFeatureFlags.useTurboModules == false ? "false" : "true")); + 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); - // TODO(T46487253): Remove after task is closed - FLog.e( - ReactConstants.TAG, - "ReactInstanceManager.createReactContext: TurboModuleManager " - + (turboModuleManager == null ? "not created" : "created")); + 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); diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java index 30b50691b9651a..7c82dd1539bc62 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java @@ -94,29 +94,19 @@ public interface ReactRootViewEventListener { private int mLastWidth = 0; private int mLastHeight = 0; private @UIManagerType int mUIManagerType = DEFAULT; - private final boolean mUseSurface; public ReactRootView(Context context) { super(context); - mUseSurface = false; - init(); - } - - public ReactRootView(Context context, boolean useSurface) { - super(context); - mUseSurface = useSurface; init(); } public ReactRootView(Context context, AttributeSet attrs) { super(context, attrs); - mUseSurface = false; init(); } public ReactRootView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - mUseSurface = false; init(); } @@ -126,13 +116,6 @@ private void init() { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // TODO: T60453649 - Add test automation to verify behavior of onMeasure - - if (mUseSurface) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - return; - } - Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactRootView.onMeasure"); try { boolean measureSpecsUpdated = @@ -200,9 +183,12 @@ public void onChildStartedNativeGesture(MotionEvent androidEvent) { return; } ReactContext reactContext = mReactInstanceManager.getCurrentReactContext(); - EventDispatcher eventDispatcher = - reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); - mJSTouchDispatcher.onChildStartedNativeGesture(androidEvent, eventDispatcher); + UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); + + if (uiManager != null) { + EventDispatcher eventDispatcher = uiManager.getEventDispatcher(); + mJSTouchDispatcher.onChildStartedNativeGesture(androidEvent, eventDispatcher); + } } @Override @@ -285,9 +271,12 @@ private void dispatchJSTouchEvent(MotionEvent event) { return; } ReactContext reactContext = mReactInstanceManager.getCurrentReactContext(); - EventDispatcher eventDispatcher = - reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); - mJSTouchDispatcher.handleTouchEvent(event, eventDispatcher); + UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); + + if (uiManager != null) { + EventDispatcher eventDispatcher = uiManager.getEventDispatcher(); + mJSTouchDispatcher.handleTouchEvent(event, eventDispatcher); + } } @Override @@ -301,9 +290,6 @@ public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - if (mUseSurface) { - super.onLayout(changed, left, top, right, bottom); - } // No-op since UIManagerModule handles actually laying out children. } @@ -387,10 +373,6 @@ public void startReactApplication( mAppProperties = initialProperties; mInitialUITemplate = initialUITemplate; - if (mUseSurface) { - // TODO initialize surface here - } - mReactInstanceManager.createReactContextInBackground(); attachToReactInstanceManager(); @@ -528,26 +510,22 @@ public void runApplication() { CatalystInstance catalystInstance = reactContext.getCatalystInstance(); String jsAppModuleName = getJSModuleName(); - if (mUseSurface) { - // TODO call surface's runApplication - } else { - if (mWasMeasured) { - updateRootLayoutSpecs(mWidthMeasureSpec, mHeightMeasureSpec); - } + if (mWasMeasured) { + updateRootLayoutSpecs(mWidthMeasureSpec, mHeightMeasureSpec); + } - WritableNativeMap appParams = new WritableNativeMap(); - appParams.putDouble("rootTag", getRootViewTag()); - @Nullable Bundle appProperties = getAppProperties(); - if (appProperties != null) { - appParams.putMap("initialProps", Arguments.fromBundle(appProperties)); - } + WritableNativeMap appParams = new WritableNativeMap(); + appParams.putDouble("rootTag", getRootViewTag()); + @Nullable Bundle appProperties = getAppProperties(); + if (appProperties != null) { + appParams.putMap("initialProps", Arguments.fromBundle(appProperties)); + } - mShouldLogContentAppeared = true; + mShouldLogContentAppeared = true; - // TODO T62192299: remove this - FLog.e(TAG, "runApplication: call AppRegistry.runApplication"); - catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams); - } + // 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); } @@ -749,10 +727,12 @@ private void emitOrientationChanged(final int newRotation) { } private void emitUpdateDimensionsEvent() { - mReactInstanceManager - .getCurrentReactContext() - .getNativeModule(DeviceInfoModule.class) - .emitUpdateDimensionsEvent(); + DeviceInfoModule deviceInfo = + mReactInstanceManager.getCurrentReactContext().getNativeModule(DeviceInfoModule.class); + + if (deviceInfo != null) { + deviceInfo.emitUpdateDimensionsEvent(); + } } private WritableMap createKeyboardEventPayload( diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/BUCK b/ReactAndroid/src/main/java/com/facebook/react/animated/BUCK index edba01a1b1485d..57e9752b640e08 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/BUCK @@ -6,6 +6,7 @@ rn_android_library( "*.java", ]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), 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 919b5a5f16e9f4..ead07f9512229b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java @@ -130,7 +130,8 @@ public void initialize() { // TODO T59412313 Implement this API on FabricUIManager to use in bridgeless mode if (reactApplicationContext != null && !reactApplicationContext.isBridgeless()) { reactApplicationContext.addLifecycleEventListener(this); - UIManagerModule uiManager = reactApplicationContext.getNativeModule(UIManagerModule.class); + UIManagerModule uiManager = + Assertions.assertNotNull(reactApplicationContext.getNativeModule(UIManagerModule.class)); uiManager.addUIManagerListener(this); } } @@ -191,7 +192,9 @@ private NativeAnimatedNodesManager getNodesManager() { ReactApplicationContext reactApplicationContext = getReactApplicationContextIfActiveOrWarn(); if (reactApplicationContext != null) { - UIManagerModule uiManager = reactApplicationContext.getNativeModule(UIManagerModule.class); + UIManagerModule uiManager = + Assertions.assertNotNull( + reactApplicationContext.getNativeModule(UIManagerModule.class)); mNodesManager = new NativeAnimatedNodesManager(uiManager); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java index 9ce9e66470ccfb..2c99f40d655a5f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java @@ -15,12 +15,14 @@ import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.UIManager; import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.bridge.WritableMap; import com.facebook.react.common.ReactConstants; import com.facebook.react.uimanager.IllegalViewOperationException; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.events.Event; +import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.react.uimanager.events.EventDispatcherListener; import java.util.ArrayDeque; import java.util.ArrayList; @@ -53,14 +55,16 @@ // there will be only one driver per mapping so all code code should be optimized around that. private final Map> mEventDrivers = new HashMap<>(); private final UIManagerModule.CustomEventNamesResolver mCustomEventNamesResolver; - private final UIManagerModule mUIManagerModule; + private final UIManager mUIManager; private int mAnimatedGraphBFSColor = 0; // Used to avoid allocating a new array on every frame in `runUpdates` and `onEventDispatch`. private final List mRunUpdateNodeList = new LinkedList<>(); public NativeAnimatedNodesManager(UIManagerModule uiManager) { - mUIManagerModule = uiManager; - uiManager.getEventDispatcher().addListener(this); + mUIManager = uiManager; + mUIManager.getEventDispatcher().addListener(this); + // TODO T64216139 Remove dependency of UIManagerModule when the Constants are not in Native + // anymore mCustomEventNamesResolver = uiManager.getDirectEventNamesResolver(); } @@ -85,7 +89,7 @@ public void createAnimatedNode(int tag, ReadableMap config) { } else if ("value".equals(type)) { node = new ValueAnimatedNode(config); } else if ("props".equals(type)) { - node = new PropsAnimatedNode(config, this, mUIManagerModule); + node = new PropsAnimatedNode(config, this, mUIManager); } else if ("interpolation".equals(type)) { node = new InterpolationAnimatedNode(config); } else if ("addition".equals(type)) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK b/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK index eaa8ab4df53479..53ac6202190a9c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK @@ -21,6 +21,7 @@ rn_android_library( exclude = INTERFACES, ), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], proguard_config = "reactnative.pro", provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), @@ -65,6 +66,7 @@ rn_android_library( name = "interfaces", srcs = glob(INTERFACES), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], proguard_config = "reactnative.pro", provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java index 09f0f6db3f10e3..1a5067b7edb358 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java @@ -62,8 +62,10 @@ public interface CatalystInstance boolean hasNativeModule(Class nativeModuleInterface); + @Nullable T getNativeModule(Class nativeModuleInterface); + @Nullable NativeModule getNativeModule(String moduleName); JSIModule getJSIModule(JSIModuleType moduleType); @@ -97,14 +99,18 @@ public interface CatalystInstance void setGlobalVariable(String propName, String jsonValue); /** - * Get the C pointer (as a long) to the JavaScriptCore context associated with this instance. + * Do not use this anymore. Use {@link #getRuntimeExecutor()} instead. Get the C pointer (as a + * long) to the JavaScriptCore context associated with this instance. * *

Use the following pattern to ensure that the JS context is not cleared while you are using * it: JavaScriptContextHolder jsContext = reactContext.getJavaScriptContextHolder() * synchronized(jsContext) { nativeThingNeedingJsContext(jsContext.get()); } */ + @Deprecated JavaScriptContextHolder getJavaScriptContextHolder(); + RuntimeExecutor getRuntimeExecutor(); + void addJSIModules(List jsiModules); /** 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 a6ac1405b054a4..62cdb8a6cda784 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java @@ -562,6 +562,7 @@ public boolean hasNativeModule(Class nativeModuleInt } @Override + @Nullable public T getNativeModule(Class nativeModuleInterface) { return (T) getNativeModule(getNameFromAnnotation(nativeModuleInterface)); } @@ -577,23 +578,28 @@ private TurboModuleRegistry getTurboModuleRegistry() { } @Override + @Nullable public NativeModule getNativeModule(String moduleName) { if (getTurboModuleRegistry() != null) { TurboModule turboModule = getTurboModuleRegistry().getModule(moduleName); - // TODO(T46487253): Remove after task is closed - FLog.e( - ReactConstants.TAG, - "CatalystInstanceImpl.getNativeModule: TurboModule " - + moduleName - + (turboModule == null ? " not" : "") - + " found"); + 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; } } - return mNativeModuleRegistry.getModule(moduleName); + return mNativeModuleRegistry.hasModule(moduleName) + ? mNativeModuleRegistry.getModule(moduleName) + : null; } private String getNameFromAnnotation(Class nativeModuleInterface) { @@ -658,6 +664,9 @@ public JavaScriptContextHolder getJavaScriptContextHolder() { return mJavaScriptContextHolder; } + @Override + public native RuntimeExecutor getRuntimeExecutor(); + @Override public void addJSIModules(List jsiModules) { mJSIModuleRegistry.registerModules(jsiModules); diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java index fe13dd689810e1..126237e74e8e31 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -158,6 +158,7 @@ public boolean hasNativeModule(Class nativeModuleInt } /** @return the instance of the specified module interface associated with this ReactContext. */ + @Nullable public T getNativeModule(Class nativeModuleInterface) { if (mCatalystInstance == null) { raiseCatalystInstanceMissingException(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/RuntimeExecutor.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/RuntimeExecutor.java new file mode 100644 index 00000000000000..2e001202e43185 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/RuntimeExecutor.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.bridge; + +import com.facebook.jni.HybridData; +import com.facebook.proguard.annotations.DoNotStrip; + +/** A Java holder for a C++ RuntimeExecutor. */ +public class RuntimeExecutor { + + @DoNotStrip private HybridData mHybridData; + + public RuntimeExecutor(HybridData hybridData) { + mHybridData = hybridData; + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java index 89ef6a717209d1..170fc7fcd3f25e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java @@ -10,6 +10,7 @@ import static com.facebook.infer.annotation.ThreadConfined.UI; import android.view.View; +import androidx.annotation.AnyThread; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import com.facebook.infer.annotation.ThreadConfined; @@ -22,6 +23,15 @@ public interface UIManager extends JSIModule, PerformanceCounter { int addRootView( final T rootView, WritableMap initialProps, @Nullable String initialUITemplate); + /** Registers a new root view with width and height. */ + @AnyThread + int startSurface( + final T rootView, + final String moduleName, + final WritableMap initialProps, + int widthMeasureSpec, + int heightMeasureSpec); + /** * Updates the layout specs of the RootShadowNode based on the Measure specs received by * parameters. diff --git a/ReactAndroid/src/main/java/com/facebook/react/common/BUCK b/ReactAndroid/src/main/java/com/facebook/react/common/BUCK index 5c67573a0254d1..0e5a4b52caeac1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/common/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/common/BUCK @@ -11,6 +11,7 @@ rn_android_library( exclude = SUB_PROJECTS, ), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/common/network/BUCK b/ReactAndroid/src/main/java/com/facebook/react/common/network/BUCK index 934c22700dffe1..86005fbc76ae79 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/common/network/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/common/network/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "network", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/config/BUCK b/ReactAndroid/src/main/java/com/facebook/react/config/BUCK index 82c24dc8158a27..347452197e226b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/config/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/config/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library") rn_android_library( name = "config", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index c5b9de82a4453f..c04a883d5fb5cc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -23,6 +23,9 @@ public class ReactFeatureFlags { */ public static volatile boolean useTurboModules = false; + /** Should we output debug logs to debug the TurboModule infra? */ + public static volatile boolean enableTurboModuleDebugLogs = false; + /* * This feature flag enables logs for Fabric */ diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK index a5c503d2f750b0..1c2b6c72e761b4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "devsupport", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], manifest = "AndroidManifest.xml", provided_deps = [ react_native_dep("third-party/android/androidx:core"), @@ -46,6 +47,7 @@ rn_android_library( name = "interfaces", srcs = glob(["interfaces/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java index 8a99c522ba9fbf..e93b645cb83bd5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java @@ -962,19 +962,22 @@ private void handleCaptureHeap(final Responder responder) { return; } JSCHeapCapture heapCapture = mCurrentContext.getNativeModule(JSCHeapCapture.class); - heapCapture.captureHeap( - mApplicationContext.getCacheDir().getPath(), - new JSCHeapCapture.CaptureCallback() { - @Override - public void onSuccess(File capture) { - responder.respond(capture.toString()); - } - @Override - public void onFailure(JSCHeapCapture.CaptureException error) { - responder.error(error.toString()); - } - }); + if (heapCapture != null) { + heapCapture.captureHeap( + mApplicationContext.getCacheDir().getPath(), + new JSCHeapCapture.CaptureCallback() { + @Override + public void onSuccess(File capture) { + responder.respond(capture.toString()); + } + + @Override + public void onFailure(JSCHeapCapture.CaptureException error) { + responder.error(error.toString()); + } + }); + } } private void updateLastErrorInfo( diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/BUCK b/ReactAndroid/src/main/java/com/facebook/react/fabric/BUCK index 7c0d2e0c11a8fa..4aa1d97440a5f3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/BUCK @@ -9,6 +9,7 @@ rn_android_library( "mounting/**/*.java", ]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), 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 4d55cf236d6038..0caf99934dd9f2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java @@ -8,6 +8,7 @@ package com.facebook.react.fabric; import androidx.annotation.NonNull; +import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.JSIModuleProvider; import com.facebook.react.bridge.JavaScriptContextHolder; import com.facebook.react.bridge.ReactApplicationContext; @@ -19,18 +20,23 @@ import com.facebook.react.fabric.mounting.LayoutMetricsConversions; import com.facebook.react.fabric.mounting.MountingManager; import com.facebook.react.fabric.mounting.mountitems.BatchMountItem; +import com.facebook.react.fabric.mounting.mountitems.CreateMountItem; import com.facebook.react.fabric.mounting.mountitems.DeleteMountItem; +import com.facebook.react.fabric.mounting.mountitems.DispatchCommandMountItem; import com.facebook.react.fabric.mounting.mountitems.DispatchIntCommandMountItem; import com.facebook.react.fabric.mounting.mountitems.DispatchStringCommandMountItem; import com.facebook.react.fabric.mounting.mountitems.InsertMountItem; import com.facebook.react.fabric.mounting.mountitems.MountItem; import com.facebook.react.fabric.mounting.mountitems.PreAllocateViewMountItem; +import com.facebook.react.fabric.mounting.mountitems.RemoveDeleteMultiMountItem; import com.facebook.react.fabric.mounting.mountitems.RemoveMountItem; +import com.facebook.react.fabric.mounting.mountitems.SendAccessibilityEvent; import com.facebook.react.fabric.mounting.mountitems.UpdateEventEmitterMountItem; import com.facebook.react.fabric.mounting.mountitems.UpdateLayoutMountItem; import com.facebook.react.fabric.mounting.mountitems.UpdateLocalDataMountItem; import com.facebook.react.fabric.mounting.mountitems.UpdatePaddingMountItem; import com.facebook.react.fabric.mounting.mountitems.UpdatePropsMountItem; +import com.facebook.react.fabric.mounting.mountitems.UpdateStateMountItem; import com.facebook.react.uimanager.StateWrapper; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.events.BatchEventDispatchedListener; @@ -83,7 +89,8 @@ public UIManager get() { private FabricUIManager createUIManager(@NonNull EventBeatManager eventBeatManager) { Systrace.beginSection( Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "FabricJSIModuleProvider.createUIManager"); - UIManagerModule nativeModule = mReactApplicationContext.getNativeModule(UIManagerModule.class); + UIManagerModule nativeModule = + Assertions.assertNotNull(mReactApplicationContext.getNativeModule(UIManagerModule.class)); EventDispatcher eventDispatcher = nativeModule.getEventDispatcher(); FabricUIManager fabricUIManager = new FabricUIManager( @@ -99,33 +106,38 @@ private FabricUIManager createUIManager(@NonNull EventBeatManager eventBeatManag // TODO T31905686: eager load Fabric classes, this is temporary and it will be removed // in the near future private static void loadClasses() { - BatchEventDispatchedListener.class.getClass(); - ReactNativeConfig.class.getClass(); - FabricComponents.class.getClass(); - StateWrapper.class.getClass(); + EventBeatManager.class.getClass(); + EventEmitterWrapper.class.getClass(); FabricEventEmitter.class.getClass(); - FabricUIManager.class.getClass(); - GuardedFrameCallback.class.getClass(); BatchMountItem.class.getClass(); + CreateMountItem.class.getClass(); DeleteMountItem.class.getClass(); + DispatchCommandMountItem.class.getClass(); DispatchIntCommandMountItem.class.getClass(); DispatchStringCommandMountItem.class.getClass(); InsertMountItem.class.getClass(); MountItem.class.getClass(); + PreAllocateViewMountItem.class.getClass(); + RemoveDeleteMultiMountItem.class.getClass(); RemoveMountItem.class.getClass(); + SendAccessibilityEvent.class.getClass(); UpdateEventEmitterMountItem.class.getClass(); UpdateLayoutMountItem.class.getClass(); UpdateLocalDataMountItem.class.getClass(); UpdatePaddingMountItem.class.getClass(); UpdatePropsMountItem.class.getClass(); + UpdateStateMountItem.class.getClass(); LayoutMetricsConversions.class.getClass(); MountingManager.class.getClass(); Binding.class.getClass(); ComponentFactoryDelegate.class.getClass(); - EventBeatManager.class.getClass(); - EventEmitterWrapper.class.getClass(); - StateWrapperImpl.class.getClass(); + FabricComponents.class.getClass(); FabricSoLoader.class.getClass(); - PreAllocateViewMountItem.class.getClass(); + FabricUIManager.class.getClass(); + GuardedFrameCallback.class.getClass(); + StateWrapper.class.getClass(); + StateWrapperImpl.class.getClass(); + BatchEventDispatchedListener.class.getClass(); + ReactNativeConfig.class.getClass(); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index d63206e3f2267c..e5239c8db9835d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -17,6 +17,7 @@ import static com.facebook.react.uimanager.common.UIManagerType.FABRIC; import android.annotation.SuppressLint; +import android.content.Context; import android.os.SystemClock; import android.view.View; import androidx.annotation.AnyThread; @@ -195,6 +196,7 @@ public int addRootView( return rootTag; } + @Override @AnyThread @ThreadConfined(ANY) public int startSurface( @@ -204,8 +206,9 @@ public int startSurface( int widthMeasureSpec, int heightMeasureSpec) { final int rootTag = ReactRootViewTagGenerator.getNextRootViewTag(); + Context context = rootView.getContext(); ThemedReactContext reactContext = - new ThemedReactContext(mReactApplicationContext, rootView.getContext(), moduleName); + new ThemedReactContext(mReactApplicationContext, context, moduleName); if (ENABLE_FABRIC_LOGS) { FLog.d(TAG, "Starting surface for module: %s and reactTag: %d", moduleName, rootTag); } @@ -219,8 +222,8 @@ public int startSurface( getMaxSize(widthMeasureSpec), getMinSize(heightMeasureSpec), getMaxSize(heightMeasureSpec), - I18nUtil.getInstance().isRTL(rootView.getContext()), - I18nUtil.getInstance().doLeftAndRightSwapInRTL(rootView.getContext())); + I18nUtil.getInstance().isRTL(context), + I18nUtil.getInstance().doLeftAndRightSwapInRTL(context)); return rootTag; } @@ -522,7 +525,6 @@ private void scheduleMountItem( long layoutEndTime, long finishTransactionStartTime, long finishTransactionEndTime) { - // TODO T31905686: support multithreading // When Binding.cpp calls scheduleMountItems during a commit phase, it always calls with // a BatchMountItem. No other sites call into this with a BatchMountItem, and Binding.cpp only // calls scheduleMountItems with a BatchMountItem. @@ -842,12 +844,6 @@ public void updateRootLayoutSpecs( if (reactContext != null) { isRTL = I18nUtil.getInstance().isRTL(reactContext); doLeftAndRightSwapInRTL = I18nUtil.getInstance().doLeftAndRightSwapInRTL(reactContext); - } else { - // TODO T65116569: analyze why this happens - ReactSoftException.logSoftException( - TAG, - new IllegalStateException( - "updateRootLayoutSpecs called before ReactContext set for tag: " + rootTag)); } mBinding.setConstraints( diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK index fc4d7c9c768531..83d5ba3a4fb4fc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK @@ -18,6 +18,7 @@ rn_xplat_cxx_library( "-frtti", ], fbandroid_allow_jni_merging = True, + labels = ["supermodule:android/default/public.react_native.infra"], platforms = (ANDROID), preprocessor_flags = [ "-DLOG_TAG=\"ReactNative\"", @@ -32,7 +33,7 @@ rn_xplat_cxx_library( react_native_xplat_target("fabric/scheduler:scheduler"), react_native_xplat_target("fabric/componentregistry:componentregistry"), react_native_xplat_target("fabric/components/scrollview:scrollview"), - react_native_xplat_target("utils:utils"), + react_native_xplat_target("runtimeexecutor:runtimeexecutor"), react_native_target("jni/react/jni:jni"), "//xplat/fbsystrace:fbsystrace", "//xplat/folly:molly", diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventBeatManager.h b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventBeatManager.h index 5a36037c7d3334..5ed943f226cec2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventBeatManager.h +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventBeatManager.h @@ -10,9 +10,9 @@ #include #include +#include #include #include -#include namespace facebook { namespace react { diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateStateMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateStateMountItem.java index 2eae18797061a9..4544e8f935e23e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateStateMountItem.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateStateMountItem.java @@ -35,7 +35,7 @@ public String toString() { new StringBuilder("UpdateStateMountItem [").append(mReactTag).append("]"); if (IS_DEVELOPMENT_ENVIRONMENT) { - result.append(" state: ").append(mStateWrapper != null ? mStateWrapper : ""); + result.append(" state: ").append(mStateWrapper != null ? mStateWrapper.getState() : ""); } return result.toString(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/BUCK b/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/BUCK index ef047b2e31f02e..1f1f74690a4719 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "react_nat rn_android_library( name = "jscexecutor", srcs = glob(["*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/jstasks/BUCK b/ReactAndroid/src/main/java/com/facebook/react/jstasks/BUCK index fa2fc5ceadf033..b2cdc99110b575 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/jstasks/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/jstasks/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "jstasks", srcs = glob(["*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/module/annotations/BUCK b/ReactAndroid/src/main/java/com/facebook/react/module/annotations/BUCK index 211b98157bf10e..f081fc83a17774 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/module/annotations/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/module/annotations/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "annotations", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], required_for_source_only_abi = True, visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/module/model/BUCK b/ReactAndroid/src/main/java/com/facebook/react/module/model/BUCK index b76f609c809272..59e700971e872b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/module/model/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/module/model/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "model", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/module/processing/BUCK b/ReactAndroid/src/main/java/com/facebook/react/module/processing/BUCK index 663c170036449a..b2c8041bdc6981 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/module/processing/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/module/processing/BUCK @@ -15,6 +15,7 @@ rn_java_annotation_processor( rn_java_library( name = "processing-lib", srcs = glob(["*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], source = "8", target = "8", deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/BUCK index c7d1ffc46c759e..5d0fa7d9d1c958 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "accessibilityinfo", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/appearance/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/appearance/BUCK index 60c8584e16c264..62802072e94797 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/appearance/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/appearance/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "appearance", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/appregistry/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/appregistry/BUCK index 5ea989b39c9429..dc2c4d824b2a52 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/appregistry/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/appregistry/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_target", "rn_android_li rn_android_library( name = "appregistry", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/BUCK index b3e191047dc295..3b873f61574438 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "appstate", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BUCK index aedfca7dd5888f..0a4d2b472e2210 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "blob", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/BUCK index 4bd4ee666c3d62..2ab5488c94a15f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/BUCK @@ -11,6 +11,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + labels = ["supermodule:android/default/public.react_native.infra"], platforms = ANDROID, soname = "libreactnativeblob.$(ext)", visibility = ["PUBLIC"], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/camera/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/camera/BUCK index 775fd1db0f00c1..01e0240e5b7dee 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/camera/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/camera/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "camera", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/clipboard/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/clipboard/BUCK index 9e0390ea8527b8..c3fa4b7884140b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/clipboard/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/clipboard/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "clipboard", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/common/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/common/BUCK index 938ef3c649f912..c8376f61beec51 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/common/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/common/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "common", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/core/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/core/BUCK index 9432c4513c5e4b..4e8a8ee3fafff2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/core/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/core/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "core", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK index 4a5b7eeb92f7ed..91683c6f233033 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "datepicker", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/debug/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/debug/BUCK index 61950b38fbe2ba..2f0d2caef1a471 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/debug/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/debug/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "debug", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], @@ -29,6 +30,7 @@ rn_android_library( rn_android_library( name = "interfaces", srcs = glob(["interfaces/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.java b/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.java index 6eae4d7a5c8200..df4b653cc9bfce 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.java @@ -75,7 +75,8 @@ public FpsInfo( public FpsDebugFrameCallback(ReactContext reactContext) { mReactContext = reactContext; - mUIManagerModule = reactContext.getNativeModule(UIManagerModule.class); + mUIManagerModule = + Assertions.assertNotNull(reactContext.getNativeModule(UIManagerModule.class)); mDidJSUpdateUiDuringFrameDetector = new DidJSUpdateUiDuringFrameDetector(); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/deviceinfo/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/deviceinfo/BUCK index 0f33ea66f71e80..a33ecbf2677641 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/deviceinfo/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/deviceinfo/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "deviceinfo", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/BUCK index 93cae84131f6e4..1987e6e9223e16 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "dialog", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/fabric/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/fabric/BUCK index b19a3c20bbc8df..5bbb74d994b22f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/fabric/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/fabric/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_target", "rn_android_li rn_android_library( name = "fabric", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ ], visibility = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK index 0e467a7738e3f9..fd6819910638ce 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "fresco", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java index df26770d309376..ac70eff2adcc19 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java @@ -12,6 +12,7 @@ import com.facebook.common.logging.FLog; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory; +import com.facebook.imagepipeline.core.ImagePipeline; import com.facebook.imagepipeline.core.ImagePipelineConfig; import com.facebook.imagepipeline.listener.RequestListener; import com.facebook.react.bridge.LifecycleEventListener; @@ -41,6 +42,7 @@ public class FrescoModule extends ReactContextBaseJavaModule public static final String NAME = "FrescoModule"; private final boolean mClearOnDestroy; private @Nullable ImagePipelineConfig mConfig; + private @Nullable ImagePipeline mImagePipeline; private static boolean sHasBeenInitialized = false; @@ -66,6 +68,20 @@ public FrescoModule(ReactApplicationContext reactContext, boolean clearOnDestroy this(reactContext, clearOnDestroy, null); } + /** + * Create a new Fresco module with a default configuration (or the previously given configuration + * via {@link #FrescoModule(ReactApplicationContext, boolean, ImagePipelineConfig)}. + * + * @param clearOnDestroy whether to clear the memory cache in onHostDestroy: this should be {@code + * true} for pure RN apps and {@code false} for apps that use Fresco outside of RN as well + * @param reactContext the context to use + */ + public FrescoModule( + ReactApplicationContext reactContext, ImagePipeline imagePipeline, boolean clearOnDestroy) { + this(reactContext, clearOnDestroy); + mImagePipeline = imagePipeline; + } + /** * Create a new Fresco module with a given ImagePipelineConfig. This should only be called when * the module has not been initialized yet. You can use {@link #hasBeenInitialized()} to check @@ -114,7 +130,7 @@ public String getName() { @Override public void clearSensitiveData() { // Clear image cache. - Fresco.getImagePipeline().clearCaches(); + getImagePipeline().clearCaches(); } /** @@ -168,7 +184,14 @@ public void onHostDestroy() { // the 'last' ReactActivity is being destroyed, which effectively means the app is being // backgrounded. if (hasBeenInitialized() && mClearOnDestroy) { - Fresco.getImagePipeline().clearMemoryCaches(); + getImagePipeline().clearMemoryCaches(); + } + } + + private ImagePipeline getImagePipeline() { + if (mImagePipeline == null) { + mImagePipeline = Fresco.getImagePipeline(); } + return mImagePipeline; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/i18nmanager/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/i18nmanager/BUCK index 36bb281dc280c0..a00c306f8da8a4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/i18nmanager/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/i18nmanager/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "i18nmanager", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/image/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/image/BUCK index 519a07adcba933..d924754e990d0e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/image/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/image/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "image", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], @@ -20,6 +21,7 @@ rn_android_library( react_native_target("java/com/facebook/react/modules/fresco:fresco"), react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/views/imagehelper:imagehelper"), + react_native_target("java/com/facebook/react/views/image:image"), ], exported_deps = [ react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/image/ImageLoaderModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/image/ImageLoaderModule.java index aca084ed9f307c..71fb0a809c816f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/image/ImageLoaderModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/image/ImageLoaderModule.java @@ -9,6 +9,7 @@ import android.net.Uri; import android.util.SparseArray; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.facebook.common.executors.CallerThreadExecutor; import com.facebook.common.references.CloseableReference; @@ -32,6 +33,7 @@ import com.facebook.react.bridge.WritableMap; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.modules.fresco.ReactNetworkImageRequest; +import com.facebook.react.views.image.ReactCallerContextFactory; import com.facebook.react.views.imagehelper.ImageSource; @ReactModule(name = ImageLoaderModule.NAME) @@ -43,9 +45,11 @@ public class ImageLoaderModule extends NativeImageLoaderAndroidSpec private static final String ERROR_GET_SIZE_FAILURE = "E_GET_SIZE_FAILURE"; public static final String NAME = "ImageLoader"; - private final Object mCallerContext; + private @Nullable final Object mCallerContext; private final Object mEnqueuedRequestMonitor = new Object(); private final SparseArray> mEnqueuedRequests = new SparseArray<>(); + private @Nullable ImagePipeline mImagePipeline = null; + private @Nullable ReactCallerContextFactory mCallerContextFactory; public ImageLoaderModule(ReactApplicationContext reactContext) { super(reactContext); @@ -57,11 +61,32 @@ public ImageLoaderModule(ReactApplicationContext reactContext, Object callerCont mCallerContext = callerContext; } + public ImageLoaderModule( + ReactApplicationContext reactContext, + ImagePipeline imagePipeline, + ReactCallerContextFactory callerContextFactory) { + super(reactContext); + mCallerContextFactory = callerContextFactory; + mImagePipeline = imagePipeline; + mCallerContext = null; + } + + private @Nullable Object getCallerContext() { + return mCallerContextFactory != null + ? mCallerContextFactory.getOrCreateCallerContext("", "") + : mCallerContext; + } + @Override + @NonNull public String getName() { return NAME; } + private ImagePipeline getImagePipeline() { + return mImagePipeline != null ? mImagePipeline : Fresco.getImagePipeline(); + } + /** * Fetch the width and height of the given image. * @@ -80,7 +105,7 @@ public void getSize(final String uriString, final Promise promise) { ImageRequest request = ImageRequestBuilder.newBuilderWithSource(source.getUri()).build(); DataSource> dataSource = - Fresco.getImagePipeline().fetchDecodedImage(request, mCallerContext); + getImagePipeline().fetchDecodedImage(request, getCallerContext()); DataSubscriber> dataSubscriber = new BaseDataSubscriber>() { @@ -141,7 +166,7 @@ public void getSizeWithHeaders( ReactNetworkImageRequest.fromBuilderWithHeaders(imageRequestBuilder, headers); DataSource> dataSource = - Fresco.getImagePipeline().fetchDecodedImage(request, mCallerContext); + getImagePipeline().fetchDecodedImage(request, getCallerContext()); DataSubscriber> dataSubscriber = new BaseDataSubscriber>() { @@ -201,7 +226,7 @@ public void prefetchImage( ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri).build(); DataSource prefetchSource = - Fresco.getImagePipeline().prefetchToDiskCache(request, mCallerContext); + getImagePipeline().prefetchToDiskCache(request, getCallerContext()); DataSubscriber prefetchSubscriber = new BaseDataSubscriber() { @Override @@ -212,6 +237,8 @@ protected void onNewResultImpl(DataSource dataSource) { try { removeRequest(requestId); promise.resolve(true); + } catch (Exception e) { + promise.reject(ERROR_PREFETCH_FAILURE, e); } finally { dataSource.close(); } @@ -246,7 +273,7 @@ public void queryCache(final ReadableArray uris, final Promise promise) { @Override protected void doInBackgroundGuarded(Void... params) { WritableMap result = Arguments.createMap(); - ImagePipeline imagePipeline = Fresco.getImagePipeline(); + ImagePipeline imagePipeline = getImagePipeline(); for (int i = 0; i < uris.size(); i++) { String uriString = uris.getString(i); final Uri uri = Uri.parse(uriString); diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/intent/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/intent/BUCK index 616d73ed7507a5..a7f538cc2ea321 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/intent/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/intent/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "intent", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/network/BUCK index fb4b470d71e615..ccb9013abe9045 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "network", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/permissions/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/permissions/BUCK index e947137a59ba69..484e374c72a94c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/permissions/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/permissions/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "permissions", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/share/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/share/BUCK index 0e45037b0cee9e..11288aa404c14c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/share/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/share/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "share", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/sound/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/sound/BUCK index ac4b1d2f0920c2..8e199ed82a85e2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/sound/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/sound/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "sound", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ ], visibility = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/BUCK index 4082dcd67a9148..8643e041815f6a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "statusbar", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/storage/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/storage/BUCK index 81a13ec37975bf..2231b08feec476 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/storage/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/storage/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "storage", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoModule.java index 24c6f4deb4cbfc..3c4be024f518c5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoModule.java @@ -12,12 +12,10 @@ import android.annotation.SuppressLint; import android.app.UiModeManager; import android.content.res.Configuration; -import android.content.res.Resources; import android.os.Build; import android.provider.Settings.Secure; import androidx.annotation.Nullable; import com.facebook.fbreact.specs.NativePlatformConstantsAndroidSpec; -import com.facebook.react.R; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.module.annotations.ReactModule; @@ -73,7 +71,9 @@ public String getName() { constants.put("Fingerprint", Build.FINGERPRINT); constants.put("Model", Build.MODEL); if (ReactBuildConfig.DEBUG) { - constants.put("ServerHost", getServerHost()); + constants.put( + "ServerHost", + AndroidInfoHelpers.getServerHost(getReactApplicationContext().getApplicationContext())); } constants.put( "isTesting", "true".equals(System.getProperty(IS_TESTING)) || isRunningScreenshotTest()); @@ -98,12 +98,4 @@ private Boolean isRunningScreenshotTest() { return false; } } - - private String getServerHost() { - Resources resources = getReactApplicationContext().getApplicationContext().getResources(); - - Integer devServerPort = resources.getInteger(R.integer.react_native_dev_server_port); - - return AndroidInfoHelpers.getServerHost(devServerPort); - } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/BUCK index 30e4988a0fad6c..afc48e3db35129 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/BUCK @@ -7,6 +7,7 @@ rn_android_library( "ReactNativeVersion.java", ], is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], @@ -31,6 +32,7 @@ rn_android_library( "AndroidInfoHelpers.java", ], is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/BUCK index 9740b735f71328..dac030819debc6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "timepicker", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/toast/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/toast/BUCK index a297071e700324..fb3b79960fe585 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/toast/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/toast/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "toast", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/vibration/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/vibration/BUCK index d817e4149e38e1..219a1d36feb288 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/vibration/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/vibration/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "vibration", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/BUCK index 26f6686d14a861..4299354a4a6d76 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "websocket", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/BUCK b/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/BUCK index 092745fd177118..1cfd88bfc35a01 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/BUCK @@ -6,6 +6,7 @@ rn_android_library( ["**/*.java"], ), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/processing/BUCK b/ReactAndroid/src/main/java/com/facebook/react/processing/BUCK index f88f4fe679b860..5ff37878c58a18 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/processing/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/processing/BUCK @@ -15,6 +15,7 @@ rn_java_annotation_processor( rn_java_library( name = "processing-lib", srcs = glob(["*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], source = "7", target = "7", deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK b/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK index 4df1ab9930362d..5f114f91e88e13 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "shell", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), @@ -51,7 +52,6 @@ rn_android_library( react_native_target("java/com/facebook/react/modules/websocket:websocket"), react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"), react_native_target("java/com/facebook/react/uimanager:uimanager"), - react_native_target("java/com/facebook/react/views/art:art"), react_native_target("java/com/facebook/react/views/drawer:drawer"), react_native_target("java/com/facebook/react/views/image:image"), react_native_target("java/com/facebook/react/views/modal:modal"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java index 7c60cda3300a9d..e5d6f99a3186b9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java +++ b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java @@ -43,8 +43,6 @@ import com.facebook.react.modules.websocket.WebSocketModule; import com.facebook.react.turbomodule.core.interfaces.TurboModule; import com.facebook.react.uimanager.ViewManager; -import com.facebook.react.views.art.ARTRenderableViewManager; -import com.facebook.react.views.art.ARTSurfaceViewManager; import com.facebook.react.views.drawer.ReactDrawerLayoutManager; import com.facebook.react.views.image.ReactImageManager; import com.facebook.react.views.modal.ReactModalHostManager; @@ -174,9 +172,6 @@ public MainReactPackage(MainPackageConfig config) { public List createViewManagers(ReactApplicationContext reactContext) { List viewManagers = new ArrayList<>(); - viewManagers.add(ARTRenderableViewManager.createARTGroupViewManager()); - viewManagers.add(ARTRenderableViewManager.createARTShapeViewManager()); - viewManagers.add(ARTRenderableViewManager.createARTTextViewManager()); viewManagers.add(new ReactDialogPickerManager()); viewManagers.add(new ReactDrawerLayoutManager()); viewManagers.add(new ReactDropdownPickerManager()); @@ -189,7 +184,6 @@ public List createViewManagers(ReactApplicationContext reactContext viewManagers.add(new SwipeRefreshLayoutManager()); // Native equivalents - viewManagers.add(new ARTSurfaceViewManager()); viewManagers.add(new FrescoBasedReactTextInlineImageViewManager()); viewManagers.add(new ReactImageManager()); viewManagers.add(new ReactModalHostManager()); diff --git a/ReactAndroid/src/main/java/com/facebook/react/surface/BUCK b/ReactAndroid/src/main/java/com/facebook/react/surface/BUCK index ad6bcd33c4a20d..7ea360411204d6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/surface/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/surface/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "surface", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/touch/BUCK b/ReactAndroid/src/main/java/com/facebook/react/touch/BUCK index bcd493aaf746b8..c57d2e682f350d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/touch/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/touch/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "touch", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/BUCK b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/BUCK index f3e34f4e46effc..7547027a771a8d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/BUCK @@ -8,6 +8,7 @@ rn_android_library( ], exclude = ["CallInvokerHolderImpl.java"], ), + labels = ["supermodule:android/default/public.react_native.infra"], required_for_source_only_abi = True, visibility = [ "PUBLIC", @@ -38,6 +39,7 @@ rn_android_library( rn_android_library( name = "callinvokerholder", srcs = ["CallInvokerHolderImpl.java"], + labels = ["supermodule:android/default/public.react_native.infra"], required_for_source_only_abi = True, visibility = [ "PUBLIC", 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 004c8e8a7407a0..6b01a2008308ad 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,6 +19,7 @@ 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; @@ -32,7 +33,7 @@ */ public class TurboModuleManager implements JSIModule, TurboModuleRegistry { private static volatile boolean sIsSoLibraryLoaded; - private final List mEagerInitModuleNames = new ArrayList<>(); + private final List mEagerInitModuleNames; private final TurboModuleProvider mJavaModuleProvider; private final TurboModuleProvider mCxxModuleProvider; @@ -64,11 +65,8 @@ public TurboModuleManager( delegate); installJSIBindings(); - if (delegate != null) { - synchronized (delegate) { - mEagerInitModuleNames.addAll(delegate.getEagerInitModuleNames()); - } - } + mEagerInitModuleNames = + delegate == null ? new ArrayList() : delegate.getEagerInitModuleNames(); mJavaModuleProvider = new TurboModuleProvider() { @@ -78,10 +76,7 @@ public TurboModule getModule(String moduleName) { return null; } - /** TODO(T65532092): Should TurboModuleManagerDelegate be thread-safe? */ - synchronized (delegate) { - return delegate.getModule(moduleName); - } + return delegate.getModule(moduleName); } }; @@ -93,13 +88,7 @@ public TurboModule getModule(String moduleName) { return null; } - CxxModuleWrapper nativeModule; - - /** TODO(T65532092): Should TurboModuleManagerDelegate be thread-safe? */ - synchronized (delegate) { - nativeModule = delegate.getLegacyCxxModule(moduleName); - } - + CxxModuleWrapper nativeModule = delegate.getLegacyCxxModule(moduleName); if (nativeModule != null) { // TurboModuleManagerDelegate must always return TurboModules Assertions.assertCondition( @@ -116,24 +105,52 @@ public List getEagerInitModuleNames() { return mEagerInitModuleNames; } + @DoNotStrip + @Nullable + private CxxModuleWrapper getLegacyCxxModule(String moduleName) { + final TurboModule turboModule = getModule(moduleName); + if (!(turboModule instanceof CxxModuleWrapper)) { + return null; + } + + return (CxxModuleWrapper) turboModule; + } + + @DoNotStrip + @Nullable + private TurboModule getJavaModule(String moduleName) { + final TurboModule turboModule = getModule(moduleName); + if (turboModule instanceof CxxModuleWrapper) { + return null; + } + + return turboModule; + } + /** - * TurboModuleHolders are used as locks to ensure that when n threads race to create a - * TurboModule, only the first thread creates that TurboModule. All other n - 1 threads wait until - * the TurboModule is created and initialized. + * Return the TurboModule instance that corresponds to the provided moduleName. + * + *

This method: - Creates and initializes the module if it doesn't already exist. - Returns + * null after TurboModuleManager has been torn down. */ @Nullable - private TurboModuleHolder getOrMaybeCreateTurboModuleHolder(String moduleName) { + public TurboModule getModule(String moduleName) { + TurboModuleHolder moduleHolder; + synchronized (mTurboModuleCleanupLock) { if (mTurboModuleCleanupStarted) { /* * Always return null after cleanup has started, so that getModule(moduleName) returns null. */ - FLog.e( - ReactConstants.TAG, - "TurboModuleManager.getOrMaybeCreateTurboModuleHolder: Tried to require TurboModule " - + moduleName - + " after cleanup initiated"); + 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; } @@ -144,24 +161,22 @@ private TurboModuleHolder getOrMaybeCreateTurboModuleHolder(String moduleName) { if (!mTurboModuleHolders.containsKey(moduleName)) { mTurboModuleHolders.put(moduleName, new TurboModuleHolder()); } - return mTurboModuleHolders.get(moduleName); + + moduleHolder = mTurboModuleHolders.get(moduleName); } + + return getModule(moduleName, moduleHolder); } /** - * If n threads race to create TurboModule x, then only the first thread should create x. All n - - * 1 other threads should wait until x is created and initialized. + * Given a TurboModuleHolder, and the TurboModule's moduleName, return the TurboModule instance. * - *

Note: After we've started cleanup, getModule will always return null. + *

Use the TurboModuleHolder to ensure that if n threads race to create TurboModule x, then + * only the first thread creates x. All n - 1 other threads wait until the x is created and + * initialized. */ @Nullable - public TurboModule getModule(String moduleName) { - final TurboModuleHolder moduleHolder = getOrMaybeCreateTurboModuleHolder(moduleName); - - if (moduleHolder == null) { - return null; - } - + private TurboModule getModule(String moduleName, @NonNull TurboModuleHolder moduleHolder) { boolean shouldCreateModule = false; synchronized (moduleHolder) { @@ -232,28 +247,6 @@ public TurboModule getModule(String moduleName) { } } - @DoNotStrip - @Nullable - private CxxModuleWrapper getLegacyCxxModule(String moduleName) { - final TurboModule turboModule = getModule(moduleName); - if (!(turboModule instanceof CxxModuleWrapper)) { - return null; - } - - return (CxxModuleWrapper) turboModule; - } - - @DoNotStrip - @Nullable - private TurboModule getJavaModule(String moduleName) { - final TurboModule turboModule = getModule(moduleName); - if (turboModule instanceof CxxModuleWrapper) { - return null; - } - - return turboModule; - } - /** Which TurboModules have been created? */ public Collection getModules() { final List turboModuleHolders = new ArrayList<>(); @@ -317,11 +310,17 @@ public void onCatalystInstanceDestroy() { mTurboModuleCleanupStarted = true; } - final Set turboModuleNames = new HashSet<>(mTurboModuleHolders.keySet()); + for (final Map.Entry moduleHolderEntry : + mTurboModuleHolders.entrySet()) { + final String moduleName = moduleHolderEntry.getKey(); + final TurboModuleHolder moduleHolder = moduleHolderEntry.getValue(); - for (final String moduleName : turboModuleNames) { - // Retrieve the TurboModule, possibly waiting for it to finish instantiating. - final TurboModule turboModule = getModule(moduleName); + /** + * ReactNative could start tearing down before this particular TurboModule has been fully + * initialized. In this case, we should wait for initialization to complete, before destroying + * the TurboModule. + */ + final TurboModule turboModule = getModule(moduleName, moduleHolder); if (turboModule != null) { // TODO(T48014458): Rename this to invalidate() diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/BUCK b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/BUCK index e48328e07291ae..3e07e5c5355a80 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/BUCK @@ -6,6 +6,7 @@ rn_android_library( ["*.java"], ), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], required_for_source_only_abi = True, visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/BUCK b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/BUCK index 4de25abe7deacc..183194f3d47dd9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/BUCK @@ -17,6 +17,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + labels = ["supermodule:android/default/public.react_native.infra"], platforms = ANDROID, preprocessor_flags = [ "-DLOG_TAG=\"ReactNative\"", @@ -55,6 +56,7 @@ rn_xplat_cxx_library( fbandroid_deps = [ FBJNI_TARGET, ], + labels = ["supermodule:android/default/public.react_native.infra"], platforms = ANDROID, preferred_linkage = "static", preprocessor_flags = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK index 33eeffd0434703..a88d679b87f4f3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK @@ -14,6 +14,7 @@ rn_android_library( ], ), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), @@ -59,6 +60,7 @@ rn_android_library( "DisplayMetricsHolder.java", ], is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java index 26d958570bc86c..35c9ff92013033 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java @@ -7,8 +7,8 @@ package com.facebook.react.uimanager; -import android.content.res.Resources; import android.graphics.Matrix; +import android.graphics.Rect; import android.graphics.RectF; import android.util.SparseArray; import android.util.SparseBooleanArray; @@ -701,14 +701,12 @@ public synchronized void measureInWindow(int tag, int[] outputBuffer) { v.getLocationOnScreen(outputBuffer); - // We need to remove the status bar from the height. getLocationOnScreen will include the - // status bar. - Resources resources = v.getContext().getResources(); - int statusBarId = resources.getIdentifier("status_bar_height", "dimen", "android"); - if (statusBarId > 0) { - int height = (int) resources.getDimension(statusBarId); - outputBuffer[1] -= height; - } + // we need to subtract visibleWindowCoords - to subtract possible window insets, split screen or + // multi window + Rect visibleWindowFrame = new Rect(); + v.getWindowVisibleDisplayFrame(visibleWindowFrame); + outputBuffer[0] = outputBuffer[0] - visibleWindowFrame.left; + outputBuffer[1] = outputBuffer[1] - visibleWindowFrame.top; // outputBuffer[0,1] already contain what we want outputBuffer[2] = v.getWidth(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java index a97220763e4621..2fba8c52164c75 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java @@ -41,9 +41,10 @@ public interface ReactRoot { /** Return native view for root */ ViewGroup getRootViewGroup(); - /** @return Cached values for widthMeasureSpec and heightMeasureSpec */ + /** @return Cached values for widthMeasureSpec. */ int getWidthMeasureSpec(); + /** @return Cached values for and heightMeasureSpec. */ int getHeightMeasureSpec(); /** Sets a flag that determines whether to log that content appeared on next view added. */ diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java index 8fdf52866ca7c1..0a5d5bb83a1345 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java @@ -805,7 +805,7 @@ private void measureLayoutRelativeToVerifiedAncestor( ReactShadowNode node, ReactShadowNode ancestor, int[] outputBuffer) { int offsetX = 0; int offsetY = 0; - if (node != ancestor) { + if (node != ancestor && !node.isVirtual()) { offsetX = Math.round(node.getLayoutX()); offsetY = Math.round(node.getLayoutY()); ReactShadowNode current = node.getParent(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java index 9d7879d425d2ae..d753e252a567c4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -425,6 +425,16 @@ public int addRootView( return tag; } + @Override + public int startSurface( + final T rootView, + final String moduleName, + final WritableMap initialProps, + int widthMeasureSpec, + int heightMeasureSpec) { + throw new UnsupportedOperationException(); + } + /** Unregisters a new root view. */ @ReactMethod public void removeRootView(int rootViewTag) { @@ -807,6 +817,7 @@ public void setViewHierarchyUpdateDebugListener( mUIImplementation.setViewHierarchyUpdateDebugListener(listener); } + @Override public EventDispatcher getEventDispatcher() { return mEventDispatcher; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java index 9c2eed060a7110..4f8844cba117ad 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java @@ -113,11 +113,14 @@ public EmitOnLayoutEventOperation( @Override public void execute() { - mReactApplicationContext - .getNativeModule(UIManagerModule.class) - .getEventDispatcher() - .dispatchEvent( - OnLayoutEvent.obtain(mTag, mScreenX, mScreenY, mScreenWidth, mScreenHeight)); + UIManagerModule uiManager = mReactApplicationContext.getNativeModule(UIManagerModule.class); + + if (uiManager != null) { + uiManager + .getEventDispatcher() + .dispatchEvent( + OnLayoutEvent.obtain(mTag, mScreenX, mScreenY, mScreenWidth, mScreenHeight)); + } } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/annotations/BUCK b/ReactAndroid/src/main/java/com/facebook/react/uimanager/annotations/BUCK index 3ecec7beea0e36..39953cea578b08 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/annotations/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/annotations/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "annotations", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], required_for_source_only_abi = True, visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/BUCK b/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/BUCK index f3b3d20aaaa3f6..9f54d4ad220281 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "common", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/util/BUCK b/ReactAndroid/src/main/java/com/facebook/react/uimanager/util/BUCK index 446c2dce76055b..1f67fb5365cf5e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/util/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/util/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "util", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/util/BUCK b/ReactAndroid/src/main/java/com/facebook/react/util/BUCK index b78a3fd8e3d8c8..84188101bbfc06 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/util/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/util/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "util", srcs = glob(["**/*.java"]), + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/BUCK b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/BUCK index 16bd74bbb87148..d950d48939265a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "viewmanagers", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/DatePickerManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/DatePickerManagerDelegate.java new file mode 100644 index 00000000000000..29288a63c8911a --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/DatePickerManagerDelegate.java @@ -0,0 +1,62 @@ +/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaDelegate.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.uimanager.BaseViewManagerDelegate; +import com.facebook.react.uimanager.BaseViewManagerInterface; +import com.facebook.react.uimanager.LayoutShadowNode; + +public class DatePickerManagerDelegate & DatePickerManagerInterface> extends BaseViewManagerDelegate { + public DatePickerManagerDelegate(U viewManager) { + super(viewManager); + } + @Override + public void setProperty(T view, String propName, @Nullable Object value) { + switch (propName) { + case "date": + mViewManager.setDate(view, value == null ? 0f : ((Double) value).floatValue()); + break; + case "initialDate": + mViewManager.setInitialDate(view, value == null ? 0f : ((Double) value).floatValue()); + break; + case "locale": + mViewManager.setLocale(view, value == null ? null : (String) value); + break; + case "maximumDate": + mViewManager.setMaximumDate(view, value == null ? 0f : ((Double) value).floatValue()); + break; + case "minimumDate": + mViewManager.setMinimumDate(view, value == null ? 0f : ((Double) value).floatValue()); + break; + case "minuteInterval": + mViewManager.setMinuteInterval(view, value == null ? 1 : ((Double) value).intValue()); + break; + case "mode": + mViewManager.setMode(view, (String) value); + break; + case "timeZoneOffsetInMinutes": + mViewManager.setTimeZoneOffsetInMinutes(view, value == null ? 0f : ((Double) value).floatValue()); + break; + default: + super.setProperty(view, propName, value); + } + } + + public void receiveCommand(DatePickerManagerInterface viewManager, T view, String commandName, ReadableArray args) { + switch (commandName) { + case "setNativeDate": + viewManager.setNativeDate(view, (float) args.getDouble(0)); + break; + } + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/DatePickerManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/DatePickerManagerInterface.java new file mode 100644 index 00000000000000..9df911c7284d3a --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/DatePickerManagerInterface.java @@ -0,0 +1,25 @@ +/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaInterface.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import androidx.annotation.Nullable; + +public interface DatePickerManagerInterface { + void setDate(T view, float value); + void setInitialDate(T view, float value); + void setLocale(T view, @Nullable String value); + void setMaximumDate(T view, float value); + void setMinimumDate(T view, float value); + void setMinuteInterval(T view, @Nullable Integer value); + void setMode(T view, @Nullable String value); + void setTimeZoneOffsetInMinutes(T view, float value); + void setNativeDate(T view, float date); +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerDelegate.java new file mode 100644 index 00000000000000..2d6732ee8d38a2 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerDelegate.java @@ -0,0 +1,51 @@ +/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaDelegate.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.ColorPropConverter; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.uimanager.BaseViewManagerDelegate; +import com.facebook.react.uimanager.BaseViewManagerInterface; +import com.facebook.react.uimanager.LayoutShadowNode; + +public class PullToRefreshViewManagerDelegate & PullToRefreshViewManagerInterface> extends BaseViewManagerDelegate { + public PullToRefreshViewManagerDelegate(U viewManager) { + super(viewManager); + } + @Override + public void setProperty(T view, String propName, @Nullable Object value) { + switch (propName) { + case "tintColor": + mViewManager.setTintColor(view, ColorPropConverter.getColor(value, view.getContext())); + break; + case "titleColor": + mViewManager.setTitleColor(view, ColorPropConverter.getColor(value, view.getContext())); + break; + case "title": + mViewManager.setTitle(view, value == null ? null : (String) value); + break; + case "refreshing": + mViewManager.setRefreshing(view, value == null ? false : (boolean) value); + break; + default: + super.setProperty(view, propName, value); + } + } + + public void receiveCommand(PullToRefreshViewManagerInterface viewManager, T view, String commandName, ReadableArray args) { + switch (commandName) { + case "setNativeRefreshing": + viewManager.setNativeRefreshing(view, args.getBoolean(0)); + break; + } + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerInterface.java new file mode 100644 index 00000000000000..4f40ee89cbba01 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerInterface.java @@ -0,0 +1,21 @@ +/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaInterface.js +*/ + +package com.facebook.react.viewmanagers; + +import android.view.View; +import androidx.annotation.Nullable; + +public interface PullToRefreshViewManagerInterface { + void setTintColor(T view, @Nullable Integer value); + void setTitleColor(T view, @Nullable Integer value); + void setTitle(T view, @Nullable String value); + void setRefreshing(T view, boolean value); + void setNativeRefreshing(T view, boolean refreshing); +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SwitchManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SwitchManagerDelegate.java index bee0b8c54f2065..5e419f8bd3fe91 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SwitchManagerDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SwitchManagerDelegate.java @@ -11,6 +11,8 @@ import android.view.View; import androidx.annotation.Nullable; +import com.facebook.react.bridge.ColorPropConverter; +import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; import com.facebook.react.uimanager.LayoutShadowNode; @@ -29,25 +31,33 @@ public void setProperty(T view, String propName, @Nullable Object value) { mViewManager.setValue(view, value == null ? false : (boolean) value); break; case "tintColor": - mViewManager.setTintColor(view, value == null ? null : ((Double) value).intValue()); + mViewManager.setTintColor(view, ColorPropConverter.getColor(value, view.getContext())); break; case "onTintColor": - mViewManager.setOnTintColor(view, value == null ? null : ((Double) value).intValue()); + mViewManager.setOnTintColor(view, ColorPropConverter.getColor(value, view.getContext())); break; case "thumbTintColor": - mViewManager.setThumbTintColor(view, value == null ? null : ((Double) value).intValue()); + mViewManager.setThumbTintColor(view, ColorPropConverter.getColor(value, view.getContext())); break; case "thumbColor": - mViewManager.setThumbColor(view, value == null ? null : ((Double) value).intValue()); + mViewManager.setThumbColor(view, ColorPropConverter.getColor(value, view.getContext())); break; case "trackColorForFalse": - mViewManager.setTrackColorForFalse(view, value == null ? null : ((Double) value).intValue()); + mViewManager.setTrackColorForFalse(view, ColorPropConverter.getColor(value, view.getContext())); break; case "trackColorForTrue": - mViewManager.setTrackColorForTrue(view, value == null ? null : ((Double) value).intValue()); + mViewManager.setTrackColorForTrue(view, ColorPropConverter.getColor(value, view.getContext())); break; default: super.setProperty(view, propName, value); } } + + public void receiveCommand(SwitchManagerInterface viewManager, T view, String commandName, ReadableArray args) { + switch (commandName) { + case "setValue": + viewManager.setValue(view, args.getBoolean(0)); + break; + } + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTGroupShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTGroupShadowNode.java deleted file mode 100644 index bc941ac54c090c..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTGroupShadowNode.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.views.art; - -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.RectF; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.uimanager.annotations.ReactProp; - -/** Shadow node for virtual ARTGroup view */ -public class ARTGroupShadowNode extends ARTVirtualNode { - - protected @Nullable RectF mClipping; - - public ARTGroupShadowNode() {} - - @ReactProp(name = "clipping") - public void setClipping(@Nullable ReadableArray clippingDims) { - float[] clippingData = PropHelper.toFloatArray(clippingDims); - if (clippingData != null) { - mClipping = createClipping(clippingData); - markUpdated(); - } - } - - @Override - public boolean isVirtual() { - return true; - } - - public void draw(Canvas canvas, Paint paint, float opacity) { - opacity *= mOpacity; - if (opacity > MIN_OPACITY_FOR_DRAW) { - saveAndSetupCanvas(canvas); - - if (mClipping != null) { - canvas.clipRect( - mClipping.left * mScale, - mClipping.top * mScale, - mClipping.right * mScale, - mClipping.bottom * mScale); - } - - for (int i = 0; i < getChildCount(); i++) { - ARTVirtualNode child = (ARTVirtualNode) getChildAt(i); - child.draw(canvas, paint, opacity); - child.markUpdateSeen(); - } - - restoreCanvas(canvas); - } - } - - /** - * Creates a {@link RectF} from an array of dimensions (e.g. [x, y, width, height]) - * - * @param data the array of dimensions - * @return the {@link RectF} that can used to clip the canvas - */ - private static RectF createClipping(float[] data) { - if (data.length != 4) { - throw new JSApplicationIllegalArgumentException( - "Clipping should be array of length 4 (e.g. [x, y, width, height])"); - } - RectF clippingRect = new RectF(data[0], data[1], data[0] + data[2], data[1] + data[3]); - return clippingRect; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTGroupViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTGroupViewManager.java deleted file mode 100644 index cde81adf02c1c6..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTGroupViewManager.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.views.art; - -import com.facebook.react.module.annotations.ReactModule; - -/** ViewManager for shadowed ART group views. */ -@ReactModule(name = ARTRenderableViewManager.CLASS_GROUP) -public class ARTGroupViewManager extends ARTRenderableViewManager { - - /* package */ ARTGroupViewManager() { - super(CLASS_GROUP); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTRenderableViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTRenderableViewManager.java deleted file mode 100644 index c1515647fa324e..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTRenderableViewManager.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.views.art; - -import android.view.View; -import com.facebook.react.uimanager.ReactShadowNode; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.ViewManager; - -/** - * ViewManager for all shadowed ART views: Group, Shape and Text. Since these never get rendered - * into native views and don't need any logic (all the logic is in {@link ARTSurfaceView}), this - * "stubbed" ViewManager is used for all of them. - */ -public class ARTRenderableViewManager extends ViewManager { - - public static final String CLASS_GROUP = "ARTGroup"; - public static final String CLASS_SHAPE = "ARTShape"; - public static final String CLASS_TEXT = "ARTText"; - - private final String mClassName; - - public static ARTRenderableViewManager createARTGroupViewManager() { - return new ARTGroupViewManager(); - } - - public static ARTRenderableViewManager createARTShapeViewManager() { - return new ARTShapeViewManager(); - } - - public static ARTRenderableViewManager createARTTextViewManager() { - return new ARTTextViewManager(); - } - - /* package */ ARTRenderableViewManager(String className) { - mClassName = className; - } - - @Override - public String getName() { - return mClassName; - } - - @Override - public ReactShadowNode createShadowNodeInstance() { - if (CLASS_GROUP.equals(mClassName)) { - return new ARTGroupShadowNode(); - } else if (CLASS_SHAPE.equals(mClassName)) { - return new ARTShapeShadowNode(); - } else if (CLASS_TEXT.equals(mClassName)) { - return new ARTTextShadowNode(); - } else { - throw new IllegalStateException("Unexpected type " + mClassName); - } - } - - @Override - public Class getShadowNodeClass() { - if (CLASS_GROUP.equals(mClassName)) { - return ARTGroupShadowNode.class; - } else if (CLASS_SHAPE.equals(mClassName)) { - return ARTShapeShadowNode.class; - } else if (CLASS_TEXT.equals(mClassName)) { - return ARTTextShadowNode.class; - } else { - throw new IllegalStateException("Unexpected type " + mClassName); - } - } - - @Override - protected View createViewInstance(ThemedReactContext reactContext) { - throw new IllegalStateException("ARTShape does not map into a native view"); - } - - @Override - public void updateExtraData(View root, Object extraData) { - throw new IllegalStateException("ARTShape does not map into a native view"); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTShapeShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTShapeShadowNode.java deleted file mode 100644 index 380e239347c01a..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTShapeShadowNode.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.views.art; - -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.DashPathEffect; -import android.graphics.LinearGradient; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.RectF; -import android.graphics.Shader; -import androidx.annotation.Nullable; -import com.facebook.common.logging.FLog; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.common.ReactConstants; -import com.facebook.react.uimanager.annotations.ReactProp; - -/** Shadow node for virtual ARTShape view */ -public class ARTShapeShadowNode extends ARTVirtualNode { - - private static final int CAP_BUTT = 0; - private static final int CAP_ROUND = 1; - private static final int CAP_SQUARE = 2; - - private static final int JOIN_BEVEL = 2; - private static final int JOIN_MITER = 0; - private static final int JOIN_ROUND = 1; - - private static final int PATH_TYPE_ARC = 4; - private static final int PATH_TYPE_CLOSE = 1; - private static final int PATH_TYPE_CURVETO = 3; - private static final int PATH_TYPE_LINETO = 2; - private static final int PATH_TYPE_MOVETO = 0; - - // For color type JS and ObjectiveC definitions counterparts - // refer to ReactNativeART.js and RCTConvert+ART.m - private static final int COLOR_TYPE_SOLID_COLOR = 0; - private static final int COLOR_TYPE_LINEAR_GRADIENT = 1; - private static final int COLOR_TYPE_RADIAL_GRADIENT = 2; - private static final int COLOR_TYPE_PATTERN = 3; - - protected @Nullable Path mPath; - private @Nullable float[] mStrokeColor; - private @Nullable float[] mBrushData; - private @Nullable float[] mStrokeDash; - private float mStrokeWidth = 1; - private int mStrokeCap = CAP_ROUND; - private int mStrokeJoin = JOIN_ROUND; - - public ARTShapeShadowNode() {} - - @ReactProp(name = "d") - public void setShapePath(@Nullable ReadableArray shapePath) { - float[] pathData = PropHelper.toFloatArray(shapePath); - mPath = createPath(pathData); - markUpdated(); - } - - @ReactProp(name = "stroke") - public void setStroke(@Nullable ReadableArray strokeColors) { - mStrokeColor = PropHelper.toFloatArray(strokeColors); - markUpdated(); - } - - @ReactProp(name = "strokeDash") - public void setStrokeDash(@Nullable ReadableArray strokeDash) { - mStrokeDash = PropHelper.toFloatArray(strokeDash); - markUpdated(); - } - - @ReactProp(name = "fill") - public void setFill(@Nullable ReadableArray fillColors) { - mBrushData = PropHelper.toFloatArray(fillColors); - markUpdated(); - } - - @ReactProp(name = "strokeWidth", defaultFloat = 1f) - public void setStrokeWidth(float strokeWidth) { - mStrokeWidth = strokeWidth; - markUpdated(); - } - - @ReactProp(name = "strokeCap", defaultInt = CAP_ROUND) - public void setStrokeCap(int strokeCap) { - mStrokeCap = strokeCap; - markUpdated(); - } - - @ReactProp(name = "strokeJoin", defaultInt = JOIN_ROUND) - public void setStrokeJoin(int strokeJoin) { - mStrokeJoin = strokeJoin; - markUpdated(); - } - - @Override - public void draw(Canvas canvas, Paint paint, float opacity) { - opacity *= mOpacity; - if (opacity > MIN_OPACITY_FOR_DRAW) { - saveAndSetupCanvas(canvas); - if (mPath == null) { - throw new JSApplicationIllegalArgumentException("Shapes should have a valid path (d) prop"); - } - if (setupFillPaint(paint, opacity)) { - canvas.drawPath(mPath, paint); - } - if (setupStrokePaint(paint, opacity)) { - canvas.drawPath(mPath, paint); - } - restoreCanvas(canvas); - } - markUpdateSeen(); - } - - /** - * Sets up {@link #mPaint} according to the props set on a shadow view. Returns {@code true} if - * the stroke should be drawn, {@code false} if not. - */ - protected boolean setupStrokePaint(Paint paint, float opacity) { - if (mStrokeWidth == 0 || mStrokeColor == null || mStrokeColor.length == 0) { - return false; - } - paint.reset(); - paint.setFlags(Paint.ANTI_ALIAS_FLAG); - paint.setStyle(Paint.Style.STROKE); - switch (mStrokeCap) { - case CAP_BUTT: - paint.setStrokeCap(Paint.Cap.BUTT); - break; - case CAP_SQUARE: - paint.setStrokeCap(Paint.Cap.SQUARE); - break; - case CAP_ROUND: - paint.setStrokeCap(Paint.Cap.ROUND); - break; - default: - throw new JSApplicationIllegalArgumentException( - "strokeCap " + mStrokeCap + " unrecognized"); - } - switch (mStrokeJoin) { - case JOIN_MITER: - paint.setStrokeJoin(Paint.Join.MITER); - break; - case JOIN_BEVEL: - paint.setStrokeJoin(Paint.Join.BEVEL); - break; - case JOIN_ROUND: - paint.setStrokeJoin(Paint.Join.ROUND); - break; - default: - throw new JSApplicationIllegalArgumentException( - "strokeJoin " + mStrokeJoin + " unrecognized"); - } - paint.setStrokeWidth(mStrokeWidth * mScale); - paint.setARGB( - (int) (mStrokeColor.length > 3 ? mStrokeColor[3] * opacity * 255 : opacity * 255), - (int) (mStrokeColor[0] * 255), - (int) (mStrokeColor[1] * 255), - (int) (mStrokeColor[2] * 255)); - if (mStrokeDash != null && mStrokeDash.length > 0) { - paint.setPathEffect(new DashPathEffect(mStrokeDash, 0)); - } - return true; - } - - /** - * Sets up {@link #mPaint} according to the props set on a shadow view. Returns {@code true} if - * the fill should be drawn, {@code false} if not. - */ - protected boolean setupFillPaint(Paint paint, float opacity) { - if (mBrushData != null && mBrushData.length > 0) { - paint.reset(); - paint.setFlags(Paint.ANTI_ALIAS_FLAG); - paint.setStyle(Paint.Style.FILL); - int colorType = (int) mBrushData[0]; - switch (colorType) { - case COLOR_TYPE_SOLID_COLOR: - paint.setARGB( - (int) (mBrushData.length > 4 ? mBrushData[4] * opacity * 255 : opacity * 255), - (int) (mBrushData[1] * 255), - (int) (mBrushData[2] * 255), - (int) (mBrushData[3] * 255)); - break; - case COLOR_TYPE_LINEAR_GRADIENT: - // For mBrushData format refer to LinearGradient and insertColorStopsIntoArray functions - // in ReactNativeART.js - if (mBrushData.length < 5) { - FLog.w( - ReactConstants.TAG, - "[ARTShapeShadowNode setupFillPaint] expects 5 elements, received " - + mBrushData.length); - return false; - } - float gradientStartX = mBrushData[1] * mScale; - float gradientStartY = mBrushData[2] * mScale; - float gradientEndX = mBrushData[3] * mScale; - float gradientEndY = mBrushData[4] * mScale; - int stops = (mBrushData.length - 5) / 5; - int[] colors = null; - float[] positions = null; - if (stops > 0) { - colors = new int[stops]; - positions = new float[stops]; - for (int i = 0; i < stops; i++) { - positions[i] = mBrushData[5 + 4 * stops + i]; - int r = (int) (255 * mBrushData[5 + 4 * i + 0]); - int g = (int) (255 * mBrushData[5 + 4 * i + 1]); - int b = (int) (255 * mBrushData[5 + 4 * i + 2]); - int a = (int) (255 * mBrushData[5 + 4 * i + 3]); - colors[i] = Color.argb(a, r, g, b); - } - } - paint.setShader( - new LinearGradient( - gradientStartX, - gradientStartY, - gradientEndX, - gradientEndY, - colors, - positions, - Shader.TileMode.CLAMP)); - break; - case COLOR_TYPE_RADIAL_GRADIENT: - // TODO(6352048): Support radial gradient etc. - case COLOR_TYPE_PATTERN: - // TODO(6352048): Support patterns etc. - default: - FLog.w(ReactConstants.TAG, "ART: Color type " + colorType + " not supported!"); - } - return true; - } - return false; - } - - /** - * Returns the floor modulus of the float arguments. Java modulus will return a negative remainder - * when the divisor is negative. Modulus should always be positive. This mimics the behavior of - * Math.floorMod, introduced in Java 8. - */ - private float modulus(float x, float y) { - float remainder = x % y; - float modulus = remainder; - if (remainder < 0) { - modulus += y; - } - return modulus; - } - - /** - * Creates a {@link Path} from an array of instructions constructed by JS (see - * ARTSerializablePath.js). Each instruction starts with a type (see PATH_TYPE_*) followed by - * arguments for that instruction. For example, to create a line the instruction will be 2 - * (PATH_LINE_TO), x, y. This will draw a line from the last draw point (or 0,0) to x,y. - * - * @param data the array of instructions - * @return the {@link Path} that can be drawn to a canvas - */ - private Path createPath(float[] data) { - Path path = new Path(); - path.moveTo(0, 0); - int i = 0; - while (i < data.length) { - int type = (int) data[i++]; - switch (type) { - case PATH_TYPE_MOVETO: - path.moveTo(data[i++] * mScale, data[i++] * mScale); - break; - case PATH_TYPE_CLOSE: - path.close(); - break; - case PATH_TYPE_LINETO: - path.lineTo(data[i++] * mScale, data[i++] * mScale); - break; - case PATH_TYPE_CURVETO: - path.cubicTo( - data[i++] * mScale, - data[i++] * mScale, - data[i++] * mScale, - data[i++] * mScale, - data[i++] * mScale, - data[i++] * mScale); - break; - case PATH_TYPE_ARC: - { - float x = data[i++] * mScale; - float y = data[i++] * mScale; - float r = data[i++] * mScale; - float start = (float) Math.toDegrees(data[i++]); - float end = (float) Math.toDegrees(data[i++]); - - boolean counterClockwise = !(data[i++] == 1f); - float sweep = end - start; - if (Math.abs(sweep) >= 360) { - path.addCircle(x, y, r, counterClockwise ? Path.Direction.CCW : Path.Direction.CW); - } else { - sweep = modulus(sweep, 360); - if (counterClockwise && sweep < 360) { - // Counter-clockwise sweeps are negative - sweep = -1 * (360 - sweep); - } - - RectF oval = new RectF(x - r, y - r, x + r, y + r); - path.arcTo(oval, start, sweep); - } - break; - } - default: - throw new JSApplicationIllegalArgumentException( - "Unrecognized drawing instruction " + type); - } - } - return path; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTShapeViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTShapeViewManager.java deleted file mode 100644 index f192481fabfbdc..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTShapeViewManager.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.views.art; - -import com.facebook.react.module.annotations.ReactModule; - -/** ViewManager for shadowed ART shape views. */ -@ReactModule(name = ARTRenderableViewManager.CLASS_SHAPE) -public class ARTShapeViewManager extends ARTRenderableViewManager { - - /* package */ ARTShapeViewManager() { - super(CLASS_SHAPE); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceView.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceView.java deleted file mode 100644 index 95d0d6fbb8956b..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceView.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.views.art; - -import android.content.Context; -import android.view.TextureView; - -/** Custom {@link View} implementation that draws an ARTSurface React view and its children. */ -public class ARTSurfaceView extends TextureView { - public ARTSurfaceView(Context context) { - super(context); - setOpaque(false); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceViewManager.java deleted file mode 100644 index 5a3e42c6b62da4..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceViewManager.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.views.art; - -import com.facebook.react.module.annotations.ReactModule; -import com.facebook.react.uimanager.BaseViewManager; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.yoga.YogaMeasureFunction; -import com.facebook.yoga.YogaMeasureMode; -import com.facebook.yoga.YogaNode; - -/** - * ViewManager for ARTSurfaceView React views. Renders as a {@link ARTSurfaceView} and handles - * invalidating the native view on shadow view updates happening in the underlying tree. - */ -@ReactModule(name = ARTSurfaceViewManager.REACT_CLASS) -public class ARTSurfaceViewManager - extends BaseViewManager { - - public static final String REACT_CLASS = "ARTSurfaceView"; - - private static final YogaMeasureFunction MEASURE_FUNCTION = - new YogaMeasureFunction() { - @Override - public long measure( - YogaNode node, - float width, - YogaMeasureMode widthMode, - float height, - YogaMeasureMode heightMode) { - throw new IllegalStateException("SurfaceView should have explicit width and height set"); - } - }; - - @Override - public String getName() { - return REACT_CLASS; - } - - @Override - public ARTSurfaceViewShadowNode createShadowNodeInstance() { - ARTSurfaceViewShadowNode node = new ARTSurfaceViewShadowNode(); - node.setMeasureFunction(MEASURE_FUNCTION); - return node; - } - - @Override - public Class getShadowNodeClass() { - return ARTSurfaceViewShadowNode.class; - } - - @Override - protected ARTSurfaceView createViewInstance(ThemedReactContext reactContext) { - return new ARTSurfaceView(reactContext); - } - - @Override - public void updateExtraData(ARTSurfaceView root, Object extraData) { - ARTSurfaceViewShadowNode shadowNode = (ARTSurfaceViewShadowNode) extraData; - shadowNode.setupSurfaceTextureListener(root); - } - - @Override - public void setBackgroundColor(ARTSurfaceView view, int backgroundColor) { - // As of Android N TextureView does not support calling setBackground on it. - // It will also throw an exception when target SDK is set to N or higher. - - // Setting the background color for this view is handled in the shadow node. - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceViewShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceViewShadowNode.java deleted file mode 100644 index acc7fcaeec9287..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceViewShadowNode.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.views.art; - -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.SurfaceTexture; -import android.os.Build; -import android.view.Surface; -import android.view.TextureView; -import androidx.annotation.Nullable; -import com.facebook.common.logging.FLog; -import com.facebook.react.bridge.LifecycleEventListener; -import com.facebook.react.common.ReactConstants; -import com.facebook.react.uimanager.LayoutShadowNode; -import com.facebook.react.uimanager.ReactShadowNode; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.UIViewOperationQueue; -import com.facebook.react.uimanager.ViewProps; -import com.facebook.react.uimanager.annotations.ReactProp; - -/** Shadow node for ART virtual tree root - ARTSurfaceView */ -public class ARTSurfaceViewShadowNode extends LayoutShadowNode - implements TextureView.SurfaceTextureListener, LifecycleEventListener { - - private @Nullable Surface mSurface; - - private @Nullable Integer mBackgroundColor; - - @ReactProp(name = ViewProps.BACKGROUND_COLOR, customType = "Color") - public void setBackgroundColor(Integer color) { - mBackgroundColor = color; - markUpdated(); - } - - @Override - public boolean isVirtual() { - return false; - } - - @Override - public boolean isVirtualAnchor() { - return true; - } - - @Override - public void onCollectExtraUpdates(UIViewOperationQueue uiUpdater) { - super.onCollectExtraUpdates(uiUpdater); - drawOutput(false); - uiUpdater.enqueueUpdateExtraData(getReactTag(), this); - } - - private void drawOutput(boolean markAsUpdated) { - if (mSurface == null || !mSurface.isValid()) { - markChildrenUpdatesSeen(this); - return; - } - - try { - Canvas canvas = mSurface.lockCanvas(null); - canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); - if (mBackgroundColor != null) { - canvas.drawColor(mBackgroundColor); - } - - Paint paint = new Paint(); - for (int i = 0; i < getChildCount(); i++) { - ARTVirtualNode child = (ARTVirtualNode) getChildAt(i); - child.draw(canvas, paint, 1f); - if (markAsUpdated) { - child.markUpdated(); - } else { - child.markUpdateSeen(); - } - } - - if (mSurface == null) { - return; - } - mSurface.unlockCanvasAndPost(canvas); - } catch (IllegalArgumentException | IllegalStateException e) { - FLog.e(ReactConstants.TAG, e.getClass().getSimpleName() + " in Surface.unlockCanvasAndPost"); - } - } - - public void setupSurfaceTextureListener(ARTSurfaceView surfaceView) { - SurfaceTexture surface = surfaceView.getSurfaceTexture(); - surfaceView.setSurfaceTextureListener(this); - if (surface != null && mSurface == null) { - mSurface = new Surface(surface); - drawOutput(true); - } - } - - private void markChildrenUpdatesSeen(ReactShadowNode shadowNode) { - for (int i = 0; i < shadowNode.getChildCount(); i++) { - ReactShadowNode child = shadowNode.getChildAt(i); - child.markUpdateSeen(); - markChildrenUpdatesSeen(child); - } - } - - @Override - public void setThemedContext(ThemedReactContext themedContext) { - super.setThemedContext(themedContext); - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) { - themedContext.addLifecycleEventListener(this); - } - } - - @Override - public void dispose() { - super.dispose(); - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) { - getThemedContext().removeLifecycleEventListener(this); - } - } - - @Override - public void onHostResume() { - drawOutput(false); - } - - @Override - public void onHostPause() {} - - @Override - public void onHostDestroy() {} - - @Override - public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { - mSurface = new Surface(surface); - drawOutput(false); - } - - @Override - public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - mSurface.release(); - mSurface = null; - return true; - } - - @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {} - - @Override - public void onSurfaceTextureUpdated(SurfaceTexture surface) {} -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTTextShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTTextShadowNode.java deleted file mode 100644 index dca51da7f92e95..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTTextShadowNode.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.views.art; - -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Typeface; -import android.text.TextUtils; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.uimanager.annotations.ReactProp; - -/** Shadow node for virtual ARTText view */ -public class ARTTextShadowNode extends ARTShapeShadowNode { - - private static final String PROP_LINES = "lines"; - - private static final String PROP_FONT = "font"; - private static final String PROP_FONT_FAMILY = "fontFamily"; - private static final String PROP_FONT_SIZE = "fontSize"; - private static final String PROP_FONT_STYLE = "fontStyle"; - private static final String PROP_FONT_WEIGHT = "fontWeight"; - - private static final int DEFAULT_FONT_SIZE = 12; - - private static final int TEXT_ALIGNMENT_CENTER = 2; - private static final int TEXT_ALIGNMENT_LEFT = 0; - private static final int TEXT_ALIGNMENT_RIGHT = 1; - - private @Nullable ReadableMap mFrame; - private int mTextAlignment = TEXT_ALIGNMENT_LEFT; - - public ARTTextShadowNode() {} - - @ReactProp(name = "frame") - public void setFrame(@Nullable ReadableMap frame) { - mFrame = frame; - } - - @ReactProp(name = "alignment", defaultInt = TEXT_ALIGNMENT_LEFT) - public void setAlignment(int alignment) { - mTextAlignment = alignment; - } - - @Override - public void draw(Canvas canvas, Paint paint, float opacity) { - if (mFrame == null) { - return; - } - opacity *= mOpacity; - if (opacity <= MIN_OPACITY_FOR_DRAW) { - return; - } - if (!mFrame.hasKey(PROP_LINES)) { - return; - } - ReadableArray linesProp = mFrame.getArray(PROP_LINES); - if (linesProp == null || linesProp.size() == 0) { - return; - } - - // only set up the canvas if we have something to draw - saveAndSetupCanvas(canvas); - String[] lines = new String[linesProp.size()]; - for (int i = 0; i < lines.length; i++) { - lines[i] = linesProp.getString(i); - } - String text = TextUtils.join("\n", lines); - if (setupStrokePaint(paint, opacity)) { - applyTextPropertiesToPaint(paint); - if (mPath == null) { - canvas.drawText(text, 0, -paint.ascent(), paint); - } else { - canvas.drawTextOnPath(text, mPath, 0, 0, paint); - } - } - if (setupFillPaint(paint, opacity)) { - applyTextPropertiesToPaint(paint); - if (mPath == null) { - canvas.drawText(text, 0, -paint.ascent(), paint); - } else { - canvas.drawTextOnPath(text, mPath, 0, 0, paint); - } - } - restoreCanvas(canvas); - markUpdateSeen(); - } - - private void applyTextPropertiesToPaint(Paint paint) { - int alignment = mTextAlignment; - switch (alignment) { - case TEXT_ALIGNMENT_LEFT: - paint.setTextAlign(Paint.Align.LEFT); - break; - case TEXT_ALIGNMENT_RIGHT: - paint.setTextAlign(Paint.Align.RIGHT); - break; - case TEXT_ALIGNMENT_CENTER: - paint.setTextAlign(Paint.Align.CENTER); - break; - } - if (mFrame != null) { - if (mFrame.hasKey(PROP_FONT)) { - ReadableMap font = mFrame.getMap(PROP_FONT); - if (font != null) { - float fontSize = DEFAULT_FONT_SIZE; - if (font.hasKey(PROP_FONT_SIZE)) { - fontSize = (float) font.getDouble(PROP_FONT_SIZE); - } - paint.setTextSize(fontSize * mScale); - boolean isBold = - font.hasKey(PROP_FONT_WEIGHT) && "bold".equals(font.getString(PROP_FONT_WEIGHT)); - boolean isItalic = - font.hasKey(PROP_FONT_STYLE) && "italic".equals(font.getString(PROP_FONT_STYLE)); - int fontStyle; - if (isBold && isItalic) { - fontStyle = Typeface.BOLD_ITALIC; - } else if (isBold) { - fontStyle = Typeface.BOLD; - } else if (isItalic) { - fontStyle = Typeface.ITALIC; - } else { - fontStyle = Typeface.NORMAL; - } - // NB: if the font family is null / unsupported, the default one will be used - paint.setTypeface(Typeface.create(font.getString(PROP_FONT_FAMILY), fontStyle)); - } - } - } - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTTextViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTTextViewManager.java deleted file mode 100644 index b49b95b76d8c5f..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTTextViewManager.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.views.art; - -import com.facebook.react.module.annotations.ReactModule; - -/** ViewManager for shadowed ART text views. */ -@ReactModule(name = ARTRenderableViewManager.CLASS_TEXT) -public class ARTTextViewManager extends ARTRenderableViewManager { - - /* package */ ARTTextViewManager() { - super(CLASS_TEXT); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTVirtualNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTVirtualNode.java deleted file mode 100644 index 8f6592924e4e54..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTVirtualNode.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.views.art; - -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Paint; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.uimanager.DisplayMetricsHolder; -import com.facebook.react.uimanager.ReactShadowNodeImpl; -import com.facebook.react.uimanager.annotations.ReactProp; - -/** - * Base class for ARTView virtual nodes: {@link ARTGroupShadowNode}, {@link ARTShapeShadowNode} and - * indirectly for {@link ARTTextShadowNode}. - */ -public abstract class ARTVirtualNode extends ReactShadowNodeImpl { - - protected static final float MIN_OPACITY_FOR_DRAW = 0.01f; - - private static final float[] sMatrixData = new float[9]; - private static final float[] sRawMatrix = new float[9]; - - protected float mOpacity = 1f; - private @Nullable Matrix mMatrix = new Matrix(); - - protected final float mScale; - - public ARTVirtualNode() { - mScale = DisplayMetricsHolder.getWindowDisplayMetrics().density; - } - - @Override - public boolean isVirtual() { - return true; - } - - public abstract void draw(Canvas canvas, Paint paint, float opacity); - - /** - * Sets up the transform matrix on the canvas before an element is drawn. - * - *

NB: for perf reasons this does not apply opacity, as that would mean creating a new canvas - * layer (which allocates an offscreen bitmap) and having it composited afterwards. Instead, the - * drawing code should apply opacity recursively. - * - * @param canvas the canvas to set up - */ - protected final void saveAndSetupCanvas(Canvas canvas) { - canvas.save(); - if (mMatrix != null) { - canvas.concat(mMatrix); - } - } - - /** - * Restore the canvas after an element was drawn. This is always called in mirror with {@link - * #saveAndSetupCanvas}. - * - * @param canvas the canvas to restore - */ - protected void restoreCanvas(Canvas canvas) { - canvas.restore(); - } - - @ReactProp(name = "opacity", defaultFloat = 1f) - public void setOpacity(float opacity) { - mOpacity = opacity; - markUpdated(); - } - - @ReactProp(name = "transform") - public void setTransform(@Nullable ReadableArray transformArray) { - if (transformArray != null) { - int matrixSize = PropHelper.toFloatArray(transformArray, sMatrixData); - if (matrixSize == 6) { - setupMatrix(); - } else if (matrixSize != -1) { - throw new JSApplicationIllegalArgumentException("Transform matrices must be of size 6"); - } - } else { - mMatrix = null; - } - markUpdated(); - } - - protected void setupMatrix() { - sRawMatrix[0] = sMatrixData[0]; - sRawMatrix[1] = sMatrixData[2]; - sRawMatrix[2] = sMatrixData[4] * mScale; - sRawMatrix[3] = sMatrixData[1]; - sRawMatrix[4] = sMatrixData[3]; - sRawMatrix[5] = sMatrixData[5] * mScale; - sRawMatrix[6] = 0; - sRawMatrix[7] = 0; - sRawMatrix[8] = 1; - if (mMatrix == null) { - mMatrix = new Matrix(); - } - mMatrix.setValues(sRawMatrix); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/art/BUCK deleted file mode 100644 index b5eae199917ce9..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/BUCK +++ /dev/null @@ -1,21 +0,0 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_target", "rn_android_library") - -rn_android_library( - name = "art", - srcs = glob(["*.java"]), - is_androidx = True, - visibility = [ - "PUBLIC", - ], - deps = [ - YOGA_TARGET, - react_native_dep("third-party/android/androidx:annotation"), - react_native_dep("libraries/fbcore/src/main/java/com/facebook/common/logging:logging"), - react_native_dep("third-party/java/jsr-305:jsr-305"), - react_native_target("java/com/facebook/react/bridge:bridge"), - react_native_target("java/com/facebook/react/common:common"), - react_native_target("java/com/facebook/react/module/annotations:annotations"), - react_native_target("java/com/facebook/react/uimanager:uimanager"), - react_native_target("java/com/facebook/react/uimanager/annotations:annotations"), - ], -) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/PropHelper.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/PropHelper.java deleted file mode 100644 index 970f505661b99b..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/PropHelper.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.views.art; - -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ReadableArray; - -/** Contains static helper methods for accessing props. */ -/* package */ class PropHelper { - - /** - * Converts {@link ReadableArray} to an array of {@code float}. Returns newly created array. - * - * @return a {@code float[]} if converted successfully, or {@code null} if {@param value} was - * {@code null}. - */ - /*package*/ static @Nullable float[] toFloatArray(@Nullable ReadableArray value) { - if (value != null) { - float[] result = new float[value.size()]; - toFloatArray(value, result); - return result; - } - return null; - } - - /** - * Converts given {@link ReadableArray} to an array of {@code float}. Writes result to the array - * passed in {@param into}. This method will write to the output array up to the number of items - * from the input array. If the input array is longer than output the remaining part of the input - * will not be converted. - * - * @param value input array - * @param into output array - * @return number of items copied from input to the output array - */ - /*package*/ static int toFloatArray(ReadableArray value, float[] into) { - int length = value.size() > into.length ? into.length : value.size(); - for (int i = 0; i < length; i++) { - into[i] = (float) value.getDouble(i); - } - return value.size(); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/common/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/common/BUCK index b6a8fbdbde991d..c9f4f1bda7ce78 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/common/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/common/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "common", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/java/jsr-305:jsr-305"), react_native_dep("third-party/android/androidx:annotation"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/BUCK index 57d72472c1964a..9b24b8e6611515 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "drawer", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java index d2f22623a81508..712353eb0a42f2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java @@ -56,9 +56,12 @@ public ReactDrawerLayoutManager() { @Override protected void addEventEmitters(ThemedReactContext reactContext, ReactDrawerLayout view) { - view.addDrawerListener( - new DrawerEventEmitter( - view, reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher())); + UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); + if (uiManager == null) { + return; + } + + view.addDrawerListener(new DrawerEventEmitter(view, uiManager.getEventDispatcher())); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK index 3cddf8e7158472..e60547c2a4101b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK @@ -8,6 +8,7 @@ rn_android_library( name = "imageevents", srcs = IMAGE_EVENT_FILES, is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), @@ -31,6 +32,7 @@ rn_android_library( exclude = IMAGE_EVENT_FILES, ), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactCallerContextFactory.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactCallerContextFactory.java index 7ccc594b946a18..46e9573fdb0ca1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactCallerContextFactory.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactCallerContextFactory.java @@ -1,3 +1,5 @@ +// (c) Facebook, Inc. and its affiliates. Confidential and proprietary. + /* * Copyright (c) Facebook, Inc. and its affiliates. * @@ -8,7 +10,6 @@ package com.facebook.react.views.image; import androidx.annotation.Nullable; -import com.facebook.react.uimanager.ThemedReactContext; /** * This interface is used from {@link ReactImageManager} to customize the CallerContext object @@ -19,8 +20,9 @@ public interface ReactCallerContextFactory { /** * This method will be called at the time {@link ReactImageManager} creates {@link ReactImageView} * - * @param reactContext {@link ThemedReactContext} used to create the {@link ReactImageView} + * @param surfaceID {@link String} used to log the name of the surface * @return an {@link Object} that represents the CallerContext. */ - Object getOrCreateCallerContext(ThemedReactContext reactContext, @Nullable String analyticTag); + @Nullable + Object getOrCreateCallerContext(@Nullable String surfaceID, @Nullable String analyticTag); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java index e90301b6acea0b..7077ceb7ad9030 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java @@ -107,7 +107,7 @@ public Object getCallerContext() { public ReactImageView createViewInstance(ThemedReactContext context) { Object callerContext = mCallerContextFactory != null - ? mCallerContextFactory.getOrCreateCallerContext(context, null) + ? mCallerContextFactory.getOrCreateCallerContext(context.getSurfaceID(), null) : getCallerContext(); return new ReactImageView( context, getDraweeControllerBuilder(), mGlobalImageLoadListener, callerContext); @@ -129,7 +129,7 @@ public void setInternal_AnalyticsTag(ReactImageView view, @Nullable String analy if (mCallerContextFactory != null) { view.updateCallerContext( mCallerContextFactory.getOrCreateCallerContext( - (ThemedReactContext) view.getContext(), analyticTag)); + ((ThemedReactContext) view.getContext()).getSurfaceID(), analyticTag)); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/BUCK index b870bef0195b24..990f459c89c89a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/BUCK @@ -7,6 +7,7 @@ rn_android_library( exclude = ["MultiSourceHelper.java"], ), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], @@ -21,6 +22,7 @@ rn_android_library( name = "withmultisource", srcs = ["MultiSourceHelper.java"], is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK index bb6d9818b89266..6c69eb6af88884 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "modal", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java index ac0cffd04979fa..00e0066b97a125 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java @@ -105,8 +105,12 @@ public void setIdentifier(ReactModalHostView view, int value) {} @Override protected void addEventEmitters(ThemedReactContext reactContext, final ReactModalHostView view) { - final EventDispatcher dispatcher = - reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); + UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); + if (uiManager == null) { + return; + } + + final EventDispatcher dispatcher = uiManager.getEventDispatcher(); view.setOnRequestCloseListener( new ReactModalHostView.OnRequestCloseListener() { @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java index 110ebdf34be342..d5312acdb18672 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java @@ -414,9 +414,14 @@ private void updateFirstChildView() { new GuardedRunnable(reactContext) { @Override public void runGuarded() { - (getReactContext()) - .getNativeModule(UIManagerModule.class) - .updateNodeSize(viewTag, viewWidth, viewHeight); + UIManagerModule uiManager = + (getReactContext()).getNativeModule(UIManagerModule.class); + + if (uiManager == null) { + return; + } + + uiManager.updateNodeSize(viewTag, viewWidth, viewHeight); } }); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/picker/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/picker/BUCK index 32fdd11dc47ebe..ca04eca2315179 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/picker/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/picker/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "picker", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:appcompat"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerManager.java index b03783ca3fea8f..e5c42e059905e6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerManager.java @@ -62,9 +62,13 @@ protected void onAfterUpdateTransaction(ReactPicker view) { @Override protected void addEventEmitters(final ThemedReactContext reactContext, final ReactPicker picker) { - picker.setOnSelectListener( - new PickerEventEmitter( - picker, reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher())); + UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); + + if (uiManager == null) { + return; + } + + picker.setOnSelectListener(new PickerEventEmitter(picker, uiManager.getEventDispatcher())); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/BUCK index 4e480cd5c812ae..6ef5436e19a58a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "progressbar", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/BUCK index ef2b7b77d4eda6..ed41f3c10ebe43 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "scroll", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index c905c5dc9a4f37..1b2c5312381c47 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -7,12 +7,17 @@ package com.facebook.react.views.scroll; +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.os.Build; import android.view.FocusFinder; import android.view.KeyEvent; import android.view.MotionEvent; @@ -82,6 +87,10 @@ public class ReactHorizontalScrollView extends HorizontalScrollView private int pendingContentOffsetY = UNSET_CONTENT_OFFSET; private @Nullable StateWrapper mStateWrapper; + private @Nullable ValueAnimator mScrollAnimator; + private int mFinalAnimatedPositionScrollX = 0; + private int mFinalAnimatedPositionScrollY = 0; + private final Rect mTempRect = new Rect(); public ReactHorizontalScrollView(Context context) { @@ -648,6 +657,20 @@ public void run() { ReactHorizontalScrollView.this, mPostTouchRunnable, ReactScrollViewHelper.MOMENTUM_DELAY); } + /** Get current X position or position after current animation finishes, if any. */ + private int getPostAnimationScrollX() { + return mScrollAnimator != null && mScrollAnimator.isRunning() + ? mFinalAnimatedPositionScrollX + : getScrollX(); + } + + /** Get current X position or position after current animation finishes, if any. */ + private int getPostAnimationScrollY() { + return mScrollAnimator != null && mScrollAnimator.isRunning() + ? mFinalAnimatedPositionScrollY + : getScrollY(); + } + private int predictFinalScrollPosition(int velocityX) { // ScrollView can *only* scroll for 250ms when using smoothScrollTo and there's // no way to customize the scroll duration. So, we create a temporary OverScroller @@ -659,8 +682,8 @@ private int predictFinalScrollPosition(int velocityX) { int maximumOffset = Math.max(0, computeHorizontalScrollRange() - getWidth()); int width = getWidth() - ViewCompat.getPaddingStart(this) - ViewCompat.getPaddingEnd(this); scroller.fling( - getScrollX(), // startX - getScrollY(), // startY + getPostAnimationScrollX(), // startX + getPostAnimationScrollY(), // startY velocityX, // velocityX 0, // velocityY 0, // minX @@ -674,13 +697,13 @@ private int predictFinalScrollPosition(int velocityX) { } /** - * This will smooth scroll us to the nearest snap offset point It currently just looks at where + * This will smooth scroll us to the nearest snap offset point. It currently just looks at where * the content is and slides to the nearest point. It is intended to be run after we are done * scrolling, and handling any momentum scrolling. */ private void smoothScrollAndSnap(int velocity) { double interval = (double) getSnapInterval(); - double currentOffset = (double) getScrollX(); + double currentOffset = (double) (getPostAnimationScrollX()); double targetOffset = (double) predictFinalScrollPosition(velocity); int previousPage = (int) Math.floor(currentOffset / interval); @@ -914,7 +937,54 @@ public void setBorderStyle(@Nullable String style) { * scroll view and state. Calling raw `smoothScrollTo` doesn't update state. */ public void reactSmoothScrollTo(int x, int y) { - smoothScrollTo(x, y); + // `smoothScrollTo` contains some logic that, if called multiple times in a short amount of + // time, will treat all calls as part of the same animation and will not lengthen the duration + // of the animation. This means that, for example, if the user is scrolling rapidly, multiple + // pages could be considered part of one animation, causing some page animations to be animated + // very rapidly - looking like they're not animated at all. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + if (mScrollAnimator != null) { + mScrollAnimator.cancel(); + } + + mFinalAnimatedPositionScrollX = x; + mFinalAnimatedPositionScrollY = y; + PropertyValuesHolder scrollX = PropertyValuesHolder.ofInt("scrollX", getScrollX(), x); + PropertyValuesHolder scrollY = PropertyValuesHolder.ofInt("scrollY", getScrollY(), y); + mScrollAnimator = ObjectAnimator.ofPropertyValuesHolder(scrollX, scrollY); + mScrollAnimator.setDuration( + ReactScrollViewHelper.getDefaultScrollAnimationDuration(getContext())); + mScrollAnimator.addUpdateListener( + new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + int scrollValueX = (Integer) valueAnimator.getAnimatedValue("scrollX"); + int scrollValueY = (Integer) valueAnimator.getAnimatedValue("scrollY"); + ReactHorizontalScrollView.this.scrollTo(scrollValueX, scrollValueY); + } + }); + mScrollAnimator.addListener( + new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animator) {} + + @Override + public void onAnimationEnd(Animator animator) { + mFinalAnimatedPositionScrollX = -1; + mFinalAnimatedPositionScrollY = -1; + mScrollAnimator = null; + } + + @Override + public void onAnimationCancel(Animator animator) {} + + @Override + public void onAnimationRepeat(Animator animator) {} + }); + mScrollAnimator.start(); + } else { + smoothScrollTo(x, y); + } updateStateOnScroll(x, y); setPendingContentOffsets(x, y); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java index ecb72fff78746f..7f11c77abf3a22 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java @@ -304,8 +304,8 @@ public void setFadingEdgeLength(ReactHorizontalScrollView view, int value) { @ReactProp(name = "contentOffset") public void setContentOffset(ReactHorizontalScrollView view, ReadableMap value) { if (value != null) { - double x = value.getDouble("x"); - double y = value.getDouble("y"); + double x = value.hasKey("x") ? value.getDouble("x") : 0; + double y = value.hasKey("y") ? value.getDouble("y") : 0; view.reactScrollTo((int) PixelUtil.toPixelFromDIP(x), (int) PixelUtil.toPixelFromDIP(y)); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index f0d4e99658553a..7a77b954415cda 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -7,11 +7,16 @@ package com.facebook.react.views.scroll; +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.animation.ValueAnimator; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.os.Build; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -87,6 +92,10 @@ public class ReactScrollView extends ScrollView private int pendingContentOffsetY = UNSET_CONTENT_OFFSET; private @Nullable StateWrapper mStateWrapper; + private @Nullable ValueAnimator mScrollAnimator; + private int mFinalAnimatedPositionScrollX; + private int mFinalAnimatedPositionScrollY; + public ReactScrollView(ReactContext context) { this(context, null); } @@ -536,6 +545,20 @@ public void run() { ReactScrollView.this, mPostTouchRunnable, ReactScrollViewHelper.MOMENTUM_DELAY); } + /** Get current X position or position after current animation finishes, if any. */ + private int getPostAnimationScrollX() { + return mScrollAnimator != null && mScrollAnimator.isRunning() + ? mFinalAnimatedPositionScrollX + : getScrollX(); + } + + /** Get current X position or position after current animation finishes, if any. */ + private int getPostAnimationScrollY() { + return mScrollAnimator != null && mScrollAnimator.isRunning() + ? mFinalAnimatedPositionScrollY + : getScrollY(); + } + private int predictFinalScrollPosition(int velocityY) { // ScrollView can *only* scroll for 250ms when using smoothScrollTo and there's // no way to customize the scroll duration. So, we create a temporary OverScroller @@ -547,8 +570,8 @@ private int predictFinalScrollPosition(int velocityY) { int maximumOffset = getMaxScrollY(); int height = getHeight() - getPaddingBottom() - getPaddingTop(); scroller.fling( - getScrollX(), // startX - getScrollY(), // startY + getPostAnimationScrollX(), // startX + getPostAnimationScrollY(), // startY 0, // velocityX velocityY, // velocityY 0, // minX @@ -568,7 +591,7 @@ private int predictFinalScrollPosition(int velocityY) { */ private void smoothScrollAndSnap(int velocity) { double interval = (double) getSnapInterval(); - double currentOffset = (double) getScrollY(); + double currentOffset = (double) getPostAnimationScrollY(); double targetOffset = (double) predictFinalScrollPosition(velocity); int previousPage = (int) Math.floor(currentOffset / interval); @@ -785,7 +808,54 @@ public void onChildViewRemoved(View parent, View child) { * scroll view and state. Calling raw `smoothScrollTo` doesn't update state. */ public void reactSmoothScrollTo(int x, int y) { - smoothScrollTo(x, y); + // `smoothScrollTo` contains some logic that, if called multiple times in a short amount of + // time, will treat all calls as part of the same animation and will not lengthen the duration + // of the animation. This means that, for example, if the user is scrolling rapidly, multiple + // pages could be considered part of one animation, causing some page animations to be animated + // very rapidly - looking like they're not animated at all. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + if (mScrollAnimator != null) { + mScrollAnimator.cancel(); + } + + mFinalAnimatedPositionScrollX = x; + mFinalAnimatedPositionScrollY = y; + PropertyValuesHolder scrollX = PropertyValuesHolder.ofInt("scrollX", getScrollX(), x); + PropertyValuesHolder scrollY = PropertyValuesHolder.ofInt("scrollY", getScrollY(), y); + mScrollAnimator = ObjectAnimator.ofPropertyValuesHolder(scrollX, scrollY); + mScrollAnimator.setDuration( + ReactScrollViewHelper.getDefaultScrollAnimationDuration(getContext())); + mScrollAnimator.addUpdateListener( + new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + int scrollValueX = (Integer) valueAnimator.getAnimatedValue("scrollX"); + int scrollValueY = (Integer) valueAnimator.getAnimatedValue("scrollY"); + ReactScrollView.this.scrollTo(scrollValueX, scrollValueY); + } + }); + mScrollAnimator.addListener( + new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animator) {} + + @Override + public void onAnimationEnd(Animator animator) { + mFinalAnimatedPositionScrollX = -1; + mFinalAnimatedPositionScrollY = -1; + mScrollAnimator = null; + } + + @Override + public void onAnimationCancel(Animator animator) {} + + @Override + public void onAnimationRepeat(Animator animator) {} + }); + mScrollAnimator.start(); + } else { + smoothScrollTo(x, y); + } updateStateOnScroll(x, y); setPendingContentOffsets(x, y); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java index 3f7b829d4eea08..5183f24c44bd80 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java @@ -7,8 +7,10 @@ package com.facebook.react.views.scroll; +import android.content.Context; import android.view.View; import android.view.ViewGroup; +import android.widget.OverScroller; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReactContext; import com.facebook.react.uimanager.UIManagerHelper; @@ -21,6 +23,12 @@ public class ReactScrollViewHelper { public static final String AUTO = "auto"; public static final String OVER_SCROLL_NEVER = "never"; + // If all else fails, this is the hardcoded value in OverScroller.java, in AOSP. + // The default is defined here (as of this diff): + // https://android.googlesource.com/platform/frameworks/base/+/ae5bcf23b5f0875e455790d6af387184dbd009c1/core/java/android/widget/OverScroller.java#44 + private static int SMOOTH_SCROLL_DURATION = 250; + private static boolean mSmoothScrollDurationInitialized = false; + /** Shared by {@link ReactScrollView} and {@link ReactHorizontalScrollView}. */ public static void emitScrollEvent(ViewGroup scrollView, float xVelocity, float yVelocity) { emitScrollEvent(scrollView, ScrollEventType.SCROLL, xVelocity, yVelocity); @@ -83,4 +91,43 @@ public static int parseOverScrollMode(String jsOverScrollMode) { throw new JSApplicationIllegalArgumentException("wrong overScrollMode: " + jsOverScrollMode); } } + + public static int getDefaultScrollAnimationDuration(Context context) { + if (!mSmoothScrollDurationInitialized) { + mSmoothScrollDurationInitialized = true; + + try { + OverScrollerDurationGetter overScrollerDurationGetter = + new OverScrollerDurationGetter(context); + SMOOTH_SCROLL_DURATION = overScrollerDurationGetter.getScrollAnimationDuration(); + } catch (Throwable e) { + } + } + + return SMOOTH_SCROLL_DURATION; + } + + private static class OverScrollerDurationGetter extends OverScroller { + // This is the default in AOSP, hardcoded in OverScroller.java. + private int mScrollAnimationDuration = 250; + + OverScrollerDurationGetter(Context context) { + // We call with a null context because OverScroller does not use the context + // in the execution path we're interested in, unless heavily modified in an AOSP fork. + super(context); + } + + public int getScrollAnimationDuration() { + // If startScroll is called without a duration, OverScroller will call `startScroll(x, y, dx, + // dy, duration)` with the default duration. + super.startScroll(0, 0, 0, 0); + + return mScrollAnimationDuration; + } + + @Override + public void startScroll(int startX, int startY, int dx, int dy, int duration) { + mScrollAnimationDuration = duration; + } + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java index ed7cd05778836e..adf04118c3f437 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java @@ -308,8 +308,8 @@ public void setFadingEdgeLength(ReactScrollView view, int value) { @ReactProp(name = "contentOffset") public void setContentOffset(ReactScrollView view, ReadableMap value) { if (value != null) { - double x = value.getDouble("x"); - double y = value.getDouble("y"); + double x = value.hasKey("x") ? value.getDouble("x") : 0; + double y = value.hasKey("y") ? value.getDouble("y") : 0; view.reactScrollTo((int) PixelUtil.toPixelFromDIP(x), (int) PixelUtil.toPixelFromDIP(y)); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/slider/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/slider/BUCK index f41e9bcc83b927..4aa48da0029ddf 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/slider/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/slider/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "slider", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], 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 9215864a9c6391..2bab0c053204a3 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 @@ -91,12 +91,17 @@ public long measure( @Override public void onProgressChanged(SeekBar seekbar, int progress, boolean fromUser) { ReactContext reactContext = (ReactContext) seekbar.getContext(); - reactContext - .getNativeModule(UIManagerModule.class) - .getEventDispatcher() - .dispatchEvent( - new ReactSliderEvent( - seekbar.getId(), ((ReactSlider) seekbar).toRealProgress(progress), fromUser)); + UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); + + if (uiManager != null) { + uiManager + .getEventDispatcher() + .dispatchEvent( + new ReactSliderEvent( + seekbar.getId(), + ((ReactSlider) seekbar).toRealProgress(progress), + fromUser)); + } } @Override @@ -105,13 +110,16 @@ public void onStartTrackingTouch(SeekBar seekbar) {} @Override public void onStopTrackingTouch(SeekBar seekbar) { ReactContext reactContext = (ReactContext) seekbar.getContext(); - reactContext - .getNativeModule(UIManagerModule.class) - .getEventDispatcher() - .dispatchEvent( - new ReactSlidingCompleteEvent( - seekbar.getId(), - ((ReactSlider) seekbar).toRealProgress(seekbar.getProgress()))); + UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); + + if (uiManager != null) { + uiManager + .getEventDispatcher() + .dispatchEvent( + new ReactSlidingCompleteEvent( + seekbar.getId(), + ((ReactSlider) seekbar).toRealProgress(seekbar.getProgress()))); + } } }; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/BUCK index e6ea16364a92f1..f4e77eb6322462 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "swiperefresh", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/switchview/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/switchview/BUCK index f7140b7d6ea198..677c0ddb179f57 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/switchview/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/switchview/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "switchview", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:appcompat"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitchManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitchManager.java index bd5336ad6b92d8..0a6b8c8762e740 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitchManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitchManager.java @@ -80,8 +80,14 @@ public long measure( @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { ReactContext reactContext = (ReactContext) buttonView.getContext(); - reactContext - .getNativeModule(UIManagerModule.class) + + UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); + + if (uiManager == null) { + return; + } + + uiManager .getEventDispatcher() .dispatchEvent(new ReactSwitchEvent(buttonView.getId(), isChecked)); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/text/BUCK index 62458f6ae265ae..6b4ef8857c33a5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "text", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], required_for_source_only_abi = True, visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java index 68bfc3455e7fe6..3d7988087ffaeb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java @@ -25,6 +25,7 @@ import androidx.appcompat.widget.AppCompatTextView; import androidx.appcompat.widget.TintContextWrapper; import com.facebook.common.logging.FLog; +import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.WritableArray; @@ -118,7 +119,8 @@ protected void onLayout( } ReactContext reactContext = getReactContext(); - UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); + UIManagerModule uiManager = + Assertions.assertNotNull(reactContext.getNativeModule(UIManagerModule.class)); Spanned text = (Spanned) getText(); Layout layout = getLayout(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java index 4b64720d80e51c..f98035c179bba1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java @@ -46,6 +46,10 @@ public class TextLayoutManager { private static final String INLINE_VIEW_PLACEHOLDER = "0"; private static final Object sSpannableCacheLock = new Object(); + private static final boolean DEFAULT_INCLUDE_FONT_PADDING = true; + private static final String INCLUDE_FONT_PADDING_KEY = "includeFontPadding"; + private static final String TEXT_BREAK_STRATEGY_KEY = "textBreakStrategy"; + private static final String MAXIMUM_NUMBER_OF_LINES_KEY = "maximumNumberOfLines"; private static LruCache sSpannableCache = new LruCache<>(spannableCacheSize); public static boolean isRTL(ReadableMap attributedString) { @@ -216,17 +220,20 @@ public static long measureText( // TODO(5578671): Handle text direction (see View#getTextDirectionHeuristic) TextPaint textPaint = sTextPaintInstance; - Spannable preparedSpannableText = + Spannable text = getOrCreateSpannableForText(context, attributedString, reactTextViewManagerCallback); int textBreakStrategy = - TextAttributeProps.getTextBreakStrategy(paragraphAttributes.getString("textBreakStrategy")); - boolean includeFontPadding = true; - - if (preparedSpannableText == null) { + TextAttributeProps.getTextBreakStrategy( + paragraphAttributes.getString(TEXT_BREAK_STRATEGY_KEY)); + boolean includeFontPadding = + paragraphAttributes.hasKey(INCLUDE_FONT_PADDING_KEY) + ? paragraphAttributes.getBoolean(INCLUDE_FONT_PADDING_KEY) + : DEFAULT_INCLUDE_FONT_PADDING; + + if (text == null) { throw new IllegalStateException("Spannable element has not been prepared in onBeforeLayout"); } - Spanned text = preparedSpannableText; BoringLayout.Metrics boring = BoringLayout.isBoring(text, textPaint); float desiredWidth = boring == null ? Layout.getDesiredWidth(text, textPaint) : Float.NaN; @@ -302,8 +309,8 @@ public static long measureText( } int maximumNumberOfLines = - paragraphAttributes.hasKey("maximumNumberOfLines") - ? paragraphAttributes.getInt("maximumNumberOfLines") + paragraphAttributes.hasKey(MAXIMUM_NUMBER_OF_LINES_KEY) + ? paragraphAttributes.getInt(MAXIMUM_NUMBER_OF_LINES_KEY) : UNSET; int calculatedLineCount = diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/BUCK index 8b755be5593036..d882979b4893af 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "frescosupport", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK index 745cfe2b89e8f0..ba19532ffc7fa1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "textinput", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], required_for_source_only_abi = True, visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 78a05c5e48d860..5f2532a3006e41 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -623,7 +623,9 @@ private void setIntrinsicContentSize() { ReactContext reactContext = getReactContext(this); final ReactTextInputLocalData localData = new ReactTextInputLocalData(this); UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); - uiManager.setViewLocalData(getId(), localData); + if (uiManager != null) { + uiManager.setViewLocalData(getId(), localData); + } } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextInputConnectionWrapper.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextInputConnectionWrapper.java index b56789ddf06e67..47b4391c327f11 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextInputConnectionWrapper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextInputConnectionWrapper.java @@ -12,6 +12,7 @@ import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnectionWrapper; import androidx.annotation.Nullable; +import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.ReactContext; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.events.EventDispatcher; @@ -62,7 +63,9 @@ class ReactEditTextInputConnectionWrapper extends InputConnectionWrapper { public ReactEditTextInputConnectionWrapper( InputConnection target, final ReactContext reactContext, final ReactEditText editText) { super(target, false); - mEventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); + mEventDispatcher = + Assertions.assertNotNull(reactContext.getNativeModule(UIManagerModule.class)) + .getEventDispatcher(); mEditText = editText; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index 6e462335820b6f..f5a83221375f67 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -1096,18 +1096,23 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent keyEvent) { private class ReactContentSizeWatcher implements ContentSizeWatcher { private ReactEditText mEditText; - private EventDispatcher mEventDispatcher; + private @Nullable EventDispatcher mEventDispatcher; private int mPreviousContentWidth = 0; private int mPreviousContentHeight = 0; public ReactContentSizeWatcher(ReactEditText editText) { mEditText = editText; ReactContext reactContext = getReactContext(editText); - mEventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); + UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); + mEventDispatcher = uiManager != null ? uiManager.getEventDispatcher() : null; } @Override public void onLayout() { + if (mEventDispatcher == null) { + return; + } + int contentWidth = mEditText.getWidth(); int contentHeight = mEditText.getHeight(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/unimplementedview/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/unimplementedview/BUCK index 41bdc06a8225f0..a4d7b073035547 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/unimplementedview/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/unimplementedview/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "unimplementedview", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/view/BUCK index 186cf548b42d7c..1b9b8e05181547 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "view", srcs = glob(["*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:core"), react_native_dep("third-party/android/androidx:fragment"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java index cad4db8b4f14b5..beb51d86fb4e39 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java @@ -233,10 +233,14 @@ public void setFocusable(final ReactViewGroup view, boolean focusable) { new View.OnClickListener() { @Override public void onClick(View v) { - final EventDispatcher mEventDispatcher = - ((ReactContext) view.getContext()) - .getNativeModule(UIManagerModule.class) - .getEventDispatcher(); + UIManagerModule uiManager = + ((ReactContext) view.getContext()).getNativeModule(UIManagerModule.class); + + if (uiManager == null) { + return; + } + + final EventDispatcher mEventDispatcher = uiManager.getEventDispatcher(); mEventDispatcher.dispatchEvent(new ViewGroupClickEvent(view.getId())); } }); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/BUCK index bcde344867c3f4..77179a7e98f8f1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "viewpager", srcs = glob(["**/*.java"]), is_androidx = True, + labels = ["supermodule:android/default/public.react_native.infra"], provided_deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/ReactViewPager.java b/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/ReactViewPager.java index 2c6fc370d0d15a..398751a8f6e79e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/ReactViewPager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/ReactViewPager.java @@ -13,6 +13,7 @@ import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.ViewPager; import com.facebook.common.logging.FLog; +import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.ReactContext; import com.facebook.react.common.ReactConstants; import com.facebook.react.uimanager.UIManagerModule; @@ -154,7 +155,9 @@ public void onPageScrollStateChanged(int state) { public ReactViewPager(ReactContext reactContext) { super(reactContext); - mEventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); + mEventDispatcher = + Assertions.assertNotNull(reactContext.getNativeModule(UIManagerModule.class)) + .getEventDispatcher(); mIsCurrentItemFromJs = false; setOnPageChangeListener(new PageChangeListener()); setAdapter(new Adapter()); diff --git a/ReactAndroid/src/main/jni/react/jni/Android.mk b/ReactAndroid/src/main/jni/react/jni/Android.mk index ed19e7fbc33810..dabd4b7c5125c9 100644 --- a/ReactAndroid/src/main/jni/react/jni/Android.mk +++ b/ReactAndroid/src/main/jni/react/jni/Android.mk @@ -25,7 +25,7 @@ LOCAL_LDLIBS += -landroid LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libglog_init libyoga # The static libraries (.a files) that this module depends on. -LOCAL_STATIC_LIBRARIES := libreactnative libcallinvokerholder +LOCAL_STATIC_LIBRARIES := libreactnative libcallinvokerholder libruntimeexecutor # Name of this module. # @@ -70,6 +70,7 @@ $(call import-module,jsi) $(call import-module,jsiexecutor) $(call import-module,callinvoker) $(call import-module,hermes) +$(call import-module,runtimeexecutor) include $(REACT_SRC_DIR)/turbomodule/core/jni/Android.mk diff --git a/ReactAndroid/src/main/jni/react/jni/BUCK b/ReactAndroid/src/main/jni/react/jni/BUCK index 53f2353ee8ab1b..931a8933d92986 100644 --- a/ReactAndroid/src/main/jni/react/jni/BUCK +++ b/ReactAndroid/src/main/jni/react/jni/BUCK @@ -19,6 +19,7 @@ EXPORTED_HEADERS = [ "NativeMap.h", "ReadableNativeArray.h", "ReadableNativeMap.h", + "JRuntimeExecutor.h", "WritableNativeArray.h", "WritableNativeMap.h", ] @@ -42,6 +43,7 @@ rn_xplat_cxx_library( "-Wno-inconsistent-missing-override", ], fbandroid_allow_jni_merging = True, + labels = ["supermodule:android/default/public.react_native.infra"], platforms = ANDROID, preprocessor_flags = [ "-DLOG_TAG=\"ReactNativeJNI\"", @@ -55,7 +57,7 @@ rn_xplat_cxx_library( deps = ([ "//xplat/third-party/linker_lib:android", "//xplat/third-party/linker_lib:atomic", - "//xplat/third-party/glog:glog", + "//third-party/glog:glog", "//xplat/folly:molly", "//fbandroid/xplat/fbgloginit:fbgloginit", "//xplat/fbsystrace:fbsystrace", @@ -64,6 +66,7 @@ rn_xplat_cxx_library( react_native_xplat_target("cxxreact:jsbigstring"), react_native_xplat_target("cxxreact:module"), react_native_xplat_target("jsinspector:jsinspector"), + react_native_xplat_target("runtimeexecutor:runtimeexecutor"), react_native_xplat_dep("jsi:jsi"), FBJNI_TARGET, ]) if not IS_OSS_BUILD else [], diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp index 4b279d208b41b1..7d5b1acf483f88 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp @@ -131,6 +131,8 @@ void CatalystInstanceImpl::registerNatives() { makeNativeMethod( "jniHandleMemoryPressure", CatalystInstanceImpl::handleMemoryPressure), + makeNativeMethod( + "getRuntimeExecutor", CatalystInstanceImpl::getRuntimeExecutor), }); JNativeRunnable::registerNatives(); @@ -326,5 +328,14 @@ CatalystInstanceImpl::getNativeCallInvokerHolder() { return nativeCallInvokerHolder_; } +jni::alias_ref +CatalystInstanceImpl::getRuntimeExecutor() { + if (!runtimeExecutor_) { + runtimeExecutor_ = jni::make_global( + JRuntimeExecutor::newObjectCxxArgs(instance_->getRuntimeExecutor())); + } + return runtimeExecutor_; +} + } // namespace react } // namespace facebook diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h index 32a2eef9178399..dd9990ef090a00 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h @@ -9,10 +9,12 @@ #include #include +#include #include #include "CxxModuleWrapper.h" #include "JMessageQueueThread.h" +#include "JRuntimeExecutor.h" #include "JSLoader.h" #include "JavaModuleWrapper.h" #include "ModuleRegistryBuilder.h" @@ -92,6 +94,7 @@ class CatalystInstanceImpl : public jni::HybridClass { void jniCallJSCallback(jint callbackId, NativeArray *arguments); jni::alias_ref getJSCallInvokerHolder(); jni::alias_ref getNativeCallInvokerHolder(); + jni::alias_ref getRuntimeExecutor(); void setGlobalVariable(std::string propName, std::string &&jsonValue); jlong getJavaScriptContext(); void handleMemoryPressure(int pressureLevel); @@ -103,6 +106,7 @@ class CatalystInstanceImpl : public jni::HybridClass { std::shared_ptr moduleMessageQueue_; jni::global_ref jsCallInvokerHolder_; jni::global_ref nativeCallInvokerHolder_; + jni::global_ref runtimeExecutor_; }; } // namespace react diff --git a/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentDescriptor.h b/ReactAndroid/src/main/jni/react/jni/JRuntimeExecutor.cpp similarity index 56% rename from React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentDescriptor.h rename to ReactAndroid/src/main/jni/react/jni/JRuntimeExecutor.cpp index 4cd2480ad5050a..e8e6436c294ff2 100644 --- a/React/Fabric/Mounting/ComponentViews/ART/RCTARTSurfaceViewComponentDescriptor.h +++ b/ReactAndroid/src/main/jni/react/jni/JRuntimeExecutor.cpp @@ -5,16 +5,17 @@ * LICENSE file in the root directory of this source tree. */ -#pragma once - -#include -#include "RCTARTSurfaceShadowNode.h" +#include "JRuntimeExecutor.h" namespace facebook { namespace react { -using RCTARTSurfaceComponentDescriptor = - ConcreteComponentDescriptor; +JRuntimeExecutor::JRuntimeExecutor(RuntimeExecutor runtimeExecutor) + : runtimeExecutor_(runtimeExecutor) {} + +RuntimeExecutor JRuntimeExecutor::get() { + return runtimeExecutor_; +} } // namespace react } // namespace facebook diff --git a/ReactAndroid/src/main/jni/react/jni/JRuntimeExecutor.h b/ReactAndroid/src/main/jni/react/jni/JRuntimeExecutor.h new file mode 100644 index 00000000000000..1a250d7a867b52 --- /dev/null +++ b/ReactAndroid/src/main/jni/react/jni/JRuntimeExecutor.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +namespace facebook { +namespace react { + +class JRuntimeExecutor : public jni::HybridClass { + public: + static auto constexpr kJavaDescriptor = + "Lcom/facebook/react/bridge/RuntimeExecutor;"; + + RuntimeExecutor get(); + + private: + friend HybridBase; + JRuntimeExecutor(RuntimeExecutor runtimeExecutor); + RuntimeExecutor runtimeExecutor_; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/better/BUCK b/ReactCommon/better/BUCK index bff98453e7633a..fb403d3a8dfad5 100644 --- a/ReactCommon/better/BUCK +++ b/ReactCommon/better/BUCK @@ -35,6 +35,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -48,10 +49,10 @@ rn_xplat_cxx_library( tests = [], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", ], ) diff --git a/ReactCommon/callinvoker/BUCK b/ReactCommon/callinvoker/BUCK index a9c3fca7e279b5..0f702cb7282867 100644 --- a/ReactCommon/callinvoker/BUCK +++ b/ReactCommon/callinvoker/BUCK @@ -16,6 +16,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], platforms = (ANDROID, APPLE), preferred_linkage = "static", diff --git a/ReactCommon/config/BUCK b/ReactCommon/config/BUCK index 361f317ba0e042..9c81d30e98dab6 100644 --- a/ReactCommon/config/BUCK +++ b/ReactCommon/config/BUCK @@ -24,6 +24,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -37,10 +38,10 @@ rn_xplat_cxx_library( "PUBLIC", ], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", ], ) diff --git a/ReactCommon/cxxreact/Android.mk b/ReactCommon/cxxreact/Android.mk index 10c321448a61c5..df9b9e640bc69c 100644 --- a/ReactCommon/cxxreact/Android.mk +++ b/ReactCommon/cxxreact/Android.mk @@ -19,7 +19,7 @@ LOCAL_CFLAGS := \ LOCAL_CFLAGS += -fexceptions -frtti -Wno-unused-lambda-capture -LOCAL_STATIC_LIBRARIES := boost jsi callinvoker +LOCAL_STATIC_LIBRARIES := boost jsi callinvoker runtimeexecutor LOCAL_SHARED_LIBRARIES := jsinspector libfolly_json glog include $(BUILD_STATIC_LIBRARY) diff --git a/ReactCommon/cxxreact/BUCK b/ReactCommon/cxxreact/BUCK index 8ef91ae51b020b..d5453556bd6e91 100644 --- a/ReactCommon/cxxreact/BUCK +++ b/ReactCommon/cxxreact/BUCK @@ -18,6 +18,7 @@ rn_xplat_cxx_library( prefix = "cxxreact", ), compiler_flags = CXX_LIBRARY_COMPILER_FLAGS, + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = get_apple_compiler_flags(), fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], force_static = True, @@ -43,6 +44,7 @@ rn_xplat_cxx_library( "-fexceptions", "-frtti", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = get_apple_compiler_flags(), fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], force_static = True, @@ -75,9 +77,9 @@ rn_xplat_cxx_library( ], deps = [ ":module", + "//third-party/glog:glog", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", ], ) @@ -126,6 +128,7 @@ rn_xplat_cxx_library( "-fexceptions", "-frtti", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbandroid_preprocessor_flags = get_android_inspector_flags(), fbobjc_compiler_flags = get_apple_compiler_flags(), fbobjc_force_static = True, @@ -151,7 +154,8 @@ rn_xplat_cxx_library( react_native_xplat_target("callinvoker:callinvoker"), react_native_xplat_target("jsinspector:jsinspector"), react_native_xplat_target("microprofiler:microprofiler"), + react_native_xplat_target("runtimeexecutor:runtimeexecutor"), + "//third-party/glog:glog", "//xplat/folly:optional", - "//xplat/third-party/glog:glog", ], ) diff --git a/ReactCommon/cxxreact/Instance.cpp b/ReactCommon/cxxreact/Instance.cpp index 6643b83a617865..d5b4af5e515ad8 100644 --- a/ReactCommon/cxxreact/Instance.cpp +++ b/ReactCommon/cxxreact/Instance.cpp @@ -229,6 +229,10 @@ std::shared_ptr Instance::getJSCallInvoker() { return std::static_pointer_cast(jsCallInvoker_); } +RuntimeExecutor Instance::getRuntimeExecutor() { + return nativeToJsBridge_->getRuntimeExecutor(); +} + std::shared_ptr Instance::getDecoratedNativeCallInvoker( std::shared_ptr nativeInvoker) { return nativeToJsBridge_->getDecoratedNativeCallInvoker(nativeInvoker); diff --git a/ReactCommon/cxxreact/Instance.h b/ReactCommon/cxxreact/Instance.h index 0d5bacb5360243..f475bf8a7fa72c 100644 --- a/ReactCommon/cxxreact/Instance.h +++ b/ReactCommon/cxxreact/Instance.h @@ -12,6 +12,7 @@ #include #include +#include #include #ifndef RN_EXPORT @@ -129,6 +130,11 @@ class RN_EXPORT Instance { std::shared_ptr getDecoratedNativeCallInvoker( std::shared_ptr nativeInvoker); + /** + * RuntimeExecutor is used by Fabric to access the jsi::Runtime. + */ + RuntimeExecutor getRuntimeExecutor(); + private: void callNativeModules(folly::dynamic &&calls, bool isEndOfBatch); void loadBundle( diff --git a/ReactCommon/cxxreact/NativeToJsBridge.cpp b/ReactCommon/cxxreact/NativeToJsBridge.cpp index 4d31ef058a17ad..64b0673423b8d9 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.cpp +++ b/ReactCommon/cxxreact/NativeToJsBridge.cpp @@ -331,5 +331,22 @@ std::shared_ptr NativeToJsBridge::getDecoratedNativeCallInvoker( return std::make_shared(m_delegate, nativeInvoker); } +RuntimeExecutor NativeToJsBridge::getRuntimeExecutor() { + 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(); + callback(*runtime); + }); + }; + return runtimeExecutor; +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/cxxreact/NativeToJsBridge.h b/ReactCommon/cxxreact/NativeToJsBridge.h index 9cc9176b093bca..d298f9c27960c2 100644 --- a/ReactCommon/cxxreact/NativeToJsBridge.h +++ b/ReactCommon/cxxreact/NativeToJsBridge.h @@ -13,6 +13,7 @@ #include #include +#include #include namespace folly { @@ -106,6 +107,12 @@ class NativeToJsBridge { std::shared_ptr getDecoratedNativeCallInvoker( std::shared_ptr nativeInvoker); + /** + * RuntimeExecutor is used on Android to access the jsi::Runtime from Fabric + * and TurboModules + */ + RuntimeExecutor getRuntimeExecutor(); + private: // This is used to avoid a race condition where a proxyCallback gets queued // after ~NativeToJsBridge(), on the same thread. In that case, the callback diff --git a/ReactCommon/cxxreact/React-cxxreact.podspec b/ReactCommon/cxxreact/React-cxxreact.podspec index 12c0ac858aa5bb..cdb34aa745a8ef 100644 --- a/ReactCommon/cxxreact/React-cxxreact.podspec +++ b/ReactCommon/cxxreact/React-cxxreact.podspec @@ -41,4 +41,5 @@ Pod::Spec.new do |s| s.dependency "glog" s.dependency "React-jsinspector", version s.dependency "React-callinvoker", version + s.dependency "React-runtimeexecutor", version end diff --git a/ReactCommon/fabric/attributedstring/BUCK b/ReactCommon/fabric/attributedstring/BUCK index 0f7c23e1a08bec..cb6d8c234116b8 100644 --- a/ReactCommon/fabric/attributedstring/BUCK +++ b/ReactCommon/fabric/attributedstring/BUCK @@ -37,6 +37,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -50,11 +51,11 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", react_native_xplat_target("utils:utils"), react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("fabric/core:core"), diff --git a/ReactCommon/fabric/attributedstring/ParagraphAttributes.cpp b/ReactCommon/fabric/attributedstring/ParagraphAttributes.cpp index 1cddadf5dc1f89..f33662b81d65a4 100644 --- a/ReactCommon/fabric/attributedstring/ParagraphAttributes.cpp +++ b/ReactCommon/fabric/attributedstring/ParagraphAttributes.cpp @@ -20,12 +20,14 @@ bool ParagraphAttributes::operator==(const ParagraphAttributes &rhs) const { maximumNumberOfLines, ellipsizeMode, textBreakStrategy, - adjustsFontSizeToFit) == + adjustsFontSizeToFit, + includeFontPadding) == std::tie( rhs.maximumNumberOfLines, rhs.ellipsizeMode, rhs.textBreakStrategy, - rhs.adjustsFontSizeToFit) && + rhs.adjustsFontSizeToFit, + rhs.includeFontPadding) && floatEquality(minimumFontSize, rhs.minimumFontSize) && floatEquality(maximumFontSize, rhs.maximumFontSize); } @@ -44,7 +46,8 @@ SharedDebugStringConvertibleList ParagraphAttributes::getDebugProps() const { debugStringConvertibleItem("textBreakStrategy", textBreakStrategy), debugStringConvertibleItem("adjustsFontSizeToFit", adjustsFontSizeToFit), debugStringConvertibleItem("minimumFontSize", minimumFontSize), - debugStringConvertibleItem("maximumFontSize", maximumFontSize)}; + debugStringConvertibleItem("maximumFontSize", maximumFontSize), + debugStringConvertibleItem("includeFontPadding", includeFontPadding)}; } #endif diff --git a/ReactCommon/fabric/attributedstring/ParagraphAttributes.h b/ReactCommon/fabric/attributedstring/ParagraphAttributes.h index acc7636a6552b1..585696033618ce 100644 --- a/ReactCommon/fabric/attributedstring/ParagraphAttributes.h +++ b/ReactCommon/fabric/attributedstring/ParagraphAttributes.h @@ -49,6 +49,12 @@ class ParagraphAttributes : public DebugStringConvertible { */ bool adjustsFontSizeToFit{}; + /* + * (Android only) Leaves enough room for ascenders and descenders instead of + * using the font ascent and descent strictly. + */ + bool includeFontPadding{true}; + /* * In case of font size adjustment enabled, defines minimum and maximum * font sizes. @@ -82,7 +88,8 @@ struct hash { attributes.textBreakStrategy, attributes.adjustsFontSizeToFit, attributes.minimumFontSize, - attributes.maximumFontSize); + attributes.maximumFontSize, + attributes.includeFontPadding); } }; } // namespace std diff --git a/ReactCommon/fabric/attributedstring/conversions.h b/ReactCommon/fabric/attributedstring/conversions.h index e92f06ace4b5ed..774913dcd326e9 100644 --- a/ReactCommon/fabric/attributedstring/conversions.h +++ b/ReactCommon/fabric/attributedstring/conversions.h @@ -448,6 +448,11 @@ inline ParagraphAttributes convertRawProp( "maximumFontSize", sourceParagraphAttributes.maximumFontSize, defaultParagraphAttributes.maximumFontSize); + paragraphAttributes.includeFontPadding = convertRawProp( + rawProps, + "includeFontPadding", + sourceParagraphAttributes.includeFontPadding, + defaultParagraphAttributes.includeFontPadding); return paragraphAttributes; } @@ -481,6 +486,8 @@ inline folly::dynamic toDynamic( values("ellipsizeMode", toString(paragraphAttributes.ellipsizeMode)); values("textBreakStrategy", toString(paragraphAttributes.textBreakStrategy)); values("adjustsFontSizeToFit", paragraphAttributes.adjustsFontSizeToFit); + values("includeFontPadding", paragraphAttributes.includeFontPadding); + return values; } diff --git a/ReactCommon/fabric/componentregistry/BUCK b/ReactCommon/fabric/componentregistry/BUCK index b5be24c533470c..1eec505f7e2cdf 100644 --- a/ReactCommon/fabric/componentregistry/BUCK +++ b/ReactCommon/fabric/componentregistry/BUCK @@ -36,6 +36,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -48,13 +49,13 @@ rn_xplat_cxx_library( ], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", "//xplat/jsi:JSIDynamic", "//xplat/jsi:jsi", - "//xplat/third-party/glog:glog", react_native_xplat_target("fabric/core:core"), react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("utils:utils"), diff --git a/ReactCommon/fabric/components/activityindicator/BUCK b/ReactCommon/fabric/components/activityindicator/BUCK index 310b4fe07f8f8a..b0eaa75eae36a7 100644 --- a/ReactCommon/fabric/components/activityindicator/BUCK +++ b/ReactCommon/fabric/components/activityindicator/BUCK @@ -35,6 +35,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -47,11 +48,11 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("fabric/core:core"), diff --git a/ReactCommon/fabric/components/image/BUCK b/ReactCommon/fabric/components/image/BUCK index 73d56d2ac01d47..9f94284cf15630 100644 --- a/ReactCommon/fabric/components/image/BUCK +++ b/ReactCommon/fabric/components/image/BUCK @@ -35,6 +35,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -47,11 +48,11 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("fabric/core:core"), diff --git a/ReactCommon/fabric/components/image/ImageShadowNode.cpp b/ReactCommon/fabric/components/image/ImageShadowNode.cpp index 5c34ca0ad34374..68d0667aa4e846 100644 --- a/ReactCommon/fabric/components/image/ImageShadowNode.cpp +++ b/ReactCommon/fabric/components/image/ImageShadowNode.cpp @@ -27,13 +27,18 @@ void ImageShadowNode::updateStateIfNeeded() { auto const &imageSource = getImageSource(); auto const ¤tState = getStateData(); + bool hasSameRadius = + getConcreteProps().blurRadius == currentState.getBlurRadius(); + bool hasSameImageSource = currentState.getImageSource() == imageSource; - if (currentState.getImageSource() == imageSource) { + if (hasSameImageSource && hasSameRadius) { return; } - auto state = ImageState{ - imageSource, imageManager_->requestImage(imageSource, getSurfaceId())}; + auto state = + ImageState{imageSource, + imageManager_->requestImage(imageSource, getSurfaceId()), + getConcreteProps().blurRadius}; setStateData(std::move(state)); } diff --git a/ReactCommon/fabric/components/image/ImageShadowNode.h b/ReactCommon/fabric/components/image/ImageShadowNode.h index a723a000b195dc..9ebcbdc97ada63 100644 --- a/ReactCommon/fabric/components/image/ImageShadowNode.h +++ b/ReactCommon/fabric/components/image/ImageShadowNode.h @@ -46,7 +46,7 @@ class ImageShadowNode final : public ConcreteViewShadowNode< ShadowNodeFamilyFragment const &familyFragment, ComponentDescriptor const &componentDescriptor) { auto imageSource = ImageSource{ImageSource::Type::Invalid}; - return {imageSource, {imageSource, nullptr}}; + return {imageSource, {imageSource, nullptr}, 0}; } #pragma mark - LayoutableShadowNode diff --git a/ReactCommon/fabric/components/image/ImageState.cpp b/ReactCommon/fabric/components/image/ImageState.cpp index 3521716d0b750e..d30d21680fb990 100644 --- a/ReactCommon/fabric/components/image/ImageState.cpp +++ b/ReactCommon/fabric/components/image/ImageState.cpp @@ -18,5 +18,9 @@ ImageRequest const &ImageState::getImageRequest() const { return *imageRequest_; } +Float ImageState::getBlurRadius() const { + return blurRadius_; +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/fabric/components/image/ImageState.h b/ReactCommon/fabric/components/image/ImageState.h index 5280e4b0c65350..e41a9f5be48c3d 100644 --- a/ReactCommon/fabric/components/image/ImageState.h +++ b/ReactCommon/fabric/components/image/ImageState.h @@ -19,10 +19,13 @@ namespace react { */ class ImageState final { public: - ImageState(ImageSource const &imageSource, ImageRequest imageRequest) + ImageState( + ImageSource const &imageSource, + ImageRequest imageRequest, + Float const blurRadius) : imageSource_(imageSource), - imageRequest_( - std::make_shared(std::move(imageRequest))){}; + imageRequest_(std::make_shared(std::move(imageRequest))), + blurRadius_(blurRadius){}; /* * Returns stored ImageSource object. @@ -35,8 +38,11 @@ class ImageState final { */ ImageRequest const &getImageRequest() const; + Float getBlurRadius() const; + #ifdef ANDROID - ImageState(ImageState const &previousState, folly::dynamic data){}; + ImageState(ImageState const &previousState, folly::dynamic data) + : blurRadius_{0} {}; /* * Empty implementation for Android because it doesn't use this class. @@ -49,6 +55,7 @@ class ImageState final { private: ImageSource imageSource_; std::shared_ptr imageRequest_; + Float const blurRadius_; }; } // namespace react diff --git a/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm index dec8a569783662..7e2c3813676cf0 100644 --- a/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm +++ b/ReactCommon/fabric/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm @@ -29,6 +29,12 @@ // If `moduleName` has "FB" prefix. return componentName + "Manager"; } + + std::string artPrefix("ART"); + if (std::mismatch(artPrefix.begin(), artPrefix.end(), componentName.begin()).first == artPrefix.end()) { + return componentName + "Manager"; + } + return "RCT" + componentName + "Manager"; } diff --git a/ReactCommon/fabric/components/modal/BUCK b/ReactCommon/fabric/components/modal/BUCK index 070a02cb8494fa..a84b80df2a456e 100644 --- a/ReactCommon/fabric/components/modal/BUCK +++ b/ReactCommon/fabric/components/modal/BUCK @@ -48,6 +48,7 @@ rn_xplat_cxx_library( fbandroid_headers = glob( ["platform/android/*.h"], ), + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbandroid_srcs = glob( ["platform/android/*.cpp"], ), @@ -71,11 +72,11 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("fabric/core:core"), diff --git a/ReactCommon/fabric/components/picker/BUCK b/ReactCommon/fabric/components/picker/BUCK index 829f5adec8fd0c..8508262ce704d0 100644 --- a/ReactCommon/fabric/components/picker/BUCK +++ b/ReactCommon/fabric/components/picker/BUCK @@ -44,7 +44,9 @@ rn_xplat_cxx_library( fbandroid_deps = [ react_native_target("jni/react/jni:jni"), ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, + fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), force_static = True, platforms = (ANDROID, APPLE, CXX), @@ -54,11 +56,11 @@ rn_xplat_cxx_library( ], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("fabric/core:core"), diff --git a/ReactCommon/fabric/components/root/BUCK b/ReactCommon/fabric/components/root/BUCK index f67ca8fc8a852d..5805cff81df76a 100644 --- a/ReactCommon/fabric/components/root/BUCK +++ b/ReactCommon/fabric/components/root/BUCK @@ -35,6 +35,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -47,11 +48,11 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("fabric/core:core"), diff --git a/ReactCommon/fabric/components/scrollview/BUCK b/ReactCommon/fabric/components/scrollview/BUCK index 492edfc0f93f11..5f59cfba1a4768 100644 --- a/ReactCommon/fabric/components/scrollview/BUCK +++ b/ReactCommon/fabric/components/scrollview/BUCK @@ -38,6 +38,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -51,11 +52,11 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("fabric/core:core"), diff --git a/ReactCommon/fabric/components/slider/BUCK b/ReactCommon/fabric/components/slider/BUCK index 52f567d985a99e..41ce2c68985eb3 100644 --- a/ReactCommon/fabric/components/slider/BUCK +++ b/ReactCommon/fabric/components/slider/BUCK @@ -53,6 +53,7 @@ rn_xplat_cxx_library( fbandroid_headers = glob( ["platform/android/*.h"], ), + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbandroid_srcs = glob( ["platform/android/*.cpp"], ), @@ -80,11 +81,11 @@ rn_xplat_cxx_library( ], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("fabric/core:core"), diff --git a/ReactCommon/fabric/components/switch/BUCK b/ReactCommon/fabric/components/switch/BUCK index f5b4493c5de37b..8d12a6a070fa0d 100644 --- a/ReactCommon/fabric/components/switch/BUCK +++ b/ReactCommon/fabric/components/switch/BUCK @@ -44,6 +44,7 @@ rn_xplat_cxx_library( fbandroid_deps = [ react_native_target("jni/react/jni:jni"), ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -55,11 +56,11 @@ rn_xplat_cxx_library( ], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("fabric/core:core"), diff --git a/ReactCommon/fabric/components/text/BUCK b/ReactCommon/fabric/components/text/BUCK index c32ad04dfc4509..a1271eb16c66ec 100644 --- a/ReactCommon/fabric/components/text/BUCK +++ b/ReactCommon/fabric/components/text/BUCK @@ -43,6 +43,7 @@ rn_xplat_cxx_library( "-Wall", ], cxx_tests = [":tests"], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -54,12 +55,12 @@ rn_xplat_cxx_library( ], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:container_evicting_cache_map", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("utils:utils"), react_native_xplat_target("fabric/attributedstring:attributedstring"), diff --git a/ReactCommon/fabric/components/textinput/BUCK b/ReactCommon/fabric/components/textinput/BUCK index aa630a15ac7383..616d7c0468e780 100644 --- a/ReactCommon/fabric/components/textinput/BUCK +++ b/ReactCommon/fabric/components/textinput/BUCK @@ -40,6 +40,7 @@ rn_xplat_cxx_library( "-Wall", ], cxx_tests = [":tests"], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -51,12 +52,12 @@ rn_xplat_cxx_library( ], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:container_evicting_cache_map", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("utils:utils"), react_native_xplat_target("fabric/attributedstring:attributedstring"), diff --git a/ReactCommon/fabric/components/textinput/androidtextinput/AndroidTextInputShadowNode.h b/ReactCommon/fabric/components/textinput/androidtextinput/AndroidTextInputShadowNode.h index 288545367b8b7e..be480cc8a13aba 100644 --- a/ReactCommon/fabric/components/textinput/androidtextinput/AndroidTextInputShadowNode.h +++ b/ReactCommon/fabric/components/textinput/androidtextinput/AndroidTextInputShadowNode.h @@ -30,6 +30,13 @@ class AndroidTextInputShadowNode : public ConcreteViewShadowNode< AndroidTextInputEventEmitter, AndroidTextInputState> { public: + static ShadowNodeTraits BaseTraits() { + auto traits = ConcreteViewShadowNode::BaseTraits(); + traits.set(ShadowNodeTraits::Trait::TextKind); + traits.set(ShadowNodeTraits::Trait::LeafYogaNode); + return traits; + } + using ConcreteViewShadowNode::ConcreteViewShadowNode; void setContextContainer(ContextContainer *contextContainer); diff --git a/ReactCommon/fabric/components/textinput/iostextinput/BUCK b/ReactCommon/fabric/components/textinput/iostextinput/BUCK index d6baec266ab94e..dfe4ccdf3df86e 100644 --- a/ReactCommon/fabric/components/textinput/iostextinput/BUCK +++ b/ReactCommon/fabric/components/textinput/iostextinput/BUCK @@ -51,12 +51,12 @@ rn_xplat_cxx_library( ], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:container_evicting_cache_map", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("utils:utils"), react_native_xplat_target("fabric/attributedstring:attributedstring"), diff --git a/ReactCommon/fabric/components/textinput/iostextinput/TextInputShadowNode.h b/ReactCommon/fabric/components/textinput/iostextinput/TextInputShadowNode.h index 96d3192c22d3ea..cfa7849ac7bd0d 100644 --- a/ReactCommon/fabric/components/textinput/iostextinput/TextInputShadowNode.h +++ b/ReactCommon/fabric/components/textinput/iostextinput/TextInputShadowNode.h @@ -36,6 +36,7 @@ class TextInputShadowNode : public ConcreteViewShadowNode< static ShadowNodeTraits BaseTraits() { auto traits = ConcreteViewShadowNode::BaseTraits(); traits.set(ShadowNodeTraits::Trait::TextKind); + traits.set(ShadowNodeTraits::Trait::LeafYogaNode); return traits; } diff --git a/ReactCommon/fabric/components/unimplementedview/BUCK b/ReactCommon/fabric/components/unimplementedview/BUCK index 1c8377d7daca60..aae773953d7f69 100644 --- a/ReactCommon/fabric/components/unimplementedview/BUCK +++ b/ReactCommon/fabric/components/unimplementedview/BUCK @@ -47,11 +47,11 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("fabric/core:core"), diff --git a/ReactCommon/fabric/components/view/BUCK b/ReactCommon/fabric/components/view/BUCK index 62aada6cf495ea..eb8a63fe20375a 100644 --- a/ReactCommon/fabric/components/view/BUCK +++ b/ReactCommon/fabric/components/view/BUCK @@ -41,6 +41,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -54,11 +55,11 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("fabric/core:core"), react_native_xplat_target("fabric/debug:debug"), diff --git a/ReactCommon/fabric/core/BUCK b/ReactCommon/fabric/core/BUCK index ecd7afa9203aba..5930a38025e754 100644 --- a/ReactCommon/fabric/core/BUCK +++ b/ReactCommon/fabric/core/BUCK @@ -44,6 +44,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -57,13 +58,13 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", "//xplat/jsi:JSIDynamic", "//xplat/jsi:jsi", - "//xplat/third-party/glog:glog", react_native_xplat_target("utils:utils"), react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("fabric/graphics:graphics"), diff --git a/ReactCommon/fabric/core/shadownode/ShadowNodeFamily.cpp b/ReactCommon/fabric/core/shadownode/ShadowNodeFamily.cpp index 2dd49e53065e66..fe2aaa84a753b4 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNodeFamily.cpp +++ b/ReactCommon/fabric/core/shadownode/ShadowNodeFamily.cpp @@ -119,6 +119,15 @@ void ShadowNodeFamily::setMostRecentState(State::Shared const &state) const { mostRecentState_ = state; } +std::shared_ptr ShadowNodeFamily::getMostRecentStateIfObsolete( + State const &state) const { + std::unique_lock lock(mutex_); + if (!state.isObsolete_) { + return {}; + } + return mostRecentState_; +} + void ShadowNodeFamily::dispatchRawState( StateUpdate &&stateUpdate, EventPriority priority) const { diff --git a/ReactCommon/fabric/core/shadownode/ShadowNodeFamily.h b/ReactCommon/fabric/core/shadownode/ShadowNodeFamily.h index 15998067f44222..1bf431061cb6b8 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNodeFamily.h +++ b/ReactCommon/fabric/core/shadownode/ShadowNodeFamily.h @@ -88,6 +88,15 @@ class ShadowNodeFamily { private: friend ShadowNode; friend ShadowNodeFamilyFragment; + friend State; + + /* + * Returns the most recent state if the given `state` is obsolete, + * otherwise returns `nullptr`. + * To be used by `State` only. + */ + std::shared_ptr getMostRecentStateIfObsolete( + State const &state) const; EventDispatcher::Weak eventDispatcher_; mutable std::shared_ptr mostRecentState_; diff --git a/ReactCommon/fabric/core/state/State.cpp b/ReactCommon/fabric/core/state/State.cpp index d6fb8afe8e5737..d8407cb7e64afe 100644 --- a/ReactCommon/fabric/core/state/State.cpp +++ b/ReactCommon/fabric/core/state/State.cpp @@ -32,6 +32,15 @@ State::Shared State::getMostRecentState() const { return family->getMostRecentState(); } +State::Shared State::getMostRecentStateIfObsolete() const { + auto family = family_.lock(); + if (!family) { + return {}; + } + + return family->getMostRecentStateIfObsolete(*this); +} + size_t State::getRevision() const { return revision_; } diff --git a/ReactCommon/fabric/core/state/State.h b/ReactCommon/fabric/core/state/State.h index e48cf15c3d409e..7e700da7e879d6 100644 --- a/ReactCommon/fabric/core/state/State.h +++ b/ReactCommon/fabric/core/state/State.h @@ -47,6 +47,12 @@ class State { */ State::Shared getMostRecentState() const; + /* + * Returns the most recent state (same as `getMostRecentState()` method) + * if this state is obsolete, otherwise returns `nullptr`. + */ + State::Shared getMostRecentStateIfObsolete() const; + /* * Returns a revision number of the `State` object. * The number is being automatically assigned during the creation of `State` diff --git a/ReactCommon/fabric/debug/BUCK b/ReactCommon/fabric/debug/BUCK index 766570e9ddbab2..9971b09cb503e3 100644 --- a/ReactCommon/fabric/debug/BUCK +++ b/ReactCommon/fabric/debug/BUCK @@ -39,6 +39,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), diff --git a/ReactCommon/fabric/graphics/BUCK b/ReactCommon/fabric/graphics/BUCK index b7a097079de887..bcedde153577c2 100644 --- a/ReactCommon/fabric/graphics/BUCK +++ b/ReactCommon/fabric/graphics/BUCK @@ -56,6 +56,7 @@ rn_xplat_cxx_library( ], prefix = "react/graphics", ), + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbandroid_srcs = glob( [ "platform/cxx/**/*.cpp", @@ -95,11 +96,11 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", ], ) diff --git a/ReactCommon/fabric/imagemanager/BUCK b/ReactCommon/fabric/imagemanager/BUCK index a5458f5071a0b6..ba638f1d1e8098 100644 --- a/ReactCommon/fabric/imagemanager/BUCK +++ b/ReactCommon/fabric/imagemanager/BUCK @@ -45,6 +45,7 @@ rn_xplat_cxx_library( ], prefix = "", ), + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbandroid_srcs = glob( [ "platform/cxx/**/*.cpp", @@ -96,11 +97,11 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("fabric/core:core"), react_native_xplat_target("fabric/mounting:mounting"), diff --git a/ReactCommon/fabric/mapbuffer/BUCK b/ReactCommon/fabric/mapbuffer/BUCK index cd4eee387d7357..89acfd5f302c30 100644 --- a/ReactCommon/fabric/mapbuffer/BUCK +++ b/ReactCommon/fabric/mapbuffer/BUCK @@ -40,10 +40,10 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", - "//xplat/third-party/glog:glog", react_native_xplat_target("utils:utils"), ], ) diff --git a/ReactCommon/fabric/mounting/BUCK b/ReactCommon/fabric/mounting/BUCK index 9d6ad218c1d131..afa937d70bd0cc 100644 --- a/ReactCommon/fabric/mounting/BUCK +++ b/ReactCommon/fabric/mounting/BUCK @@ -38,6 +38,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -51,11 +52,11 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", react_native_xplat_target("better:better"), react_native_xplat_target("fabric/components/root:root"), react_native_xplat_target("fabric/components/view:view"), @@ -76,6 +77,7 @@ fb_xplat_cxx_test( "-Wall", ], contacts = ["oncall+react_native@xmail.facebook.com"], + fbandroid_use_instrumentation_test = True, platforms = (ANDROID, APPLE, CXX), deps = [ ":mounting", diff --git a/ReactCommon/fabric/mounting/Differentiator.cpp b/ReactCommon/fabric/mounting/Differentiator.cpp index 919a7364de18ae..6661d5424407b2 100644 --- a/ReactCommon/fabric/mounting/Differentiator.cpp +++ b/ReactCommon/fabric/mounting/Differentiator.cpp @@ -54,7 +54,13 @@ class TinyMap final { // then we don't need to clean. cleanVector(erasedAtFront_ != numErased_); - return begin_(); + Iterator it = begin_(); + + if (it != nullptr) { + return it + erasedAtFront_; + } + + return nullptr; } inline Iterator end() { @@ -71,6 +77,10 @@ class TinyMap final { assert(key != 0); + if (begin_() == nullptr) { + return end(); + } + for (auto it = begin_() + erasedAtFront_; it != end(); it++) { if (it->first == key) { return it; @@ -86,14 +96,14 @@ class TinyMap final { } inline void erase(Iterator iterator) { - numErased_++; - // Invalidate tag. iterator->first = 0; if (iterator == begin_() + erasedAtFront_) { erasedAtFront_++; } + + numErased_++; } private: @@ -643,7 +653,7 @@ static void calculateShadowViewMutationsOptimizedMoves( } // At this point, oldTag is -1 or is in the new list, and hasn't been - // inserted or matched yet We're not sure yet if the new node is in the + // inserted or matched yet. We're not sure yet if the new node is in the // old list - generate an insert instruction for the new node. auto const &newChildPair = newChildPairs[newIndex]; insertMutations.push_back(ShadowViewMutation::InsertMutation( @@ -655,6 +665,14 @@ static void calculateShadowViewMutationsOptimizedMoves( // Final step: generate Create instructions for new nodes for (auto it = newInsertedPairs.begin(); it != newInsertedPairs.end(); it++) { + // Erased elements of a TinyMap will have a Tag/key of 0 - skip those + // These *should* be removed by the map; there are currently no KNOWN + // cases where TinyMap will do the wrong thing, but there are not yet + // any unit tests explicitly for TinyMap, so this is safer for now. + if (it->first == 0) { + continue; + } + auto const &newChildPair = *it->second; createMutations.push_back( ShadowViewMutation::CreateMutation(newChildPair.shadowView)); diff --git a/ReactCommon/fabric/mounting/ShadowTree.cpp b/ReactCommon/fabric/mounting/ShadowTree.cpp index 4099d0f1195dce..654d26fed0558a 100644 --- a/ReactCommon/fabric/mounting/ShadowTree.cpp +++ b/ReactCommon/fabric/mounting/ShadowTree.cpp @@ -22,6 +22,141 @@ namespace facebook { namespace react { +/* + * Generates (possibly) a new tree where all nodes with non-obsolete `State` + * objects. If all `State` objects in the tree are not obsolete for the moment + * of calling, the function returns `nullptr` (as an indication that no + * additional work is required). + */ +static ShadowNode::Unshared progressState(ShadowNode const &shadowNode) { + auto isStateChanged = false; + auto areChildrenChanged = false; + + auto newState = shadowNode.getState(); + if (newState) { + newState = newState->getMostRecentStateIfObsolete(); + if (newState) { + isStateChanged = true; + } + } + + auto newChildren = ShadowNode::ListOfShared{}; + if (shadowNode.getChildren().size() > 0) { + auto index = size_t{0}; + for (auto const &childNode : shadowNode.getChildren()) { + auto newChildNode = progressState(*childNode); + if (newChildNode) { + if (!areChildrenChanged) { + // Making a copy before the first mutation. + newChildren = shadowNode.getChildren(); + } + newChildren[index] = newChildNode; + areChildrenChanged = true; + } + index++; + } + } + + if (!areChildrenChanged && !isStateChanged) { + return nullptr; + } + + return shadowNode.clone({ + ShadowNodeFragment::propsPlaceholder(), + areChildrenChanged ? std::make_shared( + std::move(newChildren)) + : ShadowNodeFragment::childrenPlaceholder(), + isStateChanged ? newState : ShadowNodeFragment::statePlaceholder(), + }); +} + +/* + * An optimized version of the previous function (and relies on it). + * The function uses a given base tree to exclude unchanged (equal) parts + * of the three from the traversing. + */ +static ShadowNode::Unshared progressState( + ShadowNode const &shadowNode, + ShadowNode const &baseShadowNode) { + // The intuition behind the complexity: + // - A very few nodes have associated state, therefore it's mostly reading and + // it only writes when state objects were found obsolete; + // - Most before-after trees are aligned, therefore most tree branches will be + // skipped; + // - If trees are significantly different, any other algorithm will have + // close to linear complexity. + + auto isStateChanged = false; + auto areChildrenChanged = false; + + auto newState = shadowNode.getState(); + if (newState) { + newState = newState->getMostRecentStateIfObsolete(); + if (newState) { + isStateChanged = true; + } + } + + auto &children = shadowNode.getChildren(); + auto &baseChildren = baseShadowNode.getChildren(); + auto newChildren = ShadowNode::ListOfShared{}; + + auto childrenSize = children.size(); + auto baseChildrenSize = baseChildren.size(); + auto index = size_t{0}; + + // Stage 1: Aligned part. + for (index = 0; index < childrenSize && index < baseChildrenSize; index++) { + const auto &childNode = *children.at(index); + const auto &baseChildNode = *baseChildren.at(index); + + if (&childNode == &baseChildNode) { + // Nodes are identical, skipping. + continue; + } + + if (!ShadowNode::sameFamily(childNode, baseChildNode)) { + // Totally different nodes, updating is impossible. + break; + } + + auto newChildNode = progressState(childNode, baseChildNode); + if (newChildNode) { + if (!areChildrenChanged) { + // Making a copy before the first mutation. + newChildren = children; + } + newChildren[index] = newChildNode; + areChildrenChanged = true; + } + } + + // Stage 2: Misaligned part. + for (; index < childrenSize; index++) { + auto newChildNode = progressState(*children.at(index)); + if (newChildNode) { + if (!areChildrenChanged) { + // Making a copy before the first mutation. + newChildren = children; + } + newChildren[index] = newChildNode; + areChildrenChanged = true; + } + } + + if (!areChildrenChanged && !isStateChanged) { + return nullptr; + } + + return shadowNode.clone({ + ShadowNodeFragment::propsPlaceholder(), + areChildrenChanged ? std::make_shared( + std::move(newChildren)) + : ShadowNodeFragment::childrenPlaceholder(), + isStateChanged ? newState : ShadowNodeFragment::statePlaceholder(), + }); +} + static void updateMountedFlag( const SharedShadowNodeList &oldChildren, const SharedShadowNodeList &newChildren) { @@ -161,14 +296,23 @@ bool ShadowTree::tryCommit( return false; } - // Compare state revisions of old and new root - // Children of the root node may be mutated in-place if (enableStateReconciliation) { - UnsharedShadowNode reconciledNode = - reconcileStateWithTree(newRootShadowNode.get(), oldRootShadowNode); - if (reconciledNode != nullptr) { - newRootShadowNode = std::make_shared( - *reconciledNode, ShadowNodeFragment{}); + if (enableNewStateReconciliation_) { + auto updatedNewRootShadowNode = + progressState(*newRootShadowNode, *oldRootShadowNode); + if (updatedNewRootShadowNode) { + newRootShadowNode = + std::static_pointer_cast(updatedNewRootShadowNode); + } + } else { + // Compare state revisions of old and new root + // Children of the root node may be mutated in-place + UnsharedShadowNode reconciledNode = + reconcileStateWithTree(newRootShadowNode.get(), oldRootShadowNode); + if (reconciledNode != nullptr) { + newRootShadowNode = std::make_shared( + *reconciledNode, ShadowNodeFragment{}); + } } } diff --git a/ReactCommon/fabric/mounting/ShadowTree.h b/ReactCommon/fabric/mounting/ShadowTree.h index a2e9aaa1742055..f0c904d5159a0c 100644 --- a/ReactCommon/fabric/mounting/ShadowTree.h +++ b/ReactCommon/fabric/mounting/ShadowTree.h @@ -71,6 +71,14 @@ class ShadowTree final { MountingCoordinator::Shared getMountingCoordinator() const; + /* + * Temporary. + * Do not use. + */ + void setEnableNewStateReconciliation(bool value) { + enableNewStateReconciliation_ = value; + } + private: RootShadowNode::Unshared cloneRootShadowNode( RootShadowNode::Shared const &oldRootShadowNode, @@ -88,6 +96,7 @@ class ShadowTree final { mutable ShadowTreeRevision::Number revisionNumber_{ 0}; // Protected by `commitMutex_`. MountingCoordinator::Shared mountingCoordinator_; + bool enableNewStateReconciliation_{false}; }; } // namespace react diff --git a/ReactCommon/fabric/mounting/tests/MountingTelemetryTest.cpp b/ReactCommon/fabric/mounting/tests/MountingTelemetryTest.cpp index 8d1426675b85bb..cf31109a38fa32 100644 --- a/ReactCommon/fabric/mounting/tests/MountingTelemetryTest.cpp +++ b/ReactCommon/fabric/mounting/tests/MountingTelemetryTest.cpp @@ -27,7 +27,7 @@ void sleep(double durationInSeconds) { } TEST(MountingTelemetryTest, timepoints) { - auto threshold = int64_t{10}; + auto threshold = int64_t{70}; auto timepointA = telemetryTimePointNow(); sleep(0.1); @@ -39,7 +39,7 @@ TEST(MountingTelemetryTest, timepoints) { } TEST(MountingTelemetryTest, normalUseCase) { - auto threshold = int64_t{10}; + auto threshold = int64_t{70}; auto telemetry = MountingTelemetry{}; telemetry.willCommit(); diff --git a/ReactCommon/fabric/mounting/tests/MountingTest.cpp b/ReactCommon/fabric/mounting/tests/MountingTest.cpp index 4783516bf1c4a5..52361e23dc5ab3 100644 --- a/ReactCommon/fabric/mounting/tests/MountingTest.cpp +++ b/ReactCommon/fabric/mounting/tests/MountingTest.cpp @@ -77,6 +77,11 @@ TEST(MountingTest, testMinimalInstructionGeneration) { auto childD = makeNode(viewComponentDescriptor, 103, {}); auto childE = makeNode(viewComponentDescriptor, 104, {}); auto childF = makeNode(viewComponentDescriptor, 105, {}); + auto childG = makeNode(viewComponentDescriptor, 106, {}); + auto childH = makeNode(viewComponentDescriptor, 107, {}); + auto childI = makeNode(viewComponentDescriptor, 108, {}); + auto childJ = makeNode(viewComponentDescriptor, 109, {}); + auto childK = makeNode(viewComponentDescriptor, 110, {}); auto family = viewComponentDescriptor.createFamily( {10, SurfaceId(1), nullptr}, nullptr); @@ -107,6 +112,17 @@ TEST(MountingTest, testMinimalInstructionGeneration) { generateDefaultProps(viewComponentDescriptor), std::make_shared(SharedShadowNodeList{ childB, childA, childD, childF, childE, childC})}); + auto shadowNodeV7 = shadowNodeV6->clone(ShadowNodeFragment{ + generateDefaultProps(viewComponentDescriptor), + std::make_shared(SharedShadowNodeList{childF, + childE, + childC, + childD, + childG, + childH, + childI, + childJ, + childK})}); // Injecting a tree into the root node. auto rootNodeV1 = std::static_pointer_cast( @@ -139,6 +155,11 @@ TEST(MountingTest, testMinimalInstructionGeneration) { ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), std::make_shared( SharedShadowNodeList{shadowNodeV6})})); + auto rootNodeV7 = std::static_pointer_cast( + rootNodeV6->ShadowNode::clone( + ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), + std::make_shared( + SharedShadowNodeList{shadowNodeV7})})); // Layout and diff std::vector affectedLayoutableNodesV1{}; @@ -307,6 +328,23 @@ TEST(MountingTest, testMinimalInstructionGeneration) { assert(mutations5[3].type == ShadowViewMutation::Insert); assert(mutations5[3].newChildShadowView.tag == 105); assert(mutations5[3].index == 3); + + auto mutations6 = calculateShadowViewMutations( + DifferentiatorMode::OptimizedMoves, *rootNodeV6, *rootNodeV7); + + // The order and exact mutation instructions here may change at any time. + // This test just ensures that any changes are intentional. + // This test, in particular, ensures that a bug has been fixed: that with + // a particular sequence of inserts/removes/moves, we don't unintentionally + // create more "CREATE" mutations than necessary. + // The actual nodes that should be created in this transaction have a tag > + // 105. + assert(mutations6.size() == 25); + for (int i = 0; i < mutations6.size(); i++) { + if (mutations6[i].type == ShadowViewMutation::Create) { + assert(mutations6[i].newChildShadowView.tag > 105); + } + } } } // namespace react diff --git a/ReactCommon/fabric/mounting/tests/ShadowTreeLifeCycleTest.cpp b/ReactCommon/fabric/mounting/tests/ShadowTreeLifeCycleTest.cpp index 5eb9c6aa0c8583..ab2ad89b990449 100644 --- a/ReactCommon/fabric/mounting/tests/ShadowTreeLifeCycleTest.cpp +++ b/ReactCommon/fabric/mounting/tests/ShadowTreeLifeCycleTest.cpp @@ -114,6 +114,9 @@ static void testShadowNodeTreeLifeCycle( LOG(ERROR) << "Entropy seed: " << entropy.getSeed() << "\n"; + // There are some issues getting `getDebugDescription` to compile + // under test on Android for now. +#ifndef ANDROID LOG(ERROR) << "Shadow Tree before: \n" << currentRootNode->getDebugDescription(); LOG(ERROR) << "Shadow Tree after: \n" @@ -128,6 +131,7 @@ static void testShadowNodeTreeLifeCycle( LOG(ERROR) << "Mutations:" << "\n" << getDebugDescription(mutations, {}); +#endif FAIL(); } @@ -165,7 +169,7 @@ TEST(MountingTest, stableSmallerTreeMoreIterationsClassic) { TEST(MountingTest, stableBiggerTreeFewerIterationsOptimizedMoves) { testShadowNodeTreeLifeCycle( DifferentiatorMode::OptimizedMoves, - /* seed */ 1, + /* seed */ 0, /* size */ 512, /* repeats */ 32, /* stages */ 32); @@ -174,7 +178,7 @@ TEST(MountingTest, stableBiggerTreeFewerIterationsOptimizedMoves) { TEST(MountingTest, stableSmallerTreeMoreIterationsOptimizedMoves) { testShadowNodeTreeLifeCycle( DifferentiatorMode::OptimizedMoves, - /* seed */ 1, + /* seed */ 0, /* size */ 16, /* repeats */ 512, /* stages */ 32); diff --git a/ReactCommon/fabric/scheduler/AsynchronousEventBeat.cpp b/ReactCommon/fabric/scheduler/AsynchronousEventBeat.cpp new file mode 100644 index 00000000000000..2649227d327ffd --- /dev/null +++ b/ReactCommon/fabric/scheduler/AsynchronousEventBeat.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "AsynchronousEventBeat.h" + +namespace facebook { +namespace react { + +AsynchronousEventBeat::AsynchronousEventBeat( + RunLoopObserver::Unique uiRunLoopObserver, + RuntimeExecutor runtimeExecutor) + : EventBeat({}), + uiRunLoopObserver_(std::move(uiRunLoopObserver)), + runtimeExecutor_(std::move(runtimeExecutor)) { + uiRunLoopObserver_->setDelegate(this); + uiRunLoopObserver_->enable(); +} + +void AsynchronousEventBeat::activityDidChange( + RunLoopObserver::Delegate const *delegate, + RunLoopObserver::Activity activity) const noexcept { + assert(delegate == this); + induce(); +} + +void AsynchronousEventBeat::induce() const { + if (!isRequested_) { + return; + } + + // Here we know that `this` object exists because the caller has a strong + // pointer to `owner`. To ensure the object will exist inside + // `runtimeExecutor_` callback, we need to copy the pointer there. + auto weakOwner = uiRunLoopObserver_->getOwner(); + + runtimeExecutor_([this, weakOwner](jsi::Runtime &runtime) mutable { + auto owner = weakOwner.lock(); + if (!owner) { + return; + } + + if (!isRequested_) { + return; + } + + this->beat(runtime); + }); +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/scheduler/AsynchronousEventBeat.h b/ReactCommon/fabric/scheduler/AsynchronousEventBeat.h new file mode 100644 index 00000000000000..6e95c9b8f7918d --- /dev/null +++ b/ReactCommon/fabric/scheduler/AsynchronousEventBeat.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include +#include + +namespace facebook { +namespace react { + +/* + * Event beat associated with JavaScript runtime. + * The beat is called on `RuntimeExecutor`'s thread induced by the UI thread + * event loop. + */ +class AsynchronousEventBeat : public EventBeat, + public RunLoopObserver::Delegate { + public: + AsynchronousEventBeat( + RunLoopObserver::Unique uiRunLoopObserver, + RuntimeExecutor runtimeExecutor); + + void induce() const override; + +#pragma mark - RunLoopObserver::Delegate + + void activityDidChange( + RunLoopObserver::Delegate const *delegate, + RunLoopObserver::Activity activity) const noexcept override; + + private: + RunLoopObserver::Unique uiRunLoopObserver_; + RuntimeExecutor runtimeExecutor_; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/scheduler/BUCK b/ReactCommon/fabric/scheduler/BUCK index 527e6756d5f96d..e65958365b3007 100644 --- a/ReactCommon/fabric/scheduler/BUCK +++ b/ReactCommon/fabric/scheduler/BUCK @@ -36,6 +36,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -48,13 +49,13 @@ rn_xplat_cxx_library( ], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", "//xplat/jsi:JSIDynamic", "//xplat/jsi:jsi", - "//xplat/third-party/glog:glog", react_native_xplat_target("fabric/core:core"), react_native_xplat_target("fabric/mounting:mounting"), react_native_xplat_target("fabric/uimanager:uimanager"), diff --git a/ReactCommon/fabric/scheduler/Scheduler.cpp b/ReactCommon/fabric/scheduler/Scheduler.cpp index 671713b4b69a8a..e9db21ae7e7812 100644 --- a/ReactCommon/fabric/scheduler/Scheduler.cpp +++ b/ReactCommon/fabric/scheduler/Scheduler.cpp @@ -80,6 +80,14 @@ Scheduler::Scheduler( delegate_ = delegate; uiManager_ = uiManager; + +#ifdef ANDROID + enableNewStateReconciliation_ = reactNativeConfig_->getBool( + "react_fabric:enable_new_state_reconciliation_android"); +#else + enableNewStateReconciliation_ = reactNativeConfig_->getBool( + "react_fabric:enable_new_state_reconciliation_ios"); +#endif } Scheduler::~Scheduler() { @@ -141,6 +149,8 @@ void Scheduler::startSurface( *rootComponentDescriptor_, *uiManager_); + shadowTree->setEnableNewStateReconciliation(enableNewStateReconciliation_); + auto uiManager = uiManager_; uiManager->getShadowTreeRegistry().add(std::move(shadowTree)); diff --git a/ReactCommon/fabric/scheduler/Scheduler.h b/ReactCommon/fabric/scheduler/Scheduler.h index 59e91c5dfa711a..07799c62f1fa46 100644 --- a/ReactCommon/fabric/scheduler/Scheduler.h +++ b/ReactCommon/fabric/scheduler/Scheduler.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -21,7 +22,6 @@ #include #include #include -#include namespace facebook { namespace react { @@ -112,6 +112,7 @@ class Scheduler final : public UIManagerDelegate { std::shared_ptr uiManager_; std::shared_ptr reactNativeConfig_; EventDispatcher::Shared eventDispatcher_; + bool enableNewStateReconciliation_{false}; }; } // namespace react diff --git a/ReactCommon/fabric/scheduler/SchedulerToolbox.h b/ReactCommon/fabric/scheduler/SchedulerToolbox.h index 1862f1889fd0de..87462d89377ff1 100644 --- a/ReactCommon/fabric/scheduler/SchedulerToolbox.h +++ b/ReactCommon/fabric/scheduler/SchedulerToolbox.h @@ -7,10 +7,10 @@ #pragma once +#include #include #include #include -#include namespace facebook { namespace react { diff --git a/ReactCommon/fabric/scheduler/SynchronousEventBeat.cpp b/ReactCommon/fabric/scheduler/SynchronousEventBeat.cpp new file mode 100644 index 00000000000000..a30552eb51c29e --- /dev/null +++ b/ReactCommon/fabric/scheduler/SynchronousEventBeat.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "SynchronousEventBeat.h" + +namespace facebook { +namespace react { + +SynchronousEventBeat::SynchronousEventBeat( + RunLoopObserver::Unique uiRunLoopObserver, + RuntimeExecutor runtimeExecutor) + : EventBeat({}), + uiRunLoopObserver_(std::move(uiRunLoopObserver)), + runtimeExecutor_(std::move(runtimeExecutor)) { + uiRunLoopObserver_->setDelegate(this); + uiRunLoopObserver_->enable(); +} + +void SynchronousEventBeat::activityDidChange( + RunLoopObserver::Delegate const *delegate, + RunLoopObserver::Activity activity) const noexcept { + assert(delegate == this); + lockExecutorAndBeat(); +} + +void SynchronousEventBeat::induce() const { + if (!this->isRequested_) { + return; + } + + if (uiRunLoopObserver_->isOnRunLoopThread()) { + this->lockExecutorAndBeat(); + } +} + +void SynchronousEventBeat::lockExecutorAndBeat() const { + if (!this->isRequested_) { + return; + } + + executeSynchronouslyOnSameThread_CAN_DEADLOCK( + runtimeExecutor_, [this](jsi::Runtime &runtime) { beat(runtime); }); +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/scheduler/SynchronousEventBeat.h b/ReactCommon/fabric/scheduler/SynchronousEventBeat.h new file mode 100644 index 00000000000000..bf192e9078aff5 --- /dev/null +++ b/ReactCommon/fabric/scheduler/SynchronousEventBeat.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include + +namespace facebook { +namespace react { + +/* + * Event beat associated with main run loop. + * The callback is always called on the main thread. + */ +class SynchronousEventBeat final : public EventBeat, + public RunLoopObserver::Delegate { + public: + SynchronousEventBeat( + RunLoopObserver::Unique uiRunLoopObserver, + RuntimeExecutor runtimeExecutor); + + void induce() const override; + +#pragma mark - RunLoopObserver::Delegate + + void activityDidChange( + RunLoopObserver::Delegate const *delegate, + RunLoopObserver::Activity activity) const noexcept override; + + private: + void lockExecutorAndBeat() const; + + RunLoopObserver::Unique uiRunLoopObserver_; + RuntimeExecutor runtimeExecutor_; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/templateprocessor/BUCK b/ReactCommon/fabric/templateprocessor/BUCK index 4a35935675458a..168a55862964e0 100644 --- a/ReactCommon/fabric/templateprocessor/BUCK +++ b/ReactCommon/fabric/templateprocessor/BUCK @@ -37,6 +37,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -50,13 +51,13 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", "//xplat/jsi:JSIDynamic", "//xplat/jsi:jsi", - "//xplat/third-party/glog:glog", react_native_xplat_target("fabric/core:core"), react_native_xplat_target("fabric/uimanager:uimanager"), react_native_xplat_target("fabric/componentregistry:componentregistry"), diff --git a/ReactCommon/fabric/textlayoutmanager/BUCK b/ReactCommon/fabric/textlayoutmanager/BUCK index ba629ee394966b..720f3d3e8e2344 100644 --- a/ReactCommon/fabric/textlayoutmanager/BUCK +++ b/ReactCommon/fabric/textlayoutmanager/BUCK @@ -75,6 +75,7 @@ rn_xplat_cxx_library( ], prefix = "", ), + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbandroid_srcs = glob( [ "platform/android/**/*.cpp", @@ -117,11 +118,11 @@ rn_xplat_cxx_library( ], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("fabric/attributedstring:attributedstring"), react_native_xplat_target("fabric/core:core"), diff --git a/ReactCommon/fabric/uimanager/BUCK b/ReactCommon/fabric/uimanager/BUCK index e2bdd3b4c26864..0d46cf3f3fea90 100644 --- a/ReactCommon/fabric/uimanager/BUCK +++ b/ReactCommon/fabric/uimanager/BUCK @@ -37,6 +37,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), @@ -50,20 +51,20 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", "//xplat/jsi:JSIDynamic", "//xplat/jsi:jsi", - "//xplat/third-party/glog:glog", react_native_xplat_target("config:config"), react_native_xplat_target("fabric/components/view:view"), react_native_xplat_target("fabric/mounting:mounting"), react_native_xplat_target("fabric/core:core"), react_native_xplat_target("fabric/componentregistry:componentregistry"), react_native_xplat_target("fabric/debug:debug"), - react_native_xplat_target("utils:utils"), + react_native_xplat_target("runtimeexecutor:runtimeexecutor"), ], ) diff --git a/ReactCommon/fabric/uimanager/UIManager.cpp b/ReactCommon/fabric/uimanager/UIManager.cpp index c2fa6be9278cf7..e87280c58cd28a 100644 --- a/ReactCommon/fabric/uimanager/UIManager.cpp +++ b/ReactCommon/fabric/uimanager/UIManager.cpp @@ -125,11 +125,11 @@ void UIManager::clearJSResponder() const { } ShadowNode::Shared const *UIManager::getNewestCloneOfShadowNode( - ShadowNode::Shared const &shadowNode) const { + ShadowNode const &shadowNode) const { auto findNewestChildInParent = [&](auto const &parentNode) -> ShadowNode::Shared const * { for (auto const &child : parentNode.getChildren()) { - if (ShadowNode::sameFamily(*child, *shadowNode)) { + if (ShadowNode::sameFamily(*child, shadowNode)) { return &child; } } @@ -138,7 +138,7 @@ ShadowNode::Shared const *UIManager::getNewestCloneOfShadowNode( ShadowNode const *ancestorShadowNode; shadowTreeRegistry_.visit( - shadowNode->getSurfaceId(), [&](ShadowTree const &shadowTree) { + shadowNode.getSurfaceId(), [&](ShadowTree const &shadowTree) { shadowTree.tryCommit( [&](RootShadowNode::Shared const &oldRootShadowNode) { ancestorShadowNode = oldRootShadowNode.get(); @@ -147,7 +147,7 @@ ShadowNode::Shared const *UIManager::getNewestCloneOfShadowNode( true); }); - auto ancestors = shadowNode->getFamily().getAncestors(*ancestorShadowNode); + auto ancestors = shadowNode.getFamily().getAncestors(*ancestorShadowNode); return findNewestChildInParent(ancestors.rbegin()->first.get()); } @@ -156,7 +156,7 @@ ShadowNode::Shared UIManager::findNodeAtPoint( ShadowNode::Shared const &node, Point point) const { return LayoutableShadowNode::findNodeAtPoint( - *getNewestCloneOfShadowNode(node), point); + *getNewestCloneOfShadowNode(*node), point); } void UIManager::setNativeProps( @@ -200,10 +200,18 @@ LayoutMetrics UIManager::getRelativeLayoutMetrics( }, true); }); + } else { + ancestorShadowNode = getNewestCloneOfShadowNode(*ancestorShadowNode)->get(); } + // Get latest version of both the ShadowNode and its ancestor. + // It is possible for JS (or other callers) to have a reference + // to a previous version of ShadowNodes, but we enforce that + // metrics are only calculated on most recently committed versions. + auto newestShadowNode = getNewestCloneOfShadowNode(shadowNode); + auto layoutableShadowNode = - traitCast(&shadowNode); + traitCast(newestShadowNode->get()); auto layoutableAncestorShadowNode = traitCast(ancestorShadowNode); @@ -251,6 +259,10 @@ void UIManager::dispatchCommand( } } +void UIManager::configureNextLayoutAnimation( + const folly::dynamic config, + SharedEventTarget successCallback, + SharedEventTarget errorCallback) const {} void UIManager::setComponentDescriptorRegistry( const SharedComponentDescriptorRegistry &componentDescriptorRegistry) { componentDescriptorRegistry_ = componentDescriptorRegistry; diff --git a/ReactCommon/fabric/uimanager/UIManager.h b/ReactCommon/fabric/uimanager/UIManager.h index 7d282d43836205..956f459f935cee 100644 --- a/ReactCommon/fabric/uimanager/UIManager.h +++ b/ReactCommon/fabric/uimanager/UIManager.h @@ -93,7 +93,7 @@ class UIManager final : public ShadowTreeDelegate { Point point) const; ShadowNode::Shared const *getNewestCloneOfShadowNode( - ShadowNode::Shared const &shadowNode) const; + ShadowNode const &shadowNode) const; /* * Returns layout metrics of given `shadowNode` relative to @@ -116,6 +116,14 @@ class UIManager final : public ShadowTreeDelegate { std::string const &commandName, folly::dynamic const args) const; + /** + * Configure a LayoutAnimation to happen on the next commit. + * This API configures a global LayoutAnimation starting from the root node. + */ + void configureNextLayoutAnimation( + const folly::dynamic config, + SharedEventTarget successCallback, + SharedEventTarget errorCallback) const; ShadowTreeRegistry const &getShadowTreeRegistry() const; SharedComponentDescriptorRegistry componentDescriptorRegistry_; diff --git a/ReactCommon/fabric/uimanager/UIManagerBinding.cpp b/ReactCommon/fabric/uimanager/UIManagerBinding.cpp index 981a165bc669f9..4c50095e4416a8 100644 --- a/ReactCommon/fabric/uimanager/UIManagerBinding.cpp +++ b/ReactCommon/fabric/uimanager/UIManagerBinding.cpp @@ -535,10 +535,15 @@ jsi::Value UIManagerBinding::get( *shadowNodeFromValue(runtime, arguments[0]), nullptr, {/* .includeTransform = */ true}); - auto frame = layoutMetrics.frame; auto onSuccessFunction = arguments[1].getObject(runtime).getFunction(runtime); + if (layoutMetrics == EmptyLayoutMetrics) { + onSuccessFunction.call(runtime, {0, 0, 0, 0, 0, 0}); + return jsi::Value::undefined(); + } + + auto frame = layoutMetrics.frame; onSuccessFunction.call( runtime, {0, @@ -568,8 +573,13 @@ jsi::Value UIManagerBinding::get( auto onSuccessFunction = arguments[1].getObject(runtime).getFunction(runtime); - auto frame = layoutMetrics.frame; + if (layoutMetrics == EmptyLayoutMetrics) { + onSuccessFunction.call(runtime, {0, 0, 0, 0}); + return jsi::Value::undefined(); + } + + auto frame = layoutMetrics.frame; onSuccessFunction.call( runtime, {jsi::Value{runtime, (double)frame.origin.x}, @@ -598,6 +608,27 @@ jsi::Value UIManagerBinding::get( }); } + if (methodName == "configureNextLayoutAnimation") { + return jsi::Function::createFromHostFunction( + runtime, + name, + 3, + [uiManager]( + jsi::Runtime &runtime, + const jsi::Value &thisValue, + const jsi::Value *arguments, + size_t count) -> jsi::Value { + uiManager->configureNextLayoutAnimation( + commandArgsFromValue( + runtime, + arguments[0]), // TODO T66507273: do a better job of parsing + // these arguments into a real struct / use a + // C++ typed object instead of folly::dynamic + eventTargetFromValue(runtime, arguments[1], -1), + eventTargetFromValue(runtime, arguments[2], -1)); + return jsi::Value::undefined(); + }); + } return jsi::Value::undefined(); } diff --git a/ReactCommon/hermes/inspector/BUCK b/ReactCommon/hermes/inspector/BUCK index 5b5356b799794b..9757b023533637 100644 --- a/ReactCommon/hermes/inspector/BUCK +++ b/ReactCommon/hermes/inspector/BUCK @@ -50,7 +50,9 @@ fb_xplat_cxx_library( header_namespace = "hermes/inspector", exported_headers = CHROME_EXPORTED_HEADERS, compiler_flags = CFLAGS_BY_MODE[hermes_build_mode()], + fbandroid_labels = ["supermodule:android/default/public.hermes"], fbobjc_header_path_prefix = "hermes/inspector/chrome", + fbobjc_labels = ["supermodule:ios/default/public.hermes"], macosx_tests_override = [], tests = [":chrome-tests"], visibility = [ @@ -61,12 +63,12 @@ fb_xplat_cxx_library( react_native_xplat_target("jsinspector:jsinspector"), ":detail", ":inspectorlib", + "//third-party/glog:glog", "//xplat/folly:futures", "//xplat/folly:molly", "//xplat/hermes/API:HermesAPI", "//xplat/jsi:JSIDynamic", "//xplat/jsi:jsi", - "//xplat/third-party/glog:glog", ], ) @@ -116,7 +118,9 @@ fb_xplat_cxx_library( fbandroid_deps = [ "//fbandroid/native/fb:fb", ], + fbandroid_labels = ["supermodule:android/default/public.hermes"], fbobjc_header_path_prefix = "hermes/inspector/detail", + fbobjc_labels = ["supermodule:ios/default/public.hermes"], macosx_tests_override = [], tests = [":detail-tests"], visibility = [ @@ -188,7 +192,9 @@ fb_xplat_cxx_library( exported_headers = INSPECTOR_EXPORTED_HEADERS, compiler_flags = CFLAGS_BY_MODE[hermes_build_mode()], cxx_tests = [":inspector-tests"], + fbandroid_labels = ["supermodule:android/default/public.hermes"], fbobjc_header_path_prefix = "hermes/inspector", + fbobjc_labels = ["supermodule:ios/default/public.hermes"], macosx_tests_override = [], visibility = [ "PUBLIC", @@ -196,11 +202,11 @@ fb_xplat_cxx_library( xcode_public_headers_symlinks = True, deps = [ ":detail", + "//third-party/glog:glog", "//xplat/folly:futures", "//xplat/folly:molly", "//xplat/hermes/API:HermesAPI", "//xplat/jsi:jsi", - "//xplat/third-party/glog:glog", ], ) diff --git a/ReactCommon/hermes/inspector/Inspector.cpp b/ReactCommon/hermes/inspector/Inspector.cpp index 7376b578aa1e1c..3cca8ce1553b22 100644 --- a/ReactCommon/hermes/inspector/Inspector.cpp +++ b/ReactCommon/hermes/inspector/Inspector.cpp @@ -384,7 +384,8 @@ folly::Future Inspector::setPauseOnExceptions( folly::Future Inspector::setPauseOnLoads( const PauseOnLoadMode mode) { - std::unique_lock lock(mutex_); + // This flag does not touch the runtime, so it doesn't need the executor. + // Return a future anyways for consistency. auto promise = std::make_shared>(); pauseOnLoadMode_ = mode; promise->setValue(); diff --git a/ReactCommon/hermes/inspector/chrome/Connection.cpp b/ReactCommon/hermes/inspector/chrome/Connection.cpp index 6c170f312d3827..b7656bcf22c64d 100644 --- a/ReactCommon/hermes/inspector/chrome/Connection.cpp +++ b/ReactCommon/hermes/inspector/chrome/Connection.cpp @@ -35,6 +35,10 @@ namespace debugger = ::facebook::hermes::debugger; namespace inspector = ::facebook::hermes::inspector; namespace m = ::facebook::hermes::inspector::chrome::message; +static const char *const kVirtualBreakpointPrefix = "virtualbreakpoint-"; +static const char *const kBeforeScriptWithSourceMapExecution = + "beforeScriptWithSourceMapExecution"; + /* * Connection::Impl */ @@ -77,6 +81,8 @@ class Connection::Impl : public inspector::InspectorObserver, void handle(const m::debugger::ResumeRequest &req) override; void handle(const m::debugger::SetBreakpointRequest &req) override; void handle(const m::debugger::SetBreakpointByUrlRequest &req) override; + void handle( + const m::debugger::SetInstrumentationBreakpointRequest &req) override; void handle(const m::debugger::SetPauseOnExceptionsRequest &req) override; void handle(const m::debugger::StepIntoRequest &req) override; void handle(const m::debugger::StepOutRequest &req) override; @@ -88,7 +94,6 @@ class Connection::Impl : public inspector::InspectorObserver, const m::heapProfiler::StopTrackingHeapObjectsRequest &req) override; void handle(const m::runtime::EvaluateRequest &req) override; void handle(const m::runtime::GetPropertiesRequest &req) override; - void handle(const m::hermes::SetPauseOnLoadRequest &req) override; private: std::vector makePropsFromScope( @@ -111,6 +116,7 @@ class Connection::Impl : public inspector::InspectorObserver, folly::Function sendErrorToClient(int id); void sendResponseToClientViaExecutor(int id); void sendResponseToClientViaExecutor(folly::Future future, int id); + void sendResponseToClientViaExecutor(const m::Response &resp); void sendNotificationToClientViaExecutor(const m::Notification ¬e); void sendErrorToClientViaExecutor(int id, const std::string &error); @@ -131,6 +137,19 @@ class Connection::Impl : public inspector::InspectorObserver, std::mutex parsedScriptsMutex_; std::vector parsedScripts_; + // Some events are represented as a mode in Hermes but a breakpoint in CDP, + // e.g. "beforeScriptExecution" and "beforeScriptWithSourceMapExecution". + // Keep track of these separately. The caller should lock the + // virtualBreakpointMutex_. + std::mutex virtualBreakpointMutex_; + uint32_t nextVirtualBreakpoint_ = 1; + const std::string &createVirtualBreakpoint(const std::string &category); + bool isVirtualBreakpointId(const std::string &id); + bool hasVirtualBreakpoint(const std::string &category); + bool removeVirtualBreakpoint(const std::string &id); + std::unordered_map> + virtualBreakpoints_; + // The rest of these member variables are only accessed via executor_. std::unique_ptr executor_; std::unique_ptr remoteConn_; @@ -272,6 +291,7 @@ void Connection::Impl::onContextCreated(Inspector &inspector) { void Connection::Impl::onPause( Inspector &inspector, const debugger::ProgramState &state) { + bool sendNotification = true; m::debugger::PausedNotification note; note.callFrames = m::debugger::makeCallFrames(state, objTable_, getRuntime()); @@ -291,15 +311,37 @@ void Connection::Impl::onPause( case debugger::PauseReason::Exception: note.reason = "exception"; break; - case debugger::PauseReason::ScriptLoaded: - note.reason = "load"; + case debugger::PauseReason::ScriptLoaded: { + note.reason = "other"; + note.hitBreakpoints = std::vector(); + + std::lock_guard lock(virtualBreakpointMutex_); + for (auto &bp : + virtualBreakpoints_[kBeforeScriptWithSourceMapExecution]) { + note.hitBreakpoints->emplace_back(bp); + } + + // Debuggers don't tend to ever remove these kinds of breakpoints, but + // in the extremely unlikely event that it did *and* did it exactly + // between us 1. checking that we should stop, and 2. adding the stop + // reason here, then just resume and skip sending a pause notification. + if (note.hitBreakpoints->empty()) { + sendNotification = false; + inspector_->resume(); + } + }; + // This will be toggled back on in the next onScriptParsed if applicable + // Locking is handled by didPause in the inspector + inspector_->setPauseOnLoads(PauseOnLoadMode::None); break; default: note.reason = "other"; break; } - sendNotificationToClientViaExecutor(note); + if (sendNotification) { + sendNotificationToClientViaExecutor(note); + } } void Connection::Impl::onResume(Inspector &inspector) { @@ -318,6 +360,15 @@ void Connection::Impl::onScriptParsed( if (!info.sourceMappingUrl.empty()) { note.sourceMapURL = info.sourceMappingUrl; + + std::lock_guard lock(virtualBreakpointMutex_); + if (hasVirtualBreakpoint(kBeforeScriptWithSourceMapExecution)) { + // We are precariously relying on the fact that onScriptParsed + // is invoked immediately before the pause load mode is checked. + // That means that we can check for breakpoints and toggle the + // mode here, and then immediately turn it off in onPause. + inspector_->setPauseOnLoads(PauseOnLoadMode::All); + } } { @@ -525,9 +576,18 @@ void Connection::Impl::handle(const m::debugger::PauseRequest &req) { } void Connection::Impl::handle(const m::debugger::RemoveBreakpointRequest &req) { - auto breakpointId = folly::to(req.breakpointId); - sendResponseToClientViaExecutor( - inspector_->removeBreakpoint(breakpointId), req.id); + if (isVirtualBreakpointId(req.breakpointId)) { + std::lock_guard lock(virtualBreakpointMutex_); + if (!removeVirtualBreakpoint(req.breakpointId)) { + sendErrorToClientViaExecutor( + req.id, "Unknown breakpoint ID: " + req.breakpointId); + } + sendResponseToClientViaExecutor(req.id); + } else { + auto breakpointId = folly::to(req.breakpointId); + sendResponseToClientViaExecutor( + inspector_->removeBreakpoint(breakpointId), req.id); + } } void Connection::Impl::handle(const m::debugger::ResumeRequest &req) { @@ -594,6 +654,51 @@ void Connection::Impl::handle( .thenError(sendErrorToClient(req.id)); } +bool Connection::Impl::isVirtualBreakpointId(const std::string &id) { + return id.rfind(kVirtualBreakpointPrefix, 0) == 0; +} + +const std::string &Connection::Impl::createVirtualBreakpoint( + const std::string &category) { + auto ret = virtualBreakpoints_[category].insert(folly::to( + kVirtualBreakpointPrefix, nextVirtualBreakpoint_++)); + return *ret.first; +} + +bool Connection::Impl::hasVirtualBreakpoint(const std::string &category) { + auto pos = virtualBreakpoints_.find(category); + if (pos == virtualBreakpoints_.end()) + return false; + return !pos->second.empty(); +} + +bool Connection::Impl::removeVirtualBreakpoint(const std::string &id) { + // We expect roughly 1 category, so just iterate over all the sets + for (auto &kv : virtualBreakpoints_) { + if (kv.second.erase(id) > 0) { + return true; + } + } + return false; +} + +void Connection::Impl::handle( + const m::debugger::SetInstrumentationBreakpointRequest &req) { + if (req.instrumentation != kBeforeScriptWithSourceMapExecution) { + sendErrorToClientViaExecutor( + req.id, "Unknown instrumentation breakpoint: " + req.instrumentation); + return; + } + + // The act of creating and registering the breakpoint ID is enough + // to "set" it. We merely check for the existence of them later. + std::lock_guard lock(virtualBreakpointMutex_); + m::debugger::SetInstrumentationBreakpointResponse resp; + resp.id = req.id; + resp.breakpointId = createVirtualBreakpoint(req.instrumentation); + sendResponseToClientViaExecutor(resp); +} + void Connection::Impl::handle( const m::debugger::SetPauseOnExceptionsRequest &req) { debugger::PauseOnThrowMode mode = debugger::PauseOnThrowMode::None; @@ -761,21 +866,6 @@ void Connection::Impl::handle(const m::runtime::GetPropertiesRequest &req) { .thenError(sendErrorToClient(req.id)); } -void Connection::Impl::handle(const m::hermes::SetPauseOnLoadRequest &req) { - PauseOnLoadMode mode; - if (req.state == "none") { - mode = PauseOnLoadMode::None; - } else if (req.state == "all") { - mode = PauseOnLoadMode::All; - } else if (req.state == "smart") { - mode = PauseOnLoadMode::Smart; - } else { - sendErrorToClientViaExecutor(req.id, "Unrecognized pause on load mode"); - return; - } - sendResponseToClientViaExecutor(inspector_->setPauseOnLoads(mode), req.id); -} - /* * Send-to-client methods */ @@ -806,6 +896,15 @@ void Connection::Impl::sendResponseToClientViaExecutor(int id) { sendResponseToClientViaExecutor(folly::makeFuture(), id); } +void Connection::Impl::sendResponseToClientViaExecutor( + const m::Response &resp) { + std::string json = resp.toJson(); + + folly::makeFuture() + .via(executor_.get()) + .thenValue([this, json](const Unit &unit) { sendToClient(json); }); +} + void Connection::Impl::sendResponseToClientViaExecutor( folly::Future future, int id) { diff --git a/ReactCommon/hermes/inspector/chrome/MessageTypes.cpp b/ReactCommon/hermes/inspector/chrome/MessageTypes.cpp index 18ce5ac65a6a60..d40c05e14727d9 100644 --- a/ReactCommon/hermes/inspector/chrome/MessageTypes.cpp +++ b/ReactCommon/hermes/inspector/chrome/MessageTypes.cpp @@ -1,5 +1,5 @@ // Copyright 2004-present Facebook. All Rights Reserved. -// @generated SignedSource<<0d7691362d081e7bc44d2b7a0ed24371>> +// @generated SignedSource<<575de63c36edd2a9a0f191501fd4f662>> #include "MessageTypes.h" @@ -35,6 +35,8 @@ std::unique_ptr Request::fromJsonThrowOnError(const std::string &str) { {"Debugger.setBreakpoint", makeUnique}, {"Debugger.setBreakpointByUrl", makeUnique}, + {"Debugger.setInstrumentationBreakpoint", + makeUnique}, {"Debugger.setPauseOnExceptions", makeUnique}, {"Debugger.stepInto", makeUnique}, @@ -46,7 +48,6 @@ std::unique_ptr Request::fromJsonThrowOnError(const std::string &str) { makeUnique}, {"HeapProfiler.takeHeapSnapshot", makeUnique}, - {"Hermes.setPauseOnLoad", makeUnique}, {"Runtime.evaluate", makeUnique}, {"Runtime.getProperties", makeUnique}, }; @@ -506,6 +507,36 @@ void debugger::SetBreakpointByUrlRequest::accept( handler.handle(*this); } +debugger::SetInstrumentationBreakpointRequest:: + SetInstrumentationBreakpointRequest() + : Request("Debugger.setInstrumentationBreakpoint") {} + +debugger::SetInstrumentationBreakpointRequest:: + SetInstrumentationBreakpointRequest(const dynamic &obj) + : Request("Debugger.setInstrumentationBreakpoint") { + assign(id, obj, "id"); + assign(method, obj, "method"); + + dynamic params = obj.at("params"); + assign(instrumentation, params, "instrumentation"); +} + +dynamic debugger::SetInstrumentationBreakpointRequest::toDynamic() const { + dynamic params = dynamic::object; + put(params, "instrumentation", instrumentation); + + dynamic obj = dynamic::object; + put(obj, "id", id); + put(obj, "method", method); + put(obj, "params", std::move(params)); + return obj; +} + +void debugger::SetInstrumentationBreakpointRequest::accept( + RequestHandler &handler) const { + handler.handle(*this); +} + debugger::SetPauseOnExceptionsRequest::SetPauseOnExceptionsRequest() : Request("Debugger.setPauseOnExceptions") {} @@ -683,33 +714,6 @@ void heapProfiler::TakeHeapSnapshotRequest::accept( handler.handle(*this); } -hermes::SetPauseOnLoadRequest::SetPauseOnLoadRequest() - : Request("Hermes.setPauseOnLoad") {} - -hermes::SetPauseOnLoadRequest::SetPauseOnLoadRequest(const dynamic &obj) - : Request("Hermes.setPauseOnLoad") { - assign(id, obj, "id"); - assign(method, obj, "method"); - - dynamic params = obj.at("params"); - assign(state, params, "state"); -} - -dynamic hermes::SetPauseOnLoadRequest::toDynamic() const { - dynamic params = dynamic::object; - put(params, "state", state); - - dynamic obj = dynamic::object; - put(obj, "id", id); - put(obj, "method", method); - put(obj, "params", std::move(params)); - return obj; -} - -void hermes::SetPauseOnLoadRequest::accept(RequestHandler &handler) const { - handler.handle(*this); -} - runtime::EvaluateRequest::EvaluateRequest() : Request("Runtime.evaluate") {} runtime::EvaluateRequest::EvaluateRequest(const dynamic &obj) @@ -873,6 +877,24 @@ dynamic debugger::SetBreakpointByUrlResponse::toDynamic() const { return obj; } +debugger::SetInstrumentationBreakpointResponse:: + SetInstrumentationBreakpointResponse(const dynamic &obj) { + assign(id, obj, "id"); + + dynamic res = obj.at("result"); + assign(breakpointId, res, "breakpointId"); +} + +dynamic debugger::SetInstrumentationBreakpointResponse::toDynamic() const { + dynamic res = dynamic::object; + put(res, "breakpointId", breakpointId); + + dynamic obj = dynamic::object; + put(obj, "id", id); + put(obj, "result", std::move(res)); + return obj; +} + runtime::EvaluateResponse::EvaluateResponse(const dynamic &obj) { assign(id, obj, "id"); diff --git a/ReactCommon/hermes/inspector/chrome/MessageTypes.h b/ReactCommon/hermes/inspector/chrome/MessageTypes.h index 3d7222fd6ac65a..931e19fb41ab29 100644 --- a/ReactCommon/hermes/inspector/chrome/MessageTypes.h +++ b/ReactCommon/hermes/inspector/chrome/MessageTypes.h @@ -1,5 +1,5 @@ // Copyright 2004-present Facebook. All Rights Reserved. -// @generated SignedSource<<08b66e22784e225b926d36131b9a7693>> +// @generated SignedSource<> #pragma once @@ -38,6 +38,8 @@ struct SetBreakpointByUrlRequest; struct SetBreakpointByUrlResponse; struct SetBreakpointRequest; struct SetBreakpointResponse; +struct SetInstrumentationBreakpointRequest; +struct SetInstrumentationBreakpointResponse; struct SetPauseOnExceptionsRequest; struct StepIntoRequest; struct StepOutRequest; @@ -73,10 +75,6 @@ struct StopTrackingHeapObjectsRequest; struct TakeHeapSnapshotRequest; } // namespace heapProfiler -namespace hermes { -struct SetPauseOnLoadRequest; -} // namespace hermes - /// RequestHandler handles requests via the visitor pattern. struct RequestHandler { virtual ~RequestHandler() = default; @@ -90,6 +88,8 @@ struct RequestHandler { virtual void handle(const debugger::ResumeRequest &req) = 0; virtual void handle(const debugger::SetBreakpointRequest &req) = 0; virtual void handle(const debugger::SetBreakpointByUrlRequest &req) = 0; + virtual void handle( + const debugger::SetInstrumentationBreakpointRequest &req) = 0; virtual void handle(const debugger::SetPauseOnExceptionsRequest &req) = 0; virtual void handle(const debugger::StepIntoRequest &req) = 0; virtual void handle(const debugger::StepOutRequest &req) = 0; @@ -99,7 +99,6 @@ struct RequestHandler { virtual void handle( const heapProfiler::StopTrackingHeapObjectsRequest &req) = 0; virtual void handle(const heapProfiler::TakeHeapSnapshotRequest &req) = 0; - virtual void handle(const hermes::SetPauseOnLoadRequest &req) = 0; virtual void handle(const runtime::EvaluateRequest &req) = 0; virtual void handle(const runtime::GetPropertiesRequest &req) = 0; }; @@ -115,6 +114,8 @@ struct NoopRequestHandler : public RequestHandler { void handle(const debugger::ResumeRequest &req) override {} void handle(const debugger::SetBreakpointRequest &req) override {} void handle(const debugger::SetBreakpointByUrlRequest &req) override {} + void handle( + const debugger::SetInstrumentationBreakpointRequest &req) override {} void handle(const debugger::SetPauseOnExceptionsRequest &req) override {} void handle(const debugger::StepIntoRequest &req) override {} void handle(const debugger::StepOutRequest &req) override {} @@ -124,7 +125,6 @@ struct NoopRequestHandler : public RequestHandler { void handle( const heapProfiler::StopTrackingHeapObjectsRequest &req) override {} void handle(const heapProfiler::TakeHeapSnapshotRequest &req) override {} - void handle(const hermes::SetPauseOnLoadRequest &req) override {} void handle(const runtime::EvaluateRequest &req) override {} void handle(const runtime::GetPropertiesRequest &req) override {} }; @@ -351,6 +351,16 @@ struct debugger::SetBreakpointByUrlRequest : public Request { folly::Optional condition; }; +struct debugger::SetInstrumentationBreakpointRequest : public Request { + SetInstrumentationBreakpointRequest(); + explicit SetInstrumentationBreakpointRequest(const folly::dynamic &obj); + + folly::dynamic toDynamic() const override; + void accept(RequestHandler &handler) const override; + + std::string instrumentation; +}; + struct debugger::SetPauseOnExceptionsRequest : public Request { SetPauseOnExceptionsRequest(); explicit SetPauseOnExceptionsRequest(const folly::dynamic &obj); @@ -417,16 +427,6 @@ struct heapProfiler::TakeHeapSnapshotRequest : public Request { folly::Optional treatGlobalObjectsAsRoots; }; -struct hermes::SetPauseOnLoadRequest : public Request { - SetPauseOnLoadRequest(); - explicit SetPauseOnLoadRequest(const folly::dynamic &obj); - - folly::dynamic toDynamic() const override; - void accept(RequestHandler &handler) const override; - - std::string state; -}; - struct runtime::EvaluateRequest : public Request { EvaluateRequest(); explicit EvaluateRequest(const folly::dynamic &obj); @@ -499,6 +499,14 @@ struct debugger::SetBreakpointByUrlResponse : public Response { std::vector locations; }; +struct debugger::SetInstrumentationBreakpointResponse : public Response { + SetInstrumentationBreakpointResponse() = default; + explicit SetInstrumentationBreakpointResponse(const folly::dynamic &obj); + folly::dynamic toDynamic() const override; + + debugger::BreakpointId breakpointId{}; +}; + struct runtime::EvaluateResponse : public Response { EvaluateResponse() = default; explicit EvaluateResponse(const folly::dynamic &obj); diff --git a/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.cpp b/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.cpp index 9b85251ab0d415..5f9f96b9bc48b7 100644 --- a/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.cpp +++ b/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.cpp @@ -87,6 +87,10 @@ folly::Future AsyncHermesRuntime::getStoredValue() { return storedValue_.getFuture(); } +bool AsyncHermesRuntime::hasStoredValue() { + return storedValue_.isFulfilled(); +} + jsi::Value AsyncHermesRuntime::awaitStoredValue( std::chrono::milliseconds timeout) { return getStoredValue().get(timeout); diff --git a/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.h b/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.h index e1b8b24d7d70ed..b249746c407622 100644 --- a/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.h +++ b/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.h @@ -52,6 +52,11 @@ class AsyncHermesRuntime { */ folly::Future getStoredValue(); + /** + * hasStoredValue returns whether or not a value has been stored yet + */ + bool hasStoredValue(); + /** * awaitStoredValue is a helper for getStoredValue that returns the value * synchronously rather than in a future. diff --git a/ReactCommon/hermes/inspector/chrome/tests/ConnectionTests.cpp b/ReactCommon/hermes/inspector/chrome/tests/ConnectionTests.cpp index 18208192f67009..b55194a1869e1e 100644 --- a/ReactCommon/hermes/inspector/chrome/tests/ConnectionTests.cpp +++ b/ReactCommon/hermes/inspector/chrome/tests/ConnectionTests.cpp @@ -748,6 +748,46 @@ TEST(ConnectionTests, testSetBreakpointById) { expectNotification(conn); } +TEST(ConnectionTests, testSetBreakpointByIdWithColumnInIndenting) { + TestContext context; + AsyncHermesRuntime &asyncRuntime = context.runtime(); + SyncConnection &conn = context.conn(); + int msgId = 1; + + asyncRuntime.executeScriptAsync(R"( + debugger; // line 1 + Math.random(); // 2 + )"); + + send(conn, ++msgId); + expectExecutionContextCreated(conn); + auto script = expectNotification(conn); + + expectPaused(conn, "other", {{"global", 1, 1}}); + + m::debugger::SetBreakpointRequest req; + req.id = ++msgId; + req.location.scriptId = script.scriptId; + req.location.lineNumber = 2; + // Specify a column location *before* rather than *on* the actual location + req.location.columnNumber = 0; + + conn.send(req.toJson()); + auto resp = expectResponse(conn, req.id); + EXPECT_EQ(resp.actualLocation.scriptId, script.scriptId); + EXPECT_EQ(resp.actualLocation.lineNumber, 2); + // Check that we resolved the column to the first available location + EXPECT_EQ(resp.actualLocation.columnNumber.value(), 4); + + send(conn, ++msgId); + expectNotification(conn); + + expectPaused(conn, "other", {{"global", 2, 1}}); + + send(conn, ++msgId); + expectNotification(conn); +} + TEST(ConnectionTests, testSetLazyBreakpoint) { TestContext context; AsyncHermesRuntime &asyncRuntime = context.runtime(); @@ -2231,6 +2271,84 @@ function foo(){x=1}debugger;foo(); expectNotification(conn); } +TEST(ConnectionTests, canBreakOnScriptsWithSourceMap) { + TestContext context; + AsyncHermesRuntime &asyncRuntime = context.runtime(); + SyncConnection &conn = context.conn(); + int msgId = 1; + + send(conn, msgId++); + expectExecutionContextCreated(conn); + + m::debugger::SetInstrumentationBreakpointRequest req; + req.id = msgId++; + req.instrumentation = "beforeScriptWithSourceMapExecution"; + + conn.send(req.toJson()); + auto bpId = expectResponse( + conn, req.id) + .breakpointId; + + asyncRuntime.executeScriptAsync(R"( + storeValue(42); debugger; + //# sourceURL=http://example.com/source.js + //# sourceMappingURL=http://example.com/source.map + )"); + expectNotification(conn); + + // We should get a pause before the first statement + auto note = expectNotification(conn); + ASSERT_FALSE(asyncRuntime.hasStoredValue()); + EXPECT_EQ(note.reason, "other"); + ASSERT_TRUE(note.hitBreakpoints.hasValue()); + ASSERT_EQ(note.hitBreakpoints->size(), 1); + EXPECT_EQ(note.hitBreakpoints->at(0), bpId); + + // Continue and verify that the JS code has now executed + send(conn, msgId++); + expectNotification(conn); + expectNotification(conn); + EXPECT_EQ(asyncRuntime.awaitStoredValue().asNumber(), 42); + + // Resume and exit + send(conn, msgId++); + expectNotification(conn); +} + +TEST(ConnectionTests, wontStopOnFilesWithoutSourceMaps) { + TestContext context; + AsyncHermesRuntime &asyncRuntime = context.runtime(); + SyncConnection &conn = context.conn(); + int msgId = 1; + + send(conn, msgId++); + expectExecutionContextCreated(conn); + + m::debugger::SetInstrumentationBreakpointRequest req; + req.id = msgId++; + req.instrumentation = "beforeScriptWithSourceMapExecution"; + + conn.send(req.toJson()); + expectResponse( + conn, req.id); + + // This script has no source map, so it should not trigger a break + asyncRuntime.executeScriptAsync(R"( + storeValue(42); debugger; + //# sourceURL=http://example.com/source.js + )"); + expectNotification(conn); + + // Continue and verify that the JS code has now executed without first + // pausing on the script load. + expectNotification(conn); + EXPECT_EQ(asyncRuntime.awaitStoredValue().asNumber(), 42); + + // Resume and exit + send(conn, msgId++); + expectNotification(conn); +} + } // namespace chrome } // namespace inspector } // namespace hermes diff --git a/ReactCommon/hermes/inspector/tools/message_types.txt b/ReactCommon/hermes/inspector/tools/message_types.txt index 6d02ed4e754d6e..0db4a6b7709ce9 100644 --- a/ReactCommon/hermes/inspector/tools/message_types.txt +++ b/ReactCommon/hermes/inspector/tools/message_types.txt @@ -10,6 +10,7 @@ Debugger.resumed Debugger.scriptParsed Debugger.setBreakpoint Debugger.setBreakpointByUrl +Debugger.setInstrumentationBreakpoint Debugger.setPauseOnExceptions Debugger.stepInto Debugger.stepOut @@ -23,4 +24,3 @@ Runtime.consoleAPICalled Runtime.evaluate Runtime.executionContextCreated Runtime.getProperties -Hermes.setPauseOnLoad diff --git a/ReactCommon/jsi/jsi/jsi.cpp b/ReactCommon/jsi/jsi/jsi.cpp index 73a27892580cd4..388f122c178c9e 100644 --- a/ReactCommon/jsi/jsi/jsi.cpp +++ b/ReactCommon/jsi/jsi/jsi.cpp @@ -450,5 +450,11 @@ void JSError::setValue(Runtime& rt, Value&& value) { } } +JSIException::~JSIException() {} + +JSINativeException::~JSINativeException() {} + +JSError::~JSError() {} + } // namespace jsi } // namespace facebook diff --git a/ReactCommon/jsi/jsi/jsi.h b/ReactCommon/jsi/jsi/jsi.h index 677e9049498e18..e48f524a105b1d 100644 --- a/ReactCommon/jsi/jsi/jsi.h +++ b/ReactCommon/jsi/jsi/jsi.h @@ -1212,6 +1212,8 @@ class JSI_EXPORT JSIException : public std::exception { return what_.c_str(); } + virtual ~JSIException(); + protected: std::string what_; }; @@ -1221,6 +1223,8 @@ class JSI_EXPORT JSIException : public std::exception { class JSI_EXPORT JSINativeException : public JSIException { public: JSINativeException(std::string what) : JSIException(std::move(what)) {} + + virtual ~JSINativeException(); }; /// This exception will be thrown by API functions whenever a JS @@ -1249,6 +1253,8 @@ class JSI_EXPORT JSError : public JSIException { /// but necessary to avoid ambiguity with the above. JSError(std::string what, Runtime& rt, Value&& value); + virtual ~JSError(); + const std::string& getStack() const { return stack_; } diff --git a/ReactCommon/jsiexecutor/BUCK b/ReactCommon/jsiexecutor/BUCK index 5eeaf7638fa369..1edfe366a9ac7e 100644 --- a/ReactCommon/jsiexecutor/BUCK +++ b/ReactCommon/jsiexecutor/BUCK @@ -16,10 +16,11 @@ cxx_library( "-frtti", ], fbandroid_deps = [ + "//third-party/glog:glog", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", "//xplat/third-party/linker_lib:atomic", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_force_static = True, fbobjc_header_path_prefix = "", fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], diff --git a/ReactCommon/jsinspector/BUCK b/ReactCommon/jsinspector/BUCK index 18cb5aeaf394c9..22b569eabee601 100644 --- a/ReactCommon/jsinspector/BUCK +++ b/ReactCommon/jsinspector/BUCK @@ -30,6 +30,7 @@ rn_xplat_cxx_library( "-fexceptions", "-std=c++1y", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbandroid_preferred_linkage = "shared", fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], visibility = [ diff --git a/ReactCommon/microprofiler/BUCK b/ReactCommon/microprofiler/BUCK index 09cb9ae5053496..571b3cea525be1 100644 --- a/ReactCommon/microprofiler/BUCK +++ b/ReactCommon/microprofiler/BUCK @@ -16,6 +16,7 @@ cxx_library( "-fexceptions", "-fno-data-sections", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], force_static = True, visibility = [ diff --git a/ReactCommon/jscallinvoker/.clang-tidy b/ReactCommon/runtimeexecutor/.clang-tidy similarity index 100% rename from ReactCommon/jscallinvoker/.clang-tidy rename to ReactCommon/runtimeexecutor/.clang-tidy diff --git a/ReactCommon/runtimeexecutor/Android.mk b/ReactCommon/runtimeexecutor/Android.mk new file mode 100644 index 00000000000000..b22071ecdab708 --- /dev/null +++ b/ReactCommon/runtimeexecutor/Android.mk @@ -0,0 +1,19 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := runtimeexecutor + +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/ReactCommon/*.cpp) + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/ReactCommon +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) + +LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall + +include $(BUILD_STATIC_LIBRARY) diff --git a/ReactCommon/runtimeexecutor/BUCK b/ReactCommon/runtimeexecutor/BUCK new file mode 100644 index 00000000000000..561b4c8d208b49 --- /dev/null +++ b/ReactCommon/runtimeexecutor/BUCK @@ -0,0 +1,53 @@ +load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "get_preprocessor_flags_for_build_mode") +load( + "//tools/build_defs/oss:rn_defs.bzl", + "ANDROID", + "APPLE", + "CXX", + "get_apple_compiler_flags", + "get_apple_inspector_flags", + "rn_xplat_cxx_library", +) + +APPLE_COMPILER_FLAGS = get_apple_compiler_flags() + +rn_xplat_cxx_library( + name = "runtimeexecutor", + srcs = glob( + [ + "**/*.cpp", + "**/*.mm", + ], + exclude = glob(["tests/**/*.cpp"]), + ), + headers = glob( + ["**/*.h"], + exclude = glob(["tests/**/*.h"]), + ), + header_namespace = "", + exported_headers = { + "ReactCommon/RuntimeExecutor.h": "ReactCommon/RuntimeExecutor.h", + }, + compiler_flags = [ + "-fexceptions", + "-frtti", + "-std=c++14", + "-Wall", + ], + fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, + fbobjc_frameworks = ["Foundation"], + fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], + fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), + force_static = True, + macosx_tests_override = [], + platforms = (ANDROID, APPLE, CXX), + preprocessor_flags = [ + "-DLOG_TAG=\"ReactNative\"", + "-DWITH_FBSYSTRACE=1", + ], + tests = [], + visibility = ["PUBLIC"], + deps = [ + "//xplat/jsi:jsi", + ], +) diff --git a/ReactCommon/runtimeexecutor/React-runtimeexecutor.podspec b/ReactCommon/runtimeexecutor/React-runtimeexecutor.podspec new file mode 100644 index 00000000000000..83f57ab1f5ea09 --- /dev/null +++ b/ReactCommon/runtimeexecutor/React-runtimeexecutor.podspec @@ -0,0 +1,36 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +require "json" + +package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json"))) +version = package['version'] + +source = { :git => 'https://github.com/facebook/react-native.git' } +if version == '1000.0.0' + # This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in. + source[:commit] = `git rev-parse HEAD`.strip +else + source[:tag] = "v#{version}" +end + +folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' +folly_version = '2020.01.13.00' +boost_compiler_flags = '-Wno-documentation' + +Pod::Spec.new do |s| + s.name = "React-runtimeexecutor" + s.version = version + s.summary = "-" # TODO + s.homepage = "https://reactnative.dev/" + s.license = package["license"] + s.author = "Facebook, Inc. and its affiliates" + s.platforms = { :ios => "10.0", :tvos => "10.0", :osx => "10.14" } # TODO(macOS GH#214) + s.source = source + s.source_files = "**/*.{cpp,h}" + s.header_dir = "ReactCommon" + + s.dependency "React-jsi", version +end diff --git a/ReactCommon/utils/RuntimeExecutor.h b/ReactCommon/runtimeexecutor/ReactCommon/RuntimeExecutor.h similarity index 93% rename from ReactCommon/utils/RuntimeExecutor.h rename to ReactCommon/runtimeexecutor/ReactCommon/RuntimeExecutor.h index bdde3603e610f9..e01e2df41c1da8 100644 --- a/ReactCommon/utils/RuntimeExecutor.h +++ b/ReactCommon/runtimeexecutor/ReactCommon/RuntimeExecutor.h @@ -78,12 +78,10 @@ inline static void executeSynchronouslyOnSameThread_CAN_DEADLOCK( std::function &&callback) noexcept { // Note: We need the third mutex to get back to the main thread before // the lambda is finished (because all mutexes are allocated on the stack). - // We use `recursive_mutex` here to not deadlock in case if a - // `RuntimeExecutor` executes the callback synchronously. - std::recursive_mutex mutex1; - std::recursive_mutex mutex2; - std::recursive_mutex mutex3; + std::mutex mutex1; + std::mutex mutex2; + std::mutex mutex3; mutex1.lock(); mutex2.lock(); diff --git a/ReactCommon/turbomodule/core/BUCK b/ReactCommon/turbomodule/core/BUCK index f3389ae5ad9c14..af7350e7f2ccad 100644 --- a/ReactCommon/turbomodule/core/BUCK +++ b/ReactCommon/turbomodule/core/BUCK @@ -28,6 +28,7 @@ rn_xplat_cxx_library( ], prefix = "ReactCommon", ), + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbandroid_srcs = glob( [ "platform/android/**/*.cpp", @@ -70,12 +71,12 @@ rn_xplat_cxx_library( "PUBLIC", ], deps = [ + "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", "//xplat/jsi:JSIDynamic", - "//xplat/third-party/glog:glog", react_native_xplat_target("cxxreact:bridge"), react_native_xplat_target("cxxreact:module"), react_native_xplat_target("callinvoker:callinvoker"), diff --git a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm b/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm index f5a12a6dce6b26..f6179e0d344995 100644 --- a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm +++ b/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm @@ -321,12 +321,22 @@ - (void)notifyAboutTurboModuleSetup:(const char *)name */ - (id)provideRCTTurboModule:(const char *)moduleName { - TurboModuleHolder *moduleHolder = [self _getOrCreateTurboModuleHolder:moduleName]; + TurboModuleHolder *moduleHolder; - if (!moduleHolder) { - return nil; + { + std::lock_guard guard(_turboModuleHoldersMutex); + if (_invalidating) { + return nil; + } + + moduleHolder = &_turboModuleHolders[moduleName]; } + return [self _provideRCTTurboModule:moduleName moduleHolder:moduleHolder]; +} + +- (id)_provideRCTTurboModule:(const char *)moduleName moduleHolder:(TurboModuleHolder *)moduleHolder +{ bool shouldCreateModule = false; { @@ -565,20 +575,6 @@ - (void)notifyAboutTurboModuleSetup:(const char *)name return module; } -/** - * Return a pointer to this TurboModule's TurboModuleHolder entry, creating one if it doesn't exist. - * Return nullptr if we've started teardown of TurboModuleManager. - */ -- (TurboModuleHolder *)_getOrCreateTurboModuleHolder:(const char *)moduleName -{ - std::lock_guard guard(_turboModuleHoldersMutex); - if (_invalidating) { - return nullptr; - } - - return &_turboModuleHolders[moduleName]; -} - /** * Should this TurboModule be created and initialized on the main queue? * @@ -732,15 +728,16 @@ - (void)bridgeDidInvalidateModules:(NSNotification *)notification // Backward-compatibility: RCTInvalidating handling. dispatch_group_t moduleInvalidationGroup = dispatch_group_create(); - for (const auto &pair : _turboModuleHolders) { + for (auto &pair : _turboModuleHolders) { std::string moduleName = pair.first; + TurboModuleHolder *moduleHolder = &pair.second; /** * We could start tearing down ReactNative before a TurboModule is fully initialized. In this case, we should wait - * for init to finish before we call invalidate on the module. Therefore, we call provideRCTTurboModule (because - * it's guaranteed to return a fully initialized NativeModule). + * for TurboModule init to finish before calling invalidate on it. So, we call _provideRCTTurboModule:moduleHolder, + * because it's guaranteed to return a fully initialized NativeModule. */ - id module = [self provideRCTTurboModule:moduleName.c_str()]; + id module = [self _provideRCTTurboModule:moduleName.c_str() moduleHolder:moduleHolder]; if ([module respondsToSelector:@selector(invalidate)]) { if ([module respondsToSelector:@selector(methodQueue)]) { diff --git a/ReactCommon/turbomodule/samples/BUCK b/ReactCommon/turbomodule/samples/BUCK index 1948f743955733..44173730827899 100644 --- a/ReactCommon/turbomodule/samples/BUCK +++ b/ReactCommon/turbomodule/samples/BUCK @@ -26,6 +26,7 @@ rn_xplat_cxx_library( ], prefix = "ReactCommon", ), + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbandroid_srcs = glob( [ "platform/android/**/*.cpp", @@ -36,6 +37,7 @@ rn_xplat_cxx_library( "-fobjc-arc-exceptions", ], fbobjc_inherited_buck_flags = get_static_library_ios_flags(), + fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], fbobjc_preprocessor_flags = OBJC_ARC_PREPROCESSOR_FLAGS + get_preprocessor_flags_for_build_mode(), force_static = True, ios_deps = [ diff --git a/ReactCommon/turbomodule/samples/SampleTurboCxxModule.cpp b/ReactCommon/turbomodule/samples/SampleTurboCxxModule.cpp index b970b2b72623d6..5d56c59d7ece20 100644 --- a/ReactCommon/turbomodule/samples/SampleTurboCxxModule.cpp +++ b/ReactCommon/turbomodule/samples/SampleTurboCxxModule.cpp @@ -5,9 +5,9 @@ * LICENSE file in the root directory of this source tree. */ -#import "SampleTurboCxxModule.h" +#include "SampleTurboCxxModule.h" -#import +#include using namespace facebook; diff --git a/ReactCommon/turbomodule/samples/SampleTurboCxxModule.h b/ReactCommon/turbomodule/samples/SampleTurboCxxModule.h index 7f1bd07bb1a789..c1ebb682362c64 100644 --- a/ReactCommon/turbomodule/samples/SampleTurboCxxModule.h +++ b/ReactCommon/turbomodule/samples/SampleTurboCxxModule.h @@ -7,9 +7,9 @@ #pragma once -#import +#include -#import "NativeSampleTurboCxxModuleSpecJSI.h" +#include "NativeSampleTurboCxxModuleSpecJSI.h" namespace facebook { namespace react { diff --git a/ReactCommon/utils/BUCK b/ReactCommon/utils/BUCK index dfcc229b285c5d..c9660e082d7157 100644 --- a/ReactCommon/utils/BUCK +++ b/ReactCommon/utils/BUCK @@ -39,6 +39,7 @@ rn_xplat_cxx_library( "-std=c++14", "-Wall", ], + fbandroid_labels = ["supermodule:android/default/public.react_native.infra"], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_frameworks = ["Foundation"], fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"], diff --git a/ReactCommon/utils/RunLoopObserver.cpp b/ReactCommon/utils/RunLoopObserver.cpp new file mode 100644 index 00000000000000..bca81b6664d7b5 --- /dev/null +++ b/ReactCommon/utils/RunLoopObserver.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "RunLoopObserver.h" + +#include + +namespace facebook { +namespace react { + +RunLoopObserver::RunLoopObserver( + Activity activities, + WeakOwner const &owner) noexcept + : activities_(activities), owner_(owner) {} + +void RunLoopObserver::setDelegate(Delegate const *delegate) const noexcept { + // We need these constraints to ensure basic thread-safety. + assert(delegate && "A delegate must not be `nullptr`."); + assert(!delegate_ && "`RunLoopObserver::setDelegate` must be called once."); + delegate_ = delegate; +} + +void RunLoopObserver::enable() const noexcept { + if (enabled_) { + return; + } + enabled_ = true; + + startObserving(); +} + +void RunLoopObserver::disable() const noexcept { + if (!enabled_) { + return; + } + enabled_ = false; + + stopObserving(); +} + +void RunLoopObserver::activityDidChange(Activity activity) const noexcept { + if (!enabled_) { + return; + } + + assert( + !owner_.expired() && + "`owner_` is null. The caller must `lock` the owner and check it for being not null."); + + delegate_->activityDidChange(delegate_, activity); +} + +RunLoopObserver::WeakOwner RunLoopObserver::getOwner() const noexcept { + return owner_; +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/utils/RunLoopObserver.h b/ReactCommon/utils/RunLoopObserver.h new file mode 100644 index 00000000000000..5bd7bd7a4c84c8 --- /dev/null +++ b/ReactCommon/utils/RunLoopObserver.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include + +namespace facebook { +namespace react { + +/* + * A cross-platform abstraction for observing a run loop life cycle. + */ +class RunLoopObserver { + public: + using Unique = std::unique_ptr; + + /* + * The concept of an owner. + * A run loop observer normally observes a run loop running on a different + * thread. That implies that this other thread (the run loop thread) will call + * methods of this class owned by some other thread. To make it safe, we need + * to ensure that at the moment of the calling the observer still exists. To + * do so, we use an owner object (a weak pointer) that must retain (possibly + * indirectly) the observer. The platform-specific code should convert the + * weak pointer (owner) to a strong one right before calling the observer, + * ensuring the safety of calling; right after the call, the strong pointer + * should be safely released. + * + * Note, in the case when the pointer to the actual owner will be available + * later, only after calling the constructor of the class, the caller can + * create a dummy pointer beforehand and then merge it (using + * `shared_ptr(shared_ptr const &, X *)`) with the actual one (sharing + * the control block). + */ + using Owner = std::shared_ptr; + using WeakOwner = std::weak_ptr; + + /* + * Run loop activity stages which run loop observers can be observe. + */ + enum Activity : int32_t { + None = 0, + BeforeWaiting = 1 << 0, + AfterWaiting = 1 << 1, + }; + + /* + * A delegate interface. + */ + class Delegate { + public: + /* + * Called on every run loop tick at moments corresponding to requested + * activities. + * + * A platform-specific implementation guarantees that the owner pointer + * is retained during this call. + * Will be called on the thread associated with the run loop. + */ + virtual void activityDidChange(Delegate const *delegate, Activity activity) + const noexcept = 0; + + virtual ~Delegate() noexcept = default; + }; + + using Factory = std::function( + Activity activities, + WeakOwner const &owner)>; + + /* + * Constructs a run loop observer. + */ + RunLoopObserver(Activity activities, WeakOwner const &owner) noexcept; + virtual ~RunLoopObserver() noexcept = default; + + /* + * Sets the delegate. + * Must be called just once. + */ + void setDelegate(Delegate const *delegate) const noexcept; + + /* + * Enables or disables run loop observing. + * It can be used to save CPU cycles during periods of time when observing + * is not required. + * A newly constructed run time observer is initially disabled. + */ + void enable() const noexcept; + void disable() const noexcept; + + /* + * Returns true if called on a thread associated with the run loop. + * Must be implemented in subclasses. + */ + virtual bool isOnRunLoopThread() const noexcept = 0; + + /* + * Returns an owner associated with the observer. + * It might be useful to ensure the safety of consequent asynchronous calls. + */ + WeakOwner getOwner() const noexcept; + + protected: + /* + * Must be implemented in subclasses. + */ + virtual void startObserving() const noexcept = 0; + virtual void stopObserving() const noexcept = 0; + + /* + * Called by subclasses to generate a call on a delegate. + */ + void activityDidChange(Activity activity) const noexcept; + + Activity const activities_{}; + WeakOwner const owner_; + mutable Delegate const *delegate_{nullptr}; + mutable std::atomic enabled_{false}; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index bb7da7bfd91d88..c2a5c286f99580 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -3664,8 +3664,8 @@ static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid( } YOGA_EXPORT float YGRoundValueToPixelGrid( - const float value, - const float pointScaleFactor, + const double value, + const double pointScaleFactor, const bool forceCeil, const bool forceFloor) { double scaledValue = ((double) value) * pointScaleFactor; @@ -4081,24 +4081,24 @@ YOGA_EXPORT void YGConfigSetPointScaleFactor( static void YGRoundToPixelGrid( const YGNodeRef node, - const float pointScaleFactor, - const float absoluteLeft, - const float absoluteTop) { + const double pointScaleFactor, + const double absoluteLeft, + const double absoluteTop) { if (pointScaleFactor == 0.0f) { return; } - const float nodeLeft = node->getLayout().position[YGEdgeLeft]; - const float nodeTop = node->getLayout().position[YGEdgeTop]; + const double nodeLeft = node->getLayout().position[YGEdgeLeft]; + const double nodeTop = node->getLayout().position[YGEdgeTop]; - const float nodeWidth = node->getLayout().dimensions[YGDimensionWidth]; - const float nodeHeight = node->getLayout().dimensions[YGDimensionHeight]; + const double nodeWidth = node->getLayout().dimensions[YGDimensionWidth]; + const double nodeHeight = node->getLayout().dimensions[YGDimensionHeight]; - const float absoluteNodeLeft = absoluteLeft + nodeLeft; - const float absoluteNodeTop = absoluteTop + nodeTop; + const double absoluteNodeLeft = absoluteLeft + nodeLeft; + const double absoluteNodeTop = absoluteTop + nodeTop; - const float absoluteNodeRight = absoluteNodeLeft + nodeWidth; - const float absoluteNodeBottom = absoluteNodeTop + nodeHeight; + const double absoluteNodeRight = absoluteNodeLeft + nodeWidth; + const double absoluteNodeBottom = absoluteNodeTop + nodeHeight; // If a node has a custom measure function we never want to round down its // size as this could lead to unwanted text truncation. diff --git a/ReactCommon/yoga/yoga/Yoga.h b/ReactCommon/yoga/yoga/Yoga.h index 2fe60a4170da3e..87901a280ee84a 100644 --- a/ReactCommon/yoga/yoga/Yoga.h +++ b/ReactCommon/yoga/yoga/Yoga.h @@ -352,8 +352,8 @@ WIN_EXPORT void YGConfigSetContext(YGConfigRef config, void* context); WIN_EXPORT void* YGConfigGetContext(YGConfigRef config); WIN_EXPORT float YGRoundValueToPixelGrid( - float value, - float pointScaleFactor, + double value, + double pointScaleFactor, bool forceCeil, bool forceFloor); diff --git a/package.json b/package.json index dcaa7c5a44094b..96b394ccb04919 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "metro-react-native-babel-transformer": "0.59.0", "metro-source-map": "0.59.0", "nullthrows": "^1.1.1", - "pretty-format": "^25.4.0", + "pretty-format": "^26.0.1", "promise": "^8.0.3", "prop-types": "^15.7.2", "react-devtools-core": "^4.6.0", @@ -142,13 +142,13 @@ "eslint-plugin-react": "7.12.4", "eslint-plugin-react-hooks": "^3.0.0", "eslint-plugin-react-native": "3.8.1", - "eslint-plugin-relay": "1.7.0", - "flow-bin": "^0.123.0", + "eslint-plugin-relay": "1.7.1", + "flow-bin": "^0.124.0", "flow-remove-types": "1.2.3", "hermes-engine-darwin": "~0.5.0", - "jest": "^25.4.0", + "jest": "^26.0.1", "jest-junit": "^10.0.0", - "jscodeshift": "^0.7.0", + "jscodeshift": "^0.9.0", "mkdirp": "^0.5.1", "prettier": "1.19.1", "react": "16.13.1", @@ -156,7 +156,7 @@ "shelljs": "^0.7.8", "signedsource": "^1.0.0", "ws": "^6.1.4", - "yargs": "^14.2.0" + "yargs": "^15.3.1" }, "detox": { "test-runner": "jest", diff --git a/packages/react-native-codegen/.babelrc b/packages/react-native-codegen/.babelrc new file mode 100644 index 00000000000000..b8ac81899b77e0 --- /dev/null +++ b/packages/react-native-codegen/.babelrc @@ -0,0 +1,11 @@ +{ + "plugins": [ + "@babel/plugin-proposal-object-rest-spread", + "@babel/plugin-transform-async-to-generator", + "@babel/plugin-transform-destructuring", + "@babel/plugin-transform-flow-strip-types", + "@babel/plugin-syntax-dynamic-import", + "@babel/plugin-proposal-nullish-coalescing-operator", + "@babel/plugin-proposal-optional-chaining" + ] +} diff --git a/packages/react-native-codegen/.prettierrc b/packages/react-native-codegen/.prettierrc new file mode 100644 index 00000000000000..20374fd919f060 --- /dev/null +++ b/packages/react-native-codegen/.prettierrc @@ -0,0 +1,7 @@ +{ + "requirePragma": true, + "singleQuote": true, + "trailingComma": "all", + "bracketSpacing": false, + "jsxBracketSameLine": true +} diff --git a/packages/react-native-codegen/DEFS.bzl b/packages/react-native-codegen/DEFS.bzl index 9099034da04ca9..f54615a0494941 100644 --- a/packages/react-native-codegen/DEFS.bzl +++ b/packages/react-native-codegen/DEFS.bzl @@ -231,7 +231,7 @@ def rn_codegen_components( "//xplat/folly:headers_only", "//xplat/folly:memory", "//xplat/folly:molly", - "//xplat/third-party/glog:glog", + "//third-party/glog:glog", YOGA_CXX_TARGET, react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("fabric/core:core"), diff --git a/packages/react-native-codegen/package.json b/packages/react-native-codegen/package.json index 88d16e5f278f64..59168f8f95a1a9 100644 --- a/packages/react-native-codegen/package.json +++ b/packages/react-native-codegen/package.json @@ -7,16 +7,36 @@ "type": "git", "url": "git@github.com:facebook/react-native.git" }, + "scripts": { + "build": "yarn clean && node scripts/build.js --verbose", + "clean": "rm -rf lib", + "prepublish": "yarn run build" + }, "license": "MIT", "files": [ - "src" + "lib" ], "dependencies": { "flow-parser": "^0.121.0", - "jscodeshift": "^0.7.0", + "jscodeshift": "^0.9.0", "nullthrows": "^1.1.1" }, "beachball": { "shouldPublish": false - } + }, + "devDependencies": { + "@babel/core": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.0.0", + "@babel/plugin-transform-async-to-generator": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "chalk": "^4.0.0", + "glob": "^7.1.1", + "micromatch": "^4.0.2", + "mkdirp": "^0.5.1", + "prettier": "1.19.1" + } } diff --git a/packages/react-native-codegen/scripts/build.js b/packages/react-native-codegen/scripts/build.js new file mode 100644 index 00000000000000..9eefd4fdbb8f98 --- /dev/null +++ b/packages/react-native-codegen/scripts/build.js @@ -0,0 +1,117 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +/** + * script to build (transpile) files. + * + * Based off of the build script from Metro, and tweaked to run in just one + * package instead of in a monorepo. Just run `build.js` and the JS files in + * `src/` will be built in `lib/`, and the original source files will be copied + * over as `Example.js.flow`, so consumers of this module can still make use of + * type checking. + * + * Call this script with the `--verbose` flag to show the full output of this + * script. + */ + +'use strict'; + +const babel = require('@babel/core'); +const chalk = require('chalk'); +const fs = require('fs'); +const glob = require('glob'); +const micromatch = require('micromatch'); +const mkdirp = require('mkdirp'); +const path = require('path'); +const prettier = require('prettier'); +const prettierConfig = JSON.parse( + fs.readFileSync(path.resolve(__dirname, '..', '.prettierrc'), 'utf8'), +); + +const SRC_DIR = 'src'; +const BUILD_DIR = 'lib'; +const JS_FILES_PATTERN = '**/*.js'; +const IGNORE_PATTERN = '**/__tests__/**'; +const PACKAGE_DIR = path.resolve(__dirname, '../'); + +const fixedWidth = str => { + const WIDTH = 80; + const strs = str.match(new RegExp(`(.{1,${WIDTH}})`, 'g')) || [str]; + let lastString = strs[strs.length - 1]; + if (lastString.length < WIDTH) { + lastString += Array(WIDTH - lastString.length).join(chalk.dim('.')); + } + return strs + .slice(0, -1) + .concat(lastString) + .join('\n'); +}; + +function getBuildPath(file, buildFolder) { + const pkgSrcPath = path.resolve(PACKAGE_DIR, SRC_DIR); + const pkgBuildPath = path.resolve(PACKAGE_DIR, BUILD_DIR); + const relativeToSrcPath = path.relative(pkgSrcPath, file); + return path.resolve(pkgBuildPath, relativeToSrcPath); +} + +function buildFile(file, silent) { + const destPath = getBuildPath(file, BUILD_DIR); + + mkdirp.sync(path.dirname(destPath)); + if (micromatch.isMatch(file, IGNORE_PATTERN)) { + silent || + process.stdout.write( + chalk.dim(' \u2022 ') + + path.relative(PACKAGE_DIR, file) + + ' (ignore)\n', + ); + } else if (!micromatch.isMatch(file, JS_FILES_PATTERN)) { + fs.createReadStream(file).pipe(fs.createWriteStream(destPath)); + silent || + process.stdout.write( + chalk.red(' \u2022 ') + + path.relative(PACKAGE_DIR, file) + + chalk.red(' \u21D2 ') + + path.relative(PACKAGE_DIR, destPath) + + ' (copy)' + + '\n', + ); + } else { + const transformed = prettier.format( + babel.transformFileSync(file, {}).code, + { + ...prettierConfig, + parser: 'babel', + }, + ); + fs.writeFileSync(destPath, transformed); + const source = fs.readFileSync(file).toString('utf-8'); + if (/\@flow/.test(source)) { + fs.createReadStream(file).pipe(fs.createWriteStream(destPath + '.flow')); + } + silent || + process.stdout.write( + chalk.green(' \u2022 ') + + path.relative(PACKAGE_DIR, file) + + chalk.green(' \u21D2 ') + + path.relative(PACKAGE_DIR, destPath) + + '\n', + ); + } +} + +const srcDir = path.resolve(__dirname, '..', SRC_DIR); +const pattern = path.resolve(srcDir, '**/*'); +const files = glob.sync(pattern, {nodir: true}); + +process.stdout.write(fixedWidth(`${path.basename(PACKAGE_DIR)}\n`)); + +files.forEach(file => buildFile(file, !process.argv.includes('--verbose'))); + +process.stdout.write(`[ ${chalk.green('OK')} ]\n`); diff --git a/packages/react-native-codegen/src/CodegenSchema.js b/packages/react-native-codegen/src/CodegenSchema.js index 51d96416ff772e..17fb0d7df9c09d 100644 --- a/packages/react-native-codegen/src/CodegenSchema.js +++ b/packages/react-native-codegen/src/CodegenSchema.js @@ -10,6 +10,8 @@ 'use strict'; +export type PlatformType = 'iOS' | 'android'; + export type CommandsFunctionTypeAnnotation = $ReadOnly<{| type: 'FunctionTypeAnnotation', params: $ReadOnlyArray, @@ -309,8 +311,8 @@ export type OptionsShape = $ReadOnly<{| // Does not check for new name paperComponentName?: string, - // Use for components that are not used on one or the other platform. - excludedPlatform?: 'iOS' | 'android', + // Use for components that are not used on other platforms. + excludedPlatforms?: $ReadOnlyArray, // Use for components currently being renamed in paper // Will use new name if it is available and fallback to this name diff --git a/packages/react-native-codegen/src/generators/components/GenerateComponentHObjCpp.js b/packages/react-native-codegen/src/generators/components/GenerateComponentHObjCpp.js index 6ecc358b3815f4..af61b2675e78a6 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateComponentHObjCpp.js +++ b/packages/react-native-codegen/src/generators/components/GenerateComponentHObjCpp.js @@ -337,7 +337,10 @@ module.exports = { return Object.keys(components) .filter(componentName => { const component = components[componentName]; - return component.excludedPlatform !== 'iOS'; + return !( + component.excludedPlatforms && + component.excludedPlatforms.includes('iOS') + ); }) .map(componentName => { return [ diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsCpp.js b/packages/react-native-codegen/src/generators/components/GeneratePropsCpp.js index 0cfe41fa8c66ef..b6b03eb7d36979 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsCpp.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsCpp.js @@ -101,7 +101,10 @@ module.exports = { return Object.keys(components) .filter(componentName => { const component = components[componentName]; - return component.excludedPlatform !== 'iOS'; + return !( + component.excludedPlatforms && + component.excludedPlatforms.includes('iOS') + ); }) .map(componentName => { const component = components[componentName]; diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsH.js b/packages/react-native-codegen/src/generators/components/GeneratePropsH.js index adb94d16f442f4..a7ff3f9d77cda8 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsH.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsH.js @@ -768,7 +768,10 @@ module.exports = { return Object.keys(components) .filter(componentName => { const component = components[componentName]; - return component.excludedPlatform !== 'iOS'; + return !( + component.excludedPlatforms && + component.excludedPlatforms.includes('iOS') + ); }) .map(componentName => { const component = components[componentName]; diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js index 17f587b0145327..08c99a48791373 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js @@ -274,7 +274,10 @@ module.exports = { return Object.keys(components) .filter(componentName => { const component = components[componentName]; - return component.excludedPlatform !== 'android'; + return !( + component.excludedPlatforms && + component.excludedPlatforms.includes('android') + ); }) .forEach(componentName => { const component = components[componentName]; diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js index bf4f42bbfc891d..af41763c82c0e5 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js @@ -221,7 +221,10 @@ module.exports = { return Object.keys(components) .filter(componentName => { const component = components[componentName]; - return component.excludedPlatform !== 'android'; + return !( + component.excludedPlatforms && + component.excludedPlatforms.includes('android') + ); }) .forEach(componentName => { const component = components[componentName]; diff --git a/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js index 6f3bf1becb890d..31689b483dcaed 100644 --- a/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js @@ -1524,7 +1524,28 @@ const EXCLUDE_ANDROID: SchemaType = { ExcludedAndroid: { components: { ExcludedAndroidComponent: { - excludedPlatform: 'android', + excludedPlatforms: ['android'], + extendsProps: [ + { + type: 'ReactNativeBuiltInType', + knownTypeName: 'ReactNativeCoreViewProps', + }, + ], + events: [], + props: [], + commands: [], + }, + }, + }, + }, +}; + +const EXCLUDE_ANDROID_IOS: SchemaType = { + modules: { + ExcludedAndroidIos: { + components: { + ExcludedAndroidIosComponent: { + excludedPlatforms: ['android', 'iOS'], extendsProps: [ { type: 'ReactNativeBuiltInType', @@ -1566,4 +1587,5 @@ module.exports = { COMMANDS, COMMANDS_AND_PROPS, EXCLUDE_ANDROID, + EXCLUDE_ANDROID_IOS, }; diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateComponentDescriptorH-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateComponentDescriptorH-test.js.snap index 4c64141b0fbb36..e23ae48953f9ea 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateComponentDescriptorH-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateComponentDescriptorH-test.js.snap @@ -286,6 +286,32 @@ using ExcludedAndroidComponentComponentDescriptor = ConcreteComponentDescriptor< } `; +exports[`GenerateComponentDescriptorH can generate fixture EXCLUDE_ANDROID_IOS 1`] = ` +Map { + "ComponentDescriptors.h" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +namespace facebook { +namespace react { + +using ExcludedAndroidIosComponentComponentDescriptor = ConcreteComponentDescriptor; + +} // namespace react +} // namespace facebook +", +} +`; + exports[`GenerateComponentDescriptorH can generate fixture FLOAT_PROPS 1`] = ` Map { "ComponentDescriptors.h" => " diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateComponentHObjCpp-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateComponentHObjCpp-test.js.snap index 93b0a8b7f0ffe8..a921411cbe03a4 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateComponentHObjCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateComponentHObjCpp-test.js.snap @@ -385,6 +385,27 @@ NS_ASSUME_NONNULL_BEGIN @end +NS_ASSUME_NONNULL_END", +} +`; + +exports[`GenerateComponentHObjCpp can generate fixture EXCLUDE_ANDROID_IOS 1`] = ` +Map { + "RCTComponentViewHelpers.h" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + + + NS_ASSUME_NONNULL_END", } `; diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap index a13aedb1303c47..c70dc86ce28188 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap @@ -304,6 +304,29 @@ namespace react { +} // namespace react +} // namespace facebook +", +} +`; + +exports[`GenerateEventEmitterCpp can generate fixture EXCLUDE_ANDROID_IOS 1`] = ` +Map { + "EventEmitters.cpp" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +namespace facebook { +namespace react { + + + } // namespace react } // namespace facebook ", diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap index 6b0076238052ea..229c08c3f15b42 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap @@ -330,6 +330,30 @@ namespace react { +} // namespace react +} // namespace facebook +", +} +`; + +exports[`GenerateEventEmitterH can generate fixture EXCLUDE_ANDROID_IOS 1`] = ` +Map { + "EventEmitters.h" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +#pragma once + +#include + +namespace facebook { +namespace react { + + + } // namespace react } // namespace facebook ", diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsCpp-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsCpp-test.js.snap index 2d17c7496dc886..27ce7d45df9925 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsCpp-test.js.snap @@ -329,6 +329,30 @@ ExcludedAndroidComponentProps::ExcludedAndroidComponentProps( {} +} // namespace react +} // namespace facebook +", +} +`; + +exports[`GeneratePropsCpp can generate fixture EXCLUDE_ANDROID_IOS 1`] = ` +Map { + "Props.cpp" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include + +namespace facebook { +namespace react { + + + } // namespace react } // namespace facebook ", diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsH-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsH-test.js.snap index 687290a402e574..3071e0e70ed107 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsH-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsH-test.js.snap @@ -574,6 +574,30 @@ class ExcludedAndroidComponentProps final : public ViewProps { }; +} // namespace react +} // namespace facebook +", +} +`; + +exports[`GeneratePropsH can generate fixture EXCLUDE_ANDROID_IOS 1`] = ` +Map { + "Props.h" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +#pragma once + + + +namespace facebook { +namespace react { + + + } // namespace react } // namespace facebook ", diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap index 6ae0cd6f4f22c8..914f8e56da71a9 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap @@ -442,6 +442,8 @@ public class InterfaceOnlyComponentManagerDelegate "/** diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaInterface-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaInterface-test.js.snap index 45873d75b224bc..b064446f35b63a 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaInterface-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaInterface-test.js.snap @@ -247,6 +247,8 @@ public interface InterfaceOnlyComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture EXCLUDE_ANDROID 1`] = `Map {}`; +exports[`GeneratePropsJavaInterface can generate fixture EXCLUDE_ANDROID_IOS 1`] = `Map {}`; + exports[`GeneratePropsJavaInterface can generate fixture FLOAT_PROPS 1`] = ` Map { "FloatPropNativeComponentManagerInterface.java" => "/** diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeCpp-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeCpp-test.js.snap index 053638bd5b0b0e..22043570482540 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeCpp-test.js.snap @@ -253,6 +253,29 @@ extern const char ExcludedAndroidComponentComponentName[] = \\"ExcludedAndroidCo } `; +exports[`GenerateShadowNodeCpp can generate fixture EXCLUDE_ANDROID_IOS 1`] = ` +Map { + "ShadowNodes.cpp" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +namespace facebook { +namespace react { + +extern const char ExcludedAndroidIosComponentComponentName[] = \\"ExcludedAndroidIosComponent\\"; + +} // namespace react +} // namespace facebook +", +} +`; + exports[`GenerateShadowNodeCpp can generate fixture FLOAT_PROPS 1`] = ` Map { "ShadowNodes.cpp" => " diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeH-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeH-test.js.snap index 679337e818c9bc..5327702796da7c 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeH-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeH-test.js.snap @@ -360,6 +360,39 @@ using ExcludedAndroidComponentShadowNode = ConcreteViewShadowNode< } `; +exports[`GenerateShadowNodeH can generate fixture EXCLUDE_ANDROID_IOS 1`] = ` +Map { + "ShadowNodes.h" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +namespace facebook { +namespace react { + +extern const char ExcludedAndroidIosComponentComponentName[]; + +/* + * \`ShadowNode\` for component. + */ +using ExcludedAndroidIosComponentShadowNode = ConcreteViewShadowNode< + ExcludedAndroidIosComponentComponentName, + ExcludedAndroidIosComponentProps>; + +} // namespace react +} // namespace facebook +", +} +`; + exports[`GenerateShadowNodeH can generate fixture FLOAT_PROPS 1`] = ` Map { "ShadowNodes.h" => " diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateTests-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateTests-test.js.snap index 63141765868042..8f73a0c825023a 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateTests-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateTests-test.js.snap @@ -354,6 +354,34 @@ TEST(ExcludedAndroidComponentProps_DoesNotDie, etc) { } `; +exports[`GenerateTests can generate fixture EXCLUDE_ANDROID_IOS 1`] = ` +Map { + "Tests.cpp" => "/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include +#include +#include +#include + +using namespace facebook::react; + +TEST(ExcludedAndroidIosComponentProps_DoesNotDie, etc) { + auto propParser = RawPropsParser(); + propParser.prepare(); + auto const &sourceProps = ExcludedAndroidIosComponentProps(); + auto const &rawProps = RawProps(folly::dynamic::object(\\"xx_invalid_xx\\", \\"xx_invalid_xx\\")); + rawProps.parse(propParser); + ExcludedAndroidIosComponentProps(sourceProps, rawProps); +}", +} +`; + exports[`GenerateTests can generate fixture FLOAT_PROPS 1`] = ` Map { "Tests.cpp" => "/** diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap index f7e1722e545a8e..d92c6470d7cfe8 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap @@ -483,6 +483,38 @@ export default nativeComponentName; } `; +exports[`GenerateViewConfigJs can generate fixture EXCLUDE_ANDROID_IOS 1`] = ` +Map { + "EXCLUDE_ANDROID_IOSNativeViewConfig.js" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +'use strict'; + +const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); + +const ExcludedAndroidIosComponentViewConfig = { + uiViewClassName: 'ExcludedAndroidIosComponent', + validAttributes: {}, +}; + +let nativeComponentName = 'ExcludedAndroidIosComponent'; + +registerGeneratedViewConfig(nativeComponentName, ExcludedAndroidIosComponentViewConfig); + +export const __INTERNAL_VIEW_CONFIG = ExcludedAndroidIosComponentViewConfig; + +export default nativeComponentName; +", +} +`; + exports[`GenerateViewConfigJs can generate fixture FLOAT_PROPS 1`] = ` Map { "FLOAT_PROPSNativeViewConfig.js" => " diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleHObjCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleHObjCpp.js index 87e9367bae09dd..474927f779940e 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleHObjCpp.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleHObjCpp.js @@ -24,14 +24,15 @@ const { type FilesOutput = Map; -const moduleTemplate = ` -class JSI_EXPORT Native::_MODULE_NAME_::SpecJSI : public ObjCTurboModule { -public: - Native::_MODULE_NAME_::SpecJSI(const ObjCTurboModule::InitParams ¶ms); -};`; +const moduleTemplate = ` /** + * ObjC++ class for module '::_MODULE_NAME_::' + */ + class JSI_EXPORT Native::_MODULE_NAME_::SpecJSI : public ObjCTurboModule { + public: + Native::_MODULE_NAME_::SpecJSI(const ObjCTurboModule::InitParams ¶ms); + };`; -const protocolTemplate = ` -::_STRUCTS_:: +const protocolTemplate = `::_STRUCTS_:: @protocol Native::_MODULE_NAME_::Spec ::_MODULE_PROPERTIES_:: @@ -53,30 +54,36 @@ const template = ` * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * ${'@'}generated by codegen project: GenerateModuleHObjCpp.js */ -// NOTE: This entire file should be codegen'ed. +#ifndef __cplusplus +#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. +#endif #import #import -#import +#import -#import #import +#import #import + +#import #import #import -#import + +#import ::_PROTOCOLS_:: namespace facebook { -namespace react { + namespace react { ::_MODULES_:: - -} // namespace react + } // namespace react } // namespace facebook `; @@ -184,6 +191,7 @@ module.exports = { moduleSpecName: string, ): FilesOutput { const nativeModules = Object.keys(schema.modules) + .sort() .map(moduleName => { const modules = schema.modules[moduleName].nativeModules; if (modules == null) { @@ -200,6 +208,7 @@ module.exports = { .join('\n'); const protocols = Object.keys(nativeModules) + .sort() .map(name => { const objectForGeneratingStructs: Array = []; const {properties} = nativeModules[name]; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleMm.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleMm.js index a0807282399c0f..448541cd995e96 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleMm.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleMm.js @@ -18,38 +18,38 @@ const {flatObjects} = require('./ObjCppUtils/Utils'); type FilesOutput = Map; const propertyHeaderTemplate = - 'static facebook::jsi::Value __hostFunction_Native::_MODULE_NAME_::SpecJSI_::_PROPERTY_NAME_::(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {'; + ' static facebook::jsi::Value __hostFunction_Native::_MODULE_NAME_::SpecJSI_::_PROPERTY_NAME_::(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {'; const propertyCastTemplate = `static_cast(turboModule) .invokeObjCMethod(rt, ::_KIND_::, "::_PROPERTY_NAME_::", @selector(::_PROPERTY_NAME_::::_ARGS_::), args, count);`; const propertyTemplate = ` ${propertyHeaderTemplate} - return ${propertyCastTemplate} -}`.trim(); + return ${propertyCastTemplate} + }`; -const proprertyDefTemplate = - ' methodMap_["::_PROPERTY_NAME_::"] = MethodMetadata {::_ARGS_COUNT_::, __hostFunction_Native::_MODULE_NAME_::SpecJSI_::_PROPERTY_NAME_::};'; +const propertyDefTemplate = + ' methodMap_["::_PROPERTY_NAME_::"] = MethodMetadata {::_ARGS_COUNT_::, __hostFunction_Native::_MODULE_NAME_::SpecJSI_::_PROPERTY_NAME_::};'; const moduleTemplate = ` -::_TURBOMODULE_METHOD_INVOKERS_:: + ::_TURBOMODULE_METHOD_INVOKERS_:: -Native::_MODULE_NAME_::SpecJSI::Native::_MODULE_NAME_::SpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { -::_PROPERTIES_MAP_::::_CONVERSION_SELECTORS_:: -}`.trim(); + Native::_MODULE_NAME_::SpecJSI::Native::_MODULE_NAME_::SpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + ::_PROPERTIES_MAP_::::_CONVERSION_SELECTORS_:: + }`.trim(); const getterTemplate = ` - @implementation RCTCxxConvert (Native::_MODULE_NAME_::_Spec::_GETTER_NAME_::) +@implementation RCTCxxConvert (Native::_MODULE_NAME_::_Spec::_GETTER_NAME_::) + (RCTManagedPointer *)JS_Native::_MODULE_NAME_::_Spec::_GETTER_NAME_:::(id)json { return facebook::react::managedPointer(json); } @end -`.trim(); +`; const argConvertionTemplate = - '\n setMethodArgConversionSelector(@"::_ARG_NAME_::", ::_ARG_NUMBER_::, @"JS_Native::_MODULE_NAME_::_Spec::_SELECTOR_NAME_:::");'; + '\n setMethodArgConversionSelector(@"::_ARG_NAME_::", ::_ARG_NUMBER_::, @"JS_Native::_MODULE_NAME_::_Spec::_SELECTOR_NAME_:::");'; const template = ` /** @@ -57,17 +57,18 @@ const template = ` * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * ${'@'}generated by codegen project: GenerateModuleMm.js */ #include <::_INCLUDE_::> +#import + ::_GETTERS_:: namespace facebook { -namespace react { - + namespace react { ::_MODULES_:: - - -} // namespace react + } // namespace react } // namespace facebook `; @@ -242,7 +243,7 @@ module.exports = { returnTypeAnnotation.properties && returnTypeAnnotation.properties.length === 0 ? '' - : proprertyDefTemplate + : propertyDefTemplate .replace(/::_PROPERTY_NAME_::/g, propertyName) .replace(/::_ARGS_COUNT_::/g, params.length.toString()), ) diff --git a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructs.js b/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructs.js index ae924598b0ee1f..416e7c549fb03d 100644 --- a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructs.js +++ b/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructs.js @@ -44,37 +44,65 @@ inline ::_RETURN_TYPE_::JS::Native::_MODULE_NAME_::::Spec::_STRUCT_NAME_::::::_P } `; +function getSafePropertyName(name: string) { + if (name === 'id') { + return `${name}_`; + } + return name; +} + function getInlineMethodSignature( property: ObjectParamTypeAnnotation, name: string, ): string { const {typeAnnotation} = property; + function markOptionalTypeIfNecessary(type) { + if (property.optional) { + return `folly::Optional<${type}>`; + } + return type; + } switch (typeAnnotation.type) { case 'ReservedFunctionValueTypeAnnotation': switch (typeAnnotation.name) { case 'RootTag': - return `double ${property.name}() const;`; + return `double ${getSafePropertyName(property.name)}() const;`; default: (typeAnnotation.name: empty); throw new Error(`Unknown prop type, found: ${typeAnnotation.name}"`); } case 'StringTypeAnnotation': - return `NSString *${property.name}() const;`; + return `NSString *${getSafePropertyName(property.name)}() const;`; case 'NumberTypeAnnotation': case 'FloatTypeAnnotation': case 'Int32TypeAnnotation': - return `double ${property.name}() const;`; + return `${markOptionalTypeIfNecessary('double')} ${getSafePropertyName( + property.name, + )}() const;`; case 'BooleanTypeAnnotation': - return `bool ${property.name}() const;`; - case 'ObjectTypeAnnotation': - return `JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter( + return `${markOptionalTypeIfNecessary('bool')} ${getSafePropertyName( property.name, - )} ${property.name}() const;`; + )}() const;`; + case 'ObjectTypeAnnotation': + return ( + markOptionalTypeIfNecessary( + `JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter( + getSafePropertyName(property.name), + )}`, + ) + ` ${getSafePropertyName(property.name)}() const;` + ); case 'GenericObjectTypeAnnotation': case 'AnyTypeAnnotation': - return `id ${property.name}() const;`; + if (property.optional) { + return `id _Nullable ${getSafePropertyName( + property.name, + )}() const;`; + } + return `id ${getSafePropertyName(property.name)}() const;`; case 'ArrayTypeAnnotation': - return `facebook::react::LazyVector> ${property.name}() const;`; + return `${markOptionalTypeIfNecessary( + 'facebook::react::LazyVector>', + )} ${getSafePropertyName(property.name)}() const;`; case 'FunctionTypeAnnotation': default: throw new Error(`Unknown prop type, found: ${typeAnnotation.type}"`); @@ -86,6 +114,19 @@ function getInlineMethodImplementation( name: string, ): string { const {typeAnnotation} = property; + function markOptionalTypeIfNecessary(type) { + if (property.optional) { + return `folly::Optional<${type}> `; + } + return `${type} `; + } + function markOptionalValueIfNecessary(value) { + if (property.optional) { + return `RCTBridgingToOptional${capitalizeFirstLetter(value)}`; + } + return `RCTBridgingTo${capitalizeFirstLetter(value)}`; + } + switch (typeAnnotation.type) { case 'ReservedFunctionValueTypeAnnotation': switch (typeAnnotation.name) { @@ -105,40 +146,59 @@ function getInlineMethodImplementation( case 'FloatTypeAnnotation': case 'Int32TypeAnnotation': return inlineTemplate - .replace(/::_RETURN_TYPE_::/, 'double ') - .replace(/::_RETURN_VALUE_::/, 'RCTBridgingToDouble(p)'); + .replace(/::_RETURN_TYPE_::/, markOptionalTypeIfNecessary('double')) + .replace( + /::_RETURN_VALUE_::/, + `${markOptionalValueIfNecessary('double')}(p)`, + ); case 'BooleanTypeAnnotation': return inlineTemplate - .replace(/::_RETURN_TYPE_::/, 'bool ') - .replace(/::_RETURN_VALUE_::/, 'RCTBridgingToBool(p)'); + .replace(/::_RETURN_TYPE_::/, markOptionalTypeIfNecessary('bool')) + .replace( + /::_RETURN_VALUE_::/, + `${markOptionalValueIfNecessary('bool')}(p)`, + ); case 'GenericObjectTypeAnnotation': case 'AnyTypeAnnotation': return inlineTemplate - .replace(/::_RETURN_TYPE_::/, 'id ') + .replace( + /::_RETURN_TYPE_::/, + property.optional ? 'id _Nullable ' : 'id ', + ) .replace(/::_RETURN_VALUE_::/, 'p'); case 'ObjectTypeAnnotation': return inlineTemplate .replace( /::_RETURN_TYPE_::/, - `JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter( - property.name, - )} `, + markOptionalTypeIfNecessary( + `JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter( + getSafePropertyName(property.name), + )}`, + ), ) .replace( /::_RETURN_VALUE_::/, - `JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter( - property.name, - )}(p)`, + property.optional + ? `(p == nil ? folly::none : folly::make_optional(JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter( + getSafePropertyName(property.name), + )}(p)))` + : `JS::Native::_MODULE_NAME_::::Spec${name}${capitalizeFirstLetter( + getSafePropertyName(property.name), + )}(p)`, ); case 'ArrayTypeAnnotation': return inlineTemplate .replace( /::_RETURN_TYPE_::/, - 'facebook::react::LazyVector> ', + markOptionalTypeIfNecessary( + 'facebook::react::LazyVector>', + ), ) .replace( /::_RETURN_VALUE_::/, - 'RCTBridgingToVec(p, ^id(id itemValue_0) { return itemValue_0; })', + `${markOptionalValueIfNecessary( + 'vec', + )}(p, ^id(id itemValue_0) { return itemValue_0; })`, ); case 'FunctionTypeAnnotation': default: @@ -165,7 +225,10 @@ function translateObjectsForStructs( acc.concat( object.properties.map(property => getInlineMethodImplementation(property, object.name) - .replace(/::_PROPERTY_NAME_::/g, property.name) + .replace( + /::_PROPERTY_NAME_::/g, + getSafePropertyName(property.name), + ) .replace(/::_STRUCT_NAME_::/g, object.name), ), ), diff --git a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js index 25725ebaa42c26..fd534a9af516fb 100644 --- a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js @@ -463,6 +463,13 @@ const COMPLEX_OBJECTS: SchemaType = { type: 'StringTypeAnnotation', }, }, + { + optional: false, + name: 'id', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, ], }, }, @@ -480,6 +487,128 @@ const COMPLEX_OBJECTS: SchemaType = { optional: false, }, }, + { + name: 'optionals', + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + nullable: false, + type: 'VoidTypeAnnotation', + }, + params: [ + { + nullable: false, + name: 'A', + typeAnnotation: { + type: 'ObjectTypeAnnotation', + properties: [ + { + optional: true, + name: 'optionalNumberProperty', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + optional: true, + name: 'optionalArrayProperty', + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'NumberTypeAnnotation', + }, + }, + }, + { + optional: true, + name: 'optionalObjectProperty', + typeAnnotation: { + type: 'ObjectTypeAnnotation', + properties: [ + { + optional: false, + name: 'x', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + optional: false, + name: 'y', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + ], + }, + }, + { + optional: true, + name: 'optionalGenericObjectProperty', + typeAnnotation: { + type: 'GenericObjectTypeAnnotation', + }, + }, + { + optional: true, + name: 'optionalBooleanTypeProperty', + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, + }, + ], + }, + }, + ], + optional: false, + }, + }, + { + name: 'optionalMethod', + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + nullable: false, + type: 'VoidTypeAnnotation', + }, + params: [ + { + nullable: false, + name: 'options', + typeAnnotation: { + type: 'GenericObjectTypeAnnotation', + }, + }, + { + name: 'callback', + nullable: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + }, + }, + { + name: 'extras', + nullable: true, + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'ObjectTypeAnnotation', + properties: [ + { + optional: false, + name: 'key', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + ], + }, + }, + }, + ], + optional: true, + }, + }, ], }, }, diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap index f79507df8b3d3a..e3b257ba994b24 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap @@ -19,9 +19,21 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_difficult(jsi return static_cast(&turboModule)->difficult(rt, args[0].getObject(rt)); } +static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionals(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + static_cast(&turboModule)->optionals(rt, args[0].getObject(rt)); + return jsi::Value::undefined(); +} + +static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionalMethod(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + static_cast(&turboModule)->optionalMethod(rt, args[0].getObject(rt), std::move(args[1].getObject(rt).getFunction(rt)), args[2].getObject(rt).getArray(rt)); + return jsi::Value::undefined(); +} + NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker) : TurboModule(\\"SampleTurboModule\\", jsInvoker) { methodMap_[\\"difficult\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_difficult}; + methodMap_[\\"optionals\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionals}; + methodMap_[\\"optionalMethod\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionalMethod}; } diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap index 2fcc8834fa2372..308af3d47cdc32 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap @@ -23,6 +23,8 @@ protected: public: virtual jsi::Object difficult(jsi::Runtime &rt, const jsi::Object &A) = 0; +virtual void optionals(jsi::Runtime &rt, const jsi::Object &A) = 0; +virtual void optionalMethod(jsi::Runtime &rt, const jsi::Object &options, const jsi::Function &callback, const jsi::Array &extras) = 0; }; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap index 948c86afc4f0e8..6005fc72f622f0 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap @@ -8,32 +8,57 @@ Map { * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * @generated by codegen project: GenerateModuleHObjCpp.js */ -// NOTE: This entire file should be codegen'ed. +#ifndef __cplusplus +#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. +#endif #import #import -#import +#import -#import #import +#import #import + +#import #import #import -#import +#import +namespace JS { + namespace NativeSampleTurboModule { + struct SpecOptionalsAOptionalObjectProperty { + double x() const; + double y() const; + + SpecOptionalsAOptionalObjectProperty(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty:(id)json; +@end + + namespace JS { namespace NativeSampleTurboModule { struct SpecDifficultAE { bool D() const; double E() const; NSString *F() const; + double id_() const; SpecDifficultAE(NSDictionary *const v) : _v(v) {} private: @@ -47,6 +72,27 @@ namespace JS { @end +namespace JS { + namespace NativeSampleTurboModule { + struct SpecOptionalsA { + folly::Optional optionalNumberProperty() const; + folly::Optional>> optionalArrayProperty() const; + folly::Optional optionalObjectProperty() const; + id _Nullable optionalGenericObjectProperty() const; + folly::Optional optionalBooleanTypeProperty() const; + + SpecOptionalsA(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsA) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsA:(id)json; +@end + + namespace JS { namespace NativeSampleTurboModule { struct SpecDifficultReturnType { @@ -126,6 +172,41 @@ inline NSString *JS::NativeSampleTurboModule::SpecDifficultReturnType::F() const } +inline folly::Optional JS::NativeSampleTurboModule::SpecOptionalsA::optionalNumberProperty() const +{ + id const p = _v[@\\"optionalNumberProperty\\"]; + return RCTBridgingToOptionalDouble(p); +} + + +inline folly::Optional>> JS::NativeSampleTurboModule::SpecOptionalsA::optionalArrayProperty() const +{ + id const p = _v[@\\"optionalArrayProperty\\"]; + return RCTBridgingToOptionalVec(p, ^id(id itemValue_0) { return itemValue_0; }); +} + + +inline folly::Optional JS::NativeSampleTurboModule::SpecOptionalsA::optionalObjectProperty() const +{ + id const p = _v[@\\"optionalObjectProperty\\"]; + return (p == nil ? folly::none : folly::make_optional(JS::NativeSampleTurboModule::SpecOptionalsAOptionalObjectProperty(p))); +} + + +inline id _Nullable JS::NativeSampleTurboModule::SpecOptionalsA::optionalGenericObjectProperty() const +{ + id const p = _v[@\\"optionalGenericObjectProperty\\"]; + return p; +} + + +inline folly::Optional JS::NativeSampleTurboModule::SpecOptionalsA::optionalBooleanTypeProperty() const +{ + id const p = _v[@\\"optionalBooleanTypeProperty\\"]; + return RCTBridgingToOptionalBool(p); +} + + inline bool JS::NativeSampleTurboModule::SpecDifficultAE::D() const { id const p = _v[@\\"D\\"]; @@ -147,21 +228,47 @@ inline NSString *JS::NativeSampleTurboModule::SpecDifficultAE::F() const } +inline double JS::NativeSampleTurboModule::SpecDifficultAE::id_() const +{ + id const p = _v[@\\"id_\\"]; + return RCTBridgingToDouble(p); +} + + +inline double JS::NativeSampleTurboModule::SpecOptionalsAOptionalObjectProperty::x() const +{ + id const p = _v[@\\"x\\"]; + return RCTBridgingToDouble(p); +} + + +inline double JS::NativeSampleTurboModule::SpecOptionalsAOptionalObjectProperty::y() const +{ + id const p = _v[@\\"y\\"]; + return RCTBridgingToDouble(p); +} + + @protocol NativeSampleTurboModuleSpec - (NSDictionary *) difficult:(JS::NativeSampleTurboModule::SpecDifficultA&)A; +- (void) optionals:(JS::NativeSampleTurboModule::SpecOptionalsA&)A; +- (void) optionalMethod:(NSDictionary *)options + callback:(RCTResponseSenderBlock)callback + extras:(NSArray * _Nullable)extras; @end namespace facebook { -namespace react { - -class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { -public: - NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); -}; - -} // namespace react + namespace react { + /** + * ObjC++ class for module 'SampleTurboModule' + */ + class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react } // namespace facebook ", } @@ -175,23 +282,29 @@ Map { * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * @generated by codegen project: GenerateModuleHObjCpp.js */ -// NOTE: This entire file should be codegen'ed. +#ifndef __cplusplus +#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. +#endif #import #import -#import +#import -#import #import +#import #import + +#import #import #import -#import +#import @@ -203,14 +316,15 @@ Map { namespace facebook { -namespace react { - -class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { -public: - NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); -}; - -} // namespace react + namespace react { + /** + * ObjC++ class for module 'SampleTurboModule' + */ + class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react } // namespace facebook ", } @@ -224,23 +338,29 @@ Map { * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * @generated by codegen project: GenerateModuleHObjCpp.js */ -// NOTE: This entire file should be codegen'ed. +#ifndef __cplusplus +#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. +#endif #import #import -#import +#import -#import #import +#import #import + +#import #import #import -#import +#import @@ -310,14 +430,15 @@ inline JS::NativeSampleTurboModule::Constants::Builder::Builder(Constants i) : _ namespace facebook { -namespace react { - -class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { -public: - NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); -}; - -} // namespace react + namespace react { + /** + * ObjC++ class for module 'SampleTurboModule' + */ + class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react } // namespace facebook ", } @@ -331,29 +452,36 @@ Map { * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * @generated by codegen project: GenerateModuleHObjCpp.js */ -// NOTE: This entire file should be codegen'ed. +#ifndef __cplusplus +#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. +#endif #import #import -#import +#import -#import #import +#import #import + +#import #import #import -#import +#import -@protocol NativeSampleTurboModuleSpec +@protocol NativeSample2TurboModuleSpec + - (void) voidFunc; @end @@ -361,27 +489,28 @@ Map { - -@protocol NativeSample2TurboModuleSpec - +@protocol NativeSampleTurboModuleSpec - (void) voidFunc; @end namespace facebook { -namespace react { - -class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { -public: - NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); -}; - -class JSI_EXPORT NativeSample2TurboModuleSpecJSI : public ObjCTurboModule { -public: - NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); -}; - -} // namespace react + namespace react { + /** + * ObjC++ class for module 'SampleTurboModule' + */ + class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + /** + * ObjC++ class for module 'Sample2TurboModule' + */ + class JSI_EXPORT NativeSample2TurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react } // namespace facebook ", } @@ -395,29 +524,35 @@ Map { * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * @generated by codegen project: GenerateModuleHObjCpp.js */ -// NOTE: This entire file should be codegen'ed. +#ifndef __cplusplus +#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. +#endif #import #import -#import +#import -#import #import +#import #import + +#import #import #import -#import +#import -@protocol NativeSampleTurboModuleSpec +@protocol NativeSample2TurboModuleSpec - (void) voidFunc; @end @@ -425,26 +560,28 @@ Map { - -@protocol NativeSample2TurboModuleSpec +@protocol NativeSampleTurboModuleSpec - (void) voidFunc; @end namespace facebook { -namespace react { - -class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { -public: - NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); -}; - -class JSI_EXPORT NativeSample2TurboModuleSpecJSI : public ObjCTurboModule { -public: - NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); -}; - -} // namespace react + namespace react { + /** + * ObjC++ class for module 'SampleTurboModule' + */ + class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + /** + * ObjC++ class for module 'Sample2TurboModule' + */ + class JSI_EXPORT NativeSample2TurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react } // namespace facebook ", } diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap index 7b9ffc955e1b8d..86abf78460cec5 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap @@ -8,43 +8,80 @@ Map { * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * @generated by codegen project: GenerateModuleMm.js */ #include +#import + + @implementation RCTCxxConvert (NativeSampleTurboModule_SpecDifficultReturnType) + (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultReturnType:(id)json { return facebook::react::managedPointer(json); } @end + + @implementation RCTCxxConvert (NativeSampleTurboModule_SpecDifficultA) + (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultA:(id)json { return facebook::react::managedPointer(json); } @end + + +@implementation RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsA) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsA:(id)json +{ + return facebook::react::managedPointer(json); +} +@end + + @implementation RCTCxxConvert (NativeSampleTurboModule_SpecDifficultAE) + (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultAE:(id)json { return facebook::react::managedPointer(json); } @end -namespace facebook { -namespace react { -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_difficult(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, ObjectKind, \\"difficult\\", @selector(difficult:), args, count); -} -NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - methodMap_[\\"difficult\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_difficult}; - setMethodArgConversionSelector(@\\"difficult\\", 0, @\\"JS_NativeSampleTurboModule_SpecDifficultA:\\"); +@implementation RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty:(id)json +{ + return facebook::react::managedPointer(json); } +@end +namespace facebook { + namespace react { -} // namespace react + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_difficult(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) + .invokeObjCMethod(rt, ObjectKind, \\"difficult\\", @selector(difficult:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_optionals(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) + .invokeObjCMethod(rt, VoidKind, \\"optionals\\", @selector(optionals:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_optionalMethod(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) + .invokeObjCMethod(rt, VoidKind, \\"optionalMethod\\", @selector(optionalMethod:callback:extras:), args, count); + } + + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + methodMap_[\\"difficult\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_difficult}; + methodMap_[\\"optionals\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_optionals}; + methodMap_[\\"optionalMethod\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_optionalMethod}; + setMethodArgConversionSelector(@\\"difficult\\", 0, @\\"JS_NativeSampleTurboModule_SpecDifficultA:\\"); + setMethodArgConversionSelector(@\\"optionals\\", 0, @\\"JS_NativeSampleTurboModule_SpecOptionalsA:\\"); + } + } // namespace react } // namespace facebook ", } @@ -58,22 +95,23 @@ Map { * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * @generated by codegen project: GenerateModuleMm.js */ #include +#import -namespace facebook { -namespace react { - - - -NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { -} +namespace facebook { + namespace react { -} // namespace react + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + } + } // namespace react } // namespace facebook ", } @@ -87,75 +125,87 @@ Map { * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * @generated by codegen project: GenerateModuleMm.js */ #include +#import + namespace facebook { -namespace react { + namespace react { -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) .invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); -} -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); -} -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) .invokeObjCMethod(rt, BooleanKind, \\"getBool\\", @selector(getBool:), args, count); -} -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) .invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); -} -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) .invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); -} -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) .invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); -} -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) .invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); -} -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) .invokeObjCMethod(rt, NumberKind, \\"getRootTag\\", @selector(getRootTag:), args, count); -} -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:y:z:), args, count); -} -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); -} -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); -} + } -NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants}; - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; - methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getBool}; - methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber}; - methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getString}; - methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArray}; - methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObject}; - methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag}; - methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_getValue}; - methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback}; - methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise}; -} + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) + .invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:y:z:), args, count); + } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) + .invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + } -} // namespace react + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) + .invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + } + + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants}; + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getBool}; + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber}; + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getString}; + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArray}; + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObject}; + methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag}; + methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_getValue}; + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback}; + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise}; + } + } // namespace react } // namespace facebook ", } @@ -169,37 +219,40 @@ Map { * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * @generated by codegen project: GenerateModuleMm.js */ #include +#import -namespace facebook { -namespace react { - -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); -} -NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; -} +namespace facebook { + namespace react { -static facebook::jsi::Value __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); -} - -NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { + } - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc}; -} + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + } -} // namespace react + static facebook::jsi::Value __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) + .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + } + + NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc}; + } + } // namespace react } // namespace facebook ", } @@ -213,35 +266,38 @@ Map { * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * @generated by codegen project: GenerateModuleMm.js */ #include +#import + namespace facebook { -namespace react { + namespace react { -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); -} + } -NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; -} -static facebook::jsi::Value __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); -} - -NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc}; -} + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + } + static facebook::jsi::Value __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule) + .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + } -} // namespace react + NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc}; + } + } // namespace react } // namespace facebook ", } diff --git a/packages/react-native-codegen/src/parsers/flow/components/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/parsers/flow/components/__test_fixtures__/fixtures.js index 13e5131953358b..851257da1d052f 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/parsers/flow/components/__test_fixtures__/fixtures.js @@ -144,6 +144,7 @@ type ModuleProps = $ReadOnly<{| export default codegenNativeComponent('Module', { interfaceOnly: true, + excludedPlatforms: ['android'], paperComponentName: 'RCTModule', }); `; diff --git a/packages/react-native-codegen/src/parsers/flow/components/__tests__/__snapshots__/component-parser-test.js.snap b/packages/react-native-codegen/src/parsers/flow/components/__tests__/__snapshots__/component-parser-test.js.snap index 8192bb77cdf40a..6437404dd14201 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/__tests__/__snapshots__/component-parser-test.js.snap +++ b/packages/react-native-codegen/src/parsers/flow/components/__tests__/__snapshots__/component-parser-test.js.snap @@ -5935,6 +5935,9 @@ Object { }, }, ], + "excludedPlatforms": Array [ + "android", + ], "extendsProps": Array [ Object { "knownTypeName": "ReactNativeCoreViewProps", diff --git a/packages/react-native-codegen/src/parsers/flow/components/options.js b/packages/react-native-codegen/src/parsers/flow/components/options.js index f455a5f060a3f2..8044575db15913 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/options.js +++ b/packages/react-native-codegen/src/parsers/flow/components/options.js @@ -54,7 +54,13 @@ function getOptions(optionsExpression: OptionsAST): ?OptionsShape { let foundOptions; try { foundOptions = optionsExpression.properties.reduce((options, prop) => { - options[prop.key.name] = prop.value.value; + if (prop.value.type === 'ArrayExpression') { + options[prop.key.name] = prop.value.elements.map( + element => element.value, + ); + } else { + options[prop.key.name] = prop.value.value; + } return options; }, {}); } catch (e) { diff --git a/scripts/generate-native-modules-specs.sh b/scripts/generate-native-modules-specs.sh new file mode 100755 index 00000000000000..505a7769a338b0 --- /dev/null +++ b/scripts/generate-native-modules-specs.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# This script collects the JavaScript spec definitions for native +# modules, then uses react-native-codegen to generate native code. +# The script will copy the generated code to the final location by +# default. Optionally, call the script with a path to the desired +# output location. +# +# Usage: +# ./scripts/generate-native-modules-specs.sh [output-dir] +# +# Example: +# ./scripts/generate-native-modules-specs.sh ./codegen-out + +# shellcheck disable=SC2038 + +set -e + +describe () { + printf "\\n\\n>>>>> %s\\n\\n\\n" "$1" +} + +THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd) +RN_DIR=$(cd "$THIS_DIR/.." && pwd) + +TEMP_DIR=$(mktemp -d /tmp/react-native-codegen-XXXXXXXX) + +SRCS_DIR=$(cd "$RN_DIR/Libraries" && pwd) +LIBRARY_NAME="FBReactNativeSpec" +MODULE_SPEC_NAME="FBReactNativeSpec" + +SCHEMA_FILE="$RN_DIR/schema-native-modules.json" +OUTPUT_DIR="$SRCS_DIR/$LIBRARY_NAME/$MODULE_SPEC_NAME" + +describe "Generating schema from flow types" +grep --exclude NativeUIManager.js --include=Native\*.js -rnwl "$SRCS_DIR" -e 'export interface Spec extends TurboModule' -e "export default \(TurboModuleRegistry.get(Enforcing)?\('.*\): Spec\);/" \ + | xargs yarn flow-node packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js "$SCHEMA_FILE" + +describe "Generating native code from schema" +yarn flow-node packages/react-native-codegen/buck_tests/generate-tests.js "$SCHEMA_FILE" "$LIBRARY_NAME" "$TEMP_DIR" "$MODULE_SPEC_NAME" + +if [ -n "$1" ]; then + OUTPUT_DIR="$1" + mkdir -p "$OUTPUT_DIR" +fi + +describe "Copying $MODULE_SPEC_NAME output to $OUTPUT_DIR" +cp "$TEMP_DIR"/$MODULE_SPEC_NAME* "$OUTPUT_DIR/." diff --git a/scripts/react-native-xcode.sh b/scripts/react-native-xcode.sh index 88aa2a5af45021..a87c68fec607fe 100755 --- a/scripts/react-native-xcode.sh +++ b/scripts/react-native-xcode.sh @@ -14,10 +14,12 @@ DEST=$CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH # Enables iOS devices to get the IP address of the machine running Metro if [[ "$CONFIGURATION" = *Debug* && ! "$PLATFORM_NAME" == *simulator ]]; then - IP=$(ipconfig getifaddr en0) - if [[ -z "$IP" || -n "`ifconfig $value | grep 'baseT'`" ]]; then - IP=$(ipconfig getifaddr en1) - fi + for num in 0 1 2 3 4 5 6 7 8; do + IP=$(ipconfig getifaddr en${num}) + if [ ! -z "$IP" ]; then + break + fi + done if [ -z "$IP" ]; then IP=$(ifconfig | grep 'inet ' | grep -v ' 127.' | grep -v ' 169.254.' |cut -d\ -f2 | awk 'NR==1{print $1}') fi diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index 606d8f5dca7fb6..2cdade9df62ac7 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -45,6 +45,7 @@ def use_react_native! (options={}) pod 'React-jsiexecutor', :path => "#{prefix}/ReactCommon/jsiexecutor" pod 'React-jsinspector', :path => "#{prefix}/ReactCommon/jsinspector" pod 'React-callinvoker', :path => "#{prefix}/ReactCommon/callinvoker" + pod 'React-runtimeexecutor', :path => "#{prefix}/ReactCommon/runtimeexecutor" pod 'ReactCommon/turbomodule/core', :path => "#{prefix}/ReactCommon" pod 'Yoga', :path => "#{prefix}/ReactCommon/yoga", :modular_headers => true @@ -109,31 +110,4 @@ def flipper_post_install(installer) end end end - file_name = Dir.glob("*.xcodeproj")[0] - app_project = Xcodeproj::Project.open(file_name) - app_project.native_targets.each do |target| - target.build_configurations.each do |config| - cflags = config.build_settings['OTHER_CFLAGS'] || '$(inherited) ' - unless cflags.include? '-DFB_SONARKIT_ENABLED=1' - puts 'Adding -DFB_SONARKIT_ENABLED=1 in OTHER_CFLAGS...' - cflags << '-DFB_SONARKIT_ENABLED=1' - end - config.build_settings['OTHER_CFLAGS'] = cflags - if (config.build_settings['OTHER_SWIFT_FLAGS']) - unless config.build_settings['OTHER_SWIFT_FLAGS'].include? '-DFB_SONARKIT_ENABLED' - puts 'Adding -DFB_SONARKIT_ENABLED ...' - swift_flags = config.build_settings['OTHER_SWIFT_FLAGS'] - if swift_flags.split.last != '-Xcc' - config.build_settings['OTHER_SWIFT_FLAGS'] << ' -Xcc' - end - config.build_settings['OTHER_SWIFT_FLAGS'] << ' -DFB_SONARKIT_ENABLED' - end - else - puts 'OTHER_SWIFT_FLAGS does not exist thus assigning it to `$(inherited) -Xcc -DFB_SONARKIT_ENABLED`' - config.build_settings['OTHER_SWIFT_FLAGS'] = '$(inherited) -Xcc -DFB_SONARKIT_ENABLED' - end - app_project.save - end - end - installer.pods_project.save end diff --git a/scripts/run-ci-e2e-tests.js b/scripts/run-ci-e2e-tests.js index 8fb55c0834d064..ee16a0a4a5961f 100644 --- a/scripts/run-ci-e2e-tests.js +++ b/scripts/run-ci-e2e-tests.js @@ -13,7 +13,6 @@ * This script tests that React Native end to end installation/bootstrap works for different platforms * Available arguments: * --ios - 'react-native init' and check iOS app doesn't redbox - * --tvos - 'react-native init' and check tvOS app doesn't redbox * --android - 'react-native init' and check Android app doesn't redbox * --js - 'react-native init' and only check the packager returns a bundle * --skip-cli-install - to skip react-native-cli global installation (for local debugging) @@ -196,8 +195,7 @@ try { } } - if (argv.ios || argv.tvos) { - var iosTestType = argv.tvos ? 'tvOS' : 'iOS'; + if (argv.ios) { cd('ios'); // shelljs exec('', {async: true}) does not emit stdout events, so we rely on good old spawn const packagerEnv = Object.create(process.env); @@ -209,7 +207,7 @@ try { }); SERVER_PID = packagerProcess.pid; exec('sleep 15s'); - // prepare cache to reduce chances of possible red screen "Can't fibd variable __fbBatchedBridge..." + // prepare cache to reduce chances of possible red screen "Can't find variable __fbBatchedBridge..." exec( 'response=$(curl --write-out %{http_code} --silent --output /dev/null localhost:8081/index.bundle?platform=ios&dev=true)', ); @@ -218,32 +216,22 @@ try { describe('Install CocoaPod dependencies'); exec('pod install'); - describe('Test: ' + iosTestType + ' end-to-end test'); + describe('Test: iOS end-to-end test'); if ( // TODO: Get target OS and simulator from .tests.env tryExecNTimes( () => { - let destination = 'platform=iOS Simulator,name=iPhone 8,OS=13.3'; - let sdk = 'iphonesimulator'; - let scheme = 'HelloWorld'; - - if (argv.tvos) { - destination = 'platform=tvOS Simulator,name=Apple TV,OS=13.3'; - sdk = 'appletvsimulator'; - scheme = 'HelloWorld-tvOS'; - } - return exec( [ 'xcodebuild', '-workspace', '"HelloWorld.xcworkspace"', '-destination', - `"${destination}"`, + '"platform=iOS Simulator,name=iPhone 8,OS=13.3"', '-scheme', - `"${scheme}"`, + '"HelloWorld"', '-sdk', - sdk, + 'iphonesimulator', '-UseModernBuildSystem=NO', 'test', ].join(' ') + @@ -253,7 +241,7 @@ try { '--report', 'junit', '--output', - `"~/react-native/reports/junit/${iosTestType}-e2e/results.xml"`, + '"~/react-native/reports/junit/iOS-e2e/results.xml"', ].join(' ') + ' && exit ${PIPESTATUS[0]}', ).code; @@ -262,7 +250,7 @@ try { () => exec('sleep 10s'), ) ) { - echo('Failed to run ' + iosTestType + ' end-to-end tests'); + echo('Failed to run iOS end-to-end tests'); echo('Most likely the code is broken'); exitCode = 1; throw Error(exitCode); diff --git a/template/_flowconfig b/template/_flowconfig index b9e2438817bbf9..0296b285f8cf61 100644 --- a/template/_flowconfig +++ b/template/_flowconfig @@ -73,4 +73,4 @@ untyped-import untyped-type-import [version] -^0.123.0 +^0.124.0 diff --git a/template/android/app/src/debug/AndroidManifest.xml b/template/android/app/src/debug/AndroidManifest.xml index fa26aa56e1c144..b2f3ad9fce9234 100644 --- a/template/android/app/src/debug/AndroidManifest.xml +++ b/template/android/app/src/debug/AndroidManifest.xml @@ -4,5 +4,10 @@ - + + + diff --git a/template/android/app/src/main/AndroidManifest.xml b/template/android/app/src/main/AndroidManifest.xml index 0a7a9cfc66ce3f..6db8bad363a138 100644 --- a/template/android/app/src/main/AndroidManifest.xml +++ b/template/android/app/src/main/AndroidManifest.xml @@ -21,7 +21,5 @@ - - diff --git a/yarn.lock b/yarn.lock index 3defe0840ee560..1489a15c9d62ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,15 +9,6 @@ dependencies: "@babel/highlight" "^7.8.3" -"@babel/compat-data@^7.8.6", "@babel/compat-data@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.0.tgz#04815556fc90b0c174abd2c0c1bb966faa036a6c" - integrity sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g== - dependencies: - browserslist "^4.9.1" - invariant "^2.2.4" - semver "^5.5.0" - "@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.1.6", "@babel/core@^7.4.5", "@babel/core@^7.7.5": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" @@ -92,17 +83,6 @@ "@babel/helper-annotate-as-pure" "^7.8.3" "@babel/types" "^7.9.0" -"@babel/helper-compilation-targets@^7.8.7": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz#dac1eea159c0e4bd46e309b5a1b04a66b53c1dde" - integrity sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw== - dependencies: - "@babel/compat-data" "^7.8.6" - browserslist "^4.9.1" - invariant "^2.2.4" - levenary "^1.1.1" - semver "^5.5.0" - "@babel/helper-create-class-features-plugin@^7.8.3": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.6.tgz#243a5b46e2f8f0f674dc1387631eb6b28b851de0" @@ -115,7 +95,7 @@ "@babel/helper-replace-supers" "^7.8.6" "@babel/helper-split-export-declaration" "^7.8.3" -"@babel/helper-create-regexp-features-plugin@^7.8.3", "@babel/helper-create-regexp-features-plugin@^7.8.8": +"@babel/helper-create-regexp-features-plugin@^7.8.3": version "7.8.8" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz#5d84180b588f560b7864efaeea89243e58312087" integrity sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg== @@ -166,13 +146,6 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-hoist-variables@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" - integrity sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg== - dependencies: - "@babel/types" "^7.8.3" - "@babel/helper-member-expression-to-functions@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" @@ -310,15 +283,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-proposal-async-generator-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" - integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" - "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.1.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz#5e06654af5cd04b608915aada9b2a6788004464e" @@ -327,14 +291,6 @@ "@babel/helper-create-class-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-proposal-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" - integrity sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-proposal-export-default-from@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.8.3.tgz#4cb7c2fdeaed490b60d9bfd3dc8a20f81f9c2e7c" @@ -343,15 +299,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-export-default-from" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" - integrity sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.0" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.0.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": +"@babel/plugin-proposal-nullish-coalescing-operator@^7.0.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.1.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== @@ -359,15 +307,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" - integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - -"@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.9.0": +"@babel/plugin-proposal-object-rest-spread@^7.0.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.0.tgz#a28993699fc13df165995362693962ba6b061d6f" integrity sha512-UgqBv6bjq4fDb8uku9f+wcm1J7YxJ5nT7WO/jBr0cl0PLKb7t1O6RNR1kZbjgx2LQtsDI9hwoQVmn0yhXeQyow== @@ -375,7 +315,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" -"@babel/plugin-proposal-optional-catch-binding@^7.0.0", "@babel/plugin-proposal-optional-catch-binding@^7.8.3": +"@babel/plugin-proposal-optional-catch-binding@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" integrity sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw== @@ -383,7 +323,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.0.0", "@babel/plugin-proposal-optional-chaining@^7.9.0": +"@babel/plugin-proposal-optional-chaining@^7.0.0", "@babel/plugin-proposal-optional-chaining@^7.1.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== @@ -391,15 +331,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" - integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.8" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4": +"@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== @@ -420,7 +352,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-dynamic-import@^7.0.0", "@babel/plugin-syntax-dynamic-import@^7.8.0": +"@babel/plugin-syntax-dynamic-import@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== @@ -441,7 +373,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-json-strings@^7.8.0", "@babel/plugin-syntax-json-strings@^7.8.3": +"@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== @@ -469,7 +401,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": +"@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" integrity sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw== @@ -497,13 +429,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" - integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-typescript@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.8.3.tgz#c1f659dda97711a569cef75275f7e15dcaa6cabc" @@ -511,14 +436,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-arrow-functions@^7.0.0", "@babel/plugin-transform-arrow-functions@^7.8.3": +"@babel/plugin-transform-arrow-functions@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-async-to-generator@^7.0.0", "@babel/plugin-transform-async-to-generator@^7.8.3": +"@babel/plugin-transform-async-to-generator@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== @@ -527,14 +452,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/helper-remap-async-to-generator" "^7.8.3" -"@babel/plugin-transform-block-scoped-functions@^7.0.0", "@babel/plugin-transform-block-scoped-functions@^7.8.3": +"@babel/plugin-transform-block-scoped-functions@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-block-scoping@^7.0.0", "@babel/plugin-transform-block-scoping@^7.8.3": +"@babel/plugin-transform-block-scoping@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== @@ -542,7 +467,7 @@ "@babel/helper-plugin-utils" "^7.8.3" lodash "^4.17.13" -"@babel/plugin-transform-classes@^7.0.0", "@babel/plugin-transform-classes@^7.9.0": +"@babel/plugin-transform-classes@^7.0.0": version "7.9.2" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.2.tgz#8603fc3cc449e31fdbdbc257f67717536a11af8d" integrity sha512-TC2p3bPzsfvSsqBZo0kJnuelnoK9O3welkUpqSqBQuBF6R5MN2rysopri8kNvtlGIb2jmUO7i15IooAZJjZuMQ== @@ -556,36 +481,21 @@ "@babel/helper-split-export-declaration" "^7.8.3" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.0.0", "@babel/plugin-transform-computed-properties@^7.8.3": +"@babel/plugin-transform-computed-properties@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-destructuring@^7.0.0", "@babel/plugin-transform-destructuring@^7.8.3": +"@babel/plugin-transform-destructuring@^7.0.0": version "7.8.8" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.8.tgz#fadb2bc8e90ccaf5658de6f8d4d22ff6272a2f4b" integrity sha512-eRJu4Vs2rmttFCdhPUM3bV0Yo/xPSdPw6ML9KHs/bjB4bLA5HXlbvYXPOD5yASodGod+krjYx21xm1QmL8dCJQ== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" - integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-duplicate-keys@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" - integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-exponentiation-operator@^7.0.0", "@babel/plugin-transform-exponentiation-operator@^7.8.3": +"@babel/plugin-transform-exponentiation-operator@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ== @@ -601,14 +511,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-flow" "^7.8.3" -"@babel/plugin-transform-for-of@^7.0.0", "@babel/plugin-transform-for-of@^7.9.0": +"@babel/plugin-transform-for-of@^7.0.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e" integrity sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-function-name@^7.0.0", "@babel/plugin-transform-function-name@^7.8.3": +"@babel/plugin-transform-function-name@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== @@ -616,30 +526,21 @@ "@babel/helper-function-name" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-literals@^7.0.0", "@babel/plugin-transform-literals@^7.8.3": +"@babel/plugin-transform-literals@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-member-expression-literals@^7.0.0", "@babel/plugin-transform-member-expression-literals@^7.8.3": +"@babel/plugin-transform-member-expression-literals@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" integrity sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-modules-amd@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz#19755ee721912cf5bb04c07d50280af3484efef4" - integrity sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q== - dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.9.0": +"@babel/plugin-transform-modules-commonjs@^7.0.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz#e3e72f4cbc9b4a260e30be0ea59bdf5a39748940" integrity sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g== @@ -649,37 +550,15 @@ "@babel/helper-simple-access" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-systemjs@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz#e9fd46a296fc91e009b64e07ddaa86d6f0edeb90" - integrity sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ== +"@babel/plugin-transform-modules-commonjs@^7.1.0": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.6.tgz#64b7474a4279ee588cacd1906695ca721687c277" + integrity sha512-7H25fSlLcn+iYimmsNe3uK1at79IE6SKW9q0/QeEHTMC9MdOZ+4bA+T1VFB5fgOqBWoqlifXRzYD0JPdmIrgSQ== dependencies: - "@babel/helper-hoist-variables" "^7.8.3" "@babel/helper-module-transforms" "^7.9.0" "@babel/helper-plugin-utils" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-umd@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz#e909acae276fec280f9b821a5f38e1f08b480697" - integrity sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ== - dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" - integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - -"@babel/plugin-transform-new-target@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" - integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-simple-access" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.3" "@babel/plugin-transform-object-assign@^7.0.0": version "7.8.3" @@ -688,7 +567,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-object-super@^7.0.0", "@babel/plugin-transform-object-super@^7.8.3": +"@babel/plugin-transform-object-super@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== @@ -696,7 +575,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/helper-replace-supers" "^7.8.3" -"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.8.7": +"@babel/plugin-transform-parameters@^7.0.0": version "7.9.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.3.tgz#3028d0cc20ddc733166c6e9c8534559cee09f54a" integrity sha512-fzrQFQhp7mIhOzmOtPiKffvCYQSK10NR8t6BBz2yPbeUHb9OLW8RZGtgDRBn8z2hGcwvKDL3vC7ojPTLNxmqEg== @@ -704,7 +583,7 @@ "@babel/helper-get-function-arity" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-property-literals@^7.0.0", "@babel/plugin-transform-property-literals@^7.8.3": +"@babel/plugin-transform-property-literals@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" integrity sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg== @@ -744,20 +623,13 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" -"@babel/plugin-transform-regenerator@^7.0.0", "@babel/plugin-transform-regenerator@^7.8.7": +"@babel/plugin-transform-regenerator@^7.0.0": version "7.8.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8" integrity sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA== dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" - integrity sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-transform-runtime@^7.0.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.0.tgz#45468c0ae74cc13204e1d3b1f4ce6ee83258af0b" @@ -768,21 +640,21 @@ resolve "^1.8.1" semver "^5.5.1" -"@babel/plugin-transform-shorthand-properties@^7.0.0", "@babel/plugin-transform-shorthand-properties@^7.8.3": +"@babel/plugin-transform-shorthand-properties@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-spread@^7.0.0", "@babel/plugin-transform-spread@^7.8.3": +"@babel/plugin-transform-spread@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-sticky-regex@^7.0.0", "@babel/plugin-transform-sticky-regex@^7.8.3": +"@babel/plugin-transform-sticky-regex@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== @@ -790,7 +662,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/helper-regex" "^7.8.3" -"@babel/plugin-transform-template-literals@^7.0.0", "@babel/plugin-transform-template-literals@^7.8.3": +"@babel/plugin-transform-template-literals@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ== @@ -798,13 +670,6 @@ "@babel/helper-annotate-as-pure" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-typeof-symbol@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" - integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-transform-typescript@^7.5.0", "@babel/plugin-transform-typescript@^7.9.0": version "7.9.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.9.4.tgz#4bb4dde4f10bbf2d787fce9707fb09b483e33359" @@ -814,7 +679,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-typescript" "^7.8.3" -"@babel/plugin-transform-unicode-regex@^7.0.0", "@babel/plugin-transform-unicode-regex@^7.8.3": +"@babel/plugin-transform-unicode-regex@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw== @@ -822,72 +687,6 @@ "@babel/helper-create-regexp-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/preset-env@^7.1.6": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.0.tgz#a5fc42480e950ae8f5d9f8f2bbc03f52722df3a8" - integrity sha512-712DeRXT6dyKAM/FMbQTV/FvRCms2hPCx+3weRjZ8iQVQWZejWWk1wwG6ViWMyqb/ouBbGOl5b6aCk0+j1NmsQ== - dependencies: - "@babel/compat-data" "^7.9.0" - "@babel/helper-compilation-targets" "^7.8.7" - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-proposal-async-generator-functions" "^7.8.3" - "@babel/plugin-proposal-dynamic-import" "^7.8.3" - "@babel/plugin-proposal-json-strings" "^7.8.3" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-proposal-numeric-separator" "^7.8.3" - "@babel/plugin-proposal-object-rest-spread" "^7.9.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" - "@babel/plugin-proposal-optional-chaining" "^7.9.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" - "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-json-strings" "^7.8.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-syntax-numeric-separator" "^7.8.0" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - "@babel/plugin-transform-arrow-functions" "^7.8.3" - "@babel/plugin-transform-async-to-generator" "^7.8.3" - "@babel/plugin-transform-block-scoped-functions" "^7.8.3" - "@babel/plugin-transform-block-scoping" "^7.8.3" - "@babel/plugin-transform-classes" "^7.9.0" - "@babel/plugin-transform-computed-properties" "^7.8.3" - "@babel/plugin-transform-destructuring" "^7.8.3" - "@babel/plugin-transform-dotall-regex" "^7.8.3" - "@babel/plugin-transform-duplicate-keys" "^7.8.3" - "@babel/plugin-transform-exponentiation-operator" "^7.8.3" - "@babel/plugin-transform-for-of" "^7.9.0" - "@babel/plugin-transform-function-name" "^7.8.3" - "@babel/plugin-transform-literals" "^7.8.3" - "@babel/plugin-transform-member-expression-literals" "^7.8.3" - "@babel/plugin-transform-modules-amd" "^7.9.0" - "@babel/plugin-transform-modules-commonjs" "^7.9.0" - "@babel/plugin-transform-modules-systemjs" "^7.9.0" - "@babel/plugin-transform-modules-umd" "^7.9.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" - "@babel/plugin-transform-new-target" "^7.8.3" - "@babel/plugin-transform-object-super" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.8.7" - "@babel/plugin-transform-property-literals" "^7.8.3" - "@babel/plugin-transform-regenerator" "^7.8.7" - "@babel/plugin-transform-reserved-words" "^7.8.3" - "@babel/plugin-transform-shorthand-properties" "^7.8.3" - "@babel/plugin-transform-spread" "^7.8.3" - "@babel/plugin-transform-sticky-regex" "^7.8.3" - "@babel/plugin-transform-template-literals" "^7.8.3" - "@babel/plugin-transform-typeof-symbol" "^7.8.4" - "@babel/plugin-transform-unicode-regex" "^7.8.3" - "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.9.0" - browserslist "^4.9.1" - core-js-compat "^3.6.2" - invariant "^2.2.2" - levenary "^1.1.1" - semver "^5.5.0" - "@babel/preset-flow@^7.0.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.9.0.tgz#fee847c3e090b0b2d9227c1949e4da1d1379280d" @@ -896,17 +695,6 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-transform-flow-strip-types" "^7.9.0" -"@babel/preset-modules@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" - integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - "@babel/preset-typescript@^7.1.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.9.0.tgz#87705a72b1f0d59df21c179f7c3d2ef4b16ce192" @@ -933,7 +721,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.0.0", "@babel/template@^7.7.4", "@babel/template@^7.8.3", "@babel/template@^7.8.6": +"@babel/template@^7.0.0", "@babel/template@^7.3.3", "@babel/template@^7.7.4", "@babel/template@^7.8.3", "@babel/template@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== @@ -972,7 +760,7 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0": +"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.0.tgz#00b064c3df83ad32b2dbf5ff07312b15c7f1efb5" integrity sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng== @@ -981,6 +769,15 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.3.3": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7" + integrity sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA== + dependencies: + "@babel/helper-validator-identifier" "^7.9.5" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@babel/types@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444" @@ -1064,59 +861,58 @@ chalk "^2.0.1" slash "^2.0.0" -"@jest/console@^25.4.0": - version "25.4.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-25.4.0.tgz#e2760b532701137801ba824dcff6bc822c961bac" - integrity sha512-CfE0erx4hdJ6t7RzAcE1wLG6ZzsHSmybvIBQDoCkDM1QaSeWL9wJMzID/2BbHHa7ll9SsbbK43HjbERbBaFX2A== +"@jest/console@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.0.1.tgz#62b3b2fa8990f3cbffbef695c42ae9ddbc8f4b39" + integrity sha512-9t1KUe/93coV1rBSxMmBAOIK3/HVpwxArCA1CxskKyRiv6o8J70V8C/V3OJminVCTa2M0hQI9AWRd5wxu2dAHw== dependencies: - "@jest/types" "^25.4.0" - chalk "^3.0.0" - jest-message-util "^25.4.0" - jest-util "^25.4.0" + "@jest/types" "^26.0.1" + chalk "^4.0.0" + jest-message-util "^26.0.1" + jest-util "^26.0.1" slash "^3.0.0" -"@jest/core@^25.4.0": - version "25.4.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-25.4.0.tgz#cc1fe078df69b8f0fbb023bb0bcee23ef3b89411" - integrity sha512-h1x9WSVV0+TKVtATGjyQIMJENs8aF6eUjnCoi4jyRemYZmekLr8EJOGQqTWEX8W6SbZ6Skesy9pGXrKeAolUJw== +"@jest/core@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.0.1.tgz#aa538d52497dfab56735efb00e506be83d841fae" + integrity sha512-Xq3eqYnxsG9SjDC+WLeIgf7/8KU6rddBxH+SCt18gEpOhAGYC/Mq+YbtlNcIdwjnnT+wDseXSbU0e5X84Y4jTQ== dependencies: - "@jest/console" "^25.4.0" - "@jest/reporters" "^25.4.0" - "@jest/test-result" "^25.4.0" - "@jest/transform" "^25.4.0" - "@jest/types" "^25.4.0" + "@jest/console" "^26.0.1" + "@jest/reporters" "^26.0.1" + "@jest/test-result" "^26.0.1" + "@jest/transform" "^26.0.1" + "@jest/types" "^26.0.1" ansi-escapes "^4.2.1" - chalk "^3.0.0" + chalk "^4.0.0" exit "^0.1.2" - graceful-fs "^4.2.3" - jest-changed-files "^25.4.0" - jest-config "^25.4.0" - jest-haste-map "^25.4.0" - jest-message-util "^25.4.0" - jest-regex-util "^25.2.6" - jest-resolve "^25.4.0" - jest-resolve-dependencies "^25.4.0" - jest-runner "^25.4.0" - jest-runtime "^25.4.0" - jest-snapshot "^25.4.0" - jest-util "^25.4.0" - jest-validate "^25.4.0" - jest-watcher "^25.4.0" + graceful-fs "^4.2.4" + jest-changed-files "^26.0.1" + jest-config "^26.0.1" + jest-haste-map "^26.0.1" + jest-message-util "^26.0.1" + jest-regex-util "^26.0.0" + jest-resolve "^26.0.1" + jest-resolve-dependencies "^26.0.1" + jest-runner "^26.0.1" + jest-runtime "^26.0.1" + jest-snapshot "^26.0.1" + jest-util "^26.0.1" + jest-validate "^26.0.1" + jest-watcher "^26.0.1" micromatch "^4.0.2" p-each-series "^2.1.0" - realpath-native "^2.0.0" rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^25.4.0": - version "25.4.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-25.4.0.tgz#45071f525f0d8c5a51ed2b04fd42b55a8f0c7cb3" - integrity sha512-KDctiak4mu7b4J6BIoN/+LUL3pscBzoUCP+EtSPd2tK9fqyDY5OF+CmkBywkFWezS9tyH5ACOQNtpjtueEDH6Q== +"@jest/environment@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.0.1.tgz#82f519bba71959be9b483675ee89de8c8f72a5c8" + integrity sha512-xBDxPe8/nx251u0VJ2dFAFz2H23Y98qdIaNwnMK6dFQr05jc+Ne/2np73lOAx+5mSBO/yuQldRrQOf6hP1h92g== dependencies: - "@jest/fake-timers" "^25.4.0" - "@jest/types" "^25.4.0" - jest-mock "^25.4.0" + "@jest/fake-timers" "^26.0.1" + "@jest/types" "^26.0.1" + jest-mock "^26.0.1" "@jest/fake-timers@^24.8.0": version "24.8.0" @@ -1127,47 +923,57 @@ jest-message-util "^24.8.0" jest-mock "^24.8.0" -"@jest/fake-timers@^25.4.0": - version "25.4.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-25.4.0.tgz#3a9a4289ba836abd084953dca406389a57e00fbd" - integrity sha512-lI9z+VOmVX4dPPFzyj0vm+UtaB8dCJJ852lcDnY0uCPRvZAaVGnMwBBc1wxtf+h7Vz6KszoOvKAt4QijDnHDkg== +"@jest/fake-timers@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.0.1.tgz#f7aeff13b9f387e9d0cac9a8de3bba538d19d796" + integrity sha512-Oj/kCBnTKhm7CR+OJSjZty6N1bRDr9pgiYQr4wY221azLz5PHi08x/U+9+QpceAYOWheauLP8MhtSVFrqXQfhg== dependencies: - "@jest/types" "^25.4.0" - jest-message-util "^25.4.0" - jest-mock "^25.4.0" - jest-util "^25.4.0" - lolex "^5.0.0" + "@jest/types" "^26.0.1" + "@sinonjs/fake-timers" "^6.0.1" + jest-message-util "^26.0.1" + jest-mock "^26.0.1" + jest-util "^26.0.1" -"@jest/reporters@^25.4.0": - version "25.4.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-25.4.0.tgz#836093433b32ce4e866298af2d6fcf6ed351b0b0" - integrity sha512-bhx/buYbZgLZm4JWLcRJ/q9Gvmd3oUh7k2V7gA4ZYBx6J28pIuykIouclRdiAC6eGVX1uRZT+GK4CQJLd/PwPg== +"@jest/globals@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.0.1.tgz#3f67b508a7ce62b6e6efc536f3d18ec9deb19a9c" + integrity sha512-iuucxOYB7BRCvT+TYBzUqUNuxFX1hqaR6G6IcGgEqkJ5x4htNKo1r7jk1ji9Zj8ZMiMw0oB5NaA7k5Tx6MVssA== + dependencies: + "@jest/environment" "^26.0.1" + "@jest/types" "^26.0.1" + expect "^26.0.1" + +"@jest/reporters@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.0.1.tgz#14ae00e7a93e498cec35b0c00ab21c375d9b078f" + integrity sha512-NWWy9KwRtE1iyG/m7huiFVF9YsYv/e+mbflKRV84WDoJfBqUrNRyDbL/vFxQcYLl8IRqI4P3MgPn386x76Gf2g== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^25.4.0" - "@jest/test-result" "^25.4.0" - "@jest/transform" "^25.4.0" - "@jest/types" "^25.4.0" - chalk "^3.0.0" + "@jest/console" "^26.0.1" + "@jest/test-result" "^26.0.1" + "@jest/transform" "^26.0.1" + "@jest/types" "^26.0.1" + chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" glob "^7.1.2" + graceful-fs "^4.2.4" istanbul-lib-coverage "^3.0.0" istanbul-lib-instrument "^4.0.0" istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.0.2" - jest-haste-map "^25.4.0" - jest-resolve "^25.4.0" - jest-util "^25.4.0" - jest-worker "^25.4.0" + jest-haste-map "^26.0.1" + jest-resolve "^26.0.1" + jest-util "^26.0.1" + jest-worker "^26.0.0" slash "^3.0.0" source-map "^0.6.0" - string-length "^3.1.0" + string-length "^4.0.1" terminal-link "^2.0.0" v8-to-istanbul "^4.1.3" optionalDependencies: - node-notifier "^6.0.0" + node-notifier "^7.0.0" "@jest/source-map@^24.3.0": version "24.3.0" @@ -1178,13 +984,13 @@ graceful-fs "^4.1.15" source-map "^0.6.0" -"@jest/source-map@^25.2.6": - version "25.2.6" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-25.2.6.tgz#0ef2209514c6d445ebccea1438c55647f22abb4c" - integrity sha512-VuIRZF8M2zxYFGTEhkNSvQkUKafQro4y+mwUxy5ewRqs5N/ynSFUODYp3fy1zCnbCMy1pz3k+u57uCqx8QRSQQ== +"@jest/source-map@^26.0.0": + version "26.0.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.0.0.tgz#fd7706484a7d3faf7792ae29783933bbf48a4749" + integrity sha512-S2Z+Aj/7KOSU2TfW0dyzBze7xr95bkm5YXNUqqCek+HE0VbNNSNzrRwfIi5lf7wvzDTSS0/ib8XQ1krFNyYgbQ== dependencies: callsites "^3.0.0" - graceful-fs "^4.2.3" + graceful-fs "^4.2.4" source-map "^0.6.0" "@jest/test-result@^24.8.0": @@ -1196,44 +1002,44 @@ "@jest/types" "^24.8.0" "@types/istanbul-lib-coverage" "^2.0.0" -"@jest/test-result@^25.4.0": - version "25.4.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-25.4.0.tgz#6f2ec2c8da9981ef013ad8651c1c6f0cb20c6324" - integrity sha512-8BAKPaMCHlL941eyfqhWbmp3MebtzywlxzV+qtngQ3FH+RBqnoSAhNEPj4MG7d2NVUrMOVfrwuzGpVIK+QnMAA== +"@jest/test-result@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.0.1.tgz#1ffdc1ba4bc289919e54b9414b74c9c2f7b2b718" + integrity sha512-oKwHvOI73ICSYRPe8WwyYPTtiuOAkLSbY8/MfWF3qDEd/sa8EDyZzin3BaXTqufir/O/Gzea4E8Zl14XU4Mlyg== dependencies: - "@jest/console" "^25.4.0" - "@jest/types" "^25.4.0" + "@jest/console" "^26.0.1" + "@jest/types" "^26.0.1" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^25.4.0": - version "25.4.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-25.4.0.tgz#2b96f9d37f18dc3336b28e3c8070f97f9f55f43b" - integrity sha512-240cI+nsM3attx2bMp9uGjjHrwrpvxxrZi8Tyqp/cfOzl98oZXVakXBgxODGyBYAy/UGXPKXLvNc2GaqItrsJg== +"@jest/test-sequencer@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.0.1.tgz#b0563424728f3fe9e75d1442b9ae4c11da73f090" + integrity sha512-ssga8XlwfP8YjbDcmVhwNlrmblddMfgUeAkWIXts1V22equp2GMIHxm7cyeD5Q/B0ZgKPK/tngt45sH99yLLGg== dependencies: - "@jest/test-result" "^25.4.0" - jest-haste-map "^25.4.0" - jest-runner "^25.4.0" - jest-runtime "^25.4.0" + "@jest/test-result" "^26.0.1" + graceful-fs "^4.2.4" + jest-haste-map "^26.0.1" + jest-runner "^26.0.1" + jest-runtime "^26.0.1" -"@jest/transform@^25.4.0": - version "25.4.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-25.4.0.tgz#eef36f0367d639e2fd93dccd758550377fbb9962" - integrity sha512-t1w2S6V1sk++1HHsxboWxPEuSpN8pxEvNrZN+Ud/knkROWtf8LeUmz73A4ezE8476a5AM00IZr9a8FO9x1+j3g== +"@jest/transform@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.0.1.tgz#0e3ecbb34a11cd4b2080ed0a9c4856cf0ceb0639" + integrity sha512-pPRkVkAQ91drKGbzCfDOoHN838+FSbYaEAvBXvKuWeeRRUD8FjwXkqfUNUZL6Ke48aA/1cqq/Ni7kVMCoqagWA== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^25.4.0" + "@jest/types" "^26.0.1" babel-plugin-istanbul "^6.0.0" - chalk "^3.0.0" + chalk "^4.0.0" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" - graceful-fs "^4.2.3" - jest-haste-map "^25.4.0" - jest-regex-util "^25.2.6" - jest-util "^25.4.0" + graceful-fs "^4.2.4" + jest-haste-map "^26.0.1" + jest-regex-util "^26.0.0" + jest-util "^26.0.1" micromatch "^4.0.2" pirates "^4.0.1" - realpath-native "^2.0.0" slash "^3.0.0" source-map "^0.6.1" write-file-atomic "^3.0.0" @@ -1257,25 +1063,25 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" -"@jest/types@^25.4.0": - version "25.4.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.4.0.tgz#5afeb8f7e1cba153a28e5ac3c9fe3eede7206d59" - integrity sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw== +"@jest/types@^25.5.0": + version "25.5.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.5.0.tgz#4d6a4793f7b9599fc3680877b856a97dbccf2a9d" + integrity sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^15.0.0" chalk "^3.0.0" -"@jest/types@^25.5.0": - version "25.5.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.5.0.tgz#4d6a4793f7b9599fc3680877b856a97dbccf2a9d" - integrity sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw== +"@jest/types@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.0.1.tgz#b78333fbd113fa7aec8d39de24f88de8686dac67" + integrity sha512-IbtjvqI9+eS1qFnOIEL7ggWmT+iK/U+Vde9cGWtYb/b6XgKb3X44ZAe/z9YZzoAAZ/E92m0DqrilF934IGNnQA== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^15.0.0" - chalk "^3.0.0" + chalk "^4.0.0" "@react-native-community/cli-debugger-ui@^4.9.0": version "4.9.0" @@ -1398,6 +1204,13 @@ dependencies: type-detect "4.0.8" +"@sinonjs/fake-timers@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" + integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA== + dependencies: + "@sinonjs/commons" "^1.7.0" + "@types/babel__core@^7.1.7": version "7.1.7" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.7.tgz#1dacad8840364a57c98d0dd4855c6dd3752c6b89" @@ -1436,6 +1249,13 @@ resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/graceful-fs@^4.1.2": + version "4.1.3" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.3.tgz#039af35fe26bec35003e8d86d2ee9c586354348f" + integrity sha512-AiHRaEB50LQg0pZmm659vNBb9f4SJ0qrAnteuzhSeAUcJKxoYgEnprg/83kppCnc2zvtCKbdZry1a5pVY3lOTQ== + dependencies: + "@types/node" "*" + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" @@ -1461,15 +1281,20 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" +"@types/node@*": + version "13.13.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.4.tgz#1581d6c16e3d4803eb079c87d4ac893ee7501c2c" + integrity sha512-x26ur3dSXgv5AwKS0lNfbjpCakGIduWU1DU91Zz58ONRWrIKGunmZBNv4P7N+e27sJkiGDsw/3fT4AtsqQBrBA== + "@types/normalize-package-data@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== -"@types/prettier@^1.19.0": - version "1.19.1" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f" - integrity sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ== +"@types/prettier@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.0.tgz#dc85454b953178cc6043df5208b9e949b54a3bc4" + integrity sha512-/rM+sWiuOZ5dvuVzV37sUuklsbg+JPOP8d+nNFlo2ZtfpzPiPvh1/gc8liWOLBqe+sR+ZM7guPaIcTt6UZTo7Q== "@types/stack-utils@^1.0.1": version "1.0.1" @@ -1495,10 +1320,10 @@ dependencies: "@types/yargs-parser" "*" -abab@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f" - integrity sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w== +abab@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" + integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== abbrev@1: version "1.1.1" @@ -1525,35 +1350,30 @@ accepts@~1.3.5, accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" -acorn-globals@^4.3.2: - version "4.3.4" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" - integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A== +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== dependencies: - acorn "^6.0.1" - acorn-walk "^6.0.1" + acorn "^7.1.1" + acorn-walk "^7.1.1" acorn-jsx@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== -acorn-walk@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.1.0.tgz#c957f4a1460da46af4a0388ce28b4c99355b0cbc" - integrity sha512-ugTb7Lq7u4GfWSqqpwE0bGyoBZNMTok/zDBXxfEG0QM50jNlGhIWjRC1pPN7bvV1anhF+bs+/gNcRw+o55Evbg== - -acorn@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.2.tgz#6a459041c320ab17592c6317abbfdf4bbaa98ca4" - integrity sha512-GXmKIvbrN3TV7aVqAzVFaMW8F8wzVX7voEBRO3bDA64+EX37YSayggRJP5Xig6HYHBkWKpFg9W5gg6orklubhg== +acorn-walk@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.1.1.tgz#345f0dffad5c735e7373d2fec9a1023e6a44b83e" + integrity sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ== acorn@^6.0.2: version "6.1.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== -acorn@^7.1.0: +acorn@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== @@ -1769,11 +1589,6 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= -array-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" - integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= - array-filter@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" @@ -1914,17 +1729,18 @@ babel-eslint@10.0.1: eslint-scope "3.7.1" eslint-visitor-keys "^1.0.0" -babel-jest@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-25.4.0.tgz#409eb3e2ddc2ad9a92afdbb00991f1633f8018d0" - integrity sha512-p+epx4K0ypmHuCnd8BapfyOwWwosNCYhedetQey1awddtfmEX0MmdxctGl956uwUmjwXR5VSS5xJcGX9DvdIog== +babel-jest@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.0.1.tgz#450139ce4b6c17174b136425bda91885c397bc46" + integrity sha512-Z4GGmSNQ8pX3WS1O+6v3fo41YItJJZsVxG5gIQ+HuB/iuAQBJxMTHTwz292vuYws1LnHfwSRgoqI+nxdy/pcvw== dependencies: - "@jest/transform" "^25.4.0" - "@jest/types" "^25.4.0" + "@jest/transform" "^26.0.1" + "@jest/types" "^26.0.1" "@types/babel__core" "^7.1.7" babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^25.4.0" - chalk "^3.0.0" + babel-preset-jest "^26.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.4" slash "^3.0.0" babel-plugin-dynamic-import-node@^2.3.0: @@ -1934,6 +1750,13 @@ babel-plugin-dynamic-import-node@^2.3.0: dependencies: object.assign "^4.1.0" +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== + dependencies: + object.assign "^4.1.0" + babel-plugin-istanbul@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765" @@ -1945,11 +1768,13 @@ babel-plugin-istanbul@^6.0.0: istanbul-lib-instrument "^4.0.0" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-25.4.0.tgz#0c122c1b93fb76f52d2465be2e8069e798e9d442" - integrity sha512-M3a10JCtTyKevb0MjuH6tU+cP/NVQZ82QPADqI1RQYY1OphztsCeIeQmTsHmF/NS6m0E51Zl4QNsI3odXSQF5w== +babel-plugin-jest-hoist@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.0.0.tgz#fd1d35f95cf8849fc65cb01b5e58aedd710b34a8" + integrity sha512-+AuoehOrjt9irZL7DOt2+4ZaTM6dlu1s5TTS46JBa0/qem4dy7VNW3tMb96qeEqcIh20LD73TVNtmVEeymTG7w== dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" "@types/babel__traverse" "^7.0.6" babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: @@ -2040,12 +1865,12 @@ babel-preset-fbjs@^3.3.0: "@babel/plugin-transform-template-literals" "^7.0.0" babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" -babel-preset-jest@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-25.4.0.tgz#10037cc32b751b994b260964629e49dc479abf4c" - integrity sha512-PwFiEWflHdu3JCeTr0Pb9NcHHE34qWFnPQRVPvqQITx4CsDCzs6o05923I10XvLvn9nNsRHuiVgB72wG/90ZHQ== +babel-preset-jest@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.0.0.tgz#1eac82f513ad36c4db2e9263d7c485c825b1faa6" + integrity sha512-9ce+DatAa31DpR4Uir8g4Ahxs5K4W4L8refzt+qHWQANb6LhGcAEfIFgLUwk67oya2cCUd6t4eUMtO/z64ocNw== dependencies: - babel-plugin-jest-hoist "^25.4.0" + babel-plugin-jest-hoist "^26.0.0" babel-preset-current-node-syntax "^0.1.2" babylon@^6.15.0: @@ -2138,27 +1963,10 @@ braces@^3.0.1: dependencies: fill-range "^7.0.1" -browser-process-hrtime@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4" - integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw== - -browser-resolve@^1.11.3: - version "1.11.3" - resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" - integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ== - dependencies: - resolve "1.1.7" - -browserslist@^4.8.3, browserslist@^4.9.1: - version "4.11.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.11.1.tgz#92f855ee88d6e050e7e7311d987992014f1a1f1b" - integrity sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g== - dependencies: - caniuse-lite "^1.0.30001038" - electron-to-chromium "^1.3.390" - node-releases "^1.1.53" - pkg-up "^2.0.0" +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== bser@^2.0.0: version "2.0.0" @@ -2261,10 +2069,10 @@ camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-lite@^1.0.30001038: - version "1.0.30001038" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001038.tgz#44da3cbca2ab6cb6aa83d1be5d324e17f141caff" - integrity sha512-zii9quPo96XfOiRD4TrfYGs+QsGZpb2cGiMAzPjtf/hpFgB6zCPZgJb7I1+EATeMw/o+lG8FyRAnI+CWStHcaQ== +camelcase@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" + integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w== capture-exit@^1.2.0: version "1.2.0" @@ -2315,6 +2123,19 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.0.0.tgz#6e98081ed2d17faab615eb52ac66ec1fe6209e72" + integrity sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" @@ -2575,14 +2396,6 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-js-compat@^3.6.2: - version "3.6.4" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.4.tgz#938476569ebb6cda80d339bcf199fae4f16fff17" - integrity sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA== - dependencies: - browserslist "^4.8.3" - semver "7.0.0" - core-js@^2.2.2, core-js@^2.4.1: version "2.5.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" @@ -2661,7 +2474,7 @@ cross-spawn@^7.0.0: shebang-command "^2.0.0" which "^2.0.1" -cssom@^0.4.1: +cssom@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== @@ -2671,10 +2484,10 @@ cssom@~0.3.6: resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== -cssstyle@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.2.0.tgz#e4c44debccd6b7911ed617a4395e5754bba59992" - integrity sha512-sEb3XFPx3jNnCAMtqrXPDeSgQr+jojtCeNf8cvMNMh1cG970+lljssvQDzPq6lmmJu2Vhqood/gtEomBiHOGnA== +cssstyle@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== dependencies: cssom "~0.3.6" @@ -2690,14 +2503,14 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -data-urls@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" - integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ== +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== dependencies: - abab "^2.0.0" - whatwg-mimetype "^2.2.0" - whatwg-url "^7.0.0" + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" dayjs@^1.8.15: version "1.8.15" @@ -2737,6 +2550,11 @@ decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= +decimal.js@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231" + integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -2861,10 +2679,10 @@ detox@16.7.2: yargs "^13.0.0" yargs-parser "^13.0.0" -diff-sequences@^25.2.6: - version "25.2.6" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" - integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== +diff-sequences@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.0.0.tgz#0760059a5c287637b842bd7085311db7060e88a6" + integrity sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg== doctrine@^2.1.0: version "2.1.0" @@ -2873,12 +2691,12 @@ doctrine@^2.1.0: dependencies: esutils "^2.0.2" -domexception@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" - integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== dependencies: - webidl-conversions "^4.0.2" + webidl-conversions "^5.0.0" dtrace-provider@~0.8: version "0.8.7" @@ -2900,11 +2718,6 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.390: - version "1.3.392" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.392.tgz#280ab4f7a3ae47419cfabb15dbfc1567be7f1111" - integrity sha512-/hsgeVdReDsyTBE0aU9FRdh1wnNPrX3xlz3t61F+CJPOT+Umfi9DXHsCX85TEgWZQqlow0Rw44/4/jbU2Sqgkg== - emoji-regex@^7.0.1, emoji-regex@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -2996,7 +2809,12 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen@^1.11.1: +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escodegen@^1.14.1: version "1.14.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.1.tgz#ba01d0c8278b5e95a9a45350142026659027a457" integrity sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ== @@ -3111,12 +2929,12 @@ eslint-plugin-react@7.12.4: prop-types "^15.6.2" resolve "^1.9.0" -eslint-plugin-relay@1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-relay/-/eslint-plugin-relay-1.7.0.tgz#f6cfae681381dc96db9bd700d8c33fbe9783143e" - integrity sha512-JmAMQFr9CxXFLo5BppdN/sleofrE1J/cERIgkFqnYdTq0KAeUNGnz3jO41cqcp1y92/D+KJdmEKFsPfnqnDByQ== +eslint-plugin-relay@1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-relay/-/eslint-plugin-relay-1.7.1.tgz#70f479becb06320e57dd86ebc0d38938cb8a5e6e" + integrity sha512-K7j5BF8raseLfgA97udZMGKEtWan+y5BLrBYlApy952saStF0ghYzU9WElIwoVIkcBO8QP+pT4AOuNFFNRzcUw== dependencies: - graphql "^14.0.0 | ^15.0.0-rc.1" + graphql "^14.0.0 || ^15.0.0-rc.1" eslint-rule-composer@^0.3.0: version "0.3.0" @@ -3272,10 +3090,10 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@^3.2.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-3.4.0.tgz#c08ed4550ef65d858fac269ffc8572446f37eb89" - integrity sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g== +execa@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.0.tgz#7f37d6ec17f09e6b8fc53288611695b6d12b9daf" + integrity sha512-JbDUxwV3BoT5ZVXQrSVbAiaXhXUkIwvbhPIwZ0N13kX+5yCzOhUNdocxB/UQRuYOHRYYwAxKYwJYc0T4D12pDA== dependencies: cross-spawn "^7.0.0" get-stream "^5.0.0" @@ -3284,7 +3102,6 @@ execa@^3.2.0: merge-stream "^2.0.0" npm-run-path "^4.0.0" onetime "^5.1.0" - p-finally "^2.0.0" signal-exit "^3.0.2" strip-final-newline "^2.0.0" @@ -3306,17 +3123,17 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-25.4.0.tgz#0b16c17401906d1679d173e59f0d4580b22f8dc8" - integrity sha512-7BDIX99BTi12/sNGJXA9KMRcby4iAmu1xccBOhyKCyEhjcVKS3hPmHdA/4nSI9QGIOkUropKqr3vv7WMDM5lvQ== +expect@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.0.1.tgz#18697b9611a7e2725e20ba3ceadda49bc9865421" + integrity sha512-QcCy4nygHeqmbw564YxNbHTJlXh47dVID2BUP52cZFpLU9zHViMFK6h07cC1wf7GYCTIigTdAXhVua8Yl1FkKg== dependencies: - "@jest/types" "^25.4.0" + "@jest/types" "^26.0.1" ansi-styles "^4.0.0" - jest-get-type "^25.2.6" - jest-matcher-utils "^25.4.0" - jest-message-util "^25.4.0" - jest-regex-util "^25.2.6" + jest-get-type "^26.0.0" + jest-matcher-utils "^26.0.1" + jest-message-util "^26.0.1" + jest-regex-util "^26.0.0" extend-shallow@^1.1.2: version "1.1.4" @@ -3508,13 +3325,6 @@ find-cache-dir@^2.0.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -3540,10 +3350,10 @@ flat-cache@^1.2.1: rimraf "~2.6.2" write "^0.2.1" -flow-bin@^0.123.0: - version "0.123.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.123.0.tgz#7ba61a0b8775928cf4943ccf78eed2b1b05f7b3a" - integrity sha512-Ylcf8YDIM/KrqtxkPuq+f8O+6sdYA2Nuz5f+sWHlp539DatZz3YMcsO1EiXaf1C11HJgpT/3YGYe7xZ9/UZmvQ== +flow-bin@^0.124.0: + version "0.124.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.124.0.tgz#24b2e55874e1e2041f9247f42473b3db2ef32758" + integrity sha512-KEtDJ7CFUjcuhw6N52FTZshDd1krf1fxpp4APSIrwhVm+IrlcKJ+EMXpeXKM1kKNSZ347dYGh8wEvXQl4pHZEA== flow-parser@0.*: version "0.89.0" @@ -3768,15 +3578,20 @@ graceful-fs@^4.1.15: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== -graceful-fs@^4.2.0, graceful-fs@^4.2.3: +graceful-fs@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== -"graphql@^14.0.0 | ^15.0.0-rc.1": - version "15.0.0-rc.2" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.0.0-rc.2.tgz#6549e52e5415ac08900c432b22d34500c0c3635f" - integrity sha512-X9ZybETBiZ5zndyXm/Yn3dd0nJqiCNZ7w06lnd0zMiCtBR/KQGgxJmnf47Y/P/Fy7JXM4QDF+MeeoH724yc3DQ== +graceful-fs@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + +"graphql@^14.0.0 || ^15.0.0-rc.1": + version "15.0.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.0.0.tgz#042a5eb5e2506a2e2111ce41eb446a8e570b8be9" + integrity sha512-ZyVO1xIF9F+4cxfkdhOJINM+51B06Friuv4M66W7HzUOeFd+vNzUn4vtswYINPi6sysjf1M2Ri/rwZALqgwbaQ== "growl@~> 1.10.0": version "1.10.5" @@ -3889,12 +3704,12 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== -html-encoding-sniffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" - integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== dependencies: - whatwg-encoding "^1.0.1" + whatwg-encoding "^1.0.5" html-escaper@^2.0.0: version "2.0.0" @@ -4037,7 +3852,7 @@ interpret@^1.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= -invariant@^2.2.2, invariant@^2.2.4: +invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -4185,6 +4000,11 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-potential-custom-element-name@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" + integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c= + is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" @@ -4318,114 +4138,113 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jest-changed-files@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-25.4.0.tgz#e573db32c2fd47d2b90357ea2eda0622c5c5cbd6" - integrity sha512-VR/rfJsEs4BVMkwOTuStRyS630fidFVekdw/lBaBQjx9KK3VZFOZ2c0fsom2fRp8pMCrCTP6LGna00o/DXGlqA== +jest-changed-files@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.0.1.tgz#1334630c6a1ad75784120f39c3aa9278e59f349f" + integrity sha512-q8LP9Sint17HaE2LjxQXL+oYWW/WeeXMPE2+Op9X3mY8IEGFVc14xRxFjUuXUbcPAlDLhtWdIEt59GdQbn76Hw== dependencies: - "@jest/types" "^25.4.0" - execa "^3.2.0" + "@jest/types" "^26.0.1" + execa "^4.0.0" throat "^5.0.0" -jest-cli@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-25.4.0.tgz#5dac8be0fece6ce39f0d671395a61d1357322bab" - integrity sha512-usyrj1lzCJZMRN1r3QEdnn8e6E6yCx/QN7+B1sLoA68V7f3WlsxSSQfy0+BAwRiF4Hz2eHauf11GZG3PIfWTXQ== +jest-cli@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.0.1.tgz#3a42399a4cbc96a519b99ad069a117d955570cac" + integrity sha512-pFLfSOBcbG9iOZWaMK4Een+tTxi/Wcm34geqZEqrst9cZDkTQ1LZ2CnBrTlHWuYAiTMFr0EQeK52ScyFU8wK+w== dependencies: - "@jest/core" "^25.4.0" - "@jest/test-result" "^25.4.0" - "@jest/types" "^25.4.0" - chalk "^3.0.0" + "@jest/core" "^26.0.1" + "@jest/test-result" "^26.0.1" + "@jest/types" "^26.0.1" + chalk "^4.0.0" exit "^0.1.2" + graceful-fs "^4.2.4" import-local "^3.0.2" is-ci "^2.0.0" - jest-config "^25.4.0" - jest-util "^25.4.0" - jest-validate "^25.4.0" + jest-config "^26.0.1" + jest-util "^26.0.1" + jest-validate "^26.0.1" prompts "^2.0.1" - realpath-native "^2.0.0" yargs "^15.3.1" -jest-config@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-25.4.0.tgz#56e5df3679a96ff132114b44fb147389c8c0a774" - integrity sha512-egT9aKYxMyMSQV1aqTgam0SkI5/I2P9qrKexN5r2uuM2+68ypnc+zPGmfUxK7p1UhE7dYH9SLBS7yb+TtmT1AA== +jest-config@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.0.1.tgz#096a3d4150afadf719d1fab00e9a6fb2d6d67507" + integrity sha512-9mWKx2L1LFgOXlDsC4YSeavnblN6A4CPfXFiobq+YYLaBMymA/SczN7xYTSmLaEYHZOcB98UdoN4m5uNt6tztg== dependencies: "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^25.4.0" - "@jest/types" "^25.4.0" - babel-jest "^25.4.0" - chalk "^3.0.0" + "@jest/test-sequencer" "^26.0.1" + "@jest/types" "^26.0.1" + babel-jest "^26.0.1" + chalk "^4.0.0" deepmerge "^4.2.2" glob "^7.1.1" - jest-environment-jsdom "^25.4.0" - jest-environment-node "^25.4.0" - jest-get-type "^25.2.6" - jest-jasmine2 "^25.4.0" - jest-regex-util "^25.2.6" - jest-resolve "^25.4.0" - jest-util "^25.4.0" - jest-validate "^25.4.0" + graceful-fs "^4.2.4" + jest-environment-jsdom "^26.0.1" + jest-environment-node "^26.0.1" + jest-get-type "^26.0.0" + jest-jasmine2 "^26.0.1" + jest-regex-util "^26.0.0" + jest-resolve "^26.0.1" + jest-util "^26.0.1" + jest-validate "^26.0.1" micromatch "^4.0.2" - pretty-format "^25.4.0" - realpath-native "^2.0.0" + pretty-format "^26.0.1" -jest-diff@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.4.0.tgz#260b70f19a46c283adcad7f081cae71eb784a634" - integrity sha512-kklLbJVXW0y8UKOWOdYhI6TH5MG6QAxrWiBMgQaPIuhj3dNFGirKCd+/xfplBXICQ7fI+3QcqHm9p9lWu1N6ug== +jest-diff@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.0.1.tgz#c44ab3cdd5977d466de69c46929e0e57f89aa1de" + integrity sha512-odTcHyl5X+U+QsczJmOjWw5tPvww+y9Yim5xzqxVl/R1j4z71+fHW4g8qu1ugMmKdFdxw+AtQgs5mupPnzcIBQ== dependencies: - chalk "^3.0.0" - diff-sequences "^25.2.6" - jest-get-type "^25.2.6" - pretty-format "^25.4.0" + chalk "^4.0.0" + diff-sequences "^26.0.0" + jest-get-type "^26.0.0" + pretty-format "^26.0.1" jest-docblock@^21.0.0: version "21.2.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" integrity sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw== -jest-docblock@^25.3.0: - version "25.3.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-25.3.0.tgz#8b777a27e3477cd77a168c05290c471a575623ef" - integrity sha512-aktF0kCar8+zxRHxQZwxMy70stc9R1mOmrLsT5VO3pIT0uzGRSDAXxSlz4NqQWpuLjPpuMhPRl7H+5FRsvIQAg== +jest-docblock@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5" + integrity sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w== dependencies: detect-newline "^3.0.0" -jest-each@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-25.4.0.tgz#ad4e46164764e8e77058f169a0076a7f86f6b7d4" - integrity sha512-lwRIJ8/vQU/6vq3nnSSUw1Y3nz5tkYSFIywGCZpUBd6WcRgpn8NmJoQICojbpZmsJOJNHm0BKdyuJ6Xdx+eDQQ== - dependencies: - "@jest/types" "^25.4.0" - chalk "^3.0.0" - jest-get-type "^25.2.6" - jest-util "^25.4.0" - pretty-format "^25.4.0" - -jest-environment-jsdom@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-25.4.0.tgz#bbfc7f85bb6ade99089062a830c79cb454565cf0" - integrity sha512-KTitVGMDrn2+pt7aZ8/yUTuS333w3pWt1Mf88vMntw7ZSBNDkRS6/4XLbFpWXYfWfp1FjcjQTOKzbK20oIehWQ== - dependencies: - "@jest/environment" "^25.4.0" - "@jest/fake-timers" "^25.4.0" - "@jest/types" "^25.4.0" - jest-mock "^25.4.0" - jest-util "^25.4.0" - jsdom "^15.2.1" - -jest-environment-node@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-25.4.0.tgz#188aef01ae6418e001c03fdd1c299961e1439082" - integrity sha512-wryZ18vsxEAKFH7Z74zi/y/SyI1j6UkVZ6QsllBuT/bWlahNfQjLNwFsgh/5u7O957dYFoXj4yfma4n4X6kU9A== - dependencies: - "@jest/environment" "^25.4.0" - "@jest/fake-timers" "^25.4.0" - "@jest/types" "^25.4.0" - jest-mock "^25.4.0" - jest-util "^25.4.0" - semver "^6.3.0" +jest-each@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.0.1.tgz#633083061619302fc90dd8f58350f9d77d67be04" + integrity sha512-OTgJlwXCAR8NIWaXFL5DBbeS4QIYPuNASkzSwMCJO+ywo9BEa6TqkaSWsfR7VdbMLdgYJqSfQcIyjJCNwl5n4Q== + dependencies: + "@jest/types" "^26.0.1" + chalk "^4.0.0" + jest-get-type "^26.0.0" + jest-util "^26.0.1" + pretty-format "^26.0.1" + +jest-environment-jsdom@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.0.1.tgz#217690852e5bdd7c846a4e3b50c8ffd441dfd249" + integrity sha512-u88NJa3aptz2Xix2pFhihRBAatwZHWwSiRLBDBQE1cdJvDjPvv7ZGA0NQBxWwDDn7D0g1uHqxM8aGgfA9Bx49g== + dependencies: + "@jest/environment" "^26.0.1" + "@jest/fake-timers" "^26.0.1" + "@jest/types" "^26.0.1" + jest-mock "^26.0.1" + jest-util "^26.0.1" + jsdom "^16.2.2" + +jest-environment-node@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.0.1.tgz#584a9ff623124ff6eeb49e0131b5f7612b310b13" + integrity sha512-4FRBWcSn5yVo0KtNav7+5NH5Z/tEgDLp7VRQVS5tCouWORxj+nI+1tOLutM07Zb2Qi7ja+HEDoOUkjBSWZg/IQ== + dependencies: + "@jest/environment" "^26.0.1" + "@jest/fake-timers" "^26.0.1" + "@jest/types" "^26.0.1" + jest-mock "^26.0.1" + jest-util "^26.0.1" jest-get-type@^24.3.0: version "24.3.0" @@ -4437,10 +4256,10 @@ jest-get-type@^24.9.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e" integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q== -jest-get-type@^25.2.6: - version "25.2.6" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" - integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig== +jest-get-type@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.0.0.tgz#381e986a718998dbfafcd5ec05934be538db4039" + integrity sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg== jest-haste-map@^24.7.1: version "24.8.1" @@ -4461,18 +4280,19 @@ jest-haste-map@^24.7.1: optionalDependencies: fsevents "^1.2.7" -jest-haste-map@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-25.4.0.tgz#da7c309dd7071e0a80c953ba10a0ec397efb1ae2" - integrity sha512-5EoCe1gXfGC7jmXbKzqxESrgRcaO3SzWXGCnvp9BcT0CFMyrB1Q6LIsjl9RmvmJGQgW297TCfrdgiy574Rl9HQ== +jest-haste-map@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.0.1.tgz#40dcc03c43ac94d25b8618075804d09cd5d49de7" + integrity sha512-J9kBl/EdjmDsvyv7CiyKY5+DsTvVOScenprz/fGqfLg/pm1gdjbwwQ98nW0t+OIt+f+5nAVaElvn/6wP5KO7KA== dependencies: - "@jest/types" "^25.4.0" + "@jest/types" "^26.0.1" + "@types/graceful-fs" "^4.1.2" anymatch "^3.0.3" fb-watchman "^2.0.0" - graceful-fs "^4.2.3" - jest-serializer "^25.2.6" - jest-util "^25.4.0" - jest-worker "^25.4.0" + graceful-fs "^4.2.4" + jest-serializer "^26.0.0" + jest-util "^26.0.1" + jest-worker "^26.0.0" micromatch "^4.0.2" sane "^4.0.3" walker "^1.0.7" @@ -4480,27 +4300,27 @@ jest-haste-map@^25.4.0: optionalDependencies: fsevents "^2.1.2" -jest-jasmine2@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-25.4.0.tgz#3d3d19514022e2326e836c2b66d68b4cb63c5861" - integrity sha512-QccxnozujVKYNEhMQ1vREiz859fPN/XklOzfQjm2j9IGytAkUbSwjFRBtQbHaNZ88cItMpw02JnHGsIdfdpwxQ== +jest-jasmine2@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.0.1.tgz#947c40ee816636ba23112af3206d6fa7b23c1c1c" + integrity sha512-ILaRyiWxiXOJ+RWTKupzQWwnPaeXPIoLS5uW41h18varJzd9/7I0QJGqg69fhTT1ev9JpSSo9QtalriUN0oqOg== dependencies: "@babel/traverse" "^7.1.0" - "@jest/environment" "^25.4.0" - "@jest/source-map" "^25.2.6" - "@jest/test-result" "^25.4.0" - "@jest/types" "^25.4.0" - chalk "^3.0.0" + "@jest/environment" "^26.0.1" + "@jest/source-map" "^26.0.0" + "@jest/test-result" "^26.0.1" + "@jest/types" "^26.0.1" + chalk "^4.0.0" co "^4.6.0" - expect "^25.4.0" + expect "^26.0.1" is-generator-fn "^2.0.0" - jest-each "^25.4.0" - jest-matcher-utils "^25.4.0" - jest-message-util "^25.4.0" - jest-runtime "^25.4.0" - jest-snapshot "^25.4.0" - jest-util "^25.4.0" - pretty-format "^25.4.0" + jest-each "^26.0.1" + jest-matcher-utils "^26.0.1" + jest-message-util "^26.0.1" + jest-runtime "^26.0.1" + jest-snapshot "^26.0.1" + jest-util "^26.0.1" + pretty-format "^26.0.1" throat "^5.0.0" jest-junit@^10.0.0: @@ -4514,23 +4334,23 @@ jest-junit@^10.0.0: uuid "^3.3.3" xml "^1.0.1" -jest-leak-detector@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-25.4.0.tgz#cf94a160c78e53d810e7b2f40b5fd7ee263375b3" - integrity sha512-7Y6Bqfv2xWsB+7w44dvZuLs5SQ//fzhETgOGG7Gq3TTGFdYvAgXGwV8z159RFZ6fXiCPm/szQ90CyfVos9JIFQ== +jest-leak-detector@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.0.1.tgz#79b19ab3f41170e0a78eb8fa754a116d3447fb8c" + integrity sha512-93FR8tJhaYIWrWsbmVN1pQ9ZNlbgRpfvrnw5LmgLRX0ckOJ8ut/I35CL7awi2ecq6Ca4lL59bEK9hr7nqoHWPA== dependencies: - jest-get-type "^25.2.6" - pretty-format "^25.4.0" + jest-get-type "^26.0.0" + pretty-format "^26.0.1" -jest-matcher-utils@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-25.4.0.tgz#dc3e7aec402a1e567ed80b572b9ad285878895e6" - integrity sha512-yPMdtj7YDgXhnGbc66bowk8AkQ0YwClbbwk3Kzhn5GVDrciiCr27U4NJRbrqXbTdtxjImONITg2LiRIw650k5A== +jest-matcher-utils@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.0.1.tgz#12e1fc386fe4f14678f4cc8dbd5ba75a58092911" + integrity sha512-PUMlsLth0Azen8Q2WFTwnSkGh2JZ8FYuwijC8NR47vXKpsrKmA1wWvgcj1CquuVfcYiDEdj985u5Wmg7COEARw== dependencies: - chalk "^3.0.0" - jest-diff "^25.4.0" - jest-get-type "^25.2.6" - pretty-format "^25.4.0" + chalk "^4.0.0" + jest-diff "^26.0.1" + jest-get-type "^26.0.0" + pretty-format "^26.0.1" jest-message-util@^24.8.0: version "24.8.0" @@ -4546,18 +4366,19 @@ jest-message-util@^24.8.0: slash "^2.0.0" stack-utils "^1.0.1" -jest-message-util@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-25.4.0.tgz#2899e8bc43f5317acf8dfdfe89ea237d354fcdab" - integrity sha512-LYY9hRcVGgMeMwmdfh9tTjeux1OjZHMusq/E5f3tJN+dAoVVkJtq5ZUEPIcB7bpxDUt2zjUsrwg0EGgPQ+OhXQ== +jest-message-util@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.0.1.tgz#07af1b42fc450b4cc8e90e4c9cef11b33ce9b0ac" + integrity sha512-CbK8uQREZ8umUfo8+zgIfEt+W7HAHjQCoRaNs4WxKGhAYBGwEyvxuK81FXa7VeB9pwDEXeeKOB2qcsNVCAvB7Q== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/types" "^25.4.0" + "@jest/types" "^26.0.1" "@types/stack-utils" "^1.0.1" - chalk "^3.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.4" micromatch "^4.0.2" slash "^3.0.0" - stack-utils "^1.0.1" + stack-utils "^2.0.2" jest-mock@^24.8.0: version "24.8.0" @@ -4566,98 +4387,99 @@ jest-mock@^24.8.0: dependencies: "@jest/types" "^24.8.0" -jest-mock@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-25.4.0.tgz#ded7d64b5328d81d78d2138c825d3a45e30ec8ca" - integrity sha512-MdazSfcYAUjJjuVTTnusLPzE0pE4VXpOUzWdj8sbM+q6abUjm3bATVPXFqTXrxSieR8ocpvQ9v/QaQCftioQFg== +jest-mock@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.0.1.tgz#7fd1517ed4955397cf1620a771dc2d61fad8fd40" + integrity sha512-MpYTBqycuPYSY6xKJognV7Ja46/TeRbAZept987Zp+tuJvMN0YBWyyhG9mXyYQaU3SBI0TUlSaO5L3p49agw7Q== dependencies: - "@jest/types" "^25.4.0" + "@jest/types" "^26.0.1" jest-pnp-resolver@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== -jest-regex-util@^25.2.6: - version "25.2.6" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-25.2.6.tgz#d847d38ba15d2118d3b06390056028d0f2fd3964" - integrity sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw== +jest-regex-util@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" + integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== -jest-resolve-dependencies@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-25.4.0.tgz#783937544cfc40afcc7c569aa54748c4b3f83f5a" - integrity sha512-A0eoZXx6kLiuG1Ui7wITQPl04HwjLErKIJTt8GR3c7UoDAtzW84JtCrgrJ6Tkw6c6MwHEyAaLk7dEPml5pf48A== +jest-resolve-dependencies@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.0.1.tgz#607ba7ccc32151d185a477cff45bf33bce417f0b" + integrity sha512-9d5/RS/ft0vB/qy7jct/qAhzJsr6fRQJyGAFigK3XD4hf9kIbEH5gks4t4Z7kyMRhowU6HWm/o8ILqhaHdSqLw== dependencies: - "@jest/types" "^25.4.0" - jest-regex-util "^25.2.6" - jest-snapshot "^25.4.0" + "@jest/types" "^26.0.1" + jest-regex-util "^26.0.0" + jest-snapshot "^26.0.1" -jest-resolve@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-25.4.0.tgz#6f4540ce0d419c4c720e791e871da32ba4da7a60" - integrity sha512-wOsKqVDFWUiv8BtLMCC6uAJ/pHZkfFgoBTgPtmYlsprAjkxrr2U++ZnB3l5ykBMd2O24lXvf30SMAjJIW6k2aA== +jest-resolve@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.0.1.tgz#21d1ee06f9ea270a343a8893051aeed940cde736" + integrity sha512-6jWxk0IKZkPIVTvq6s72RH735P8f9eCJW3IM5CX/SJFeKq1p2cZx0U49wf/SdMlhaB/anann5J2nCJj6HrbezQ== dependencies: - "@jest/types" "^25.4.0" - browser-resolve "^1.11.3" - chalk "^3.0.0" + "@jest/types" "^26.0.1" + chalk "^4.0.0" + graceful-fs "^4.2.4" jest-pnp-resolver "^1.2.1" + jest-util "^26.0.1" read-pkg-up "^7.0.1" - realpath-native "^2.0.0" - resolve "^1.15.1" + resolve "^1.17.0" slash "^3.0.0" -jest-runner@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-25.4.0.tgz#6ca4a3d52e692bbc081228fa68f750012f1f29e5" - integrity sha512-wWQSbVgj2e/1chFdMRKZdvlmA6p1IPujhpLT7TKNtCSl1B0PGBGvJjCaiBal/twaU2yfk8VKezHWexM8IliBfA== +jest-runner@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.0.1.tgz#ea03584b7ae4bacfb7e533d680a575a49ae35d50" + integrity sha512-CApm0g81b49Znm4cZekYQK67zY7kkB4umOlI2Dx5CwKAzdgw75EN+ozBHRvxBzwo1ZLYZ07TFxkaPm+1t4d8jA== dependencies: - "@jest/console" "^25.4.0" - "@jest/environment" "^25.4.0" - "@jest/test-result" "^25.4.0" - "@jest/types" "^25.4.0" - chalk "^3.0.0" + "@jest/console" "^26.0.1" + "@jest/environment" "^26.0.1" + "@jest/test-result" "^26.0.1" + "@jest/types" "^26.0.1" + chalk "^4.0.0" exit "^0.1.2" - graceful-fs "^4.2.3" - jest-config "^25.4.0" - jest-docblock "^25.3.0" - jest-haste-map "^25.4.0" - jest-jasmine2 "^25.4.0" - jest-leak-detector "^25.4.0" - jest-message-util "^25.4.0" - jest-resolve "^25.4.0" - jest-runtime "^25.4.0" - jest-util "^25.4.0" - jest-worker "^25.4.0" + graceful-fs "^4.2.4" + jest-config "^26.0.1" + jest-docblock "^26.0.0" + jest-haste-map "^26.0.1" + jest-jasmine2 "^26.0.1" + jest-leak-detector "^26.0.1" + jest-message-util "^26.0.1" + jest-resolve "^26.0.1" + jest-runtime "^26.0.1" + jest-util "^26.0.1" + jest-worker "^26.0.0" source-map-support "^0.5.6" throat "^5.0.0" -jest-runtime@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-25.4.0.tgz#1e5227a9e2159d26ae27dcd426ca6bc041983439" - integrity sha512-lgNJlCDULtXu9FumnwCyWlOub8iytijwsPNa30BKrSNtgoT6NUMXOPrZvsH06U6v0wgD/Igwz13nKA2wEKU2VA== - dependencies: - "@jest/console" "^25.4.0" - "@jest/environment" "^25.4.0" - "@jest/source-map" "^25.2.6" - "@jest/test-result" "^25.4.0" - "@jest/transform" "^25.4.0" - "@jest/types" "^25.4.0" +jest-runtime@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.0.1.tgz#a121a6321235987d294168e282d52b364d7d3f89" + integrity sha512-Ci2QhYFmANg5qaXWf78T2Pfo6GtmIBn2rRaLnklRyEucmPccmCKvS9JPljcmtVamsdMmkyNkVFb9pBTD6si9Lw== + dependencies: + "@jest/console" "^26.0.1" + "@jest/environment" "^26.0.1" + "@jest/fake-timers" "^26.0.1" + "@jest/globals" "^26.0.1" + "@jest/source-map" "^26.0.0" + "@jest/test-result" "^26.0.1" + "@jest/transform" "^26.0.1" + "@jest/types" "^26.0.1" "@types/yargs" "^15.0.0" - chalk "^3.0.0" + chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" glob "^7.1.3" - graceful-fs "^4.2.3" - jest-config "^25.4.0" - jest-haste-map "^25.4.0" - jest-message-util "^25.4.0" - jest-mock "^25.4.0" - jest-regex-util "^25.2.6" - jest-resolve "^25.4.0" - jest-snapshot "^25.4.0" - jest-util "^25.4.0" - jest-validate "^25.4.0" - realpath-native "^2.0.0" + graceful-fs "^4.2.4" + jest-config "^26.0.1" + jest-haste-map "^26.0.1" + jest-message-util "^26.0.1" + jest-mock "^26.0.1" + jest-regex-util "^26.0.0" + jest-resolve "^26.0.1" + jest-snapshot "^26.0.1" + jest-util "^26.0.1" + jest-validate "^26.0.1" slash "^3.0.0" strip-bom "^4.0.0" yargs "^15.3.1" @@ -4667,30 +4489,33 @@ jest-serializer@^24.4.0: resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.4.0.tgz#f70c5918c8ea9235ccb1276d232e459080588db3" integrity sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q== -jest-serializer@^25.2.6: - version "25.2.6" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-25.2.6.tgz#3bb4cc14fe0d8358489dbbefbb8a4e708ce039b7" - integrity sha512-RMVCfZsezQS2Ww4kB5HJTMaMJ0asmC0BHlnobQC6yEtxiFKIxohFA4QSXSabKwSggaNkqxn6Z2VwdFCjhUWuiQ== +jest-serializer@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.0.0.tgz#f6c521ddb976943b93e662c0d4d79245abec72a3" + integrity sha512-sQGXLdEGWFAE4wIJ2ZaIDb+ikETlUirEOBsLXdoBbeLhTHkZUJwgk3+M8eyFizhM6le43PDCCKPA1hzkSDo4cQ== + dependencies: + graceful-fs "^4.2.4" -jest-snapshot@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-25.4.0.tgz#e0b26375e2101413fd2ccb4278a5711b1922545c" - integrity sha512-J4CJ0X2SaGheYRZdLz9CRHn9jUknVmlks4UBeu270hPAvdsauFXOhx9SQP2JtRzhnR3cvro/9N9KP83/uvFfRg== +jest-snapshot@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.0.1.tgz#1baa942bd83d47b837a84af7fcf5fd4a236da399" + integrity sha512-jxd+cF7+LL+a80qh6TAnTLUZHyQoWwEHSUFJjkw35u3Gx+BZUNuXhYvDqHXr62UQPnWo2P6fvQlLjsU93UKyxA== dependencies: "@babel/types" "^7.0.0" - "@jest/types" "^25.4.0" - "@types/prettier" "^1.19.0" - chalk "^3.0.0" - expect "^25.4.0" - jest-diff "^25.4.0" - jest-get-type "^25.2.6" - jest-matcher-utils "^25.4.0" - jest-message-util "^25.4.0" - jest-resolve "^25.4.0" + "@jest/types" "^26.0.1" + "@types/prettier" "^2.0.0" + chalk "^4.0.0" + expect "^26.0.1" + graceful-fs "^4.2.4" + jest-diff "^26.0.1" + jest-get-type "^26.0.0" + jest-matcher-utils "^26.0.1" + jest-message-util "^26.0.1" + jest-resolve "^26.0.1" make-dir "^3.0.0" natural-compare "^1.4.0" - pretty-format "^25.4.0" - semver "^6.3.0" + pretty-format "^26.0.1" + semver "^7.3.2" jest-util@^24.8.0: version "24.8.0" @@ -4710,13 +4535,14 @@ jest-util@^24.8.0: slash "^2.0.0" source-map "^0.6.0" -jest-util@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-25.4.0.tgz#6a093d09d86d2b41ef583e5fe7dd3976346e1acd" - integrity sha512-WSZD59sBtAUjLv1hMeKbNZXmMcrLRWcYqpO8Dz8b4CeCTZpfNQw2q9uwrYAD+BbJoLJlu4ezVPwtAmM/9/SlZA== +jest-util@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.0.1.tgz#72c4c51177b695fdd795ca072a6f94e3d7cef00a" + integrity sha512-byQ3n7ad1BO/WyFkYvlWQHTsomB6GIewBh8tlGtusiylAlaxQ1UpS0XYH0ngOyhZuHVLN79Qvl6/pMiDMSSG1g== dependencies: - "@jest/types" "^25.4.0" - chalk "^3.0.0" + "@jest/types" "^26.0.1" + chalk "^4.0.0" + graceful-fs "^4.2.4" is-ci "^2.0.0" make-dir "^3.0.0" @@ -4744,29 +4570,29 @@ jest-validate@^24.9.0: leven "^3.1.0" pretty-format "^24.9.0" -jest-validate@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-25.4.0.tgz#2e177a93b716a137110eaf2768f3d9095abd3f38" - integrity sha512-hvjmes/EFVJSoeP1yOl8qR8mAtMR3ToBkZeXrD/ZS9VxRyWDqQ/E1C5ucMTeSmEOGLipvdlyipiGbHJ+R1MQ0g== +jest-validate@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.0.1.tgz#a62987e1da5b7f724130f904725e22f4e5b2e23c" + integrity sha512-u0xRc+rbmov/VqXnX3DlkxD74rHI/CfS5xaV2VpeaVySjbb1JioNVOyly5b56q2l9ZKe7bVG5qWmjfctkQb0bA== dependencies: - "@jest/types" "^25.4.0" - camelcase "^5.3.1" - chalk "^3.0.0" - jest-get-type "^25.2.6" + "@jest/types" "^26.0.1" + camelcase "^6.0.0" + chalk "^4.0.0" + jest-get-type "^26.0.0" leven "^3.1.0" - pretty-format "^25.4.0" + pretty-format "^26.0.1" -jest-watcher@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-25.4.0.tgz#63ec0cd5c83bb9c9d1ac95be7558dd61c995ff05" - integrity sha512-36IUfOSRELsKLB7k25j/wutx0aVuHFN6wO94gPNjQtQqFPa2rkOymmx9rM5EzbF3XBZZ2oqD9xbRVoYa2w86gw== +jest-watcher@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.0.1.tgz#5b5e3ebbdf10c240e22a98af66d645631afda770" + integrity sha512-pdZPydsS8475f89kGswaNsN3rhP6lnC3/QDCppP7bg1L9JQz7oU9Mb/5xPETk1RHDCWeqmVC47M4K5RR7ejxFw== dependencies: - "@jest/test-result" "^25.4.0" - "@jest/types" "^25.4.0" + "@jest/test-result" "^26.0.1" + "@jest/types" "^26.0.1" ansi-escapes "^4.2.1" - chalk "^3.0.0" - jest-util "^25.4.0" - string-length "^3.1.0" + chalk "^4.0.0" + jest-util "^26.0.1" + string-length "^4.0.1" jest-worker@^24.6.0: version "24.6.0" @@ -4776,22 +4602,22 @@ jest-worker@^24.6.0: merge-stream "^1.0.1" supports-color "^6.1.0" -jest-worker@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.4.0.tgz#ee0e2ceee5a36ecddf5172d6d7e0ab00df157384" - integrity sha512-ghAs/1FtfYpMmYQ0AHqxV62XPvKdUDIBBApMZfly+E9JEmYh2K45G0R5dWxx986RN12pRCxsViwQVtGl+N4whw== +jest-worker@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.0.0.tgz#4920c7714f0a96c6412464718d0c58a3df3fb066" + integrity sha512-pPaYa2+JnwmiZjK9x7p9BoZht+47ecFCDFA/CJxspHzeDvQcfVBLWzCiWyo+EGrSiQMWZtCFo9iSvMZnAAo8vw== dependencies: merge-stream "^2.0.0" supports-color "^7.0.0" -jest@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-25.4.0.tgz#fb96892c5c4e4a6b9bcb12068849cddf4c5f8cc7" - integrity sha512-XWipOheGB4wai5JfCYXd6vwsWNwM/dirjRoZgAa7H2wd8ODWbli2AiKjqG8AYhyx+8+5FBEdpO92VhGlBydzbw== +jest@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest/-/jest-26.0.1.tgz#5c51a2e58dff7525b65f169721767173bf832694" + integrity sha512-29Q54kn5Bm7ZGKIuH2JRmnKl85YRigp0o0asTc6Sb6l2ch1DCXIeZTLLFy9ultJvhkTqbswF5DEx4+RlkmCxWg== dependencies: - "@jest/core" "^25.4.0" + "@jest/core" "^26.0.1" import-local "^3.0.2" - jest-cli "^25.4.0" + jest-cli "^26.0.1" jetifier@^1.6.2: version "1.6.4" @@ -4834,16 +4660,17 @@ jsc-android@^245459.0.0: resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-245459.0.0.tgz#e584258dd0b04c9159a27fb104cd5d491fd202c9" integrity sha512-wkjURqwaB1daNkDi2OYYbsLnIdC/lUM2nPXQKRs5pqEU9chDg435bjvo+LSaHotDENygHQDHe+ntUkkw2gwMtg== -jscodeshift@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.7.0.tgz#4eee7506fd4fdacbd80340287d61575af991fdab" - integrity sha512-Kt6rpTa1HVhAWagD6J0y6qxxqRmDgkFvczerLgOsDNSGoUZSmq2CO1vFRcda9OV1BaZKSHCIh+VREPts5tB/Ig== +jscodeshift@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.9.0.tgz#672025658e868a63e24d6a6f4c44af9edb6e55f3" + integrity sha512-SUeXq8dJzj5LR8uy71axgG3bmiHoC0IdHy7n89SqKzkzBWpAds5F9IIGE+lqUSZX9J0ZfEzN8fXWIqQV0dIp2w== dependencies: "@babel/core" "^7.1.6" "@babel/parser" "^7.1.6" "@babel/plugin-proposal-class-properties" "^7.1.0" - "@babel/plugin-proposal-object-rest-spread" "^7.0.0" - "@babel/preset-env" "^7.1.6" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.1.0" + "@babel/plugin-proposal-optional-chaining" "^7.1.0" + "@babel/plugin-transform-modules-commonjs" "^7.1.0" "@babel/preset-flow" "^7.0.0" "@babel/preset-typescript" "^7.1.0" "@babel/register" "^7.0.0" @@ -4858,36 +4685,36 @@ jscodeshift@^0.7.0: temp "^0.8.1" write-file-atomic "^2.3.0" -jsdom@^15.2.1: - version "15.2.1" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-15.2.1.tgz#d2feb1aef7183f86be521b8c6833ff5296d07ec5" - integrity sha512-fAl1W0/7T2G5vURSyxBzrJ1LSdQn6Tr5UX/xD4PXDx/PDgwygedfW6El/KIj3xJ7FU61TTYnc/l/B7P49Eqt6g== - dependencies: - abab "^2.0.0" - acorn "^7.1.0" - acorn-globals "^4.3.2" - array-equal "^1.0.0" - cssom "^0.4.1" - cssstyle "^2.0.0" - data-urls "^1.1.0" - domexception "^1.0.1" - escodegen "^1.11.1" - html-encoding-sniffer "^1.0.2" +jsdom@^16.2.2: + version "16.2.2" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.2.2.tgz#76f2f7541646beb46a938f5dc476b88705bedf2b" + integrity sha512-pDFQbcYtKBHxRaP55zGXCJWgFHkDAYbKcsXEK/3Icu9nKYZkutUXfLBwbD+09XDutkYSHcgfQLZ0qvpAAm9mvg== + dependencies: + abab "^2.0.3" + acorn "^7.1.1" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.2.0" + data-urls "^2.0.0" + decimal.js "^10.2.0" + domexception "^2.0.1" + escodegen "^1.14.1" + html-encoding-sniffer "^2.0.1" + is-potential-custom-element-name "^1.0.0" nwsapi "^2.2.0" - parse5 "5.1.0" - pn "^1.1.0" - request "^2.88.0" - request-promise-native "^1.0.7" - saxes "^3.1.9" - symbol-tree "^3.2.2" + parse5 "5.1.1" + request "^2.88.2" + request-promise-native "^1.0.8" + saxes "^5.0.0" + symbol-tree "^3.2.4" tough-cookie "^3.0.1" - w3c-hr-time "^1.0.1" - w3c-xmlserializer "^1.1.2" - webidl-conversions "^4.0.2" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.0.0" whatwg-encoding "^1.0.5" whatwg-mimetype "^2.3.0" - whatwg-url "^7.0.0" - ws "^7.0.0" + whatwg-url "^8.0.0" + ws "^7.2.3" xml-name-validator "^3.0.0" jsesc@^2.5.1: @@ -5043,13 +4870,6 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levenary@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" - integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== - dependencies: - leven "^3.1.0" - levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -5063,14 +4883,6 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -5127,13 +4939,6 @@ logkitty@^0.7.1: dayjs "^1.8.15" yargs "^15.1.0" -lolex@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-5.1.2.tgz#953694d098ce7c07bc5ed6d0e42bc6c0c6d5a367" - integrity sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A== - dependencies: - "@sinonjs/commons" "^1.7.0" - loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -5788,16 +5593,17 @@ node-modules-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= -node-notifier@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-6.0.0.tgz#cea319e06baa16deec8ce5cd7f133c4a46b68e12" - integrity sha512-SVfQ/wMw+DesunOm5cKqr6yDcvUTDl/yc97ybGHMrteNEY6oekXpNpS3lZwgLlwz0FLgHoiW28ZpmBHUDg37cw== +node-notifier@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-7.0.0.tgz#513bc42f2aa3a49fce1980a7ff375957c71f718a" + integrity sha512-y8ThJESxsHcak81PGpzWwQKxzk+5YtP3IxR8AYdpXQ1IB6FmcVzFdZXrkPin49F/DKUCfeeiziB8ptY9npzGuA== dependencies: growly "^1.3.0" is-wsl "^2.1.1" - semver "^6.3.0" + semver "^7.2.1" shellwords "^0.1.1" - which "^1.3.1" + uuid "^7.0.3" + which "^2.0.2" node-pre-gyp@^0.10.0: version "0.10.3" @@ -5815,11 +5621,6 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" -node-releases@^1.1.53: - version "1.1.53" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4" - integrity sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ== - node-stream-zip@^1.9.1: version "1.11.3" resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.11.3.tgz#223892620b4889bce9782b256a76682631c507be" @@ -6096,23 +5897,11 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= -p-finally@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" - integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== - p-is-promise@^1.1.0: version "1.1.0" resolved "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4= -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - p-limit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec" @@ -6127,13 +5916,6 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -6148,11 +5930,6 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - p-try@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" @@ -6176,10 +5953,10 @@ parse-json@^5.0.0: json-parse-better-errors "^1.0.1" lines-and-columns "^1.1.6" -parse5@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" - integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== +parse5@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" + integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== parseurl@~1.3.2: version "1.3.2" @@ -6281,13 +6058,6 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" - integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= - dependencies: - find-up "^2.1.0" - plist@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.1.tgz#a9b931d17c304e8912ef0ba3bdd6182baf2e1f8c" @@ -6313,11 +6083,6 @@ pluralize@^7.0.0: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== -pn@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" - integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== - posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -6373,12 +6138,12 @@ pretty-format@^25.2.0: ansi-styles "^4.0.0" react-is "^16.12.0" -pretty-format@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.4.0.tgz#c58801bb5c4926ff4a677fe43f9b8b99812c7830" - integrity sha512-PI/2dpGjXK5HyXexLPZU/jw5T9Q6S1YVXxxVxco+LIqzUFHXIbKZKdUVt7GcX7QUCr31+3fzhi4gN4/wUYPVxQ== +pretty-format@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.0.1.tgz#a4fe54fe428ad2fd3413ca6bbd1ec8c2e277e197" + integrity sha512-SWxz6MbupT3ZSlL0Po4WF/KujhQaVehijR2blyRDCzk9e45EaYMVhMBn49fnRuHxtkSpXTes1GxNpVmH86Bxfw== dependencies: - "@jest/types" "^25.4.0" + "@jest/types" "^26.0.1" ansi-regex "^5.0.0" ansi-styles "^4.0.0" react-is "^16.12.0" @@ -6582,11 +6347,6 @@ readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@^2.1.5, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -realpath-native@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-2.0.0.tgz#7377ac429b6e1fd599dc38d08ed942d0d7beb866" - integrity sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q== - recast@^0.18.1: version "0.18.7" resolved "https://registry.yarnpkg.com/recast/-/recast-0.18.7.tgz#56338a6d803c8c3b9113344440dc70d13c8a1ef7" @@ -6700,7 +6460,7 @@ request-promise-core@1.1.3: dependencies: lodash "^4.17.15" -request-promise-native@^1.0.7: +request-promise-native@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== @@ -6735,7 +6495,7 @@ request@^2.85.0: tunnel-agent "^0.6.0" uuid "^3.3.2" -request@^2.88.0: +request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -6806,18 +6566,20 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= - -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.15.1, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1, resolve@^1.9.0: +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1, resolve@^1.9.0: version "1.15.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== dependencies: path-parse "^1.0.6" +resolve@^1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -6949,12 +6711,12 @@ sax@^1.2.1, sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -saxes@^3.1.9: - version "3.1.11" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.11.tgz#d59d1fd332ec92ad98a2e0b2ee644702384b1c5b" - integrity sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g== +saxes@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== dependencies: - xmlchars "^2.1.1" + xmlchars "^2.2.0" scheduler@0.19.1, scheduler@^0.19.1: version "0.19.1" @@ -6969,11 +6731,6 @@ scheduler@0.19.1, scheduler@^0.19.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1: version "5.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" @@ -6984,6 +6741,11 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.2.1, semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" @@ -7298,6 +7060,13 @@ stack-utils@^1.0.1: resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620" integrity sha1-1PM6tU6OOHeLDKXP07OvsS22hiA= +stack-utils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.2.tgz#5cf48b4557becb4638d0bc4f21d23f5d19586593" + integrity sha512-0H7QK2ECz3fyZMzQ8rH0j2ykpfbnd20BFtfg/SqVC2+sCTtcw0aDTGB7dk+de4U4uUeuz6nOtJcrkFFLG1B0Rg== + dependencies: + escape-string-regexp "^2.0.0" + stacktrace-parser@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.4.tgz#01397922e5f62ecf30845522c95c4fe1d25e7d4e" @@ -7336,13 +7105,13 @@ stream-buffers@~2.2.0: resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4" integrity sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ= -string-length@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-3.1.0.tgz#107ef8c23456e187a8abd4a61162ff4ac6e25837" - integrity sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA== +string-length@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.1.tgz#4a973bf31ef77c4edbceadd6af2611996985f8a1" + integrity sha512-PKyXUd0LK0ePjSOnWn34V2uD6acUWev9uy0Ft05k0E8xRW+SKcA0F7eMr7h5xlzfn+4O3N+55rduYyet3Jk+jw== dependencies: - astral-regex "^1.0.0" - strip-ansi "^5.2.0" + char-regex "^1.0.2" + strip-ansi "^6.0.0" string-width@^1.0.1: version "1.0.2" @@ -7496,10 +7265,10 @@ symbol-observable@1.0.1: resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" integrity sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ= -symbol-tree@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" - integrity sha1-rifbOPZgp64uHDt9G8KQgZuFGeY= +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== table@^4.0.3: version "4.0.3" @@ -7691,12 +7460,12 @@ tough-cookie@~2.4.3: psl "^1.1.24" punycode "^1.4.1" -tr46@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" - integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= +tr46@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.0.2.tgz#03273586def1595ae08fedb38d7733cee91d2479" + integrity sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg== dependencies: - punycode "^2.1.0" + punycode "^2.1.1" truncate-utf8-bytes@^1.0.0: version "1.0.2" @@ -7877,6 +7646,11 @@ uuid@^3.3.3: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" + integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== + v8-to-istanbul@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-4.1.3.tgz#22fe35709a64955f49a08a7c7c959f6520ad6f20" @@ -7918,20 +7692,18 @@ vlq@^1.0.0: resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.1.tgz#c003f6e7c0b4c1edd623fd6ee50bbc0d6a1de468" integrity sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w== -w3c-hr-time@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" - integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU= +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== dependencies: - browser-process-hrtime "^0.1.2" + browser-process-hrtime "^1.0.0" -w3c-xmlserializer@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz#30485ca7d70a6fd052420a3d12fd90e6339ce794" - integrity sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg== +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== dependencies: - domexception "^1.0.1" - webidl-conversions "^4.0.2" xml-name-validator "^3.0.0" walker@^1.0.7, walker@~1.0.5: @@ -7948,12 +7720,17 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" -webidl-conversions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" - integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== -whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.5: +webidl-conversions@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + +whatwg-encoding@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== @@ -7965,19 +7742,19 @@ whatwg-fetch@>=0.10.0, whatwg-fetch@^3.0.0: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== -whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0: +whatwg-mimetype@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== -whatwg-url@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.0.0.tgz#fde926fa54a599f3adf82dff25a9f7be02dc6edd" - integrity sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ== +whatwg-url@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.0.0.tgz#37f256cb746398e19b107bd6ef820b4ae2d15871" + integrity sha512-41ou2Dugpij8/LPO5Pq64K5q++MnRCBpEHvQr26/mArEKTkCV5aoXIqyhuYtE0pkqScXwhf2JP57rkRTYM29lQ== dependencies: lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" + tr46 "^2.0.0" + webidl-conversions "^5.0.0" which-module@^2.0.0: version "2.0.0" @@ -8107,10 +7884,10 @@ ws@^7: dependencies: async-limiter "^1.0.0" -ws@^7.0.0: - version "7.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.3.tgz#a5411e1fb04d5ed0efee76d26d5c46d830c39b46" - integrity sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ== +ws@^7.2.3: + version "7.2.5" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.5.tgz#abb1370d4626a5a9cd79d8de404aa18b3465d10d" + integrity sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA== xcode@^2.0.0: version "2.0.0" @@ -8135,7 +7912,7 @@ xmlbuilder@^9.0.7: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= -xmlchars@^2.1.1: +xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==