+ `); + }); + + it('renders styles', () => { + const style = { + display: 'flex', + flex: 1, + backgroundColor: 'white', + marginInlineStart: 10, + userSelect: 'none', + verticalAlign: 'middle', + }; + + const instance = ReactTestRenderer.create(); + + expect(instance.toJSON()).toMatchInlineSnapshot(` + + `); + }); +}); diff --git a/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap b/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap index ea3b4c1f0627..ac93dc2e644c 100644 --- a/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap +++ b/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap @@ -2,15 +2,6 @@ exports[`TextInput tests should render as expected: should deep render when mocked (please verify output manually) 1`] = ` `; -exports[`TextInput tests should render as expected: should shallow render as when mocked 1`] = ``; +exports[`TextInput tests should render as expected: should shallow render as when mocked 1`] = ``; -exports[`TextInput tests should render as expected: should shallow render as when not mocked 1`] = ``; +exports[`TextInput tests should render as expected: should shallow render as when not mocked 1`] = ``; diff --git a/Libraries/Components/Touchable/TouchableOpacity.js b/Libraries/Components/Touchable/TouchableOpacity.js index 2aef4e824f10..cc18e8ecd0db 100644 --- a/Libraries/Components/Touchable/TouchableOpacity.js +++ b/Libraries/Components/Touchable/TouchableOpacity.js @@ -301,9 +301,8 @@ class TouchableOpacity extends React.Component { this.state.pressability.configure(this._createPressabilityConfig()); if ( this.props.disabled !== prevProps.disabled || - (flattenStyle(prevProps.style)?.opacity !== - flattenStyle(this.props.style)?.opacity) !== - undefined + flattenStyle(prevProps.style)?.opacity !== + flattenStyle(this.props.style)?.opacity ) { this._opacityInactive(250); } diff --git a/Libraries/Components/Touchable/TouchableWithoutFeedback.d.ts b/Libraries/Components/Touchable/TouchableWithoutFeedback.d.ts index a6f3316d36be..aa5e14b7e270 100644 --- a/Libraries/Components/Touchable/TouchableWithoutFeedback.d.ts +++ b/Libraries/Components/Touchable/TouchableWithoutFeedback.d.ts @@ -69,7 +69,7 @@ export interface TouchableWithoutFeedbackProps * the Z-index of sibling views always takes precedence if a touch hits * two overlapping views. */ - hitSlop?: Insets | undefined; + hitSlop?: null | Insets | number | undefined; /** * Used to reference react managed views from native code. @@ -121,7 +121,7 @@ export interface TouchableWithoutFeedbackProps * while the scroll view is disabled. Ensure you pass in a constant * to reduce memory allocations. */ - pressRetentionOffset?: Insets | undefined; + pressRetentionOffset?: null | Insets | number | undefined; /** * Used to locate this view in end-to-end tests. diff --git a/Libraries/Components/Touchable/TouchableWithoutFeedback.js b/Libraries/Components/Touchable/TouchableWithoutFeedback.js index 70b43370b11f..364fc5220ebf 100755 --- a/Libraries/Components/Touchable/TouchableWithoutFeedback.js +++ b/Libraries/Components/Touchable/TouchableWithoutFeedback.js @@ -15,7 +15,7 @@ import type { AccessibilityState, AccessibilityValue, } from '../../Components/View/ViewAccessibility'; -import type {EdgeInsetsProp} from '../../StyleSheet/EdgeInsetsPropType'; +import type {EdgeInsetsOrSizeProp} from '../../StyleSheet/EdgeInsetsPropType'; import type { BlurEvent, FocusEvent, @@ -67,7 +67,7 @@ type Props = $ReadOnly<{| delayPressOut?: ?number, disabled?: ?boolean, focusable?: ?boolean, - hitSlop?: ?EdgeInsetsProp, + hitSlop?: ?EdgeInsetsOrSizeProp, id?: string, importantForAccessibility?: ?('auto' | 'yes' | 'no' | 'no-hide-descendants'), nativeID?: ?string, @@ -79,7 +79,7 @@ type Props = $ReadOnly<{| onPress?: ?(event: PressEvent) => mixed, onPressIn?: ?(event: PressEvent) => mixed, onPressOut?: ?(event: PressEvent) => mixed, - pressRetentionOffset?: ?EdgeInsetsProp, + pressRetentionOffset?: ?EdgeInsetsOrSizeProp, rejectResponderTermination?: ?boolean, testID?: ?string, touchSoundDisabled?: ?boolean, diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index 8ef1f814a312..86540410c83b 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -57,7 +57,6 @@ const View: React.AbstractComponent< nativeID, pointerEvents, role, - style, tabIndex, ...otherProps }: ViewProps, @@ -66,23 +65,42 @@ const View: React.AbstractComponent< const _accessibilityLabelledBy = ariaLabelledBy?.split(/\s*,\s*/g) ?? accessibilityLabelledBy; - const _accessibilityState = { - busy: ariaBusy ?? accessibilityState?.busy, - checked: ariaChecked ?? accessibilityState?.checked, - disabled: ariaDisabled ?? accessibilityState?.disabled, - expanded: ariaExpanded ?? accessibilityState?.expanded, - selected: ariaSelected ?? accessibilityState?.selected, - }; + let _accessibilityState; + if ( + accessibilityState != null || + ariaBusy != null || + ariaChecked != null || + ariaDisabled != null || + ariaExpanded != null || + ariaSelected != null + ) { + _accessibilityState = { + busy: ariaBusy ?? accessibilityState?.busy, + checked: ariaChecked ?? accessibilityState?.checked, + disabled: ariaDisabled ?? accessibilityState?.disabled, + expanded: ariaExpanded ?? accessibilityState?.expanded, + selected: ariaSelected ?? accessibilityState?.selected, + }; + } + let _accessibilityValue; + if ( + accessibilityValue != null || + ariaValueMax != null || + ariaValueMin != null || + ariaValueNow != null || + ariaValueText != null + ) { + _accessibilityValue = { + max: ariaValueMax ?? accessibilityValue?.max, + min: ariaValueMin ?? accessibilityValue?.min, + now: ariaValueNow ?? accessibilityValue?.now, + text: ariaValueText ?? accessibilityValue?.text, + }; + } - const _accessibilityValue = { - max: ariaValueMax ?? accessibilityValue?.max, - min: ariaValueMin ?? accessibilityValue?.min, - now: ariaValueNow ?? accessibilityValue?.now, - text: ariaValueText ?? accessibilityValue?.text, - }; + let style = flattenStyle(otherProps.style); - const flattenedStyle = flattenStyle(style); - const newPointerEvents = flattenedStyle?.pointerEvents || pointerEvents; + const newPointerEvents = style?.pointerEvents || pointerEvents; return ( diff --git a/Libraries/Components/View/ViewAccessibility.d.ts b/Libraries/Components/View/ViewAccessibility.d.ts index c68c758410c8..b06d1cbd4504 100644 --- a/Libraries/Components/View/ViewAccessibility.d.ts +++ b/Libraries/Components/View/ViewAccessibility.d.ts @@ -251,6 +251,12 @@ export interface AccessibilityPropsAndroid { | 'no' | 'no-hide-descendants' | undefined; + + /** + * A reference to another element `nativeID` used to build complex forms. The value of `accessibilityLabelledBy` should match the `nativeID` of the related element. + * @platform android + */ + accessibilityLabelledBy?: string | string[] | undefined; } export interface AccessibilityPropsIOS { @@ -290,6 +296,13 @@ export interface AccessibilityPropsIOS { * @platform ios */ accessibilityIgnoresInvertColors?: boolean | undefined; + + /** + * By using the accessibilityLanguage property, the screen reader will understand which language to use while reading the element's label, value and hint. The provided string value must follow the BCP 47 specification (https://www.rfc-editor.org/info/bcp47). + * https://reactnative.dev/docs/accessibility#accessibilitylanguage-ios + * @platform ios + */ + accessibilityLanguage?: string | undefined; } export type Role = diff --git a/Libraries/Components/View/__tests__/View-test.js b/Libraries/Components/View/__tests__/View-test.js new file mode 100644 index 000000000000..78e547a67331 --- /dev/null +++ b/Libraries/Components/View/__tests__/View-test.js @@ -0,0 +1,193 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @emails oncall+react_native + */ + +'use strict'; + +const render = require('../../../../jest/renderer'); +const React = require('../React'); +const View = require('../View'); + +jest.unmock('../View'); +jest.unmock('../ViewNativeComponent'); + +describe('View', () => { + it('default render', () => { + const instance = render.create(); + + expect(instance.toJSON()).toMatchInlineSnapshot(``); + }); + + it('has displayName', () => { + expect(View.displayName).toEqual('View'); + }); +}); + +describe('View compat with web', () => { + it('renders core props', () => { + const props = { + id: 'id', + tabIndex: 0, + testID: 'testID', + }; + + const instance = render.create(); + + expect(instance.toJSON()).toMatchInlineSnapshot(` + + `); + }); + + it('renders "aria-*" props', () => { + const props = { + 'aria-activedescendant': 'activedescendant', + 'aria-atomic': true, + 'aria-autocomplete': 'list', + 'aria-busy': true, + 'aria-checked': true, + 'aria-columncount': 5, + 'aria-columnindex': 3, + 'aria-columnspan': 2, + 'aria-controls': 'controls', + 'aria-current': 'current', + 'aria-describedby': 'describedby', + 'aria-details': 'details', + 'aria-disabled': true, + 'aria-errormessage': 'errormessage', + 'aria-expanded': true, + 'aria-flowto': 'flowto', + 'aria-haspopup': true, + 'aria-hidden': true, + 'aria-invalid': true, + 'aria-keyshortcuts': 'Cmd+S', + 'aria-label': 'label', + 'aria-labelledby': 'labelledby', + 'aria-level': 3, + 'aria-live': 'polite', + 'aria-modal': true, + 'aria-multiline': true, + 'aria-multiselectable': true, + 'aria-orientation': 'portrait', + 'aria-owns': 'owns', + 'aria-placeholder': 'placeholder', + 'aria-posinset': 5, + 'aria-pressed': true, + 'aria-readonly': true, + 'aria-required': true, + role: 'main', + 'aria-roledescription': 'roledescription', + 'aria-rowcount': 5, + 'aria-rowindex': 3, + 'aria-rowspan': 3, + 'aria-selected': true, + 'aria-setsize': 5, + 'aria-sort': 'ascending', + 'aria-valuemax': 5, + 'aria-valuemin': 0, + 'aria-valuenow': 3, + 'aria-valuetext': '3', + }; + + const instance = render.create(); + + expect(instance.toJSON()).toMatchInlineSnapshot(` + + `); + }); + + it('renders styles', () => { + const style = { + display: 'flex', + flex: 1, + backgroundColor: 'white', + marginInlineStart: 10, + pointerEvents: 'none', + }; + + const instance = render.create(); + + expect(instance.toJSON()).toMatchInlineSnapshot(` + + `); + }); +}); diff --git a/Libraries/Core/ReactNativeVersion.js b/Libraries/Core/ReactNativeVersion.js index ac66c1db28f9..b2d6230b5c8a 100644 --- a/Libraries/Core/ReactNativeVersion.js +++ b/Libraries/Core/ReactNativeVersion.js @@ -12,6 +12,6 @@ exports.version = { major: 0, minor: 71, - patch: 0, - prerelease: 'rc.1', + patch: 17, + prerelease: null, }; diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index f874c6abc93f..ca219faa8069 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -158,13 +158,13 @@ const BaseImage = (props: ImagePropsType, forwardedRef) => { const {width = props.width, height = props.height, uri} = source; style = flattenStyle([{width, height}, styles.base, props.style]); sources = [source]; - if (uri === '') { console.warn('source.uri should not be an empty string'); } } const {height, width, ...restProps} = props; + const {onLoadStart, onLoad, onLoadEnd, onError} = props; const nativeProps = { ...restProps, diff --git a/Libraries/Image/ImageSource.js b/Libraries/Image/ImageSource.js index 20966d581660..bbb32572125c 100644 --- a/Libraries/Image/ImageSource.js +++ b/Libraries/Image/ImageSource.js @@ -11,8 +11,6 @@ 'use strict'; /** - * Keep this in sync with `DeprecatedImageSourcePropType.js`. - * * This type is intentionally inexact in order to permit call sites that supply * extra properties. */ diff --git a/Libraries/Lists/FlatList.d.ts b/Libraries/Lists/FlatList.d.ts index 0cb4302f1ee0..4f60e18c4daa 100644 --- a/Libraries/Lists/FlatList.d.ts +++ b/Libraries/Lists/FlatList.d.ts @@ -14,53 +14,11 @@ import type { VirtualizedListProps, } from './VirtualizedList'; import type {ScrollViewComponent} from '../Components/ScrollView/ScrollView'; -import {StyleProp} from '../StyleSheet/StyleSheet'; -import {ViewStyle} from '../StyleSheet/StyleSheetTypes'; -import {View} from '../Components/View/View'; +import type {StyleProp} from '../StyleSheet/StyleSheet'; +import type {ViewStyle} from '../StyleSheet/StyleSheetTypes'; +import type {View} from '../Components/View/View'; export interface FlatListProps extends VirtualizedListProps { - /** - * Rendered in between each item, but not at the top or bottom - */ - ItemSeparatorComponent?: React.ComponentType | null | undefined; - - /** - * Rendered when the list is empty. - */ - ListEmptyComponent?: - | React.ComponentType - | React.ReactElement - | null - | undefined; - - /** - * Rendered at the very end of the list. - */ - ListFooterComponent?: - | React.ComponentType - | React.ReactElement - | null - | undefined; - - /** - * Styling for internal View for ListFooterComponent - */ - ListFooterComponentStyle?: StyleProp | undefined; - - /** - * Rendered at the very beginning of the list. - */ - ListHeaderComponent?: - | React.ComponentType - | React.ReactElement - | null - | undefined; - - /** - * Styling for internal View for ListHeaderComponent - */ - ListHeaderComponentStyle?: StyleProp | undefined; - /** * Optional custom style for multi-item rows generated when numColumns > 1 */ @@ -82,10 +40,10 @@ export interface FlatListProps extends VirtualizedListProps { | undefined; /** - * For simplicity, data is just a plain array. If you want to use something else, - * like an immutable list, use the underlying VirtualizedList directly. + * An array (or array-like list) of items to render. Other data types can be + * used by targetting VirtualizedList directly. */ - data: ReadonlyArray | null | undefined; + data: ArrayLike | null | undefined; /** * A marker property for telling the list to re-render (since it implements PureComponent). @@ -248,6 +206,7 @@ export class FlatList extends React.Component< scrollToItem: (params: { animated?: boolean | null | undefined; item: ItemT; + viewOffset?: number | undefined; viewPosition?: number | undefined; }) => void; diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index 3da7714a670b..9b280f237cfb 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -30,10 +30,10 @@ const React = require('react'); type RequiredProps = {| /** - * For simplicity, data is just a plain array. If you want to use something else, like an - * immutable list, use the underlying `VirtualizedList` directly. + * An array (or array-like list) of items to render. Other data types can be + * used by targetting VirtualizedList directly. */ - data: ?$ReadOnlyArray, + data: ?$ArrayLike, |}; type OptionalProps = {| /** @@ -163,6 +163,11 @@ function numColumnsOrDefault(numColumns: ?number) { return numColumns ?? 1; } +function isArrayLike(data: mixed): boolean { + // $FlowExpectedError[incompatible-use] + return typeof Object(data).length === 'number'; +} + type FlatListProps = {| ...RequiredProps, ...OptionalProps, @@ -334,6 +339,7 @@ class FlatList extends React.PureComponent, void> { scrollToItem(params: { animated?: ?boolean, item: ItemT, + viewOffset?: number, viewPosition?: number, ... }) { @@ -496,8 +502,10 @@ class FlatList extends React.PureComponent, void> { ); } - // $FlowFixMe[missing-local-annot] - _getItem = (data: Array, index: number) => { + _getItem = ( + data: $ArrayLike, + index: number, + ): ?(ItemT | $ReadOnlyArray) => { const numColumns = numColumnsOrDefault(this.props.numColumns); if (numColumns > 1) { const ret = []; @@ -514,8 +522,14 @@ class FlatList extends React.PureComponent, void> { } }; - _getItemCount = (data: ?Array): number => { - if (Array.isArray(data)) { + _getItemCount = (data: ?$ArrayLike): number => { + // Legacy behavior of FlatList was to forward "undefined" length if invalid + // data like a non-arraylike object is passed. VirtualizedList would then + // coerce this, and the math would work out to no-op. For compatibility, if + // invalid data is passed, we tell VirtualizedList there are zero items + // available to prevent it from trying to read from the invalid data + // (without propagating invalidly typed data). + if (data != null && isArrayLike(data)) { const numColumns = numColumnsOrDefault(this.props.numColumns); return numColumns > 1 ? Math.ceil(data.length / numColumns) : data.length; } else { diff --git a/Libraries/Lists/SectionList.d.ts b/Libraries/Lists/SectionList.d.ts index 48c24b1a60f9..ae1b10df46a1 100644 --- a/Libraries/Lists/SectionList.d.ts +++ b/Libraries/Lists/SectionList.d.ts @@ -61,48 +61,6 @@ export type SectionListRenderItem = ( export interface SectionListProps extends VirtualizedListWithoutRenderItemProps { - /** - * Rendered in between adjacent Items within each section. - */ - ItemSeparatorComponent?: React.ComponentType | null | undefined; - - /** - * Rendered when the list is empty. - */ - ListEmptyComponent?: - | React.ComponentType - | React.ReactElement - | null - | undefined; - - /** - * Rendered at the very end of the list. - */ - ListFooterComponent?: - | React.ComponentType - | React.ReactElement - | null - | undefined; - - /** - * Styling for internal View for ListFooterComponent - */ - ListFooterComponentStyle?: StyleProp | undefined | null; - - /** - * Rendered at the very beginning of the list. - */ - ListHeaderComponent?: - | React.ComponentType - | React.ReactElement - | null - | undefined; - - /** - * Styling for internal View for ListHeaderComponent - */ - ListHeaderComponentStyle?: StyleProp | undefined | null; - /** * Rendered in between each section. */ diff --git a/Libraries/Lists/VirtualizedList.d.ts b/Libraries/Lists/VirtualizedList.d.ts index 29c040a236ca..eaef385999f5 100644 --- a/Libraries/Lists/VirtualizedList.d.ts +++ b/Libraries/Lists/VirtualizedList.d.ts @@ -9,7 +9,14 @@ import type * as React from 'react'; import type {LayoutChangeEvent} from '../../types'; -import type {ScrollViewProps} from '../Components/ScrollView/ScrollView'; +import {StyleProp} from '../StyleSheet/StyleSheet'; +import {ViewStyle} from '../StyleSheet/StyleSheetTypes'; +import type { + ScrollResponderMixin, + ScrollView, + ScrollViewProps, +} from '../Components/ScrollView/ScrollView'; +import type {View} from '../Components/View/View'; export interface ViewToken { item: any; @@ -96,6 +103,7 @@ export class VirtualizedList extends React.Component< scrollToItem: (params: { animated?: boolean | undefined; item: ItemT; + viewOffset?: number | undefined; viewPosition?: number | undefined; }) => void; @@ -111,6 +119,13 @@ export class VirtualizedList extends React.Component< }) => void; recordInteraction: () => void; + + getScrollRef: () => + | React.ElementRef + | React.ElementRef + | null; + + getScrollResponder: () => ScrollResponderMixin | null; } /** @@ -124,6 +139,11 @@ export interface VirtualizedListProps export interface VirtualizedListWithoutRenderItemProps extends ScrollViewProps { + /** + * Rendered in between each item, but not at the top or bottom + */ + ItemSeparatorComponent?: React.ComponentType | null | undefined; + /** * Rendered when the list is empty. Can be a React Component Class, a render function, or * a rendered element. @@ -144,6 +164,11 @@ export interface VirtualizedListWithoutRenderItemProps | null | undefined; + /** + * Styling for internal View for ListFooterComponent + */ + ListFooterComponentStyle?: StyleProp | undefined; + /** * Rendered at the top of all the items. Can be a React Component Class, a render function, or * a rendered element. @@ -154,6 +179,11 @@ export interface VirtualizedListWithoutRenderItemProps | null | undefined; + /** + * Styling for internal View for ListHeaderComponent + */ + ListHeaderComponentStyle?: StyleProp | undefined; + /** * The default accessor functions assume this is an Array<{key: string}> but you can override * getItem, getItemCount, and keyExtractor to handle any type of index-based data. diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 4e46e1458c3f..453433029fa9 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -157,6 +157,9 @@ export default class VirtualizedList extends StateSafePureComponent< scrollToEnd(params?: ?{animated?: ?boolean, ...}) { const animated = params ? params.animated : true; const veryLast = this.props.getItemCount(this.props.data) - 1; + if (veryLast < 0) { + return; + } const frame = this.__getFrameMetricsApprox(veryLast, this.props); const offset = Math.max( 0, @@ -263,6 +266,7 @@ export default class VirtualizedList extends StateSafePureComponent< scrollToItem(params: { animated?: ?boolean, item: Item, + viewOffset?: number, viewPosition?: number, ... }) { @@ -859,16 +863,19 @@ export default class VirtualizedList extends StateSafePureComponent< )): any); cells.push( - React.cloneElement(element, { - key: '$empty', - onLayout: event => { - this._onLayoutEmpty(event); - if (element.props.onLayout) { - element.props.onLayout(event); - } - }, - style: StyleSheet.compose(inversionStyle, element.props.style), - }), + + {React.cloneElement(element, { + onLayout: (event: LayoutEvent) => { + this._onLayoutEmpty(event); + if (element.props.onLayout) { + element.props.onLayout(event); + } + }, + style: StyleSheet.compose(inversionStyle, element.props.style), + })} + , ); } diff --git a/Libraries/Lists/__tests__/FlatList-test.js b/Libraries/Lists/__tests__/FlatList-test.js index bc7c9d1faf16..e9f9197b2c50 100644 --- a/Libraries/Lists/__tests__/FlatList-test.js +++ b/Libraries/Lists/__tests__/FlatList-test.js @@ -182,4 +182,29 @@ describe('FlatList', () => { expect(renderItemInThreeColumns).toHaveBeenCalledTimes(7); }); + it('renders array-like data', () => { + const arrayLike = { + length: 3, + 0: {key: 'i1'}, + 1: {key: 'i2'}, + 2: {key: 'i3'}, + }; + + const component = ReactTestRenderer.create( + } + />, + ); + expect(component).toMatchSnapshot(); + }); + it('ignores invalid data', () => { + const component = ReactTestRenderer.create( + } + />, + ); + expect(component).toMatchSnapshot(); + }); }); diff --git a/Libraries/Lists/__tests__/VirtualizedList-test.js b/Libraries/Lists/__tests__/VirtualizedList-test.js index 969d72b90142..9852a62987f6 100644 --- a/Libraries/Lists/__tests__/VirtualizedList-test.js +++ b/Libraries/Lists/__tests__/VirtualizedList-test.js @@ -137,6 +137,20 @@ describe('VirtualizedList', () => { expect(component).toMatchSnapshot(); }); + it('scrollToEnd works with null list', () => { + const listRef = React.createRef(null); + ReactTestRenderer.create( + } + getItem={(data, index) => data[index]} + getItemCount={data => 0} + ref={listRef} + />, + ); + listRef.current.scrollToEnd(); + }); + it('renders empty list with empty component', () => { const component = ReactTestRenderer.create( { expect(component).toMatchSnapshot(); }); + it('handles nested list in ListEmptyComponent', () => { + const ListEmptyComponent = ( + + ); + + let component; + + ReactTestRenderer.act(() => { + component = ReactTestRenderer.create( + , + ); + }); + + ReactTestRenderer.act(() => { + component.update( + , + ); + }); + }); + it('returns the viewableItems correctly in the onViewableItemsChanged callback after changing the data', () => { const ITEM_HEIGHT = 800; let data = [{key: 'i1'}, {key: 'i2'}, {key: 'i3'}]; diff --git a/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap index 03e7c9533385..2fec3a235fb1 100644 --- a/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap @@ -1,5 +1,63 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`FlatList ignores invalid data 1`] = ` + + + +`; + exports[`FlatList renders all the bells and whistles 1`] = ` `; +exports[`FlatList renders array-like data 1`] = ` + + + + + + + + + + + + + +`; + exports[`FlatList renders empty list 1`] = ` ; export type Observer = ( @@ -154,7 +155,7 @@ function appendNewLog(newLog: LogBoxLog) { if (newLog.level === 'fatal') { // If possible, to avoid jank, we don't want to open the error before // it's symbolicated. To do that, we optimistically wait for - // sybolication for up to a second before adding the log. + // symbolication for up to a second before adding the log. const OPTIMISTIC_WAIT_TIME = 1000; let addPendingLog: ?() => void = () => { @@ -198,7 +199,7 @@ export function addLog(log: LogData): void { // otherwise spammy logs would pause rendering. setImmediate(() => { try { - const stack = parseErrorStack(errorForStackTrace?.stack); + const stack = parseErrorStack(log.stack ?? errorForStackTrace?.stack); appendNewLog( new LogBoxLog({ diff --git a/Libraries/LogBox/Data/parseLogBoxLog.js b/Libraries/LogBox/Data/parseLogBoxLog.js index f0abc77961d1..a8d281022c3a 100644 --- a/Libraries/LogBox/Data/parseLogBoxLog.js +++ b/Libraries/LogBox/Data/parseLogBoxLog.js @@ -14,12 +14,38 @@ import type {LogBoxLogData} from './LogBoxLog'; import parseErrorStack from '../../Core/Devtools/parseErrorStack'; import UTFSequence from '../../UTFSequence'; import stringifySafe from '../../Utilities/stringifySafe'; +import ansiRegex from 'ansi-regex'; + +const ANSI_REGEX = ansiRegex().source; const BABEL_TRANSFORM_ERROR_FORMAT = /^(?:TransformError )?(?:SyntaxError: |ReferenceError: )(.*): (.*) \((\d+):(\d+)\)\n\n([\s\S]+)/; + +// https://github.com/babel/babel/blob/33dbb85e9e9fe36915273080ecc42aee62ed0ade/packages/babel-code-frame/src/index.ts#L183-L184 +const BABEL_CODE_FRAME_MARKER_PATTERN = new RegExp( + [ + // Beginning of a line (per 'm' flag) + '^', + // Optional ANSI escapes for colors + `(?:${ANSI_REGEX})*`, + // Marker + '>', + // Optional ANSI escapes for colors + `(?:${ANSI_REGEX})*`, + // Left padding for line number + ' +', + // Line number + '[0-9]+', + // Gutter + ' \\|', + ].join(''), + 'm', +); + const BABEL_CODE_FRAME_ERROR_FORMAT = // eslint-disable-next-line no-control-regex /^(?:TransformError )?(?:.*):? (?:.*?)(\/.*): ([\s\S]+?)\n([ >]{2}[\d\s]+ \|[\s\S]+|\u{001b}[\s\S]+)/u; + const METRO_ERROR_FORMAT = /^(?:InternalError Metro has encountered an error:) (.*): (.*) \((\d+):(\d+)\)\n\n([\s\S]+)/u; @@ -241,27 +267,31 @@ export function parseLogBoxException( }; } - const babelCodeFrameError = message.match(BABEL_CODE_FRAME_ERROR_FORMAT); + // Perform a cheap match first before trying to parse the full message, which + // can get expensive for arbitrary input. + if (BABEL_CODE_FRAME_MARKER_PATTERN.test(message)) { + const babelCodeFrameError = message.match(BABEL_CODE_FRAME_ERROR_FORMAT); - if (babelCodeFrameError) { - // Codeframe errors are thrown from any use of buildCodeFrameError. - const [fileName, content, codeFrame] = babelCodeFrameError.slice(1); - return { - level: 'syntax', - stack: [], - isComponentError: false, - componentStack: [], - codeFrame: { - fileName, - location: null, // We are not given the location. - content: codeFrame, - }, - message: { - content, - substitutions: [], - }, - category: `${fileName}-${1}-${1}`, - }; + if (babelCodeFrameError) { + // Codeframe errors are thrown from any use of buildCodeFrameError. + const [fileName, content, codeFrame] = babelCodeFrameError.slice(1); + return { + level: 'syntax', + stack: [], + isComponentError: false, + componentStack: [], + codeFrame: { + fileName, + location: null, // We are not given the location. + content: codeFrame, + }, + message: { + content, + substitutions: [], + }, + category: `${fileName}-${1}-${1}`, + }; + } } if (message.match(/^TransformError /)) { diff --git a/Libraries/PermissionsAndroid/PermissionsAndroid.js b/Libraries/PermissionsAndroid/PermissionsAndroid.js index 14096da108f7..094b3ccf9016 100644 --- a/Libraries/PermissionsAndroid/PermissionsAndroid.js +++ b/Libraries/PermissionsAndroid/PermissionsAndroid.js @@ -75,7 +75,8 @@ const PERMISSIONS = Object.freeze({ ANSWER_PHONE_CALLS: 'android.permission.ANSWER_PHONE_CALLS', READ_PHONE_NUMBERS: 'android.permission.READ_PHONE_NUMBERS', UWB_RANGING: 'android.permission.UWB_RANGING', - POST_NOTIFICATION: 'android.permission.POST_NOTIFICATIONS', + POST_NOTIFICATION: 'android.permission.POST_NOTIFICATIONS', // Remove in 0.72 + POST_NOTIFICATIONS: 'android.permission.POST_NOTIFICATIONS', NEARBY_WIFI_DEVICES: 'android.permission.NEARBY_WIFI_DEVICES', }); @@ -106,7 +107,8 @@ class PermissionsAndroid { CAMERA: string, GET_ACCOUNTS: string, NEARBY_WIFI_DEVICES: string, - POST_NOTIFICATION: string, + POST_NOTIFICATION: string, // Remove in 0.72 + POST_NOTIFICATIONS: string, PROCESS_OUTGOING_CALLS: string, READ_CALENDAR: string, READ_CALL_LOG: string, diff --git a/Libraries/PushNotificationIOS/PushNotificationIOS.d.ts b/Libraries/PushNotificationIOS/PushNotificationIOS.d.ts index 5926c7878c36..364bd8aa01ed 100644 --- a/Libraries/PushNotificationIOS/PushNotificationIOS.d.ts +++ b/Libraries/PushNotificationIOS/PushNotificationIOS.d.ts @@ -49,6 +49,11 @@ export interface PushNotification { */ getData(): Object; + /** + * Gets the thread ID on the notif + */ + getThreadId(): string; + /** * iOS Only * Signifies remote notification handling is complete @@ -135,6 +140,21 @@ export interface PushNotificationIOSStatic { */ cancelAllLocalNotifications(): void; + /** + * Remove all delivered notifications from Notification Center. + */ + removeAllDeliveredNotifications(): void; + + /** + * Provides you with a list of the app’s notifications that are still displayed in Notification Center. + */ + getDeliveredNotifications(callback: (notifications: Object[]) => void): void; + + /** + * Removes the specified notifications from Notification Center + */ + removeDeliveredNotifications(identifiers: string[]): void; + /** * Cancel local notifications. * Optionally restricts the set of canceled notifications to those notifications whose userInfo fields match the corresponding fields in the userInfo argument. diff --git a/Libraries/ReactNative/AppContainer.js b/Libraries/ReactNative/AppContainer.js index cf3f1d0274e8..347bda2a2b41 100644 --- a/Libraries/ReactNative/AppContainer.js +++ b/Libraries/ReactNative/AppContainer.js @@ -17,6 +17,8 @@ import {type EventSubscription} from '../vendor/emitter/EventEmitter'; import {RootTagContext, createRootTag} from './RootTag'; import * as React from 'react'; +const reactDevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__; + type Props = $ReadOnly<{| children?: React.Node, fabric?: boolean, @@ -45,9 +47,17 @@ class AppContainer extends React.Component { }; _mainRef: ?React.ElementRef; _subscription: ?EventSubscription = null; + _reactDevToolsAgentListener: ?() => void = null; static getDerivedStateFromError: any = undefined; + mountReactDevToolsOverlays(): void { + const DevtoolsOverlay = require('../Inspector/DevtoolsOverlay').default; + const devtoolsOverlay = ; + + this.setState({devtoolsOverlay}); + } + componentDidMount(): void { if (__DEV__) { if (!this.props.internal_excludeInspector) { @@ -69,13 +79,21 @@ class AppContainer extends React.Component { this.setState({inspector}); }, ); - if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__ != null) { - const DevtoolsOverlay = - require('../Inspector/DevtoolsOverlay').default; - const devtoolsOverlay = ( - + + if (reactDevToolsHook != null) { + if (reactDevToolsHook.reactDevtoolsAgent) { + // In case if this is not the first AppContainer rendered and React DevTools are already attached + this.mountReactDevToolsOverlays(); + return; + } + + this._reactDevToolsAgentListener = () => + this.mountReactDevToolsOverlays(); + + reactDevToolsHook.on( + 'react-devtools', + this._reactDevToolsAgentListener, ); - this.setState({devtoolsOverlay}); } } } @@ -85,6 +103,10 @@ class AppContainer extends React.Component { if (this._subscription != null) { this._subscription.remove(); } + + if (reactDevToolsHook != null && this._reactDevToolsAgentListener != null) { + reactDevToolsHook.off('react-devtools', this._reactDevToolsAgentListener); + } } render(): React.Node { diff --git a/Libraries/ReactNative/AppRegistry.d.ts b/Libraries/ReactNative/AppRegistry.d.ts index 468f7d3bd57c..2e792e79b240 100644 --- a/Libraries/ReactNative/AppRegistry.d.ts +++ b/Libraries/ReactNative/AppRegistry.d.ts @@ -8,9 +8,12 @@ */ import type * as React from 'react'; +import type {IPerformanceLogger} from '../Utilities/createPerformanceLogger'; type Task = (taskData: any) => Promise; type TaskProvider = () => Task; +type TaskCanceller = () => void; +type TaskCancelProvider = () => TaskCanceller; export type ComponentProvider = () => React.ComponentType; @@ -22,6 +25,15 @@ export type AppConfig = { run?: Runnable | undefined; }; +export type ComponentProviderInstrumentationHook = ( + component: ComponentProvider, + scopedPerformanceLogger: IPerformanceLogger, +) => React.ComponentType; + +export type WrapperComponentProvider = ( + appParameters: any, +) => React.ComponentType; + /** * `AppRegistry` is the JS entry point to running all React Native apps. App * root components should register themselves with @@ -38,17 +50,31 @@ export type AppConfig = { * `require`d. */ export namespace AppRegistry { + export function setWrapperComponentProvider( + provider: WrapperComponentProvider, + ): void; + export function registerConfig(config: AppConfig[]): void; export function registerComponent( appKey: string, getComponentFunc: ComponentProvider, + section?: boolean, ): string; export function registerRunnable(appKey: string, func: Runnable): string; + export function registerSection( + appKey: string, + component: ComponentProvider, + ): void; + export function getAppKeys(): string[]; + export function getSectionKeys(): string[]; + + export function getSections(): Record; + export function unmountApplicationComponentAtRootTag(rootTag: number): void; export function runApplication(appKey: string, appParameters: any): void; @@ -65,4 +91,29 @@ export namespace AppRegistry { ): void; export function getRunnable(appKey: string): Runnable | undefined; + + export function getRegistry(): {sections: string[]; runnables: Runnable[]}; + + export function setComponentProviderInstrumentationHook( + hook: ComponentProviderInstrumentationHook, + ): void; + + export function registerHeadlessTask( + taskKey: string, + taskProvider: TaskProvider, + ): void; + + export function registerCancellableHeadlessTask( + taskKey: string, + taskProvider: TaskProvider, + taskCancelProvider: TaskCancelProvider, + ): void; + + export function startHeadlessTask( + taskId: number, + taskKey: string, + data: any, + ): void; + + export function cancelHeadlessTask(taskId: number, taskKey: string): void; } diff --git a/Libraries/ReactNative/AppRegistry.js b/Libraries/ReactNative/AppRegistry.js index 775acb7c95c2..45c08d49f997 100644 --- a/Libraries/ReactNative/AppRegistry.js +++ b/Libraries/ReactNative/AppRegistry.js @@ -51,7 +51,9 @@ export type Registry = { runnables: Runnables, ... }; -export type WrapperComponentProvider = any => React$ComponentType; +export type WrapperComponentProvider = ( + appParameters: any, +) => React$ComponentType; const runnables: Runnables = {}; let runCount = 1; diff --git a/Libraries/ReactNative/RootTag.d.ts b/Libraries/ReactNative/RootTag.d.ts new file mode 100644 index 000000000000..2522b8937a9e --- /dev/null +++ b/Libraries/ReactNative/RootTag.d.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import type * as React from 'react'; + +export type RootTag = number; +export const RootTagContext: React.Context; diff --git a/Libraries/StyleSheet/StyleSheet.d.ts b/Libraries/StyleSheet/StyleSheet.d.ts index 95ad0dd76731..53ab3e1f2784 100644 --- a/Libraries/StyleSheet/StyleSheet.d.ts +++ b/Libraries/StyleSheet/StyleSheet.d.ts @@ -87,9 +87,13 @@ export namespace StyleSheet { * an array, saving allocations and maintaining reference equality for * PureComponent checks. */ - export function compose( - style1: StyleProp | Array>, - style2: StyleProp | Array>, + export function compose< + T extends ViewStyle | TextStyle | ImageStyle, + U extends T, + V extends T, + >( + style1: StyleProp | Array>, + style2: StyleProp | Array>, ): StyleProp; /** diff --git a/Libraries/StyleSheet/StyleSheetTypes.d.ts b/Libraries/StyleSheet/StyleSheetTypes.d.ts index 5e0b8d8e1ab3..f6936730b5c3 100644 --- a/Libraries/StyleSheet/StyleSheetTypes.d.ts +++ b/Libraries/StyleSheet/StyleSheetTypes.d.ts @@ -180,6 +180,7 @@ export interface TransformsStyle { | SkewYTransform | MatrixTransform )[] + | string | undefined; /** * @deprecated Use matrix in transform prop instead. @@ -236,7 +237,6 @@ export interface ViewStyle extends FlexStyle, ShadowStyleIOS, TransformsStyle { borderTopWidth?: number | undefined; borderWidth?: number | undefined; opacity?: number | undefined; - testID?: string | undefined; /** * Sets the elevation of a view, using Android's underlying * [elevation API](https://developer.android.com/training/material/shadows-clipping.html#Elevation). diff --git a/Libraries/StyleSheet/__tests__/__snapshots__/processAspectRatio-test.js.snap b/Libraries/StyleSheet/__tests__/__snapshots__/processAspectRatio-test.js.snap index bf6d088a9415..d9d5f987b129 100644 --- a/Libraries/StyleSheet/__tests__/__snapshots__/processAspectRatio-test.js.snap +++ b/Libraries/StyleSheet/__tests__/__snapshots__/processAspectRatio-test.js.snap @@ -1,7 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`processAspectRatio should not accept invalid formats 1`] = `"aspectRatio must either be a number, a ratio or \`auto\`. You passed: 0a"`; +exports[`processAspectRatio should not accept invalid formats 1`] = `"aspectRatio must either be a number, a ratio string or \`auto\`. You passed: 0a"`; -exports[`processAspectRatio should not accept invalid formats 2`] = `"aspectRatio must either be a number, a ratio or \`auto\`. You passed: 1 / 1 1"`; +exports[`processAspectRatio should not accept invalid formats 2`] = `"aspectRatio must either be a number, a ratio string or \`auto\`. You passed: 1 / 1 1"`; -exports[`processAspectRatio should not accept invalid formats 3`] = `"aspectRatio must either be a number, a ratio or \`auto\`. You passed: auto 1/1"`; +exports[`processAspectRatio should not accept invalid formats 3`] = `"aspectRatio must either be a number, a ratio string or \`auto\`. You passed: auto 1/1"`; + +exports[`processAspectRatio should not accept non string truthy types 1`] = `"aspectRatio must either be a number, a ratio string or \`auto\`. You passed: function () {}"`; + +exports[`processAspectRatio should not accept non string truthy types 2`] = `"aspectRatio must either be a number, a ratio string or \`auto\`. You passed: 1,2,3"`; + +exports[`processAspectRatio should not accept non string truthy types 3`] = `"aspectRatio must either be a number, a ratio string or \`auto\`. You passed: [object Object]"`; diff --git a/Libraries/StyleSheet/__tests__/processAspectRatio-test.js b/Libraries/StyleSheet/__tests__/processAspectRatio-test.js index 7a3fbd313833..1097d956203e 100644 --- a/Libraries/StyleSheet/__tests__/processAspectRatio-test.js +++ b/Libraries/StyleSheet/__tests__/processAspectRatio-test.js @@ -47,4 +47,18 @@ describe('processAspectRatio', () => { expect(() => processAspectRatio('1 / 1 1')).toThrowErrorMatchingSnapshot(); expect(() => processAspectRatio('auto 1/1')).toThrowErrorMatchingSnapshot(); }); + + it('should ignore non string falsy types', () => { + const invalidThings = [undefined, null, false]; + invalidThings.forEach(thing => { + expect(processAspectRatio(thing)).toBe(undefined); + }); + }); + + it('should not accept non string truthy types', () => { + const invalidThings = [() => {}, [1, 2, 3], {}]; + invalidThings.forEach(thing => { + expect(() => processAspectRatio(thing)).toThrowErrorMatchingSnapshot(); + }); + }); }); diff --git a/Libraries/StyleSheet/processAspectRatio.js b/Libraries/StyleSheet/processAspectRatio.js index bde4a4a645c0..d3c1f8a45239 100644 --- a/Libraries/StyleSheet/processAspectRatio.js +++ b/Libraries/StyleSheet/processAspectRatio.js @@ -12,10 +12,20 @@ const invariant = require('invariant'); -function processAspectRatio(aspectRatio: number | string): ?number { +function processAspectRatio(aspectRatio?: number | string): ?number { if (typeof aspectRatio === 'number') { return aspectRatio; } + if (typeof aspectRatio !== 'string') { + if (__DEV__) { + invariant( + !aspectRatio, + 'aspectRatio must either be a number, a ratio string or `auto`. You passed: %s', + aspectRatio, + ); + } + return; + } const matches = aspectRatio.split('/').map(s => s.trim()); @@ -34,7 +44,7 @@ function processAspectRatio(aspectRatio: number | string): ?number { if (__DEV__) { invariant( !hasNonNumericValues && (matches.length === 1 || matches.length === 2), - 'aspectRatio must either be a number, a ratio or `auto`. You passed: %s', + 'aspectRatio must either be a number, a ratio string or `auto`. You passed: %s', aspectRatio, ); } diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 1f6524721cc8..dde3a5b4d75d 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -9,17 +9,16 @@ */ import type {PressEvent} from '../Types/CoreEventTypes'; +import type {TextProps} from './TextProps'; import * as PressabilityDebug from '../Pressability/PressabilityDebug'; import usePressability from '../Pressability/usePressability'; import flattenStyle from '../StyleSheet/flattenStyle'; import processColor from '../StyleSheet/processColor'; -import StyleSheet from '../StyleSheet/StyleSheet'; import {getAccessibilityRoleFromRole} from '../Utilities/AcessibilityMapping'; import Platform from '../Utilities/Platform'; import TextAncestor from './TextAncestor'; import {NativeText, NativeVirtualText} from './TextNativeComponent'; -import {type TextProps} from './TextProps'; import * as React from 'react'; import {useContext, useMemo, useState} from 'react'; @@ -36,6 +35,7 @@ const Text: React.AbstractComponent< accessible, accessibilityLabel, accessibilityRole, + accessibilityState, allowFontScaling, 'aria-busy': ariaBusy, 'aria-checked': ariaChecked, @@ -64,13 +64,23 @@ const Text: React.AbstractComponent< const [isHighlighted, setHighlighted] = useState(false); - const _accessibilityState = { - busy: ariaBusy ?? props.accessibilityState?.busy, - checked: ariaChecked ?? props.accessibilityState?.checked, - disabled: ariaDisabled ?? props.accessibilityState?.disabled, - expanded: ariaExpanded ?? props.accessibilityState?.expanded, - selected: ariaSelected ?? props.accessibilityState?.selected, - }; + let _accessibilityState; + if ( + accessibilityState != null || + ariaBusy != null || + ariaChecked != null || + ariaDisabled != null || + ariaExpanded != null || + ariaSelected != null + ) { + _accessibilityState = { + busy: ariaBusy ?? accessibilityState?.busy, + checked: ariaChecked ?? accessibilityState?.checked, + disabled: ariaDisabled ?? accessibilityState?.disabled, + expanded: ariaExpanded ?? accessibilityState?.expanded, + selected: ariaSelected ?? accessibilityState?.selected, + }; + } const _disabled = restProps.disabled != null @@ -174,25 +184,11 @@ const Text: React.AbstractComponent< ? null : processColor(restProps.selectionColor); - let style = flattenStyle(restProps.style); - - let _selectable = restProps.selectable; - if (style?.userSelect != null) { - _selectable = userSelectToSelectableMap[style.userSelect]; - } - - if (style?.verticalAlign != null) { - style = StyleSheet.compose(style, { - textAlignVertical: - verticalAlignToTextAlignVerticalMap[style.verticalAlign], - }); - } + let style = restProps.style; if (__DEV__) { if (PressabilityDebug.isEnabled() && onPress != null) { - style = StyleSheet.compose(restProps.style, { - color: 'magenta', - }); + style = [restProps.style, {color: 'magenta'}]; } } @@ -211,10 +207,22 @@ const Text: React.AbstractComponent< default: accessible, }); - let flattenedStyle = flattenStyle(style); + style = flattenStyle(style); + + if (typeof style?.fontWeight === 'number') { + style.fontWeight = style?.fontWeight.toString(); + } + + let _selectable = restProps.selectable; + if (style?.userSelect != null) { + _selectable = userSelectToSelectableMap[style.userSelect]; + delete style.userSelect; + } - if (typeof flattenedStyle?.fontWeight === 'number') { - flattenedStyle.fontWeight = flattenedStyle?.fontWeight.toString(); + if (style?.verticalAlign != null) { + style.textAlignVertical = + verticalAlignToTextAlignVerticalMap[style.verticalAlign]; + delete style.verticalAlign; } const _hasOnPressOrOnLongPress = @@ -223,46 +231,46 @@ const Text: React.AbstractComponent< return hasTextAncestor ? ( ) : ( ); diff --git a/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m b/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m index 7722f831ad08..9dca6a5567d9 100644 --- a/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m +++ b/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m @@ -168,6 +168,8 @@ @interface RCTBackedTextViewDelegateAdapter () @implementation RCTBackedTextViewDelegateAdapter { __weak UITextView *_backedTextInputView; + NSAttributedString *_lastStringStateWasUpdatedWith; + BOOL _ignoreNextTextInputCall; BOOL _textDidChangeIsComing; UITextRange *_previousSelectedTextRange; } @@ -254,12 +256,21 @@ - (BOOL)textView:(__unused UITextView *)textView shouldChangeTextInRange:(NSRang - (void)textViewDidChange:(__unused UITextView *)textView { + if (_ignoreNextTextInputCall && [_lastStringStateWasUpdatedWith isEqual:_backedTextInputView.attributedText]) { + _ignoreNextTextInputCall = NO; + return; + } _textDidChangeIsComing = NO; [_backedTextInputView.textInputDelegate textInputDidChange]; } - (void)textViewDidChangeSelection:(__unused UITextView *)textView { + if (_lastStringStateWasUpdatedWith && ![_lastStringStateWasUpdatedWith isEqual:_backedTextInputView.attributedText]) { + [self textViewDidChange:_backedTextInputView]; + _ignoreNextTextInputCall = YES; + } + _lastStringStateWasUpdatedWith = _backedTextInputView.attributedText; [self textViewProbablyDidChangeSelection]; } diff --git a/Libraries/Text/__tests__/Text-test.js b/Libraries/Text/__tests__/Text-test.js new file mode 100644 index 000000000000..ad565833a1f8 --- /dev/null +++ b/Libraries/Text/__tests__/Text-test.js @@ -0,0 +1,209 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @emails oncall+react_native + */ + +'use strict'; + +const render = require('../../../jest/renderer'); +const React = require('../React'); +const Text = require('../Text'); + +jest.unmock('../Text'); +jest.unmock('../TextNativeComponent'); + +describe('Text', () => { + it('default render', () => { + const instance = render.create(); + + expect(instance.toJSON()).toMatchInlineSnapshot(` + + `); + }); + + it('has displayName', () => { + expect(Text.displayName).toEqual('Text'); + }); +}); + +describe('Text compat with web', () => { + it('renders core props', () => { + const props = { + id: 'id', + tabIndex: 0, + testID: 'testID', + }; + + const instance = render.create(); + + expect(instance.toJSON()).toMatchInlineSnapshot(` + + `); + }); + + it('renders "aria-*" props', () => { + const props = { + 'aria-activedescendant': 'activedescendant', + 'aria-atomic': true, + 'aria-autocomplete': 'list', + 'aria-busy': true, + 'aria-checked': true, + 'aria-columncount': 5, + 'aria-columnindex': 3, + 'aria-columnspan': 2, + 'aria-controls': 'controls', + 'aria-current': 'current', + 'aria-describedby': 'describedby', + 'aria-details': 'details', + 'aria-disabled': true, + 'aria-errormessage': 'errormessage', + 'aria-expanded': true, + 'aria-flowto': 'flowto', + 'aria-haspopup': true, + 'aria-hidden': true, + 'aria-invalid': true, + 'aria-keyshortcuts': 'Cmd+S', + 'aria-label': 'label', + 'aria-labelledby': 'labelledby', + 'aria-level': 3, + 'aria-live': 'polite', + 'aria-modal': true, + 'aria-multiline': true, + 'aria-multiselectable': true, + 'aria-orientation': 'portrait', + 'aria-owns': 'owns', + 'aria-placeholder': 'placeholder', + 'aria-posinset': 5, + 'aria-pressed': true, + 'aria-readonly': true, + 'aria-required': true, + role: 'main', + 'aria-roledescription': 'roledescription', + 'aria-rowcount': 5, + 'aria-rowindex': 3, + 'aria-rowspan': 3, + 'aria-selected': true, + 'aria-setsize': 5, + 'aria-sort': 'ascending', + 'aria-valuemax': 5, + 'aria-valuemin': 0, + 'aria-valuenow': 3, + 'aria-valuetext': '3', + }; + + const instance = render.create(); + + expect(instance.toJSON()).toMatchInlineSnapshot(` + + `); + }); + + it('renders styles', () => { + const style = { + display: 'flex', + flex: 1, + backgroundColor: 'white', + marginInlineStart: 10, + userSelect: 'none', + verticalAlign: 'middle', + }; + + const instance = render.create(); + + expect(instance.toJSON()).toMatchInlineSnapshot(` + + `); + }); +}); diff --git a/Libraries/TurboModule/TurboModuleRegistry.d.ts b/Libraries/TurboModule/TurboModuleRegistry.d.ts index dd41d56c8e8d..4bee7be8bff7 100644 --- a/Libraries/TurboModule/TurboModuleRegistry.d.ts +++ b/Libraries/TurboModule/TurboModuleRegistry.d.ts @@ -9,7 +9,5 @@ import {TurboModule} from './RCTExport'; -export const TurboModuleRegistry: { - get(name: string): T | null; - getEnforcing(name: string): T; -}; +export function get(name: string): T | null; +export function getEnforcing(name: string): T; diff --git a/Libraries/Utilities/createPerformanceLogger.d.ts b/Libraries/Utilities/createPerformanceLogger.d.ts new file mode 100644 index 000000000000..57b590b99da4 --- /dev/null +++ b/Libraries/Utilities/createPerformanceLogger.d.ts @@ -0,0 +1,48 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +export type Timespan = { + startTime: number; + endTime?: number; + totalTime?: number; + startExtras?: Extras; + endExtras?: Extras; +}; + +// Extra values should be serializable primitives +export type ExtraValue = number | string | boolean; + +export type Extras = {[key: string]: ExtraValue}; + +export interface IPerformanceLogger { + addTimespan( + key: string, + startTime: number, + endTime: number, + startExtras?: Extras, + endExtras?: Extras, + ): void; + append(logger: IPerformanceLogger): void; + clear(): void; + clearCompleted(): void; + close(): void; + currentTimestamp(): number; + getExtras(): {[key: string]: ExtraValue | null}; + getPoints(): {[key: string]: number | null}; + getPointExtras(): {[key: string]: Extras | null}; + getTimespans(): {[key: string]: Timespan | null}; + hasTimespan(key: string): boolean; + isClosed(): boolean; + logEverything(): void; + markPoint(key: string, timestamp?: number, extras?: Extras): void; + removeExtra(key: string): ExtraValue | null; + setExtra(key: string, value: ExtraValue): void; + startTimespan(key: string, timestamp?: number, extras?: Extras): void; + stopTimespan(key: string, timestamp?: number, extras?: Extras): void; +} diff --git a/Libraries/Vibration/Vibration.d.ts b/Libraries/Vibration/Vibration.d.ts index 5cc57135fa7e..6e194b320a6e 100644 --- a/Libraries/Vibration/Vibration.d.ts +++ b/Libraries/Vibration/Vibration.d.ts @@ -31,7 +31,7 @@ * V(fixed) --wait(1s)--> V(fixed) --wait(2s)--> V(fixed) --wait(3s)--> V(fixed) */ export interface VibrationStatic { - vibrate(pattern?: number | number[] | null, repeat?: boolean | null): void; + vibrate(pattern?: number | number[], repeat?: boolean): void; /** * Stop vibration diff --git a/Libraries/promiseRejectionTrackingOptions.js b/Libraries/promiseRejectionTrackingOptions.js index a57f3666899d..3973bb494551 100644 --- a/Libraries/promiseRejectionTrackingOptions.js +++ b/Libraries/promiseRejectionTrackingOptions.js @@ -10,6 +10,8 @@ import typeof {enable} from 'promise/setimmediate/rejection-tracking'; +import LogBox from './LogBox/LogBox'; + type ExtractOptionsType =

(((options?: ?P) => void)) => P; let rejectionTrackingOptions: $Call = { @@ -34,19 +36,36 @@ let rejectionTrackingOptions: $Call = { ? rejection : JSON.stringify((rejection: $FlowFixMe)); } + // It could although this object is not a standard error, it still has stack information to unwind + // $FlowFixMe ignore types just check if stack is there + if (rejection.stack && typeof rejection.stack === 'string') { + stack = rejection.stack; + } } - const warning = - `Possible Unhandled Promise Rejection (id: ${id}):\n` + - `${message ?? ''}\n` + - (stack == null ? '' : stack); - console.warn(warning); + const warning = `Possible unhandled promise rejection (id: ${id}):\n${ + message ?? '' + }`; + if (__DEV__) { + LogBox.addLog({ + level: 'warn', + message: { + content: warning, + substitutions: [], + }, + componentStack: [], + stack, + category: 'possible_unhandled_promise_rejection', + }); + } else { + console.warn(warning); + } }, onHandled: id => { const warning = - `Promise Rejection Handled (id: ${id})\n` + + `Promise rejection handled (id: ${id})\n` + 'This means you can ignore any previous messages of the form ' + - `"Possible Unhandled Promise Rejection (id: ${id}):"`; + `"Possible unhandled promise rejection (id: ${id}):"`; console.warn(warning); }, }; diff --git a/React-Core.podspec b/React-Core.podspec index 7be727f36705..d21b50fc8c10 100644 --- a/React-Core.podspec +++ b/React-Core.podspec @@ -75,12 +75,20 @@ Pod::Spec.new do |s| s.subspec "Default" do |ss| ss.source_files = "React/**/*.{c,h,m,mm,S,cpp}" - ss.exclude_files = "React/CoreModules/**/*", - "React/DevSupport/**/*", - "React/Fabric/**/*", - "React/FBReactNativeSpec/**/*", - "React/Tests/**/*", - "React/Inspector/**/*" + exclude_files = [ + "React/CoreModules/**/*", + "React/DevSupport/**/*", + "React/Fabric/**/*", + "React/FBReactNativeSpec/**/*", + "React/Tests/**/*", + "React/Inspector/**/*" + ] + # If we are using Hermes (the default is use hermes, so USE_HERMES can be nil), we don't have jsc installed + # So we have to exclude the JSCExecutorFactory + if ENV['USE_HERMES'] == nil || ENV['USE_HERMES'] == "1" + exclude_files = exclude_files.append("React/CxxBridge/JSCExecutorFactory.{h,mm}") + end + ss.exclude_files = exclude_files ss.private_header_files = "React/Cxx*/*.h" end @@ -114,4 +122,11 @@ Pod::Spec.new do |s| s.dependency "React-jsiexecutor", version s.dependency "Yoga" s.dependency "glog" + + if ENV['USE_HERMES'] == "0" + s.dependency 'React-jsc' + else + s.dependency 'React-hermes' + s.dependency 'hermes-engine' + end end diff --git a/React/Base/RCTBundleURLProvider.h b/React/Base/RCTBundleURLProvider.h index cbf8132b1da9..7072e05dd839 100644 --- a/React/Base/RCTBundleURLProvider.h +++ b/React/Base/RCTBundleURLProvider.h @@ -101,6 +101,7 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed); @property (nonatomic, assign) BOOL enableMinification; @property (nonatomic, assign) BOOL enableDev; +@property (nonatomic, assign) BOOL inlineSourceMap; /** * The scheme/protocol used of the packager, the default is the http protocol @@ -125,13 +126,32 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed); + (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot packagerHost:(NSString *)packagerHost enableDev:(BOOL)enableDev - enableMinification:(BOOL)enableMinification; + enableMinification:(BOOL)enableMinification + __deprecated_msg( + "Use `jsBundleURLForBundleRoot:packagerHost:enableDev:enableMinification:inlineSourceMap:` instead"); + ++ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot + packagerHost:(NSString *)packagerHost + packagerScheme:(NSString *)scheme + enableDev:(BOOL)enableDev + enableMinification:(BOOL)enableMinification + modulesOnly:(BOOL)modulesOnly + runModule:(BOOL)runModule + __deprecated_msg( + "Use jsBundleURLForBundleRoot:packagerHost:enableDev:enableMinification:inlineSourceMap:modulesOnly:runModule:` instead"); + ++ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot + packagerHost:(NSString *)packagerHost + enableDev:(BOOL)enableDev + enableMinification:(BOOL)enableMinification + inlineSourceMap:(BOOL)inlineSourceMap; + (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot packagerHost:(NSString *)packagerHost packagerScheme:(NSString *)scheme enableDev:(BOOL)enableDev enableMinification:(BOOL)enableMinification + inlineSourceMap:(BOOL)inlineSourceMap modulesOnly:(BOOL)modulesOnly runModule:(BOOL)runModule; /** @@ -142,6 +162,17 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed); + (NSURL *)resourceURLForResourcePath:(NSString *)path packagerHost:(NSString *)packagerHost scheme:(NSString *)scheme - query:(NSString *)query; + query:(NSString *)query + __deprecated_msg("Use version with queryItems parameter instead"); + +/** + * Given a hostname for the packager and a resource path (including "/"), return the URL to the resource. + * In general, please use the instance method to decide if the packager is running and fallback to the pre-packaged + * resource if it is not: -resourceURLForResourceRoot:resourceName:resourceExtension:offlineBundle: + */ ++ (NSURL *)resourceURLForResourcePath:(NSString *)path + packagerHost:(NSString *)packagerHost + scheme:(NSString *)scheme + queryItems:(NSArray *)queryItems; @end diff --git a/React/Base/RCTBundleURLProvider.mm b/React/Base/RCTBundleURLProvider.mm index bee7394ee29f..1321edc474a5 100644 --- a/React/Base/RCTBundleURLProvider.mm +++ b/React/Base/RCTBundleURLProvider.mm @@ -22,10 +22,12 @@ void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed) kRCTAllowPackagerAccess = allowed; } #endif +static NSString *const kRCTPlatformName = @"ios"; static NSString *const kRCTPackagerSchemeKey = @"RCT_packager_scheme"; static NSString *const kRCTJsLocationKey = @"RCT_jsLocation"; static NSString *const kRCTEnableDevKey = @"RCT_enableDev"; static NSString *const kRCTEnableMinificationKey = @"RCT_enableMinification"; +static NSString *const kRCTInlineSourceMapKey = @"RCT_inlineSourceMap"; @implementation RCTBundleURLProvider @@ -183,6 +185,7 @@ - (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot fallbackURLProvider:( packagerScheme:[self packagerScheme] enableDev:[self enableDev] enableMinification:[self enableMinification] + inlineSourceMap:[self inlineSourceMap] modulesOnly:NO runModule:YES]; } @@ -195,6 +198,7 @@ - (NSURL *)jsBundleURLForSplitBundleRoot:(NSString *)bundleRoot packagerScheme:[self packagerScheme] enableDev:[self enableDev] enableMinification:[self enableMinification] + inlineSourceMap:[self inlineSourceMap] modulesOnly:YES runModule:NO]; } @@ -234,13 +238,29 @@ - (NSURL *)resourceURLForResourceRoot:(NSString *)root return [[self class] resourceURLForResourcePath:path packagerHost:packagerServerHostPort scheme:packagerServerScheme - query:nil]; + queryItems:nil]; } + (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot packagerHost:(NSString *)packagerHost enableDev:(BOOL)enableDev enableMinification:(BOOL)enableMinification +{ + return [self jsBundleURLForBundleRoot:bundleRoot + packagerHost:packagerHost + packagerScheme:nil + enableDev:enableDev + enableMinification:enableMinification + inlineSourceMap:NO + modulesOnly:NO + runModule:YES]; +} + ++ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot + packagerHost:(NSString *)packagerHost + enableDev:(BOOL)enableDev + enableMinification:(BOOL)enableMinification + inlineSourceMap:(BOOL)inlineSourceMap { return [self jsBundleURLForBundleRoot:bundleRoot @@ -248,6 +268,7 @@ + (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot packagerScheme:nil enableDev:enableDev enableMinification:enableMinification + inlineSourceMap:inlineSourceMap modulesOnly:NO runModule:YES]; } @@ -259,27 +280,45 @@ + (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot enableMinification:(BOOL)enableMinification modulesOnly:(BOOL)modulesOnly runModule:(BOOL)runModule +{ + return [self jsBundleURLForBundleRoot:bundleRoot + packagerHost:packagerHost + packagerScheme:nil + enableDev:enableDev + enableMinification:enableMinification + inlineSourceMap:NO + modulesOnly:modulesOnly + runModule:runModule]; +} + ++ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot + packagerHost:(NSString *)packagerHost + packagerScheme:(NSString *)scheme + enableDev:(BOOL)enableDev + enableMinification:(BOOL)enableMinification + inlineSourceMap:(BOOL)inlineSourceMap + modulesOnly:(BOOL)modulesOnly + runModule:(BOOL)runModule { NSString *path = [NSString stringWithFormat:@"/%@.bundle", bundleRoot]; + BOOL lazy = enableDev; + NSArray *queryItems = @[ + [[NSURLQueryItem alloc] initWithName:@"platform" value:kRCTPlatformName], + [[NSURLQueryItem alloc] initWithName:@"dev" value:enableDev ? @"true" : @"false"], + [[NSURLQueryItem alloc] initWithName:@"minify" value:enableMinification ? @"true" : @"false"], + [[NSURLQueryItem alloc] initWithName:@"inlineSourceMap" value:inlineSourceMap ? @"true" : @"false"], + [[NSURLQueryItem alloc] initWithName:@"modulesOnly" value:modulesOnly ? @"true" : @"false"], + [[NSURLQueryItem alloc] initWithName:@"runModule" value:runModule ? @"true" : @"false"], #ifdef HERMES_BYTECODE_VERSION - NSString *runtimeBytecodeVersion = [NSString stringWithFormat:@"&runtimeBytecodeVersion=%u", HERMES_BYTECODE_VERSION]; -#else - NSString *runtimeBytecodeVersion = @""; + [[NSURLQueryItem alloc] initWithName:@"runtimeBytecodeVersion" value:HERMES_BYTECODE_VERSION], #endif - - // When we support only iOS 8 and above, use queryItems for a better API. - NSString *query = [NSString stringWithFormat:@"platform=ios&dev=%@&minify=%@&modulesOnly=%@&runModule=%@%@", - enableDev ? @"true" : @"false", - enableMinification ? @"true" : @"false", - modulesOnly ? @"true" : @"false", - runModule ? @"true" : @"false", - runtimeBytecodeVersion]; + ]; NSString *bundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey]; if (bundleID) { - query = [NSString stringWithFormat:@"%@&app=%@", query, bundleID]; + queryItems = [queryItems arrayByAddingObject:[[NSURLQueryItem alloc] initWithName:@"app" value:bundleID]]; } - return [[self class] resourceURLForResourcePath:path packagerHost:packagerHost scheme:scheme query:query]; + return [[self class] resourceURLForResourcePath:path packagerHost:packagerHost scheme:scheme queryItems:queryItems]; } + (NSURL *)resourceURLForResourcePath:(NSString *)path @@ -296,6 +335,20 @@ + (NSURL *)resourceURLForResourcePath:(NSString *)path return components.URL; } ++ (NSURL *)resourceURLForResourcePath:(NSString *)path + packagerHost:(NSString *)packagerHost + scheme:(NSString *)scheme + queryItems:(NSArray *)queryItems +{ + NSURLComponents *components = [NSURLComponents componentsWithURL:serverRootWithHostPort(packagerHost, scheme) + resolvingAgainstBaseURL:NO]; + components.path = path; + if (queryItems != nil) { + components.queryItems = queryItems; + } + return components.URL; +} + - (void)updateValue:(id)object forKey:(NSString *)key { [[NSUserDefaults standardUserDefaults] setObject:object forKey:key]; @@ -313,6 +366,11 @@ - (BOOL)enableMinification return [[NSUserDefaults standardUserDefaults] boolForKey:kRCTEnableMinificationKey]; } +- (BOOL)inlineSourceMap +{ + return [[NSUserDefaults standardUserDefaults] boolForKey:kRCTInlineSourceMapKey]; +} + - (NSString *)jsLocation { return [[NSUserDefaults standardUserDefaults] stringForKey:kRCTJsLocationKey]; @@ -342,6 +400,11 @@ - (void)setEnableMinification:(BOOL)enableMinification [self updateValue:@(enableMinification) forKey:kRCTEnableMinificationKey]; } +- (void)setInlineSourceMap:(BOOL)inlineSourceMap +{ + [self updateValue:@(inlineSourceMap) forKey:kRCTInlineSourceMapKey]; +} + - (void)setPackagerScheme:(NSString *)packagerScheme { [self updateValue:packagerScheme forKey:kRCTPackagerSchemeKey]; diff --git a/React/Base/RCTJavaScriptLoader.mm b/React/Base/RCTJavaScriptLoader.mm index 133851a1d7f4..b789d949a9ce 100755 --- a/React/Base/RCTJavaScriptLoader.mm +++ b/React/Base/RCTJavaScriptLoader.mm @@ -312,7 +312,17 @@ static void attemptAsynchronousLoadOfBundleAtURL( return; } - RCTSource *source = RCTSourceCreate(scriptURL, data, data.length); + // Prefer `Content-Location` as the canonical source URL, if given, or fall back to scriptURL. + NSURL *sourceURL = scriptURL; + NSString *contentLocationHeader = headers[@"Content-Location"]; + if (contentLocationHeader) { + NSURL *contentLocationURL = [NSURL URLWithString:contentLocationHeader relativeToURL:scriptURL]; + if (contentLocationURL) { + sourceURL = contentLocationURL; + } + } + + RCTSource *source = RCTSourceCreate(sourceURL, data, data.length); parseHeaders(headers, source); onComplete(nil, source); } diff --git a/React/Base/RCTVersion.m b/React/Base/RCTVersion.m index 4f6d3c1f5ec5..441764a716d9 100644 --- a/React/Base/RCTVersion.m +++ b/React/Base/RCTVersion.m @@ -23,8 +23,8 @@ __rnVersion = @{ RCTVersionMajor: @(0), RCTVersionMinor: @(71), - RCTVersionPatch: @(0), - RCTVersionPrerelease: @"rc.1", + RCTVersionPatch: @(17), + RCTVersionPrerelease: [NSNull null], }; }); return __rnVersion; diff --git a/React/CoreModules/RCTAlertController.m b/React/CoreModules/RCTAlertController.m index 02636c3f4a7b..3387a6e8d97c 100644 --- a/React/CoreModules/RCTAlertController.m +++ b/React/CoreModules/RCTAlertController.m @@ -20,10 +20,24 @@ @implementation RCTAlertController - (UIWindow *)alertWindow { if (_alertWindow == nil) { - _alertWindow = [[UIWindow alloc] initWithFrame:RCTSharedApplication().keyWindow.bounds]; - _alertWindow.rootViewController = [UIViewController new]; - _alertWindow.windowLevel = UIWindowLevelAlert + 1; + _alertWindow = [self getUIWindowFromScene]; + + if (_alertWindow == nil) { + UIWindow *keyWindow = RCTSharedApplication().keyWindow; + if (keyWindow) { + _alertWindow = [[UIWindow alloc] initWithFrame:keyWindow.bounds]; + } else { + // keyWindow is nil, so we cannot create and initialize _alertWindow + NSLog(@"Unable to create alert window: keyWindow is nil"); + } + } + + if (_alertWindow) { + _alertWindow.rootViewController = [UIViewController new]; + _alertWindow.windowLevel = UIWindowLevelAlert + 1; + } } + return _alertWindow; } @@ -49,4 +63,17 @@ - (void)hide _alertWindow = nil; } +- (UIWindow *)getUIWindowFromScene +{ + if (@available(iOS 13.0, *)) { + for (UIScene *scene in RCTSharedApplication().connectedScenes) { + if (scene.activationState == UISceneActivationStateForegroundActive && + [scene isKindOfClass:[UIWindowScene class]]) { + return [[UIWindow alloc] initWithWindowScene:(UIWindowScene *)scene]; + } + } + } + return nil; +} + @end diff --git a/React/CoreModules/RCTDevLoadingView.mm b/React/CoreModules/RCTDevLoadingView.mm index f162b0f836df..9bac8178b390 100644 --- a/React/CoreModules/RCTDevLoadingView.mm +++ b/React/CoreModules/RCTDevLoadingView.mm @@ -110,6 +110,20 @@ - (void)showMessage:(NSString *)message color:(UIColor *)color backgroundColor:( return; } + // Input validation + if (message == nil || [message isEqualToString:@""]) { + NSLog(@"Error: message cannot be nil or empty"); + return; + } + if (color == nil) { + NSLog(@"Error: color cannot be nil"); + return; + } + if (backgroundColor == nil) { + NSLog(@"Error: backgroundColor cannot be nil"); + return; + } + dispatch_async(dispatch_get_main_queue(), ^{ self->_showDate = [NSDate date]; if (!self->_window && !RCTRunningInTestEnvironment()) { diff --git a/React/CoreModules/React-CoreModules.podspec b/React/CoreModules/React-CoreModules.podspec index a4a605aaf012..34cc4a59bbc1 100644 --- a/React/CoreModules/React-CoreModules.podspec +++ b/React/CoreModules/React-CoreModules.podspec @@ -44,4 +44,5 @@ Pod::Spec.new do |s| s.dependency "React-RCTImage", version s.dependency "ReactCommon/turbomodule/core", version s.dependency "React-jsi", version + s.dependency 'React-RCTBlob' end diff --git a/React/CxxBridge/JSCExecutorFactory.mm b/React/CxxBridge/JSCExecutorFactory.mm index 4d8a1ba1b294..78584cd4e6c1 100644 --- a/React/CxxBridge/JSCExecutorFactory.mm +++ b/React/CxxBridge/JSCExecutorFactory.mm @@ -7,7 +7,7 @@ #include "JSCExecutorFactory.h" -#import +#import #import diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index 047a7c2c4eb4..be4b79fa8409 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -474,6 +474,7 @@ - (void)start // Load the source asynchronously, then store it for later execution. dispatch_group_enter(prepareBridge); __block NSData *sourceCode; + __block NSURL *sourceURL = self.bundleURL; #if (RCT_DEV | RCT_ENABLE_LOADING_VIEW) && __has_include() { @@ -489,6 +490,9 @@ - (void)start } sourceCode = source.data; + if (source.url) { + sourceURL = source.url; + } dispatch_group_leave(prepareBridge); } onProgress:^(RCTLoadingProgress *progressData) { @@ -503,7 +507,7 @@ - (void)start dispatch_group_notify(prepareBridge, dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{ RCTCxxBridge *strongSelf = weakSelf; if (sourceCode && strongSelf.loading) { - [strongSelf executeSourceCode:sourceCode sync:NO]; + [strongSelf executeSourceCode:sourceCode withSourceURL:sourceURL sync:NO]; } }); RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @""); @@ -1049,7 +1053,7 @@ - (void)registerModuleForFrameUpdates:(id)module withModuleData [_displayLink registerModuleForFrameUpdates:module withModuleData:moduleData]; } -- (void)executeSourceCode:(NSData *)sourceCode sync:(BOOL)sync +- (void)executeSourceCode:(NSData *)sourceCode withSourceURL:(NSURL *)url sync:(BOOL)sync { // This will get called from whatever thread was actually executing JS. dispatch_block_t completion = ^{ @@ -1074,12 +1078,13 @@ - (void)executeSourceCode:(NSData *)sourceCode sync:(BOOL)sync }; if (sync) { - [self executeApplicationScriptSync:sourceCode url:self.bundleURL]; + [self executeApplicationScriptSync:sourceCode url:url]; completion(); } else { - [self enqueueApplicationScript:sourceCode url:self.bundleURL onComplete:completion]; + [self enqueueApplicationScript:sourceCode url:url onComplete:completion]; } + // Use the original request URL here - HMRClient uses this to derive the /hot URL and entry point. [self.devSettings setupHMRClientWithBundleURL:self.bundleURL]; } diff --git a/React/Views/RCTModalHostViewManager.m b/React/Views/RCTModalHostViewManager.m index 7fab70ef6363..4b9f9ad7267c 100644 --- a/React/Views/RCTModalHostViewManager.m +++ b/React/Views/RCTModalHostViewManager.m @@ -75,13 +75,15 @@ - (void)presentModalHostView:(RCTModalHostView *)modalHostView modalHostView.onShow(nil); } }; - if (_presentationBlock) { - _presentationBlock([modalHostView reactViewController], viewController, animated, completionBlock); - } else { - [[modalHostView reactViewController] presentViewController:viewController - animated:animated - completion:completionBlock]; - } + dispatch_async(dispatch_get_main_queue(), ^{ + if (self->_presentationBlock) { + self->_presentationBlock([modalHostView reactViewController], viewController, animated, completionBlock); + } else { + [[modalHostView reactViewController] presentViewController:viewController + animated:animated + completion:completionBlock]; + } + }); } - (void)dismissModalHostView:(RCTModalHostView *)modalHostView @@ -93,11 +95,13 @@ - (void)dismissModalHostView:(RCTModalHostView *)modalHostView [[self.bridge moduleForClass:[RCTModalManager class]] modalDismissed:modalHostView.identifier]; } }; - if (_dismissalBlock) { - _dismissalBlock([modalHostView reactViewController], viewController, animated, completionBlock); - } else { - [viewController.presentingViewController dismissViewControllerAnimated:animated completion:completionBlock]; - } + dispatch_async(dispatch_get_main_queue(), ^{ + if (self->_dismissalBlock) { + self->_dismissalBlock([modalHostView reactViewController], viewController, animated, completionBlock); + } else { + [viewController.presentingViewController dismissViewControllerAnimated:animated completion:completionBlock]; + } + }); } - (RCTShadowView *)shadowView diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index d43535934995..d03f3ddfdb2e 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -5,17 +5,12 @@ * LICENSE file in the root directory of this source tree. */ -buildscript { - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${rootProject.hasProperty("kotlinVersion") ? rootProject.ext.kotlinVersion : KOTLIN_VERSION}" - } -} - plugins { id("com.android.library") id("com.facebook.react") id("de.undercouch.download") id("maven-publish") + id("org.jetbrains.kotlin.android") } import com.facebook.react.tasks.internal.* @@ -39,6 +34,16 @@ def downloadsDir = customDownloadsDir ? new File(customDownloadsDir) : new File( def thirdPartyNdkDir = new File("$buildDir/third-party-ndk") def reactNativeRootDir = projectDir.parent +// We put the publishing version from gradle.properties inside ext. so other +// subprojects can access it as well. +ext.publishing_version = VERSION_NAME + +// This is the version of CMake we're requesting to the Android SDK to use. +// If missing it will be downloaded automatically. Only CMake versions shipped with the +// Android SDK are supported (you can find them listed in the SDK Manager of Android Studio). +def cmakeVersion = System.getenv("CMAKE_VERSION") ?: "3.22.1" +ext.cmake_version = cmakeVersion + // You need to have following folders in this directory: // - boost_1_76_0 // - double-conversion-1.1.6 @@ -92,6 +97,10 @@ final def preparePrefab = tasks.register("preparePrefab", PreparePrefabHeadersTa "react_newarchdefaults", new Pair("src/main/jni/react/newarchdefaults", "") ), + new PrefabPreprocessingEntry( + "react_render_animations", + new Pair("../ReactCommon/react/renderer/animations/", "react/renderer/animations/") + ), new PrefabPreprocessingEntry( "react_render_core", new Pair("../ReactCommon/react/renderer/core/", "react/renderer/core/") @@ -103,6 +112,10 @@ final def preparePrefab = tasks.register("preparePrefab", PreparePrefabHeadersTa new Pair("../ReactCommon/react/renderer/graphics/platform/cxx/", ""), ] ), + new PrefabPreprocessingEntry( + "rrc_root", + new Pair("../ReactCommon/react/renderer/components/root/", "react/renderer/components/root/") + ), new PrefabPreprocessingEntry( "rrc_view", new Pair("../ReactCommon/react/renderer/components/view/", "react/renderer/components/view/") @@ -117,7 +130,10 @@ final def preparePrefab = tasks.register("preparePrefab", PreparePrefabHeadersTa ), new PrefabPreprocessingEntry( "fabricjni", - new Pair("src/main/jni/react/fabric", "") + [ + new Pair("src/main/jni/react/fabric", "react/fabric/"), + new Pair("src/main/jni/react/cxxcomponents", "react/cxxcomponents/") + ] ), new PrefabPreprocessingEntry( "react_render_mapbuffer", @@ -144,6 +160,7 @@ final def preparePrefab = tasks.register("preparePrefab", PreparePrefabHeadersTa new Pair(new File(buildDir, "third-party-ndk/boost/boost_1_76_0/").absolutePath, ""), new Pair(new File(buildDir, "third-party-ndk/double-conversion/").absolutePath, ""), new Pair(new File(buildDir, "third-party-ndk/folly/").absolutePath, ""), + new Pair(new File(buildDir, "third-party-ndk/glog/exported/").absolutePath, ""), new Pair("../ReactCommon/butter/", "butter/"), new Pair("../ReactCommon/callinvoker/", ""), new Pair("../ReactCommon/react/bridging/", "react/bridging/"), @@ -152,6 +169,8 @@ final def preparePrefab = tasks.register("preparePrefab", PreparePrefabHeadersTa new Pair("../ReactCommon/react/nativemodule/core/platform/android/", ""), new Pair("../ReactCommon/react/renderer/componentregistry/", "react/renderer/componentregistry/"), new Pair("../ReactCommon/react/renderer/components/root/", "react/renderer/components/root/"), + new Pair("../ReactCommon/react/renderer/core/", "react/renderer/core/"), + new Pair("../ReactCommon/react/renderer/debug/", "react/renderer/debug/"), new Pair("../ReactCommon/react/renderer/leakchecker/", "react/renderer/leakchecker/"), new Pair("../ReactCommon/react/renderer/mapbuffer/", "react/renderer/mapbuffer/"), new Pair("../ReactCommon/react/renderer/mounting/", "react/renderer/mounting/"), @@ -159,6 +178,7 @@ final def preparePrefab = tasks.register("preparePrefab", PreparePrefabHeadersTa new Pair("../ReactCommon/react/renderer/scheduler/", "react/renderer/scheduler/"), new Pair("../ReactCommon/react/renderer/telemetry/", "react/renderer/telemetry/"), new Pair("../ReactCommon/react/renderer/uimanager/", "react/renderer/uimanager/"), + new Pair("../ReactCommon/react/debug/", "react/debug/"), new Pair("../ReactCommon/react/utils/", "react/utils/"), new Pair("src/main/jni/react/jni", "react/jni/"), ] @@ -174,22 +194,54 @@ final def preparePrefab = tasks.register("preparePrefab", PreparePrefabHeadersTa "rrc_image", new Pair("../ReactCommon/react/renderer/components/image/", "react/renderer/components/image/") ), + // These prefab targets are used by Expo & Reanimated + new PrefabPreprocessingEntry( + "hermes_executor", + // "hermes_executor" is statically linking against "hermes_executor_common" + // and "hermes_inspector". Here we expose only the headers that we know are needed. + new Pair("../ReactCommon/hermes/inspector/", "hermes/inspector/") + ), + new PrefabPreprocessingEntry( + "jscexecutor", + // "jscexecutor" is statically linking against "jscruntime" + // Here we expose only the headers that we know are needed. + new Pair("../ReactCommon/jsc/", "jsc/") + ), + new PrefabPreprocessingEntry( + "react_render_uimanager", + new Pair("../ReactCommon/react/renderer/uimanager/", "react/renderer/uimanager/"), + ), + new PrefabPreprocessingEntry( + "react_render_scheduler", + new Pair("../ReactCommon/react/renderer/scheduler/", "react/renderer/scheduler/"), + ), + new PrefabPreprocessingEntry( + "react_render_mounting", + new Pair("../ReactCommon/react/renderer/mounting/", "react/renderer/mounting/"), + ), + new PrefabPreprocessingEntry( + "reactnativejni", + [ + new Pair("src/main/jni/react/jni", "react/jni/"), + new Pair("../ReactCommon/cxxreact/", "cxxreact/"), + ] + ), + new PrefabPreprocessingEntry( + "jsinspector", + new Pair("../ReactCommon/jsinspector/", "jsinspector/"), + ), ] ) it.outputDir.set(prefabHeadersDir) } -// We put the publishing version from gradle.properties inside ext. so other -// subprojects can access it as well. -ext.publishing_version = VERSION_NAME - task createNativeDepsDirectories { downloadsDir.mkdirs() thirdPartyNdkDir.mkdirs() } task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) { - src("https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION.replace("_", ".")}/source/boost_${BOOST_VERSION}.tar.gz") + src("https://archives.boost.io/release/${BOOST_VERSION.replace("_", ".")}/source/boost_${BOOST_VERSION}.tar.gz") onlyIfNewer(true) overwrite(false) dest(new File(downloadsDir, "boost_${BOOST_VERSION}.tar.gz")) @@ -402,12 +454,11 @@ android { "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-21" - targets "reactnativejni", - "jscexecutor", - "jsijniprofiler", + targets "jsijniprofiler", "reactnativeblob", "reactperfloggerjni", // prefab targets + "reactnativejni", "react_render_debug", "turbomodulejsijni", "runtimeexecutor", @@ -415,9 +466,11 @@ android { "react_debug", "react_render_componentregistry", "react_newarchdefaults", + "react_render_animations", "react_render_core", "react_render_graphics", "rrc_image", + "rrc_root", "rrc_view", "jsi", "glog", @@ -426,7 +479,13 @@ android { "yoga", "folly_runtime", "react_nativemodule_core", - "react_render_imagemanager" + "react_render_imagemanager", + "react_render_uimanager", + "react_render_scheduler", + "react_render_mounting", + "hermes_executor", + "jscexecutor", + "jsinspector" } } ndk { @@ -434,26 +493,9 @@ android { } } - buildTypes { - debug { - externalNativeBuild { - cmake { - targets "hermes-executor-debug" - } - } - } - - release { - externalNativeBuild { - cmake { - targets "hermes-executor-release" - } - } - } - } - externalNativeBuild { cmake { + version cmakeVersion path "src/main/jni/CMakeLists.txt" } } @@ -513,6 +555,9 @@ android { react_newarchdefaults { headers(new File(prefabHeadersDir, "react_newarchdefaults").absolutePath) } + react_render_animations { + headers(new File(prefabHeadersDir, "react_render_animations").absolutePath) + } react_render_core { headers(new File(prefabHeadersDir, "react_render_core").absolutePath) } @@ -522,6 +567,9 @@ android { rrc_image { headers(new File(prefabHeadersDir, "rrc_image").absolutePath) } + rrc_root { + headers(new File(prefabHeadersDir, "rrc_root").absolutePath) + } rrc_view { headers(new File(prefabHeadersDir, "rrc_view").absolutePath) } @@ -549,6 +597,27 @@ android { react_render_imagemanager { headers(new File(prefabHeadersDir, "react_render_imagemanager").absolutePath) } + react_render_uimanager { + headers(new File(prefabHeadersDir, "react_render_uimanager").absolutePath) + } + react_render_scheduler { + headers(new File(prefabHeadersDir, "react_render_scheduler").absolutePath) + } + react_render_mounting { + headers(new File(prefabHeadersDir, "react_render_mounting").absolutePath) + } + reactnativejni { + headers(new File(prefabHeadersDir, "reactnativejni").absolutePath) + } + hermes_executor { + headers(new File(prefabHeadersDir, "hermes_executor").absolutePath) + } + jscexecutor { + headers(new File(prefabHeadersDir, "jscexecutor").absolutePath) + } + jsinspector { + headers(new File(prefabHeadersDir, "jsinspector").absolutePath) + } } publishing { @@ -602,12 +671,7 @@ react { // TODO: The library name is chosen for parity with Fabric components & iOS // This should be changed to a more generic name, e.g. `ReactCoreSpec`. libraryName = "rncore" - root = file("..") jsRootDir = file("../Libraries") - reactNativeDir = file("$projectDir/..") - // We search for the codegen in either one of the `node_modules` folder or in the - // root packages folder (that's for when we build from source without calling `yarn install`). - codegenDir = file(findNodeModulePath(projectDir, "react-native-codegen") ?: "../packages/react-native-codegen/") } apply plugin: "org.jetbrains.kotlin.android" diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 0e58265ada08..f8dc83323117 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=0.71.0-rc.1 +VERSION_NAME=0.71.17 GROUP=com.facebook.react # JVM Versions @@ -30,8 +30,5 @@ FOLLY_VERSION=2021.07.22.00 GLOG_VERSION=0.3.5 LIBEVENT_VERSION=2.1.12 -# Plugins Versions -KOTLIN_VERSION=1.6.10 - android.useAndroidX=true android.enableJetifier=true diff --git a/ReactAndroid/hermes-engine/build.gradle b/ReactAndroid/hermes-engine/build.gradle index 760aaef0d573..c714f877e5e0 100644 --- a/ReactAndroid/hermes-engine/build.gradle +++ b/ReactAndroid/hermes-engine/build.gradle @@ -16,18 +16,19 @@ plugins { group = "com.facebook.react" version = parent.publishing_version +def cmakeVersion = parent.cmake_version -def cmakeVersion = "3.18.1" /** * We use the bundled version of CMake in the Android SDK if available, to don't force Android * users to install CMake externally. */ def findCmakePath(cmakeVersion) { - if (System.getenv("ANDROID_SDK_ROOT")) { - return "${System.getenv("ANDROID_SDK_ROOT")}/cmake/${cmakeVersion}/bin/cmake" + def cmakeRelativePath = "/cmake/${cmakeVersion}/bin/cmake" + if (System.getenv("ANDROID_SDK_ROOT") && new File("${System.getenv("ANDROID_SDK_ROOT")}/${cmakeRelativePath}").exists()) { + return "${System.getenv("ANDROID_SDK_ROOT")}/${cmakeRelativePath}" } - if (System.getenv("ANDROID_HOME")) { - return "${System.getenv("ANDROID_HOME")}/cmake/${cmakeVersion}/bin/cmake" + if (System.getenv("ANDROID_HOME") && new File("${System.getenv("ANDROID_HOME")}/${cmakeRelativePath}").exists()) { + return "${System.getenv("ANDROID_HOME")}/${cmakeRelativePath}" } return "cmake" } diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK index 0c00d480eddb..2c954374c38d 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK @@ -17,6 +17,7 @@ rn_android_library( react_native_target("java/com/facebook/hermes/instrumentation:instrumentation"), react_native_target("java/com/facebook/hermes/instrumentation:hermes_samplingprofiler"), react_native_target("java/com/facebook/react/bridge:bridge"), + react_native_target("java/com/facebook/react/common:common"), react_native_target("jni/react/hermes/reactexecutor:jni"), ":runtimeconfig", ], diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java index 48eaaa4c0668..b0e4f24d10d9 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java @@ -9,6 +9,7 @@ import com.facebook.jni.HybridData; import com.facebook.react.bridge.JavaScriptExecutor; +import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.soloader.SoLoader; import javax.annotation.Nullable; @@ -23,11 +24,11 @@ public static void loadLibrary() throws UnsatisfiedLinkError { if (mode_ == null) { // libhermes must be loaded explicitly to invoke its JNI_OnLoad. SoLoader.loadLibrary("hermes"); - try { - SoLoader.loadLibrary("hermes-executor-debug"); + SoLoader.loadLibrary("hermes_executor"); + // libhermes_executor is built differently for Debug & Release so we load the proper mode. + if (ReactBuildConfig.DEBUG == true) { mode_ = "Debug"; - } catch (UnsatisfiedLinkError e) { - SoLoader.loadLibrary("hermes-executor-release"); + } else { mode_ = "Release"; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java b/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java index 28b259596e5d..c67d041787af 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java @@ -113,6 +113,7 @@ public void requestPermissions( @Override public void onRequestPermissionsResult( int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); mDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java index e0c37c31a24e..0ef1e5135067 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java @@ -12,9 +12,9 @@ import static com.facebook.react.uimanager.common.UIManagerType.FABRIC; import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE; -import android.app.Activity; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Insets; import android.graphics.Point; import android.graphics.Rect; import android.os.Build; @@ -33,8 +33,6 @@ import android.widget.FrameLayout; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; -import androidx.core.graphics.Insets; -import androidx.core.view.WindowInsetsCompat; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.ThreadConfined; @@ -776,7 +774,7 @@ public void runApplication() { @VisibleForTesting /* package */ void simulateCheckForKeyboardForTesting() { - if (Build.VERSION.SDK_INT >= 23) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { getCustomGlobalLayoutListener().checkForKeyboardEvents(); } else { getCustomGlobalLayoutListener().checkForKeyboardEventsLegacy(); @@ -907,9 +905,7 @@ public void onGlobalLayout() { return; } - // WindowInsetsCompat IME measurement is reliable for API level 23+. - // https://developer.android.com/jetpack/androidx/releases/core#1.5.0-alpha02 - if (Build.VERSION.SDK_INT >= 23) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { checkForKeyboardEvents(); } else { checkForKeyboardEventsLegacy(); @@ -919,22 +915,44 @@ public void onGlobalLayout() { checkForDeviceDimensionsChanges(); } - @RequiresApi(api = Build.VERSION_CODES.M) + private @Nullable WindowManager.LayoutParams getWindowLayoutParams() { + View view = ReactRootView.this; + if (view.getLayoutParams() instanceof WindowManager.LayoutParams) { + return (WindowManager.LayoutParams) view.getLayoutParams(); + } + while (view.getParent() instanceof View) { + view = (View) view.getParent(); + if (view.getLayoutParams() instanceof WindowManager.LayoutParams) { + return (WindowManager.LayoutParams) view.getLayoutParams(); + } + } + return null; + } + + @RequiresApi(api = Build.VERSION_CODES.R) private void checkForKeyboardEvents() { getRootView().getWindowVisibleDisplayFrame(mVisibleViewArea); WindowInsets rootInsets = getRootView().getRootWindowInsets(); - WindowInsetsCompat compatRootInsets = WindowInsetsCompat.toWindowInsetsCompat(rootInsets); + if (rootInsets == null) { + return; + } - boolean keyboardIsVisible = compatRootInsets.isVisible(WindowInsetsCompat.Type.ime()); + boolean keyboardIsVisible = rootInsets.isVisible(WindowInsets.Type.ime()); if (keyboardIsVisible != mKeyboardIsVisible) { mKeyboardIsVisible = keyboardIsVisible; if (keyboardIsVisible) { - Insets imeInsets = compatRootInsets.getInsets(WindowInsetsCompat.Type.ime()); - Insets barInsets = compatRootInsets.getInsets(WindowInsetsCompat.Type.systemBars()); + Insets imeInsets = rootInsets.getInsets(WindowInsets.Type.ime()); + Insets barInsets = rootInsets.getInsets(WindowInsets.Type.systemBars()); int height = imeInsets.bottom - barInsets.bottom; - int softInputMode = ((Activity) getContext()).getWindow().getAttributes().softInputMode; + int softInputMode; + WindowManager.LayoutParams windowLayoutParams = getWindowLayoutParams(); + if (windowLayoutParams != null) { + softInputMode = windowLayoutParams.softInputMode; + } else { + return; + } int screenY = softInputMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING ? mVisibleViewArea.bottom - height diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/FrameBasedAnimationDriver.java b/ReactAndroid/src/main/java/com/facebook/react/animated/FrameBasedAnimationDriver.java index 798fcffd7442..711e050e6800 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/FrameBasedAnimationDriver.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/FrameBasedAnimationDriver.java @@ -7,9 +7,12 @@ package com.facebook.react.animated; +import com.facebook.common.logging.FLog; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableType; +import com.facebook.react.common.ReactConstants; +import com.facebook.react.common.build.ReactBuildConfig; /** * Implementation of {@link AnimationDriver} which provides a support for simple time-based @@ -70,7 +73,17 @@ public void runAnimationStep(long frameTimeNanos) { long timeFromStartMillis = (frameTimeNanos - mStartFrameTimeNanos) / 1000000; int frameIndex = (int) Math.round(timeFromStartMillis / FRAME_TIME_MILLIS); if (frameIndex < 0) { - throw new IllegalStateException("Calculated frame index should never be lower than 0"); + String message = + "Calculated frame index should never be lower than 0. Called with frameTimeNanos " + + frameTimeNanos + + " and mStartFrameTimeNanos " + + mStartFrameTimeNanos; + if (ReactBuildConfig.DEBUG) { + throw new IllegalStateException(message); + } else { + FLog.w(ReactConstants.TAG, message); + return; + } } else if (mHasFinished) { // nothing to do here return; diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java index 0b787014524b..3dae1f0ba165 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java @@ -39,15 +39,21 @@ public static int getJNIPassCounter() { return mJniCallCounter; } - private HashMap getLocalMap() { - if (mLocalMap != null) { - return mLocalMap; - } + private void ensureKeysAreImported() { synchronized (this) { if (mKeys == null) { mKeys = Assertions.assertNotNull(importKeys()); mJniCallCounter++; } + } + } + + private HashMap getLocalMap() { + if (mLocalMap != null) { + return mLocalMap; + } + ensureKeysAreImported(); + synchronized (this) { if (mLocalMap == null) { Object[] values = Assertions.assertNotNull(importValues()); mJniCallCounter++; @@ -69,11 +75,8 @@ private HashMap getLocalMap() { if (mLocalTypeMap != null) { return mLocalTypeMap; } + ensureKeysAreImported(); synchronized (this) { - if (mKeys == null) { - mKeys = Assertions.assertNotNull(importKeys()); - mJniCallCounter++; - } // check that no other thread has already updated if (mLocalTypeMap == null) { Object[] types = Assertions.assertNotNull(importTypes()); @@ -187,48 +190,47 @@ public int getInt(@NonNull String name) { @Override public @NonNull Iterator> getEntryIterator() { - if (mKeys == null) { - mKeys = Assertions.assertNotNull(importKeys()); - } + ensureKeysAreImported(); final String[] iteratorKeys = mKeys; - final Object[] iteratorValues = Assertions.assertNotNull(importValues()); - return new Iterator>() { - int currentIndex = 0; + synchronized (this) { + final Object[] iteratorValues = Assertions.assertNotNull(importValues()); - @Override - public boolean hasNext() { - return currentIndex < iteratorKeys.length; - } + return new Iterator>() { + int currentIndex = 0; - @Override - public Map.Entry next() { - final int index = currentIndex++; - return new Map.Entry() { - @Override - public String getKey() { - return iteratorKeys[index]; - } - - @Override - public Object getValue() { - return iteratorValues[index]; - } - - @Override - public Object setValue(Object value) { - throw new UnsupportedOperationException( - "Can't set a value while iterating over a ReadableNativeMap"); - } - }; - } - }; + @Override + public boolean hasNext() { + return currentIndex < iteratorKeys.length; + } + + @Override + public Map.Entry next() { + final int index = currentIndex++; + return new Map.Entry() { + @Override + public String getKey() { + return iteratorKeys[index]; + } + + @Override + public Object getValue() { + return iteratorValues[index]; + } + + @Override + public Object setValue(Object value) { + throw new UnsupportedOperationException( + "Can't set a value while iterating over a ReadableNativeMap"); + } + }; + } + }; + } } @Override public @NonNull ReadableMapKeySetIterator keySetIterator() { - if (mKeys == null) { - mKeys = Assertions.assertNotNull(importKeys()); - } + ensureKeysAreImported(); final String[] iteratorKeys = mKeys; return new ReadableMapKeySetIterator() { int currentIndex = 0; 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 0141e70c3eb6..8fece5579f94 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java @@ -20,6 +20,7 @@ import android.graphics.Color; import android.graphics.Typeface; import android.hardware.SensorManager; +import android.os.Build; import android.util.Pair; import android.view.Gravity; import android.view.View; @@ -1098,7 +1099,7 @@ private void reload() { if (!mIsReceiverRegistered) { IntentFilter filter = new IntentFilter(); filter.addAction(getReloadAppAction(mApplicationContext)); - mApplicationContext.registerReceiver(mReloadAppBroadcastReceiver, filter); + compatRegisterReceiver(mApplicationContext, mReloadAppBroadcastReceiver, filter, true); mIsReceiverRegistered = true; } @@ -1214,4 +1215,21 @@ public void setPackagerLocationCustomizer( return mSurfaceDelegateFactory.createSurfaceDelegate(moduleName); } + + /** + * Starting with Android 14, apps and services that target Android 14 and use context-registered + * receivers are required to specify a flag to indicate whether or not the receiver should be + * exported to all other apps on the device: either RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED + * + *

https://developer.android.com/about/versions/14/behavior-changes-14#runtime-receivers-exported + */ + private void compatRegisterReceiver( + Context context, BroadcastReceiver receiver, IntentFilter filter, boolean exported) { + if (Build.VERSION.SDK_INT >= 34 && context.getApplicationInfo().targetSdkVersion >= 34) { + context.registerReceiver( + receiver, filter, exported ? Context.RECEIVER_EXPORTED : Context.RECEIVER_NOT_EXPORTED); + } else { + context.registerReceiver(receiver, filter); + } + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index d2214c67f8d1..4312ecb9df66 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -17,6 +17,6 @@ public class ReactNativeVersion { public static final Map VERSION = MapBuilder.of( "major", 0, "minor", 71, - "patch", 0, - "prerelease", "rc.1"); + "patch", 17, + "prerelease", null); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.java index 438ec3fd0b57..9cbb6d11731f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.java @@ -204,6 +204,11 @@ public ColorPropSetter(ReactProp prop, Method setter, int defaultValue) { mDefaultValue = defaultValue; } + public ColorPropSetter(ReactPropGroup prop, Method setter, int index, int defaultValue) { + super(prop, "mixed", setter, index); + mDefaultValue = defaultValue; + } + @Override protected Object getValueOrDefault(Object value, Context context) { if (value == null) { @@ -331,6 +336,10 @@ public BoxedColorPropSetter(ReactProp prop, Method setter) { super(prop, "mixed", setter); } + public BoxedColorPropSetter(ReactPropGroup prop, Method setter, int index) { + super(prop, "mixed", setter, index); + } + @Override protected @Nullable Object getValueOrDefault(Object value, Context context) { if (value != null) { @@ -463,7 +472,11 @@ private static void createPropSetters( } } else if (propTypeClass == int.class) { for (int i = 0; i < names.length; i++) { - props.put(names[i], new IntPropSetter(annotation, method, i, annotation.defaultInt())); + if ("Color".equals(annotation.customType())) { + props.put(names[i], new ColorPropSetter(annotation, method, i, annotation.defaultInt())); + } else { + props.put(names[i], new IntPropSetter(annotation, method, i, annotation.defaultInt())); + } } } else if (propTypeClass == float.class) { for (int i = 0; i < names.length; i++) { @@ -476,7 +489,11 @@ private static void createPropSetters( } } else if (propTypeClass == Integer.class) { for (int i = 0; i < names.length; i++) { - props.put(names[i], new BoxedIntPropSetter(annotation, method, i)); + if ("Color".equals(annotation.customType())) { + props.put(names[i], new BoxedColorPropSetter(annotation, method, i)); + } else { + props.put(names[i], new BoxedIntPropSetter(annotation, method, i)); + } } } else { throw new RuntimeException( diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLetterSpacingSpan.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLetterSpacingSpan.java index 3b9cf58e33d3..d537cd5dccc1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLetterSpacingSpan.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLetterSpacingSpan.java @@ -37,6 +37,10 @@ public void updateMeasureState(TextPaint paint) { apply(paint); } + public float getSpacing() { + return mLetterSpacing; + } + private void apply(TextPaint paint) { if (!Float.isNaN(mLetterSpacing)) { paint.setLetterSpacing(mLetterSpacing); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java index b249126cf957..7866390bfa09 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java @@ -71,6 +71,10 @@ public int getWeight() { return mFontFamily; } + public @Nullable String getFontFeatureSettings() { + return mFeatureSettings; + } + private static void apply( Paint paint, int style, diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java index f1591a5fe35d..82c9f5d75ac5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java @@ -31,8 +31,6 @@ public class ReactTextUpdate { private final int mSelectionEnd; private final int mJustificationMode; - public boolean mContainsMultipleFragments; - /** * @deprecated Use a non-deprecated constructor for ReactTextUpdate instead. This one remains * because it's being used by a unit test that isn't currently open source. @@ -142,13 +140,11 @@ public static ReactTextUpdate buildReactTextUpdateFromState( int jsEventCounter, int textAlign, int textBreakStrategy, - int justificationMode, - boolean containsMultipleFragments) { + int justificationMode) { ReactTextUpdate reactTextUpdate = new ReactTextUpdate( text, jsEventCounter, false, textAlign, textBreakStrategy, justificationMode); - reactTextUpdate.mContainsMultipleFragments = containsMultipleFragments; return reactTextUpdate; } 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 e5e405682f00..6e742793eafe 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 @@ -54,7 +54,6 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie private boolean mContainsImages; private final int mDefaultGravityHorizontal; private final int mDefaultGravityVertical; - private int mTextAlign; private int mNumberOfLines; private TextUtils.TruncateAt mEllipsizeLocation; private boolean mAdjustsFontSizeToFit; @@ -69,8 +68,7 @@ public ReactTextView(Context context) { super(context); // Get these defaults only during the constructor - these should never be set otherwise - mDefaultGravityHorizontal = - getGravity() & (Gravity.HORIZONTAL_GRAVITY_MASK | Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK); + mDefaultGravityHorizontal = getGravityHorizontal(); mDefaultGravityVertical = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; initView(); @@ -89,10 +87,10 @@ private void initView() { mReactBackgroundManager = new ReactViewBackgroundManager(this); - mTextAlign = Gravity.NO_GRAVITY; mNumberOfLines = ViewDefaults.NUMBER_OF_LINES; mAdjustsFontSizeToFit = false; mLinkifyMaskType = 0; + mNotifyOnInlineViewLayout = false; mTextIsSelectable = false; mEllipsizeLocation = TextUtils.TruncateAt.END; @@ -392,10 +390,9 @@ public void setText(ReactTextUpdate update) { } int nextTextAlign = update.getTextAlign(); - if (mTextAlign != nextTextAlign) { - mTextAlign = nextTextAlign; + if (nextTextAlign != getGravityHorizontal()) { + setGravityHorizontal(nextTextAlign); } - setGravityHorizontal(mTextAlign); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (getBreakStrategy() != update.getTextBreakStrategy()) { setBreakStrategy(update.getTextBreakStrategy()); @@ -552,6 +549,11 @@ public boolean hasOverlappingRendering() { return false; } + /* package */ int getGravityHorizontal() { + return getGravity() + & (Gravity.HORIZONTAL_GRAVITY_MASK | Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK); + } + /* package */ void setGravityHorizontal(int gravityHorizontal) { if (gravityHorizontal == 0) { gravityHorizontal = mDefaultGravityHorizontal; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java index 0c8a7f0621b9..705223f832d4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java @@ -8,6 +8,7 @@ package com.facebook.react.views.text; import android.content.Context; +import android.os.Build; import android.text.Spannable; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -23,6 +24,7 @@ import com.facebook.react.uimanager.ReactStylesDiffMap; import com.facebook.react.uimanager.StateWrapper; import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewProps; import com.facebook.yoga.YogaMeasureMode; import java.util.HashMap; import java.util.Map; @@ -148,15 +150,19 @@ public Object updateState( view.setSpanned(spanned); int textBreakStrategy = - TextAttributeProps.getTextBreakStrategy(paragraphAttributes.getString("textBreakStrategy")); + TextAttributeProps.getTextBreakStrategy( + paragraphAttributes.getString(ViewProps.TEXT_BREAK_STRATEGY)); + int currentJustificationMode = + Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? 0 : view.getJustificationMode(); return new ReactTextUpdate( spanned, state.hasKey("mostRecentEventCount") ? state.getInt("mostRecentEventCount") : -1, false, // TODO add this into local Data - TextAttributeProps.getTextAlignment(props, TextLayoutManager.isRTL(attributedString)), + TextAttributeProps.getTextAlignment( + props, TextLayoutManager.isRTL(attributedString), view.getGravityHorizontal()), textBreakStrategy, - TextAttributeProps.getJustificationMode(props)); + TextAttributeProps.getJustificationMode(props, currentJustificationMode)); } private Object getReactTextUpdate(ReactTextView view, ReactStylesDiffMap props, MapBuffer state) { @@ -171,15 +177,17 @@ private Object getReactTextUpdate(ReactTextView view, ReactStylesDiffMap props, int textBreakStrategy = TextAttributeProps.getTextBreakStrategy( paragraphAttributes.getString(TextLayoutManagerMapBuffer.PA_KEY_TEXT_BREAK_STRATEGY)); + int currentJustificationMode = + Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? 0 : view.getJustificationMode(); return new ReactTextUpdate( spanned, -1, // UNUSED FOR TEXT false, // TODO add this into local Data TextAttributeProps.getTextAlignment( - props, TextLayoutManagerMapBuffer.isRTL(attributedString)), + props, TextLayoutManagerMapBuffer.isRTL(attributedString), view.getGravityHorizontal()), textBreakStrategy, - TextAttributeProps.getJustificationMode(props)); + TextAttributeProps.getJustificationMode(props, currentJustificationMode)); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java index 787ab9bb14db..0a14e28af3e4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java @@ -249,35 +249,35 @@ public static TextAttributeProps fromReadableMap(ReactStylesDiffMap props) { return result; } - public static int getTextAlignment(ReactStylesDiffMap props, boolean isRTL) { - @Nullable - String textAlignPropValue = - props.hasKey(ViewProps.TEXT_ALIGN) ? props.getString(ViewProps.TEXT_ALIGN) : null; - int textAlignment; + public static int getTextAlignment(ReactStylesDiffMap props, boolean isRTL, int defaultValue) { + if (!props.hasKey(ViewProps.TEXT_ALIGN)) { + return defaultValue; + } + String textAlignPropValue = props.getString(ViewProps.TEXT_ALIGN); if ("justify".equals(textAlignPropValue)) { - textAlignment = Gravity.LEFT; + return Gravity.LEFT; } else { if (textAlignPropValue == null || "auto".equals(textAlignPropValue)) { - textAlignment = Gravity.NO_GRAVITY; + return Gravity.NO_GRAVITY; } else if ("left".equals(textAlignPropValue)) { - textAlignment = isRTL ? Gravity.RIGHT : Gravity.LEFT; + return isRTL ? Gravity.RIGHT : Gravity.LEFT; } else if ("right".equals(textAlignPropValue)) { - textAlignment = isRTL ? Gravity.LEFT : Gravity.RIGHT; + return isRTL ? Gravity.LEFT : Gravity.RIGHT; } else if ("center".equals(textAlignPropValue)) { - textAlignment = Gravity.CENTER_HORIZONTAL; + return Gravity.CENTER_HORIZONTAL; } else { throw new JSApplicationIllegalArgumentException("Invalid textAlign: " + textAlignPropValue); } } - return textAlignment; } - public static int getJustificationMode(ReactStylesDiffMap props) { - @Nullable - String textAlignPropValue = - props.hasKey(ViewProps.TEXT_ALIGN) ? props.getString(ViewProps.TEXT_ALIGN) : null; + public static int getJustificationMode(ReactStylesDiffMap props, int defaultValue) { + if (!props.hasKey(ViewProps.TEXT_ALIGN)) { + return defaultValue; + } + String textAlignPropValue = props.getString(ViewProps.TEXT_ALIGN); if ("justify".equals(textAlignPropValue) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { return Layout.JUSTIFICATION_MODE_INTER_WORD; } 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 14863e498018..290bd23f2e0b 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 @@ -11,6 +11,8 @@ import static com.facebook.react.views.text.TextAttributeProps.UNSET; import android.content.Context; +import android.graphics.Color; +import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.Drawable; @@ -50,15 +52,19 @@ import com.facebook.react.views.text.CustomLineHeightSpan; import com.facebook.react.views.text.CustomStyleSpan; import com.facebook.react.views.text.ReactAbsoluteSizeSpan; +import com.facebook.react.views.text.ReactBackgroundColorSpan; +import com.facebook.react.views.text.ReactForegroundColorSpan; import com.facebook.react.views.text.ReactSpan; +import com.facebook.react.views.text.ReactStrikethroughSpan; import com.facebook.react.views.text.ReactTextUpdate; import com.facebook.react.views.text.ReactTypefaceUtils; +import com.facebook.react.views.text.ReactUnderlineSpan; import com.facebook.react.views.text.TextAttributes; import com.facebook.react.views.text.TextInlineImageSpan; import com.facebook.react.views.text.TextLayoutManager; import com.facebook.react.views.view.ReactViewBackgroundManager; import java.util.ArrayList; -import java.util.List; +import java.util.Objects; /** * A wrapper around the EditText that lets us better control what happens when an EditText gets @@ -82,7 +88,6 @@ public class ReactEditText extends AppCompatEditText // *TextChanged events should be triggered. This is less expensive than removing the text // listeners and adding them back again after the text change is completed. protected boolean mIsSettingTextFromJS; - protected boolean mIsSettingTextFromCacheUpdate = false; private int mDefaultGravityHorizontal; private int mDefaultGravityVertical; @@ -362,7 +367,7 @@ protected void onSelectionChanged(int selStart, int selEnd) { } super.onSelectionChanged(selStart, selEnd); - if (!mIsSettingTextFromCacheUpdate && mSelectionWatcher != null && hasFocus()) { + if (mSelectionWatcher != null && hasFocus()) { mSelectionWatcher.onSelectionChanged(selStart, selEnd); } } @@ -512,6 +517,14 @@ public void setFontStyle(String fontStyleString) { } } + @Override + public void setFontFeatureSettings(String fontFeatureSettings) { + if (!Objects.equals(fontFeatureSettings, getFontFeatureSettings())) { + super.setFontFeatureSettings(fontFeatureSettings); + mTypefaceDirty = true; + } + } + public void maybeUpdateTypeface() { if (!mTypefaceDirty) { return; @@ -523,6 +536,17 @@ public void maybeUpdateTypeface() { ReactTypefaceUtils.applyStyles( getTypeface(), mFontStyle, mFontWeight, mFontFamily, getContext().getAssets()); setTypeface(newTypeface); + + // Match behavior of CustomStyleSpan and enable SUBPIXEL_TEXT_FLAG when setting anything + // nonstandard + if (mFontStyle != UNSET + || mFontWeight != UNSET + || mFontFamily != null + || getFontFeatureSettings() != null) { + setPaintFlags(getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG); + } else { + setPaintFlags(getPaintFlags() & (~Paint.SUBPIXEL_TEXT_FLAG)); + } } // VisibleForTesting from {@link TextInputEventsTestCase}. @@ -584,7 +608,9 @@ public void maybeSetText(ReactTextUpdate reactTextUpdate) { SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(reactTextUpdate.getText()); - manageSpans(spannableStringBuilder, reactTextUpdate.mContainsMultipleFragments); + manageSpans(spannableStringBuilder); + stripStyleEquivalentSpans(spannableStringBuilder); + mContainsImages = reactTextUpdate.containsImages(); // When we update text, we trigger onChangeText code that will @@ -611,7 +637,7 @@ public void maybeSetText(ReactTextUpdate reactTextUpdate) { } // Update cached spans (in Fabric only). - updateCachedSpannable(false); + updateCachedSpannable(); } /** @@ -620,8 +646,7 @@ public void maybeSetText(ReactTextUpdate reactTextUpdate) { * will adapt to the new text, hence why {@link SpannableStringBuilder#replace} never removes * them. */ - private void manageSpans( - SpannableStringBuilder spannableStringBuilder, boolean skipAddSpansForMeasurements) { + private void manageSpans(SpannableStringBuilder spannableStringBuilder) { Object[] spans = getText().getSpans(0, length(), Object.class); for (int spanIdx = 0; spanIdx < spans.length; spanIdx++) { Object span = spans[spanIdx]; @@ -649,96 +674,187 @@ private void manageSpans( spannableStringBuilder.setSpan(span, spanStart, spanEnd, spanFlags); } } + } - // In Fabric only, apply necessary styles to entire span - // If the Spannable was constructed from multiple fragments, we don't apply any spans that could - // impact the whole Spannable, because that would override "local" styles per-fragment - if (!skipAddSpansForMeasurements) { - addSpansForMeasurement(getText()); - } + // TODO: Replace with Predicate and lambdas once Java 8 builds in OSS + interface SpanPredicate { + boolean test(T span); } - private static boolean sameTextForSpan( - final Editable oldText, - final SpannableStringBuilder newText, - final int start, - final int end) { - if (start > newText.length() || end > newText.length()) { - return false; + /** + * Remove spans from the SpannableStringBuilder which can be represented by TextAppearance + * attributes on the underlying EditText. This works around instability on Samsung devices with + * the presence of spans https://github.com/facebook/react-native/issues/35936 (S318090) + */ + private void stripStyleEquivalentSpans(SpannableStringBuilder sb) { + stripSpansOfKind( + sb, + ReactAbsoluteSizeSpan.class, + new SpanPredicate() { + @Override + public boolean test(ReactAbsoluteSizeSpan span) { + return span.getSize() == mTextAttributes.getEffectiveFontSize(); + } + }); + + stripSpansOfKind( + sb, + ReactBackgroundColorSpan.class, + new SpanPredicate() { + @Override + public boolean test(ReactBackgroundColorSpan span) { + return span.getBackgroundColor() == mReactBackgroundManager.getBackgroundColor(); + } + }); + + stripSpansOfKind( + sb, + ReactForegroundColorSpan.class, + new SpanPredicate() { + @Override + public boolean test(ReactForegroundColorSpan span) { + return span.getForegroundColor() == getCurrentTextColor(); + } + }); + + stripSpansOfKind( + sb, + ReactStrikethroughSpan.class, + new SpanPredicate() { + @Override + public boolean test(ReactStrikethroughSpan span) { + return (getPaintFlags() & Paint.STRIKE_THRU_TEXT_FLAG) != 0; + } + }); + + stripSpansOfKind( + sb, + ReactUnderlineSpan.class, + new SpanPredicate() { + @Override + public boolean test(ReactUnderlineSpan span) { + return (getPaintFlags() & Paint.UNDERLINE_TEXT_FLAG) != 0; + } + }); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + stripSpansOfKind( + sb, + CustomLetterSpacingSpan.class, + new SpanPredicate() { + @Override + public boolean test(CustomLetterSpacingSpan span) { + return span.getSpacing() == mTextAttributes.getEffectiveLetterSpacing(); + } + }); } - for (int charIdx = start; charIdx < end; charIdx++) { - if (oldText.charAt(charIdx) != newText.charAt(charIdx)) { - return false; + + stripSpansOfKind( + sb, + CustomStyleSpan.class, + new SpanPredicate() { + @Override + public boolean test(CustomStyleSpan span) { + return span.getStyle() == mFontStyle + && Objects.equals(span.getFontFamily(), mFontFamily) + && span.getWeight() == mFontWeight + && Objects.equals(span.getFontFeatureSettings(), getFontFeatureSettings()); + } + }); + } + + private void stripSpansOfKind( + SpannableStringBuilder sb, Class clazz, SpanPredicate shouldStrip) { + T[] spans = sb.getSpans(0, sb.length(), clazz); + + for (T span : spans) { + if (shouldStrip.test(span)) { + sb.removeSpan(span); } } - return true; } - // This is hacked in for Fabric. When we delete non-Fabric code, we might be able to simplify or - // clean this up a bit. - private void addSpansForMeasurement(Spannable spannable) { - if (!mFabricViewStateManager.hasStateWrapper()) { - return; - } + /** + * Copy styles represented as attributes to the underlying span, for later measurement or other + * usage outside the ReactEditText. + */ + private void addSpansFromStyleAttributes(SpannableStringBuilder workingText) { + int spanFlags = Spannable.SPAN_INCLUSIVE_INCLUSIVE; - boolean originalDisableTextDiffing = mDisableTextDiffing; - mDisableTextDiffing = true; + // Set all bits for SPAN_PRIORITY so that this span has the highest possible priority + // (least precedence). This ensures the span is behind any overlapping spans. + spanFlags |= Spannable.SPAN_PRIORITY; - int start = 0; - int end = spannable.length(); - - // Remove duplicate spans we might add here - Object[] spans = spannable.getSpans(0, length(), Object.class); - for (Object span : spans) { - int spanFlags = spannable.getSpanFlags(span); - boolean isInclusive = - (spanFlags & Spanned.SPAN_INCLUSIVE_INCLUSIVE) == Spanned.SPAN_INCLUSIVE_INCLUSIVE - || (spanFlags & Spanned.SPAN_INCLUSIVE_EXCLUSIVE) == Spanned.SPAN_INCLUSIVE_EXCLUSIVE; - if (isInclusive - && span instanceof ReactSpan - && spannable.getSpanStart(span) == start - && spannable.getSpanEnd(span) == end) { - spannable.removeSpan(span); - } + workingText.setSpan( + new ReactAbsoluteSizeSpan(mTextAttributes.getEffectiveFontSize()), + 0, + workingText.length(), + spanFlags); + + workingText.setSpan( + new ReactForegroundColorSpan(getCurrentTextColor()), 0, workingText.length(), spanFlags); + + int backgroundColor = mReactBackgroundManager.getBackgroundColor(); + if (backgroundColor != Color.TRANSPARENT) { + workingText.setSpan( + new ReactBackgroundColorSpan(backgroundColor), 0, workingText.length(), spanFlags); } - List ops = new ArrayList<>(); + if ((getPaintFlags() & Paint.STRIKE_THRU_TEXT_FLAG) != 0) { + workingText.setSpan(new ReactStrikethroughSpan(), 0, workingText.length(), spanFlags); + } - if (!Float.isNaN(mTextAttributes.getLetterSpacing())) { - ops.add( - new TextLayoutManager.SetSpanOperation( - start, end, new CustomLetterSpacingSpan(mTextAttributes.getLetterSpacing()))); + if ((getPaintFlags() & Paint.UNDERLINE_TEXT_FLAG) != 0) { + workingText.setSpan(new ReactUnderlineSpan(), 0, workingText.length(), spanFlags); } - ops.add( - new TextLayoutManager.SetSpanOperation( - start, end, new ReactAbsoluteSizeSpan((int) mTextAttributes.getEffectiveFontSize()))); - if (mFontStyle != UNSET || mFontWeight != UNSET || mFontFamily != null) { - ops.add( - new TextLayoutManager.SetSpanOperation( - start, - end, - new CustomStyleSpan( - mFontStyle, - mFontWeight, - null, // TODO: do we need to support FontFeatureSettings / fontVariant? - mFontFamily, - getReactContext(ReactEditText.this).getAssets()))); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + float effectiveLetterSpacing = mTextAttributes.getEffectiveLetterSpacing(); + if (!Float.isNaN(effectiveLetterSpacing)) { + workingText.setSpan( + new CustomLetterSpacingSpan(effectiveLetterSpacing), + 0, + workingText.length(), + spanFlags); + } } - if (!Float.isNaN(mTextAttributes.getEffectiveLineHeight())) { - ops.add( - new TextLayoutManager.SetSpanOperation( - start, end, new CustomLineHeightSpan(mTextAttributes.getEffectiveLineHeight()))); + + if (mFontStyle != UNSET + || mFontWeight != UNSET + || mFontFamily != null + || getFontFeatureSettings() != null) { + workingText.setSpan( + new CustomStyleSpan( + mFontStyle, + mFontWeight, + getFontFeatureSettings(), + mFontFamily, + getContext().getAssets()), + 0, + workingText.length(), + spanFlags); } - int priority = 0; - for (TextLayoutManager.SetSpanOperation op : ops) { - // Actual order of calling {@code execute} does NOT matter, - // but the {@code priority} DOES matter. - op.execute(spannable, priority); - priority++; + float lineHeight = mTextAttributes.getEffectiveLineHeight(); + if (!Float.isNaN(lineHeight)) { + workingText.setSpan(new CustomLineHeightSpan(lineHeight), 0, workingText.length(), spanFlags); } + } - mDisableTextDiffing = originalDisableTextDiffing; + private static boolean sameTextForSpan( + final Editable oldText, + final SpannableStringBuilder newText, + final int start, + final int end) { + if (start > newText.length() || end > newText.length()) { + return false; + } + for (int charIdx = start; charIdx < end; charIdx++) { + if (oldText.charAt(charIdx) != newText.charAt(charIdx)) { + return false; + } + } + return true; } protected boolean showSoftKeyboard() { @@ -795,6 +911,11 @@ private void setIntrinsicContentSize() { } } + /* package */ int getGravityHorizontal() { + return getGravity() + & (Gravity.HORIZONTAL_GRAVITY_MASK | Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK); + } + /* package */ void setGravityHorizontal(int gravityHorizontal) { if (gravityHorizontal == 0) { gravityHorizontal = mDefaultGravityHorizontal; @@ -1005,7 +1126,9 @@ protected void applyTextAttributes() { float effectiveLetterSpacing = mTextAttributes.getEffectiveLetterSpacing(); if (!Float.isNaN(effectiveLetterSpacing)) { - setLetterSpacing(effectiveLetterSpacing); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + setLetterSpacing(effectiveLetterSpacing); + } } } @@ -1020,7 +1143,7 @@ public FabricViewStateManager getFabricViewStateManager() { * TextLayoutManager.java with some very minor modifications. There's some duplication between * here and TextLayoutManager, so there might be an opportunity for refactor. */ - private void updateCachedSpannable(boolean resetStyles) { + private void updateCachedSpannable() { // Noops in non-Fabric if (mFabricViewStateManager == null || !mFabricViewStateManager.hasStateWrapper()) { return; @@ -1030,12 +1153,6 @@ private void updateCachedSpannable(boolean resetStyles) { return; } - if (resetStyles) { - mIsSettingTextFromCacheUpdate = true; - addSpansForMeasurement(getText()); - mIsSettingTextFromCacheUpdate = false; - } - Editable currentText = getText(); boolean haveText = currentText != null && currentText.length() > 0; @@ -1093,11 +1210,9 @@ private void updateCachedSpannable(boolean resetStyles) { // Measure something so we have correct height, even if there's no string. sb.append("I"); } - - // Make sure that all text styles are applied when we're measurable the hint or "blank" text - addSpansForMeasurement(sb); } + addSpansFromStyleAttributes(sb); TextLayoutManager.setCachedSpannabledForTag(getId(), sb); } @@ -1112,7 +1227,7 @@ void setEventDispatcher(@Nullable EventDispatcher eventDispatcher) { private class TextWatcherDelegator implements TextWatcher { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { - if (!mIsSettingTextFromCacheUpdate && !mIsSettingTextFromJS && mListeners != null) { + if (!mIsSettingTextFromJS && mListeners != null) { for (TextWatcher listener : mListeners) { listener.beforeTextChanged(s, start, count, after); } @@ -1126,23 +1241,20 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { TAG, "onTextChanged[" + getId() + "]: " + s + " " + start + " " + before + " " + count); } - if (!mIsSettingTextFromCacheUpdate) { - if (!mIsSettingTextFromJS && mListeners != null) { - for (TextWatcher listener : mListeners) { - listener.onTextChanged(s, start, before, count); - } + if (!mIsSettingTextFromJS && mListeners != null) { + for (TextWatcher listener : mListeners) { + listener.onTextChanged(s, start, before, count); } - - updateCachedSpannable( - !mIsSettingTextFromJS && !mIsSettingTextFromState && start == 0 && before == 0); } + updateCachedSpannable(); + onContentSizeChange(); } @Override public void afterTextChanged(Editable s) { - if (!mIsSettingTextFromCacheUpdate && !mIsSettingTextFromJS && mListeners != null) { + if (!mIsSettingTextFromJS && mListeners != null) { for (TextWatcher listener : mListeners) { listener.afterTextChanged(s); } 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 85fb317a2a9d..5fda12a3f7f4 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 @@ -13,6 +13,7 @@ import android.content.res.ColorStateList; import android.graphics.BlendMode; import android.graphics.BlendModeColorFilter; +import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Build; @@ -67,6 +68,7 @@ import com.facebook.react.views.text.ReactBaseTextShadowNode; import com.facebook.react.views.text.ReactTextUpdate; import com.facebook.react.views.text.ReactTextViewManagerCallback; +import com.facebook.react.views.text.ReactTypefaceUtils; import com.facebook.react.views.text.TextAttributeProps; import com.facebook.react.views.text.TextInlineImageSpan; import com.facebook.react.views.text.TextLayoutManager; @@ -404,6 +406,11 @@ public void setFontStyle(ReactEditText view, @Nullable String fontStyle) { view.setFontStyle(fontStyle); } + @ReactProp(name = ViewProps.FONT_VARIANT) + public void setFontVariant(ReactEditText view, @Nullable ReadableArray fontVariant) { + view.setFontFeatureSettings(ReactTypefaceUtils.parseFontVariant(fontVariant)); + } + @ReactProp(name = ViewProps.INCLUDE_FONT_PADDING, defaultBoolean = true) public void setIncludeFontPadding(ReactEditText view, boolean includepad) { view.setIncludeFontPadding(includepad); @@ -925,6 +932,20 @@ public void setAutoFocus(ReactEditText view, boolean autoFocus) { view.setAutoFocus(autoFocus); } + @ReactProp(name = ViewProps.TEXT_DECORATION_LINE) + public void setTextDecorationLine(ReactEditText view, @Nullable String textDecorationLineString) { + view.setPaintFlags( + view.getPaintFlags() & ~(Paint.STRIKE_THRU_TEXT_FLAG | Paint.UNDERLINE_TEXT_FLAG)); + + for (String token : textDecorationLineString.split(" ")) { + if (token.equals("underline")) { + view.setPaintFlags(view.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + } else if (token.equals("line-through")) { + view.setPaintFlags(view.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); + } + } + } + @ReactPropGroup( names = { ViewProps.BORDER_WIDTH, @@ -1305,10 +1326,7 @@ public Object updateState( } ReadableNativeMap state = stateWrapper.getStateData(); - if (state == null) { - return null; - } - if (!state.hasKey("attributedString")) { + if (state == null || !state.hasKey("attributedString")) { return null; } @@ -1322,19 +1340,19 @@ public Object updateState( TextLayoutManager.getOrCreateSpannableForText( view.getContext(), attributedString, mReactTextViewManagerCallback); - boolean containsMultipleFragments = - attributedString.getArray("fragments").toArrayList().size() > 1; - int textBreakStrategy = - TextAttributeProps.getTextBreakStrategy(paragraphAttributes.getString("textBreakStrategy")); + TextAttributeProps.getTextBreakStrategy( + paragraphAttributes.getString(ViewProps.TEXT_BREAK_STRATEGY)); + int currentJustificationMode = + Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? 0 : view.getJustificationMode(); return ReactTextUpdate.buildReactTextUpdateFromState( spanned, state.getInt("mostRecentEventCount"), - TextAttributeProps.getTextAlignment(props, TextLayoutManager.isRTL(attributedString)), + TextAttributeProps.getTextAlignment( + props, TextLayoutManager.isRTL(attributedString), view.getGravityHorizontal()), textBreakStrategy, - TextAttributeProps.getJustificationMode(props), - containsMultipleFragments); + TextAttributeProps.getJustificationMode(props, currentJustificationMode)); } public Object getReactTextUpdate(ReactEditText view, ReactStylesDiffMap props, MapBuffer state) { @@ -1355,20 +1373,18 @@ public Object getReactTextUpdate(ReactEditText view, ReactStylesDiffMap props, M TextLayoutManagerMapBuffer.getOrCreateSpannableForText( view.getContext(), attributedString, mReactTextViewManagerCallback); - boolean containsMultipleFragments = - attributedString.getMapBuffer(TextLayoutManagerMapBuffer.AS_KEY_FRAGMENTS).getCount() > 1; - int textBreakStrategy = TextAttributeProps.getTextBreakStrategy( paragraphAttributes.getString(TextLayoutManagerMapBuffer.PA_KEY_TEXT_BREAK_STRATEGY)); + int currentJustificationMode = + Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? 0 : view.getJustificationMode(); return ReactTextUpdate.buildReactTextUpdateFromState( spanned, state.getInt(TX_STATE_KEY_MOST_RECENT_EVENT_COUNT), TextAttributeProps.getTextAlignment( - props, TextLayoutManagerMapBuffer.isRTL(attributedString)), + props, TextLayoutManagerMapBuffer.isRTL(attributedString), view.getGravityHorizontal()), textBreakStrategy, - TextAttributeProps.getJustificationMode(props), - containsMultipleFragments); + TextAttributeProps.getJustificationMode(props, currentJustificationMode)); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java index 827aaec706ea..6a53ed80f1be 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java @@ -791,7 +791,7 @@ private void updatePath() { /** Compute mInnerTopLeftCorner */ mInnerTopLeftCorner.x = mInnerClipTempRectForBorderRadius.left; - mInnerTopLeftCorner.y = mInnerClipTempRectForBorderRadius.top * 2; + mInnerTopLeftCorner.y = mInnerClipTempRectForBorderRadius.top; getEllipseIntersectionWithLine( // Ellipse Bounds @@ -817,7 +817,7 @@ private void updatePath() { } mInnerBottomLeftCorner.x = mInnerClipTempRectForBorderRadius.left; - mInnerBottomLeftCorner.y = mInnerClipTempRectForBorderRadius.bottom * -2; + mInnerBottomLeftCorner.y = mInnerClipTempRectForBorderRadius.bottom; getEllipseIntersectionWithLine( // Ellipse Bounds @@ -843,7 +843,7 @@ private void updatePath() { } mInnerTopRightCorner.x = mInnerClipTempRectForBorderRadius.right; - mInnerTopRightCorner.y = mInnerClipTempRectForBorderRadius.top * 2; + mInnerTopRightCorner.y = mInnerClipTempRectForBorderRadius.top; getEllipseIntersectionWithLine( // Ellipse Bounds @@ -869,7 +869,7 @@ private void updatePath() { } mInnerBottomRightCorner.x = mInnerClipTempRectForBorderRadius.right; - mInnerBottomRightCorner.y = mInnerClipTempRectForBorderRadius.bottom * -2; + mInnerBottomRightCorner.y = mInnerClipTempRectForBorderRadius.bottom; getEllipseIntersectionWithLine( // Ellipse Bounds diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundManager.java index 4a5fce52c3a9..9b479fa42214 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundManager.java @@ -19,6 +19,7 @@ public class ReactViewBackgroundManager { private @Nullable ReactViewBackgroundDrawable mReactBackgroundDrawable; private View mView; + private int mColor = Color.TRANSPARENT; public ReactViewBackgroundManager(View view) { this.mView = view; @@ -56,6 +57,10 @@ public void setBackgroundColor(int color) { } } + public int getBackgroundColor() { + return mColor; + } + public void setBorderWidth(int position, float width) { getOrCreateReactViewBackground().setBorderWidth(position, width); } diff --git a/ReactAndroid/src/main/jni/CMakeLists.txt b/ReactAndroid/src/main/jni/CMakeLists.txt index 420794146092..c7ee6155e9cc 100644 --- a/ReactAndroid/src/main/jni/CMakeLists.txt +++ b/ReactAndroid/src/main/jni/CMakeLists.txt @@ -56,6 +56,7 @@ add_react_common_subdir(reactperflogger) add_react_common_subdir(logger) add_react_common_subdir(jsiexecutor) add_react_common_subdir(cxxreact) +add_react_common_subdir(jsc) add_react_common_subdir(jsi) add_react_common_subdir(butter) add_react_common_subdir(callinvoker) diff --git a/ReactAndroid/src/main/jni/react/hermes/reactexecutor/BUCK b/ReactAndroid/src/main/jni/react/hermes/reactexecutor/BUCK index 94229f186158..e292584fa628 100644 --- a/ReactAndroid/src/main/jni/react/hermes/reactexecutor/BUCK +++ b/ReactAndroid/src/main/jni/react/hermes/reactexecutor/BUCK @@ -14,6 +14,6 @@ rn_xplat_cxx_library( headers = [], header_namespace = "", compiler_flags = ["-fexceptions"], - soname = "libhermes-executor.$(ext)", + soname = "libhermes_executor.$(ext)", visibility = ["PUBLIC"], ) diff --git a/ReactAndroid/src/main/jni/react/hermes/reactexecutor/CMakeLists.txt b/ReactAndroid/src/main/jni/react/hermes/reactexecutor/CMakeLists.txt index d446141c7ed9..550b324e8219 100644 --- a/ReactAndroid/src/main/jni/react/hermes/reactexecutor/CMakeLists.txt +++ b/ReactAndroid/src/main/jni/react/hermes/reactexecutor/CMakeLists.txt @@ -8,29 +8,20 @@ set(CMAKE_VERBOSE_MAKEFILE on) file(GLOB_RECURSE hermes_executor_SRC CONFIGURE_DEPENDS *.cpp) -if(${CMAKE_BUILD_TYPE} MATCHES Debug) - set(HERMES_TARGET_SUFFIX debug) -else() - set(HERMES_TARGET_SUFFIX release) -endif() - -set(HERMES_TARGET_NAME hermes-executor-${HERMES_TARGET_SUFFIX}) - -add_library( - ${HERMES_TARGET_NAME} +add_library(hermes_executor SHARED ${hermes_executor_SRC} ) target_compile_options( - ${HERMES_TARGET_NAME} + hermes_executor PRIVATE $<$:-DHERMES_ENABLE_DEBUGGER=1> -fexceptions ) -target_include_directories(${HERMES_TARGET_NAME} PRIVATE .) +target_include_directories(hermes_executor PRIVATE .) target_link_libraries( - ${HERMES_TARGET_NAME} - hermes-executor-common + hermes_executor + hermes_executor_common jsireact fb fbjni diff --git a/ReactAndroid/src/main/jni/react/jscexecutor/BUCK b/ReactAndroid/src/main/jni/react/jscexecutor/BUCK index 7719f27dbc96..8b3e82eb665f 100644 --- a/ReactAndroid/src/main/jni/react/jscexecutor/BUCK +++ b/ReactAndroid/src/main/jni/react/jscexecutor/BUCK @@ -16,7 +16,7 @@ rn_xplat_cxx_library( deps = [ FBJNI_TARGET, react_native_target("jni/react/jni:jni"), - react_native_xplat_target("jsi:JSCRuntime"), + react_native_xplat_target("jsc:JSCRuntime"), react_native_xplat_target("jsiexecutor:jsiexecutor"), ], ) diff --git a/ReactAndroid/src/main/jni/react/jscexecutor/CMakeLists.txt b/ReactAndroid/src/main/jni/react/jscexecutor/CMakeLists.txt index 464aa19ccef8..67858803b3cf 100644 --- a/ReactAndroid/src/main/jni/react/jscexecutor/CMakeLists.txt +++ b/ReactAndroid/src/main/jni/react/jscexecutor/CMakeLists.txt @@ -13,9 +13,22 @@ add_library(jscexecutor SHARED ${jscexecutor_SRC}) target_include_directories(jscexecutor PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +# Patch from Expo: https://github.com/expo/react-native/blob/02714ab44d1e206fa80e81aef618e61017cccdc1/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/CMakeLists.txt#L16-L25 +# Explicitly link libgcc.a to prevent undefined `_Unwind_Resume` symbol and crash from throwing c++ exceptions even someone tries to catch the exceptions. +# according to https://android.googlesource.com/platform/ndk/+/master/docs/BuildSystemMaintainers.md#unwinding, +# we should put the unwinder between static libs and shared libs. +# +# TODO(ncor): we don't need this patch anymore after upgrading to ndk r23 +if(ANDROID_NDK_REVISION VERSION_LESS "23.0.0") + set(LIB_UNWIND gcc) +else() + set(LIB_UNWIND unwind) +endif() + target_link_libraries(jscexecutor jsireact jscruntime + ${LIB_UNWIND} fb fbjni folly_runtime diff --git a/ReactAndroid/src/main/jni/react/jscexecutor/OnLoad.cpp b/ReactAndroid/src/main/jni/react/jscexecutor/OnLoad.cpp index 60450b5c404b..9d38412d1cb9 100644 --- a/ReactAndroid/src/main/jni/react/jscexecutor/OnLoad.cpp +++ b/ReactAndroid/src/main/jni/react/jscexecutor/OnLoad.cpp @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include #include diff --git a/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.h b/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.h index fd2a71134900..921101b6aafa 100644 --- a/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.h +++ b/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.h @@ -7,8 +7,8 @@ #pragma once -#include #include +#include #include #include #include diff --git a/ReactCommon/React-Fabric.podspec b/ReactCommon/React-Fabric.podspec index c28eee60d06f..9c9d69348759 100644 --- a/ReactCommon/React-Fabric.podspec +++ b/ReactCommon/React-Fabric.podspec @@ -78,7 +78,6 @@ Pod::Spec.new do |s| s.subspec "core" do |ss| ss.dependency folly_dep_name, folly_version - ss.dependency "React-jsidynamic", version ss.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags ss.source_files = "react/renderer/core/**/*.{m,mm,cpp,h}" ss.exclude_files = "react/renderer/core/tests" @@ -303,7 +302,6 @@ Pod::Spec.new do |s| s.subspec "uimanager" do |ss| ss.dependency folly_dep_name, folly_version - ss.dependency "React-jsidynamic", version ss.compiler_flags = folly_compiler_flags ss.source_files = "react/renderer/uimanager/**/*.{m,mm,cpp,h}" ss.exclude_files = "react/renderer/uimanager/tests" diff --git a/ReactCommon/ReactCommon.podspec b/ReactCommon/ReactCommon.podspec index 46af7c0411ba..0d9792abc411 100644 --- a/ReactCommon/ReactCommon.podspec +++ b/ReactCommon/ReactCommon.podspec @@ -19,7 +19,7 @@ end folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32 -Wno-gnu-zero-variadic-macro-arguments' folly_version = '2021.07.22.00' boost_compiler_flags = '-Wno-documentation' - +using_hermes = ENV['USE_HERMES'] == nil || ENV['USE_HERMES'] == "1" Pod::Spec.new do |s| s.name = "ReactCommon" s.module_name = "ReactCommon" @@ -49,6 +49,9 @@ Pod::Spec.new do |s| s.dependency "React-logger", version ss.dependency "DoubleConversion" ss.dependency "glog" + if using_hermes + ss.dependency "hermes-engine" + end ss.subspec "bridging" do |sss| sss.dependency "React-jsi", version @@ -56,12 +59,18 @@ Pod::Spec.new do |s| sss.exclude_files = "react/bridging/tests" sss.header_dir = "react/bridging" sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + if using_hermes + sss.dependency "hermes-engine" + end end ss.subspec "core" do |sss| sss.source_files = "react/nativemodule/core/ReactCommon/**/*.{cpp,h}", "react/nativemodule/core/platform/ios/**/*.{mm,cpp,h}" - sss.dependency "React-jsidynamic", version + excluded_files = ENV['USE_FRAMEWORKS'] == nil ? + "react/nativemodule/core/ReactCommon/LongLivedObject.h" : + "react/nativemodule/core/ReactCommon/{LongLivedObject,CallbackWrapper}.h" + sss.exclude_files = excluded_files end s.subspec "react_debug_core" do |sss| diff --git a/ReactCommon/cxxreact/React-cxxreact.podspec b/ReactCommon/cxxreact/React-cxxreact.podspec index 8888f8547334..33910c93eb4f 100644 --- a/ReactCommon/cxxreact/React-cxxreact.podspec +++ b/ReactCommon/cxxreact/React-cxxreact.podspec @@ -46,4 +46,8 @@ Pod::Spec.new do |s| s.dependency "React-perflogger", version s.dependency "React-jsi", version s.dependency "React-logger", version + + if ENV['USE_HERMES'] == nil || ENV['USE_HERMES'] == "1" + s.dependency 'hermes-engine' + end end diff --git a/ReactCommon/cxxreact/ReactNativeVersion.h b/ReactCommon/cxxreact/ReactNativeVersion.h index 3cfc7975bf70..348e0165c9dc 100644 --- a/ReactCommon/cxxreact/ReactNativeVersion.h +++ b/ReactCommon/cxxreact/ReactNativeVersion.h @@ -17,8 +17,8 @@ namespace facebook::react { constexpr struct { int32_t Major = 0; int32_t Minor = 71; - int32_t Patch = 0; - std::string_view Prerelease = "rc.1"; + int32_t Patch = 17; + std::string_view Prerelease = ""; } ReactNativeVersion; } // namespace facebook::react diff --git a/ReactCommon/hermes/React-hermes.podspec b/ReactCommon/hermes/React-hermes.podspec index 1a33547c2c43..d29457ecb7fe 100644 --- a/ReactCommon/hermes/React-hermes.podspec +++ b/ReactCommon/hermes/React-hermes.podspec @@ -44,7 +44,6 @@ Pod::Spec.new do |s| }.merge!(build_type == :debug ? { "GCC_PREPROCESSOR_DEFINITIONS" => "HERMES_ENABLE_DEBUGGER=1" } : {}) s.header_dir = "reacthermes" s.dependency "React-cxxreact", version - s.dependency "React-jsidynamic", version s.dependency "React-jsiexecutor", version s.dependency "React-jsinspector", version s.dependency "React-perflogger", version @@ -53,4 +52,5 @@ Pod::Spec.new do |s| s.dependency "glog" s.dependency "RCT-Folly/Futures", folly_version s.dependency "hermes-engine" + s.dependency "React-jsi" end diff --git a/ReactCommon/hermes/executor/CMakeLists.txt b/ReactCommon/hermes/executor/CMakeLists.txt index a6d8bbac1ddf..10cf67f5f0e7 100644 --- a/ReactCommon/hermes/executor/CMakeLists.txt +++ b/ReactCommon/hermes/executor/CMakeLists.txt @@ -8,21 +8,22 @@ set(CMAKE_VERBOSE_MAKEFILE on) file(GLOB_RECURSE hermes_executor_SRC CONFIGURE_DEPENDS *.cpp) add_library( - hermes-executor-common + hermes_executor_common STATIC ${hermes_executor_SRC} ) -target_include_directories(hermes-executor-common PUBLIC .) -target_link_libraries(hermes-executor-common +target_include_directories(hermes_executor_common PUBLIC .) +target_link_libraries(hermes_executor_common jsireact hermes-engine::libhermes jsi - debug hermes-inspector + debug + hermes_inspector ) if(${CMAKE_BUILD_TYPE} MATCHES Debug) target_compile_options( - hermes-executor-common + hermes_executor_common PRIVATE -DHERMES_ENABLE_DEBUGGER=1 ) diff --git a/ReactCommon/hermes/inspector/CMakeLists.txt b/ReactCommon/hermes/inspector/CMakeLists.txt index 14f6f1ce2639..1b4c6a3b59f4 100644 --- a/ReactCommon/hermes/inspector/CMakeLists.txt +++ b/ReactCommon/hermes/inspector/CMakeLists.txt @@ -8,20 +8,20 @@ set(CMAKE_VERBOSE_MAKEFILE on) file(GLOB hermesinspector_SRC CONFIGURE_DEPENDS *.cpp detail/*.cpp chrome/*.cpp) -add_library(hermes-inspector +add_library(hermes_inspector STATIC ${hermesinspector_SRC}) target_compile_options( - hermes-inspector + hermes_inspector PRIVATE -DHERMES_ENABLE_DEBUGGER=1 -DHERMES_INSPECTOR_FOLLY_KLUDGE=1 -fexceptions ) -target_include_directories(hermes-inspector PUBLIC ${REACT_COMMON_DIR}) -target_link_libraries(hermes-inspector +target_include_directories(hermes_inspector PUBLIC ${REACT_COMMON_DIR}) +target_link_libraries(hermes_inspector jsinspector fb fbjni diff --git a/ReactCommon/jsc/.clang-tidy b/ReactCommon/jsc/.clang-tidy new file mode 100644 index 000000000000..9f33ef5a06d8 --- /dev/null +++ b/ReactCommon/jsc/.clang-tidy @@ -0,0 +1,6 @@ +--- +Checks: '> +clang-diagnostic-*, +' +InheritParentConfig: true +... diff --git a/ReactCommon/jsc/BUCK b/ReactCommon/jsc/BUCK new file mode 100644 index 000000000000..3981ca830a7b --- /dev/null +++ b/ReactCommon/jsc/BUCK @@ -0,0 +1,34 @@ +load("//tools/build_defs/oss:rn_defs.bzl", "APPLE", "IOS", "MACOSX", "get_apple_compiler_flags", "get_apple_inspector_flags", "get_preprocessor_flags_for_build_mode", "react_native_xplat_dep", "rn_xplat_cxx_library") + +APPLE_COMPILER_FLAGS = get_apple_compiler_flags() + +rn_xplat_cxx_library( + name = "JSCRuntime", + srcs = [ + "JSCRuntime.cpp", + ], + header_namespace = "jsc", + exported_headers = [ + "JSCRuntime.h", + ], + apple_sdks = (IOS, MACOSX), + compiler_flags_pedantic = True, + fbobjc_compiler_flags = APPLE_COMPILER_FLAGS + [ + "-Os", + ], + fbobjc_frameworks = [ + "$SDKROOT/System/Library/Frameworks/JavaScriptCore.framework", + ], + fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), + labels = [ + "pfh:ReactNative_CommonInfrastructurePlaceholder", + ], + platforms = APPLE, + visibility = ["PUBLIC"], + xplat_mangled_args = { + "soname": "libjscjsi.$(ext)", + }, + exported_deps = [ + react_native_xplat_dep("jsi:jsi"), + ], +) diff --git a/ReactCommon/jsc/CMakeLists.txt b/ReactCommon/jsc/CMakeLists.txt new file mode 100644 index 000000000000..2f387fa996f6 --- /dev/null +++ b/ReactCommon/jsc/CMakeLists.txt @@ -0,0 +1,35 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +################## +### jscruntime ### +################## + +cmake_minimum_required(VERSION 3.13) +set(CMAKE_VERBOSE_MAKEFILE on) + +add_compile_options( + -fexceptions + -frtti + -O3 + -Wno-unused-lambda-capture + -DLOG_TAG=\"ReactNative\") + +add_library(jscruntime + STATIC + JSCRuntime.h + JSCRuntime.cpp) + +target_include_directories(jscruntime PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +target_link_libraries(jscruntime + folly_runtime + jsc + jsi + glog) + +# TODO: Remove this flag when ready. +# Android has this enabled by default, but the flag is still needed for iOS. +target_compile_options(jscruntime PRIVATE -DRN_FABRIC_ENABLED) diff --git a/ReactCommon/jsi/JSCRuntime.cpp b/ReactCommon/jsc/JSCRuntime.cpp similarity index 99% rename from ReactCommon/jsi/JSCRuntime.cpp rename to ReactCommon/jsc/JSCRuntime.cpp index bbc606561ee3..38ebedaf78d2 100644 --- a/ReactCommon/jsi/JSCRuntime.cpp +++ b/ReactCommon/jsc/JSCRuntime.cpp @@ -300,6 +300,9 @@ class JSCRuntime : public jsi::Runtime { #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0 #define _JSC_NO_ARRAY_BUFFERS #endif +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 160400 +#define _JSC_HAS_INSPECTABLE +#endif #endif #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_11 @@ -396,6 +399,13 @@ JSCRuntime::JSCRuntime(JSGlobalContextRef ctx) stringCounter_(0) #endif { +#ifndef NDEBUG +#ifdef _JSC_HAS_INSPECTABLE + if (__builtin_available(macOS 13.3, iOS 16.4, tvOS 16.4, *)) { + JSGlobalContextSetInspectable(ctx_, true); + } +#endif +#endif } JSCRuntime::~JSCRuntime() { diff --git a/ReactCommon/jsi/JSCRuntime.h b/ReactCommon/jsc/JSCRuntime.h similarity index 100% rename from ReactCommon/jsi/JSCRuntime.h rename to ReactCommon/jsc/JSCRuntime.h diff --git a/ReactCommon/jsi/React-jsc.podspec b/ReactCommon/jsc/React-jsc.podspec similarity index 94% rename from ReactCommon/jsi/React-jsc.podspec rename to ReactCommon/jsc/React-jsc.podspec index ce59f0e69e6a..6bb2347e57ed 100644 --- a/ReactCommon/jsi/React-jsc.podspec +++ b/ReactCommon/jsc/React-jsc.podspec @@ -28,12 +28,8 @@ Pod::Spec.new do |s| s.source_files = "JSCRuntime.{cpp,h}" s.exclude_files = "**/test/*" s.framework = "JavaScriptCore" - s.dependency "React-jsi", version - s.default_subspec = "Default" - s.subspec "Default" do - # no-op - end + s.dependency "React-jsi", version s.subspec "Fabric" do |ss| ss.pod_target_xcconfig = { "OTHER_CFLAGS" => "$(inherited) -DRN_FABRIC_ENABLED" } diff --git a/ReactCommon/jsi/BUCK b/ReactCommon/jsi/BUCK index 2d5e68fe3de0..72d8a39190de 100644 --- a/ReactCommon/jsi/BUCK +++ b/ReactCommon/jsi/BUCK @@ -1,4 +1,4 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "APPLE", "IOS", "MACOSX", "react_native_xplat_dep", "rn_xplat_cxx_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_xplat_dep", "rn_xplat_cxx_library") rn_xplat_cxx_library( name = "jsi", @@ -56,33 +56,3 @@ rn_xplat_cxx_library( react_native_xplat_dep("jsi:jsi"), ], ) - -rn_xplat_cxx_library( - name = "JSCRuntime", - srcs = [ - "JSCRuntime.cpp", - ], - header_namespace = "jsi", - exported_headers = [ - "JSCRuntime.h", - ], - apple_sdks = (IOS, MACOSX), - compiler_flags_pedantic = True, - fbobjc_compiler_flags = [ - "-Os", - ], - fbobjc_frameworks = [ - "$SDKROOT/System/Library/Frameworks/JavaScriptCore.framework", - ], - labels = [ - "pfh:ReactNative_CommonInfrastructurePlaceholder", - ], - platforms = APPLE, - visibility = ["PUBLIC"], - xplat_mangled_args = { - "soname": "libjscjsi.$(ext)", - }, - exported_deps = [ - react_native_xplat_dep("jsi:jsi"), - ], -) diff --git a/ReactCommon/jsi/CMakeLists.txt b/ReactCommon/jsi/CMakeLists.txt index 3f2a8c15d3fa..0967a7d7ee69 100644 --- a/ReactCommon/jsi/CMakeLists.txt +++ b/ReactCommon/jsi/CMakeLists.txt @@ -25,19 +25,3 @@ target_include_directories(jsi PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(jsi folly_runtime glog) - -################## -### jscruntime ### -################## - -add_library(jscruntime STATIC - JSCRuntime.h - JSCRuntime.cpp) - -target_include_directories(jscruntime PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - -target_link_libraries(jscruntime folly_runtime jsc glog) - -# TODO: Remove this flag when ready. -# Android has this enabled by default, but the flag is still needed for iOS. -target_compile_options(jscruntime PRIVATE -DRN_FABRIC_ENABLED) diff --git a/ReactCommon/jsi/React-jsi.podspec b/ReactCommon/jsi/React-jsi.podspec index ac21bada4f44..621faa989600 100644 --- a/ReactCommon/jsi/React-jsi.podspec +++ b/ReactCommon/jsi/React-jsi.podspec @@ -20,6 +20,10 @@ 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 = '2021.07.22.00' +boost_compiler_flags = '-Wno-documentation' + Pod::Spec.new do |s| s.name = "React-jsi" s.version = version @@ -30,18 +34,27 @@ Pod::Spec.new do |s| s.platforms = { :ios => "12.4" } s.source = source + s.header_dir = "jsi" + s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags + s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\"" } + + s.dependency "boost", "1.76.0" + s.dependency "DoubleConversion" + s.dependency "RCT-Folly", folly_version + s.dependency "glog" + if js_engine == :jsc s.source_files = "**/*.{cpp,h}" s.exclude_files = [ - "jsi/JSIDynamic.{h,cpp}", "jsi/jsilib-posix.cpp", "jsi/jsilib-windows.cpp", "**/test/*" ] - s.header_dir = "jsi" + elsif js_engine == :hermes # JSI is provided by hermes-engine when Hermes is enabled - s.source_files = "" + # Just need to provide JSIDynamic in this case. + s.source_files = "jsi/JSIDynamic.{cpp,h}" s.dependency "hermes-engine" end end diff --git a/ReactCommon/jsi/React-jsidynamic.podspec b/ReactCommon/jsi/React-jsidynamic.podspec deleted file mode 100644 index 831c6b010fc4..000000000000 --- a/ReactCommon/jsi/React-jsidynamic.podspec +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -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 if system("git rev-parse --git-dir > /dev/null 2>&1") -else - source[:tag] = "v#{version}" -end - -folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' -folly_version = '2021.07.22.00' -boost_compiler_flags = '-Wno-documentation' - -Pod::Spec.new do |s| - s.name = "React-jsidynamic" - s.version = version - s.summary = "Provides support for converting between folly::dynamic and jsi::value" - s.homepage = "https://reactnative.dev/" - s.license = package["license"] - s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "12.4" } - s.source = source - s.source_files = "jsi/JSIDynamic.{cpp,h}" - s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags - s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\"" } - s.header_dir = 'jsi' - - s.dependency "boost", "1.76.0" - s.dependency "DoubleConversion" - s.dependency "RCT-Folly", folly_version - s.dependency "glog" - s.dependency "React-jsi", version -end diff --git a/ReactCommon/jsiexecutor/React-jsiexecutor.podspec b/ReactCommon/jsiexecutor/React-jsiexecutor.podspec index c0846011f90c..9a6b44756509 100644 --- a/ReactCommon/jsiexecutor/React-jsiexecutor.podspec +++ b/ReactCommon/jsiexecutor/React-jsiexecutor.podspec @@ -36,9 +36,12 @@ Pod::Spec.new do |s| s.dependency "React-cxxreact", version s.dependency "React-jsi", version - s.dependency "React-jsidynamic", version s.dependency "React-perflogger", version s.dependency "RCT-Folly", folly_version s.dependency "DoubleConversion" s.dependency "glog" + + if ENV['USE_HERMES'] == nil || ENV['USE_HERMES'] == "1" + s.dependency 'hermes-engine' + end end diff --git a/ReactCommon/react/bridging/CallbackWrapper.h b/ReactCommon/react/bridging/CallbackWrapper.h index fc2980cb9253..8670f2bf08c6 100644 --- a/ReactCommon/react/bridging/CallbackWrapper.h +++ b/ReactCommon/react/bridging/CallbackWrapper.h @@ -8,7 +8,7 @@ #pragma once #include -#include +#include "LongLivedObject.h" #include diff --git a/ReactCommon/react/nativemodule/core/ReactCommon/CallbackWrapper.h b/ReactCommon/react/nativemodule/core/ReactCommon/CallbackWrapper.h new file mode 100644 index 000000000000..2c105d9c3f72 --- /dev/null +++ b/ReactCommon/react/nativemodule/core/ReactCommon/CallbackWrapper.h @@ -0,0 +1,11 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +// This header is left here for compatibility reasons. +#include diff --git a/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h index 92e10268daf0..613665898dca 100644 --- a/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h +++ b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h @@ -13,8 +13,7 @@ #include #include -#include -#include +#include namespace facebook { namespace react { diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index 88c77ab85014..a66adec1234d 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -2540,6 +2540,11 @@ static void YGJustifyMainAxis( const YGNodeRef child = node->getChild(i); const YGStyle& childStyle = child->getStyle(); const YGLayout childLayout = child->getLayout(); + const bool isLastChild = i == collectedFlexItemsValues.endOfLineIndex - 1; + // remove the gap if it is the last element of the line + if (isLastChild) { + betweenMainDim -= gap; + } if (childStyle.display() == YGDisplayNone) { continue; } diff --git a/android/README.md b/android/README.md new file mode 100644 index 000000000000..613d9a3f2839 --- /dev/null +++ b/android/README.md @@ -0,0 +1,21 @@ +# The `/android` folder inside `react-native` + +Starting from React Native 0.71, we're not shipping the `/android` folder inside the React Native NPM package +anymore due to sizing constraints on NPM. The Android artifacts are distributed via Maven Central. +You can read more about it in this RFC: +https://github.com/react-native-community/discussions-and-proposals/pull/508 + +If you're a library author and you're manipulating the React Native .aar files, to extract headers, +extract `.so` files or do anything with it, you're probably doing something wrong. React Native +0.71 ships with all the necessary logic to let you consume it transparently by just using: + +``` +implementation("com.facebook.react:react-android") +// or to keep backward compatibility with older versions of React Native: +implementation("com.facebook.react:react-native:+") +``` + +You should consider refactoring your library code not to unzip/manipulate the React Native .aar files. + +This README.md file is kept in this folder as some libraries are checking the existence of the `/android` folder +and failing user builds if the folder is missing. diff --git a/build.gradle.kts b/build.gradle.kts index bd1b0dc5ac7f..72cfdd032a72 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -35,6 +35,7 @@ buildscript { dependencies { classpath("com.android.tools.build:gradle:7.3.1") classpath("de.undercouch:gradle-download-task:5.0.1") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10") } } diff --git a/flow-typed/npm/ansi-regex_v5.x.x.js b/flow-typed/npm/ansi-regex_v5.x.x.js new file mode 100644 index 000000000000..150902f4a12e --- /dev/null +++ b/flow-typed/npm/ansi-regex_v5.x.x.js @@ -0,0 +1,14 @@ +/** + * @flow strict + * @format + */ + +declare module 'ansi-regex' { + declare export type Options = { + /** + * Match only the first ANSI escape. + */ + +onlyFirst?: boolean, + }; + declare export default function ansiRegex(options?: Options): RegExp; +} diff --git a/jest/react-native-env.js b/jest/react-native-env.js index b45ac255d9c2..624d3648766c 100644 --- a/jest/react-native-env.js +++ b/jest/react-native-env.js @@ -12,5 +12,7 @@ const NodeEnv = require('jest-environment-node').TestEnvironment; module.exports = class ReactNativeEnv extends NodeEnv { - // this is where we'll add our custom logic + exportConditions() { + return ['react-native']; + } }; diff --git a/package.json b/package.json index 515150860fa1..52ee9519be25 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.71.0-rc.1", + "version": "0.71.17", "bin": "./cli.js", "description": "A framework for building native apps using React", "license": "MIT", @@ -15,9 +15,11 @@ }, "files": [ "android", + "build.gradle.kts", "cli.js", "flow", "flow-typed", + "gradle.properties", "index.js", "interface.js", "jest-preset.js", @@ -61,6 +63,7 @@ "sdks/.hermesversion", "sdks/hermes-engine", "sdks/hermesc", + "settings.gradle.kts", "template.config.js", "template", "!template/node_modules", @@ -85,7 +88,7 @@ "prettier": "prettier --write \"./**/*.{js,md,yml,ts,tsx}\"", "format-check": "prettier --list-different \"./**/*.{js,md,yml,ts,tsx}\"", "update-lock": "npx yarn-deduplicate", - "docker-setup-android": "docker pull reactnativecommunity/react-native-android:6.1", + "docker-setup-android": "docker pull reactnativecommunity/react-native-android:6.2", "docker-build-android": "docker build -t reactnativeci/android -f .circleci/Dockerfiles/Dockerfile.android .", "test-android-run-instrumentation": "docker run --cap-add=SYS_ADMIN -it reactnativeci/android bash .circleci/Dockerfiles/scripts/run-android-docker-instrumentation-tests.sh", "test-android-run-unit": "docker run --cap-add=SYS_ADMIN -it reactnativeci/android bash .circleci/Dockerfiles/scripts/run-android-docker-unit-tests.sh", @@ -97,37 +100,42 @@ "test-e2e-local": "node ./scripts/test-e2e-local.js", "test-e2e-local-clean": "node ./scripts/test-e2e-local-clean.js", "test-ios": "./scripts/objc-test.sh test", - "test-typescript": "dtslint types" + "test-typescript": "dtslint types", + "test-typescript-offline": "dtslint --localTs node_modules/typescript/lib types", + "bump-all-updated-packages": "node ./scripts/monorepo/bump-all-updated-packages", + "align-package-versions": "node ./scripts/monorepo/align-package-versions.js", + "trigger-react-native-release": "node ./scripts/trigger-react-native-release.js" }, "peerDependencies": { "react": "18.2.0" }, "dependencies": { "@jest/create-cache-key-function": "^29.2.1", - "@react-native-community/cli": "10.0.0-alpha.5", - "@react-native-community/cli-platform-android": "10.0.0-alpha.4", - "@react-native-community/cli-platform-ios": "10.0.0-alpha.3", + "@react-native-community/cli": "10.2.7", + "@react-native-community/cli-platform-android": "10.2.0", + "@react-native-community/cli-platform-ios": "10.2.5", "@react-native/assets": "1.0.0", "@react-native/normalize-color": "2.1.0", "@react-native/polyfills": "2.0.0", "abort-controller": "^3.0.0", "anser": "^1.4.9", + "ansi-regex": "^5.0.0", "base64-js": "^1.1.2", - "deprecated-react-native-prop-types": "^2.3.0", + "deprecated-react-native-prop-types": "^3.0.1", "event-target-shim": "^5.0.1", "invariant": "^2.2.4", "jest-environment-node": "^29.2.1", - "jsc-android": "^250230.2.1", + "jsc-android": "^250231.0.0", "memoize-one": "^5.0.0", - "metro-react-native-babel-transformer": "0.73.3", - "metro-runtime": "0.73.3", - "metro-source-map": "0.73.3", + "metro-react-native-babel-transformer": "0.73.10", + "metro-runtime": "0.73.10", + "metro-source-map": "0.73.10", "mkdirp": "^0.5.1", "nullthrows": "^1.1.1", "pretty-format": "^26.5.2", "promise": "^8.3.0", "react-devtools-core": "^4.26.1", - "react-native-gradle-plugin": "^0.71.9", + "react-native-gradle-plugin": "^0.71.19", "react-refresh": "^0.4.0", "react-shallow-renderer": "^16.15.0", "regenerator-runtime": "^0.13.2", @@ -136,21 +144,22 @@ "use-sync-external-store": "^1.0.0", "whatwg-fetch": "^3.0.0", "ws": "^6.2.2", - "react-native-codegen": "^0.71.3" + "react-native-codegen": "^0.71.6" }, "devDependencies": { "flow-bin": "^0.191.0", "hermes-eslint": "0.8.0", "react": "18.2.0", "react-test-renderer": "18.2.0", - "@babel/core": "^7.14.0", + "@babel/core": "^7.20.0", "@babel/eslint-parser": "^7.18.2", - "@babel/generator": "^7.14.0", + "@babel/generator": "^7.20.0", "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/preset-flow": "^7.18.0", "@definitelytyped/dtslint": "^0.0.127", "@react-native-community/eslint-config": "*", "@react-native-community/eslint-plugin": "*", - "@react-native/eslint-plugin-specs": "^0.71.1", + "@react-native/eslint-plugin-specs": "^0.71.2", "@reactions/component": "^2.0.2", "@types/react": "^18.0.18", "@typescript-eslint/parser": "^5.30.5", @@ -174,9 +183,9 @@ "inquirer": "^7.1.0", "jest": "^29.2.1", "jest-junit": "^10.0.0", - "jscodeshift": "^0.13.1", - "metro-babel-register": "0.73.3", - "metro-memory-fs": "0.73.3", + "jscodeshift": "^0.14.0", + "metro-babel-register": "0.73.10", + "metro-memory-fs": "0.73.10", "mkdirp": "^0.5.1", "mock-fs": "^5.1.4", "prettier": "^2.4.1", diff --git a/packages/babel-plugin-codegen/__tests__/__snapshots__/index-test.js.snap b/packages/babel-plugin-codegen/__tests__/__snapshots__/index-test.js.snap index 93cdd3389e1a..5aecf0862f11 100644 --- a/packages/babel-plugin-codegen/__tests__/__snapshots__/index-test.js.snap +++ b/packages/babel-plugin-codegen/__tests__/__snapshots__/index-test.js.snap @@ -2,14 +2,14 @@ exports[`Babel plugin inline view configs can inline config for FullNativeComponent.js 1`] = ` "// @flow -const codegenNativeCommands = require('codegenNativeCommands'); +const codegenNativeCommands = require('codegenNativeCommands'); const codegenNativeComponent = require('codegenNativeComponent'); - import type { Int32, BubblingEventHandler, DirectEventHandler, WithDefault } from 'CodegenFlowtypes'; import type { NativeComponentType } from 'codegenNativeComponent'; import type { ViewProps } from 'ViewPropTypes'; -type ModuleProps = $ReadOnly<{| ...ViewProps, +type ModuleProps = $ReadOnly<{| + ...ViewProps, // Props boolean_default_true_optional_both?: WithDefault, // Events @@ -21,17 +21,13 @@ interface NativeCommands { +hotspotUpdate: (viewRef: React.ElementRef, x: Int32, y: Int32) => void, +scrollTo: (viewRef: React.ElementRef, y: Int32, animated: boolean) => void, } - const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry'); - const { ConditionallyIgnoredEventHandlers } = require('react-native/Libraries/NativeComponent/ViewConfigIgnore'); - const { dispatchCommand } = require(\\"react-native/Libraries/ReactNative/RendererProxy\\"); - let nativeComponentName = 'RCTModule'; export const __INTERNAL_VIEW_CONFIG = { uiViewClassName: 'RCTModule', @@ -61,24 +57,22 @@ export const Commands = { hotspotUpdate(ref, x, y) { dispatchCommand(ref, \\"hotspotUpdate\\", [x, y]); }, - scrollTo(ref, y, animated) { dispatchCommand(ref, \\"scrollTo\\", [y, animated]); } - };" `; exports[`Babel plugin inline view configs can inline config for FullTypedNativeComponent.js 1`] = ` "// @flow -const codegenNativeCommands = require('codegenNativeCommands'); +const codegenNativeCommands = require('codegenNativeCommands'); const codegenNativeComponent = require('codegenNativeComponent'); - import type { NativeComponentType } from 'codegenNativeComponent'; import type { Int32, BubblingEventHandler, DirectEventHandler, WithDefault } from 'CodegenFlowtypes'; import type { ViewProps } from 'ViewPropTypes'; -type ModuleProps = $ReadOnly<{| ...ViewProps, +type ModuleProps = $ReadOnly<{| + ...ViewProps, // Props boolean_default_true_optional_both?: WithDefault, // Events @@ -90,17 +84,13 @@ interface NativeCommands { +hotspotUpdate: (viewRef: React.ElementRef, x: Int32, y: Int32) => void, +scrollTo: (viewRef: React.ElementRef, y: Int32, animated: boolean) => void, } - const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry'); - const { ConditionallyIgnoredEventHandlers } = require('react-native/Libraries/NativeComponent/ViewConfigIgnore'); - const { dispatchCommand } = require(\\"react-native/Libraries/ReactNative/RendererProxy\\"); - let nativeComponentName = 'RCTModule'; export const __INTERNAL_VIEW_CONFIG = { uiViewClassName: 'RCTModule', @@ -130,17 +120,14 @@ export const Commands = { hotspotUpdate(ref, x, y) { dispatchCommand(ref, \\"hotspotUpdate\\", [x, y]); }, - scrollTo(ref, y, animated) { dispatchCommand(ref, \\"scrollTo\\", [y, animated]); } - };" `; exports[`Babel plugin inline view configs can inline config for NotANativeComponent.js 1`] = ` "const requireNativeComponent = require('requireNativeComponent'); - export default 'Not a view config';" `; diff --git a/packages/babel-plugin-codegen/package.json b/packages/babel-plugin-codegen/package.json index 9a06f6cfa73a..fcff465a64cc 100644 --- a/packages/babel-plugin-codegen/package.json +++ b/packages/babel-plugin-codegen/package.json @@ -1,5 +1,5 @@ { - "version": "0.71.1", + "version": "0.71.3", "name": "@react-native/babel-plugin-codegen", "description": "Babel plugin to generate native module and view manager code for React Native.", "repository": { @@ -11,7 +11,7 @@ "index.js" ], "dependencies": { - "react-native-codegen": "*" + "react-native-codegen": "0.71.6" }, "devDependencies": { "@babel/core": "^7.14.0" diff --git a/packages/eslint-config-react-native-community/package.json b/packages/eslint-config-react-native-community/package.json index c9d777b7bd3f..53f6ca2e9b7c 100644 --- a/packages/eslint-config-react-native-community/package.json +++ b/packages/eslint-config-react-native-community/package.json @@ -13,7 +13,7 @@ "dependencies": { "@babel/core": "^7.14.0", "@babel/eslint-parser": "^7.18.2", - "@react-native-community/eslint-plugin": "^1.1.0", + "@react-native-community/eslint-plugin": "^1.3.0", "@typescript-eslint/eslint-plugin": "^5.30.5", "@typescript-eslint/parser": "^5.30.5", "eslint-config-prettier": "^8.5.0", diff --git a/packages/eslint-plugin-specs/package.json b/packages/eslint-plugin-specs/package.json index 2956a52d482a..43289715a98a 100644 --- a/packages/eslint-plugin-specs/package.json +++ b/packages/eslint-plugin-specs/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/eslint-plugin-specs", - "version": "0.71.1", + "version": "0.71.2", "description": "ESLint rules to validate NativeModule and Component Specs", "main": "index.js", "repository": { @@ -20,7 +20,7 @@ "flow-parser": "^0.185.0", "make-dir": "^2.1.0", "pirates": "^4.0.1", - "react-native-codegen": "*", + "react-native-codegen": "0.71.6", "source-map-support": "0.5.0" }, "license": "MIT" diff --git a/packages/react-native-codegen/e2e/__test_fixtures__/components/ArrayPropsNativeComponent.js b/packages/react-native-codegen/e2e/__test_fixtures__/components/ArrayPropsNativeComponent.js index fc24aadc4aeb..b65f3ce50b39 100644 --- a/packages/react-native-codegen/e2e/__test_fixtures__/components/ArrayPropsNativeComponent.js +++ b/packages/react-native-codegen/e2e/__test_fixtures__/components/ArrayPropsNativeComponent.js @@ -35,6 +35,7 @@ type NativeProps = $ReadOnly<{| // edgeInsets?: $ReadOnlyArray, sizes?: WithDefault<$ReadOnlyArray<'small' | 'large'>, 'small'>, object?: $ReadOnlyArray<$ReadOnly<{|prop: string|}>>, + arrayOfObjects?: $ReadOnlyArray<$ReadOnly<{|prop1: Float, prop2: Int32|}>>, |}>; export default (codegenNativeComponent( diff --git a/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GeneratePropsCpp-test.js.snap b/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GeneratePropsCpp-test.js.snap index 63443148619e..6de527c44d34 100644 --- a/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GeneratePropsCpp-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GeneratePropsCpp-test.js.snap @@ -33,7 +33,8 @@ ArrayPropsNativeComponentViewProps::ArrayPropsNativeComponentViewProps( srcs(convertRawProp(context, rawProps, \\"srcs\\", sourceProps.srcs, {})), points(convertRawProp(context, rawProps, \\"points\\", sourceProps.points, {})), sizes(convertRawProp(context, rawProps, \\"sizes\\", sourceProps.sizes, {static_cast(ArrayPropsNativeComponentViewSizes::Small)})), - object(convertRawProp(context, rawProps, \\"object\\", sourceProps.object, {})) + object(convertRawProp(context, rawProps, \\"object\\", sourceProps.object, {})), + arrayOfObjects(convertRawProp(context, rawProps, \\"arrayOfObjects\\", sourceProps.arrayOfObjects, {})) {} } // namespace react diff --git a/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GeneratePropsH-test.js.snap b/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GeneratePropsH-test.js.snap index ba79b2cf4149..91c0ca90fd83 100644 --- a/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GeneratePropsH-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GeneratePropsH-test.js.snap @@ -17,6 +17,7 @@ Object { #include #include #include +#include #include #include #include @@ -106,6 +107,38 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu } } + +struct ArrayPropsNativeComponentViewArrayOfObjectsStruct { + Float prop1; + int prop2; +}; + +static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, ArrayPropsNativeComponentViewArrayOfObjectsStruct &result) { + auto map = (butter::map)value; + + auto tmp_prop1 = map.find(\\"prop1\\"); + if (tmp_prop1 != map.end()) { + fromRawValue(context, tmp_prop1->second, result.prop1); + } + auto tmp_prop2 = map.find(\\"prop2\\"); + if (tmp_prop2 != map.end()) { + fromRawValue(context, tmp_prop2->second, result.prop2); + } +} + +static inline std::string toString(const ArrayPropsNativeComponentViewArrayOfObjectsStruct &value) { + return \\"[Object ArrayPropsNativeComponentViewArrayOfObjectsStruct]\\"; +} + +static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, std::vector &result) { + auto items = (std::vector)value; + for (const auto &item : items) { + ArrayPropsNativeComponentViewArrayOfObjectsStruct newItem; + fromRawValue(context, item, newItem); + result.emplace_back(newItem); + } +} + class JSI_EXPORT ArrayPropsNativeComponentViewProps final : public ViewProps { public: ArrayPropsNativeComponentViewProps() = default; @@ -122,6 +155,7 @@ class JSI_EXPORT ArrayPropsNativeComponentViewProps final : public ViewProps { std::vector points{}; ArrayPropsNativeComponentViewSizesMask sizes{static_cast(ArrayPropsNativeComponentViewSizes::Small)}; std::vector object{}; + std::vector arrayOfObjects{}; }; } // namespace react diff --git a/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GeneratePropsJavaDelegate-test.js.snap b/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GeneratePropsJavaDelegate-test.js.snap index 6e97f60966f9..461895f3b0d4 100644 --- a/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GeneratePropsJavaDelegate-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GeneratePropsJavaDelegate-test.js.snap @@ -53,6 +53,9 @@ public class ArrayPropsNativeComponentViewManagerDelegate { void setPoints(T view, @Nullable ReadableArray value); void setSizes(T view, @Nullable ReadableArray value); void setObject(T view, @Nullable ReadableArray value); + void setArrayOfObjects(T view, @Nullable ReadableArray value); } ", } diff --git a/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GenerateViewConfigJs-test.js.snap b/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GenerateViewConfigJs-test.js.snap index 12fa79b3d4f4..400735e1e9ce 100644 --- a/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GenerateViewConfigJs-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GenerateViewConfigJs-test.js.snap @@ -38,6 +38,7 @@ export const __INTERNAL_VIEW_CONFIG = { points: true, sizes: true, object: true, + arrayOfObjects: true, }, }; diff --git a/packages/react-native-codegen/package.json b/packages/react-native-codegen/package.json index 48240b88ee75..7b93e0ba6b04 100644 --- a/packages/react-native-codegen/package.json +++ b/packages/react-native-codegen/package.json @@ -1,6 +1,6 @@ { "name": "react-native-codegen", - "version": "0.71.3", + "version": "0.71.6", "description": "⚛️ Code generation tools for React Native", "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-codegen", "repository": { @@ -20,7 +20,7 @@ "dependencies": { "@babel/parser": "^7.14.0", "flow-parser": "^0.185.0", - "jscodeshift": "^0.13.1", + "jscodeshift": "^0.14.0", "nullthrows": "^1.1.1" }, "devDependencies": { diff --git a/packages/react-native-codegen/src/generators/components/ComponentsGeneratorUtils.js b/packages/react-native-codegen/src/generators/components/ComponentsGeneratorUtils.js index 5e6b6c9aeb3b..104b35d45293 100644 --- a/packages/react-native-codegen/src/generators/components/ComponentsGeneratorUtils.js +++ b/packages/react-native-codegen/src/generators/components/ComponentsGeneratorUtils.js @@ -270,8 +270,11 @@ function getLocalImports( typeAnnotation.type === 'ArrayTypeAnnotation' && typeAnnotation.elementType.type === 'ObjectTypeAnnotation' ) { + imports.add('#include '); const objectProps = typeAnnotation.elementType.properties; + // $FlowFixMe[incompatible-call] the type is guaranteed to be ObjectTypeAnnotation const objectImports = getImports(objectProps); + // $FlowFixMe[incompatible-call] the type is guaranteed to be ObjectTypeAnnotation const localImports = getLocalImports(objectProps); // $FlowFixMe[method-unbinding] added when improving typing for this parameters objectImports.forEach(imports.add, imports); 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 7f8a84fe0020..30fd96825792 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 @@ -17,6 +17,7 @@ Map { #include #include #include +#include #include #include #include @@ -234,6 +235,7 @@ Map { #include #include #include +#include #include #include #include diff --git a/packages/react-native-gradle-plugin/build.gradle.kts b/packages/react-native-gradle-plugin/build.gradle.kts index dd9a08ae0991..5ea92ee71b41 100644 --- a/packages/react-native-gradle-plugin/build.gradle.kts +++ b/packages/react-native-gradle-plugin/build.gradle.kts @@ -50,8 +50,8 @@ dependencies { } java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } tasks.withType { diff --git a/packages/react-native-gradle-plugin/package.json b/packages/react-native-gradle-plugin/package.json index d5a4546f416f..235bfe988d4e 100644 --- a/packages/react-native-gradle-plugin/package.json +++ b/packages/react-native-gradle-plugin/package.json @@ -1,6 +1,6 @@ { "name": "react-native-gradle-plugin", - "version": "0.71.9", + "version": "0.71.19", "description": "⚛️ Gradle Plugin for React Native", "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-gradle-plugin", "repository": { diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactExtension.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactExtension.kt index 5dfb3737ee9d..9738124c7946 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactExtension.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactExtension.kt @@ -129,9 +129,9 @@ abstract class ReactExtension @Inject constructor(project: Project) { /** * The root directory for all JS files for the app. * - * Default: [root] (i.e. ${rootProject.dir}/../) + * Default: the parent folder of the `/android` folder. */ - val jsRootDir: DirectoryProperty = objects.directoryProperty().convention(root.get()) + val jsRootDir: DirectoryProperty = objects.directoryProperty() /** * The library name that will be used for the codegen artifacts. diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt index 8538eaa9941d..25ee481d3d9f 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt @@ -8,15 +8,18 @@ package com.facebook.react import com.android.build.api.variant.AndroidComponentsExtension +import com.android.build.gradle.AppExtension import com.android.build.gradle.internal.tasks.factory.dependsOn +import com.facebook.react.internal.PrivateReactExtension import com.facebook.react.tasks.BuildCodegenCLITask import com.facebook.react.tasks.GenerateCodegenArtifactsTask import com.facebook.react.tasks.GenerateCodegenSchemaTask import com.facebook.react.utils.AgpConfiguratorUtils.configureBuildConfigFields import com.facebook.react.utils.AgpConfiguratorUtils.configureDevPorts +import com.facebook.react.utils.BackwardCompatUtils.configureBackwardCompatibilityReactMap import com.facebook.react.utils.DependencyUtils.configureDependencies import com.facebook.react.utils.DependencyUtils.configureRepositories -import com.facebook.react.utils.DependencyUtils.readVersionString +import com.facebook.react.utils.DependencyUtils.readVersionAndGroupStrings import com.facebook.react.utils.JsonUtils import com.facebook.react.utils.NdkConfiguratorUtils.configureReactNativeNdk import com.facebook.react.utils.ProjectUtils.needsCodegenFromPackageJson @@ -33,29 +36,66 @@ class ReactPlugin : Plugin { checkJvmVersion(project) val extension = project.extensions.create("react", ReactExtension::class.java, project) + // We register a private extension on the rootProject so that project wide configs + // like codegen config can be propagated from app project to libraries. + val rootExtension = + project.rootProject.extensions.findByType(PrivateReactExtension::class.java) + ?: project.rootProject.extensions.create( + "privateReact", PrivateReactExtension::class.java, project) + // App Only Configuration project.pluginManager.withPlugin("com.android.application") { + // We wire the root extension with the values coming from the app (either user populated or + // defaults). + rootExtension.root.set(extension.root) + rootExtension.reactNativeDir.set(extension.reactNativeDir) + rootExtension.codegenDir.set(extension.codegenDir) + rootExtension.nodeExecutableAndArgs.set(extension.nodeExecutableAndArgs) + project.afterEvaluate { val reactNativeDir = extension.reactNativeDir.get().asFile val propertiesFile = File(reactNativeDir, "ReactAndroid/gradle.properties") - val versionString = readVersionString(propertiesFile) - configureDependencies(project, versionString) + val versionAndGroupStrings = readVersionAndGroupStrings(propertiesFile) + val versionString = versionAndGroupStrings.first + val groupString = versionAndGroupStrings.second + configureDependencies(project, versionString, groupString) configureRepositories(project, reactNativeDir) } configureReactNativeNdk(project, extension) configureBuildConfigFields(project) configureDevPorts(project) + configureBackwardCompatibilityReactMap(project) + + project.extensions.getByType(AndroidComponentsExtension::class.java).apply { + onVariants(selector().all()) { variant -> + project.configureReactTasks(variant = variant, config = extension) + } + } - project.extensions.getByType(AndroidComponentsExtension::class.java).onVariants { variant -> - project.configureReactTasks(variant = variant, config = extension) + // This is a legacy AGP api. Needed as AGP 7.3 is not consuming generated resources correctly. + // Can be removed as we bump to AGP 7.4 stable. + // This registers the $buildDir/generated/res/react/ folder as a + // res folder to be consumed with the old AGP Apis which are not broken. + project.extensions.getByType(AppExtension::class.java).apply { + this.applicationVariants.all { variant -> + val isDebuggableVariant = + extension.debuggableVariants.get().any { it.equals(variant.name, ignoreCase = true) } + val targetName = variant.name.replaceFirstChar { it.uppercase() } + val bundleTaskName = "createBundle${targetName}JsAndAssets" + if (!isDebuggableVariant) { + variant.registerGeneratedResFolders( + project.layout.buildDirectory.files("generated/res/react/${variant.name}")) + variant.mergeResourcesProvider.get().dependsOn(bundleTaskName) + } + } } - configureCodegen(project, extension, isLibrary = false) + configureCodegen(project, extension, rootExtension, isLibrary = false) } // Library Only Configuration project.pluginManager.withPlugin("com.android.library") { - configureCodegen(project, extension, isLibrary = true) + configureCodegen(project, extension, rootExtension, isLibrary = true) } } @@ -78,25 +118,37 @@ class ReactPlugin : Plugin { } } - /** - * A plugin to enable react-native-codegen in Gradle environment. See the Gradle API docs for more - * information: https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html - */ + /** This function sets up `react-native-codegen` in our Gradle plugin. */ @Suppress("UnstableApiUsage") - private fun configureCodegen(project: Project, extension: ReactExtension, isLibrary: Boolean) { + private fun configureCodegen( + project: Project, + localExtension: ReactExtension, + rootExtension: PrivateReactExtension, + isLibrary: Boolean + ) { // First, we set up the output dir for the codegen. val generatedSrcDir = File(project.buildDir, "generated/source/codegen") + // We specify the default value (convention) for jsRootDir. + // It's the root folder for apps (so ../../ from the Gradle project) + // and the package folder for library (so ../ from the Gradle project) + if (isLibrary) { + localExtension.jsRootDir.convention(project.layout.projectDirectory.dir("../")) + } else { + localExtension.jsRootDir.convention(localExtension.root) + } + val buildCodegenTask = project.tasks.register("buildCodegenCLI", BuildCodegenCLITask::class.java) { - it.codegenDir.set(extension.codegenDir) + it.codegenDir.set(rootExtension.codegenDir) val bashWindowsHome = project.findProperty("REACT_WINDOWS_BASH") as String? it.bashWindowsHome.set(bashWindowsHome) // Please note that appNeedsCodegen is triggering a read of the package.json at // configuration time as we need to feed the onlyIf condition of this task. // Therefore, the appNeedsCodegen needs to be invoked inside this lambda. - it.onlyIf { isLibrary || project.needsCodegenFromPackageJson(extension) } + val needsCodegenFromPackageJson = project.needsCodegenFromPackageJson(rootExtension.root) + it.onlyIf { isLibrary || needsCodegenFromPackageJson } } // We create the task to produce schema from JS files. @@ -104,23 +156,25 @@ class ReactPlugin : Plugin { project.tasks.register( "generateCodegenSchemaFromJavaScript", GenerateCodegenSchemaTask::class.java) { it -> it.dependsOn(buildCodegenTask) - it.nodeExecutableAndArgs.set(extension.nodeExecutableAndArgs) - it.codegenDir.set(extension.codegenDir) + it.nodeExecutableAndArgs.set(rootExtension.nodeExecutableAndArgs) + it.codegenDir.set(rootExtension.codegenDir) it.generatedSrcDir.set(generatedSrcDir) // We're reading the package.json at configuration time to properly feed // the `jsRootDir` @Input property of this task & the onlyIf. Therefore, the // parsePackageJson should be invoked inside this lambda. - val packageJson = findPackageJsonFile(project, extension) + val packageJson = findPackageJsonFile(project, rootExtension.root) val parsedPackageJson = packageJson?.let { JsonUtils.fromCodegenJson(it) } val jsSrcsDirInPackageJson = parsedPackageJson?.codegenConfig?.jsSrcsDir if (jsSrcsDirInPackageJson != null) { it.jsRootDir.set(File(packageJson.parentFile, jsSrcsDirInPackageJson)) } else { - it.jsRootDir.set(extension.jsRootDir) + it.jsRootDir.set(localExtension.jsRootDir) } - it.onlyIf { isLibrary || project.needsCodegenFromPackageJson(parsedPackageJson) } + val needsCodegenFromPackageJson = + project.needsCodegenFromPackageJson(rootExtension.root) + it.onlyIf { isLibrary || needsCodegenFromPackageJson } } // We create the task to generate Java code from schema. @@ -128,18 +182,19 @@ class ReactPlugin : Plugin { project.tasks.register( "generateCodegenArtifactsFromSchema", GenerateCodegenArtifactsTask::class.java) { it.dependsOn(generateCodegenSchemaTask) - it.reactNativeDir.set(extension.reactNativeDir) - it.nodeExecutableAndArgs.set(extension.nodeExecutableAndArgs) - it.codegenDir.set(extension.codegenDir) + it.reactNativeDir.set(rootExtension.reactNativeDir) + it.nodeExecutableAndArgs.set(rootExtension.nodeExecutableAndArgs) it.generatedSrcDir.set(generatedSrcDir) - it.packageJsonFile.set(findPackageJsonFile(project, extension)) - it.codegenJavaPackageName.set(extension.codegenJavaPackageName) - it.libraryName.set(extension.libraryName) + it.packageJsonFile.set(findPackageJsonFile(project, rootExtension.root)) + it.codegenJavaPackageName.set(localExtension.codegenJavaPackageName) + it.libraryName.set(localExtension.libraryName) // Please note that appNeedsCodegen is triggering a read of the package.json at // configuration time as we need to feed the onlyIf condition of this task. // Therefore, the appNeedsCodegen needs to be invoked inside this lambda. - it.onlyIf { isLibrary || project.needsCodegenFromPackageJson(extension) } + val needsCodegenFromPackageJson = + project.needsCodegenFromPackageJson(rootExtension.root) + it.onlyIf { isLibrary || needsCodegenFromPackageJson } } // We update the android configuration to include the generated sources. diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt index bb3699d58df0..c7db4db88341 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt @@ -22,14 +22,16 @@ internal fun Project.configureReactTasks(variant: Variant, config: ReactExtensio val targetName = variant.name.replaceFirstChar { it.uppercase() } val targetPath = variant.name - // React js bundle directories + // Resources: generated/assets/react//index.android.bundle val resourcesDir = File(buildDir, "generated/res/react/$targetPath") - // Bundle: generated/assets/react/path/index.android.bundle + // Bundle: generated/assets/react//index.android.bundle val jsBundleDir = File(buildDir, "generated/assets/react/$targetPath") - // Sourcemap: generated/sourcemaps/react/path/index.android.bundle.map + // Sourcemap: generated/sourcemaps/react//index.android.bundle.map val jsSourceMapsDir = File(buildDir, "generated/sourcemaps/react/$targetPath") - // Intermediate packager: intermediates/sourcemaps/react/path/index.android.bundle.packager.map - // Intermediate compiler: intermediates/sourcemaps/react/path/index.android.bundle.compiler.map + // Intermediate packager: + // intermediates/sourcemaps/react//index.android.bundle.packager.map + // Intermediate compiler: + // intermediates/sourcemaps/react//index.android.bundle.compiler.map val jsIntermediateSourceMapsDir = File(buildDir, "intermediates/sourcemaps/react/$targetPath") // The location of the cli.js file for React Native @@ -46,17 +48,17 @@ internal fun Project.configureReactTasks(variant: Variant, config: ReactExtensio config.debuggableVariants.get().any { it.equals(variant.name, ignoreCase = true) } configureNewArchPackagingOptions(project, variant) - configureJsEnginePackagingOptions( - config, variant, isHermesEnabledInThisVariant, isDebuggableVariant) + configureJsEnginePackagingOptions(config, variant, isHermesEnabledInThisVariant) if (!isDebuggableVariant) { + val entryFileEnvVariable = System.getenv("ENTRY_FILE") val bundleTask = tasks.register("createBundle${targetName}JsAndAssets", BundleHermesCTask::class.java) { it.root.set(config.root) it.nodeExecutableAndArgs.set(config.nodeExecutableAndArgs) it.cliFile.set(cliFile) it.bundleCommand.set(config.bundleCommand) - it.entryFile.set(detectedEntryFile(config)) + it.entryFile.set(detectedEntryFile(config, entryFileEnvVariable)) it.extraPackagerArgs.set(config.extraPackagerArgs) it.bundleConfig.set(config.bundleConfig) it.bundleAssetName.set(config.bundleAssetName) @@ -71,7 +73,9 @@ internal fun Project.configureReactTasks(variant: Variant, config: ReactExtensio it.hermesFlags.set(config.hermesFlags) it.reactNativeDir.set(config.reactNativeDir) } - variant.sources.res?.addGeneratedSourceDirectory(bundleTask, BundleHermesCTask::resourcesDir) + // Currently broken inside AGP 7.3 We need to wait for a release of AGP 7.4 in order to use + // the addGeneratedSourceDirectory API. + // variant.sources.res?.addGeneratedSourceDirectory(bundleTask, BundleHermesCTask::resourcesDir) variant.sources.assets?.addGeneratedSourceDirectory(bundleTask, BundleHermesCTask::jsBundleDir) } } diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/internal/PrivateReactExtension.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/internal/PrivateReactExtension.kt new file mode 100644 index 000000000000..011640ba086d --- /dev/null +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/internal/PrivateReactExtension.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.internal + +import javax.inject.Inject +import org.gradle.api.Project +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.ListProperty + +/** + * A private extension we set on the rootProject to make easier to share values at execution time + * between app project and library project. + * + * Specifically, the [codegenDir], [reactNativeDir] and other properties should be provided by apps + * (for setups like a monorepo which are app specific) and libraries should honor those values. + * + * Users are not supposed to access directly this extension from their build.gradle file. + */ +abstract class PrivateReactExtension @Inject constructor(project: Project) { + + private val objects = project.objects + + val root: DirectoryProperty = + objects + .directoryProperty() + .convention( + // This is the default for the project root if the users hasn't specified anything. + // If the project is called "react-native-github" + // - We're inside the Github Repo -> root is defined by RN Tester (so no default + // needed) + // - We're inside an includedBuild as we're performing a build from source + // (then we're inside `node_modules/react-native`, so default should be ../../) + // If the project is called in any other name + // - We're inside a user project, so inside the ./android folder. Default should be + // ../ + // User can always override this default by setting a `root =` inside the template. + if (project.rootProject.name == "react-native-github") { + project.rootProject.layout.projectDirectory.dir("../../") + } else { + project.rootProject.layout.projectDirectory.dir("../") + }) + + val reactNativeDir: DirectoryProperty = + objects.directoryProperty().convention(root.dir("node_modules/react-native")) + + val nodeExecutableAndArgs: ListProperty = + objects.listProperty(String::class.java).convention(listOf("node")) + + val codegenDir: DirectoryProperty = + objects.directoryProperty().convention(root.dir("node_modules/react-native-codegen")) +} diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleHermesCTask.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleHermesCTask.kt index 2801d3aea634..2eb989143b80 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleHermesCTask.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleHermesCTask.kt @@ -7,6 +7,7 @@ package com.facebook.react.tasks +import com.facebook.react.utils.Os.cliPath import com.facebook.react.utils.detectOSAwareHermesCommand import com.facebook.react.utils.moveTo import com.facebook.react.utils.windowsAwareCommandLine @@ -135,8 +136,9 @@ abstract class BundleHermesCTask : DefaultTask() { internal fun getBundleCommand(bundleFile: File, sourceMapFile: File): List = windowsAwareCommandLine( buildList { + val rootFile = root.get().asFile addAll(nodeExecutableAndArgs.get()) - add(cliFile.get().asFile.absolutePath) + add(cliFile.get().asFile.cliPath(rootFile)) add(bundleCommand.get()) add("--platform") add("android") @@ -144,16 +146,16 @@ abstract class BundleHermesCTask : DefaultTask() { add(devEnabled.get().toString()) add("--reset-cache") add("--entry-file") - add(entryFile.get().asFile.toString()) + add(entryFile.get().asFile.cliPath(rootFile)) add("--bundle-output") - add(bundleFile.toString()) + add(bundleFile.cliPath(rootFile)) add("--assets-dest") - add(resourcesDir.get().asFile.toString()) + add(resourcesDir.get().asFile.cliPath(rootFile)) add("--sourcemap-output") - add(sourceMapFile.toString()) + add(sourceMapFile.cliPath(rootFile)) if (bundleConfig.isPresent) { add("--config") - add(bundleConfig.get().asFile.absolutePath) + add(bundleConfig.get().asFile.cliPath(rootFile)) } add("--minify") add(minifyEnabled.get().toString()) @@ -165,26 +167,30 @@ abstract class BundleHermesCTask : DefaultTask() { hermesCommand: String, bytecodeFile: File, bundleFile: File - ): List = - windowsAwareCommandLine( - hermesCommand, - "-emit-binary", - "-out", - bytecodeFile.absolutePath, - bundleFile.absolutePath, - *hermesFlags.get().toTypedArray()) + ): List { + val rootFile = root.get().asFile + return windowsAwareCommandLine( + hermesCommand, + "-emit-binary", + "-out", + bytecodeFile.cliPath(rootFile), + bundleFile.cliPath(rootFile), + *hermesFlags.get().toTypedArray()) + } internal fun getComposeSourceMapsCommand( composeScript: File, packagerSourceMap: File, compilerSourceMap: File, outputSourceMap: File - ): List = - windowsAwareCommandLine( - *nodeExecutableAndArgs.get().toTypedArray(), - composeScript.absolutePath, - packagerSourceMap.toString(), - compilerSourceMap.toString(), - "-o", - outputSourceMap.toString()) + ): List { + val rootFile = root.get().asFile + return windowsAwareCommandLine( + *nodeExecutableAndArgs.get().toTypedArray(), + composeScript.cliPath(rootFile), + packagerSourceMap.cliPath(rootFile), + compilerSourceMap.cliPath(rootFile), + "-o", + outputSourceMap.cliPath(rootFile)) + } } diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt index 12830982d0ca..30f92ff7d474 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt @@ -8,6 +8,7 @@ package com.facebook.react.tasks import com.facebook.react.utils.JsonUtils +import com.facebook.react.utils.Os.cliPath import com.facebook.react.utils.windowsAwareCommandLine import org.gradle.api.file.Directory import org.gradle.api.file.DirectoryProperty @@ -26,8 +27,6 @@ abstract class GenerateCodegenArtifactsTask : Exec() { @get:Internal abstract val reactNativeDir: DirectoryProperty - @get:Internal abstract val codegenDir: DirectoryProperty - @get:Internal abstract val generatedSrcDir: DirectoryProperty @get:InputFile abstract val packageJsonFile: RegularFileProperty @@ -38,10 +37,6 @@ abstract class GenerateCodegenArtifactsTask : Exec() { @get:Input abstract val libraryName: Property - @get:InputFile - val combineJsToSchemaCli: Provider = - codegenDir.file("lib/cli/combine/combine-js-to-schema-cli.js") - @get:InputFile val generatedSchemaFile: Provider = generatedSrcDir.file("schema.json") @@ -69,16 +64,17 @@ abstract class GenerateCodegenArtifactsTask : Exec() { } internal fun setupCommandLine(libraryName: String, codegenJavaPackageName: String) { + val workingDir = project.projectDir commandLine( windowsAwareCommandLine( *nodeExecutableAndArgs.get().toTypedArray(), - reactNativeDir.file("scripts/generate-specs-cli.js").get().asFile.absolutePath, + reactNativeDir.file("scripts/generate-specs-cli.js").get().asFile.cliPath(workingDir), "--platform", "android", "--schemaPath", - generatedSchemaFile.get().asFile.absolutePath, + generatedSchemaFile.get().asFile.cliPath(workingDir), "--outputDir", - generatedSrcDir.get().asFile.absolutePath, + generatedSrcDir.get().asFile.cliPath(workingDir), "--libraryName", libraryName, "--javaPackageName", diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt index d72bc0a379f2..3f724eb5ff22 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt @@ -7,6 +7,7 @@ package com.facebook.react.tasks +import com.facebook.react.utils.Os.cliPath import com.facebook.react.utils.windowsAwareCommandLine import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.RegularFile @@ -63,6 +64,7 @@ abstract class GenerateCodegenSchemaTask : Exec() { } internal fun setupCommandLine() { + val workingDir = project.projectDir commandLine( windowsAwareCommandLine( *nodeExecutableAndArgs.get().toTypedArray(), @@ -70,11 +72,11 @@ abstract class GenerateCodegenSchemaTask : Exec() { .file("lib/cli/combine/combine-js-to-schema-cli.js") .get() .asFile - .absolutePath, + .cliPath(workingDir), "--platform", "android", - generatedSchemaFile.get().asFile.absolutePath, - jsRootDir.asFile.get().absolutePath, + generatedSchemaFile.get().asFile.cliPath(workingDir), + jsRootDir.asFile.get().cliPath(workingDir), )) } } diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/BackwardCompatUtils.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/BackwardCompatUtils.kt new file mode 100644 index 000000000000..5c39266900f6 --- /dev/null +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/BackwardCompatUtils.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.utils + +import java.util.* +import org.gradle.api.Project + +internal object BackwardCompatUtils { + + fun configureBackwardCompatibilityReactMap(project: Project) { + if (project.extensions.extraProperties.has("react")) { + @Suppress("UNCHECKED_CAST") + val reactMap = + project.extensions.extraProperties.get("react") as? Map ?: mapOf() + if (reactMap.isNotEmpty()) { + project.logger.error( + """ + ******************************************************************************** + + ERROR: Using old project.ext.react configuration. + We identified that your project is using a old configuration block as: + + project.ext.react = [ + // ... + ] + + You should migrate to the new configuration: + + react { + // ... + } + You can find documentation inside `android/app/build.gradle` on how to use it. + + ******************************************************************************** + """ + .trimIndent()) + } + } + + // We set an empty react[] map so if a library is reading it, they will find empty values. + project.extensions.extraProperties.set("react", mapOf()) + } +} diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt index d11199ed2cdc..d74a7d102089 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt @@ -13,61 +13,97 @@ import java.util.* import org.gradle.api.Project import org.gradle.api.artifacts.repositories.MavenArtifactRepository +internal const val DEFAULT_GROUP_STRING = "com.facebook.react" + internal object DependencyUtils { + /** + * This method takes care of configuring the repositories{} block for both the app and all the 3rd + * party libraries which are auto-linked. + */ fun configureRepositories(project: Project, reactNativeDir: File) { - with(project) { - if (hasProperty("REACT_NATIVE_MAVEN_LOCAL_REPO")) { - mavenRepoFromUrl("file://${property("REACT_NATIVE_MAVEN_LOCAL_REPO")}") + project.rootProject.allprojects { eachProject -> + with(eachProject) { + if (hasProperty("REACT_NATIVE_MAVEN_LOCAL_REPO")) { + val mavenLocalRepoPath = property("REACT_NATIVE_MAVEN_LOCAL_REPO") as String + mavenRepoFromURI(File(mavenLocalRepoPath).toURI()) + } + // We add the snapshot for users on nightlies. + mavenRepoFromUrl("https://oss.sonatype.org/content/repositories/snapshots/") + repositories.mavenCentral() + // Android JSC is installed from npm + mavenRepoFromURI(File(reactNativeDir, "../jsc-android/dist").toURI()) + repositories.google() + mavenRepoFromUrl("https://www.jitpack.io") } - // We add the snapshot for users on nightlies. - mavenRepoFromUrl("https://oss.sonatype.org/content/repositories/snapshots/") - repositories.mavenCentral() - // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm - mavenRepoFromUrl("file://${reactNativeDir}/android") - // Android JSC is installed from npm - mavenRepoFromUrl("file://${reactNativeDir}/../jsc-android/dist") - repositories.google() - mavenRepoFromUrl("https://www.jitpack.io") } } - fun configureDependencies(project: Project, versionString: String) { + /** + * This method takes care of configuring the resolution strategy for both the app and all the 3rd + * party libraries which are auto-linked. Specifically it takes care of: + * - Forcing the react-android/hermes-android version to the one specified in the package.json + * - Substituting `react-native` with `react-android` and `hermes-engine` with `hermes-android`. + */ + fun configureDependencies( + project: Project, + versionString: String, + groupString: String = DEFAULT_GROUP_STRING + ) { if (versionString.isBlank()) return - project.configurations.all { configuration -> - // Here we set a dependencySubstitution for both react-native and hermes-engine as those - // coordinates are voided due to https://github.com/facebook/react-native/issues/35210 - // This allows users to import libraries that are still using - // implementation("com.facebook.react:react-native:+") and resolve the right dependency. - configuration.resolutionStrategy.dependencySubstitution { - it.substitute(it.module("com.facebook.react:react-native")) - .using(it.module("com.facebook.react:react-android:${versionString}")) - .because( - "The react-native artifact was deprecated in favor of react-android due to https://github.com/facebook/react-native/issues/35210.") - it.substitute(it.module("com.facebook.react:hermes-engine")) - .using(it.module("com.facebook.react:hermes-android:${versionString}")) - .because( - "The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210.") + project.rootProject.allprojects { eachProject -> + eachProject.configurations.all { configuration -> + // Here we set a dependencySubstitution for both react-native and hermes-engine as those + // coordinates are voided due to https://github.com/facebook/react-native/issues/35210 + // This allows users to import libraries that are still using + // implementation("com.facebook.react:react-native:+") and resolve the right dependency. + configuration.resolutionStrategy.dependencySubstitution { + it.substitute(it.module("com.facebook.react:react-native")) + .using(it.module("${groupString}:react-android:${versionString}")) + .because( + "The react-native artifact was deprecated in favor of react-android due to https://github.com/facebook/react-native/issues/35210.") + it.substitute(it.module("com.facebook.react:hermes-engine")) + .using(it.module("${groupString}:hermes-android:${versionString}")) + .because( + "The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210.") + if (groupString != DEFAULT_GROUP_STRING) { + it.substitute(it.module("com.facebook.react:react-android")) + .using(it.module("${groupString}:react-android:${versionString}")) + .because( + "The react-android dependency was modified to use the correct Maven group.") + it.substitute(it.module("com.facebook.react:hermes-android")) + .using(it.module("${groupString}:hermes-android:${versionString}")) + .because( + "The hermes-android dependency was modified to use the correct Maven group.") + } + } + configuration.resolutionStrategy.force( + "${groupString}:react-android:${versionString}", + "${groupString}:hermes-android:${versionString}", + ) } - configuration.resolutionStrategy.force( - "com.facebook.react:react-android:${versionString}", - "com.facebook.react:hermes-android:${versionString}", - ) } } - fun readVersionString(propertiesFile: File): String { + fun readVersionAndGroupStrings(propertiesFile: File): Pair { val reactAndroidProperties = Properties() propertiesFile.inputStream().use { reactAndroidProperties.load(it) } - val versionString = reactAndroidProperties["VERSION_NAME"] as? String ?: "" + val versionStringFromFile = reactAndroidProperties["VERSION_NAME"] as? String ?: "" // If on a nightly, we need to fetch the -SNAPSHOT artifact from Sonatype. - return if (versionString.startsWith("0.0.0")) { - "$versionString-SNAPSHOT" - } else { - versionString - } + val versionString = + if (versionStringFromFile.startsWith("0.0.0")) { + "$versionStringFromFile-SNAPSHOT" + } else { + versionStringFromFile + } + // Returns Maven group for repos using different group for Maven artifacts + val groupString = reactAndroidProperties["GROUP"] as? String ?: DEFAULT_GROUP_STRING + return Pair(versionString, groupString) } fun Project.mavenRepoFromUrl(url: String): MavenArtifactRepository = project.repositories.maven { it.url = URI.create(url) } + + fun Project.mavenRepoFromURI(uri: URI): MavenArtifactRepository = + project.repositories.maven { it.url = uri } } diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt index 479c3f742eda..74b85fa0d65a 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt @@ -10,6 +10,7 @@ package com.facebook.react.utils import com.android.build.api.variant.AndroidComponentsExtension import com.android.build.api.variant.Variant import com.facebook.react.ReactExtension +import com.facebook.react.utils.ProjectUtils.getReactNativeArchitectures import com.facebook.react.utils.ProjectUtils.isNewArchEnabled import java.io.File import org.gradle.api.Project @@ -49,6 +50,13 @@ internal object NdkConfiguratorUtils { if ("-DANDROID_STL" !in cmakeArgs) { cmakeArgs.add("-DANDROID_STL=c++_shared") } + + val architectures = project.getReactNativeArchitectures() + // abiFilters are split ABI are not compatible each other, so we set the abiFilters + // only if the user hasn't enabled the split abi feature. + if (architectures.isNotEmpty() && !ext.splits.abi.isEnable) { + ext.defaultConfig.ndk.abiFilters.addAll(architectures) + } } } } @@ -112,36 +120,25 @@ internal object NdkConfiguratorUtils { config: ReactExtension, variant: Variant, hermesEnabled: Boolean, - debuggableVariant: Boolean ) { if (config.enableSoCleanup.get()) { - val (excludes, includes) = getPackagingOptionsForVariant(hermesEnabled, debuggableVariant) + val (excludes, includes) = getPackagingOptionsForVariant(hermesEnabled) variant.packaging.jniLibs.excludes.addAll(excludes) variant.packaging.jniLibs.pickFirsts.addAll(includes) } } - fun getPackagingOptionsForVariant( - hermesEnabled: Boolean, - debuggableVariant: Boolean - ): Pair, List> { + fun getPackagingOptionsForVariant(hermesEnabled: Boolean): Pair, List> { val excludes = mutableListOf() val includes = mutableListOf() if (hermesEnabled) { excludes.add("**/libjsc.so") excludes.add("**/libjscexecutor.so") includes.add("**/libhermes.so") - if (debuggableVariant) { - excludes.add("**/libhermes-executor-release.so") - includes.add("**/libhermes-executor-debug.so") - } else { - excludes.add("**/libhermes-executor-debug.so") - includes.add("**/libhermes-executor-release.so") - } + includes.add("**/libhermes_executor.so") } else { excludes.add("**/libhermes.so") - excludes.add("**/libhermes-executor-debug.so") - excludes.add("**/libhermes-executor-release.so") + excludes.add("**/libhermes_executor.so") includes.add("**/libjsc.so") includes.add("**/libjscexecutor.so") } diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/Os.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/Os.kt index c4dfad637fc5..4ca00699b841 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/Os.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/Os.kt @@ -7,7 +7,9 @@ package com.facebook.react.utils -object Os { +import java.io.File + +internal object Os { fun isWindows(): Boolean = System.getProperty("os.name")?.lowercase()?.contains("windows") ?: false @@ -28,4 +30,15 @@ object Os { it } } + + /** + * As Gradle doesn't support well path with spaces on Windows, we need to return relative path on + * Win. On Linux & Mac we'll default to return absolute path. + */ + fun File.cliPath(base: File): String = + if (isWindows()) { + this.relativeTo(base).path + } else { + this.absolutePath + } } diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt index 74fe49ca17a3..2f874947d87c 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt @@ -11,8 +11,10 @@ package com.facebook.react.utils import com.facebook.react.ReactExtension import com.facebook.react.model.ModelPackageJson +import com.facebook.react.utils.Os.cliPath import java.io.File import org.gradle.api.Project +import org.gradle.api.file.DirectoryProperty /** * Computes the entry file for React Native. The Algo follows this order: @@ -23,9 +25,11 @@ import org.gradle.api.Project * * @param config The [ReactExtension] configured for this project */ -internal fun detectedEntryFile(config: ReactExtension): File = +internal fun detectedEntryFile(config: ReactExtension, envVariableOverride: String? = null): File = detectEntryFile( - entryFile = config.entryFile.orNull?.asFile, reactRoot = config.root.get().asFile) + entryFile = config.entryFile.orNull?.asFile, + reactRoot = config.root.get().asFile, + envVariableOverride = envVariableOverride) /** * Computes the CLI file for React Native. The Algo follows this order: @@ -52,9 +56,13 @@ internal fun detectedCliFile(config: ReactExtension): File = internal fun detectedHermesCommand(config: ReactExtension): String = detectOSAwareHermesCommand(config.root.get().asFile, config.hermesCommand.get()) -private fun detectEntryFile(entryFile: File?, reactRoot: File): File = +private fun detectEntryFile( + entryFile: File?, + reactRoot: File, + envVariableOverride: String? = null +): File = when { - System.getenv("ENTRY_FILE") != null -> File(System.getenv("ENTRY_FILE")) + envVariableOverride != null -> File(reactRoot, envVariableOverride) entryFile != null -> entryFile File(reactRoot, "index.android.js").exists() -> File(reactRoot, "index.android.js") else -> File(reactRoot, "index.js") @@ -130,7 +138,7 @@ internal fun detectOSAwareHermesCommand(projectRoot: File, hermesCommand: String val builtHermesc = getBuiltHermescFile(projectRoot, System.getenv("REACT_NATIVE_OVERRIDE_HERMES_DIR")) if (builtHermesc.exists()) { - return builtHermesc.absolutePath + return builtHermesc.cliPath(projectRoot) } // 3. If the react-native contains a pre-built hermesc, use it. @@ -142,7 +150,7 @@ internal fun detectOSAwareHermesCommand(projectRoot: File, hermesCommand: String val prebuiltHermes = File(projectRoot, prebuiltHermesPath) if (prebuiltHermes.exists()) { - return prebuiltHermes.absolutePath + return prebuiltHermes.cliPath(projectRoot) } error( @@ -188,23 +196,33 @@ internal fun projectPathToLibraryName(projectPath: String): String = * Gradle module (generally the case for library projects) or we fallback to looking into the `root` * folder of a React Native project (generally the case for app projects). */ -internal fun findPackageJsonFile(project: Project, extension: ReactExtension): File? = - if (project.file("../package.json").exists()) { - project.file("../package.json") - } else { - extension.root.file("package.json").orNull?.asFile - } +internal fun findPackageJsonFile(project: Project, rootProperty: DirectoryProperty): File? { + val inParent = project.file("../package.json") + if (inParent.exists()) { + return inParent + } + + val fromExtension = rootProperty.file("package.json").orNull?.asFile + if (fromExtension?.exists() == true) { + return fromExtension + } + + return null +} /** * Function to look for the `package.json` and parse it. It returns a [ModelPackageJson] if found or * null others. * - * Please note that this function access the [ReactExtension] field properties and calls .get() on - * them, so calling this during apply() of the ReactPlugin is not recommended. It should be invoked - * inside lazy lambdas or at execution time. + * Please note that this function access the [DirectoryProperty] parameter and calls .get() on them, + * so calling this during apply() of the ReactPlugin is not recommended. It should be invoked inside + * lazy lambdas or at execution time. */ -internal fun readPackageJsonFile(project: Project, extension: ReactExtension): ModelPackageJson? { - val packageJson = findPackageJsonFile(project, extension) +internal fun readPackageJsonFile( + project: Project, + rootProperty: DirectoryProperty +): ModelPackageJson? { + val packageJson = findPackageJsonFile(project, rootProperty) return packageJson?.let { JsonUtils.fromCodegenJson(it) } } diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/ProjectUtils.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/ProjectUtils.kt index c18946a0cd0e..e941da78b564 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/ProjectUtils.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/ProjectUtils.kt @@ -7,9 +7,9 @@ package com.facebook.react.utils -import com.facebook.react.ReactExtension import com.facebook.react.model.ModelPackageJson import org.gradle.api.Project +import org.gradle.api.file.DirectoryProperty internal object ProjectUtils { internal val Project.isNewArchEnabled: Boolean @@ -35,12 +35,21 @@ internal object ProjectUtils { HERMES_FALLBACK } - internal fun Project.needsCodegenFromPackageJson(extension: ReactExtension): Boolean { - val parsedPackageJson = readPackageJsonFile(this, extension) + internal fun Project.needsCodegenFromPackageJson(rootProperty: DirectoryProperty): Boolean { + val parsedPackageJson = readPackageJsonFile(this, rootProperty) return needsCodegenFromPackageJson(parsedPackageJson) } internal fun Project.needsCodegenFromPackageJson(model: ModelPackageJson?): Boolean { return model?.codegenConfig != null } + + internal fun Project.getReactNativeArchitectures(): List { + val architectures = mutableListOf() + if (project.hasProperty("reactNativeArchitectures")) { + val architecturesString = project.property("reactNativeArchitectures").toString() + architectures.addAll(architecturesString.split(",").filter { it.isNotBlank() }) + } + return architectures + } } diff --git a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/BundleHermesCTaskTest.kt b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/BundleHermesCTaskTest.kt index fbe7fed63049..3e07a78b36e1 100644 --- a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/BundleHermesCTaskTest.kt +++ b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/BundleHermesCTaskTest.kt @@ -7,7 +7,9 @@ package com.facebook.react.tasks +import com.facebook.react.tests.OS import com.facebook.react.tests.OsRule +import com.facebook.react.tests.WithOs import com.facebook.react.tests.createTestTask import java.io.File import org.junit.Assert.* @@ -205,6 +207,7 @@ class BundleHermesCTaskTest { val task = createTestTask { it.nodeExecutableAndArgs.set(listOf("node", "arg1", "arg2")) + it.root.set(tempFolder.root) it.cliFile.set(cliFile) it.bundleCommand.set("bundle") it.devEnabled.set(true) @@ -244,6 +247,60 @@ class BundleHermesCTaskTest { assertEquals(24, bundleCommand.size) } + @Test + @WithOs(OS.WIN) + fun getBundleCommand_onWindows_returnsWinValidCommandsPaths() { + val entryFile = tempFolder.newFile("index.js") + val cliFile = tempFolder.newFile("cli.js") + val bundleFile = tempFolder.newFile("bundle.js") + val sourceMapFile = tempFolder.newFile("bundle.js.map") + val resourcesDir = tempFolder.newFolder("res") + val bundleConfig = tempFolder.newFile("bundle.config") + val task = + createTestTask { + it.nodeExecutableAndArgs.set(listOf("node", "arg1", "arg2")) + it.root.set(tempFolder.root) + it.cliFile.set(cliFile) + it.bundleCommand.set("bundle") + it.devEnabled.set(true) + it.entryFile.set(entryFile) + it.resourcesDir.set(resourcesDir) + it.bundleConfig.set(bundleConfig) + it.minifyEnabled.set(true) + it.extraPackagerArgs.set(listOf("--read-global-cache")) + } + + val bundleCommand = task.getBundleCommand(bundleFile, sourceMapFile) + + assertEquals("cmd", bundleCommand[0]) + assertEquals("/c", bundleCommand[1]) + assertEquals("node", bundleCommand[2]) + assertEquals("arg1", bundleCommand[3]) + assertEquals("arg2", bundleCommand[4]) + assertEquals(cliFile.relativeTo(tempFolder.root).path, bundleCommand[5]) + assertEquals("bundle", bundleCommand[6]) + assertEquals("--platform", bundleCommand[7]) + assertEquals("android", bundleCommand[8]) + assertEquals("--dev", bundleCommand[9]) + assertEquals("true", bundleCommand[10]) + assertEquals("--reset-cache", bundleCommand[11]) + assertEquals("--entry-file", bundleCommand[12]) + assertEquals(entryFile.relativeTo(tempFolder.root).path, bundleCommand[13]) + assertEquals("--bundle-output", bundleCommand[14]) + assertEquals(bundleFile.relativeTo(tempFolder.root).path, bundleCommand[15]) + assertEquals("--assets-dest", bundleCommand[16]) + assertEquals(resourcesDir.relativeTo(tempFolder.root).path, bundleCommand[17]) + assertEquals("--sourcemap-output", bundleCommand[18]) + assertEquals(sourceMapFile.relativeTo(tempFolder.root).path, bundleCommand[19]) + assertEquals("--config", bundleCommand[20]) + assertEquals(bundleConfig.relativeTo(tempFolder.root).path, bundleCommand[21]) + assertEquals("--minify", bundleCommand[22]) + assertEquals("true", bundleCommand[23]) + assertEquals("--read-global-cache", bundleCommand[24]) + assertEquals("--verbose", bundleCommand[25]) + assertEquals(26, bundleCommand.size) + } + @Test fun getBundleCommand_withoutConfig_returnsCommandWithoutConfig() { val entryFile = tempFolder.newFile("index.js") @@ -254,6 +311,7 @@ class BundleHermesCTaskTest { val task = createTestTask { it.nodeExecutableAndArgs.set(listOf("node", "arg1", "arg2")) + it.root.set(tempFolder.root) it.cliFile.set(cliFile) it.bundleCommand.set("bundle") it.devEnabled.set(true) @@ -274,7 +332,10 @@ class BundleHermesCTaskTest { val bytecodeFile = tempFolder.newFile("bundle.js.hbc") val bundleFile = tempFolder.newFile("bundle.js") val task = - createTestTask { it.hermesFlags.set(listOf("my-custom-hermes-flag")) } + createTestTask { + it.root.set(tempFolder.root) + it.hermesFlags.set(listOf("my-custom-hermes-flag")) + } val hermesCommand = task.getHermescCommand(customHermesc, bytecodeFile, bundleFile) @@ -287,6 +348,31 @@ class BundleHermesCTaskTest { assertEquals(6, hermesCommand.size) } + @Test + @WithOs(OS.WIN) + fun getHermescCommand_onWindows_returnsRelativePaths() { + val customHermesc = "hermesc" + val bytecodeFile = tempFolder.newFile("bundle.js.hbc") + val bundleFile = tempFolder.newFile("bundle.js") + val task = + createTestTask { + it.root.set(tempFolder.root) + it.hermesFlags.set(listOf("my-custom-hermes-flag")) + } + + val hermesCommand = task.getHermescCommand(customHermesc, bytecodeFile, bundleFile) + + assertEquals("cmd", hermesCommand[0]) + assertEquals("/c", hermesCommand[1]) + assertEquals(customHermesc, hermesCommand[2]) + assertEquals("-emit-binary", hermesCommand[3]) + assertEquals("-out", hermesCommand[4]) + assertEquals(bytecodeFile.relativeTo(tempFolder.root).path, hermesCommand[5]) + assertEquals(bundleFile.relativeTo(tempFolder.root).path, hermesCommand[6]) + assertEquals("my-custom-hermes-flag", hermesCommand[7]) + assertEquals(8, hermesCommand.size) + } + @Test fun getComposeSourceMapsCommand_returnsCorrectCommand() { val packagerMap = tempFolder.newFile("bundle.js.packager.map") @@ -296,6 +382,7 @@ class BundleHermesCTaskTest { val composeSourceMapsFile = File(reactNativeDir, "scripts/compose-source-maps.js") val task = createTestTask { + it.root.set(tempFolder.root) it.nodeExecutableAndArgs.set(listOf("node", "arg1", "arg2")) } @@ -312,4 +399,34 @@ class BundleHermesCTaskTest { assertEquals(outputMap.absolutePath, composeSourcemapCommand[7]) assertEquals(8, composeSourcemapCommand.size) } + + @Test + @WithOs(OS.WIN) + fun getComposeSourceMapsCommand_onWindows_returnsRelativePaths() { + val packagerMap = tempFolder.newFile("bundle.js.packager.map") + val compilerMap = tempFolder.newFile("bundle.js.compiler.map") + val outputMap = tempFolder.newFile("bundle.js.map") + val reactNativeDir = tempFolder.newFolder("node_modules/react-native") + val composeSourceMapsFile = File(reactNativeDir, "scripts/compose-source-maps.js") + val task = + createTestTask { + it.root.set(tempFolder.root) + it.nodeExecutableAndArgs.set(listOf("node", "arg1", "arg2")) + } + + val composeSourcemapCommand = + task.getComposeSourceMapsCommand(composeSourceMapsFile, packagerMap, compilerMap, outputMap) + + assertEquals("cmd", composeSourcemapCommand[0]) + assertEquals("/c", composeSourcemapCommand[1]) + assertEquals("node", composeSourcemapCommand[2]) + assertEquals("arg1", composeSourcemapCommand[3]) + assertEquals("arg2", composeSourcemapCommand[4]) + assertEquals(composeSourceMapsFile.relativeTo(tempFolder.root).path, composeSourcemapCommand[5]) + assertEquals(packagerMap.relativeTo(tempFolder.root).path, composeSourcemapCommand[6]) + assertEquals(compilerMap.relativeTo(tempFolder.root).path, composeSourcemapCommand[7]) + assertEquals("-o", composeSourcemapCommand[8]) + assertEquals(outputMap.relativeTo(tempFolder.root).path, composeSourcemapCommand[9]) + assertEquals(10, composeSourcemapCommand.size) + } } diff --git a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTaskTest.kt b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTaskTest.kt index 86f45fec3207..e2bf1ad7b9b4 100644 --- a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTaskTest.kt +++ b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTaskTest.kt @@ -7,9 +7,8 @@ package com.facebook.react.tasks -import com.facebook.react.tests.OS -import com.facebook.react.tests.OsRule -import com.facebook.react.tests.WithOs +import com.facebook.react.tests.* +import com.facebook.react.tests.createProject import com.facebook.react.tests.createTestTask import java.io.File import org.junit.Assert.assertEquals @@ -29,28 +28,16 @@ class GenerateCodegenArtifactsTaskTest { val codegenDir = tempFolder.newFolder("codegen") val outputDir = tempFolder.newFolder("output") - val task = - createTestTask { - it.codegenDir.set(codegenDir) - it.generatedSrcDir.set(outputDir) - } + val task = createTestTask { it.generatedSrcDir.set(outputDir) } - assertEquals( - File(codegenDir, "lib/cli/combine/combine-js-to-schema-cli.js"), - task.combineJsToSchemaCli.get().asFile) assertEquals(File(outputDir, "schema.json"), task.generatedSchemaFile.get().asFile) } @Test fun generateCodegenSchema_outputFile_isSetCorrectly() { - val codegenDir = tempFolder.newFolder("codegen") val outputDir = tempFolder.newFolder("output") - val task = - createTestTask { - it.codegenDir.set(codegenDir) - it.generatedSrcDir.set(outputDir) - } + val task = createTestTask { it.generatedSrcDir.set(outputDir) } assertEquals(File(outputDir, "java"), task.generatedJavaFiles.get().asFile) assertEquals(File(outputDir, "jni"), task.generatedJniFiles.get().asFile) @@ -80,13 +67,11 @@ class GenerateCodegenArtifactsTaskTest { @WithOs(OS.LINUX) fun setupCommandLine_willSetupCorrectly() { val reactNativeDir = tempFolder.newFolder("node_modules/react-native/") - val codegenDir = tempFolder.newFolder("codegen") val outputDir = tempFolder.newFolder("output") val task = createTestTask { it.reactNativeDir.set(reactNativeDir) - it.codegenDir.set(codegenDir) it.generatedSrcDir.set(outputDir) it.nodeExecutableAndArgs.set(listOf("--verbose")) } @@ -111,6 +96,44 @@ class GenerateCodegenArtifactsTaskTest { task.commandLine.toMutableList()) } + @Test + @WithOs(OS.WIN) + fun setupCommandLine_onWindows_willSetupCorrectly() { + val reactNativeDir = tempFolder.newFolder("node_modules/react-native/") + val outputDir = tempFolder.newFolder("output") + + val project = createProject() + val task = + createTestTask(project) { + it.reactNativeDir.set(reactNativeDir) + it.generatedSrcDir.set(outputDir) + it.nodeExecutableAndArgs.set(listOf("--verbose")) + } + + task.setupCommandLine("example-test", "com.example.test") + + assertEquals( + listOf( + "cmd", + "/c", + "--verbose", + File(reactNativeDir, "scripts/generate-specs-cli.js") + .relativeTo(project.projectDir) + .path, + "--platform", + "android", + "--schemaPath", + File(outputDir, "schema.json").relativeTo(project.projectDir).path, + "--outputDir", + outputDir.relativeTo(project.projectDir).path, + "--libraryName", + "example-test", + "--javaPackageName", + "com.example.test", + ), + task.commandLine.toMutableList()) + } + @Test fun resolveTaskParameters_withConfigInPackageJson_usesIt() { val packageJsonFile = diff --git a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTaskTest.kt b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTaskTest.kt index 98e2b39795c1..abe77f0dd155 100644 --- a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTaskTest.kt +++ b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTaskTest.kt @@ -7,9 +7,8 @@ package com.facebook.react.tasks -import com.facebook.react.tests.OS -import com.facebook.react.tests.OsRule -import com.facebook.react.tests.WithOs +import com.facebook.react.tests.* +import com.facebook.react.tests.createProject import com.facebook.react.tests.createTestTask import java.io.File import org.junit.Assert.* @@ -140,13 +139,14 @@ class GenerateCodegenSchemaTaskTest { it.codegenDir.set(codegenDir) it.jsRootDir.set(jsRootDir) it.generatedSrcDir.set(outputDir) - it.nodeExecutableAndArgs.set(listOf("--verbose")) + it.nodeExecutableAndArgs.set(listOf("node", "--verbose")) } task.setupCommandLine() assertEquals( listOf( + "node", "--verbose", File(codegenDir, "lib/cli/combine/combine-js-to-schema-cli.js").toString(), "--platform", @@ -156,4 +156,39 @@ class GenerateCodegenSchemaTaskTest { ), task.commandLine.toMutableList()) } + + @Test + @WithOs(OS.WIN) + fun setupCommandLine_onWindows_willSetupCorrectly() { + val codegenDir = tempFolder.newFolder("codegen") + val jsRootDir = tempFolder.newFolder("js") + val outputDir = tempFolder.newFolder("output") + + val project = createProject() + val task = + createTestTask(project) { + it.codegenDir.set(codegenDir) + it.jsRootDir.set(jsRootDir) + it.generatedSrcDir.set(outputDir) + it.nodeExecutableAndArgs.set(listOf("node", "--verbose")) + } + + task.setupCommandLine() + + assertEquals( + listOf( + "cmd", + "/c", + "node", + "--verbose", + File(codegenDir, "lib/cli/combine/combine-js-to-schema-cli.js") + .relativeTo(project.projectDir) + .path, + "--platform", + "android", + File(outputDir, "schema.json").relativeTo(project.projectDir).path, + jsRootDir.relativeTo(project.projectDir).path, + ), + task.commandLine.toMutableList()) + } } diff --git a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/BackwardCompatUtilsTest.kt b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/BackwardCompatUtilsTest.kt new file mode 100644 index 000000000000..da08d88ad06a --- /dev/null +++ b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/BackwardCompatUtilsTest.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.utils + +import com.facebook.react.tests.createProject +import com.facebook.react.utils.BackwardCompatUtils.configureBackwardCompatibilityReactMap +import org.junit.Assert.assertTrue +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder + +class BackwardCompatUtilsTest { + + @get:Rule val tempFolder = TemporaryFolder() + + @Test + fun configureBackwardCompatibilityReactMap_addsEmptyReactMap() { + val project = createProject() + + configureBackwardCompatibilityReactMap(project) + + assertTrue(project.extensions.extraProperties.has("react")) + @Suppress("UNCHECKED_CAST") + assertTrue((project.extensions.extraProperties.get("react") as Map).isEmpty()) + } + + @Test + fun configureBackwardCompatibilityReactMap_withExistingMapSetByUser_wipesTheMap() { + val project = createProject() + project.extensions.extraProperties.set("react", mapOf("enableHermes" to true)) + + configureBackwardCompatibilityReactMap(project) + + assertTrue(project.extensions.extraProperties.has("react")) + @Suppress("UNCHECKED_CAST") + assertTrue((project.extensions.extraProperties.get("react") as Map).isEmpty()) + } +} diff --git a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt index 4386e33233d3..f77c0bb3026b 100644 --- a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt +++ b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt @@ -10,10 +10,12 @@ package com.facebook.react.utils import com.facebook.react.tests.createProject import com.facebook.react.utils.DependencyUtils.configureDependencies import com.facebook.react.utils.DependencyUtils.configureRepositories +import com.facebook.react.utils.DependencyUtils.mavenRepoFromURI import com.facebook.react.utils.DependencyUtils.mavenRepoFromUrl -import com.facebook.react.utils.DependencyUtils.readVersionString +import com.facebook.react.utils.DependencyUtils.readVersionAndGroupStrings import java.net.URI import org.gradle.api.artifacts.repositories.MavenArtifactRepository +import org.gradle.testfixtures.ProjectBuilder import org.junit.Assert.* import org.junit.Rule import org.junit.Test @@ -26,9 +28,9 @@ class DependencyUtilsTest { @Test fun configureRepositories_withProjectPropertySet_configuresMavenLocalCorrectly() { val localMaven = tempFolder.newFolder("m2") - val localMavenURI = URI.create("file://$localMaven/") + val localMavenURI = localMaven.toURI() val project = createProject() - project.extensions.extraProperties.set("REACT_NATIVE_MAVEN_LOCAL_REPO", localMaven) + project.extensions.extraProperties.set("REACT_NATIVE_MAVEN_LOCAL_REPO", localMaven.absolutePath) configureRepositories(project, tempFolder.root) @@ -51,21 +53,6 @@ class DependencyUtilsTest { }) } - @Test - fun configureRepositories_containsReactNativeNpmLocalMavenRepo() { - val projectFolder = tempFolder.newFolder() - val reactNativeDir = tempFolder.newFolder("react-native") - val repositoryURI = URI.create("file://${reactNativeDir}/android") - val project = createProject(projectFolder) - - configureRepositories(project, reactNativeDir) - - assertNotNull( - project.repositories.firstOrNull { - it is MavenArtifactRepository && it.url == repositoryURI - }) - } - @Test fun configureRepositories_containsJscLocalMavenRepo() { val projectFolder = tempFolder.newFolder() @@ -124,10 +111,10 @@ class DependencyUtilsTest { @Test fun configureRepositories_withProjectPropertySet_hasHigherPriorityThanMavenCentral() { val localMaven = tempFolder.newFolder("m2") - val localMavenURI = URI.create("file://$localMaven/") + val localMavenURI = localMaven.toURI() val mavenCentralURI = URI.create("https://repo.maven.apache.org/maven2/") val project = createProject() - project.extensions.extraProperties.set("REACT_NATIVE_MAVEN_LOCAL_REPO", localMaven) + project.extensions.extraProperties.set("REACT_NATIVE_MAVEN_LOCAL_REPO", localMaven.absolutePath) configureRepositories(project, tempFolder.root) @@ -161,6 +148,46 @@ class DependencyUtilsTest { assertTrue(indexOfSnapshotRepo < indexOfMavenCentral) } + @Test + fun configureRepositories_appliesToAllProjects() { + val repositoryURI = URI.create("https://repo.maven.apache.org/maven2/") + val rootProject = ProjectBuilder.builder().build() + val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build() + val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build() + + configureRepositories(appProject, tempFolder.root) + + assertNotNull( + appProject.repositories.firstOrNull { + it is MavenArtifactRepository && it.url == repositoryURI + }) + assertNotNull( + libProject.repositories.firstOrNull { + it is MavenArtifactRepository && it.url == repositoryURI + }) + } + + @Test + fun configureRepositories_withPreviousExclusionRulesOnMavenCentral_appliesCorrectly() { + val repositoryURI = URI.create("https://repo.maven.apache.org/maven2/") + val rootProject = ProjectBuilder.builder().build() + val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build() + val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build() + + // Let's emulate a library which set an `excludeGroup` on `com.facebook.react` for Central. + libProject.repositories.mavenCentral { repo -> + repo.content { content -> content.excludeGroup("com.facebook.react") } + } + + configureRepositories(appProject, tempFolder.root) + + // We need to make sure we have Maven Central defined twice, one by the library, + // and another is the override by RNGP. + assertEquals( + 2, + libProject.repositories.count { it is MavenArtifactRepository && it.url == repositoryURI }) + } + @Test fun configureDependencies_withEmptyVersion_doesNothing() { val project = createProject() @@ -181,6 +208,42 @@ class DependencyUtilsTest { assertTrue(forcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" }) } + @Test + fun configureDependencies_withVersionString_appliesOnAllProjects() { + val rootProject = ProjectBuilder.builder().build() + val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build() + val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build() + appProject.plugins.apply("com.android.application") + libProject.plugins.apply("com.android.library") + + configureDependencies(appProject, "1.2.3") + + val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules + val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules + assertTrue(appForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" }) + assertTrue(appForcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" }) + assertTrue(libForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" }) + assertTrue(libForcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" }) + } + + @Test + fun configureDependencies_withVersionStringAndGroupString_appliesOnAllProjects() { + val rootProject = ProjectBuilder.builder().build() + val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build() + val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build() + appProject.plugins.apply("com.android.application") + libProject.plugins.apply("com.android.library") + + configureDependencies(appProject, "1.2.3", "io.github.test") + + val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules + val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules + assertTrue(appForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" }) + assertTrue(appForcedModules.any { it.toString() == "io.github.test:hermes-android:1.2.3" }) + assertTrue(libForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" }) + assertTrue(libForcedModules.any { it.toString() == "io.github.test:hermes-android:1.2.3" }) + } + @Test fun readVersionString_withCorrectVersionString_returnsIt() { val propertiesFile = @@ -193,7 +256,7 @@ class DependencyUtilsTest { .trimIndent()) } - val versionString = readVersionString(propertiesFile) + val versionString = readVersionAndGroupStrings(propertiesFile).first assertEquals("1000.0.0", versionString) } @@ -210,7 +273,7 @@ class DependencyUtilsTest { .trimIndent()) } - val versionString = readVersionString(propertiesFile) + val versionString = readVersionAndGroupStrings(propertiesFile).first assertEquals("0.0.0-20221101-2019-cfe811ab1-SNAPSHOT", versionString) } @@ -226,7 +289,7 @@ class DependencyUtilsTest { .trimIndent()) } - val versionString = readVersionString(propertiesFile) + val versionString = readVersionAndGroupStrings(propertiesFile).first assertEquals("", versionString) } @@ -242,10 +305,43 @@ class DependencyUtilsTest { .trimIndent()) } - val versionString = readVersionString(propertiesFile) + val versionString = readVersionAndGroupStrings(propertiesFile).first assertEquals("", versionString) } + @Test + fun readGroupString_withCorrectGroupString_returnsIt() { + val propertiesFile = + tempFolder.newFile("gradle.properties").apply { + writeText( + """ + GROUP=io.github.test + ANOTHER_PROPERTY=true + """ + .trimIndent()) + } + + val groupString = readVersionAndGroupStrings(propertiesFile).second + + assertEquals("io.github.test", groupString) + } + + @Test + fun readGroupString_withEmptyGroupString_returnsDefault() { + val propertiesFile = + tempFolder.newFile("gradle.properties").apply { + writeText( + """ + ANOTHER_PROPERTY=true + """ + .trimIndent()) + } + + val groupString = readVersionAndGroupStrings(propertiesFile).second + + assertEquals("com.facebook.react", groupString) + } + @Test fun mavenRepoFromUrl_worksCorrectly() { val process = createProject() @@ -253,4 +349,13 @@ class DependencyUtilsTest { assertEquals(URI.create("https://hello.world"), mavenRepo.url) } + + @Test + fun mavenRepoFromURI_worksCorrectly() { + val process = createProject() + val repoFolder = tempFolder.newFolder("maven-repo") + val mavenRepo = process.mavenRepoFromURI(repoFolder.toURI()) + + assertEquals(repoFolder.toURI(), mavenRepo.url) + } } diff --git a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/NdkConfiguratorUtilsTest.kt b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/NdkConfiguratorUtilsTest.kt index 2d0093c6a565..bf2f27926ab3 100644 --- a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/NdkConfiguratorUtilsTest.kt +++ b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/NdkConfiguratorUtilsTest.kt @@ -15,70 +15,28 @@ import org.junit.Test class NdkConfiguratorUtilsTest { @Test - fun getPackagingOptionsForVariant_withHermesEnabled_andDebuggableVariant() { - val (excludes, includes) = - getPackagingOptionsForVariant(hermesEnabled = true, debuggableVariant = true) + fun getPackagingOptionsForVariant_withHermesEnabled() { + val (excludes, includes) = getPackagingOptionsForVariant(hermesEnabled = true) assertTrue("**/libjsc.so" in excludes) assertTrue("**/libjscexecutor.so" in excludes) - assertTrue("**/libhermes-executor-release.so" in excludes) assertFalse("**/libjsc.so" in includes) assertFalse("**/libjscexecutor.so" in includes) - assertFalse("**/libhermes-executor-release.so" in includes) assertTrue("**/libhermes.so" in includes) - assertTrue("**/libhermes-executor-debug.so" in includes) + assertTrue("**/libhermes_executor.so" in includes) assertFalse("**/libhermes.so" in excludes) - assertFalse("**/libhermes-executor-debug.so" in excludes) + assertFalse("**/libhermes_executor.so" in excludes) } @Test - fun getPackagingOptionsForVariant_withHermesEnabled_andNonDebuggableVariant() { - val (excludes, includes) = - getPackagingOptionsForVariant(hermesEnabled = true, debuggableVariant = false) - - assertTrue("**/libjsc.so" in excludes) - assertTrue("**/libjscexecutor.so" in excludes) - assertTrue("**/libhermes-executor-debug.so" in excludes) - assertFalse("**/libjsc.so" in includes) - assertFalse("**/libjscexecutor.so" in includes) - assertFalse("**/libhermes-executor-debug.so" in includes) - - assertTrue("**/libhermes.so" in includes) - assertTrue("**/libhermes-executor-release.so" in includes) - assertFalse("**/libhermes.so" in excludes) - assertFalse("**/libhermes-executor-release.so" in excludes) - } - - @Test - fun getPackagingOptionsForVariant_withHermesDisabled_andDebuggableVariant() { - val (excludes, includes) = - getPackagingOptionsForVariant(hermesEnabled = false, debuggableVariant = true) - - assertTrue("**/libhermes.so" in excludes) - assertTrue("**/libhermes-executor-debug.so" in excludes) - assertTrue("**/libhermes-executor-release.so" in excludes) - assertFalse("**/libhermes.so" in includes) - assertFalse("**/libhermes-executor-debug.so" in includes) - assertFalse("**/libhermes-executor-release.so" in includes) - - assertTrue("**/libjsc.so" in includes) - assertTrue("**/libjscexecutor.so" in includes) - assertFalse("**/libjsc.so" in excludes) - assertFalse("**/libjscexecutor.so" in excludes) - } - - @Test - fun getPackagingOptionsForVariant_withHermesDisabled_andNonDebuggableVariant() { - val (excludes, includes) = - getPackagingOptionsForVariant(hermesEnabled = false, debuggableVariant = false) + fun getPackagingOptionsForVariant_withHermesDisabled() { + val (excludes, includes) = getPackagingOptionsForVariant(hermesEnabled = false) assertTrue("**/libhermes.so" in excludes) - assertTrue("**/libhermes-executor-debug.so" in excludes) - assertTrue("**/libhermes-executor-release.so" in excludes) + assertTrue("**/libhermes_executor.so" in excludes) assertFalse("**/libhermes.so" in includes) - assertFalse("**/libhermes-executor-debug.so" in includes) - assertFalse("**/libhermes-executor-release.so" in includes) + assertFalse("**/libhermes_executor.so" in includes) assertTrue("**/libjsc.so" in includes) assertTrue("**/libjscexecutor.so" in includes) diff --git a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/OsTest.kt b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/OsTest.kt index fd37f2474f77..b58a2e067f8d 100644 --- a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/OsTest.kt +++ b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/OsTest.kt @@ -10,14 +10,17 @@ package com.facebook.react.utils import com.facebook.react.tests.OS import com.facebook.react.tests.OsRule import com.facebook.react.tests.WithOs +import com.facebook.react.utils.Os.cliPath import com.facebook.react.utils.Os.unixifyPath import org.junit.Assert.* import org.junit.Rule import org.junit.Test +import org.junit.rules.TemporaryFolder class OsTest { @get:Rule val osRule = OsRule() + @get:Rule val tempFolder = TemporaryFolder() @Test @WithOs(OS.LINUX, "amd64") @@ -56,4 +59,28 @@ class OsTest { assertEquals("/D/just/a/windows/path/", aWindowsPath.unixifyPath()) } + + @Test + @WithOs(OS.WIN) + fun cliPath_onWindows_returnsRelativePath() { + val tempFile = tempFolder.newFile("test.txt").apply { createNewFile() } + + assertEquals(tempFile.relativeTo(tempFolder.root).path, tempFile.cliPath(tempFolder.root)) + } + + @Test + @WithOs(OS.LINUX) + fun cliPath_onLinux_returnsAbsolutePath() { + val tempFile = tempFolder.newFile("test.txt").apply { createNewFile() } + + assertEquals(tempFile.absolutePath, tempFile.cliPath(tempFolder.root)) + } + + @Test + @WithOs(OS.MAC) + fun cliPath_onMac_returnsAbsolutePath() { + val tempFile = tempFolder.newFile("test.txt").apply { createNewFile() } + + assertEquals(tempFile.absolutePath, tempFile.cliPath(tempFolder.root)) + } } diff --git a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/PathUtilsTest.kt b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/PathUtilsTest.kt index fb230f49551d..461a66147601 100644 --- a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/PathUtilsTest.kt +++ b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/PathUtilsTest.kt @@ -13,7 +13,6 @@ import com.facebook.react.tests.OS import com.facebook.react.tests.OsRule import com.facebook.react.tests.WithOs import java.io.File -import java.io.FileNotFoundException import org.gradle.testfixtures.ProjectBuilder import org.junit.Assert.* import org.junit.Assume.assumeTrue @@ -58,6 +57,20 @@ class PathUtilsTest { assertEquals(File(tempFolder.root, "index.js"), actual) } + @Test + fun detectedEntryFile_withEnvironmentVariable() { + val extension = TestReactExtension(ProjectBuilder.builder().build()) + val expected = tempFolder.newFile("./fromenv.index.js") + // As we can't override env variable for tests, we're going to emulate them here. + val envVariable = "./fromenv.index.js" + + extension.root.set(tempFolder.root) + + val actual = detectedEntryFile(extension, envVariable) + + assertEquals(expected, actual) + } + @Test fun detectedCliPath_withCliPathFromExtensionAndFileExists_returnsIt() { val project = ProjectBuilder.builder().build() @@ -232,7 +245,7 @@ class PathUtilsTest { project.plugins.apply("com.facebook.react") val extension = project.extensions.getByType(ReactExtension::class.java) - assertEquals(project.file("../package.json"), findPackageJsonFile(project, extension)) + assertEquals(project.file("../package.json"), findPackageJsonFile(project, extension.root)) } @Test @@ -246,10 +259,10 @@ class PathUtilsTest { val extension = project.extensions.getByType(ReactExtension::class.java).apply { root.set(moduleFolder) } - assertEquals(localFile, findPackageJsonFile(project, extension)) + assertEquals(localFile, findPackageJsonFile(project, extension.root)) } - @Test(expected = FileNotFoundException::class) + @Test fun readPackageJsonFile_withMissingFile_returnsNull() { val moduleFolder = tempFolder.newFolder("awesome-module") val project = ProjectBuilder.builder().withProjectDir(moduleFolder).build() @@ -258,7 +271,7 @@ class PathUtilsTest { val extension = project.extensions.getByType(ReactExtension::class.java).apply { root.set(moduleFolder) } - val actual = readPackageJsonFile(project, extension) + val actual = readPackageJsonFile(project, extension.root) assertNull(actual) } @@ -273,7 +286,7 @@ class PathUtilsTest { val extension = project.extensions.getByType(ReactExtension::class.java).apply { root.set(moduleFolder) } - val actual = readPackageJsonFile(project, extension) + val actual = readPackageJsonFile(project, extension.root) assertNotNull(actual) assertNull(actual!!.codegenConfig) @@ -299,7 +312,7 @@ class PathUtilsTest { val extension = project.extensions.getByType(ReactExtension::class.java).apply { root.set(moduleFolder) } - val actual = readPackageJsonFile(project, extension) + val actual = readPackageJsonFile(project, extension.root) assertNotNull(actual) assertNotNull(actual!!.codegenConfig) diff --git a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/ProjectUtilsTest.kt b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/ProjectUtilsTest.kt index d918c285d1cf..70ea15401cc6 100644 --- a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/ProjectUtilsTest.kt +++ b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/ProjectUtilsTest.kt @@ -11,12 +11,12 @@ import com.facebook.react.TestReactExtension import com.facebook.react.model.ModelCodegenConfig import com.facebook.react.model.ModelPackageJson import com.facebook.react.tests.createProject +import com.facebook.react.utils.ProjectUtils.getReactNativeArchitectures import com.facebook.react.utils.ProjectUtils.isHermesEnabled import com.facebook.react.utils.ProjectUtils.isNewArchEnabled import com.facebook.react.utils.ProjectUtils.needsCodegenFromPackageJson import java.io.File -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue +import org.junit.Assert.* import org.junit.Rule import org.junit.Test import org.junit.rules.TemporaryFolder @@ -125,7 +125,7 @@ class ProjectUtilsTest { .trimIndent()) } extension.root.set(tempFolder.root) - assertTrue(project.needsCodegenFromPackageJson(extension)) + assertTrue(project.needsCodegenFromPackageJson(extension.root)) } @Test @@ -143,7 +143,7 @@ class ProjectUtilsTest { .trimIndent()) } extension.root.set(tempFolder.root) - assertFalse(project.needsCodegenFromPackageJson(extension)) + assertFalse(project.needsCodegenFromPackageJson(extension.root)) } @Test @@ -161,4 +161,49 @@ class ProjectUtilsTest { assertFalse(project.needsCodegenFromPackageJson(model)) } + + @Test + fun needsCodegenFromPackageJson_withMissingPackageJson_returnsFalse() { + val project = createProject() + val extension = TestReactExtension(project) + + assertFalse(project.needsCodegenFromPackageJson(extension.root)) + } + + @Test + fun getReactNativeArchitectures_withMissingProperty_returnsEmptyList() { + val project = createProject() + assertTrue(project.getReactNativeArchitectures().isEmpty()) + } + + @Test + fun getReactNativeArchitectures_withEmptyProperty_returnsEmptyList() { + val project = createProject() + project.extensions.extraProperties.set("reactNativeArchitectures", "") + assertTrue(project.getReactNativeArchitectures().isEmpty()) + } + + @Test + fun getReactNativeArchitectures_withSingleArch_returnsSingleton() { + val project = createProject() + project.extensions.extraProperties.set("reactNativeArchitectures", "x86") + + val archs = project.getReactNativeArchitectures() + assertEquals(1, archs.size) + assertEquals("x86", archs[0]) + } + + @Test + fun getReactNativeArchitectures_withMultipleArch_returnsList() { + val project = createProject() + project.extensions.extraProperties.set( + "reactNativeArchitectures", "armeabi-v7a,arm64-v8a,x86,x86_64") + + val archs = project.getReactNativeArchitectures() + assertEquals(4, archs.size) + assertEquals("armeabi-v7a", archs[0]) + assertEquals("arm64-v8a", archs[1]) + assertEquals("x86", archs[2]) + assertEquals("x86_64", archs[3]) + } } diff --git a/packages/rn-tester/Gemfile b/packages/rn-tester/Gemfile index 7bb000655cb6..081fa4ff8054 100644 --- a/packages/rn-tester/Gemfile +++ b/packages/rn-tester/Gemfile @@ -1,5 +1,8 @@ # Gemfile source 'https://rubygems.org' -gem 'cocoapods', '= 1.11.3' +# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper +# bound in the template on Cocoapods with next React Native release. +gem 'cocoapods', '>= 1.13', '< 1.15' gem 'rexml' +gem 'activesupport', '>= 6.1.7.3', '< 7.1.0' diff --git a/packages/rn-tester/Podfile b/packages/rn-tester/Podfile index 3e6f2c798d1c..36b03d00d2cb 100644 --- a/packages/rn-tester/Podfile +++ b/packages/rn-tester/Podfile @@ -37,7 +37,8 @@ def pods(target_name, options = {}, use_flipper: !IN_CI && !USE_FRAMEWORKS) flipper_configuration: use_flipper ? FlipperConfiguration.enabled : FlipperConfiguration.disabled, app_path: "#{Dir.pwd}", config_file_dir: "#{Dir.pwd}/node_modules", - production: !ENV['PRODUCTION'].nil? + production: !ENV['PRODUCTION'].nil?, + ios_folder: '.', ) pod 'ReactCommon/turbomodule/samples', :path => "#{@prefix_path}/ReactCommon" diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index e0e985659ce5..836f5035a30a 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -2,14 +2,14 @@ PODS: - boost (1.76.0) - CocoaAsyncSocket (7.6.5) - DoubleConversion (1.1.6) - - FBLazyVector (0.71.0-rc.0) - - FBReactNativeSpec (0.71.0-rc.0): - - RCT-Folly (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-Core (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) + - FBLazyVector (0.71.16) + - FBReactNativeSpec (0.71.16): + - RCT-Folly (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-Core (= 0.71.16) + - React-jsi (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) - Flipper (0.125.0): - Flipper-Folly (~> 2.6) - Flipper-RSocket (~> 1.4) @@ -73,9 +73,9 @@ PODS: - FlipperKit/FlipperKitNetworkPlugin - fmt (6.2.1) - glog (0.3.5) - - hermes-engine (0.71.0-rc.0): - - hermes-engine/Pre-built (= 0.71.0-rc.0) - - hermes-engine/Pre-built (0.71.0-rc.0) + - hermes-engine (0.71.16): + - hermes-engine/Pre-built (= 0.71.16) + - hermes-engine/Pre-built (0.71.16) - libevent (2.1.12) - OpenSSL-Universal (1.1.1100) - RCT-Folly (2021.07.22.00): @@ -100,656 +100,687 @@ PODS: - fmt (~> 6.2.1) - glog - libevent - - RCTRequired (0.71.0-rc.0) - - RCTTypeSafety (0.71.0-rc.0): - - FBLazyVector (= 0.71.0-rc.0) - - RCTRequired (= 0.71.0-rc.0) - - React-Core (= 0.71.0-rc.0) - - React (0.71.0-rc.0): - - React-Core (= 0.71.0-rc.0) - - React-Core/DevSupport (= 0.71.0-rc.0) - - React-Core/RCTWebSocket (= 0.71.0-rc.0) - - React-RCTActionSheet (= 0.71.0-rc.0) - - React-RCTAnimation (= 0.71.0-rc.0) - - React-RCTBlob (= 0.71.0-rc.0) - - React-RCTImage (= 0.71.0-rc.0) - - React-RCTLinking (= 0.71.0-rc.0) - - React-RCTNetwork (= 0.71.0-rc.0) - - React-RCTSettings (= 0.71.0-rc.0) - - React-RCTText (= 0.71.0-rc.0) - - React-RCTVibration (= 0.71.0-rc.0) - - React-callinvoker (0.71.0-rc.0) - - React-Codegen (0.71.0-rc.0): - - FBReactNativeSpec (= 0.71.0-rc.0) + - RCTRequired (0.71.16) + - RCTTypeSafety (0.71.16): + - FBLazyVector (= 0.71.16) + - RCTRequired (= 0.71.16) + - React-Core (= 0.71.16) + - React (0.71.16): + - React-Core (= 0.71.16) + - React-Core/DevSupport (= 0.71.16) + - React-Core/RCTWebSocket (= 0.71.16) + - React-RCTActionSheet (= 0.71.16) + - React-RCTAnimation (= 0.71.16) + - React-RCTBlob (= 0.71.16) + - React-RCTImage (= 0.71.16) + - React-RCTLinking (= 0.71.16) + - React-RCTNetwork (= 0.71.16) + - React-RCTSettings (= 0.71.16) + - React-RCTText (= 0.71.16) + - React-RCTVibration (= 0.71.16) + - React-callinvoker (0.71.16) + - React-Codegen (0.71.16): + - FBReactNativeSpec - hermes-engine - - RCT-Folly (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-Core (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-rncore (= 0.71.0-rc.0) - - ReactCommon/turbomodule/bridging (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Core (0.71.0-rc.0): + - RCT-Folly + - RCTRequired + - RCTTypeSafety + - React-Core + - React-graphics + - React-jsi + - React-jsiexecutor + - React-rncore + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - React-Core (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.71.0-rc.0) - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-Core/Default (= 0.71.16) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-Core/CoreModulesHeaders (0.71.0-rc.0): + - React-Core/CoreModulesHeaders (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-Core/Default (0.71.0-rc.0): + - React-Core/Default (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-Core/DevSupport (0.71.0-rc.0): + - React-Core/DevSupport (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.71.0-rc.0) - - React-Core/RCTWebSocket (= 0.71.0-rc.0) - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-jsinspector (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-Core/Default (= 0.71.16) + - React-Core/RCTWebSocket (= 0.71.16) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-jsinspector (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-Core/RCTActionSheetHeaders (0.71.0-rc.0): + - React-Core/RCTActionSheetHeaders (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-Core/RCTAnimationHeaders (0.71.0-rc.0): + - React-Core/RCTAnimationHeaders (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-Core/RCTBlobHeaders (0.71.0-rc.0): + - React-Core/RCTBlobHeaders (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-Core/RCTImageHeaders (0.71.0-rc.0): + - React-Core/RCTImageHeaders (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-Core/RCTLinkingHeaders (0.71.0-rc.0): + - React-Core/RCTLinkingHeaders (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-Core/RCTNetworkHeaders (0.71.0-rc.0): + - React-Core/RCTNetworkHeaders (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-Core/RCTPushNotificationHeaders (0.71.0-rc.0): + - React-Core/RCTPushNotificationHeaders (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-Core/RCTSettingsHeaders (0.71.0-rc.0): + - React-Core/RCTSettingsHeaders (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-Core/RCTTextHeaders (0.71.0-rc.0): + - React-Core/RCTTextHeaders (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-Core/RCTVibrationHeaders (0.71.0-rc.0): + - React-Core/RCTVibrationHeaders (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-Core/RCTWebSocket (0.71.0-rc.0): + - React-Core/RCTWebSocket (0.71.16): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.71.0-rc.0) - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) + - React-Core/Default (= 0.71.16) + - React-cxxreact (= 0.71.16) + - React-hermes + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-perflogger (= 0.71.16) - Yoga - - React-CoreModules (0.71.0-rc.0): - - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-Codegen (= 0.71.0-rc.0) - - React-Core/CoreModulesHeaders (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-RCTImage (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-cxxreact (0.71.0-rc.0): + - React-CoreModules (0.71.16): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.71.16) + - React-Codegen (= 0.71.16) + - React-Core/CoreModulesHeaders (= 0.71.16) + - React-jsi (= 0.71.16) + - React-RCTBlob + - React-RCTImage (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-cxxreact (0.71.16): - boost (= 1.76.0) - DoubleConversion - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsinspector (= 0.71.0-rc.0) - - React-logger (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) - - React-runtimeexecutor (= 0.71.0-rc.0) - - React-Fabric (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-Fabric/animations (= 0.71.0-rc.0) - - React-Fabric/attributedstring (= 0.71.0-rc.0) - - React-Fabric/butter (= 0.71.0-rc.0) - - React-Fabric/componentregistry (= 0.71.0-rc.0) - - React-Fabric/componentregistrynative (= 0.71.0-rc.0) - - React-Fabric/components (= 0.71.0-rc.0) - - React-Fabric/config (= 0.71.0-rc.0) - - React-Fabric/core (= 0.71.0-rc.0) - - React-Fabric/debug_core (= 0.71.0-rc.0) - - React-Fabric/debug_renderer (= 0.71.0-rc.0) - - React-Fabric/imagemanager (= 0.71.0-rc.0) - - React-Fabric/leakchecker (= 0.71.0-rc.0) - - React-Fabric/mapbuffer (= 0.71.0-rc.0) - - React-Fabric/mounting (= 0.71.0-rc.0) - - React-Fabric/runtimescheduler (= 0.71.0-rc.0) - - React-Fabric/scheduler (= 0.71.0-rc.0) - - React-Fabric/telemetry (= 0.71.0-rc.0) - - React-Fabric/templateprocessor (= 0.71.0-rc.0) - - React-Fabric/textlayoutmanager (= 0.71.0-rc.0) - - React-Fabric/uimanager (= 0.71.0-rc.0) - - React-Fabric/utils (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/animations (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/attributedstring (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/butter (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/componentregistry (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/componentregistrynative (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/components (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-Fabric/components/activityindicator (= 0.71.0-rc.0) - - React-Fabric/components/image (= 0.71.0-rc.0) - - React-Fabric/components/inputaccessory (= 0.71.0-rc.0) - - React-Fabric/components/legacyviewmanagerinterop (= 0.71.0-rc.0) - - React-Fabric/components/modal (= 0.71.0-rc.0) - - React-Fabric/components/root (= 0.71.0-rc.0) - - React-Fabric/components/safeareaview (= 0.71.0-rc.0) - - React-Fabric/components/scrollview (= 0.71.0-rc.0) - - React-Fabric/components/slider (= 0.71.0-rc.0) - - React-Fabric/components/text (= 0.71.0-rc.0) - - React-Fabric/components/textinput (= 0.71.0-rc.0) - - React-Fabric/components/unimplementedview (= 0.71.0-rc.0) - - React-Fabric/components/view (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/components/activityindicator (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/components/image (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/components/inputaccessory (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/components/legacyviewmanagerinterop (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/components/modal (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/components/root (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/components/safeareaview (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/components/scrollview (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/components/slider (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/components/text (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/components/textinput (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/components/unimplementedview (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/components/view (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) + - React-callinvoker (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsinspector (= 0.71.16) + - React-logger (= 0.71.16) + - React-perflogger (= 0.71.16) + - React-runtimeexecutor (= 0.71.16) + - React-Fabric (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-Fabric/animations (= 0.71.16) + - React-Fabric/attributedstring (= 0.71.16) + - React-Fabric/butter (= 0.71.16) + - React-Fabric/componentregistry (= 0.71.16) + - React-Fabric/componentregistrynative (= 0.71.16) + - React-Fabric/components (= 0.71.16) + - React-Fabric/config (= 0.71.16) + - React-Fabric/core (= 0.71.16) + - React-Fabric/debug_core (= 0.71.16) + - React-Fabric/debug_renderer (= 0.71.16) + - React-Fabric/imagemanager (= 0.71.16) + - React-Fabric/leakchecker (= 0.71.16) + - React-Fabric/mapbuffer (= 0.71.16) + - React-Fabric/mounting (= 0.71.16) + - React-Fabric/runtimescheduler (= 0.71.16) + - React-Fabric/scheduler (= 0.71.16) + - React-Fabric/telemetry (= 0.71.16) + - React-Fabric/templateprocessor (= 0.71.16) + - React-Fabric/textlayoutmanager (= 0.71.16) + - React-Fabric/uimanager (= 0.71.16) + - React-Fabric/utils (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/animations (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/attributedstring (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/butter (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/componentregistry (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/componentregistrynative (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/components (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-Fabric/components/activityindicator (= 0.71.16) + - React-Fabric/components/image (= 0.71.16) + - React-Fabric/components/inputaccessory (= 0.71.16) + - React-Fabric/components/legacyviewmanagerinterop (= 0.71.16) + - React-Fabric/components/modal (= 0.71.16) + - React-Fabric/components/root (= 0.71.16) + - React-Fabric/components/safeareaview (= 0.71.16) + - React-Fabric/components/scrollview (= 0.71.16) + - React-Fabric/components/slider (= 0.71.16) + - React-Fabric/components/text (= 0.71.16) + - React-Fabric/components/textinput (= 0.71.16) + - React-Fabric/components/unimplementedview (= 0.71.16) + - React-Fabric/components/view (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/components/activityindicator (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/components/image (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/components/inputaccessory (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/components/legacyviewmanagerinterop (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/components/modal (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/components/root (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/components/safeareaview (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/components/scrollview (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/components/slider (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/components/text (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/components/textinput (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/components/unimplementedview (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/components/view (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) - Yoga - - React-Fabric/config (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/core (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsidynamic (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/debug_core (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/debug_renderer (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/imagemanager (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-RCTImage (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/leakchecker (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/mapbuffer (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/mounting (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/runtimescheduler (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/scheduler (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/telemetry (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/templateprocessor (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/textlayoutmanager (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) + - React-Fabric/config (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/core (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/debug_core (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/debug_renderer (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/imagemanager (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - React-RCTImage (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/leakchecker (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/mapbuffer (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/mounting (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/runtimescheduler (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/scheduler (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/telemetry (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/templateprocessor (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/textlayoutmanager (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) - React-Fabric/uimanager - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/uimanager (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsidynamic (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-Fabric/utils (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - RCTRequired (= 0.71.0-rc.0) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-graphics (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-graphics (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - React-Core/Default (= 0.71.0-rc.0) - - React-hermes (0.71.0-rc.0): + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/uimanager (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-Fabric/utils (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 0.71.16) + - RCTTypeSafety (= 0.71.16) + - React-graphics (= 0.71.16) + - React-jsi (= 0.71.16) + - React-jsiexecutor (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-graphics (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - React-Core/Default (= 0.71.16) + - React-hermes (0.71.16): - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - RCT-Folly/Futures (= 2021.07.22.00) - - React-cxxreact (= 0.71.0-rc.0) - - React-jsidynamic (= 0.71.0-rc.0) - - React-jsiexecutor (= 0.71.0-rc.0) - - React-jsinspector (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) - - React-jsi (0.71.0-rc.0): - - hermes-engine - - React-jsidynamic (0.71.0-rc.0): + - React-cxxreact (= 0.71.16) + - React-jsi + - React-jsiexecutor (= 0.71.16) + - React-jsinspector (= 0.71.16) + - React-perflogger (= 0.71.16) + - React-jsi (0.71.16): - boost (= 1.76.0) - DoubleConversion - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-jsi (= 0.71.0-rc.0) - - React-jsiexecutor (0.71.0-rc.0): + - React-jsiexecutor (0.71.16): - DoubleConversion - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsidynamic (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) - - React-jsinspector (0.71.0-rc.0) - - React-logger (0.71.0-rc.0): + - React-cxxreact (= 0.71.16) + - React-jsi (= 0.71.16) + - React-perflogger (= 0.71.16) + - React-jsinspector (0.71.16) + - React-logger (0.71.16): - glog - - React-perflogger (0.71.0-rc.0) - - React-RCTActionSheet (0.71.0-rc.0): - - React-Core/RCTActionSheetHeaders (= 0.71.0-rc.0) - - React-RCTAnimation (0.71.0-rc.0): - - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-Codegen (= 0.71.0-rc.0) - - React-Core/RCTAnimationHeaders (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-RCTAppDelegate (0.71.0-rc.0): + - React-perflogger (0.71.16) + - React-RCTActionSheet (0.71.16): + - React-Core/RCTActionSheetHeaders (= 0.71.16) + - React-RCTAnimation (0.71.16): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.71.16) + - React-Codegen (= 0.71.16) + - React-Core/RCTAnimationHeaders (= 0.71.16) + - React-jsi (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-RCTAppDelegate (0.71.16): - RCT-Folly - RCTRequired - RCTTypeSafety - React-Core - ReactCommon/turbomodule/core - - React-RCTBlob (0.71.0-rc.0): - - RCT-Folly (= 2021.07.22.00) - - React-Codegen (= 0.71.0-rc.0) - - React-Core/RCTBlobHeaders (= 0.71.0-rc.0) - - React-Core/RCTWebSocket (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-RCTNetwork (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-RCTFabric (0.71.0-rc.0): - - RCT-Folly/Fabric (= 2021.07.22.00) - - React-Core (= 0.71.0-rc.0) - - React-Fabric (= 0.71.0-rc.0) - - React-RCTImage (= 0.71.0-rc.0) - - React-RCTImage (0.71.0-rc.0): - - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-Codegen (= 0.71.0-rc.0) - - React-Core/RCTImageHeaders (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-RCTNetwork (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-RCTLinking (0.71.0-rc.0): - - React-Codegen (= 0.71.0-rc.0) - - React-Core/RCTLinkingHeaders (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-RCTNetwork (0.71.0-rc.0): - - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-Codegen (= 0.71.0-rc.0) - - React-Core/RCTNetworkHeaders (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-RCTPushNotification (0.71.0-rc.0): - - RCTTypeSafety (= 0.71.0-rc.0) - - React-Codegen (= 0.71.0-rc.0) - - React-Core/RCTPushNotificationHeaders (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-RCTSettings (0.71.0-rc.0): - - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.0-rc.0) - - React-Codegen (= 0.71.0-rc.0) - - React-Core/RCTSettingsHeaders (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-RCTTest (0.71.0-rc.0): - - RCT-Folly (= 2021.07.22.00) - - React-Core (= 0.71.0-rc.0) - - React-CoreModules (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-RCTText (0.71.0-rc.0): - - React-Core/RCTTextHeaders (= 0.71.0-rc.0) - - React-RCTVibration (0.71.0-rc.0): - - RCT-Folly (= 2021.07.22.00) - - React-Codegen (= 0.71.0-rc.0) - - React-Core/RCTVibrationHeaders (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) - - React-rncore (0.71.0-rc.0) - - React-runtimeexecutor (0.71.0-rc.0): - - React-jsi (= 0.71.0-rc.0) - - ReactCommon/turbomodule/bridging (0.71.0-rc.0): + - React-RCTBlob (0.71.16): + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - React-Codegen (= 0.71.16) + - React-Core/RCTBlobHeaders (= 0.71.16) + - React-Core/RCTWebSocket (= 0.71.16) + - React-jsi (= 0.71.16) + - React-RCTNetwork (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-RCTFabric (0.71.16): + - RCT-Folly/Fabric (= 2021.07.22.00) + - React-Core (= 0.71.16) + - React-Fabric (= 0.71.16) + - React-RCTImage (= 0.71.16) + - React-RCTImage (0.71.16): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.71.16) + - React-Codegen (= 0.71.16) + - React-Core/RCTImageHeaders (= 0.71.16) + - React-jsi (= 0.71.16) + - React-RCTNetwork (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-RCTLinking (0.71.16): + - React-Codegen (= 0.71.16) + - React-Core/RCTLinkingHeaders (= 0.71.16) + - React-jsi (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-RCTNetwork (0.71.16): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.71.16) + - React-Codegen (= 0.71.16) + - React-Core/RCTNetworkHeaders (= 0.71.16) + - React-jsi (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-RCTPushNotification (0.71.16): + - RCTTypeSafety (= 0.71.16) + - React-Codegen (= 0.71.16) + - React-Core/RCTPushNotificationHeaders (= 0.71.16) + - React-jsi (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-RCTSettings (0.71.16): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.71.16) + - React-Codegen (= 0.71.16) + - React-Core/RCTSettingsHeaders (= 0.71.16) + - React-jsi (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-RCTTest (0.71.16): + - RCT-Folly (= 2021.07.22.00) + - React-Core (= 0.71.16) + - React-CoreModules (= 0.71.16) + - React-jsi (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-RCTText (0.71.16): + - React-Core/RCTTextHeaders (= 0.71.16) + - React-RCTVibration (0.71.16): + - RCT-Folly (= 2021.07.22.00) + - React-Codegen (= 0.71.16) + - React-Core/RCTVibrationHeaders (= 0.71.16) + - React-jsi (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) + - React-rncore (0.71.16) + - React-runtimeexecutor (0.71.16): + - React-jsi (= 0.71.16) + - ReactCommon/turbomodule/bridging (0.71.16): - DoubleConversion - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.71.0-rc.0) - - React-Core (= 0.71.0-rc.0) - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-logger (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (0.71.0-rc.0): + - React-callinvoker (= 0.71.16) + - React-Core (= 0.71.16) + - React-cxxreact (= 0.71.16) + - React-jsi (= 0.71.16) + - React-logger (= 0.71.16) + - React-perflogger (= 0.71.16) + - ReactCommon/turbomodule/core (0.71.16): - DoubleConversion - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.71.0-rc.0) - - React-Core (= 0.71.0-rc.0) - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-jsidynamic (= 0.71.0-rc.0) - - React-logger (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) - - ReactCommon/turbomodule/samples (0.71.0-rc.0): + - React-callinvoker (= 0.71.16) + - React-Core (= 0.71.16) + - React-cxxreact (= 0.71.16) + - React-jsi (= 0.71.16) + - React-logger (= 0.71.16) + - React-perflogger (= 0.71.16) + - ReactCommon/turbomodule/samples (0.71.16): - DoubleConversion - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.71.0-rc.0) - - React-Core (= 0.71.0-rc.0) - - React-cxxreact (= 0.71.0-rc.0) - - React-jsi (= 0.71.0-rc.0) - - React-logger (= 0.71.0-rc.0) - - React-perflogger (= 0.71.0-rc.0) - - ReactCommon/turbomodule/core (= 0.71.0-rc.0) + - React-callinvoker (= 0.71.16) + - React-Core (= 0.71.16) + - React-cxxreact (= 0.71.16) + - React-jsi (= 0.71.16) + - React-logger (= 0.71.16) + - React-perflogger (= 0.71.16) + - ReactCommon/turbomodule/core (= 0.71.16) - ScreenshotManager (0.0.1): - RCT-Folly (= 2021.07.22.00) - React-Core @@ -785,7 +816,7 @@ DEPENDENCIES: - FlipperKit/FlipperKitUserDefaultsPlugin (= 0.125.0) - FlipperKit/SKIOSNetworkPlugin (= 0.125.0) - glog (from `../../third-party-podspecs/glog.podspec`) - - hermes-engine (from `../../sdks/hermes/hermes-engine.podspec`) + - hermes-engine (from `../../sdks/hermes-engine/hermes-engine.podspec`) - libevent (~> 2.1.12) - OpenSSL-Universal (= 1.1.1100) - RCT-Folly (from `../../third-party-podspecs/RCT-Folly.podspec`) @@ -804,7 +835,6 @@ DEPENDENCIES: - React-graphics (from `../../ReactCommon/react/renderer/graphics`) - React-hermes (from `../../ReactCommon/hermes`) - React-jsi (from `../../ReactCommon/jsi`) - - React-jsidynamic (from `../../ReactCommon/jsi`) - React-jsiexecutor (from `../../ReactCommon/jsiexecutor`) - React-jsinspector (from `../../ReactCommon/jsinspector`) - React-logger (from `../../ReactCommon/logger`) @@ -859,7 +889,7 @@ EXTERNAL SOURCES: glog: :podspec: "../../third-party-podspecs/glog.podspec" hermes-engine: - :podspec: "../../sdks/hermes/hermes-engine.podspec" + :podspec: "../../sdks/hermes-engine/hermes-engine.podspec" RCT-Folly: :podspec: "../../third-party-podspecs/RCT-Folly.podspec" RCTRequired: @@ -886,8 +916,6 @@ EXTERNAL SOURCES: :path: "../../ReactCommon/hermes" React-jsi: :path: "../../ReactCommon/jsi" - React-jsidynamic: - :path: "../../ReactCommon/jsi" React-jsiexecutor: :path: "../../ReactCommon/jsiexecutor" React-jsinspector: @@ -934,11 +962,11 @@ EXTERNAL SOURCES: :path: "../../ReactCommon/yoga" SPEC CHECKSUMS: - boost: 57d2868c099736d80fcd648bf211b4431e51a558 + boost: 7dcd2de282d72e344012f7d6564d024930a6a440 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 - FBLazyVector: a96ec3f59b8c90499d34335be5009ff98173c820 - FBReactNativeSpec: ce0d3bbe50bf00f6063739310ec02ff846e8e25a + FBLazyVector: 9840513ec2766e31fb9e34c2dabb2c4671400fcd + FBReactNativeSpec: 510e811a56c257b4b1e3e9ea9ec0f4199f9be314 Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0 Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 @@ -950,48 +978,47 @@ SPEC CHECKSUMS: FlipperKit: cbdee19bdd4e7f05472a66ce290f1b729ba3cb86 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b - hermes-engine: 61d7d52b260b08591e4fcc20309e084ab6d4547d + hermes-engine: 2382506846564caf4152c45390dc24f08fce7057 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 - RCTRequired: 2e752d0602620b58ca34b8fdb206c5ea2299a1b6 - RCTTypeSafety: 043f37f7679d28a42e48391a88a6baa665aaa875 - React: b880ae6be1584cb9dc58a5833c692b9fc6645767 - React-callinvoker: e364d27799930b492e3197b3e9aae472f861aa65 - React-Codegen: b719a4e28f3ec6db5976159e589e3c18f2963e03 - React-Core: bf34ffba62b57bc481578c2e381ccb8084823a8c - React-CoreModules: 08072bc4fc72d77d6f6476642a0976068f8a3f91 - React-cxxreact: 4d9cdb74e6f9156b5c63a58bc8cbc22b6b718332 - React-Fabric: 90859ecf3b1b93fa00d39695e1677e099f14b672 - React-graphics: c32f3e87a5dd23b3d653d57e2972d170e48900ee - React-hermes: 76843a3f2613caba1dad537d990aa15cfbcff7fb - React-jsi: f4af16a8fc555f49953deb4ce0b0f48dbc6c043f - React-jsidynamic: 55422c39884324bf1e4b04ab4be164bcc064fff9 - React-jsiexecutor: 6e0893f69e4a169f81d904192490447ee0f3a170 - React-jsinspector: a4ad2370d57f0150f21f4684b8931b8226580353 - React-logger: 95b3d56468b4968ecce58951e756f03082eb6bed - React-perflogger: 9533f63024f91cb527178f236ae3317c94fdc15f - React-RCTActionSheet: 0e2efddd25f88028c8b1df202afe7a0aeeeb170b - React-RCTAnimation: 1868f537cfd001f2183550199a3fb44a7921d1f0 - React-RCTAppDelegate: 6ae05562a28eb400a39a7d7d20c4dbc5a3604871 - React-RCTBlob: d6905b10424f7dbd244253dbb15193ac2bf8a073 - React-RCTFabric: 1ea60620417e316457e9bde0bf86aa8ed99aef48 - React-RCTImage: 5b1194ff3ebba402ff0e286719b341081786e21a - React-RCTLinking: 7cc81f96011a7979f610793c510ad75dbcc32727 - React-RCTNetwork: 13455ef64bbd0dbe58b0d7bd511bf9702550b64b - React-RCTPushNotification: e1b6f9e6d400eb40e96b29e6855eb8e32b02b203 - React-RCTSettings: 4ad5cbbda0c58f57e416d23a27d927c312194864 - React-RCTTest: a98da24c11276d12eee4dc590e5a9bf058f44a37 - React-RCTText: d7fb841e8dd730ef1633dfe92674248e7106f775 - React-RCTVibration: 64be373eed57a9fd53cf8e0d0bfd781e60814ec3 - React-rncore: cd0d14bf29f01491f49d1f19fd1a044d4b43e754 - React-runtimeexecutor: 7a1ac2b06a997a985f9fbdc6abbac38dd9e9aa48 - ReactCommon: a2930d4580a7bcc1f09d59c08de08e2d758f506a - ScreenshotManager: cf552c19152e3357f08875fc2f85adb2dee6a66b + RCTRequired: 44a3cda52ccac0be738fbf43fef90f3546a48c52 + RCTTypeSafety: da7fbf9826fc898ca8b10dc840f2685562039a64 + React: defd955b6d6ffb9791bb66dee08d90b87a8e2c0c + React-callinvoker: 39ea57213d56ec9c527d51bd0dfb45cbb12ef447 + React-Codegen: 36395766ab7ae5f4e7a2b3d22909e71ea0589760 + React-Core: 898cb2f7785640e21d381b23fc64a2904628b368 + React-CoreModules: 7f71e7054395d61585048061a66d67b58d3d27b7 + React-cxxreact: 57fca29dd6995de0ee360980709c4be82d40cda1 + React-Fabric: 497eb843376544dfbe37cc6c334d8bd18cdff63b + React-graphics: 313d5aff65e62453b8bcd5c0c437448a4f01200b + React-hermes: 33229fc1867df496665b36b222a82a0f850bcae1 + React-jsi: 3a55652789df6ddd777cce9601bf000e18d6b9df + React-jsiexecutor: 9b2a87f674f30da4706af52520e4860974cec149 + React-jsinspector: b3b341764ccda14f3659c00a9bc5b098b334db2b + React-logger: dc96fadd2f7f6bc38efc3cfb5fef876d4e6290a2 + React-perflogger: c944b06edad34f5ecded0f29a6e66290a005d365 + React-RCTActionSheet: fa467f37777dacba2c72da4be7ae065da4482d7d + React-RCTAnimation: 0591ee5f9e3d8c864a0937edea2165fe968e7099 + React-RCTAppDelegate: 8b7f60103a83ad1670bda690571e73efddba29a0 + React-RCTBlob: 082e8612f48b0ec12ca6dc949fb7c310593eff83 + React-RCTFabric: 71d180575130f799cc466ffd7b2a5ef7903ab1f8 + React-RCTImage: 6300660ef04d0e8a710ad9ea5d2fb4d9521c200d + React-RCTLinking: 7703ee1b10d3568c143a489ae74adc419c3f3ef3 + React-RCTNetwork: 5748c647e09c66b918f81ae15ed7474327f653be + React-RCTPushNotification: 550538bea1aa073efc706afa5749a6f3107484b0 + React-RCTSettings: 8c8a84ee363db9cbc287c8b8f2fb782acf7ba414 + React-RCTTest: 09d2227cadfb85cd29a608af540d2787b360b623 + React-RCTText: d5e53c0741e3e2df91317781e993b5e42bd70448 + React-RCTVibration: 052dd488ba95f461a37c992b9e01bd4bcc59a7b6 + React-rncore: 5d2bb753849256d058b3986f96823102f6f7c21b + React-runtimeexecutor: b5abe02558421897cd9f73d4f4b6adb4bc297083 + ReactCommon: a1a263d94f02a0dc8442f341d5a11b3d7a9cd44d + ScreenshotManager: e77ad8e427160ebce1f86313e2b21ea56b665285 SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 - Yoga: 167c6bcfbcd203adef48d2310491e85c51daeaf2 + Yoga: e29645ec5a66fb00934fad85338742d1c247d4cb YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: 5d1fc1e8809808c4384337ae55c5be2de48ffe4c +PODFILE CHECKSUM: 8da43cb75927abd2bbb2fc21dcebfebb05b89963 -COCOAPODS: 1.11.3 +COCOAPODS: 1.14.2 diff --git a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj index 73488e795ff4..f3be7d174154 100644 --- a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj +++ b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj @@ -410,8 +410,8 @@ 13B07F8E1A680F5B00A75B9A /* Resources */, 68CD48B71D2BCB2C007E06A9 /* Build JS Bundle */, 5CF0FD27207FC6EC00C13D65 /* Start Metro */, - 2FCDFB64B37634EC8EC3139B /* [CP] Embed Pods Frameworks */, A8DE6393E2BB72D8FBBF6C27 /* [CP] Copy Pods Resources */, + 0E73F7BE135ED3CB747D68FD /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -431,7 +431,7 @@ E7DB209C22B2BA84005AC45F /* Frameworks */, E7DB209D22B2BA84005AC45F /* Resources */, 9A596313B3964A4DEB794409 /* [CP] Copy Pods Resources */, - 284FCEB787673BF7B938D5E0 /* [CP] Embed Pods Frameworks */, + EDAA7465432C085C1E35BA3C /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -452,7 +452,7 @@ E7DB215022B2F332005AC45F /* Frameworks */, E7DB215122B2F332005AC45F /* Resources */, 98E057AC8860597818FB485A /* [CP] Copy Pods Resources */, - 5814D608FC5071AB8F979BB0 /* [CP] Embed Pods Frameworks */, + ADECEE449CBDE08EA2E9E85F /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -531,46 +531,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 161EF0F0977844159431F6A5 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RNTester-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 284FCEB787673BF7B938D5E0 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 2FCDFB64B37634EC8EC3139B /* [CP] Embed Pods Frameworks */ = { + 0E73F7BE135ED3CB747D68FD /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -587,7 +548,7 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 4930FC87997EBCAD361CEF12 /* [CP] Check Pods Manifest.lock */ = { + 161EF0F0977844159431F6A5 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -602,28 +563,33 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RNTesterUnitTests-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-RNTester-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 5814D608FC5071AB8F979BB0 /* [CP] Embed Pods Frameworks */ = { + 4930FC87997EBCAD361CEF12 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - name = "[CP] Embed Pods Frameworks"; + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RNTesterUnitTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 5CF0FD27207FC6EC00C13D65 /* Start Metro */ = { @@ -730,6 +696,40 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-resources.sh\"\n"; showEnvVarsInLog = 0; }; + ADECEE449CBDE08EA2E9E85F /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + EDAA7465432C085C1E35BA3C /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -911,7 +911,7 @@ ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -919,6 +919,7 @@ GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", + _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION, ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; @@ -996,9 +997,13 @@ ENABLE_BITCODE = NO; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION, + ); GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; diff --git a/packages/rn-tester/RNTesterUnitTests/RCTBundleURLProviderTests.m b/packages/rn-tester/RNTesterUnitTests/RCTBundleURLProviderTests.m index 89164bc0bb4f..2f89a22c3233 100644 --- a/packages/rn-tester/RNTesterUnitTests/RCTBundleURLProviderTests.m +++ b/packages/rn-tester/RNTesterUnitTests/RCTBundleURLProviderTests.m @@ -27,7 +27,7 @@ URLWithString: [NSString stringWithFormat: - @"http://localhost:8081/%@.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&runtimeBytecodeVersion=%u&app=com.apple.dt.xctest.tool", + @"http://localhost:8081/%@.bundle?platform=ios&dev=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&runtimeBytecodeVersion=%u&app=com.apple.dt.xctest.tool", testFile, HERMES_BYTECODE_VERSION]]; #else @@ -35,7 +35,7 @@ URLWithString: [NSString stringWithFormat: - @"http://localhost:8081/%@.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=com.apple.dt.xctest.tool", + @"http://localhost:8081/%@.bundle?platform=ios&dev=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.apple.dt.xctest.tool", testFile]]; #endif } @@ -47,7 +47,7 @@ URLWithString: [NSString stringWithFormat: - @"http://192.168.1.1:8081/%@.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&runtimeBytecodeVersion=%u&app=com.apple.dt.xctest.tool", + @"http://192.168.1.1:8081/%@.bundle?platform=ios&dev=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&runtimeBytecodeVersion=%u&app=com.apple.dt.xctest.tool", testFile, HERMES_BYTECODE_VERSION]]; #else @@ -55,7 +55,7 @@ URLWithString: [NSString stringWithFormat: - @"http://192.168.1.1:8081/%@.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=com.apple.dt.xctest.tool", + @"http://192.168.1.1:8081/%@.bundle?platform=ios&dev=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.apple.dt.xctest.tool", testFile]]; #endif } diff --git a/packages/rn-tester/js/examples/PermissionsAndroid/PermissionsExample.js b/packages/rn-tester/js/examples/PermissionsAndroid/PermissionsExample.js index a0e40519725d..cd7f3035f93e 100644 --- a/packages/rn-tester/js/examples/PermissionsAndroid/PermissionsExample.js +++ b/packages/rn-tester/js/examples/PermissionsAndroid/PermissionsExample.js @@ -82,6 +82,17 @@ function PermissionsExample() { } style={styles.option} /> + + setPermission(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS) + } + selected={ + permission === PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS + } + style={styles.option} + /> diff --git a/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js b/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js index 7cff25b37ada..a5a4bf5c24bd 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js @@ -824,6 +824,13 @@ exports.examples = ([ + + + ); }, diff --git a/react.gradle b/react.gradle index da5505975a0c..250299bb7835 100644 --- a/react.gradle +++ b/react.gradle @@ -442,11 +442,11 @@ afterEvaluate { if (cleanup) { // Reduce size by deleting the debugger/inspector - include '**/libhermes-executor-debug.so' + include '**/libhermes_executor_debug.so' } else { // Release libs take precedence and must be removed // to allow debugging - include '**/libhermes-executor-release.so' + include '**/libhermes_executor_release.so' } } else { // For JSC, delete all the libhermes* files diff --git a/repo-config/package.json b/repo-config/package.json index d5a529afb2d7..aa5945caef29 100644 --- a/repo-config/package.json +++ b/repo-config/package.json @@ -9,14 +9,14 @@ "url": "git@github.com:facebook/react-native.git" }, "dependencies": { - "@babel/core": "^7.14.0", + "@babel/core": "^7.20.0", "@babel/eslint-parser": "^7.18.2", - "@babel/generator": "^7.14.0", + "@babel/generator": "^7.20.0", "@babel/plugin-transform-regenerator": "^7.0.0", "@definitelytyped/dtslint": "^0.0.127", "@react-native-community/eslint-config": "*", "@react-native-community/eslint-plugin": "*", - "@react-native/eslint-plugin-specs": "^0.71.1", + "@react-native/eslint-plugin-specs": "^0.71.2", "@reactions/component": "^2.0.2", "@types/react": "^18.0.18", "@typescript-eslint/parser": "^5.30.5", @@ -41,13 +41,13 @@ "inquirer": "^7.1.0", "jest": "^29.2.1", "jest-junit": "^10.0.0", - "jscodeshift": "^0.13.1", - "metro-babel-register": "0.73.3", - "metro-memory-fs": "0.73.3", + "jscodeshift": "^0.14.0", + "metro-babel-register": "0.73.10", + "metro-memory-fs": "0.73.10", "mkdirp": "^0.5.1", "prettier": "^2.4.1", "react": "18.2.0", - "react-native-codegen": "^0.71.3", + "react-native-codegen": "^0.71.6", "react-test-renderer": "18.2.0", "shelljs": "^0.8.5", "signedsource": "^1.0.0", diff --git a/scripts/__tests__/version-utils-test.js b/scripts/__tests__/version-utils-test.js index 0dd087e20b01..493be638bc7a 100644 --- a/scripts/__tests__/version-utils-test.js +++ b/scripts/__tests__/version-utils-test.js @@ -141,15 +141,6 @@ describe('version-utils', () => { expect(prerelease).toBe('rc.4'); }); - it('should reject pre-release version with patch != 0', () => { - function testInvalidVersion() { - parseVersion('0.66.3-rc.4', 'release'); - } - expect(testInvalidVersion).toThrowErrorMatchingInlineSnapshot( - `"Version 0.66.3-rc.4 is not valid for Release"`, - ); - }); - it('should reject pre-release version from tag with random prerelease pattern', () => { function testInvalidVersion() { parseVersion('v0.66.0-something_invalid', 'release'); @@ -228,15 +219,6 @@ describe('version-utils', () => { expect(prerelease).toBe('rc.0'); }); - it('should reject dryrun with prerelease . version with patch different from 0', () => { - function testInvalidFunction() { - parseVersion('0.20.3-rc.0', 'dry-run'); - } - expect(testInvalidFunction).toThrowErrorMatchingInlineSnapshot( - `"Version 0.20.3-rc.0 is not valid for dry-runs"`, - ); - }); - it('should parse dryrun with prerelease - version', () => { const {version, major, minor, patch, prerelease} = parseVersion( '0.20.0-rc-0', @@ -249,15 +231,6 @@ describe('version-utils', () => { expect(prerelease).toBe('rc-0'); }); - it('should reject dryrun with prerelease - version with patch different from 0', () => { - function testInvalidFunction() { - parseVersion('0.20.3-rc-0', 'dry-run'); - } - expect(testInvalidFunction).toThrowErrorMatchingInlineSnapshot( - `"Version 0.20.3-rc-0 is not valid for dry-runs"`, - ); - }); - it('should parse dryrun with main version', () => { const {version, major, minor, patch, prerelease} = parseVersion( '1000.0.0', diff --git a/scripts/circle-ci-artifacts-utils.js b/scripts/circle-ci-artifacts-utils.js new file mode 100644 index 000000000000..3a9d9d2a0c83 --- /dev/null +++ b/scripts/circle-ci-artifacts-utils.js @@ -0,0 +1,198 @@ +#!/usr/bin/env node +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +'use strict'; + +const {exec} = require('shelljs'); + +const util = require('util'); +const asyncRequest = require('request'); +const request = util.promisify(asyncRequest); + +let circleCIHeaders; +let jobs; +let baseTemporaryPath; + +async function initialize(circleCIToken, baseTempPath, branchName) { + console.info('Getting CircleCI information'); + circleCIHeaders = {'Circle-Token': circleCIToken}; + baseTemporaryPath = baseTempPath; + exec(`mkdir -p ${baseTemporaryPath}`); + const pipeline = await _getLastCircleCIPipelineID(branchName); + const packageAndReleaseWorkflow = await _getPackageAndReleaseWorkflow( + pipeline.id, + ); + const testsWorkflow = await _getTestsWorkflow(pipeline.id); + const jobsPromises = [ + _getCircleCIJobs(packageAndReleaseWorkflow.id), + _getCircleCIJobs(testsWorkflow.id), + ]; + + const jobsResults = await Promise.all(jobsPromises); + + jobs = jobsResults.flatMap(j => j); +} + +function baseTmpPath() { + return baseTemporaryPath; +} + +async function _getLastCircleCIPipelineID(branchName) { + const options = { + method: 'GET', + url: 'https://circleci.com/api/v2/project/gh/facebook/react-native/pipeline', + qs: { + branch: branchName, + }, + headers: circleCIHeaders, + }; + + const response = await request(options); + if (response.error) { + throw new Error(error); + } + + const items = JSON.parse(response.body).items; + + if (!items || items.length === 0) { + throw new Error( + 'No pipelines found on this branch. Make sure that the CI has run at least once, successfully', + ); + } + + const lastPipeline = items[0]; + return {id: lastPipeline.id, number: lastPipeline.number}; +} + +async function _getSpecificWorkflow(pipelineId, workflowName) { + const options = { + method: 'GET', + url: `https://circleci.com/api/v2/pipeline/${pipelineId}/workflow`, + headers: circleCIHeaders, + }; + const response = await request(options); + if (response.error) { + throw new Error(error); + } + + const body = JSON.parse(response.body); + let workflow = body.items.find(w => w.name === workflowName); + _throwIfWorkflowNotFound(workflow, workflowName); + return workflow; +} + +function _throwIfWorkflowNotFound(workflow, name) { + if (!workflow) { + throw new Error( + `Can't find a workflow named ${name}. Please check whether that workflow has started.`, + ); + } +} + +async function _getPackageAndReleaseWorkflow(pipelineId) { + return _getSpecificWorkflow(pipelineId, 'package_and_publish_release_dryrun'); +} + +async function _getTestsWorkflow(pipelineId) { + return _getSpecificWorkflow(pipelineId, 'tests'); +} + +async function _getCircleCIJobs(workflowId) { + const options = { + method: 'GET', + url: `https://circleci.com/api/v2/workflow/${workflowId}/job`, + headers: circleCIHeaders, + }; + const response = await request(options); + if (response.error) { + throw new Error(error); + } + + const body = JSON.parse(response.body); + return body.items; +} + +async function _getJobsArtifacts(jobNumber) { + const options = { + method: 'GET', + url: `https://circleci.com/api/v2/project/gh/facebook/react-native/${jobNumber}/artifacts`, + headers: circleCIHeaders, + }; + const response = await request(options); + if (response.error) { + throw new Error(error); + } + + const body = JSON.parse(response.body); + return body.items; +} + +async function _findUrlForJob(jobName, artifactPath) { + const job = jobs.find(j => j.name === jobName); + _throwIfJobIsNull(job); + _throwIfJobIsUnsuccessful(job); + + const artifacts = await _getJobsArtifacts(job.job_number); + return artifacts.find(artifact => artifact.path.indexOf(artifactPath) > -1) + .url; +} + +function _throwIfJobIsNull(job) { + if (!job) { + throw new Error( + `Can't find a job with name ${job.name}. Please verify that it has been executed and that all its dependencies completed successfully.`, + ); + } +} + +function _throwIfJobIsUnsuccessful(job) { + if (job.status !== 'success') { + throw new Error( + `The job ${job.name} status is ${job.status}. We need a 'success' status to proceed with the testing.`, + ); + } +} + +async function artifactURLHermesDebug() { + return _findUrlForJob('build_hermes_macos-Debug', 'hermes-ios-debug.tar.gz'); +} + +async function artifactURLForMavenLocal() { + return _findUrlForJob('build_and_publish_npm_package-2', 'maven-local.zip'); +} + +async function artifactURLForHermesRNTesterAPK(emulatorArch) { + return _findUrlForJob( + 'test_android', + `rntester-apk/hermes/debug/app-hermes-${emulatorArch}-debug.apk`, + ); +} + +async function artifactURLForJSCRNTesterAPK(emulatorArch) { + return _findUrlForJob( + 'test_android', + `rntester-apk/jsc/debug/app-jsc-${emulatorArch}-debug.apk`, + ); +} + +function downloadArtifact(artifactURL, destination) { + exec(`rm -rf ${destination}`); + exec(`curl ${artifactURL} -Lo ${destination}`); +} + +module.exports = { + initialize, + downloadArtifact, + artifactURLForJSCRNTesterAPK, + artifactURLForHermesRNTesterAPK, + artifactURLForMavenLocal, + artifactURLHermesDebug, + baseTmpPath, +}; diff --git a/scripts/circleci/poll-maven.js b/scripts/circleci/poll-maven.js new file mode 100644 index 000000000000..298909691e4c --- /dev/null +++ b/scripts/circleci/poll-maven.js @@ -0,0 +1,72 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const fetch = require('node-fetch'); +const fs = require('fs'); + +const baseMavenRepo = 'https://repo1.maven.org/maven2/com/facebook/react'; +const artifacts = ['react-native-artifacts', 'react-android', 'hermes-android']; +const humanNames = { + 'react-native-artifacts': 'Hermes for iOS', + 'react-android': 'React Native for Android', + 'hermes-android': 'Hermes for Android', +}; +const ping_minutes = 5; +const max_hours = 5; +const ping_interval = ping_minutes * 60 * 1000; // 5 minutes +const max_wait = max_hours * 60 * 60 * 1000; // 5 hours + +const startTime = Date.now(); + +async function pingMaven(artifact, rnVersion) { + const url = `${baseMavenRepo}/${artifact}/${rnVersion}`; + const response = await fetch(url, {method: 'HEAD'}); + if (response.status === 200) { + console.log(`Found artifact for ${humanNames[artifact]}\n`); + return; + } else if (response.status !== 404) { + throw new Error( + `Unexpected response code ${response.status} for ${humanNames[artifact]}`, + ); + } + + const elapsedTime = Date.now() - startTime; + if (elapsedTime > max_wait) { + throw new Error(`${max_hours} hours has passed. Exiting.`); + } + // Wait a bit + console.log( + `${humanNames[artifact]} not available yet. Waiting ${ping_minutes} minutes.\n`, + ); + await new Promise(resolve => setTimeout(resolve, ping_interval)); + await pingMaven(url); +} + +async function main() { + const package = JSON.parse( + fs.readFileSync('packages/react-native/package.json', 'utf8'), + ); + const rnVersion = package.version; + + if (rnVersion === '1000.0.0') { + console.log( + 'We are not on a release branch when a release has been initiated. Exiting.', + ); + return; + } + + console.log(`Checking artifacts for React Native version ${rnVersion}\n`); + + for (const artifact of artifacts) { + console.log(`Start pinging for ${humanNames[artifact]}`); + await pingMaven(artifact, rnVersion); + } +} + +main(); diff --git a/scripts/cocoapods/__tests__/codegen_utils-test.rb b/scripts/cocoapods/__tests__/codegen_utils-test.rb index 35f732efac60..219ba48eac30 100644 --- a/scripts/cocoapods/__tests__/codegen_utils-test.rb +++ b/scripts/cocoapods/__tests__/codegen_utils-test.rb @@ -15,6 +15,14 @@ require_relative "./test_utils/CodegenScriptPhaseExtractorMock.rb" require_relative "./test_utils/FileUtilsMock.rb" +# mocking the min_ios_version_supported function +# as it is not possible to require the original react_native_pod +# without incurring in circular deps +# TODO: move `min_ios_version_supported` to utils.rb +def min_ios_version_supported + return '12.4' +end + class CodegenUtilsTests < Test::Unit::TestCase :base_path @@ -344,7 +352,7 @@ def testUseReactCodegenDiscovery_whenParametersAreGood_executeCodegen '[Codegen] warn: using experimental new codegen integration' ]) assert_equal(codegen_utils_mock.get_react_codegen_script_phases_params, [{ - :app_path => "~/app", + :app_path => app_path, :config_file_dir => "", :config_key => "codegenConfig", :fabric_enabled => false, @@ -353,7 +361,7 @@ def testUseReactCodegenDiscovery_whenParametersAreGood_executeCodegen assert_equal(codegen_utils_mock.get_react_codegen_spec_params, [{ :fabric_enabled => false, :folly_version=>"2021.07.22.00", - :package_json_file => "../node_modules/react-native/package.json", + :package_json_file => "#{app_path}/ios/../node_modules/react-native/package.json", :script_phases => "echo TestScript" }]) assert_equal(codegen_utils_mock.generate_react_codegen_spec_params, [{ @@ -380,9 +388,10 @@ def testCleanUpCodegenFolder_whenCleanupDone_doNothing # Arrange CodegenUtils.set_cleanup_done(true) codegen_dir = "build/generated/ios" + ios_folder = '.' # Act - CodegenUtils.clean_up_build_folder(@base_path, codegen_dir) + CodegenUtils.clean_up_build_folder(@base_path, ios_folder, codegen_dir) # Assert assert_equal(FileUtils::FileUtilsStorage.rmrf_invocation_count, 0) @@ -394,9 +403,10 @@ def testCleanUpCodegenFolder_whenFolderDoesNotExists_markAsCleanupDone # Arrange CodegenUtils.set_cleanup_done(false) codegen_dir = "build/generated/ios" + ios_folder = '.' # Act - CodegenUtils.clean_up_build_folder(@base_path, codegen_dir) + CodegenUtils.clean_up_build_folder(@base_path, ios_folder, codegen_dir) # Assert assert_equal(FileUtils::FileUtilsStorage.rmrf_invocation_count, 0) @@ -409,7 +419,8 @@ def testCleanUpCodegenFolder_whenFolderExists_deleteItAndSetCleanupDone # Arrange CodegenUtils.set_cleanup_done(false) codegen_dir = "build/generated/ios" - codegen_path = "#{@base_path}/#{codegen_dir}" + ios_folder = '.' + codegen_path = "#{@base_path}/./#{codegen_dir}" globs = [ "/MyModuleSpecs/MyModule.h", "#{codegen_path}/MyModuleSpecs/MyModule.mm", @@ -420,15 +431,65 @@ def testCleanUpCodegenFolder_whenFolderExists_deleteItAndSetCleanupDone Dir.mocked_existing_globs(globs, "#{codegen_path}/*") # Act - CodegenUtils.clean_up_build_folder(@base_path, codegen_dir) + CodegenUtils.clean_up_build_folder(@base_path, ios_folder, codegen_dir) # Assert - assert_equal(Dir.exist_invocation_params, [codegen_path]) - assert_equal(Dir.glob_invocation, ["#{codegen_path}/*"]) + assert_equal(Dir.exist_invocation_params, [codegen_path, codegen_path]) + assert_equal(Dir.glob_invocation, ["#{codegen_path}/*", "#{codegen_path}/*"]) assert_equal(FileUtils::FileUtilsStorage.rmrf_invocation_count, 1) assert_equal(FileUtils::FileUtilsStorage.rmrf_paths, [globs]) assert_equal(CodegenUtils.cleanup_done(), true) + end + + # ===================================== # + # Test - Assert Codegen Folder Is Empty # + # ===================================== # + + def test_assertCodegenFolderIsEmpty_whenItDoesNotExists_doesNotAbort + # Arrange + codegen_dir = "build/generated/ios" + codegen_path = "#{@base_path}/./#{codegen_dir}" + ios_folder = '.' + + # Act + CodegenUtils.assert_codegen_folder_is_empty(@base_path, ios_folder, codegen_dir) + + # Assert + assert_equal(Pod::UI.collected_warns, []) + end + + def test_assertCodegenFolderIsEmpty_whenItExistsAndIsEmpty_doesNotAbort + # Arrange + codegen_dir = "build/generated/ios" + codegen_path = "#{@base_path}/./#{codegen_dir}" + ios_folder = '.' + Dir.mocked_existing_dirs(codegen_path) + Dir.mocked_existing_globs([], "#{codegen_path}/*") + # Act + CodegenUtils.assert_codegen_folder_is_empty(@base_path, ios_folder, codegen_dir) + + # Assert + assert_equal(Pod::UI.collected_warns, []) + end + + def test_assertCodegenFolderIsEmpty_whenItIsNotEmpty_itAborts + # Arrange + codegen_dir = "build/generated/ios" + codegen_path = "#{@base_path}/./#{codegen_dir}" + ios_folder = '.' + Dir.mocked_existing_dirs(codegen_path) + Dir.mocked_existing_globs(["#{codegen_path}/MyModuleSpecs/MyModule.mm",], "#{codegen_path}/*") + + # Act + assert_raises() { + CodegenUtils.assert_codegen_folder_is_empty(@base_path, ios_folder, codegen_dir) + } + + # Assert + assert_equal(Pod::UI.collected_warns, [ + "Unable to remove the content of ~/app/ios/./build/generated/ios folder. Please run rm -rf ~/app/ios/./build/generated/ios and try again." + ]) end private @@ -445,7 +506,7 @@ def get_podspec_no_fabric_no_script 'source' => { :git => '' }, 'header_mappings_dir' => './', 'platforms' => { - 'ios' => '11.0', + 'ios' => min_ios_version_supported, }, 'source_files' => "**/*.{h,mm,cpp}", 'pod_target_xcconfig' => { "HEADER_SEARCH_PATHS" => diff --git a/scripts/cocoapods/__tests__/jsengine-test.rb b/scripts/cocoapods/__tests__/jsengine-test.rb index 303e99949dc9..8ea0b4cfd816 100644 --- a/scripts/cocoapods/__tests__/jsengine-test.rb +++ b/scripts/cocoapods/__tests__/jsengine-test.rb @@ -14,8 +14,10 @@ class JSEngineTests < Test::Unit::TestCase :react_native_path def setup + File.enable_testing_mode! @react_native_path = "../.." podSpy_cleanUp() + end def teardown @@ -25,6 +27,8 @@ def teardown Pod::UI.reset() podSpy_cleanUp() ENV['USE_HERMES'] = '1' + ENV['REACT_NATIVE_CI'] = nil + File.reset() end # =============== # @@ -40,7 +44,7 @@ def test_setupJsc_installsPods # Assert assert_equal($podInvocationCount, 2) assert_equal($podInvocation["React-jsi"][:path], "../../ReactCommon/jsi") - assert_equal($podInvocation["React-jsc"][:path], "../../ReactCommon/jsi") + assert_equal($podInvocation["React-jsc"][:path], "../../ReactCommon/jsc") end def test_setupJsc_installsPods_installsFabricSubspecWhenFabricEnabled @@ -53,8 +57,8 @@ def test_setupJsc_installsPods_installsFabricSubspecWhenFabricEnabled # Assert assert_equal($podInvocationCount, 3) assert_equal($podInvocation["React-jsi"][:path], "../../ReactCommon/jsi") - assert_equal($podInvocation["React-jsc"][:path], "../../ReactCommon/jsi") - assert_equal($podInvocation["React-jsc/Fabric"][:path], "../../ReactCommon/jsi") + assert_equal($podInvocation["React-jsc"][:path], "../../ReactCommon/jsc") + assert_equal($podInvocation["React-jsc/Fabric"][:path], "../../ReactCommon/jsc") end # ================== # @@ -103,7 +107,7 @@ def test_setupHermes_whenHermesScriptSucceeds_installsPods assert_equal($podInvocation["React-jsi"][:path], "../../ReactCommon/jsi") assert_equal($podInvocation["React-hermes"][:path], "../../ReactCommon/hermes") assert_equal($podInvocation["libevent"][:version], "~> 2.1.12") - assert_equal($podInvocation["hermes-engine"][:podspec], "../../sdks/hermes/hermes-engine.podspec") + assert_equal($podInvocation["hermes-engine"][:podspec], "../../sdks/hermes-engine/hermes-engine.podspec") end def test_setupHermes_installsPods_installsFabricSubspecWhenFabricEnabled @@ -116,7 +120,7 @@ def test_setupHermes_installsPods_installsFabricSubspecWhenFabricEnabled # Assert assert_equal($podInvocationCount, 4) assert_equal($podInvocation["React-jsi"][:path], "../../ReactCommon/jsi") - assert_equal($podInvocation["hermes-engine"][:podspec], "../../sdks/hermes/hermes-engine.podspec") + assert_equal($podInvocation["hermes-engine"][:podspec], "../../sdks/hermes-engine/hermes-engine.podspec") assert_equal($podInvocation["React-hermes"][:path], "../../ReactCommon/hermes") assert_equal($podInvocation["libevent"][:version], "~> 2.1.12") end @@ -125,16 +129,26 @@ def test_setupHermes_installsPods_installsFabricSubspecWhenFabricEnabled # TEST - isBuildingHermesFromSource # # ================================= # def test_isBuildingHermesFromSource_whenTarballIsNilAndVersionIsNotNightly_returnTrue - assert_true(is_building_hermes_from_source("1000.0.0")) + assert_true(is_building_hermes_from_source("1000.0.0", '../..')) + end + + def test_isBuildingHermesFromSource_whenTarballIsNilAndInReleaseBranch_returnTrue + ENV['REACT_NATIVE_CI'] = 'true' + File.mocked_existing_files(['../../sdks/.hermesversion']) + assert_true(is_building_hermes_from_source("0.999.0", '../..')) end def test_isBuildingHermesFromSource_whenTarballIsNotNil_returnFalse ENV['HERMES_ENGINE_TARBALL_PATH'] = "~/Downloads/hermes-ios-debug.tar.gz" - assert_false(is_building_hermes_from_source("1000.0.0")) + assert_false(is_building_hermes_from_source("1000.0.0", '../..')) end def test_isBuildingHermesFromSource_whenIsNigthly_returnsFalse - assert_false(is_building_hermes_from_source("0.0.0-")) + assert_false(is_building_hermes_from_source("0.0.0-", '../..')) + end + + def test_isBuildingHermesFromSource_whenIsStbleRelease_returnsFalse + assert_false(is_building_hermes_from_source("0.71.0", '../..')) end end diff --git a/scripts/cocoapods/__tests__/new_architecture-test.rb b/scripts/cocoapods/__tests__/new_architecture-test.rb index 98ceecdc37a3..35394fd1ae56 100644 --- a/scripts/cocoapods/__tests__/new_architecture-test.rb +++ b/scripts/cocoapods/__tests__/new_architecture-test.rb @@ -125,6 +125,7 @@ def test_installModulesDependencies_whenNewArchEnabledAndNewArchAndNoSearchPaths assert_equal(spec.compiler_flags, NewArchitectureHelper.folly_compiler_flags) assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "\"$(PODS_ROOT)/boost\"") assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++17") + assert_equal(spec.pod_target_xcconfig["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1") assert_equal( spec.dependencies, [ diff --git a/scripts/cocoapods/__tests__/test_utils/DirMock.rb b/scripts/cocoapods/__tests__/test_utils/DirMock.rb index 9c7a91328a76..c8c229b05c3b 100644 --- a/scripts/cocoapods/__tests__/test_utils/DirMock.rb +++ b/scripts/cocoapods/__tests__/test_utils/DirMock.rb @@ -49,7 +49,11 @@ def self.glob_invocation def self.glob(path) @@glob_invocation.push(path) - return @@mocked_existing_globs[path] + return @@mocked_existing_globs[path] != nil ? @@mocked_existing_globs[path] : [] + end + + def self.remove_mocked_paths(path) + @@mocked_existing_globs = @@mocked_existing_globs.select { |k, v| v != path } end def self.set_pwd(pwd) diff --git a/scripts/cocoapods/__tests__/test_utils/FileUtilsMock.rb b/scripts/cocoapods/__tests__/test_utils/FileUtilsMock.rb index 4675fcd60cf8..cb2155a5e366 100644 --- a/scripts/cocoapods/__tests__/test_utils/FileUtilsMock.rb +++ b/scripts/cocoapods/__tests__/test_utils/FileUtilsMock.rb @@ -3,9 +3,9 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -module FileUtils - +require_relative './DirMock.rb' +module FileUtils class FileUtilsStorage @@RMRF_INVOCATION_COUNT = 0 @@RMRF_PATHS = [] @@ -35,5 +35,6 @@ def self.reset def self.rm_rf(path) FileUtilsStorage.push_rmrf_path(path) FileUtilsStorage.increase_rmrfi_invocation_count + Dir.remove_mocked_paths(path) end end diff --git a/scripts/cocoapods/__tests__/test_utils/TargetDefinitionMock.rb b/scripts/cocoapods/__tests__/test_utils/TargetDefinitionMock.rb new file mode 100644 index 000000000000..0a4ddfab6d82 --- /dev/null +++ b/scripts/cocoapods/__tests__/test_utils/TargetDefinitionMock.rb @@ -0,0 +1,12 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +class TargetDefinitionMock + attr_reader :build_type + + def initialize(build_type) + @build_type = build_type + end +end diff --git a/scripts/cocoapods/__tests__/test_utils/XcodebuildMock.rb b/scripts/cocoapods/__tests__/test_utils/XcodebuildMock.rb new file mode 100644 index 000000000000..4cbef2e811da --- /dev/null +++ b/scripts/cocoapods/__tests__/test_utils/XcodebuildMock.rb @@ -0,0 +1,26 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +class XcodebuildMock < Xcodebuild + @@version = "" + @@version_invocation_count = 0 + + def self.set_version=(v) + @@version = v + end + + def self.version + @@version_invocation_count += 1 + @@version + end + + def self.version_invocation_count + @@version_invocation_count + end + + def self.reset() + @@version_invocation_count = 0 + end +end diff --git a/scripts/cocoapods/__tests__/utils-test.rb b/scripts/cocoapods/__tests__/utils-test.rb index 429055cf4ca2..7e2ede25ad39 100644 --- a/scripts/cocoapods/__tests__/utils-test.rb +++ b/scripts/cocoapods/__tests__/utils-test.rb @@ -13,6 +13,8 @@ require_relative "./test_utils/FileMock.rb" require_relative "./test_utils/systemUtils.rb" require_relative "./test_utils/PathnameMock.rb" +require_relative "./test_utils/TargetDefinitionMock.rb" +require_relative "./test_utils/XcodebuildMock.rb" class UtilsTests < Test::Unit::TestCase def setup @@ -28,8 +30,10 @@ def teardown Pod::Config.reset() SysctlChecker.reset() Environment.reset() + XcodebuildMock.reset() ENV['RCT_NEW_ARCH_ENABLED'] = '0' ENV['USE_HERMES'] = '1' + ENV['USE_FRAMEWORKS'] = nil system_reset_commands end @@ -176,11 +180,33 @@ def test_hasPod_whenInstallerHasPod_returnTrue # ============================ # # Test - Exclude Architectures # # ============================ # - def test_excludeArchitectures_whenHermesEngineIsNotIncluded_excludeNothing + def test_excludeArchitectures_whenHermesEngineIsNotIncluded_withNoValue_leaveUnset + # Arrange + user_project_mock = prepare_empty_user_project_mock() + pods_projects_mock = PodsProjectMock.new() + installer = InstallerMock.new(PodsProjectMock.new(), [ + AggregatedProjectMock.new(user_project_mock) + ]) + + # Act + ReactNativePodsUtils.exclude_i386_architecture_while_using_hermes(installer) + + # Assert + user_project_mock.build_configurations.each do |config| + assert_equal(config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"], nil) + end + assert_equal(user_project_mock.save_invocation_count, 0) + assert_equal(pods_projects_mock.save_invocation_count, 0) + end + + def test_excludeArchitectures_whenHermesEngineIsNotIncluded_withExistingValue_preserveExistingValue # Arrange user_project_mock = prepare_empty_user_project_mock() + user_project_mock.build_configurations.each do |config| + config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64" + end pods_projects_mock = PodsProjectMock.new() - installer = InstallerMock.new(PodsProjectMock.new(), [ + installer = InstallerMock.new(pods_projects_mock, [ AggregatedProjectMock.new(user_project_mock) ]) @@ -189,13 +215,14 @@ def test_excludeArchitectures_whenHermesEngineIsNotIncluded_excludeNothing # Assert user_project_mock.build_configurations.each do |config| - assert_equal(config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"], "") + assert_equal(config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"], "arm64") end - assert_equal(user_project_mock.save_invocation_count, 1) + + assert_equal(user_project_mock.save_invocation_count, 0) assert_equal(pods_projects_mock.save_invocation_count, 0) end - def test_excludeArchitectures_whenHermesEngineIsIncluded_excludeI386 + def test_excludeArchitectures_whenHermesEngineIsIncluded_withNoValue_onlyExcludeI386 # Arrange user_project_mock = prepare_empty_user_project_mock() pods_projects_mock = PodsProjectMock.new([], {"hermes-engine" => {}}) @@ -215,6 +242,29 @@ def test_excludeArchitectures_whenHermesEngineIsIncluded_excludeI386 assert_equal(pods_projects_mock.save_invocation_count, 1) end + def test_excludeArchitectures_whenHermesEngineIsIncluded_withExistingValue_appendI386 + # Arrange + user_project_mock = prepare_empty_user_project_mock() + user_project_mock.build_configurations.each do |config| + config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64" + end + pods_projects_mock = PodsProjectMock.new([], {"hermes-engine" => {}}) + installer = InstallerMock.new(pods_projects_mock, [ + AggregatedProjectMock.new(user_project_mock) + ]) + + # Act + ReactNativePodsUtils.exclude_i386_architecture_while_using_hermes(installer) + + # Assert + user_project_mock.build_configurations.each do |config| + assert_equal(config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"], "arm64 i386") + end + + assert_equal(user_project_mock.save_invocation_count, 1) + assert_equal(pods_projects_mock.save_invocation_count, 1) + end + # ================= # # Test - Fix Config # # ================= # @@ -433,6 +483,153 @@ def test_applyMacCatalystPatches_correctlyAppliesNecessaryPatches assert_equal(user_project_mock.save_invocation_count, 1) end + # ================================= # + # Test - Apply Xcode 15 Patch # + # ================================= # + def test_applyXcode15Patch_whenXcodebuild14_correctlyAppliesNecessaryPatch + # Arrange + XcodebuildMock.set_version = "Xcode 14.3" + first_target = prepare_target("FirstTarget") + second_target = prepare_target("SecondTarget") + third_target = TargetMock.new("ThirdTarget", [ + BuildConfigurationMock.new("Debug", { + "GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" ' + }), + BuildConfigurationMock.new("Release", { + "GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" ' + }), + ], nil) + + user_project_mock = UserProjectMock.new("a/path", [ + prepare_config("Debug"), + prepare_config("Release"), + ], + :native_targets => [ + first_target, + second_target + ] + ) + pods_projects_mock = PodsProjectMock.new([], {"hermes-engine" => {}}, :native_targets => [ + third_target + ]) + installer = InstallerMock.new(pods_projects_mock, [ + AggregatedProjectMock.new(user_project_mock) + ]) + + # Act + user_project_mock.build_configurations.each do |config| + assert_nil(config.build_settings["OTHER_LDFLAGS"]) + end + + ReactNativePodsUtils.apply_xcode_15_patch(installer, :xcodebuild_manager => XcodebuildMock) + + # Assert + user_project_mock.build_configurations.each do |config| + assert_equal("$(inherited) _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION", config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"]) + assert_equal("$(inherited) ", config.build_settings["OTHER_LDFLAGS"]) + end + + # User project and Pods project + assert_equal(2, XcodebuildMock.version_invocation_count) + end + + def test_applyXcode15Patch_whenXcodebuild15_correctlyAppliesNecessaryPatch + # Arrange + XcodebuildMock.set_version = "Xcode 15.0" + first_target = prepare_target("FirstTarget") + second_target = prepare_target("SecondTarget") + third_target = TargetMock.new("ThirdTarget", [ + BuildConfigurationMock.new("Debug", { + "GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" ' + }), + BuildConfigurationMock.new("Release", { + "GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" ' + }), + ], nil) + + user_project_mock = UserProjectMock.new("/a/path", [ + prepare_config("Debug"), + prepare_config("Release"), + ], + :native_targets => [ + first_target, + second_target + ] + ) + pods_projects_mock = PodsProjectMock.new([], {"hermes-engine" => {}}, :native_targets => [ + third_target + ]) + installer = InstallerMock.new(pods_projects_mock, [ + AggregatedProjectMock.new(user_project_mock) + ]) + + # Act + user_project_mock.build_configurations.each do |config| + assert_nil(config.build_settings["OTHER_LDFLAGS"]) + end + + ReactNativePodsUtils.apply_xcode_15_patch(installer, :xcodebuild_manager => XcodebuildMock) + + # Assert + user_project_mock.build_configurations.each do |config| + assert_equal("$(inherited) _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION", config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"]) + assert_equal("$(inherited) -Wl -ld_classic", config.build_settings["OTHER_LDFLAGS"]) + end + + # User project and Pods project + assert_equal(2, XcodebuildMock.version_invocation_count) + end + + def test_applyXcode15Patch_whenXcodebuild14ButProjectHasSettings_correctlyRemovesNecessaryPatch + # Arrange + XcodebuildMock.set_version = "Xcode 14.3" + first_target = prepare_target("FirstTarget") + second_target = prepare_target("SecondTarget") + third_target = TargetMock.new("ThirdTarget", [ + BuildConfigurationMock.new("Debug", { + "GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" ' + }), + BuildConfigurationMock.new("Release", { + "GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) "SomeFlag=1" ' + }), + ], nil) + + debug_config = prepare_config("Debug", {"OTHER_LDFLAGS" => "$(inherited) -Wl -ld_classic "}) + release_config = prepare_config("Release", {"OTHER_LDFLAGS" => "$(inherited) -Wl -ld_classic "}) + + user_project_mock = UserProjectMock.new("/a/path", [ + debug_config, + release_config, + ], + :native_targets => [ + first_target, + second_target + ] + ) + pods_projects_mock = PodsProjectMock.new([debug_config.clone, release_config.clone], {"hermes-engine" => {}}, :native_targets => [ + third_target + ]) + installer = InstallerMock.new(pods_projects_mock, [ + AggregatedProjectMock.new(user_project_mock) + ]) + + # Act + user_project_mock.build_configurations.each do |config| + assert_equal("$(inherited) -Wl -ld_classic ", config.build_settings["OTHER_LDFLAGS"]) + end + + ReactNativePodsUtils.apply_xcode_15_patch(installer, :xcodebuild_manager => XcodebuildMock) + + # Assert + user_project_mock.build_configurations.each do |config| + assert_equal("$(inherited) _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION", config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"]) + assert_equal("$(inherited)", config.build_settings["OTHER_LDFLAGS"]) + end + + # User project and Pods project + assert_equal(2, XcodebuildMock.version_invocation_count) + end + # ==================================== # # Test - Set Node_Modules User Setting # # ==================================== # @@ -481,6 +678,57 @@ def test_createXcodeEnvIfMissing_whenItIsNotPresent_createsIt assert_equal(File.exist_invocation_params, ["/.xcode.env"]) assert_equal($collected_commands, ["echo 'export NODE_BINARY=$(command -v node)' > /.xcode.env"]) end + + # ============================ # + # Test - Detect Use Frameworks # + # ============================ # + def test_detectUseFrameworks_whenEnvAlreadySet_DoesNothing + # Arrange + ENV['USE_FRAMEWORKS'] = 'static' + target_definition = TargetDefinitionMock.new('something') + + # Act + ReactNativePodsUtils.detect_use_frameworks(target_definition) + + # Assert + assert_equal(Pod::UI.collected_messages, []) + end + + def test_detectUseFrameworks_whenEnvNotSetAndNotUsed_setEnvVarToNil + # Arrange + target_definition = TargetDefinitionMock.new('static library') + + # Act + ReactNativePodsUtils.detect_use_frameworks(target_definition) + + # Assert + assert_equal(Pod::UI.collected_messages, ["Framework build type is static library"]) + assert_nil(ENV['USE_FRAMEWORKS']) + end + + def test_detectUseFrameworks_whenEnvNotSetAndStaticFrameworks_setEnvVarToStatic + # Arrange + target_definition = TargetDefinitionMock.new('static framework') + + # Act + ReactNativePodsUtils.detect_use_frameworks(target_definition) + + # Assert + assert_equal(Pod::UI.collected_messages, ["Framework build type is static framework"]) + assert_equal(ENV['USE_FRAMEWORKS'], 'static') + end + + def test_detectUseFrameworks_whenEnvNotSetAndDynamicFrameworks_setEnvVarToDynamic + # Arrange + target_definition = TargetDefinitionMock.new('dynamic framework') + + # Act + ReactNativePodsUtils.detect_use_frameworks(target_definition) + + # Assert + assert_equal(Pod::UI.collected_messages, ["Framework build type is dynamic framework"]) + assert_equal(ENV['USE_FRAMEWORKS'], 'dynamic') + end end def prepare_empty_user_project_mock @@ -490,12 +738,14 @@ def prepare_empty_user_project_mock ]) end -def prepare_config(config_name) - return BuildConfigurationMock.new(config_name, {"LIBRARY_SEARCH_PATHS" => [ +def prepare_config(config_name, extra_config = {}) + config = {"LIBRARY_SEARCH_PATHS" => [ "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", "\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"", "another/path", - ]}) + ]}.merge(extra_config) + + return BuildConfigurationMock.new(config_name, config) end def prepare_target(name, product_type = nil) diff --git a/scripts/cocoapods/codegen_utils.rb b/scripts/cocoapods/codegen_utils.rb index 14fc35c602c4..a624b5139801 100644 --- a/scripts/cocoapods/codegen_utils.rb +++ b/scripts/cocoapods/codegen_utils.rb @@ -85,7 +85,7 @@ def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fa 'source' => { :git => '' }, 'header_mappings_dir' => './', 'platforms' => { - 'ios' => '11.0', + 'ios' => min_ios_version_supported, }, 'source_files' => "**/*.{h,mm,cpp}", 'pod_target_xcconfig' => { "HEADER_SEARCH_PATHS" => @@ -274,7 +274,7 @@ def use_react_native_codegen_discovery!( :config_key => config_key ) react_codegen_spec = codegen_utils.get_react_codegen_spec( - File.join(react_native_path, "package.json"), + File.join(relative_installation_root, react_native_path, "package.json"), :folly_version => folly_version, :fabric_enabled => fabric_enabled, :hermes_enabled => hermes_enabled, @@ -306,14 +306,25 @@ def self.cleanup_done return @@CLEANUP_DONE end - def self.clean_up_build_folder(app_path, codegen_dir) + def self.clean_up_build_folder(app_path, ios_folder, codegen_dir) return if CodegenUtils.cleanup_done() CodegenUtils.set_cleanup_done(true) - codegen_path = File.join(app_path, codegen_dir) + codegen_path = File.join(app_path, ios_folder, codegen_dir) return if !Dir.exist?(codegen_path) FileUtils.rm_rf(Dir.glob("#{codegen_path}/*")) - CodegenUtils.set_cleanup_done(true) + CodegenUtils.assert_codegen_folder_is_empty(app_path, ios_folder, codegen_dir) + end + + # Need to split this function from the previous one to be able to test it properly. + def self.assert_codegen_folder_is_empty(app_path, ios_folder, codegen_dir) + # double check that the files have actually been deleted. + # Emit an error message if not. + codegen_path = File.join(app_path, ios_folder, codegen_dir) + if Dir.exist?(codegen_path) && Dir.glob("#{codegen_path}/*").length() != 0 + Pod::UI.warn "Unable to remove the content of #{codegen_path} folder. Please run rm -rf #{codegen_path} and try again." + abort + end end end diff --git a/scripts/cocoapods/helpers.rb b/scripts/cocoapods/helpers.rb index 03e3a5cbeac6..6d2a58d5973f 100644 --- a/scripts/cocoapods/helpers.rb +++ b/scripts/cocoapods/helpers.rb @@ -11,6 +11,14 @@ def call_sysctl_arm64 end end +# Helper class that is used to easily send commands to Xcodebuild +# And that can be subclassed for testing purposes. +class Xcodebuild + def self.version + `xcodebuild -version` + end +end + # Helper object to wrap system properties like RUBY_PLATFORM # This makes it easier to mock the behaviour in tests class Environment @@ -26,3 +34,11 @@ def self.find_codegen_file(path) return `find #{path} -type f \\( #{js_files} -or #{ts_files} \\)`.split("\n").sort() end end + +module Helpers + class Constants + def self.min_ios_version_supported + return '12.4' + end + end +end diff --git a/scripts/cocoapods/jsengine.rb b/scripts/cocoapods/jsengine.rb index 3b92b8687112..6551ef3e50fd 100644 --- a/scripts/cocoapods/jsengine.rb +++ b/scripts/cocoapods/jsengine.rb @@ -11,9 +11,9 @@ # @parameter fabric_enabled: whether Fabirc is enabled def setup_jsc!(react_native_path: "../node_modules/react-native", fabric_enabled: false) pod 'React-jsi', :path => "#{react_native_path}/ReactCommon/jsi" - pod 'React-jsc', :path => "#{react_native_path}/ReactCommon/jsi" + pod 'React-jsc', :path => "#{react_native_path}/ReactCommon/jsc" if fabric_enabled - pod 'React-jsc/Fabric', :path => "#{react_native_path}/ReactCommon/jsi" + pod 'React-jsc/Fabric', :path => "#{react_native_path}/ReactCommon/jsc" end end @@ -30,14 +30,14 @@ def setup_hermes!(react_native_path: "../node_modules/react-native", fabric_enab abort unless prep_status == 0 pod 'React-jsi', :path => "#{react_native_path}/ReactCommon/jsi" - pod 'hermes-engine', :podspec => "#{react_native_path}/sdks/hermes/hermes-engine.podspec" + pod 'hermes-engine', :podspec => "#{react_native_path}/sdks/hermes-engine/hermes-engine.podspec" pod 'React-hermes', :path => "#{react_native_path}/ReactCommon/hermes" pod 'libevent', '~> 2.1.12' end def add_copy_hermes_framework_script_phase(installer, react_native_path) utils_dir = File.join(react_native_path, "sdks", "hermes-engine", "utils") - phase_name = "[RN]Copy Hermes framework" + phase_name = "[RN] Copy Hermes Framework" project = installer.generated_aggregate_targets.first.user_project target = project.targets.first if target.shell_script_build_phases.none? { |phase| phase.name == phase_name } @@ -49,9 +49,14 @@ def add_copy_hermes_framework_script_phase(installer, react_native_path) def remove_copy_hermes_framework_script_phase(installer, react_native_path) utils_dir = File.join(react_native_path, "sdks", "hermes-engine", "utils") - phase_name = "[RN]Copy Hermes framework" + phase_name = "[RN] Copy Hermes Framework" project = installer.generated_aggregate_targets.first.user_project - project.targets.first.shell_script_build_phases.delete_if { |phase| phase.name == phase_name } + target = project.native_targets.first + target.shell_script_build_phases.each do |phase| + if phase.name == phase_name + target.build_phases.delete(phase) + end + end project.save() end @@ -59,14 +64,18 @@ def remove_hermesc_build_dir(react_native_path) %x(rm -rf #{react_native_path}/sdks/hermes-engine/build_host_hermesc) end -def is_building_hermes_from_source(react_native_version) - is_nightly = react_native_version.start_with?('0.0.0-') - has_tarball = ENV['HERMES_ENGINE_TARBALL_PATH'] != nil - - # this is the same logic in the hermes-engine.podspec - if has_tarball || is_nightly +def is_building_hermes_from_source(react_native_version, react_native_path) + if ENV['HERMES_ENGINE_TARBALL_PATH'] != nil return false end - return true + isInMain = react_native_version.include?('1000.0.0') + + hermestag_file = File.join(react_native_path, "sdks", ".hermesversion") + isInCI = ENV['REACT_NATIVE_CI'] === 'true' + + isReleaseBranch = File.exist?(hermestag_file) && isInCI + + + return isInMain || isReleaseBranch end diff --git a/scripts/cocoapods/new_architecture.rb b/scripts/cocoapods/new_architecture.rb index 0ce4b91f8b8f..90141cd004c9 100644 --- a/scripts/cocoapods/new_architecture.rb +++ b/scripts/cocoapods/new_architecture.rb @@ -76,12 +76,13 @@ def self.install_modules_dependencies(spec, new_arch_enabled, folly_version) spec.compiler_flags = compiler_flags.empty? ? @@folly_compiler_flags : "#{compiler_flags} #{@@folly_compiler_flags}" current_config["HEADER_SEARCH_PATHS"] = current_headers.empty? ? boost_search_path : "#{current_headers} #{boost_search_path}" current_config["CLANG_CXX_LANGUAGE_STANDARD"] = @@cplusplus_version - spec.pod_target_xcconfig = current_config + spec.dependency "React-Core" spec.dependency "RCT-Folly", '2021.07.22.00' if new_arch_enabled + current_config["OTHER_CPLUSPLUSFLAGS"] = @@new_arch_cpp_flags spec.dependency "React-RCTFabric" # This is for Fabric Component spec.dependency "React-Codegen" @@ -90,6 +91,8 @@ def self.install_modules_dependencies(spec, new_arch_enabled, folly_version) spec.dependency "ReactCommon/turbomodule/bridging" spec.dependency "ReactCommon/turbomodule/core" end + + spec.pod_target_xcconfig = current_config end def self.folly_compiler_flags diff --git a/scripts/cocoapods/utils.rb b/scripts/cocoapods/utils.rb index dcf864220649..25968c29d6d4 100644 --- a/scripts/cocoapods/utils.rb +++ b/scripts/cocoapods/utils.rb @@ -53,22 +53,35 @@ def self.turn_off_resource_bundle_react_core(installer) end end - def self.exclude_i386_architecture_while_using_hermes(installer) - projects = installer.aggregate_targets + def self.extract_projects(installer) + return installer.aggregate_targets .map{ |t| t.user_project } .uniq{ |p| p.path } .push(installer.pods_project) + end + def self.exclude_i386_architecture_while_using_hermes(installer) + is_using_hermes = self.has_pod(installer, 'hermes-engine') - # Hermes does not support `i386` architecture - excluded_archs_default = ReactNativePodsUtils.has_pod(installer, 'hermes-engine') ? "i386" : "" + if is_using_hermes + key = "EXCLUDED_ARCHS[sdk=iphonesimulator*]" - projects.each do |project| - project.build_configurations.each do |config| - config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = excluded_archs_default - end + projects = self.extract_projects(installer) - project.save() + projects.each do |project| + project.build_configurations.each do |config| + current_setting = config.build_settings[key] || "" + + excluded_archs_includes_I386 = current_setting.include?("i386") + + if !excluded_archs_includes_I386 + # Hermes does not support `i386` architecture + config.build_settings[key] = "#{current_setting} i386".strip + end + end + + project.save() + end end end @@ -131,6 +144,32 @@ def self.apply_mac_catalyst_patches(installer) end end + def self.apply_xcode_15_patch(installer, xcodebuild_manager: Xcodebuild) + projects = self.extract_projects(installer) + + gcc_preprocessor_definition_key = 'GCC_PREPROCESSOR_DEFINITIONS' + other_ld_flags_key = 'OTHER_LDFLAGS' + libcpp_cxx17_fix = '_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION' + xcode15_compatibility_flags = '-Wl -ld_classic ' + + projects.each do |project| + project.build_configurations.each do |config| + # fix for unary_function and binary_function + self.safe_init(config, gcc_preprocessor_definition_key) + self.add_value_to_setting_if_missing(config, gcc_preprocessor_definition_key, libcpp_cxx17_fix) + + # fix for weak linking + self.safe_init(config, other_ld_flags_key) + if self.is_using_xcode15_0(:xcodebuild_manager => xcodebuild_manager) + self.add_value_to_setting_if_missing(config, other_ld_flags_key, xcode15_compatibility_flags) + else + self.remove_value_from_setting_if_present(config, other_ld_flags_key, xcode15_compatibility_flags) + end + end + project.save() + end + end + private def self.fix_library_search_path(config) @@ -163,4 +202,118 @@ def self.create_xcode_env_if_missing system("echo 'export NODE_BINARY=$(command -v node)' > #{file_path}") end + + # It examines the target_definition property and sets the appropriate value for + # ENV['USE_FRAMEWORKS'] variable. + # + # - parameter target_definition: The current target definition + def self.detect_use_frameworks(target_definition) + if ENV['USE_FRAMEWORKS'] != nil + return + end + + framework_build_type = target_definition.build_type.to_s + + Pod::UI.puts("Framework build type is #{framework_build_type}") + + if framework_build_type === "static framework" + ENV['USE_FRAMEWORKS'] = 'static' + elsif framework_build_type === "dynamic framework" + ENV['USE_FRAMEWORKS'] = 'dynamic' + else + ENV['USE_FRAMEWORKS'] = nil + end + end + + def self.updateIphoneOSDeploymentTarget(installer) + pod_to_update = Set.new([ + "boost", + "CocoaAsyncSocket", + "Flipper", + "Flipper-DoubleConversion", + "Flipper-Fmt", + "Flipper-Boost-iOSX", + "Flipper-Folly", + "Flipper-Glog", + "Flipper-PeerTalk", + "FlipperKit", + "fmt", + "libevent", + "OpenSSL-Universal", + "RCT-Folly", + "SocketRocket", + "YogaKit" + ]) + + installer.target_installation_results.pod_target_installation_results + .each do |pod_name, target_installation_result| + unless pod_to_update.include?(pod_name) + next + end + target_installation_result.native_target.build_configurations.each do |config| + config.build_settings["IPHONEOS_DEPLOYMENT_TARGET"] = Helpers::Constants.min_ios_version_supported + end + end + end + + # ========= # + # Utilities # + # ========= # + + def self.extract_projects(installer) + return installer.aggregate_targets + .map{ |t| t.user_project } + .uniq{ |p| p.path } + .push(installer.pods_project) + end + + def self.safe_init(config, setting_name) + old_config = config.build_settings[setting_name] + if old_config == nil + config.build_settings[setting_name] ||= '$(inherited) ' + end + end + + def self.add_value_to_setting_if_missing(config, setting_name, value) + old_config = config.build_settings[setting_name] + if old_config.is_a?(Array) + old_config = old_config.join(" ") + end + + trimmed_value = value.strip() + if !old_config.include?(trimmed_value) + config.build_settings[setting_name] = "#{old_config.strip()} #{trimmed_value}".strip() + end + end + + def self.remove_value_from_setting_if_present(config, setting_name, value) + old_config = config.build_settings[setting_name] + if old_config.is_a?(Array) + old_config = old_config.join(" ") + end + + trimmed_value = value.strip() + if old_config.include?(trimmed_value) + new_config = old_config.gsub(trimmed_value, "") + config.build_settings[setting_name] = new_config.strip() + end + end + + def self.is_using_xcode15_0(xcodebuild_manager: Xcodebuild) + xcodebuild_version = xcodebuild_manager.version + + # The output of xcodebuild -version is something like + # Xcode 15.0 + # or + # Xcode 14.3.1 + # We want to capture the version digits + regex = /(\d+)\.(\d+)(?:\.(\d+))?/ + if match_data = xcodebuild_version.match(regex) + major = match_data[1].to_i + minor = match_data[2].to_i + return major == 15 && minor == 0 + end + + return false + end end diff --git a/scripts/hermes/prepare-hermes-for-build.js b/scripts/hermes/prepare-hermes-for-build.js index 87792738e7c0..711de87d90b5 100644 --- a/scripts/hermes/prepare-hermes-for-build.js +++ b/scripts/hermes/prepare-hermes-for-build.js @@ -39,7 +39,7 @@ async function main(isInCI) { } } -const isInCI = process.env.CI === 'true'; +const isInCI = process.env.REACT_NATIVE_CI === 'true'; main(isInCI).then(() => { process.exit(0); diff --git a/scripts/monorepo/__tests__/bump-package-version-test.js b/scripts/monorepo/__tests__/bump-package-version-test.js new file mode 100644 index 000000000000..dd67ab2b6b5c --- /dev/null +++ b/scripts/monorepo/__tests__/bump-package-version-test.js @@ -0,0 +1,39 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const path = require('path'); +const {writeFileSync} = require('fs'); + +const bumpPackageVersion = require('../bump-all-updated-packages/bump-package-version'); + +jest.mock('fs', () => ({ + writeFileSync: jest.fn(), + readFileSync: jest.fn(() => '{}'), +})); + +jest.mock('../for-each-package', () => callback => {}); + +describe('bumpPackageVersionTest', () => { + it('updates patch version of the package', () => { + const mockedPackageLocation = '~/packages/assets'; + const mockedPackageManifest = { + name: '@react-native/test', + version: '1.2.3', + }; + + bumpPackageVersion(mockedPackageLocation, mockedPackageManifest); + + expect(writeFileSync).toHaveBeenCalledWith( + path.join(mockedPackageLocation, 'package.json'), + JSON.stringify({...mockedPackageManifest, version: '1.2.4'}, null, 2) + + '\n', + 'utf-8', + ); + }); +}); diff --git a/scripts/monorepo/__tests__/find-and-publish-all-bumped-packages-test.js b/scripts/monorepo/__tests__/find-and-publish-all-bumped-packages-test.js new file mode 100644 index 000000000000..7ef3f9ca0de7 --- /dev/null +++ b/scripts/monorepo/__tests__/find-and-publish-all-bumped-packages-test.js @@ -0,0 +1,41 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const {spawnSync} = require('child_process'); + +const {PUBLISH_PACKAGES_TAG} = require('../constants'); +const forEachPackage = require('../for-each-package'); +const findAndPublishAllBumpedPackages = require('../find-and-publish-all-bumped-packages'); + +jest.mock('child_process', () => ({spawnSync: jest.fn()})); +jest.mock('../for-each-package', () => jest.fn()); + +describe('findAndPublishAllBumpedPackages', () => { + it('throws an error if updated version is not 0.x.y', () => { + const mockedPackageNewVersion = '1.0.0'; + + forEachPackage.mockImplementationOnce(callback => { + callback('absolute/path/to/package', 'to/package', { + version: mockedPackageNewVersion, + }); + }); + + spawnSync.mockImplementationOnce(() => ({ + stdout: `- "version": "0.72.0"\n+ "version": "${mockedPackageNewVersion}"\n`, + })); + + spawnSync.mockImplementationOnce(() => ({ + stdout: `This is my commit message\n\n${PUBLISH_PACKAGES_TAG}`, + })); + + expect(() => findAndPublishAllBumpedPackages()).toThrow( + `Package version expected to be 0.x.y, but received ${mockedPackageNewVersion}`, + ); + }); +}); diff --git a/scripts/monorepo/__tests__/for-each-package-test.js b/scripts/monorepo/__tests__/for-each-package-test.js new file mode 100644 index 000000000000..34ba8ecdb1c8 --- /dev/null +++ b/scripts/monorepo/__tests__/for-each-package-test.js @@ -0,0 +1,51 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const path = require('path'); +const {readdirSync, readFileSync} = require('fs'); + +const forEachPackage = require('../for-each-package'); + +jest.mock('fs', () => ({ + readdirSync: jest.fn(), + readFileSync: jest.fn(), +})); + +describe('forEachPackage', () => { + it('executes callback call with parameters', () => { + const callback = jest.fn(); + const mockedPackageManifest = '{"name": "my-new-package"}'; + const mockedParsedPackageManifest = JSON.parse(mockedPackageManifest); + const mockedPackageName = 'my-new-package'; + + readdirSync.mockImplementationOnce(() => [ + {name: mockedPackageName, isDirectory: () => true}, + ]); + readFileSync.mockImplementationOnce(() => mockedPackageManifest); + + forEachPackage(callback); + + expect(callback).toHaveBeenCalledWith( + path.join(__dirname, '..', '..', '..', 'packages', mockedPackageName), + path.join('packages', mockedPackageName), + mockedParsedPackageManifest, + ); + }); + + it('filters react-native folder', () => { + const callback = jest.fn(); + readdirSync.mockImplementationOnce(() => [ + {name: 'react-native', isDirectory: () => true}, + ]); + + forEachPackage(callback); + + expect(callback).not.toHaveBeenCalled(); + }); +}); diff --git a/scripts/monorepo/align-package-versions.js b/scripts/monorepo/align-package-versions.js new file mode 100644 index 000000000000..e29272f324bb --- /dev/null +++ b/scripts/monorepo/align-package-versions.js @@ -0,0 +1,146 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const {spawnSync} = require('child_process'); +const {writeFileSync, readFileSync} = require('fs'); +const path = require('path'); + +const checkForGitChanges = require('./check-for-git-changes'); +const forEachPackage = require('./for-each-package'); + +const ROOT_LOCATION = path.join(__dirname, '..', '..'); +const TEMPLATE_LOCATION = path.join(ROOT_LOCATION, 'template'); +const REPO_CONFIG_LOCATION = path.join(ROOT_LOCATION, 'repo-config'); + +const readJSONFile = pathToFile => JSON.parse(readFileSync(pathToFile)); + +const checkIfShouldUpdateDependencyPackageVersion = ( + consumerPackageAbsolutePath, + updatedPackageName, + updatedPackageVersion, +) => { + const consumerPackageManifestPath = path.join( + consumerPackageAbsolutePath, + 'package.json', + ); + const consumerPackageManifest = readJSONFile(consumerPackageManifestPath); + + const dependencyVersion = + consumerPackageManifest.dependencies?.[updatedPackageName]; + + if (dependencyVersion && dependencyVersion !== '*') { + const updatedDependencyVersion = dependencyVersion.startsWith('^') + ? `^${updatedPackageVersion}` + : updatedPackageVersion; + + if (updatedDependencyVersion !== dependencyVersion) { + console.log( + `\uD83D\uDCA1 ${consumerPackageManifest.name} was updated: now using version ${updatedPackageVersion} of ${updatedPackageName}`, + ); + + const updatedPackageManifest = { + ...consumerPackageManifest, + dependencies: { + ...consumerPackageManifest.dependencies, + [updatedPackageName]: updatedDependencyVersion, + }, + }; + + writeFileSync( + consumerPackageManifestPath, + JSON.stringify(updatedPackageManifest, null, 2) + '\n', + 'utf-8', + ); + } + } + + const devDependencyVersion = + consumerPackageManifest.devDependencies?.[updatedPackageName]; + + if (devDependencyVersion && devDependencyVersion !== '*') { + const updatedDependencyVersion = devDependencyVersion.startsWith('^') + ? `^${updatedPackageVersion}` + : updatedPackageVersion; + + if (updatedDependencyVersion !== devDependencyVersion) { + console.log( + `\uD83D\uDCA1 ${consumerPackageManifest.name} was updated: now using version ${updatedPackageVersion} of ${updatedPackageName}`, + ); + + const updatedPackageManifest = { + ...consumerPackageManifest, + devDependencies: { + ...consumerPackageManifest.devDependencies, + [updatedPackageName]: updatedDependencyVersion, + }, + }; + + writeFileSync( + consumerPackageManifestPath, + JSON.stringify(updatedPackageManifest, null, 2) + '\n', + 'utf-8', + ); + } + } +}; + +const alignPackageVersions = () => { + if (checkForGitChanges()) { + console.log( + '\u274c Found uncommitted changes. Please commit or stash them before running this script', + ); + + process.exit(1); + } + + forEachPackage((packageAbsolutePath, _, packageManifest) => { + checkIfShouldUpdateDependencyPackageVersion( + ROOT_LOCATION, + packageManifest.name, + packageManifest.version, + ); + + checkIfShouldUpdateDependencyPackageVersion( + TEMPLATE_LOCATION, + packageManifest.name, + packageManifest.version, + ); + + checkIfShouldUpdateDependencyPackageVersion( + REPO_CONFIG_LOCATION, + packageManifest.name, + packageManifest.version, + ); + + forEachPackage(pathToPackage => + checkIfShouldUpdateDependencyPackageVersion( + pathToPackage, + packageManifest.name, + packageManifest.version, + ), + ); + }); + + if (!checkForGitChanges()) { + console.log( + '\u2705 There were no changes. Every consumer package uses the actual version of dependency package.', + ); + return; + } + + console.log('Running yarn to update lock file...'); + spawnSync('yarn', ['install'], { + cwd: ROOT_LOCATION, + shell: true, + stdio: 'inherit', + encoding: 'utf-8', + }); +}; + +alignPackageVersions(); diff --git a/scripts/monorepo/bump-all-updated-packages/bump-package-version.js b/scripts/monorepo/bump-all-updated-packages/bump-package-version.js new file mode 100644 index 000000000000..d403eb9f94e7 --- /dev/null +++ b/scripts/monorepo/bump-all-updated-packages/bump-package-version.js @@ -0,0 +1,52 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const {writeFileSync} = require('fs'); +const path = require('path'); + +const getIncrementedVersion = (version, increment) => + version + .split('.') + .map((token, index) => { + const indexOfVersionToIncrement = increment === 'minor' ? 1 : 2; + + if (index === indexOfVersionToIncrement) { + return parseInt(token, 10) + 1; + } + + if (index > indexOfVersionToIncrement) { + return 0; + } + + return token; + }) + .join('.'); + +const bumpPackageVersion = ( + packageAbsolutePath, + packageManifest, + increment = 'patch', +) => { + const updatedVersion = getIncrementedVersion( + packageManifest.version, + increment, + ); + + // Not using simple `npm version patch` because it updates dependencies and yarn.lock file + writeFileSync( + path.join(packageAbsolutePath, 'package.json'), + JSON.stringify({...packageManifest, version: updatedVersion}, null, 2) + + '\n', + 'utf-8', + ); + + return updatedVersion; +}; + +module.exports = bumpPackageVersion; diff --git a/scripts/monorepo/bump-all-updated-packages/bump-utils.js b/scripts/monorepo/bump-all-updated-packages/bump-utils.js new file mode 100644 index 000000000000..07c57e5313ab --- /dev/null +++ b/scripts/monorepo/bump-all-updated-packages/bump-utils.js @@ -0,0 +1,49 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const chalk = require('chalk'); +const {echo, exec} = require('shelljs'); + +const detectPackageUnreleasedChanges = ( + packageRelativePathFromRoot, + packageName, + ROOT_LOCATION, +) => { + const hashOfLastCommitInsidePackage = exec( + `git log -n 1 --format=format:%H -- ${packageRelativePathFromRoot}`, + {cwd: ROOT_LOCATION, silent: true}, + ).stdout.trim(); + + const hashOfLastCommitThatChangedVersion = exec( + `git log -G\\"version\\": --format=format:%H -n 1 -- ${packageRelativePathFromRoot}/package.json`, + {cwd: ROOT_LOCATION, silent: true}, + ).stdout.trim(); + + if (hashOfLastCommitInsidePackage === hashOfLastCommitThatChangedVersion) { + echo( + `\uD83D\uDD0E No changes for package ${chalk.green( + packageName, + )} since last version bump`, + ); + return false; + } else { + echo(`\uD83D\uDCA1 Found changes for ${chalk.yellow(packageName)}:`); + exec( + `git log --pretty=oneline ${hashOfLastCommitThatChangedVersion}..${hashOfLastCommitInsidePackage} ${packageRelativePathFromRoot}`, + { + cwd: ROOT_LOCATION, + }, + ); + echo(); + + return true; + } +}; + +module.exports = detectPackageUnreleasedChanges; diff --git a/scripts/monorepo/bump-all-updated-packages/index.js b/scripts/monorepo/bump-all-updated-packages/index.js new file mode 100644 index 000000000000..2501c86461c4 --- /dev/null +++ b/scripts/monorepo/bump-all-updated-packages/index.js @@ -0,0 +1,225 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const chalk = require('chalk'); +const {execSync} = require('child_process'); +const inquirer = require('inquirer'); +const path = require('path'); +const {echo, exec, exit} = require('shelljs'); +const yargs = require('yargs'); + +const { + PUBLISH_PACKAGES_TAG, + GENERIC_COMMIT_MESSAGE, + NO_COMMIT_CHOICE, + COMMIT_WITH_GENERIC_MESSAGE_CHOICE, + COMMIT_WITH_CUSTOM_MESSAGE_CHOICE, +} = require('../constants'); +const forEachPackage = require('../for-each-package'); +const checkForGitChanges = require('../check-for-git-changes'); +const bumpPackageVersion = require('./bump-package-version'); +const detectPackageUnreleasedChanges = require('./bump-utils'); + +const ROOT_LOCATION = path.join(__dirname, '..', '..', '..'); + +const { + argv: {releaseBranchCutoff}, +} = yargs + .option('release-branch-cutoff', { + type: 'boolean', + describe: 'Should force bump minor version for each public package', + }) + .strict(); + +const buildExecutor = + (packageAbsolutePath, packageRelativePathFromRoot, packageManifest) => + async () => { + const {name: packageName} = packageManifest; + if (packageManifest.private) { + echo(`\u23ED Skipping private package ${chalk.dim(packageName)}`); + + return; + } + + if (releaseBranchCutoff) { + const updatedVersion = bumpPackageVersion( + packageAbsolutePath, + packageManifest, + 'minor', + ); + echo( + `\u2705 Successfully bumped ${chalk.green( + packageName, + )} to ${chalk.green(updatedVersion)}`, + ); + + return; + } + + if ( + !detectPackageUnreleasedChanges( + packageRelativePathFromRoot, + packageName, + ROOT_LOCATION, + ) + ) { + return; + } + + await inquirer + .prompt([ + { + type: 'list', + name: 'shouldBumpPackage', + message: `Do you want to bump ${packageName}?`, + choices: ['Yes', 'No'], + filter: val => val === 'Yes', + }, + ]) + .then(({shouldBumpPackage}) => { + if (!shouldBumpPackage) { + echo(`Skipping bump for ${packageName}`); + return; + } + + return inquirer + .prompt([ + { + type: 'list', + name: 'increment', + message: 'Which version you want to increment?', + choices: ['patch', 'minor'], + }, + ]) + .then(({increment}) => { + const updatedVersion = bumpPackageVersion( + packageAbsolutePath, + packageManifest, + increment, + ); + echo( + `\u2705 Successfully bumped ${chalk.green( + packageName, + )} to ${chalk.green(updatedVersion)}`, + ); + }); + }); + }; + +const buildAllExecutors = () => { + const executors = []; + + forEachPackage( + (...params) => { + executors.push(buildExecutor(...params)); + }, + [ + 'assets', + 'eslint-config-react-native-community', + 'eslint-plugin-react-native-community', + 'normalize-color', + 'polyfills', + ], + ); + + return executors; +}; + +const main = async () => { + if (checkForGitChanges()) { + echo( + chalk.red( + 'Found uncommitted changes. Please commit or stash them before running this script', + ), + ); + exit(1); + } + + const executors = buildAllExecutors(); + for (const executor of executors) { + await executor() + .catch(() => exit(1)) + .then(() => echo()); + } + + if (checkForGitChanges()) { + await inquirer + .prompt([ + { + type: 'list', + name: 'commitChoice', + message: 'Do you want to submit a commit with these changes?', + choices: [ + { + name: 'Yes, with generic message', + value: COMMIT_WITH_GENERIC_MESSAGE_CHOICE, + }, + { + name: 'Yes, with custom message', + value: COMMIT_WITH_CUSTOM_MESSAGE_CHOICE, + }, + { + name: 'No', + value: NO_COMMIT_CHOICE, + }, + ], + }, + ]) + .then(({commitChoice}) => { + switch (commitChoice) { + case NO_COMMIT_CHOICE: { + echo('Not submitting a commit, but keeping all changes'); + + break; + } + + case COMMIT_WITH_GENERIC_MESSAGE_CHOICE: { + exec(`git commit -am "${GENERIC_COMMIT_MESSAGE}"`, { + cwd: ROOT_LOCATION, + silent: true, + }); + + break; + } + + case COMMIT_WITH_CUSTOM_MESSAGE_CHOICE: { + // exec from shelljs currently does not support interactive input + // https://github.com/shelljs/shelljs/wiki/FAQ#running-interactive-programs-with-exec + execSync('git commit -a', {cwd: ROOT_LOCATION, stdio: 'inherit'}); + + const enteredCommitMessage = exec( + 'git log -n 1 --format=format:%B', + { + cwd: ROOT_LOCATION, + silent: true, + }, + ).stdout.trim(); + const commitMessageWithTag = + enteredCommitMessage + `\n\n${PUBLISH_PACKAGES_TAG}`; + + exec(`git commit --amend -m "${commitMessageWithTag}"`, { + cwd: ROOT_LOCATION, + silent: true, + }); + + break; + } + + default: + throw new Error(''); + } + }) + .then(() => echo()); + } + + echo(chalk.green('Successfully finished the process of bumping packages')); + exit(0); +}; + +main(); diff --git a/scripts/monorepo/check-for-git-changes.js b/scripts/monorepo/check-for-git-changes.js new file mode 100644 index 000000000000..77e2d5d0190d --- /dev/null +++ b/scripts/monorepo/check-for-git-changes.js @@ -0,0 +1,39 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const {spawnSync} = require('child_process'); +const path = require('path'); + +const ROOT_LOCATION = path.join(__dirname, '..', '..'); + +const checkForGitChanges = () => { + const {stdout: thereIsSomethingToCommit, stderr} = spawnSync( + 'git', + ['status', '--porcelain'], + { + cwd: ROOT_LOCATION, + shell: true, + stdio: 'pipe', + encoding: 'utf-8', + }, + ); + + if (stderr) { + console.log( + '\u274c An error occured while running `git status --porcelain`:', + ); + console.log(stderr); + + process.exit(1); + } + + return Boolean(thereIsSomethingToCommit); +}; + +module.exports = checkForGitChanges; diff --git a/scripts/monorepo/constants.js b/scripts/monorepo/constants.js new file mode 100644 index 000000000000..8dd1f6c5fe87 --- /dev/null +++ b/scripts/monorepo/constants.js @@ -0,0 +1,24 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +const PUBLISH_PACKAGES_TAG = '#publish-packages-to-npm'; +const GENERIC_COMMIT_MESSAGE = `bumped packages versions\n\n${PUBLISH_PACKAGES_TAG}`; + +const NO_COMMIT_CHOICE = 'NO_COMMIT'; +const COMMIT_WITH_GENERIC_MESSAGE_CHOICE = 'COMMIT_WITH_GENERIC_MESSAGE'; +const COMMIT_WITH_CUSTOM_MESSAGE_CHOICE = 'COMMIT_WITH_CUSTOM_MESSAGE'; + +module.exports = { + PUBLISH_PACKAGES_TAG, + GENERIC_COMMIT_MESSAGE, + NO_COMMIT_CHOICE, + COMMIT_WITH_GENERIC_MESSAGE_CHOICE, + COMMIT_WITH_CUSTOM_MESSAGE_CHOICE, +}; diff --git a/scripts/monorepo/find-and-publish-all-bumped-packages.js b/scripts/monorepo/find-and-publish-all-bumped-packages.js new file mode 100644 index 000000000000..51d782d5c269 --- /dev/null +++ b/scripts/monorepo/find-and-publish-all-bumped-packages.js @@ -0,0 +1,130 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const path = require('path'); +const {spawnSync} = require('child_process'); + +const {PUBLISH_PACKAGES_TAG} = require('./constants'); +const forEachPackage = require('./for-each-package'); + +const ROOT_LOCATION = path.join(__dirname, '..', '..'); +const NPM_CONFIG_OTP = process.env.NPM_CONFIG_OTP; + +const findAndPublishAllBumpedPackages = () => { + console.log('Traversing all packages inside /packages...'); + + forEachPackage( + (packageAbsolutePath, packageRelativePathFromRoot, packageManifest) => { + if (packageManifest.private) { + console.log(`\u23ED Skipping private package ${packageManifest.name}`); + + return; + } + + const {stdout: diff, stderr: commitDiffStderr} = spawnSync( + 'git', + [ + 'log', + '-p', + '--format=""', + 'HEAD~1..HEAD', + `${packageRelativePathFromRoot}/package.json`, + ], + {cwd: ROOT_LOCATION, shell: true, stdio: 'pipe', encoding: 'utf-8'}, + ); + + if (commitDiffStderr) { + console.log( + `\u274c Failed to get latest committed changes for ${packageManifest.name}:`, + ); + console.log(commitDiffStderr); + + process.exit(1); + } + + const previousVersionPatternMatches = diff.match( + /- {2}"version": "([0-9]+.[0-9]+.[0-9]+)"/, + ); + + if (!previousVersionPatternMatches) { + console.log(`\uD83D\uDD0E No version bump for ${packageManifest.name}`); + + return; + } + + const {stdout: commitMessage, stderr: commitMessageStderr} = spawnSync( + 'git', + [ + 'log', + '-n', + '1', + '--format=format:%B', + `${packageRelativePathFromRoot}/package.json`, + ], + {cwd: ROOT_LOCATION, shell: true, stdio: 'pipe', encoding: 'utf-8'}, + ); + + if (commitMessageStderr) { + console.log( + `\u274c Failed to get latest commit message for ${packageManifest.name}:`, + ); + console.log(commitMessageStderr); + + process.exit(1); + } + + const hasSpecificPublishTag = + commitMessage.includes(PUBLISH_PACKAGES_TAG); + + if (!hasSpecificPublishTag) { + throw new Error( + `Package ${packageManifest.name} was updated, but not through CI script`, + ); + } + + const [, previousVersion] = previousVersionPatternMatches; + const nextVersion = packageManifest.version; + + console.log( + `\uD83D\uDCA1 ${packageManifest.name} was updated: ${previousVersion} -> ${nextVersion}`, + ); + + if (!nextVersion.startsWith('0.')) { + throw new Error( + `Package version expected to be 0.x.y, but received ${nextVersion}`, + ); + } + + const npmOTPFlag = NPM_CONFIG_OTP ? `--otp ${NPM_CONFIG_OTP}` : ''; + + const {status, stderr} = spawnSync('npm', ['publish', `${npmOTPFlag}`], { + cwd: packageAbsolutePath, + shell: true, + stdio: 'pipe', + encoding: 'utf-8', + }); + if (status !== 0) { + console.log( + `\u274c Failed to publish version ${nextVersion} of ${packageManifest.name}. npm publish exited with code ${status}:`, + ); + console.log(stderr); + + process.exit(1); + } else { + console.log( + `\u2705 Successfully published new version of ${packageManifest.name}`, + ); + } + }, + ); + + process.exit(0); +}; + +findAndPublishAllBumpedPackages(); diff --git a/scripts/monorepo/for-each-package.js b/scripts/monorepo/for-each-package.js new file mode 100644 index 000000000000..2118139c1ac7 --- /dev/null +++ b/scripts/monorepo/for-each-package.js @@ -0,0 +1,61 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const path = require('path'); +const {readdirSync, readFileSync} = require('fs'); + +const ROOT_LOCATION = path.join(__dirname, '..', '..'); +const PACKAGES_LOCATION = path.join(ROOT_LOCATION, 'packages'); + +const PACKAGES_BLOCK_LIST = ['react-native']; + +/** + * Function, which returns an array of all directories inside specified location + * + * @param {string} source Path to directory, where this should be executed + * @returns {string[]} List of directories names + */ +const getDirectories = source => + readdirSync(source, {withFileTypes: true}) + .filter(file => file.isDirectory()) + .map(directory => directory.name); + +/** + * @callback forEachPackageCallback + * @param {string} packageAbsolutePath + * @param {string} packageRelativePathFromRoot + * @param {Object} packageManifest + */ + +/** + * Iterate through every package inside /packages (ignoring react-native and any additional excluded packages) and call provided callback for each of them + * + * @param {forEachPackageCallback} callback - The callback which will be called for each package + * @param {string[]} [additionalExcludes] - Additional packages to exclude + */ +const forEachPackage = (callback, additionalExcludes = []) => { + const packagesToExclude = [...PACKAGES_BLOCK_LIST, ...additionalExcludes]; + + const packagesDirectories = getDirectories(PACKAGES_LOCATION).filter( + directoryName => !packagesToExclude.includes(directoryName), + ); + + packagesDirectories.forEach(packageDirectory => { + const packageAbsolutePath = path.join(PACKAGES_LOCATION, packageDirectory); + const packageRelativePathFromRoot = path.join('packages', packageDirectory); + + const packageManifest = JSON.parse( + readFileSync(path.join(packageAbsolutePath, 'package.json')), + ); + + callback(packageAbsolutePath, packageRelativePathFromRoot, packageManifest); + }); +}; + +module.exports = forEachPackage; diff --git a/scripts/npm-utils.js b/scripts/npm-utils.js new file mode 100644 index 000000000000..effeb4ce33c0 --- /dev/null +++ b/scripts/npm-utils.js @@ -0,0 +1,41 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +'use strict'; + +/** + * `package` is an object form of package.json + * `dependencies` is a map of dependency to version string + * + * This replaces both dependencies and devDependencies in package.json + */ +function applyPackageVersions(originalPackageJson, packageVersions) { + const packageJson = {...originalPackageJson}; + + for (const name of Object.keys(packageVersions)) { + if ( + packageJson.dependencies != null && + packageJson.dependencies[name] != null + ) { + packageJson.dependencies[name] = packageVersions[name]; + } + + if ( + packageJson.devDependencies != null && + packageJson.devDependencies[name] != null + ) { + packageJson.devDependencies[name] = packageVersions[name]; + } + } + return packageJson; +} + +module.exports = { + applyPackageVersions, +}; diff --git a/scripts/publish-npm.js b/scripts/publish-npm.js index 3cf96f5f1783..60b96d4c68b4 100755 --- a/scripts/publish-npm.js +++ b/scripts/publish-npm.js @@ -99,7 +99,7 @@ const rawVersion = : // For nightly we continue to use 0.0.0 for clarity for npm nightlyBuild ? '0.0.0' - : // For pre-release and stable releases, we use the git tag of the version we're releasing (set in bump-oss-version) + : // For pre-release and stable releases, we use the git tag of the version we're releasing (set in trigger-react-native-release) buildTag; let version, diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index d3e69f755110..78b187a975c0 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -15,6 +15,7 @@ require_relative './cocoapods/utils.rb' require_relative './cocoapods/new_architecture.rb' require_relative './cocoapods/local_podspec_patch.rb' +require_relative './cocoapods/helpers.rb' $CODEGEN_OUTPUT_DIR = 'build/generated/ios' $CODEGEN_COMPONENT_DIR = 'react/renderer/components' @@ -23,11 +24,11 @@ $START_TIME = Time.now.to_i -# This function returns the min iOS version supported by React Native -# By using this function, you won't have to manualy change your Podfile +# This function returns the min supported OS versions supported by React Native +# By using this function, you won't have to manually change your Podfile # when we change the minimum version supported by the framework. def min_ios_version_supported - return '12.4' + return Helpers::Constants.min_ios_version_supported end # This function prepares the project for React Native, before processing @@ -51,6 +52,7 @@ def prepare_react_native_project! # - flipper_configuration: The configuration to use for flipper. # - app_path: path to the React Native app. Required by the New Architecture. # - config_file_dir: directory of the `package.json` file, required by the New Architecture. +# - ios_folder: the folder where the iOS code base lives. For a template app, it is `ios`, the default. For RNTester, it is `.`. def use_react_native! ( path: "../node_modules/react-native", fabric_enabled: false, @@ -59,9 +61,15 @@ def use_react_native! ( hermes_enabled: ENV['USE_HERMES'] && ENV['USE_HERMES'] == '0' ? false : true, flipper_configuration: FlipperConfiguration.disabled, app_path: '..', - config_file_dir: '') + config_file_dir: '', + ios_folder: 'ios' +) - CodegenUtils.clean_up_build_folder(app_path, $CODEGEN_OUTPUT_DIR) + # Current target definition is provided by Cocoapods and it refers to the target + # that has invoked the `use_react_native!` function. + ReactNativePodsUtils.detect_use_frameworks(current_target_definition) + + CodegenUtils.clean_up_build_folder(app_path, ios_folder, $CODEGEN_OUTPUT_DIR) # We are relying on this flag also in third parties libraries to proper install dependencies. # Better to rely and enable this environment flag if the new architecture is turned on using flags. @@ -100,7 +108,7 @@ def use_react_native! ( else setup_jsc!(:react_native_path => prefix, :fabric_enabled => fabric_enabled) end - pod 'React-jsidynamic', :path => "#{prefix}/ReactCommon/jsi" + pod 'React-jsiexecutor', :path => "#{prefix}/ReactCommon/jsiexecutor" pod 'React-jsinspector', :path => "#{prefix}/ReactCommon/jsinspector" @@ -202,23 +210,28 @@ def react_native_post_install(installer, react_native_path = "../node_modules/re flipper_post_install(installer) end - package = JSON.parse(File.read(File.join(react_native_path, "package.json"))) + package_path = File.join(Pod::Config.instance.installation_root, react_native_path, "package.json") + package = JSON.parse(File.read(package_path)) version = package['version'] - if ReactNativePodsUtils.has_pod(installer, 'hermes-engine') && is_building_hermes_from_source(version) + if ReactNativePodsUtils.has_pod(installer, 'hermes-engine') && is_building_hermes_from_source(version, react_native_path) add_copy_hermes_framework_script_phase(installer, react_native_path) else remove_copy_hermes_framework_script_phase(installer, react_native_path) + remove_hermesc_build_dir(react_native_path) end ReactNativePodsUtils.exclude_i386_architecture_while_using_hermes(installer) ReactNativePodsUtils.fix_library_search_paths(installer) ReactNativePodsUtils.set_node_modules_user_settings(installer, react_native_path) + ReactNativePodsUtils.apply_xcode_15_patch(installer) + ReactNativePodsUtils.updateIphoneOSDeploymentTarget(installer) NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer) is_new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == "1" NewArchitectureHelper.modify_flags_for_new_architecture(installer, is_new_arch_enabled) + Pod::UI.puts "Pod install took #{Time.now.to_i - $START_TIME} [s] to run".green end diff --git a/scripts/react_native_pods_utils/script_phases.sh b/scripts/react_native_pods_utils/script_phases.sh index 32c59234407a..08efd2afbde0 100755 --- a/scripts/react_native_pods_utils/script_phases.sh +++ b/scripts/react_native_pods_utils/script_phases.sh @@ -13,8 +13,6 @@ GENERATED_SCHEMA_FILE="$GENERATED_SRCS_DIR/schema.json" cd "$RCT_SCRIPT_RN_DIR" -CODEGEN_REPO_PATH="$RCT_SCRIPT_RN_DIR/packages/react-native-codegen" -CODEGEN_NPM_PATH="$RCT_SCRIPT_RN_DIR/../react-native-codegen" CODEGEN_CLI_PATH="" error () { @@ -23,15 +21,6 @@ error () { exit 1 } -# Determine path to react-native-codegen -if [ -d "$CODEGEN_REPO_PATH" ]; then - CODEGEN_CLI_PATH=$(cd "$CODEGEN_REPO_PATH" && pwd) -elif [ -d "$CODEGEN_NPM_PATH" ]; then - CODEGEN_CLI_PATH=$(cd "$CODEGEN_NPM_PATH" && pwd) -else - error "error: Could not determine react-native-codegen location in $CODEGEN_REPO_PATH or $CODEGEN_NPM_PATH. Try running 'yarn install' or 'npm install' in your project root." -fi - find_node () { NODE_BINARY="${NODE_BINARY:-$(command -v node || true)}" if [ -z "$NODE_BINARY" ]; then @@ -41,6 +30,13 @@ find_node () { fi } +find_codegen () { + CODEGEN_CLI_PATH=$("$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native-codegen/package.json'))") + if ! [ -d "$CODEGEN_CLI_PATH" ]; then + error "error: Could not determine react-native-codegen location, using node module resolution. Try running 'yarn install' or 'npm install' in your project root." + fi +} + setup_dirs () { set +e rm -rf "$GENERATED_SRCS_DIR" @@ -108,7 +104,7 @@ moveOutputs () { mkdir -p "$RCT_SCRIPT_OUTPUT_DIR" # Copy all output to output_dir - cp -R "$TEMP_OUTPUT_DIR/" "$RCT_SCRIPT_OUTPUT_DIR" || exit 1 + cp -R "$TEMP_OUTPUT_DIR/." "$RCT_SCRIPT_OUTPUT_DIR" || exit 1 echo "$LIBRARY_NAME output has been written to $RCT_SCRIPT_OUTPUT_DIR:" >> "${SCRIPT_OUTPUT_FILE_0}" 2>&1 ls -1 "$RCT_SCRIPT_OUTPUT_DIR" >> "${SCRIPT_OUTPUT_FILE_0}" 2>&1 } @@ -116,6 +112,7 @@ moveOutputs () { withCodgenDiscovery () { setup_dirs find_node + find_codegen generateArtifacts moveOutputs } @@ -123,6 +120,7 @@ withCodgenDiscovery () { noCodegenDiscovery () { setup_dirs find_node + find_codegen generateCodegenSchemaFromJavaScript generateCodegenArtifactsFromSchema moveOutputs diff --git a/scripts/release-utils.js b/scripts/release-utils.js index ae0ca5876d95..e61648a1201b 100644 --- a/scripts/release-utils.js +++ b/scripts/release-utils.js @@ -111,11 +111,6 @@ function generateiOSArtifacts( ) { pushd(`${hermesCoreSourceFolder}`); - //Need to generate hermesc - exec( - `${hermesCoreSourceFolder}/utils/build-hermesc-xcode.sh ${hermesCoreSourceFolder}/build_host_hermesc`, - ); - //Generating iOS Artifacts exec( `JSI_PATH=${jsiFolder} BUILD_TYPE=${buildType} ${hermesCoreSourceFolder}/utils/build-mac-framework.sh`, diff --git a/scripts/run-ci-e2e-tests.js b/scripts/run-ci-e2e-tests.js index 9a928be712e5..a94e1be44688 100644 --- a/scripts/run-ci-e2e-tests.js +++ b/scripts/run-ci-e2e-tests.js @@ -19,11 +19,13 @@ * --retries [num] - how many times to retry possible flaky commands: yarn add and running tests, default 1 */ -const {cd, cp, echo, exec, exit, mv, rm} = require('shelljs'); +const {cd, cp, echo, exec, exit, mv} = require('shelljs'); const spawn = require('child_process').spawn; const argv = require('yargs').argv; const path = require('path'); -const {setupVerdaccio} = require('./setup-verdaccio'); + +const forEachPackage = require('./monorepo/for-each-package'); +const setupVerdaccio = require('./setup-verdaccio'); const SCRIPTS = __dirname; const ROOT = path.normalize(path.join(__dirname, '..')); @@ -34,6 +36,9 @@ const REACT_NATIVE_TEMP_DIR = exec( ).stdout.trim(); const REACT_NATIVE_APP_DIR = `${REACT_NATIVE_TEMP_DIR}/template`; const numberOfRetries = argv.retries || 1; + +const VERDACCIO_CONFIG_PATH = path.join(ROOT, '.circleci/verdaccio.yml'); + let SERVER_PID; let APPIUM_PID; let VERDACCIO_PID; @@ -73,17 +78,21 @@ try { const REACT_NATIVE_PACKAGE = path.join(ROOT, 'react-native-*.tgz'); describe('Set up Verdaccio'); - VERDACCIO_PID = setupVerdaccio(); + VERDACCIO_PID = setupVerdaccio(ROOT, VERDACCIO_CONFIG_PATH); describe('Publish packages'); - const packages = JSON.parse( - JSON.parse(exec('yarn --json workspaces info').stdout).data, + forEachPackage( + (packageAbsolutePath, packageRelativePathFromRoot, packageManifest) => { + if (packageManifest.private) { + return; + } + + exec( + 'npm publish --registry http://localhost:4873 --yes --access public', + {cwd: packageAbsolutePath}, + ); + }, ); - Object.keys(packages).forEach(packageName => { - exec( - `cd ${packages[packageName].location} && npm publish --registry http://localhost:4873 --yes --access public`, - ); - }); describe('Scaffold a basic React Native app from template'); exec(`rsync -a ${ROOT}/template ${REACT_NATIVE_TEMP_DIR}`); diff --git a/scripts/run-ci-javascript-tests.js b/scripts/run-ci-javascript-tests.js index bdb9fedd7c7e..30fee2573f95 100644 --- a/scripts/run-ci-javascript-tests.js +++ b/scripts/run-ci-javascript-tests.js @@ -65,6 +65,13 @@ try { throw Error(exitCode); } + describe('Test: TypeScript tests'); + if (exec(`${YARN_BINARY} run test-typescript-offline`).code) { + echo('Failed to run TypeScript tests.'); + exitCode = 1; + throw Error(exitCode); + } + exitCode = 0; } finally { // Do cleanup here diff --git a/scripts/set-rn-version.js b/scripts/set-rn-version.js index 44f9ae4764a4..c0b24f35a07e 100755 --- a/scripts/set-rn-version.js +++ b/scripts/set-rn-version.js @@ -38,7 +38,12 @@ let argv = yargs const buildType = argv.buildType; const version = argv.toVersion; -validateBuildType(buildType); + +try { + validateBuildType(buildType); +} catch (e) { + throw e; +} let major, minor, @@ -47,8 +52,7 @@ let major, try { ({major, minor, patch, prerelease} = parseVersion(version, buildType)); } catch (e) { - echo(e.message); - exit(1); + throw e; } const tmpVersioningFolder = fs.mkdtempSync( diff --git a/scripts/setup-verdaccio.js b/scripts/setup-verdaccio.js index e62e7918540d..26e8559e74eb 100644 --- a/scripts/setup-verdaccio.js +++ b/scripts/setup-verdaccio.js @@ -9,22 +9,41 @@ 'use strict'; -const {exec} = require('shelljs'); -const spawn = require('child_process').spawn; - -function setupVerdaccio() { - const verdaccioProcess = spawn('npx', [ - 'verdaccio@5.15.3', - '--config', - '.circleci/verdaccio.yml', - ]); +const {execSync, spawn} = require('child_process'); + +function setupVerdaccio( + reactNativeRootPath, // Path to React Native root folder + verdaccioConfigPath, // Path to Verdaccio config file, which you want to use for bootstrapping Verdaccio + verdaccioStoragePath, // Path to Verdaccio storage, where it should keep packages. Optional. Default value will be decided by your Verdaccio config +) { + if (!reactNativeRootPath) { + throw new Error( + 'Path to React Native repo root is not specified. You should provide it as a first argument', + ); + } + + if (!verdaccioConfigPath) { + throw new Error( + 'Path to Verdaccio config is not specified. You should provide it as a second argument', + ); + } + + execSync('echo "//localhost:4873/:_authToken=secretToken" > .npmrc', { + cwd: reactNativeRootPath, + }); + + const verdaccioProcess = spawn( + 'npx', + ['verdaccio@5.16.3', '--config', verdaccioConfigPath], + {env: {...process.env, VERDACCIO_STORAGE_PATH: verdaccioStoragePath}}, + ); + const VERDACCIO_PID = verdaccioProcess.pid; - exec('npx wait-on@6.0.1 http://localhost:4873'); - exec('npm set registry http://localhost:4873'); - exec('echo "//localhost:4873/:_authToken=secretToken" > .npmrc'); + + execSync('npx wait-on@6.0.1 http://localhost:4873'); + execSync('npm set registry http://localhost:4873'); + return VERDACCIO_PID; } -module.exports = { - setupVerdaccio: setupVerdaccio, -}; +module.exports = setupVerdaccio; diff --git a/scripts/template/initialize.js b/scripts/template/initialize.js new file mode 100644 index 000000000000..eaba0e4e9003 --- /dev/null +++ b/scripts/template/initialize.js @@ -0,0 +1,95 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +'use strict'; + +const yargs = require('yargs'); +const {execSync, spawnSync} = require('child_process'); + +const forEachPackage = require('../monorepo/for-each-package'); +const setupVerdaccio = require('../setup-verdaccio'); + +const {argv} = yargs + .option('r', { + alias: 'reactNativeRootPath', + describe: 'Path to root folder of react-native', + required: true, + }) + .option('n', { + alias: 'templateName', + describe: 'Template App name', + required: true, + }) + .option('tcp', { + alias: 'templateConfigPath', + describe: 'Path to folder containing template config', + required: true, + }) + .option('d', { + alias: 'directory', + describe: 'Path to template application folder', + required: true, + }) + .strict(); + +const {reactNativeRootPath, templateName, templateConfigPath, directory} = argv; + +const VERDACCIO_CONFIG_PATH = `${reactNativeRootPath}/.circleci/verdaccio.yml`; + +function install() { + const VERDACCIO_PID = setupVerdaccio( + reactNativeRootPath, + VERDACCIO_CONFIG_PATH, + ); + process.stdout.write('Bootstrapped Verdaccio \u2705\n'); + + process.stdout.write('Starting to publish every package...\n'); + forEachPackage( + (packageAbsolutePath, packageRelativePathFromRoot, packageManifest) => { + if (packageManifest.private) { + return; + } + + execSync('npm publish --registry http://localhost:4873 --access public', { + cwd: packageAbsolutePath, + stdio: [process.stdin, process.stdout, process.stderr], + }); + + process.stdout.write( + `Published ${packageManifest.name} to proxy \u2705\n`, + ); + }, + ); + + process.stdout.write('Published every package \u2705\n'); + + execSync( + `node cli.js init ${templateName} --directory ${directory} --template ${templateConfigPath} --verbose --skip-install`, + { + cwd: reactNativeRootPath, + stdio: [process.stdin, process.stdout, process.stderr], + }, + ); + process.stdout.write('Completed initialization of template app \u2705\n'); + + process.stdout.write('Installing dependencies in template app folder...\n'); + spawnSync('yarn', ['install'], { + cwd: directory, + stdio: [process.stdin, process.stdout, process.stderr], + }); + process.stdout.write('Installed dependencies via Yarn \u2705\n'); + + process.stdout.write(`Killing verdaccio. PID — ${VERDACCIO_PID}...\n`); + execSync(`kill -9 ${VERDACCIO_PID}`); + process.stdout.write('Killed Verdaccio process \u2705\n'); + + process.exit(); +} + +install(); diff --git a/scripts/test-e2e-local-clean.js b/scripts/test-e2e-local-clean.js index 37ca37032732..6dd85f5bba7c 100644 --- a/scripts/test-e2e-local-clean.js +++ b/scripts/test-e2e-local-clean.js @@ -44,6 +44,7 @@ if (isPackagerRunning() === 'running') { console.info('\n** Cleaning Gradle build artifacts **\n'); exec('./gradlew cleanAll'); exec('rm -rf /tmp/maven-local'); +exec('rm -rf /tmp/react-native-tmp'); // iOS console.info('\n** Nuking the derived data folder **\n'); @@ -56,9 +57,6 @@ exec('rm -rf ~/Library/Caches/CocoaPods/Pods/External/hermes-engine'); console.info('\n** Removing the RNTester Pods **\n'); exec('rm -rf packages/rn-tester/Pods'); -// I'm not sure we want to also remove the lock file -// exec('rm -rf packages/rn-tester/Podfile.lock'); - // RNTestProject console.info('\n** Removing the RNTestProject folder **\n'); exec('rm -rf /tmp/RNTestProject'); diff --git a/scripts/test-e2e-local.js b/scripts/test-e2e-local.js index 03605481c676..775e7e79ecd2 100644 --- a/scripts/test-e2e-local.js +++ b/scripts/test-e2e-local.js @@ -16,30 +16,21 @@ * and to make it more accessible for other devs to play around with. */ -const {exec, exit, pushd, popd, pwd, cd, cp} = require('shelljs'); +const {exec, pushd, popd, pwd, cd} = require('shelljs'); +const updateTemplatePackage = require('./update-template-package'); const yargs = require('yargs'); -const fs = require('fs'); const path = require('path'); +const fs = require('fs'); const os = require('os'); -const {getBranchName} = require('./scm-utils'); const { - launchAndroidEmulator, - isPackagerRunning, + checkPackagerRunning, + maybeLaunchAndroidEmulator, launchPackagerInSeparateWindow, + setupCircleCIArtifacts, + prepareArtifacts, } = require('./testing-utils'); -const { - generateAndroidArtifacts, - saveFilesToRestore, - generateiOSArtifacts, -} = require('./release-utils'); - -const { - downloadHermesSourceTarball, - expandHermesSourceTarball, -} = require('./hermes/hermes-utils'); - const argv = yargs .option('t', { alias: 'target', @@ -55,113 +46,152 @@ const argv = yargs alias: 'hermes', type: 'boolean', default: true, + }) + .option('c', { + alias: 'circleciToken', + type: 'string', }).argv; -/* - * see the test-local-e2e.js script for clean up process +// === RNTester === // + +/** + * Start the test for RNTester on iOS. + * + * Parameters: + * - @circleCIArtifacts manager object to manage all the download of CircleCIArtifacts. If null, it will fallback not to use them. + * - @onReleaseBranch whether we are on a release branch or not */ +async function testRNTesterIOS(circleCIArtifacts, onReleaseBranch) { + console.info( + `We're going to test the ${ + argv.hermes ? 'Hermes' : 'JSC' + } version of RNTester iOS with the new Architecture enabled`, + ); -// command order: we ask the user to select if they want to test RN tester -// or RNTestProject + // remember that for this to be successful + // you should have run bundle install once + // in your local setup + if (argv.hermes && circleCIArtifacts != null) { + const hermesURL = await circleCIArtifacts.artifactURLHermesDebug(); + const hermesPath = path.join( + circleCIArtifacts.baseTmpPath(), + 'hermes-ios-debug.tar.gz', + ); + // download hermes source code from manifold + circleCIArtifacts.downloadArtifact(hermesURL, hermesPath); + console.info(`Downloaded Hermes in ${hermesPath}`); + exec( + `HERMES_ENGINE_TARBALL_PATH=${hermesPath} RCT_NEW_ARCH_ENABLED=1 bundle exec pod install --ansi`, + ); + } else { + exec( + `USE_HERMES=${ + argv.hermes ? 1 : 0 + } REACT_NATIVE_CI=${onReleaseBranch} RCT_NEW_ARCH_ENABLED=1 bundle exec pod install --ansi`, + ); + } -// if they select RN tester, we ask if iOS or Android, and then we run the tests -// if they select RNTestProject, we run the RNTestProject test + // if everything succeeded so far, we can launch Metro and the app + // start the Metro server in a separate window + launchPackagerInSeparateWindow(pwd()); -// let's check if Metro is already running, if it is let's kill it and start fresh -if (isPackagerRunning() === 'running') { - exec("lsof -i :8081 | grep LISTEN | /usr/bin/awk '{print $2}' | xargs kill"); + // launch the app on iOS simulator + exec('npx react-native run-ios --scheme RNTester --simulator "iPhone 14"'); } -const onReleaseBranch = exec('git rev-parse --abbrev-ref HEAD', { - silent: true, -}) - .stdout.trim() - .endsWith('-stable'); +/** + * Start the test for RNTester on Android. + * + * Parameters: + * - @circleCIArtifacts manager object to manage all the download of CircleCIArtifacts. If null, it will fallback not to use them. + */ +async function testRNTesterAndroid(circleCIArtifacts) { + maybeLaunchAndroidEmulator(); -if (argv.target === 'RNTester') { - // FIXME: make sure that the commands retains colors - // (--ansi) doesn't always work - // see also https://github.com/shelljs/shelljs/issues/86 + console.info( + `We're going to test the ${ + argv.hermes ? 'Hermes' : 'JSC' + } version of RNTester Android with the new Architecture enabled`, + ); - if (argv.platform === 'iOS') { - console.info( - `We're going to test the ${ - argv.hermes ? 'Hermes' : 'JSC' - } version of RNTester iOS with the new Architecture enabled`, - ); + // Start the Metro server so it will be ready if the app can be built and installed successfully. + launchPackagerInSeparateWindow(pwd()); - // remember that for this to be successful - // you should have run bundle install once - // in your local setup - also: if I'm on release branch, I pick the - // hermes ref from the hermes ref file (see hermes-engine.podspec) - exec( - `cd packages/rn-tester && USE_HERMES=${ - argv.hermes ? 1 : 0 - } CI=${onReleaseBranch} RCT_NEW_ARCH_ENABLED=1 bundle exec pod install --ansi`, - ); + // Wait for the Android Emulator to be properly loaded and bootstrapped + exec( + "adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done; input keyevent 82'", + ); - // if everything succeeded so far, we can launch Metro and the app - // start the Metro server in a separate window - launchPackagerInSeparateWindow(); + if (circleCIArtifacts != null) { + const downloadPath = path.join( + circleCIArtifacts.baseTmpPath(), + 'rntester.apk', + ); - // launch the app on iOS simulator - pushd('packages/rn-tester'); - exec('npx react-native run-ios --scheme RNTester'); - popd(); - } else { - // we do the android path here + const emulatorArch = exec('adb shell getprop ro.product.cpu.abi').trim(); + const rntesterAPKURL = argv.hermes + ? await circleCIArtifacts.artifactURLForHermesRNTesterAPK(emulatorArch) + : await circleCIArtifacts.artifactURLForJSCRNTesterAPK(emulatorArch); - launchAndroidEmulator(); + console.info('Start Downloading APK'); + circleCIArtifacts.downloadArtifact(rntesterAPKURL, downloadPath); - console.info( - `We're going to test the ${ - argv.hermes ? 'Hermes' : 'JSC' - } version of RNTester Android with the new Architecture enabled`, - ); + exec(`adb install ${downloadPath}`); + } else { exec( - `./gradlew :packages:rn-tester:android:app:${ + `../../gradlew :packages:rn-tester:android:app:${ argv.hermes ? 'installHermesDebug' : 'installJscDebug' } --quiet`, ); + } - // launch the app on Android simulator - // TODO: we should find a way to make it work like for iOS, via npx react-native run-android - // currently, that fails with an error. + // launch the app + // TODO: we should find a way to make it work like for iOS, via npx react-native run-android + // currently, that fails with an error. + exec( + 'adb shell am start -n com.facebook.react.uiapp/com.facebook.react.uiapp.RNTesterActivity', + ); - // if everything succeeded so far, we can launch Metro and the app - // start the Metro server in a separate window - launchPackagerInSeparateWindow(); + // just to make sure that the Android up won't have troubles finding the Metro server + exec('adb reverse tcp:8081 tcp:8081'); +} - // launch the app - exec( - 'adb shell am start -n com.facebook.react.uiapp/com.facebook.react.uiapp.RNTesterActivity', - ); +/** + * Function that start testing on RNTester. + * + * Parameters: + * - @circleCIArtifacts manager object to manage all the download of CircleCIArtifacts. If null, it will fallback not to use them. + * - @onReleaseBranch whether we are on a release branch or not + */ +async function testRNTester(circleCIArtifacts, onReleaseBranch) { + // FIXME: make sure that the commands retains colors + // (--ansi) doesn't always work + // see also https://github.com/shelljs/shelljs/issues/86 + pushd('packages/rn-tester'); - // just to make sure that the Android up won't have troubles finding the Metro server - exec('adb reverse tcp:8081 tcp:8081'); + if (argv.platform === 'iOS') { + await testRNTesterIOS(circleCIArtifacts, onReleaseBranch); + } else { + await testRNTesterAndroid(circleCIArtifacts); } -} else { + popd(); +} + +// === RNTestProject === // + +async function testRNTestProject(circleCIArtifacts) { console.info("We're going to test a fresh new RN project"); // create the local npm package to feed the CLI // base setup required (specular to publish-npm.js) - const tmpPublishingFolder = fs.mkdtempSync( - path.join(os.tmpdir(), 'rn-publish-'), - ); - console.info(`The temp publishing folder is ${tmpPublishingFolder}`); - - saveFilesToRestore(tmpPublishingFolder); - - // we need to add the unique timestamp to avoid npm/yarn to use some local caches const baseVersion = require('../package.json').version; - const branchName = getBranchName(); - const buildType = - branchName.endsWith('-stable') && baseVersion !== '1000.0.0' - ? 'release' - : 'dry-run'; + // in local testing, 1000.0.0 mean we are on main, every other case means we are + // working on a release version + const buildType = baseVersion !== '1000.0.0' ? 'release' : 'dry-run'; + // we need to add the unique timestamp to avoid npm/yarn to use some local caches const dateIdentifier = new Date() .toISOString() .slice(0, -8) @@ -170,57 +200,49 @@ if (argv.target === 'RNTester') { const releaseVersion = `${baseVersion}-${dateIdentifier}`; - // this is needed to generate the Android artifacts correctly - exec( - `node scripts/set-rn-version.js --to-version ${releaseVersion} --build-type ${buildType}`, - ).code; - - // Generate native files for Android - generateAndroidArtifacts(releaseVersion, tmpPublishingFolder); - - // Setting up generating native iOS (will be done later) + // Prepare some variables for later use const repoRoot = pwd(); - const jsiFolder = `${repoRoot}/ReactCommon/jsi`; - const hermesCoreSourceFolder = `${repoRoot}/sdks/hermes`; - - if (!fs.existsSync(hermesCoreSourceFolder)) { - console.info('The Hermes source folder is missing. Downloading...'); - downloadHermesSourceTarball(); - expandHermesSourceTarball(); - } - - // need to move the scripts inside the local hermes cloned folder - // cp sdks/hermes-engine/utils/*.sh /utils/. - cp( - `${repoRoot}/sdks/hermes-engine/utils/*.sh`, - `${repoRoot}/sdks/hermes/utils/.`, + const reactNativePackagePath = `${repoRoot}`; + const localNodeTGZPath = `${reactNativePackagePath}/react-native-${releaseVersion}.tgz`; + + const mavenLocalPath = + circleCIArtifacts != null + ? path.join(circleCIArtifacts.baseTmpPath(), 'maven-local.zip') + : '/private/tmp/maven-local'; + const hermesPath = await prepareArtifacts( + circleCIArtifacts, + mavenLocalPath, + localNodeTGZPath, + releaseVersion, + buildType, + reactNativePackagePath, ); - // for this scenario, we only need to create the debug build - // (env variable PRODUCTION defines that podspec side) - const buildTypeiOSArtifacts = 'Debug'; - - // the android ones get set into /private/tmp/maven-local - const localMavenPath = '/private/tmp/maven-local'; - - // Generate native files for iOS - const tarballOutputPath = generateiOSArtifacts( - jsiFolder, - hermesCoreSourceFolder, - buildTypeiOSArtifacts, - localMavenPath, - ); + updateTemplatePackage({ + 'react-native': `file:${localNodeTGZPath}`, + }); // create locally the node module - exec('npm pack'); - - const localNodeTGZPath = `${repoRoot}/react-native-${releaseVersion}.tgz`; - exec(`node scripts/set-rn-template-version.js "file:${localNodeTGZPath}"`); + exec('npm pack --pack-destination ', {cwd: reactNativePackagePath}); + + // node pack does not creates a version of React Native with the right name on main. + // Let's add some defensive programming checks: + if (!fs.existsSync(localNodeTGZPath)) { + const tarfile = fs + .readdirSync(reactNativePackagePath) + .find(name => name.startsWith('react-native-') && name.endsWith('.tgz')); + if (!tarfile) { + throw new Error("Couldn't find a zipped version of react-native"); + } + exec( + `cp ${path.join(reactNativePackagePath, tarfile)} ${localNodeTGZPath}`, + ); + } pushd('/tmp/'); // need to avoid the pod install step - we'll do it later exec( - `node ${repoRoot}/cli.js init RNTestProject --template ${repoRoot} --skip-install`, + `node ${repoRoot}/cli.js init RNTestProject --template ${localNodeTGZPath} --skip-install`, ); cd('RNTestProject'); @@ -228,14 +250,14 @@ if (argv.target === 'RNTester') { // need to do this here so that Android will be properly setup either way exec( - 'echo "REACT_NATIVE_MAVEN_LOCAL_REPO=/private/tmp/maven-local" >> android/gradle.properties', + `echo "REACT_NATIVE_MAVEN_LOCAL_REPO=${mavenLocalPath}" >> android/gradle.properties`, ); // doing the pod install here so that it's easier to play around RNTestProject cd('ios'); exec('bundle install'); exec( - `HERMES_ENGINE_TARBALL_PATH=${tarballOutputPath} USE_HERMES=${ + `HERMES_ENGINE_TARBALL_PATH=${hermesPath} USE_HERMES=${ argv.hermes ? 1 : 0 } bundle exec pod install --ansi`, ); @@ -251,7 +273,37 @@ if (argv.target === 'RNTester') { popd(); // just cleaning up the temp folder, the rest is done by the test clean script - exec(`rm -rf ${tmpPublishingFolder}`); + exec(`rm -rf /tmp/react-native-tmp`); +} + +async function main() { + /* + * see the test-local-e2e.js script for clean up process + */ + + // command order: we ask the user to select if they want to test RN tester + // or RNTestProject + + // if they select RN tester, we ask if iOS or Android, and then we run the tests + // if they select RNTestProject, we run the RNTestProject test + + checkPackagerRunning(); + + const branchName = exec('git rev-parse --abbrev-ref HEAD', { + silent: true, + }).stdout.trim(); + const onReleaseBranch = branchName.endsWith('-stable'); + + let circleCIArtifacts = await setupCircleCIArtifacts( + argv.circleciToken, + branchName, + ); + + if (argv.target === 'RNTester') { + await testRNTester(circleCIArtifacts, onReleaseBranch); + } else { + await testRNTestProject(circleCIArtifacts); + } } -exit(0); +main(); diff --git a/scripts/testing-utils.js b/scripts/testing-utils.js index a687a37cd562..b742209a6def 100644 --- a/scripts/testing-utils.js +++ b/scripts/testing-utils.js @@ -9,9 +9,23 @@ 'use strict'; -const {exec} = require('shelljs'); +const {exec, cp} = require('shelljs'); +const fs = require('fs'); const os = require('os'); const {spawn} = require('node:child_process'); +const path = require('path'); + +const circleCIArtifactsUtils = require('./circle-ci-artifacts-utils.js'); + +const { + generateAndroidArtifacts, + generateiOSArtifacts, +} = require('./release-utils'); + +const { + downloadHermesSourceTarball, + expandHermesSourceTarball, +} = require('./hermes/hermes-utils.js'); /* * Android related utils - leverages android tooling @@ -35,12 +49,12 @@ const launchEmulator = emulatorName => { // from docs: "When using the detached option to start a long-running process, the process will not stay running in the background after the parent exits unless it is provided with a stdio configuration that is not connected to the parent. If the parent's stdio is inherited, the child will remain attached to the controlling terminal." // here: https://nodejs.org/api/child_process.html#optionsdetached - const cp = spawn(emulatorCommand, [`@${emulatorName}`], { + const child_process = spawn(emulatorCommand, [`@${emulatorName}`], { detached: true, stdio: 'ignore', }); - cp.unref(); + child_process.unref(); }; function tryLaunchEmulator() { @@ -60,7 +74,20 @@ function tryLaunchEmulator() { }; } -function launchAndroidEmulator() { +function hasConnectedDevice() { + const physicalDevices = exec('adb devices | grep -v emulator', {silent: true}) + .stdout.trim() + .split('\n') + .slice(1); + return physicalDevices.length > 0; +} + +function maybeLaunchAndroidEmulator() { + if (hasConnectedDevice()) { + console.info('Already have a device connected. Skip launching emulator.'); + return; + } + const result = tryLaunchEmulator(); if (result.success) { console.info('Successfully launched emulator.'); @@ -97,15 +124,169 @@ function isPackagerRunning( } // this is a very limited implementation of how this should work -// literally, this is macos only -// a more robust implementation can be found here: -// https://github.com/react-native-community/cli/blob/7c003f2b1d9d80ec5c167614ba533a004272c685/packages/cli-platform-android/src/commands/runAndroid/index.ts#L195 -function launchPackagerInSeparateWindow() { - exec("open -a 'Terminal' ./scripts/packager.sh"); +function launchPackagerInSeparateWindow(folderPath) { + const command = `tell application "Terminal" to do script "cd ${folderPath} && yarn start"`; + exec(`osascript -e '${command}' >/dev/null </hermes-engine.podspec + cp( + `${reactNativePackagePath}/sdks/hermes-engine/hermes-engine.podspec`, + `${reactNativePackagePath}/sdks/hermes/hermes-engine.podspec`, + ); + // need to move the hermes-utils file from hermes-engine to hermes folder + // cp sdks/hermes-engine/hermes-utils.rb /hermes-utils.rb + cp( + `${reactNativePackagePath}/sdks/hermes-engine/hermes-utils.rb`, + `${reactNativePackagePath}/sdks/hermes/hermes-utils.rb`, + ); + // need to move the shell scripts file from hermes-engine to hermes folder + // cp sdks/hermes-engine/utils/*.sh /utils/. + cp( + `${reactNativePackagePath}/sdks/hermes-engine/utils/*.sh`, + `${reactNativePackagePath}/sdks/hermes/utils/.`, + ); + + // for this scenario, we only need to create the debug build + // (env variable PRODUCTION defines that podspec side) + const buildTypeiOSArtifacts = 'Debug'; + + // the android ones get set into /private/tmp/maven-local + const localMavenPath = '/private/tmp/maven-local'; + + // Generate native files for iOS + const hermesPath = generateiOSArtifacts( + jsiFolder, + hermesCoreSourceFolder, + buildTypeiOSArtifacts, + localMavenPath, + ); + + return hermesPath; +} + +/** + * It prepares the artifacts required to run a new project created from the template + * + * Parameters: + * - @circleCIArtifacts manager object to manage all the download of CircleCIArtifacts. If null, it will fallback not to use them. + * - @mavenLocalPath path to the local maven repo that is needed by Android. + * - @localNodeTGZPath path where we want to store the react-native tgz. + * - @releaseVersion the version that is about to be released. + * - @buildType the type of build we want to execute if we build locally. + * - @reactNativePackagePath the path to the react native package within the repo. + * + * Returns: + * - @hermesPath the path to hermes for iOS + */ +async function prepareArtifacts( + circleCIArtifacts, + mavenLocalPath, + localNodeTGZPath, + releaseVersion, + buildType, + reactNativePackagePath, +) { + return circleCIArtifacts != null + ? await downloadArtifactsFromCircleCI( + circleCIArtifacts, + mavenLocalPath, + localNodeTGZPath, + ) + : buildArtifactsLocally(releaseVersion, buildType, reactNativePackagePath); } module.exports = { - launchAndroidEmulator, + checkPackagerRunning, + maybeLaunchAndroidEmulator, isPackagerRunning, launchPackagerInSeparateWindow, + setupCircleCIArtifacts, + prepareArtifacts, }; diff --git a/scripts/bump-oss-version.js b/scripts/trigger-react-native-release.js old mode 100755 new mode 100644 similarity index 63% rename from scripts/bump-oss-version.js rename to scripts/trigger-react-native-release.js index bf8c3d8e9139..f1f794896867 --- a/scripts/bump-oss-version.js +++ b/scripts/trigger-react-native-release.js @@ -14,14 +14,21 @@ * This script walks a releaser through bumping the version for a release * It will commit the appropriate tags to trigger the CircleCI jobs. */ -const {exit} = require('shelljs'); +const {exit, echo} = require('shelljs'); +const chalk = require('chalk'); const yargs = require('yargs'); const inquirer = require('inquirer'); const request = require('request'); +const path = require('path'); const {getBranchName, exitIfNotOnGit} = require('./scm-utils'); const {parseVersion, isReleaseBranch} = require('./version-utils'); const {failIfTagExists} = require('./release-utils'); +const checkForGitChanges = require('./monorepo/check-for-git-changes'); +const forEachPackage = require('./monorepo/for-each-package'); +const detectPackageUnreleasedChanges = require('./monorepo/bump-all-updated-packages/bump-utils.js'); + +const ROOT_LOCATION = path.join(__dirname, '..'); let argv = yargs .option('r', { @@ -42,7 +49,7 @@ let argv = yargs .check(() => { const branch = exitIfNotOnGit( () => getBranchName(), - "Not in git. You can't invoke bump-oss-versions.js from outside a git repo.", + "Not in git. You can't invoke trigger-react-native-release from outside a git repo.", ); exitIfNotOnReleaseBranch(branch); return true; @@ -57,6 +64,61 @@ function exitIfNotOnReleaseBranch(branch) { } } +const buildExecutor = + (packageAbsolutePath, packageRelativePathFromRoot, packageManifest) => + async () => { + const {name: packageName} = packageManifest; + if (packageManifest.private) { + return; + } + + if ( + detectPackageUnreleasedChanges( + packageRelativePathFromRoot, + packageName, + ROOT_LOCATION, + ) + ) { + // if I enter here, I want to throw an error upward + throw new Error( + `Package ${packageName} has unreleased changes. Please release it first.`, + ); + } + }; + +const buildAllExecutors = () => { + const executors = []; + + forEachPackage( + (...params) => { + executors.push(buildExecutor(...params)); + }, + [ + 'assets', + 'eslint-config-react-native-community', + 'eslint-plugin-react-native-community', + 'normalize-color', + 'polyfills', + ], + ); + + return executors; +}; + +async function exitIfUnreleasedPackages() { + // use the other script to verify that there's no packages in the monorepo + // that have changes that haven't been released + + const executors = buildAllExecutors(); + for (const executor of executors) { + await executor().catch(error => { + echo(chalk.red(error)); + // need to throw upward + throw error; + }); + } +} + function triggerReleaseWorkflow(options) { return new Promise((resolve, reject) => { request(options, function (error, response, body) { @@ -72,8 +134,26 @@ function triggerReleaseWorkflow(options) { async function main() { const branch = exitIfNotOnGit( () => getBranchName(), - "Not in git. You can't invoke bump-oss-versions.js from outside a git repo.", + "Not in git. You can't invoke trigger-react-native-release from outside a git repo.", ); + + // check for uncommitted changes + if (checkForGitChanges()) { + echo( + chalk.red( + 'Found uncommitted changes. Please commit or stash them before running this script', + ), + ); + exit(1); + } + + // now check for unreleased packages + try { + await exitIfUnreleasedPackages(); + } catch (error) { + exit(1); + } + const token = argv.token; const releaseVersion = argv.toVersion; failIfTagExists(releaseVersion, 'release'); diff --git a/scripts/update-ruby.sh b/scripts/update-ruby.sh index 2e8f39bb74be..cb9c20b392ce 100755 --- a/scripts/update-ruby.sh +++ b/scripts/update-ruby.sh @@ -32,23 +32,6 @@ fi if [ -z "$VERSION" ]; then die "Please provide an installed/usable Ruby version" fi -echo "Setting Ruby version to: $VERSION" - -cd "$ROOT" || die "Failed to change to $ROOT" - -# do this first, so rbenv/rvm will automatically pick the desired version -echo "$VERSION" > .ruby-version - -# make sure we're using it -CURRENT_VERSION=$(ruby --version | cut -d' ' -f2 | cut -dp -f1) -if [ -z "$CURRENT_VERSION" ]; then - # rbenv/rvm uses shims, the commands do exist, but do not return a version if misconfigured - die "Missing usable ruby, check your installation" -elif [ "$VERSION" != "$CURRENT_VERSION" ]; then - die "Plese use the ruby version you are trying to set: $VERSION ('$CURRENT_VERSION' in use)" -fi - -echo "$VERSION" > template/_ruby-version rm -f Gemfile.lock @@ -62,10 +45,7 @@ export GIT_DISCOVERY_ACROSS_FILESYSTEM=1; IS_GIT_REPO=$(git rev-parse --is-inside-work-tree 2> /dev/null || true) export GIT_DISCOVERY_ACROSS_FILESYSTEM=0; if [ "$IS_GIT_REPO" = "true" ]; then - git add \ - .ruby-version \ - Gemfile.lock \ - template/_ruby-version + git add Gemfile.lock else echo "Detected that you're not in Git. If on another SCM, don't forget to commit the edited files." fi diff --git a/scripts/update-template-package.js b/scripts/update-template-package.js new file mode 100644 index 000000000000..77f0b74ecc53 --- /dev/null +++ b/scripts/update-template-package.js @@ -0,0 +1,51 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const {applyPackageVersions} = require('./npm-utils'); + +/** + * Updates the react-native template package.json with + * dependencies in `dependencyMap`. + * + * `dependencyMap` is a dict of package name to its version + * ex. {"react-native": "0.23.0", "other-dep": "nightly"} + */ +function updateTemplatePackage(dependencyMap) { + const jsonPath = path.join(__dirname, '../template/package.json'); + const templatePackageJson = require(jsonPath); + + const updatedPackageJson = applyPackageVersions( + templatePackageJson, + dependencyMap, + ); + + fs.writeFileSync( + jsonPath, + JSON.stringify(updatedPackageJson, null, 2) + '\n', + 'utf-8', + ); +} + +if (require.main === module) { + const dependencyMapStr = process.argv[2]; + if (!dependencyMapStr) { + console.error( + 'Please provide a json string of package name and their version. Ex. \'{"packageName":"0.23.0"}\'', + ); + process.exit(1); + } + + updateTemplatePackage(JSON.parse(dependencyMapStr)); +} + +module.exports = updateTemplatePackage; diff --git a/scripts/update_podfile_lock.sh b/scripts/update_podfile_lock.sh index fa6db464666e..6cfca208a42d 100755 --- a/scripts/update_podfile_lock.sh +++ b/scripts/update_podfile_lock.sh @@ -20,6 +20,7 @@ validate_env () { update_pods () { cd "$RNTESTER_DIR" || exit + bundle install || exit bundle check || exit bundle exec pod install cd "$THIS_DIR" || exit diff --git a/scripts/version-utils.js b/scripts/version-utils.js index e73ea62ed442..6c44e768f3b8 100644 --- a/scripts/version-utils.js +++ b/scripts/version-utils.js @@ -18,6 +18,7 @@ const VERSION_REGEX = /^v?((\d+)\.(\d+)\.(\d+)(?:-(.+))?)$/; * Some examples of valid versions are: * - stable: 0.68.1 * - stable prerelease: 0.70.0-rc.0 + * - e2e-test: X.Y.Z-20221116-2018 * - nightly: 0.0.0-20221116-2018-0bc4547fc * - dryrun: 1000.0.0 * @@ -38,7 +39,11 @@ const VERSION_REGEX = /^v?((\d+)\.(\d+)\.(\d+)(?:-(.+))?)$/; * */ function parseVersion(versionStr, buildType) { - validateBuildType(buildType); + try { + validateBuildType(buildType); + } catch (e) { + throw e; + } const match = extractMatchIfValid(versionStr); const [, version, major, minor, patch, prerelease] = match; @@ -51,7 +56,11 @@ function parseVersion(versionStr, buildType) { prerelease, }; - validateVersion(versionObject, buildType); + try { + validateVersion(versionObject, buildType); + } catch (e) { + throw e; + } return versionObject; } @@ -126,10 +135,11 @@ function isStablePrerelease(version) { return ( version.major === '0' && version.minor !== '0' && - version.patch === '0' && + version.patch.match(/^\d+$/) && version.prerelease != null && (version.prerelease.startsWith('rc.') || - version.prerelease.startsWith('rc-')) + version.prerelease.startsWith('rc-') || + version.prerelease.match(/^(\d{8})-(\d{4})$/)) ); } diff --git a/sdks/.hermesversion b/sdks/.hermesversion index d18f67396068..b235e486a2df 100644 --- a/sdks/.hermesversion +++ b/sdks/.hermesversion @@ -1 +1 @@ -hermes-2022-11-03-RNv0.71.0-85613e1f9d1216f2cce7e54604be46057092939d \ No newline at end of file +hermes-2023-03-07-RNv0.71.4-31fdcf738940875c9bacf251e149006cf515d763 \ No newline at end of file diff --git a/sdks/hermes-engine/hermes-engine.podspec b/sdks/hermes-engine/hermes-engine.podspec index 9f3b90bf77e8..b80054750b18 100644 --- a/sdks/hermes-engine/hermes-engine.podspec +++ b/sdks/hermes-engine/hermes-engine.podspec @@ -17,7 +17,7 @@ version = package['version'] # sdks/.hermesversion hermestag_file = File.join(react_native_path, "sdks", ".hermesversion") -isInCI = ENV['CI'] === 'true' +isInCI = ENV['REACT_NATIVE_CI'] === 'true' source = {} git = "https://github.com/facebook/hermes.git" @@ -43,7 +43,7 @@ elsif isNightly destination_path = download_nightly_hermes(react_native_path, version) # set tarball as hermes engine source[:http] = "file://#{destination_path}" -elsif File.exists?(hermestag_file) && isInCI +elsif File.exist?(hermestag_file) && isInCI Pod::UI.puts '[Hermes] Detected that you are on a React Native release branch, building Hermes from source but fetched from tag...'.yellow if Object.const_defined?("Pod::UI") hermestag = File.read(hermestag_file).strip source[:git] = git diff --git a/sdks/hermes-engine/utils/build-apple-framework.sh b/sdks/hermes-engine/utils/build-apple-framework.sh index 87faae6cb699..eaf7f58ba819 100755 --- a/sdks/hermes-engine/utils/build-apple-framework.sh +++ b/sdks/hermes-engine/utils/build-apple-framework.sh @@ -52,13 +52,8 @@ function build_host_hermesc { # Utility function to configure an Apple framework function configure_apple_framework { - local build_cli_tools enable_bitcode enable_debugger cmake_build_type + local build_cli_tools enable_debugger cmake_build_type xcode_15_flags xcode_major_version - if [[ $1 == iphoneos || $1 == catalyst ]]; then - enable_bitcode="true" - else - enable_bitcode="false" - fi if [[ $1 == macosx ]]; then build_cli_tools="true" else @@ -77,8 +72,15 @@ function configure_apple_framework { cmake_build_type="MinSizeRel" fi + xcode_15_flags="" + xcode_major_version=$(xcodebuild -version | grep -oE '[0-9]*' | head -n 1) + if [[ $xcode_major_version -ge 15 ]]; then + xcode_15_flags="LINKER:-ld_classic" + fi + pushd "$HERMES_PATH" > /dev/null || exit 1 cmake -S . -B "build_$1" \ + -DHERMES_EXTRA_LINKER_FLAGS="$xcode_15_flags" \ -DHERMES_APPLE_TARGET_PLATFORM:STRING="$1" \ -DCMAKE_OSX_ARCHITECTURES:STRING="$2" \ -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING="$3" \ @@ -87,7 +89,7 @@ function configure_apple_framework { -DHERMES_ENABLE_LIBFUZZER:BOOLEAN=false \ -DHERMES_ENABLE_FUZZILLI:BOOLEAN=false \ -DHERMES_ENABLE_TEST_SUITE:BOOLEAN=false \ - -DHERMES_ENABLE_BITCODE:BOOLEAN="$enable_bitcode" \ + -DHERMES_ENABLE_BITCODE:BOOLEAN=false \ -DHERMES_BUILD_APPLE_FRAMEWORK:BOOLEAN=true \ -DHERMES_BUILD_APPLE_DSYM:BOOLEAN=true \ -DHERMES_ENABLE_TOOLS:BOOLEAN="$build_cli_tools" \ diff --git a/sdks/hermes-engine/utils/build-hermes-xcode.sh b/sdks/hermes-engine/utils/build-hermes-xcode.sh index 37faee325060..fa2ebe91bbca 100755 --- a/sdks/hermes-engine/utils/build-hermes-xcode.sh +++ b/sdks/hermes-engine/utils/build-hermes-xcode.sh @@ -33,6 +33,13 @@ if [ -z "$deployment_target" ]; then deployment_target=${MACOSX_DEPLOYMENT_TARGET} fi +xcode_15_flags="" +xcode_major_version=$(xcodebuild -version | grep -oE '[0-9]*' | head -n 1) +if [[ $xcode_major_version -ge 15 ]]; then + echo "########### Using LINKER:-ld_classic ###########" + xcode_15_flags="LINKER:-ld_classic" +fi + architectures=$( echo "$ARCHS" | tr " " ";" ) echo "Configure Apple framework" @@ -40,6 +47,7 @@ echo "Configure Apple framework" "$CMAKE_BINARY" \ -S "${PODS_ROOT}/hermes-engine" \ -B "${PODS_ROOT}/hermes-engine/build/${PLATFORM_NAME}" \ + -DHERMES_EXTRA_LINKER_FLAGS="$xcode_15_flags" \ -DHERMES_APPLE_TARGET_PLATFORM:STRING="$PLATFORM_NAME" \ -DCMAKE_OSX_ARCHITECTURES:STRING="$architectures" \ -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING="$deployment_target" \ diff --git a/settings.gradle.kts b/settings.gradle.kts index 836c9a2946ea..f4dc00a0c229 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,14 +13,15 @@ pluginManagement { } } -include( - ":ReactAndroid", - ":ReactAndroid:hermes-engine", - ":ReactAndroid:external-artifacts", - ":packages:rn-tester:android:app") +include(":ReactAndroid", ":ReactAndroid:hermes-engine", ":ReactAndroid:external-artifacts") -// Include this to enable codegen Gradle plugin. -includeBuild("packages/react-native-gradle-plugin/") +// If the ./packages folder exists, then we're inside the React Native repository. +// If not, a users is consuming this project for a build from source. +if (File("${rootDir}/packages").exists()) { + include(":packages:rn-tester:android:app") + // Include this to enable codegen Gradle plugin. + includeBuild("packages/react-native-gradle-plugin/") +} rootProject.name = "react-native-github" diff --git a/template/Gemfile b/template/Gemfile index 567e59805c4a..68f1b2ad5564 100644 --- a/template/Gemfile +++ b/template/Gemfile @@ -1,6 +1,9 @@ source 'https://rubygems.org' # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version -ruby File.read(File.join(__dir__, '.ruby-version')).strip +ruby '>= 2.6.10' -gem 'cocoapods', '~> 1.11', '>= 1.11.3' +# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper +# bound in the template on Cocoapods with next React Native release. +gem 'cocoapods', '>= 1.13', '< 1.15' +gem 'activesupport', '>= 6.1.7.3', '< 7.1.0' diff --git a/template/_eslintrc.js b/template/_eslintrc.js index 189699723fd2..40c6dcd05f31 100644 --- a/template/_eslintrc.js +++ b/template/_eslintrc.js @@ -1,6 +1,4 @@ module.exports = { root: true, extends: '@react-native-community', - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint'], }; diff --git a/template/_node-version b/template/_node-version index b6a7d89c68e0..3c032078a4a2 100644 --- a/template/_node-version +++ b/template/_node-version @@ -1 +1 @@ -16 +18 diff --git a/template/_ruby-version b/template/_ruby-version deleted file mode 100644 index 49cdd668e1c8..000000000000 --- a/template/_ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.7.6 diff --git a/template/android/app/build.gradle b/template/android/app/build.gradle index e3b8c4c9cf4a..71195c76234a 100644 --- a/template/android/app/build.gradle +++ b/template/android/app/build.gradle @@ -12,9 +12,9 @@ react { // The root of your project, i.e. where "package.json" lives. Default is '..' // root = file("../") // The folder where the react-native NPM package is. Default is ../node_modules/react-native - // reactNativeDir = file("../node-modules/react-native") + // reactNativeDir = file("../node_modules/react-native") // The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen - // codegenDir = file("../node-modules/react-native-codegen") + // codegenDir = file("../node_modules/react-native-codegen") // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js // cliFile = file("../node_modules/react-native/cli.js") diff --git a/template/android/build.gradle b/template/android/build.gradle index 4631930d4a5c..67d887b03078 100644 --- a/template/android/build.gradle +++ b/template/android/build.gradle @@ -19,19 +19,3 @@ buildscript { classpath("com.facebook.react:react-native-gradle-plugin") } } - -allprojects { - repositories { - maven { - // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm - url("$rootDir/../node_modules/react-native/android") - } - maven { - // Android JSC is installed from npm - url("$rootDir/../node_modules/jsc-android/dist") - } - mavenCentral() - google() - maven { url 'https://www.jitpack.io' } - } -} diff --git a/template/ios/HelloWorld/AppDelegate.mm b/template/ios/HelloWorld/AppDelegate.mm index 6edcfa51889a..47957cfd08b5 100644 --- a/template/ios/HelloWorld/AppDelegate.mm +++ b/template/ios/HelloWorld/AppDelegate.mm @@ -7,6 +7,10 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.moduleName = @"HelloWorld"; + // You can add your custom initial props in the dictionary below. + // They will be passed down to the ViewController used by React Native. + self.initialProps = @{}; + return [super application:application didFinishLaunchingWithOptions:launchOptions]; } diff --git a/template/ios/Podfile b/template/ios/Podfile index 579715789c9f..74f991b244a2 100644 --- a/template/ios/Podfile +++ b/template/ios/Podfile @@ -1,11 +1,26 @@ require_relative '../node_modules/react-native/scripts/react_native_pods' -require_relative '../node_modules/react-native/scripts/native_modules' +require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' platform :ios, min_ios_version_supported prepare_react_native_project! +# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. +# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded +# +# To fix this you can also exclude `react-native-flipper` using a `react-native.config.js` +# ```js +# module.exports = { +# dependencies: { +# ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), +# ``` flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled +linkage = ENV['USE_FRAMEWORKS'] +if linkage != nil + Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green + use_frameworks! :linkage => linkage.to_sym +end + target 'HelloWorld' do config = use_native_modules! diff --git a/template/package.json b/template/package.json index a0766384380e..2f01b0d17a3a 100644 --- a/template/package.json +++ b/template/package.json @@ -11,23 +11,21 @@ }, "dependencies": { "react": "18.2.0", - "react-native": "0.71.0-rc.1" + "react-native": "0.71.17" }, "devDependencies": { - "@babel/core": "^7.12.9", - "@babel/preset-env": "^7.14.0", - "@babel/runtime": "^7.12.5", - "@react-native-community/eslint-config": "^3.0.0", + "@babel/core": "^7.20.0", + "@babel/preset-env": "^7.20.0", + "@babel/runtime": "^7.20.0", + "@react-native-community/eslint-config": "^3.2.0", "@tsconfig/react-native": "^2.0.2", "@types/jest": "^29.2.1", "@types/react": "^18.0.24", "@types/react-test-renderer": "^18.0.0", - "@typescript-eslint/eslint-plugin": "^5.37.0", - "@typescript-eslint/parser": "^5.37.0", "babel-jest": "^29.2.1", "eslint": "^8.19.0", "jest": "^29.2.1", - "metro-react-native-babel-preset": "0.73.3", + "metro-react-native-babel-preset": "0.73.10", "prettier": "^2.4.1", "react-test-renderer": "18.2.0", "typescript": "4.8.4" diff --git a/third-party-podspecs/boost.podspec b/third-party-podspecs/boost.podspec index 3d9331c95d12..bbbb7380e51a 100644 --- a/third-party-podspecs/boost.podspec +++ b/third-party-podspecs/boost.podspec @@ -10,7 +10,7 @@ Pod::Spec.new do |spec| spec.homepage = 'http://www.boost.org' spec.summary = 'Boost provides free peer-reviewed portable C++ source libraries.' spec.authors = 'Rene Rivera' - spec.source = { :http => 'https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.bz2', + spec.source = { :http => 'https://archives.boost.io/release/1.76.0/source/boost_1_76_0.tar.bz2', :sha256 => 'f0397ba6e982c4450f27bf32a2a83292aba035b827a5623a14636ea583318c41' } # Pinning to the same version as React.podspec. diff --git a/types/__typetests__/index.tsx b/types/__typetests__/index.tsx index f530b0702fcb..768b798bafd8 100644 --- a/types/__typetests__/index.tsx +++ b/types/__typetests__/index.tsx @@ -291,24 +291,49 @@ const combinedStyle6: StyleProp = StyleSheet.compose( null, ); -// The following use of the compose method is invalid: -// @ts-expect-error -const combinedStyle7 = StyleSheet.compose(composeImageStyle, composeTextStyle); +const page = StyleSheet.create({ + container: { + flex: 1, + padding: 24, + backgroundColor: '#fff', + }, + text: { + fontSize: 30, + color: '#000', + }, +}); -// @ts-expect-error +const lists = StyleSheet.create({ + listContainer: { + flex: 1, + backgroundColor: '#61dafb', + }, + listItem: { + fontStyle: 'italic', + fontWeight: 'bold', + }, +}); + +const container = StyleSheet.compose(page.container, lists.listContainer); +; +const text = StyleSheet.compose(page.text, lists.listItem); +; + +// The following use of the compose method is invalid: const combinedStyle8: StyleProp = StyleSheet.compose( + // @ts-expect-error composeTextStyle, composeTextStyle, ); -// @ts-expect-error const combinedStyle9: StyleProp = StyleSheet.compose( + // @ts-expect-error [composeTextStyle], null, ); -// @ts-expect-error const combinedStyle10: StyleProp = StyleSheet.compose( + // @ts-expect-error Math.random() < 0.5 ? composeTextStyle : null, null, ); diff --git a/types/index.d.ts b/types/index.d.ts index c29ececdc92b..ff9d3ec7c316 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -127,6 +127,7 @@ export * from '../Libraries/PushNotificationIOS/PushNotificationIOS'; export * from '../Libraries/ReactNative/AppRegistry'; export * from '../Libraries/ReactNative/I18nManager'; export * from '../Libraries/ReactNative/RendererProxy'; +export * from '../Libraries/ReactNative/RootTag'; export * from '../Libraries/ReactNative/UIManager'; export * from '../Libraries/ReactNative/requireNativeComponent'; export * from '../Libraries/Settings/Settings'; @@ -138,7 +139,7 @@ export * from '../Libraries/StyleSheet/StyleSheetTypes'; export * from '../Libraries/StyleSheet/processColor'; export * from '../Libraries/Text/Text'; export * from '../Libraries/TurboModule/RCTExport'; -export * from '../Libraries/TurboModule/TurboModuleRegistry'; +export * as TurboModuleRegistry from '../Libraries/TurboModule/TurboModuleRegistry'; export * from '../Libraries/Types/CoreEventTypes'; export * from '../Libraries/Utilities/Appearance'; export * from '../Libraries/Utilities/BackHandler'; diff --git a/types/public/ReactNativeTypes.d.ts b/types/public/ReactNativeTypes.d.ts index 38e00e1cc933..3acd235ac579 100644 --- a/types/public/ReactNativeTypes.d.ts +++ b/types/public/ReactNativeTypes.d.ts @@ -86,9 +86,11 @@ export interface NativeMethods { * _Can also be called with a relativeNativeNodeHandle but is deprecated._ */ measureLayout( - relativeToNativeComponentRef: HostComponent | number, + relativeToNativeComponentRef: + | React.ElementRef> + | number, onSuccess: MeasureLayoutOnSuccessCallback, - onFail: () => void /* currently unused */, + onFail?: () => void, ): void; /** diff --git a/yarn.lock b/yarn.lock index 58deebf06011..45d08919d79f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,6 +22,11 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.3.tgz#707b939793f867f5a73b2666e6d9a3396eb03151" integrity sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw== +"@babel/compat-data@^7.20.5": + version "7.20.10" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.10.tgz#9d92fa81b87542fff50e848ed585b4212c1d34ec" + integrity sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg== + "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.14.0": version "7.19.1" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.1.tgz#c8fa615c5e88e272564ace3d42fbc8b17bfeb22b" @@ -43,6 +48,27 @@ json5 "^2.2.1" semver "^6.3.0" +"@babel/core@^7.20.0": + version "7.20.12" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.12.tgz#7930db57443c6714ad216953d1356dac0eb8496d" + integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.7" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-module-transforms" "^7.20.11" + "@babel/helpers" "^7.20.7" + "@babel/parser" "^7.20.7" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.12" + "@babel/types" "^7.20.7" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.2" + semver "^6.3.0" + "@babel/eslint-parser@^7.18.2": version "7.18.2" resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.18.2.tgz#e14dee36c010edfb0153cf900c2b0815e82e3245" @@ -52,7 +78,7 @@ eslint-visitor-keys "^2.1.0" semver "^6.3.0" -"@babel/generator@^7.14.0", "@babel/generator@^7.19.0", "@babel/generator@^7.7.2": +"@babel/generator@^7.19.0": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.0.tgz#785596c06425e59334df2ccee63ab166b738419a" integrity sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg== @@ -61,6 +87,24 @@ "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" +"@babel/generator@^7.20.0", "@babel/generator@^7.7.2": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.5.tgz#cb25abee3178adf58d6814b68517c62bdbfdda95" + integrity sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA== + dependencies: + "@babel/types" "^7.20.5" + "@jridgewell/gen-mapping" "^0.3.2" + jsesc "^2.5.1" + +"@babel/generator@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.7.tgz#f8ef57c8242665c5929fe2e8d82ba75460187b4a" + integrity sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw== + dependencies: + "@babel/types" "^7.20.7" + "@jridgewell/gen-mapping" "^0.3.2" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.12.13", "@babel/helper-annotate-as-pure@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" @@ -78,6 +122,17 @@ browserslist "^4.21.3" semver "^6.3.0" +"@babel/helper-compilation-targets@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz#a6cd33e93629f5eb473b021aac05df62c4cd09bb" + integrity sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ== + dependencies: + "@babel/compat-data" "^7.20.5" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.21.3" + lru-cache "^5.1.1" + semver "^6.3.0" + "@babel/helper-create-class-features-plugin@^7.16.7", "@babel/helper-create-class-features-plugin@^7.18.6": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz#bfd6904620df4e46470bae4850d66be1054c404b" @@ -91,6 +146,20 @@ "@babel/helper-replace-supers" "^7.18.9" "@babel/helper-split-export-declaration" "^7.18.6" +"@babel/helper-create-class-features-plugin@^7.20.7": + version "7.20.12" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.12.tgz#4349b928e79be05ed2d1643b20b99bb87c503819" + integrity sha512-9OunRkbT0JQcednL0UFvbfXpAsUXiGjUk0a7sN8fUXX7Mue79cUSMjHGDRRi/Vz9vYlpIhLV5fMD5dKoMhhsNQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-member-expression-to-functions" "^7.20.7" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-replace-supers" "^7.20.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b" @@ -140,6 +209,13 @@ dependencies: "@babel/types" "^7.18.9" +"@babel/helper-member-expression-to-functions@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.20.7.tgz#a6f26e919582275a93c3aa6594756d71b0bb7f05" + integrity sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw== + dependencies: + "@babel/types" "^7.20.7" + "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.13.12", "@babel/helper-module-imports@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" @@ -161,6 +237,20 @@ "@babel/traverse" "^7.19.0" "@babel/types" "^7.19.0" +"@babel/helper-module-transforms@^7.20.11": + version "7.20.11" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz#df4c7af713c557938c50ea3ad0117a7944b2f1b0" + integrity sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.10" + "@babel/types" "^7.20.7" + "@babel/helper-optimise-call-expression@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" @@ -173,6 +263,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf" integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw== +"@babel/helper-plugin-utils@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" + integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== + "@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" @@ -194,6 +289,18 @@ "@babel/traverse" "^7.19.1" "@babel/types" "^7.19.0" +"@babel/helper-replace-supers@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz#243ecd2724d2071532b2c8ad2f0f9f083bcae331" + integrity sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-member-expression-to-functions" "^7.20.7" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.7" + "@babel/types" "^7.20.7" + "@babel/helper-simple-access@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" @@ -201,6 +308,13 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-simple-access@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" + integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== + dependencies: + "@babel/types" "^7.20.2" + "@babel/helper-skip-transparent-expression-wrappers@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz#778d87b3a758d90b471e7b9918f34a9a02eb5818" @@ -208,6 +322,13 @@ dependencies: "@babel/types" "^7.18.9" +"@babel/helper-skip-transparent-expression-wrappers@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" + integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg== + dependencies: + "@babel/types" "^7.20.0" + "@babel/helper-split-export-declaration@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" @@ -220,6 +341,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56" integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw== +"@babel/helper-string-parser@^7.19.4": + version "7.19.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" + integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== + "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": version "7.19.1" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" @@ -249,6 +375,15 @@ "@babel/traverse" "^7.19.0" "@babel/types" "^7.19.0" +"@babel/helpers@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.7.tgz#04502ff0feecc9f20ecfaad120a18f011a8e6dce" + integrity sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA== + dependencies: + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.7" + "@babel/types" "^7.20.7" + "@babel/highlight@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" @@ -263,6 +398,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.1.tgz#6f6d6c2e621aad19a92544cc217ed13f1aac5b4c" integrity sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A== +"@babel/parser@^7.20.0", "@babel/parser@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.7.tgz#66fe23b3c8569220817d5feb8b9dcdc95bb4f71b" + integrity sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg== + "@babel/plugin-proposal-async-generator-functions@^7.0.0": version "7.19.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz#34f6f5174b688529342288cd264f80c9ea9fb4a7" @@ -360,7 +500,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-syntax-flow@^7.0.0", "@babel/plugin-syntax-flow@^7.18.6", "@babel/plugin-syntax-flow@^7.2.0": +"@babel/plugin-syntax-flow@^7.0.0", "@babel/plugin-syntax-flow@^7.18.0", "@babel/plugin-syntax-flow@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.18.6.tgz#774d825256f2379d06139be0c723c4dd444f3ca1" integrity sha512-LUbR+KNTBWCUAqRG9ex5Gnzu2IOkt8jRJbHHXFT9q+L9zm7M/QQbEqXyw1n1pohYvOyWC8CjeyjrSaIwiYjK7A== @@ -444,6 +584,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-syntax-typescript@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" + integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/plugin-transform-arrow-functions@^7.0.0": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" @@ -671,6 +818,15 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-typescript" "^7.16.7" +"@babel/plugin-transform-typescript@^7.18.6": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.7.tgz#673f49499cd810ae32a1ea5f3f8fab370987e055" + integrity sha512-m3wVKEvf6SoszD8pu4NZz3PvfKRCMgk6D6d0Qi9hNnlM5M6CFS92EgF4EiHVLKbU0r/r7ty1hg7NPZwE7WRbYw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.20.7" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-typescript" "^7.20.0" + "@babel/plugin-transform-unicode-regex@^7.0.0": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" @@ -679,7 +835,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/preset-flow@^7.13.13", "@babel/preset-flow@^7.17.12": +"@babel/preset-flow@^7.13.13", "@babel/preset-flow@^7.17.12", "@babel/preset-flow@^7.18.0": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.18.6.tgz#83f7602ba566e72a9918beefafef8ef16d2810cb" integrity sha512-E7BDhL64W6OUqpuyHnSroLnqyRTcG6ZdOBl1OKI/QK/HJfplqK/S3sq1Cckx7oTodJ5yOXyfw7rEADJ6UjoQDQ== @@ -688,7 +844,7 @@ "@babel/helper-validator-option" "^7.18.6" "@babel/plugin-transform-flow-strip-types" "^7.18.6" -"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.15.0": +"@babel/preset-typescript@^7.13.0": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9" integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ== @@ -697,6 +853,15 @@ "@babel/helper-validator-option" "^7.16.7" "@babel/plugin-transform-typescript" "^7.16.7" +"@babel/preset-typescript@^7.18.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" + integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-typescript" "^7.18.6" + "@babel/register@^7.0.0", "@babel/register@^7.13.16": version "7.16.9" resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.16.9.tgz#fcfb23cfdd9ad95c9771e58183de83b513857806" @@ -732,7 +897,16 @@ "@babel/parser" "^7.18.10" "@babel/types" "^7.18.10" -"@babel/traverse@^7.13.0", "@babel/traverse@^7.14.0", "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.7.2", "@babel/traverse@^7.7.4": +"@babel/template@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" + integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + +"@babel/traverse@^7.13.0", "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.7.2", "@babel/traverse@^7.7.4": version "7.19.1" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.1.tgz#0fafe100a8c2a603b4718b1d9bf2568d1d193347" integrity sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA== @@ -748,6 +922,22 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.20.0", "@babel/traverse@^7.20.10", "@babel/traverse@^7.20.12", "@babel/traverse@^7.20.7": + version "7.20.12" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.12.tgz#7f0f787b3a67ca4475adef1f56cb94f6abd4a4b5" + integrity sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.7" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + debug "^4.1.0" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.13.12", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3": version "7.19.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.3.tgz#fc420e6bbe54880bce6779ffaf315f5e43ec9624" @@ -757,6 +947,24 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" +"@babel/types@^7.20.0", "@babel/types@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.5.tgz#e206ae370b5393d94dfd1d04cd687cace53efa84" + integrity sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + +"@babel/types@^7.20.2", "@babel/types@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f" + integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -1206,49 +1414,48 @@ optionalDependencies: npmlog "2 || ^3.1.0 || ^4.0.0" -"@react-native-community/cli-clean@^10.0.0-alpha.0": - version "10.0.0-alpha.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-10.0.0-alpha.0.tgz#602011486bb002685dec6ca374b703f4ded7bdd5" - integrity sha512-ywRMWf2xfJaIYnMSUu4rOH0QVw6OY5zCzVwSGE5p/iZ2KW7lWcPbq8axhn7VIjUDnwfLgx6AMaGgEX1gqtiFgw== +"@react-native-community/cli-clean@^10.1.1": + version "10.1.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-10.1.1.tgz#4c73ce93a63a24d70c0089d4025daac8184ff504" + integrity sha512-iNsrjzjIRv9yb5y309SWJ8NDHdwYtnCpmxZouQDyOljUdC9MwdZ4ChbtA4rwQyAwgOVfS9F/j56ML3Cslmvrxg== dependencies: - "@react-native-community/cli-tools" "^10.0.0-alpha.0" + "@react-native-community/cli-tools" "^10.1.1" chalk "^4.1.2" execa "^1.0.0" prompts "^2.4.0" -"@react-native-community/cli-config@^10.0.0-alpha.3": - version "10.0.0-alpha.3" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-10.0.0-alpha.3.tgz#4645efb7078e2c2c116e6845b17733790a93274b" - integrity sha512-j6fLNSM04xND3q50RsW+DkQbaRVJsbv4mRqPqXbS4/uPJaittJbsZGsngv+77ChWM391eZXcsPHRly6WTQucjA== +"@react-native-community/cli-config@^10.1.1": + version "10.1.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-10.1.1.tgz#08dcc5d7ca1915647dc06507ed853fe0c1488395" + integrity sha512-p4mHrjC+s/ayiNVG6T35GdEGdP6TuyBUg5plVGRJfTl8WT6LBfLYLk+fz/iETrEZ/YkhQIsQcEUQC47MqLNHog== dependencies: - "@react-native-community/cli-tools" "^10.0.0-alpha.0" + "@react-native-community/cli-tools" "^10.1.1" chalk "^4.1.2" cosmiconfig "^5.1.0" deepmerge "^3.2.0" glob "^7.1.3" joi "^17.2.1" -"@react-native-community/cli-debugger-ui@^10.0.0-alpha.0": - version "10.0.0-alpha.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-10.0.0-alpha.0.tgz#8f6711587f802a4bf6b6f81438a5653ecc010671" - integrity sha512-MdNyZWBEDbYWb7DjWI71hqImtWUDW4O39Cgf7KSU2gs6AmoeGBrP8bIwz07ikqgkEXDRqotqYNXLEAaqJvYibg== +"@react-native-community/cli-debugger-ui@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-10.0.0.tgz#4bb6d41c7e46449714dc7ba5d9f5b41ef0ea7c57" + integrity sha512-8UKLcvpSNxnUTRy8CkCl27GGLqZunQ9ncGYhSrWyKrU9SWBJJGeZwi2k2KaoJi5FvF2+cD0t8z8cU6lsq2ZZmA== dependencies: serve-static "^1.13.1" -"@react-native-community/cli-doctor@^10.0.0-alpha.3": - version "10.0.0-alpha.3" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-10.0.0-alpha.3.tgz#23c933aa7442f6f8d4956d8f75cc5a4baed87c51" - integrity sha512-i4+5wKlXxZptNeSlmdhMaey9m/ikWvSMDsShkLTeLbyi6mESalUk5PqnpFSqvhLzMbzI/FHIVGhrVPBvNGTe9Q== +"@react-native-community/cli-doctor@^10.2.7": + version "10.2.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-10.2.7.tgz#1a3ecd18a7b1e685864c9dc95e014a5f8f225f84" + integrity sha512-MejE7m+63DxfKwFSvyZGfq+72jX0RSP9SdSmDbW0Bjz2NIEE3BsE8rNay+ByFbdSLsapRPvaZv2Jof+dK2Y/yg== dependencies: - "@react-native-community/cli-config" "^10.0.0-alpha.3" - "@react-native-community/cli-platform-ios" "^10.0.0-alpha.3" - "@react-native-community/cli-tools" "^10.0.0-alpha.0" + "@react-native-community/cli-config" "^10.1.1" + "@react-native-community/cli-platform-ios" "^10.2.5" + "@react-native-community/cli-tools" "^10.1.1" chalk "^4.1.2" command-exists "^1.2.8" envinfo "^7.7.2" execa "^1.0.0" hermes-profile-transformer "^0.0.6" - ip "^1.1.5" node-stream-zip "^1.9.1" ora "^5.4.1" prompts "^2.4.0" @@ -1257,62 +1464,63 @@ sudo-prompt "^9.0.0" wcwidth "^1.0.1" -"@react-native-community/cli-hermes@^10.0.0-alpha.4": - version "10.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-10.0.0-alpha.4.tgz#d15434b2ff70655e5ac59ae38f26c3faae290c20" - integrity sha512-KhOJwOcBOuikTRcwiGxAjROtBOtMAePM2CdsC4OlvVNb2d3YY4PmQn7tDNh+pi8myYMgF8iLaxOCm/g331UK9Q== +"@react-native-community/cli-hermes@^10.2.7": + version "10.2.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-10.2.7.tgz#bcb28dfe551562a68d13c787550319f9831576b4" + integrity sha512-MULfkgeLx1fietx10pLFLmlfRh0dcfX/HABXB5Tm0BzQDXy7ofFIJ/UxH+IF55NwPKXl6aEpTbPwbgsyJxqPiA== dependencies: - "@react-native-community/cli-platform-android" "^10.0.0-alpha.4" - "@react-native-community/cli-tools" "^10.0.0-alpha.0" + "@react-native-community/cli-platform-android" "^10.2.0" + "@react-native-community/cli-tools" "^10.1.1" chalk "^4.1.2" hermes-profile-transformer "^0.0.6" - ip "^1.1.5" -"@react-native-community/cli-platform-android@10.0.0-alpha.4", "@react-native-community/cli-platform-android@^10.0.0-alpha.4": - version "10.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-10.0.0-alpha.4.tgz#6fa184a85548e682c3e21d7485cc1ef86aed0489" - integrity sha512-KW4qJx0nW09WUyFlCcdo0pLKOjz+IoqdKtpN3ya9PP2utb2bsn5U8oOxR9UQaMBZQ+Z5cgiJQ6YUfDEWBHeydw== +"@react-native-community/cli-platform-android@10.2.0", "@react-native-community/cli-platform-android@^10.2.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-10.2.0.tgz#0bc689270a5f1d9aaf9e723181d43ca4dbfffdef" + integrity sha512-CBenYwGxwFdObZTn1lgxWtMGA5ms2G/ALQhkS+XTAD7KHDrCxFF9yT/fnAjFZKM6vX/1TqGI1RflruXih3kAhw== dependencies: - "@react-native-community/cli-tools" "^10.0.0-alpha.0" + "@react-native-community/cli-tools" "^10.1.1" chalk "^4.1.2" execa "^1.0.0" glob "^7.1.3" logkitty "^0.7.1" -"@react-native-community/cli-platform-ios@10.0.0-alpha.3", "@react-native-community/cli-platform-ios@^10.0.0-alpha.3": - version "10.0.0-alpha.3" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-10.0.0-alpha.3.tgz#0291b2c143864b8d4367300f3f6c5075ab4c4945" - integrity sha512-eoezusigfUvIpBIFQblDKlP4IQqX1NqNFhi2lFCxdAeZNEw3ZzyOahe1FXf6BJgX7I3bs8O7eimc0LiPpLWrAg== +"@react-native-community/cli-platform-ios@10.2.5", "@react-native-community/cli-platform-ios@^10.2.5": + version "10.2.5" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-10.2.5.tgz#7888c74b83099885bf9e6d52170c6e663ad971ee" + integrity sha512-hq+FZZuSBK9z82GLQfzdNDl8vbFx5UlwCLFCuTtNCROgBoapFtVZQKRP2QBftYNrQZ0dLAb01gkwxagHsQCFyg== dependencies: - "@react-native-community/cli-tools" "^10.0.0-alpha.0" + "@react-native-community/cli-tools" "^10.1.1" chalk "^4.1.2" execa "^1.0.0" + fast-xml-parser "^4.0.12" glob "^7.1.3" ora "^5.4.1" -"@react-native-community/cli-plugin-metro@^10.0.0-alpha.1": - version "10.0.0-alpha.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-10.0.0-alpha.1.tgz#48e815e7e3c057a78ec10c3e7749d946b14d5a7f" - integrity sha512-GGJvPX1NWVMOBBvFh9sIgk6YwIsRno8+X4M5f1VgW7jJ9Q9sRmBa/iTbBL1EPGkO7yzsysUl67p3/UiVe5P/yg== +"@react-native-community/cli-plugin-metro@^10.2.3": + version "10.2.3" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-10.2.3.tgz#419e0155a50951c3329818fba51cb5021a7294f1" + integrity sha512-jHi2oDuTePmW4NEyVT8JEGNlIYcnFXCSV2ZMp4rnDrUk4TzzyvS3IMvDlESEmG8Kry8rvP0KSUx/hTpy37Sbkw== dependencies: - "@react-native-community/cli-server-api" "^10.0.0-alpha.0" - "@react-native-community/cli-tools" "^10.0.0-alpha.0" + "@react-native-community/cli-server-api" "^10.1.1" + "@react-native-community/cli-tools" "^10.1.1" chalk "^4.1.2" - metro "0.73.3" - metro-config "0.73.3" - metro-core "0.73.3" - metro-react-native-babel-transformer "0.73.3" - metro-resolver "0.73.3" - metro-runtime "0.73.3" + execa "^1.0.0" + metro "0.73.10" + metro-config "0.73.10" + metro-core "0.73.10" + metro-react-native-babel-transformer "0.73.10" + metro-resolver "0.73.10" + metro-runtime "0.73.10" readline "^1.3.0" -"@react-native-community/cli-server-api@^10.0.0-alpha.0": - version "10.0.0-alpha.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-10.0.0-alpha.0.tgz#046207aada81618c9be93c53066017263cf32d12" - integrity sha512-0Yw45ijtLVfBIMak9vBWr2GYXuBRCRr3CwM46Kpgj8J61NCZUA7OxjxTFViddUWAPvGMhaQn4NtnGkSHKQD4Kg== +"@react-native-community/cli-server-api@^10.1.1": + version "10.1.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-10.1.1.tgz#e382269de281bb380c2e685431364fbbb8c1cb3a" + integrity sha512-NZDo/wh4zlm8as31UEBno2bui8+ufzsZV+KN7QjEJWEM0levzBtxaD+4je0OpfhRIIkhaRm2gl/vVf7OYAzg4g== dependencies: - "@react-native-community/cli-debugger-ui" "^10.0.0-alpha.0" - "@react-native-community/cli-tools" "^10.0.0-alpha.0" + "@react-native-community/cli-debugger-ui" "^10.0.0" + "@react-native-community/cli-tools" "^10.1.1" compression "^1.7.1" connect "^3.6.5" errorhandler "^1.5.0" @@ -1321,10 +1529,10 @@ serve-static "^1.13.1" ws "^7.5.1" -"@react-native-community/cli-tools@^10.0.0-alpha.0": - version "10.0.0-alpha.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-10.0.0-alpha.0.tgz#171c40dc81dc238350bf9a5e81673d1a38c88105" - integrity sha512-fZc0UfyNwkd8rBJHzYg+uLUvIdsWwW83c2LGnpmevEfQhe1lV/f4+H+l63JGiB/TJ3ru6RmV6MvrBUgRTfqEEg== +"@react-native-community/cli-tools@^10.1.1": + version "10.1.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-10.1.1.tgz#fa66e509c0d3faa31f7bb87ed7d42ad63f368ddd" + integrity sha512-+FlwOnZBV+ailEzXjcD8afY2ogFEBeHOw/8+XXzMgPaquU2Zly9B+8W089tnnohO3yfiQiZqkQlElP423MY74g== dependencies: appdirsjs "^1.2.4" chalk "^4.1.2" @@ -1336,27 +1544,27 @@ semver "^6.3.0" shell-quote "^1.7.3" -"@react-native-community/cli-types@^10.0.0-alpha.0": - version "10.0.0-alpha.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-10.0.0-alpha.0.tgz#9b6929bd8cc6cb4204a780c963c120e0e22a1602" - integrity sha512-Mo31VhKKDIGZw9J8LfOqslKadqUvBRGYcUoTT2H17Eg08VuA2TX/M67d+zuCw5wAmJGmPYx1C4jc0S9Xe45s5Q== +"@react-native-community/cli-types@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-10.0.0.tgz#046470c75ec18f8b3bd906e54e43a6f678e01a45" + integrity sha512-31oUM6/rFBZQfSmDQsT1DX/5fjqfxg7sf2u8kTPJK7rXVya5SRpAMaCXsPAG0omsmJxXt+J9HxUi3Ic+5Ux5Iw== dependencies: joi "^17.2.1" -"@react-native-community/cli@10.0.0-alpha.5": - version "10.0.0-alpha.5" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-10.0.0-alpha.5.tgz#5e183366ea6596e60078488b9f1c915a6e8383ae" - integrity sha512-eUWMi9sJOols+5mpTAJpwH0ODuKidAJBe0LytrWc2rCL30SsrXwXTbFW39TaW4ZY9Z0QMwD9DgRikXgEdXjYNQ== - dependencies: - "@react-native-community/cli-clean" "^10.0.0-alpha.0" - "@react-native-community/cli-config" "^10.0.0-alpha.3" - "@react-native-community/cli-debugger-ui" "^10.0.0-alpha.0" - "@react-native-community/cli-doctor" "^10.0.0-alpha.3" - "@react-native-community/cli-hermes" "^10.0.0-alpha.4" - "@react-native-community/cli-plugin-metro" "^10.0.0-alpha.1" - "@react-native-community/cli-server-api" "^10.0.0-alpha.0" - "@react-native-community/cli-tools" "^10.0.0-alpha.0" - "@react-native-community/cli-types" "^10.0.0-alpha.0" +"@react-native-community/cli@10.2.7": + version "10.2.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-10.2.7.tgz#013c47827d138bcc5ac64fb5c5e792ff3350a0e8" + integrity sha512-31GrAP5PjHosXV5bkHWVnYGjAeka2gkTTsPqasJAki5RI1njB1a2WAkYFV0sn+gqc4RU1s96RELBBfT+EGzhAQ== + dependencies: + "@react-native-community/cli-clean" "^10.1.1" + "@react-native-community/cli-config" "^10.1.1" + "@react-native-community/cli-debugger-ui" "^10.0.0" + "@react-native-community/cli-doctor" "^10.2.7" + "@react-native-community/cli-hermes" "^10.2.7" + "@react-native-community/cli-plugin-metro" "^10.2.3" + "@react-native-community/cli-server-api" "^10.1.1" + "@react-native-community/cli-tools" "^10.1.1" + "@react-native-community/cli-types" "^10.0.0" chalk "^4.1.2" commander "^9.4.1" execa "^1.0.0" @@ -1395,10 +1603,10 @@ resolved "https://registry.yarnpkg.com/@react-native/assets/-/assets-1.0.0.tgz#c6f9bf63d274bafc8e970628de24986b30a55c8e" integrity sha512-KrwSpS1tKI70wuKl68DwJZYEvXktDHdZMG0k2AXD/rJVSlB23/X2CB2cutVR0HwNMJIal9HOUOBB2rVfa6UGtQ== -"@react-native/eslint-plugin-specs@^0.71.1": - version "0.71.1" - resolved "https://registry.yarnpkg.com/@react-native/eslint-plugin-specs/-/eslint-plugin-specs-0.71.1.tgz#07b1395edeeda74349d28b214c31f871956b325d" - integrity sha512-rnn8U6vecXLAD3XldnzPlsfeCq2j1O8CIU7mQc95jBkNTRPoLePdPeghHwCuAZQevkFjY9FpqMJ7SwU7P40rhw== +"@react-native/eslint-plugin-specs@^0.71.2": + version "0.71.2" + resolved "https://registry.yarnpkg.com/@react-native/eslint-plugin-specs/-/eslint-plugin-specs-0.71.2.tgz#5a73e873a92aff3d49edd20352561e33de828d98" + integrity sha512-lxWzcuLymWolWaqwaeni+QAe+P59zV2UqhbjFWe2vpiNCrcVv+2MKpSdsNrissvlZJ5UrirS5jhiNomPSbikVg== dependencies: "@babel/core" "^7.14.0" "@babel/eslint-parser" "^7.18.2" @@ -1407,7 +1615,7 @@ flow-parser "^0.185.0" make-dir "^2.1.0" pirates "^4.0.1" - react-native-codegen "*" + react-native-codegen "0.71.6" source-map-support "0.5.0" "@react-native/normalize-color@*", "@react-native/normalize-color@2.1.0": @@ -1920,21 +2128,6 @@ aria-query@^4.2.2: "@babel/runtime" "^7.10.2" "@babel/runtime-corejs3" "^7.10.2" -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - array-includes@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb" @@ -1951,11 +2144,6 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - array.prototype.flatmap@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz#a7e8ed4225f4788a70cd910abcf0791e76a5534f" @@ -1983,20 +2171,15 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - ast-types-flow@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= -ast-types@0.14.2: - version "0.14.2" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.14.2.tgz#600b882df8583e3cd4f2df5fa20fa83759d4bdfd" - integrity sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA== +ast-types@0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.15.2.tgz#39ae4809393c4b16df751ee563411423e85fb49d" + integrity sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg== dependencies: tslib "^2.0.1" @@ -2020,11 +2203,6 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -atob@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -2203,19 +2381,6 @@ base64-js@^1.1.2, base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -2240,22 +2405,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - braces@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -2308,21 +2457,6 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -2449,16 +2583,6 @@ clang-format@^1.8.0: glob "^7.0.0" resolve "^1.1.6" -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -2523,14 +2647,6 @@ collect-v8-coverage@^1.0.0: resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -2592,11 +2708,6 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -component-emitter@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= - compressible@~2.0.14: version "2.0.15" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.15.tgz#857a9ab0a7e5a07d8d837ed43fe2defff64fe212" @@ -2654,11 +2765,6 @@ convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: dependencies: safe-buffer "~5.1.1" -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - core-js-compat@^3.9.1: version "3.25.5" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.25.5.tgz#0016e8158c904f7b059486639e6e82116eafa7d9" @@ -2739,7 +2845,7 @@ dayjs@^1.8.15: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.15.tgz#7121bc04e6a7f2621ed6db566be4a8aaf8c3913e" integrity sha512-HYHCI1nohG52B45vCQg8Re3hNDZbMroWPkhz50yaX7Lu0ATyjGsTdoYZBpjED9ar6chqTx2dmSmM8A51mojnAg== -debug@2.6.9, debug@^2.2.0, debug@^2.3.3: +debug@2.6.9, debug@^2.2.0: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -2758,11 +2864,6 @@ decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= -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" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" @@ -2798,28 +2899,6 @@ define-properties@^1.1.3, define-properties@^1.1.4: has-property-descriptors "^1.0.0" object-keys "^1.1.1" -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -2840,10 +2919,10 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= -deprecated-react-native-prop-types@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-2.3.0.tgz#c10c6ee75ff2b6de94bb127f142b814e6e08d9ab" - integrity sha512-pWD0voFtNYxrVqvBMYf5gq3NA2GCpfodS1yNynTPc93AYA/KEMGeWDqqeUB6R2Z9ZofVhks2aeJXiuQqKNpesA== +deprecated-react-native-prop-types@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-3.0.1.tgz#a275f84cd8519cd1665e8df3c99e9067d57a23ec" + integrity sha512-J0jCJcsk4hMlIb7xwOZKLfMpuJn6l8UtrPEzzQV5ewz5gvKNYakhBuq9h2rWX7YwHHJZFhU5W8ye7dB9oN8VcQ== dependencies: "@react-native/normalize-color" "*" invariant "*" @@ -3312,19 +3391,6 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - expect@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/expect/-/expect-29.2.1.tgz#25752d0df92d3daa5188dc8804de1f30759658cf" @@ -3336,21 +3402,6 @@ expect@^29.2.1: jest-message-util "^29.2.1" jest-util "^29.2.1" -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -3365,20 +3416,6 @@ external-editor@^3.0.3: iconv-lite "^0.4.24" tmp "^0.0.33" -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -3420,6 +3457,13 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fast-xml-parser@^4.0.12: + version "4.1.2" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.1.2.tgz#5a98c18238d28a57bbdfa9fe4cda01211fff8f4a" + integrity sha512-CDYeykkle1LiA/uqQyNwYpFbyF6Axec6YapmpUP+/RHWIoR1zKjocdvNaTsxCxZzQ6v9MLXaSYm9Qq0thv0DHg== + dependencies: + strnum "^1.0.5" + fastq@^1.6.0: version "1.13.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" @@ -3448,16 +3492,6 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -3533,11 +3567,6 @@ flow-parser@0.*, flow-parser@^0.185.0: resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.185.0.tgz#56bde60805bad19b2934ebfc50c9485e5c5424f9" integrity sha512-VWpXjEbQbIGQvB6CyWwx56wMioGZ6w2s8qJlFiuE3S7D8O+xE5t988i1u2TGFO5TLSzQPUhfIOzPpLYA93H9Jg== -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -3552,13 +3581,6 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -3569,15 +3591,6 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== -fs-extra@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950" - integrity sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA= - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - klaw "^1.0.0" - fs-extra@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" @@ -3706,11 +3719,6 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -3768,7 +3776,7 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== @@ -3842,37 +3850,6 @@ has-unicode@^2.0.0: resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -4053,25 +4030,6 @@ invariant@*, invariant@^2.2.4: dependencies: loose-envify "^1.0.0" -ip@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -4092,11 +4050,6 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-callable@^1.1.4, is-callable@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" @@ -4109,60 +4062,16 @@ is-core-module@^2.2.0, is-core-module@^2.5.0, is-core-module@^2.9.0: dependencies: has "^1.0.3" -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - is-directory@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -4214,19 +4123,12 @@ is-number-object@^1.0.4: dependencies: has-tostringtag "^1.0.0" -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-plain-object@^2.0.3, is-plain-object@^2.0.4: +is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== @@ -4289,17 +4191,12 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - is-wsl@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= -isarray@1.0.0, isarray@~1.0.0: +isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -4309,14 +4206,7 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: +isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= @@ -4854,15 +4744,20 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -jsc-android@^250230.2.1: - version "250230.2.1" - resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250230.2.1.tgz#3790313a970586a03ab0ad47defbc84df54f1b83" - integrity sha512-KmxeBlRjwoqCnBBKGsihFtvsBHyUFlBxJPK4FzeYcIuBfdjv6jFys44JITAgSTbQD+vIdwMEfyZklsuQX0yI1Q== +jsc-android@^250231.0.0: + version "250231.0.0" + resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250231.0.0.tgz#91720f8df382a108872fa4b3f558f33ba5e95262" + integrity sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw== + +jsc-safe-url@^0.2.2: + version "0.2.4" + resolved "https://registry.yarnpkg.com/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz#141c14fbb43791e88d5dc64e85a374575a83477a" + integrity sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q== -jscodeshift@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.13.1.tgz#69bfe51e54c831296380585c6d9e733512aecdef" - integrity sha512-lGyiEbGOvmMRKgWk4vf+lUrCWO/8YR8sUR3FKF1Cq5fovjZDlIcw3Hu5ppLHAnEXshVffvaM0eyuY/AbOeYpnQ== +jscodeshift@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.14.0.tgz#7542e6715d6d2e8bde0b4e883f0ccea358b46881" + integrity sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA== dependencies: "@babel/core" "^7.13.16" "@babel/parser" "^7.13.16" @@ -4877,10 +4772,10 @@ jscodeshift@^0.13.1: chalk "^4.1.2" flow-parser "0.*" graceful-fs "^4.2.4" - micromatch "^3.1.10" + micromatch "^4.0.4" neo-async "^2.5.0" node-dir "^0.1.17" - recast "^0.20.4" + recast "^0.21.0" temp "^0.8.4" write-file-atomic "^2.3.0" @@ -4936,12 +4831,10 @@ json5@^2.2.1: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== -jsonfile@^2.1.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= - optionalDependencies: - graceful-fs "^4.1.6" +json5@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonfile@^4.0.0: version "4.0.0" @@ -4973,37 +4866,11 @@ jsprim@^1.2.2: array-includes "^3.1.5" object.assign "^4.1.2" -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: +kind-of@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -klaw@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= - optionalDependencies: - graceful-fs "^4.1.9" - kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -5115,6 +4982,13 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -5144,18 +5018,6 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - memoize-one@^5.0.0: version "5.2.1" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" @@ -5171,69 +5033,69 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -metro-babel-register@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.73.3.tgz#fc5601bbe166efb59d063d8b330de062475c257b" - integrity sha512-uuNoggz/tr5FrG5lbzMHMO5wN0L3BZi/AYC/8oPTbiIJEavZ5ugVaePOoTU04c67KMGgNLIbJESZpLZn/ttN7A== +metro-babel-register@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.73.10.tgz#ec559ee155693991c075fe5e9589451fe037a2d0" + integrity sha512-ozZQhlV7g4aIoNV+P15KkxoG6bgL9loKfmVbu6BTCXgOUe5Vh10Fr014khoKJ2ztQ4aLvacXud/pefibmR1PXg== dependencies: - "@babel/core" "^7.14.0" + "@babel/core" "^7.20.0" "@babel/plugin-proposal-nullish-coalescing-operator" "^7.0.0" "@babel/plugin-proposal-optional-chaining" "^7.0.0" "@babel/plugin-syntax-class-properties" "^7.0.0" "@babel/plugin-transform-flow-strip-types" "^7.0.0" "@babel/plugin-transform-modules-commonjs" "^7.0.0" - "@babel/preset-typescript" "^7.15.0" + "@babel/preset-typescript" "^7.18.0" "@babel/register" "^7.0.0" babel-plugin-replace-ts-export-assignment "^0.0.2" escape-string-regexp "^1.0.5" -metro-babel-transformer@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.73.3.tgz#13e2e5d7981049f9b4babd6a97e40c8decdf19a8" - integrity sha512-vNNFMxsZn1JasZEk9RlC84KQiei1ecZ3BmRsNCipWN7YMC/SbV8QLMdqhgF8XIfKnZnS6Z2RCFGPYPxu7/9sJA== +metro-babel-transformer@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.73.10.tgz#b27732fa3869f397246ee8ecf03b64622ab738c1" + integrity sha512-Yv2myTSnpzt/lTyurLvqYbBkytvUJcLHN8XD3t7W6rGiLTQPzmf1zypHQLphvcAXtCWBOXFtH7KLOSi2/qMg+A== dependencies: - "@babel/core" "^7.14.0" + "@babel/core" "^7.20.0" hermes-parser "0.8.0" - metro-source-map "0.73.3" + metro-source-map "0.73.10" nullthrows "^1.1.1" -metro-cache-key@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.73.3.tgz#eabd107ba6274aa9c629a807c9801c914fc1091a" - integrity sha512-LsP8aZr/LJuw428hNAQHKJkL7N3RvYcHcG6kbUXUfRqwOsoE4q6C8kXebtm+5+fbNduNVzHjEBIQM2uFUctMow== +metro-cache-key@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.73.10.tgz#8d63591187d295b62a80aed64a87864b1e9d67a2" + integrity sha512-JMVDl/EREDiUW//cIcUzRjKSwE2AFxVWk47cFBer+KA4ohXIG2CQPEquT56hOw1Y1s6gKNxxs1OlAOEsubrFjw== -metro-cache@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.73.3.tgz#172f4a5c88738643f1b11b7593c2edec6882bef6" - integrity sha512-nRLxn1B8J4LxFZo02OCFryalqaJKW1ddAteS5zdSmsJLdaDwvKH+J73Rp/XOR5Puu1A05A7BF4/aYKzwY/HU4A== +metro-cache@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.73.10.tgz#02e9cb7c1e42aab5268d2ecce35ad8f2c08891de" + integrity sha512-wPGlQZpdVlM404m7MxJqJ+hTReDr5epvfPbt2LerUAHY9RN99w61FeeAe25BMZBwgUgDtAsfGlJ51MBHg8MAqw== dependencies: - metro-core "0.73.3" + metro-core "0.73.10" rimraf "^3.0.2" -metro-config@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.73.3.tgz#52fbb1b4ecf638fe16d2227535795609e4faf396" - integrity sha512-k1OSBNVe/i+Vm1IPA35qt1eD/3yjtEA0qfzvLeTmuvarE+twBpXupJViKqtfqvo6rldk0VoYX/UlnqzkaJ1hIg== +metro-config@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.73.10.tgz#a9ec3d0a1290369e3f46c467a4c4f6dd43acc223" + integrity sha512-wIlybd1Z9I8K2KcStTiJxTB7OK529dxFgogNpKCTU/3DxkgAASqSkgXnZP6kVyqjh5EOWAKFe5U6IPic7kXDdQ== dependencies: cosmiconfig "^5.0.5" jest-validate "^26.5.2" - metro "0.73.3" - metro-cache "0.73.3" - metro-core "0.73.3" - metro-runtime "0.73.3" + metro "0.73.10" + metro-cache "0.73.10" + metro-core "0.73.10" + metro-runtime "0.73.10" -metro-core@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.73.3.tgz#dc79fa4abe6a266a4d3b4a2352864f4cb6440298" - integrity sha512-wsW2XyWU9QtWnNMrUIDnoTIKDHBvKa/uupY+91gYV9l6glKboP1F8AD0mpzNwFqOXtx48jm7iDa7xzEY25bgcA== +metro-core@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.73.10.tgz#feb3c228aa8c0dde71d8e4cef614cc3a1dc3bbd7" + integrity sha512-5uYkajIxKyL6W45iz/ftNnYPe1l92CvF2QJeon1CHsMXkEiOJxEjo41l+iSnO/YodBGrmMCyupSO4wOQGUc0lw== dependencies: lodash.throttle "^4.1.1" - metro-resolver "0.73.3" + metro-resolver "0.73.10" -metro-file-map@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.73.3.tgz#e23b2e4d0cab5271372707ef80c91ad1f3512714" - integrity sha512-t6JrJH4YO8a1Qf+THZ4FCW1NRZ2qSUQb7p42T1Ea1w3C18OnfOg19xZUAiGQ/46FN7ROeZDdE8LLJDPT0s4fzQ== +metro-file-map@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.73.10.tgz#55bd906fb7c1bef8e1a31df4b29a3ef4b49f0b5a" + integrity sha512-XOMWAybeaXyD6zmVZPnoCCL2oO3rp4ta76oUlqWP0skBzhFxVtkE/UtDwApEMUY361JeBBago647gnKiARs+1g== dependencies: abort-controller "^3.0.0" anymatch "^3.0.3" @@ -5251,46 +5113,46 @@ metro-file-map@0.73.3: optionalDependencies: fsevents "^2.3.2" -metro-hermes-compiler@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-hermes-compiler/-/metro-hermes-compiler-0.73.3.tgz#017c200ec0d2585eed19314612fa7a599a935f06" - integrity sha512-9r+dXiIt2k2uYmaNgeJoLJNZ2FnO6ok7pLppnMZIwFUEvOiFpvOBlBIpqOCEzzRh3gLinEtZ0SmRPhDstI+Iog== +metro-hermes-compiler@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-hermes-compiler/-/metro-hermes-compiler-0.73.10.tgz#4525a7835c803a5d0b3b05c6619202e2273d630f" + integrity sha512-rTRWEzkVrwtQLiYkOXhSdsKkIObnL+Jqo+IXHI7VEK2aSLWRAbtGNqECBs44kbOUypDYTFFE+WLtoqvUWqYkWg== -metro-inspector-proxy@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.73.3.tgz#6ac40f1217fb2ef7fa1331cffe730036dee70b36" - integrity sha512-I3Eixd28uamjbKtO6LB7jlGgdwt8zxBrRznp3qMWL8WZU6gu9TU/SAJa1TnABOK0VwdPmz161fWL/eHBEKZCrg== +metro-inspector-proxy@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.73.10.tgz#752fed2ab88199c9dcc3369c3d59da6c5b954a51" + integrity sha512-CEEvocYc5xCCZBtGSIggMCiRiXTrnBbh8pmjKQqm9TtJZALeOGyt5pXUaEkKGnhrXETrexsg6yIbsQHhEvVfvQ== dependencies: connect "^3.6.5" debug "^2.2.0" ws "^7.5.1" yargs "^17.5.1" -metro-memory-fs@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-memory-fs/-/metro-memory-fs-0.73.3.tgz#cd5feba53b77f35c31e530de763c856aa5685d13" - integrity sha512-uE/LLrf+LqsLUunWjSmrnHpdqaO1rTBAN/HExQ16TLwwAEovUF/UKS2CqTp4VEKGwfD/458c6YXL45xxLDOp3g== +metro-memory-fs@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-memory-fs/-/metro-memory-fs-0.73.10.tgz#77b695e5e67a3b4bf2cb032b7653cb36c6223591" + integrity sha512-5WHqgTFYPqYl6dVgpJ7JvKo86In3NYw0W1SGvvfHbzXIb8aXDZAqffpD1mT08JQ0oVwcTEXpP4qNL9KLvUZWrw== -metro-minify-terser@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.73.3.tgz#e0d8164a42067bcf8dfe8a066545d080af213bf5" - integrity sha512-EDA+G7WM9ACtlvIc735u002UNedTIKBXx4RaIFFnLbp8Z+0csrTnFY0hsasxwkFR1KcL42TppLiY0L+iO5TuJw== +metro-minify-terser@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.73.10.tgz#557eab3a512b90b7779350ff5d25a215c4dbe61f" + integrity sha512-uG7TSKQ/i0p9kM1qXrwbmY3v+6BrMItsOcEXcSP8Z+68bb+t9HeVK0T/hIfUu1v1PEnonhkhfzVsaP8QyTd5lQ== dependencies: terser "^5.15.0" -metro-minify-uglify@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.73.3.tgz#9e3438e73208a21e085891d5cdf60c80dd97bbb7" - integrity sha512-ksI9tiXYwFaNPMyuArzD1x5Fz3CNzlI7dL0uqEriDMdVXk5/7FDwi6hV+pAefTxJlTVt9NStDfKyQyj3x8CxJQ== +metro-minify-uglify@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.73.10.tgz#4de79056d502479733854c90f2075374353ea154" + integrity sha512-eocnSeJKnLz/UoYntVFhCJffED7SLSgbCHgNvI6ju6hFb6EFHGJT9OLbkJWeXaWBWD3Zw5mYLS8GGqGn/CHZPA== dependencies: uglify-es "^3.1.9" -metro-react-native-babel-preset@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.73.3.tgz#c4a0fcae395894ec85e235ec75de88d56f64e291" - integrity sha512-JJ22lR4CVaw3OKTz9YAY/ckymr3DbO+qy/x5kLaF4g0LcvZmhhKfDK+fml577AZU6sKb/CTd0SBwt+VAz+Hu7Q== +metro-react-native-babel-preset@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.73.10.tgz#304b24bb391537d2c987732cc0a9774be227d3f6" + integrity sha512-1/dnH4EHwFb2RKEKx34vVDpUS3urt2WEeR8FYim+ogqALg4sTpG7yeQPxWpbgKATezt4rNfqAANpIyH19MS4BQ== dependencies: - "@babel/core" "^7.14.0" + "@babel/core" "^7.20.0" "@babel/plugin-proposal-async-generator-functions" "^7.0.0" "@babel/plugin-proposal-class-properties" "^7.0.0" "@babel/plugin-proposal-export-default-from" "^7.0.0" @@ -5300,7 +5162,7 @@ metro-react-native-babel-preset@0.73.3: "@babel/plugin-proposal-optional-chaining" "^7.0.0" "@babel/plugin-syntax-dynamic-import" "^7.0.0" "@babel/plugin-syntax-export-default-from" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.2.0" + "@babel/plugin-syntax-flow" "^7.18.0" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" "@babel/plugin-syntax-optional-chaining" "^7.0.0" "@babel/plugin-transform-arrow-functions" "^7.0.0" @@ -5329,102 +5191,102 @@ metro-react-native-babel-preset@0.73.3: "@babel/template" "^7.0.0" react-refresh "^0.4.0" -metro-react-native-babel-transformer@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.73.3.tgz#a521e5f559cec4ec9b878087e606afbb8e92db2b" - integrity sha512-9cCdN2S+skTx1IT/A+UHteN80eOmgU0ir3E/wWybUbV/zhWtHQjbxBnB+bEbFNRe9Jmk73Ga9pWkCFqO8txwYw== +metro-react-native-babel-transformer@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.73.10.tgz#4e20a9ce131b873cda0b5a44d3eb4002134a64b8" + integrity sha512-4G/upwqKdmKEjmsNa92/NEgsOxUWOygBVs+FXWfXWKgybrmcjh3NoqdRYrROo9ZRA/sB9Y/ZXKVkWOGKHtGzgg== dependencies: - "@babel/core" "^7.14.0" + "@babel/core" "^7.20.0" babel-preset-fbjs "^3.4.0" hermes-parser "0.8.0" - metro-babel-transformer "0.73.3" - metro-react-native-babel-preset "0.73.3" - metro-source-map "0.73.3" + metro-babel-transformer "0.73.10" + metro-react-native-babel-preset "0.73.10" + metro-source-map "0.73.10" nullthrows "^1.1.1" -metro-resolver@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.73.3.tgz#dc21ca03c8aeb0bc05fe4e8c318791e213bde9d7" - integrity sha512-XbiZ22MaFFchaErNfqeW9ZPPRpiQEIylhtlja9/5QzNgAcAWbfIGY0Ok39XyVyWjX4Ab8YAwQUeCqyO48ojzZQ== +metro-resolver@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.73.10.tgz#c39a3bd8d33e5d78cb256110d29707d8d49ed0be" + integrity sha512-HeXbs+0wjakaaVQ5BI7eT7uqxlZTc9rnyw6cdBWWMgUWB++KpoI0Ge7Hi6eQAOoVAzXC3m26mPFYLejpzTWjng== dependencies: absolute-path "^0.0.0" -metro-runtime@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.73.3.tgz#39fde3484342bf4eb8a3ec9bce8bc519e128e1ea" - integrity sha512-ywNq9exXtCiBA/vcmiyuI+sBR3tVMQIkvrmcHJ+cOWf5kl/vBS2FbYimESlMwZKjzH7l07LrQcvAvTn215N9bw== +metro-runtime@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.73.10.tgz#c3de19d17e75ffe1a145778d99422e7ffc208768" + integrity sha512-EpVKm4eN0Fgx2PEWpJ5NiMArV8zVoOin866jIIvzFLpmkZz1UEqgjf2JAfUJnjgv3fjSV3JqeGG2vZCaGQBTow== dependencies: "@babel/runtime" "^7.0.0" react-refresh "^0.4.0" -metro-source-map@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.73.3.tgz#6eaf99ccd98b46f8afd8cb5cbb5e360dcce3836a" - integrity sha512-zOm8Ha0hWiJhI52IcMibdNIS6O3YK6qUnQ7dgZOGvnEWRTfzYlX08yFXwMg91GIdXzxHJE43opcPwSE1RDvoGQ== +metro-source-map@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.73.10.tgz#28e09a28f1a2f7a4f8d0845b845cbed74e2f48f9" + integrity sha512-NAGv14701p/YaFZ76KzyPkacBw/QlEJF1f8elfs23N1tC33YyKLDKvPAzFJiYqjdcFvuuuDCA8JCXd2TgLxNPw== dependencies: - "@babel/traverse" "^7.14.0" - "@babel/types" "^7.0.0" + "@babel/traverse" "^7.20.0" + "@babel/types" "^7.20.0" invariant "^2.2.4" - metro-symbolicate "0.73.3" + metro-symbolicate "0.73.10" nullthrows "^1.1.1" - ob1 "0.73.3" + ob1 "0.73.10" source-map "^0.5.6" vlq "^1.0.0" -metro-symbolicate@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.73.3.tgz#2641dd63fc8ef348a3c2bb0fa2f82f1a75d8b96a" - integrity sha512-gOjoQcUFuDl3YKO0D7rcLEDIw331LM+CiKgIzQlZmx7uZimORnt9xf/8P/Ued0y77q8ColuJAVDqp/JirqRfEw== +metro-symbolicate@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.73.10.tgz#7853a9a8fbfd615a5c9db698fffc685441ac880f" + integrity sha512-PmCe3TOe1c/NVwMlB+B17me951kfkB3Wve5RqJn+ErPAj93od1nxicp6OJe7JT4QBRnpUP8p9tw2sHKqceIzkA== dependencies: invariant "^2.2.4" - metro-source-map "0.73.3" + metro-source-map "0.73.10" nullthrows "^1.1.1" source-map "^0.5.6" through2 "^2.0.1" vlq "^1.0.0" -metro-transform-plugins@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.73.3.tgz#cd620058531758665b55427fcb06a3d259086e6c" - integrity sha512-zes8OxN07nLcPq/BD7FgFusoVlVYbmQpdW290SRCsnnQK7ul4amzm9clygX54WYjYm8aHXSEmVrZtd/80Q+rZw== +metro-transform-plugins@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.73.10.tgz#1b762330cbbedb6c18438edc3d76b063c88882af" + integrity sha512-D4AgD3Vsrac+4YksaPmxs/0ocT67bvwTkFSIgWWeDvWwIG0U1iHzTS9f8Bvb4PITnXryDoFtjI6OWF7uOpGxpA== dependencies: - "@babel/core" "^7.14.0" - "@babel/generator" "^7.14.0" + "@babel/core" "^7.20.0" + "@babel/generator" "^7.20.0" "@babel/template" "^7.0.0" - "@babel/traverse" "^7.14.0" + "@babel/traverse" "^7.20.0" nullthrows "^1.1.1" -metro-transform-worker@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.73.3.tgz#093735e55e2c3564f560e188ff999d9752fc253d" - integrity sha512-oF/hFX8Oj/PLuacpzWwYTgf0k0vSxI/nlWBPQkAUuW7QYOv7w9WRWRNczl8fbYohr8LU7CbwuQ662DRzzQDrAQ== +metro-transform-worker@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.73.10.tgz#bb401dbd7b10a6fe443a5f7970cba38425efece0" + integrity sha512-IySvVubudFxahxOljWtP0QIMMpgUrCP0bW16cz2Enof0PdumwmR7uU3dTbNq6S+XTzuMHR+076aIe4VhPAWsIQ== dependencies: - "@babel/core" "^7.14.0" - "@babel/generator" "^7.14.0" - "@babel/parser" "^7.14.0" - "@babel/types" "^7.0.0" + "@babel/core" "^7.20.0" + "@babel/generator" "^7.20.0" + "@babel/parser" "^7.20.0" + "@babel/types" "^7.20.0" babel-preset-fbjs "^3.4.0" - metro "0.73.3" - metro-babel-transformer "0.73.3" - metro-cache "0.73.3" - metro-cache-key "0.73.3" - metro-hermes-compiler "0.73.3" - metro-source-map "0.73.3" - metro-transform-plugins "0.73.3" + metro "0.73.10" + metro-babel-transformer "0.73.10" + metro-cache "0.73.10" + metro-cache-key "0.73.10" + metro-hermes-compiler "0.73.10" + metro-source-map "0.73.10" + metro-transform-plugins "0.73.10" nullthrows "^1.1.1" -metro@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/metro/-/metro-0.73.3.tgz#d1e3bd247468e0293b644bca408265e725d686f9" - integrity sha512-AHjeWI05YyTPaMNAXW4kUDLVr2MPs6DeawofS6CxiWGh2P9aVosC3GPJmXF2fGRW7MKdGvGWIDqUlWJUw8M0CA== +metro@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/metro/-/metro-0.73.10.tgz#d9a0efb1e403e3aee5cf5140e0a96a7220c23901" + integrity sha512-J2gBhNHFtc/Z48ysF0B/bfTwUwaRDLjNv7egfhQCc+934dpXcjJG2KZFeuybF+CvA9vo4QUi56G2U+RSAJ5tsA== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/core" "^7.14.0" - "@babel/generator" "^7.14.0" - "@babel/parser" "^7.14.0" + "@babel/core" "^7.20.0" + "@babel/generator" "^7.20.0" + "@babel/parser" "^7.20.0" "@babel/template" "^7.0.0" - "@babel/traverse" "^7.14.0" - "@babel/types" "^7.0.0" + "@babel/traverse" "^7.20.0" + "@babel/types" "^7.20.0" absolute-path "^0.0.0" accepts "^1.3.7" async "^3.2.2" @@ -5434,30 +5296,30 @@ metro@0.73.3: debug "^2.2.0" denodeify "^1.2.1" error-stack-parser "^2.0.6" - fs-extra "^1.0.0" graceful-fs "^4.2.4" hermes-parser "0.8.0" image-size "^0.6.0" invariant "^2.2.4" jest-worker "^27.2.0" + jsc-safe-url "^0.2.2" lodash.throttle "^4.1.1" - metro-babel-transformer "0.73.3" - metro-cache "0.73.3" - metro-cache-key "0.73.3" - metro-config "0.73.3" - metro-core "0.73.3" - metro-file-map "0.73.3" - metro-hermes-compiler "0.73.3" - metro-inspector-proxy "0.73.3" - metro-minify-terser "0.73.3" - metro-minify-uglify "0.73.3" - metro-react-native-babel-preset "0.73.3" - metro-resolver "0.73.3" - metro-runtime "0.73.3" - metro-source-map "0.73.3" - metro-symbolicate "0.73.3" - metro-transform-plugins "0.73.3" - metro-transform-worker "0.73.3" + metro-babel-transformer "0.73.10" + metro-cache "0.73.10" + metro-cache-key "0.73.10" + metro-config "0.73.10" + metro-core "0.73.10" + metro-file-map "0.73.10" + metro-hermes-compiler "0.73.10" + metro-inspector-proxy "0.73.10" + metro-minify-terser "0.73.10" + metro-minify-uglify "0.73.10" + metro-react-native-babel-preset "0.73.10" + metro-resolver "0.73.10" + metro-runtime "0.73.10" + metro-source-map "0.73.10" + metro-symbolicate "0.73.10" + metro-transform-plugins "0.73.10" + metro-transform-worker "0.73.10" mime-types "^2.1.27" node-fetch "^2.2.0" nullthrows "^1.1.1" @@ -5470,25 +5332,6 @@ metro@0.73.3: ws "^7.5.1" yargs "^17.5.1" -micromatch@^3.1.10: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - micromatch@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" @@ -5551,14 +5394,6 @@ minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - "mkdirp@>=0.5 0", mkdirp@^0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" @@ -5591,23 +5426,6 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - natural-compare-lite@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" @@ -5730,25 +5548,16 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -ob1@0.73.3: - version "0.73.3" - resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.73.3.tgz#36e796fa6fbea4696063cf711fe53505be7bc9a2" - integrity sha512-KpCFQty/eGriUsF3tD4FybV2vsWNzID3Thq/3o0VzXn+rtcQdRk1r6USM5PddWaFjxZqbVXjlr6u7DJGhPz9xw== +ob1@0.73.10: + version "0.73.10" + resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.73.10.tgz#bf0a2e8922bb8687ddca82327c5cf209414a1bd4" + integrity sha512-aO6EYC+QRRCkZxVJhCWhLKgVjhNuD6Gu1riGjxrIm89CqLsmKgxzYDDEsktmKsoDeRdWGQM5EdMzXDl5xcVfsw== object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - object-inspect@^1.12.0, object-inspect@^1.9.0: version "1.12.2" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" @@ -5759,13 +5568,6 @@ object-keys@^1.1.1: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - object.assign@^4.1.0, object.assign@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" @@ -5802,13 +5604,6 @@ object.hasown@^1.1.1: define-properties "^1.1.4" es-abstract "^1.19.5" -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - object.values@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" @@ -5963,11 +5758,6 @@ parsimmon@^1.13.0: resolved "https://registry.yarnpkg.com/parsimmon/-/parsimmon-1.18.1.tgz#d8dd9c28745647d02fc6566f217690897eed7709" integrity sha512-u7p959wLfGAhJpSDJVYXoyMCXWYwHia78HhRBWqk7AIbxdmlrfdp5wX0l3xv/iTSH5HvhN9K7o26hwwpgS5Nmw== -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -6042,11 +5832,6 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -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" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -6178,30 +5963,20 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-native-codegen@*: - version "0.72.0" - resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.72.0.tgz#b130e9798bbbc70a75e293b432438e65bda9d3c5" - integrity sha512-FoM//DIikIgdTurw+3EJyM4enZSKDdEswxhvWa/6eiRNzCegPFVLgk7WppGfJ084R3jEE2Q1e0IHu+nhff6LeA== - dependencies: - "@babel/parser" "^7.14.0" - flow-parser "^0.185.0" - jscodeshift "^0.13.1" - nullthrows "^1.1.1" - -react-native-codegen@^0.71.3: - version "0.71.3" - resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.71.3.tgz#75fbc591819050791319ebdb9fe341ee4df5c288" - integrity sha512-5AvdHVU1sAaXg05i0dG664ZTaCaIFaY1znV5vNsj+wUu6MGxNEUNbDKk9dxKUkkxOyk2KZOK5uhzWL0p5H5yZQ== +react-native-codegen@0.71.6, react-native-codegen@^0.71.6: + version "0.71.6" + resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.71.6.tgz#481a610c3af9135b09e1e031da032e7270e0cc1b" + integrity sha512-e5pR4VldIhEaFctfSAEgxbng0uG4gjBQxAHes3EKLdosH/Av90pQfSe9IDVdFIngvNPzt8Y14pNjrtqov/yNIg== dependencies: "@babel/parser" "^7.14.0" flow-parser "^0.185.0" - jscodeshift "^0.13.1" + jscodeshift "^0.14.0" nullthrows "^1.1.1" -react-native-gradle-plugin@^0.71.9: - version "0.71.9" - resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.9.tgz#c269938fddc4ca8418d3927a35b3344e9308773e" - integrity sha512-hv/xt/aRzzlA7asGCIebvVBwjsxPMaXXGrKsk9W19CInUpShTFSBvBitViNfpw/hOQ7OHa6SxWpG2OZf5yZ21w== +react-native-gradle-plugin@^0.71.19: + version "0.71.19" + resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.19.tgz#3379e28341fcd189bc1f4691cefc84c1a4d7d232" + integrity sha512-1dVk9NwhoyKHCSxcrM6vY6cxmojeATsBobDicX0ZKr7DgUF2cBQRTKsimQFvzH8XhOVXyH8p4HyDSZNIFI8OlQ== react-refresh@^0.4.0: version "0.4.0" @@ -6259,12 +6034,12 @@ readline@^1.3.0: resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c" integrity sha1-xYDXfvLPyHUrEySYBg3JeTp6wBw= -recast@^0.20.4: - version "0.20.5" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.20.5.tgz#8e2c6c96827a1b339c634dd232957d230553ceae" - integrity sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ== +recast@^0.21.0: + version "0.21.5" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.21.5.tgz#e8cd22bb51bcd6130e54f87955d33a2b2e57b495" + integrity sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg== dependencies: - ast-types "0.14.2" + ast-types "0.15.2" esprima "~4.0.0" source-map "~0.6.1" tslib "^2.0.1" @@ -6300,14 +6075,6 @@ regenerator-transform@^0.15.0: dependencies: "@babel/runtime" "^7.8.4" -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - regexp.prototype.flags@^1.4.1, regexp.prototype.flags@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" @@ -6346,16 +6113,6 @@ regjsparser@^0.9.1: dependencies: jsesc "~0.5.0" -repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" @@ -6414,11 +6171,6 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - resolve.exports@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" @@ -6449,11 +6201,6 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" @@ -6519,13 +6266,6 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -6594,16 +6334,6 @@ set-blocking@^2.0.0, set-blocking@~2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" @@ -6697,47 +6427,6 @@ slide@^1.1.6: resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" integrity sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw== -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== - dependencies: - atob "^2.1.1" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - source-map-support@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.0.tgz#2018a7ad2bdf8faf2691e5fddab26bed5a2bacab" @@ -6761,11 +6450,6 @@ source-map-support@^0.5.16, source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= - source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -6807,13 +6491,6 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779" integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA== -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -6858,14 +6535,6 @@ stacktrace-parser@^0.1.3: resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.4.tgz#01397922e5f62ecf30845522c95c4fe1d25e7d4e" integrity sha1-ATl5IuX2Ls8whFUiyVxP4dJefU4= -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - "statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" @@ -7004,6 +6673,11 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + sudo-prompt@^9.0.0: version "9.1.1" resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.1.1.tgz#73853d729770392caec029e2470db9c221754db0" @@ -7144,21 +6818,6 @@ to-fast-properties@^2.0.0: resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -7166,16 +6825,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -7317,16 +6966,6 @@ unicode-property-aliases-ecmascript@^2.0.0: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -7337,14 +6976,6 @@ unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - update-browserslist-db@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz#2924d3927367a38d5c555413a7ce138fc95fcb18" @@ -7360,21 +6991,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - use-sync-external-store@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.0.0.tgz#d98f4a9c2e73d0f958e7e2d2c2bfb5f618cbd8fd" integrity sha512-AFVsxg5GkFg8GDcxnl+Z0lMAz9rE8DGJCc28qnBuQF7lac57B5smLcT37aXpXIIPz75rW4g3eXHPjhHwdGskOw== -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -7579,6 +7200,11 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"