From f0f73e644481f4b53cb0c1e4003f1f8e935ff67e Mon Sep 17 00:00:00 2001 From: mdaj06 Date: Thu, 2 Sep 2021 00:30:32 +0530 Subject: [PATCH 01/18] removed defaultProps and replaced it with a default value where necessary --- .../DrawerAndroid/DrawerLayoutAndroid.android.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index deebd5102e05a3..5a3a7c74c55c75 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -161,11 +161,6 @@ class DrawerLayoutAndroid extends React.Component { return {Left: 'left', Right: 'right'}; } - static defaultProps: {| - drawerBackgroundColor: 'white', - |} = { - drawerBackgroundColor: 'white', - }; _nativeRef = React.createRef< React.ElementRef, @@ -189,7 +184,7 @@ class DrawerLayoutAndroid extends React.Component { styles.drawerSubview, { width: this.props.drawerWidth, - backgroundColor: this.props.drawerBackgroundColor, + backgroundColor: this.props.drawerBackgroundColor || 'white', }, ]} collapsable={false}> From 75d45c851922b9672ed801893be61f91c4b3eda3 Mon Sep 17 00:00:00 2001 From: mdaj06 Date: Thu, 2 Sep 2021 00:47:46 +0530 Subject: [PATCH 02/18] removed drawerBackgroundColor from Props since we have removed it from as a static field --- .../Components/DrawerAndroid/DrawerLayoutAndroid.android.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index 5a3a7c74c55c75..49fa63f6a47ff5 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -56,8 +56,6 @@ type Props = $ReadOnly<{| * ); * ``` */ - drawerBackgroundColor: ColorValue, - /** * Specifies the side of the screen from which the drawer will slide in. */ From 6a9a2cd6aa5a24125dbb0b370542dd9728940faf Mon Sep 17 00:00:00 2001 From: mdaj06 Date: Thu, 2 Sep 2021 01:16:03 +0530 Subject: [PATCH 03/18] updated the props list with a default value --- .../Components/DrawerAndroid/DrawerLayoutAndroid.android.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index 49fa63f6a47ff5..b7125ccdc7cc22 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -55,7 +55,9 @@ type Props = $ReadOnly<{| * * ); * ``` - */ + + drawerBackgroundColor: ColorValue, +*/ /** * Specifies the side of the screen from which the drawer will slide in. */ @@ -168,6 +170,7 @@ class DrawerLayoutAndroid extends React.Component { render(): React.Node { const { + drawerBackgroundColor = "white", onDrawerStateChanged, renderNavigationView, onDrawerOpen, From fe133f626dbbaa0efc9febad51ef9e41a1c96a7d Mon Sep 17 00:00:00 2001 From: mdaj06 Date: Thu, 2 Sep 2021 01:30:13 +0530 Subject: [PATCH 04/18] reinstated the prop value --- .../Components/DrawerAndroid/DrawerLayoutAndroid.android.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index b7125ccdc7cc22..c434e41a2c0dd2 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -55,9 +55,9 @@ type Props = $ReadOnly<{| * * ); * ``` - + */ drawerBackgroundColor: ColorValue, -*/ + /** * Specifies the side of the screen from which the drawer will slide in. */ @@ -170,7 +170,7 @@ class DrawerLayoutAndroid extends React.Component { render(): React.Node { const { - drawerBackgroundColor = "white", + drawerBackgroundColor = 'white', onDrawerStateChanged, renderNavigationView, onDrawerOpen, From b2e7f7ff0d244b45687ddb15b7c5936331e840e1 Mon Sep 17 00:00:00 2001 From: mdaj06 Date: Thu, 2 Sep 2021 01:34:56 +0530 Subject: [PATCH 05/18] deleted the Prop value instead of commenting it --- .../Components/DrawerAndroid/DrawerLayoutAndroid.android.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index c434e41a2c0dd2..cec8f15c725721 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -56,8 +56,7 @@ type Props = $ReadOnly<{| * ); * ``` */ - drawerBackgroundColor: ColorValue, - + /** * Specifies the side of the screen from which the drawer will slide in. */ From b535543e20c7bb217a7a51a4ba776ca6e0790280 Mon Sep 17 00:00:00 2001 From: mdaj06 Date: Thu, 2 Sep 2021 02:13:02 +0530 Subject: [PATCH 06/18] added drawerBackgroundColor to type prop --- .../Components/DrawerAndroid/DrawerLayoutAndroid.android.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index cec8f15c725721..6c4c84c5dbe853 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -56,7 +56,8 @@ type Props = $ReadOnly<{| * ); * ``` */ - + drawerBackgroundColor: ColorValue, + /** * Specifies the side of the screen from which the drawer will slide in. */ From ceaeb39994ad18eb11be08e36e4d6cb935712fdd Mon Sep 17 00:00:00 2001 From: mdaj06 Date: Thu, 2 Sep 2021 03:01:51 +0530 Subject: [PATCH 07/18] removed background colour initialization --- .../Components/DrawerAndroid/DrawerLayoutAndroid.android.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index 6c4c84c5dbe853..b85991383e81f0 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -170,7 +170,6 @@ class DrawerLayoutAndroid extends React.Component { render(): React.Node { const { - drawerBackgroundColor = 'white', onDrawerStateChanged, renderNavigationView, onDrawerOpen, From a9e3153973d6665389f3df5a39121b277df3215b Mon Sep 17 00:00:00 2001 From: mdaj06 Date: Thu, 2 Sep 2021 10:51:02 +0530 Subject: [PATCH 08/18] removed usage of this.props.drawerBackgroundColor and added a const drawerBackgroundColor --- .../Components/DrawerAndroid/DrawerLayoutAndroid.android.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index b85991383e81f0..05df9835ff2616 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -170,6 +170,7 @@ class DrawerLayoutAndroid extends React.Component { render(): React.Node { const { + drawerBackgroundColor = 'white', onDrawerStateChanged, renderNavigationView, onDrawerOpen, @@ -184,7 +185,7 @@ class DrawerLayoutAndroid extends React.Component { styles.drawerSubview, { width: this.props.drawerWidth, - backgroundColor: this.props.drawerBackgroundColor || 'white', + backgroundColor: drawerBackgroundColor, }, ]} collapsable={false}> From c1e1655415e4384ee00d5c0f0f9982bc783f4668 Mon Sep 17 00:00:00 2001 From: mdaj06 Date: Thu, 2 Sep 2021 16:29:58 +0530 Subject: [PATCH 09/18] added drawerBackgroundColor as a prop to AndroidDrawerLayoutNativeComponent since the native component expects it --- .../DrawerLayoutAndroid.android.js | 1 + gradlew.bat | 178 +++++++++--------- .../react-native-codegen/android/gradlew.bat | 178 +++++++++--------- template/android/gradlew.bat | 178 +++++++++--------- 4 files changed, 268 insertions(+), 267 deletions(-) diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index 05df9835ff2616..e1d290e8f41707 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -216,6 +216,7 @@ class DrawerLayoutAndroid extends React.Component { NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/packages/react-native-codegen/android/gradlew.bat b/packages/react-native-codegen/android/gradlew.bat index ac1b06f93825db..107acd32c4e687 100644 --- a/packages/react-native-codegen/android/gradlew.bat +++ b/packages/react-native-codegen/android/gradlew.bat @@ -1,89 +1,89 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/template/android/gradlew.bat b/template/android/gradlew.bat index ac1b06f93825db..107acd32c4e687 100644 --- a/template/android/gradlew.bat +++ b/template/android/gradlew.bat @@ -1,89 +1,89 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega From 4f89ce056fc0124a83c9311bc3297b96d8318523 Mon Sep 17 00:00:00 2001 From: mdaj06 Date: Thu, 2 Sep 2021 16:49:25 +0530 Subject: [PATCH 10/18] removed the drawerbackgroundColor from Props since we are setting it as a default inside render() --- .../DrawerAndroid/DrawerLayoutAndroid.android.js | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index e1d290e8f41707..b278d71fb5651e 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -45,19 +45,7 @@ type Props = $ReadOnly<{| */ keyboardDismissMode?: ?('none' | 'on-drag'), - /** - * Specifies the background color of the drawer. The default value is white. - * If you want to set the opacity of the drawer, use rgba. Example: - * - * ``` - * return ( - * - * - * ); - * ``` - */ - drawerBackgroundColor: ColorValue, - + /** * Specifies the side of the screen from which the drawer will slide in. */ @@ -216,7 +204,7 @@ class DrawerLayoutAndroid extends React.Component { Date: Thu, 2 Sep 2021 17:06:51 +0530 Subject: [PATCH 11/18] refactored to follow eslint rules as suggested by the code analyzer --- .../Components/DrawerAndroid/DrawerLayoutAndroid.android.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index b278d71fb5651e..3681c5f201a0c9 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -45,7 +45,6 @@ type Props = $ReadOnly<{| */ keyboardDismissMode?: ?('none' | 'on-drag'), - /** * Specifies the side of the screen from which the drawer will slide in. */ From 6514b675ec5decd535d7df2bd51a544d2ecebedc Mon Sep 17 00:00:00 2001 From: mdaj06 Date: Thu, 2 Sep 2021 18:33:18 +0530 Subject: [PATCH 12/18] updated snapshots tests for DrawerAndroid to match the removal of defaultProps --- .../__tests__/__snapshots__/DrawerAndroid-test.js.snap | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Libraries/Components/DrawerAndroid/__tests__/__snapshots__/DrawerAndroid-test.js.snap b/Libraries/Components/DrawerAndroid/__tests__/__snapshots__/DrawerAndroid-test.js.snap index 00893319c5c904..3bded8ec3a6f37 100644 --- a/Libraries/Components/DrawerAndroid/__tests__/__snapshots__/DrawerAndroid-test.js.snap +++ b/Libraries/Components/DrawerAndroid/__tests__/__snapshots__/DrawerAndroid-test.js.snap @@ -2,7 +2,6 @@ exports[` should render as expected: should deep render when mocked (please verify output manually) 1`] = ` should render as expected: should deep render w exports[` should render as expected: should deep render when not mocked (please verify output manually) 1`] = ` should render as expected: should deep render w exports[` should render as expected: should shallow render as when mocked 1`] = ` should render as expected: should shallow rende exports[` should render as expected: should shallow render as when not mocked 1`] = ` Date: Thu, 2 Sep 2021 18:57:12 +0530 Subject: [PATCH 13/18] updated snapshots tests for DrawerAndroid to match the removal of defaultProps drawerBackgroundColor --- .../__tests__/__snapshots__/DrawerAndroid-test.js.snap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Libraries/Components/DrawerAndroid/__tests__/__snapshots__/DrawerAndroid-test.js.snap b/Libraries/Components/DrawerAndroid/__tests__/__snapshots__/DrawerAndroid-test.js.snap index 3bded8ec3a6f37..19a7303e92abbf 100644 --- a/Libraries/Components/DrawerAndroid/__tests__/__snapshots__/DrawerAndroid-test.js.snap +++ b/Libraries/Components/DrawerAndroid/__tests__/__snapshots__/DrawerAndroid-test.js.snap @@ -2,6 +2,7 @@ exports[` should render as expected: should deep render when mocked (please verify output manually) 1`] = ` should render as expected: should deep render w exports[` should render as expected: should deep render when not mocked (please verify output manually) 1`] = ` Date: Thu, 2 Sep 2021 22:16:40 +0530 Subject: [PATCH 14/18] Delete gradlew.bat --- .../react-native-codegen/android/gradlew.bat | 89 ------------------- 1 file changed, 89 deletions(-) delete mode 100644 packages/react-native-codegen/android/gradlew.bat diff --git a/packages/react-native-codegen/android/gradlew.bat b/packages/react-native-codegen/android/gradlew.bat deleted file mode 100644 index 107acd32c4e687..00000000000000 --- a/packages/react-native-codegen/android/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega From 40a6c11a7043fb95d8e39dd55300326781ef4188 Mon Sep 17 00:00:00 2001 From: Meghnath Pillay Date: Thu, 2 Sep 2021 22:17:03 +0530 Subject: [PATCH 15/18] Delete gradlew.bat --- template/android/gradlew.bat | 89 ------------------------------------ 1 file changed, 89 deletions(-) delete mode 100644 template/android/gradlew.bat diff --git a/template/android/gradlew.bat b/template/android/gradlew.bat deleted file mode 100644 index 107acd32c4e687..00000000000000 --- a/template/android/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega From 8767dff798b2973a712fd0ec5839516a96a1e24c Mon Sep 17 00:00:00 2001 From: Meghnath Pillay Date: Thu, 2 Sep 2021 22:17:24 +0530 Subject: [PATCH 16/18] Delete gradlew.bat --- gradlew.bat | 89 ----------------------------------------------------- 1 file changed, 89 deletions(-) delete mode 100644 gradlew.bat diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index 107acd32c4e687..00000000000000 --- a/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega From 2daa3a65cddbe4ac234deb77bb7043cde9296b1d Mon Sep 17 00:00:00 2001 From: mdaj06 Date: Tue, 7 Sep 2021 02:06:55 +0530 Subject: [PATCH 17/18] remerged main to get all the upstream changes --- .flowconfig | 2 +- .flowconfig.android | 2 +- .gitignore | 3 + BUCK | 1 + CODE_OF_CONDUCT.md | 4 +- Libraries/Animated/NativeAnimatedHelper.js | 2 +- .../DatePicker/DatePickerIOS.ios.js | 9 +- .../__tests__/DatePickerIOS-test.js | 14 + .../__snapshots__/DatePickerIOS-test.js.snap | 48 ++ .../DatePickerAndroid.android.js | 87 --- .../DatePickerAndroid.ios.js | 30 - .../DatePickerAndroidTypes.js | 30 - Libraries/Components/ScrollView/ScrollView.js | 13 +- .../ScrollView/ScrollViewStickyHeader.js | 520 +++++++++--------- .../Components/View/ViewAccessibility.js | 1 + Libraries/Core/ExceptionsManager.js | 4 +- Libraries/Core/polyfillPromise.js | 2 +- Libraries/Core/setUpBatchedBridge.js | 2 +- Libraries/Core/setUpGlobals.js | 2 + Libraries/Core/setUpTimers.js | 10 +- Libraries/Image/Image.ios.js | 6 + Libraries/Image/ImageBackground.js | 4 +- Libraries/Image/ImageSource.js | 2 +- .../Nodes/RCTPropsAnimatedNode.m | 3 - .../NativePermissionsAndroid.js | 3 +- .../PermissionsAndroid/PermissionsAndroid.js | 2 + Libraries/Pressability/Pressability.js | 1 + .../PressabilityPerformanceEventEmitter.js | 1 + Libraries/ReactNative/PaperUIManager.js | 1 + Libraries/Renderer/REVISION | 2 +- .../implementations/ReactFabric-dev.fb.js | 176 ++---- .../implementations/ReactFabric-prod.fb.js | 14 +- .../ReactFabric-profiling.fb.js | 14 +- .../ReactNativeRenderer-dev.fb.js | 170 ++---- .../ReactNativeRenderer-prod.fb.js | 12 +- .../ReactNativeRenderer-profiling.fb.js | 12 +- .../__tests__/normalizeColor-test.js | 8 +- Libraries/StyleSheet/normalizeColor.js | 4 +- Libraries/Text/TextProps.js | 8 +- Libraries/TurboModule/TurboModuleRegistry.js | 2 +- Libraries/UTFSequence.js | 2 +- Libraries/Utilities/HMRClient.js | 16 +- Libraries/Utilities/MatrixMath.js | 2 +- Libraries/Utilities/deprecatedPropType.js | 4 +- .../emitter/_EventSubscriptionVendor.js | 2 +- React/Base/RCTBridge+Private.h | 8 + React/Base/RCTBridge.m | 5 + React/Base/RCTBundleURLProvider.h | 25 + React/Base/RCTBundleURLProvider.mm | 86 ++- React/Base/RCTConstants.h | 6 + React/Base/RCTConstants.m | 15 + React/Base/RCTCxxConvert.h | 2 +- React/Base/RCTEventDispatcherProtocol.h | 2 + React/Base/RCTRootView.h | 15 + React/Base/RCTRootView.m | 15 + .../RCTSurfaceHostingProxyRootView.h | 3 + .../RCTSurfaceHostingProxyRootView.mm | 16 + React/CoreModules/RCTDevSettings.mm | 10 +- React/CoreModules/RCTEventDispatcher.mm | 5 + React/CoreModules/RCTLogBox.mm | 24 +- React/CxxBridge/RCTCxxBridge.mm | 5 + React/DevSupport/RCTPackagerConnection.mm | 17 +- .../FBReactNativeSpec.podspec | 14 +- .../ScrollView/RCTScrollViewComponentView.mm | 9 + .../TextInput/RCTTextInputComponentView.mm | 23 +- .../View/RCTViewComponentView.mm | 18 + React/Fabric/Mounting/RCTMountingManager.mm | 16 +- React/Fabric/RCTConversions.h | 3 + React/Fabric/RCTSurfacePresenter.mm | 7 +- .../Fabric/RCTSurfacePresenterBridgeAdapter.h | 2 +- React/Fabric/RCTSurfaceRegistry.h | 2 +- React/Fabric/Surface/RCTFabricSurface.mm | 5 + React/Profiler/RCTProfileTrampoline-arm.S | 2 +- React/Profiler/RCTProfileTrampoline-arm64.S | 4 +- React/Views/RCTFont.mm | 92 ++-- React/Views/RCTViewManager.m | 6 +- ReactAndroid/Android-prebuilt.mk | 8 + ReactAndroid/build.gradle | 12 +- ReactAndroid/src/androidTest/buck-runner/BUCK | 1 + .../java/com/facebook/react/testing/rule/BUCK | 7 +- .../java/com/facebook/react/tests/BUCK | 1 - .../react/tests/DatePickerDialogTestCase.java | 172 ------ .../java/com/facebook/react/tests/core/BUCK | 7 +- .../js/DatePickerDialogTestModule.js | 45 -- ReactAndroid/src/androidTest/js/TestBundle.js | 7 - .../hermes/instrumentation/Android.mk | 4 +- .../facebook/hermes/reactexecutor/Android.mk | 8 +- .../reactexecutor/HermesExecutorFactory.java | 2 +- .../hermes/reactexecutor/RuntimeConfig.java | 6 - .../src/main/java/com/facebook/react/BUCK | 1 - .../facebook/react/ReactInstanceManager.java | 115 ++-- .../react/ReactInstanceManagerBuilder.java | 12 + .../com/facebook/react/ReactNativeHost.java | 6 + .../react/bridge/CatalystInstance.java | 4 + .../react/bridge/CatalystInstanceImpl.java | 4 + .../react/bridge/ReactCxxErrorHandler.java | 39 ++ .../react/bridge/RuntimeScheduler.java | 21 + .../facebook/react/common/mapbuffer/jni/BUCK | 2 +- .../react/config/ReactFeatureFlags.java | 6 + .../com/facebook/react/fabric/Binding.java | 5 + .../react/fabric/FabricJSIModuleProvider.java | 1 + .../com/facebook/react/fabric/jni/Android.mk | 3 +- .../java/com/facebook/react/fabric/jni/BUCK | 2 +- .../com/facebook/react/fabric/jni/Binding.cpp | 14 + .../com/facebook/react/fabric/jni/Binding.h | 2 + .../fabric/mounting/MountItemDispatcher.java | 10 +- .../mounting/SurfaceMountingManager.java | 19 + .../com/facebook/react/jscexecutor/Android.mk | 4 +- .../react/modules/blob/jni/Android.mk | 4 +- .../facebook/react/modules/datepicker/BUCK | 27 - .../datepicker/DatePickerDialogFragment.java | 137 ----- .../datepicker/DatePickerDialogModule.java | 153 ------ .../DismissableDatePickerDialog.java | 117 ---- .../com/facebook/react/runtimescheduler/BUCK | 20 - .../RuntimeSchedulerManager.java | 39 -- .../react/runtimescheduler/jni/Android.mk | 34 -- .../facebook/react/runtimescheduler/jni/BUCK | 35 -- .../react/runtimescheduler/jni/OnLoad.cpp | 15 - .../jni/RuntimeSchedulerManager.cpp | 46 -- .../jni/RuntimeSchedulerManager.h | 40 -- .../main/java/com/facebook/react/shell/BUCK | 1 - .../react/shell/MainReactPackage.java | 5 - .../com/facebook/react/uimanager/jni/BUCK | 2 +- .../text/ReactTextAnchorViewManager.java | 4 - .../react/views/text/ReactTextShadowNode.java | 21 + .../react/views/text/ReactTextView.java | 8 + .../react/views/text/TextAttributeProps.java | 21 +- .../react/views/text/TextLayoutManager.java | 31 +- .../text/TextLayoutManagerMapBuffer.java | 30 +- .../ReactEditTextInputConnectionWrapper.java | 3 + .../src/main/jni/react/jni/Android.mk | 5 +- ReactAndroid/src/main/jni/react/jni/BUCK | 6 +- .../jni/react/jni/CatalystInstanceImpl.cpp | 29 + .../main/jni/react/jni/CatalystInstanceImpl.h | 4 + .../jni/react/jni/JReactCxxErrorHandler.cpp | 18 + .../jni/react/jni/JReactCxxErrorHandler.h | 25 + .../main/jni/react/jni/JRuntimeScheduler.cpp | 22 + .../main/jni/react/jni/JRuntimeScheduler.h | 30 + .../main/third-party/android/androidx/BUCK | 45 +- .../third-party/java/testing-support-lib/BUCK | 31 -- ReactCommon/hermes/executor/Android.mk | 8 +- ReactCommon/hermes/inspector/Android.mk | 3 +- ReactCommon/jsi/Android.mk | 2 +- ReactCommon/jsi/BUCK | 2 - ReactCommon/jsiexecutor/Android.mk | 4 +- .../react/nativemodule/core/Android.mk | 4 +- .../samples/platform/android/Android.mk | 2 +- .../animations/LayoutAnimationDriver.cpp | 1 - .../LayoutAnimationKeyFrameManager.cpp | 49 +- .../attributedstring/AttributedString.h | 1 - .../attributedstring/ParagraphAttributes.cpp | 10 +- .../attributedstring/ParagraphAttributes.h | 14 +- .../attributedstring/TextAttributes.h | 2 +- .../renderer/attributedstring/conversions.h | 65 ++- .../renderer/attributedstring/primitives.h | 20 +- .../renderer/components/image/Android.mk | 2 +- .../renderer/components/inputaccessory/BUCK | 2 +- .../components/legacyviewmanagerinterop/BUCK | 2 +- ...cyViewManagerInteropComponentDescriptor.mm | 1 - .../renderer/components/safeareaview/BUCK | 2 +- .../renderer/components/scrollview/Android.mk | 2 +- .../react/renderer/components/text/Android.mk | 2 +- .../components/text/RawTextShadowNode.h | 6 - .../renderer/components/text/TextShadowNode.h | 6 - .../renderer/components/textinput/Android.mk | 2 +- .../textinput/iostextinput/TextInputProps.cpp | 14 +- .../textinput/iostextinput/TextInputProps.h | 5 +- .../textinput/iostextinput/primitives.h | 6 + .../textinput/iostextinput/propsConversions.h | 33 ++ .../components/unimplementedview/Android.mk | 2 +- .../components/view/AccessibilityPrimitives.h | 21 + .../components/view/AccessibilityProps.cpp | 6 + .../components/view/AccessibilityProps.h | 1 + .../react/renderer/components/view/Android.mk | 2 +- .../components/view/ViewPropsInterpolation.h | 7 - .../renderer/components/view/ViewShadowNode.h | 2 +- .../view/YogaLayoutableShadowNode.cpp | 56 +- .../view/YogaLayoutableShadowNode.h | 6 - .../view/accessibilityPropsConversions.h | 43 ++ ReactCommon/react/renderer/core/Android.mk | 2 +- .../core/ConcreteComponentDescriptor.h | 13 - .../react/renderer/core/ConcreteShadowNode.h | 1 + .../renderer/core/LayoutableShadowNode.h | 6 - ReactCommon/react/renderer/core/Props.h | 1 + .../react/renderer/core/PropsParserContext.h | 5 +- .../react/renderer/core/RawPropsKey.cpp | 12 +- .../react/renderer/core/ReactPrimitives.h | 2 - .../react/renderer/core/ShadowNodeFamily.h | 1 + ReactCommon/react/renderer/mapbuffer/BUCK | 4 +- .../react/renderer/mounting/Android.mk | 2 +- .../renderer/runtimescheduler/Android.mk | 2 +- .../react/renderer/runtimescheduler/BUCK | 1 - .../runtimescheduler/RuntimeScheduler.cpp | 6 +- .../runtimescheduler/RuntimeScheduler.h | 6 +- .../RuntimeSchedulerBinding.cpp | 7 +- .../RuntimeSchedulerBinding.h | 6 +- .../runtimescheduler/RuntimeSchedulerClock.h | 6 +- .../runtimescheduler/SchedulerPriority.h | 7 +- .../react/renderer/runtimescheduler/Task.cpp | 6 +- .../react/renderer/runtimescheduler/Task.h | 6 +- .../renderer/runtimescheduler/primitives.h | 6 +- .../react/renderer/scheduler/SurfaceHandler.h | 8 +- .../platform/ios/RCTAttributedTextUtils.h | 2 + .../platform/ios/RCTAttributedTextUtils.mm | 22 + ReactCommon/react/test_utils/BUCK | 3 + .../react/test_utils/MockSurfaceHandler.h | 25 + ReactCommon/react/utils/ContextContainer.h | 27 - flow/HermesInternalType.js | 114 ++++ flow/global.js | 47 ++ gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- index.js | 25 +- jest/setup.js | 1 + package.json | 8 +- .../index.js | 1 + .../package.json | 8 +- .../normalize-color/__tests__/base-test.js | 129 ----- .../__tests__/normalizeColor-test.js | 131 +++++ packages/normalize-color/base.js | 387 ------------- packages/normalize-color/index.js | 378 +++++++++++++ packages/normalize-color/index.js.flow | 10 + packages/normalize-color/package.json | 4 +- packages/polyfills/package.json | 2 +- packages/react-native-codegen/BUCK | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../generators/modules/GenerateModuleJniH.js | 4 +- .../GenerateModuleJniH-test.js.snap | 24 +- .../build.gradle.kts | 5 +- .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59536 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + packages/react-native-gradle-plugin/gradlew | 185 +++++++ .../settings.gradle.kts | 12 +- .../facebook/react/AndroidConfiguration.kt | 4 +- .../com/facebook/react/ReactAppPlugin.kt | 16 +- .../com/facebook/react/TaskConfiguration.kt | 136 +++-- .../react/tasks/BundleJsAndAssetsTask.kt | 11 +- .../facebook/react/tasks/HermesBinaryTask.kt | 12 +- .../ScreenshotManager.podspec | 39 ++ packages/rn-tester/Podfile | 4 + packages/rn-tester/Podfile.lock | 10 +- packages/rn-tester/README.md | 9 +- packages/rn-tester/RNTester/AppDelegate.mm | 1 + packages/rn-tester/RNTester/Info.plist | 8 + .../RCTRootViewIntegrationTests.m | 6 +- .../RNTesterPods.xcodeproj/project.pbxproj | 5 +- .../RCTBundleURLProviderTests.m | 2 +- .../RNTesterUnitTests/RCTFontTests.m | 2 +- packages/rn-tester/android/app/build.gradle | 1 + .../js/components/ListExampleShared.js | 4 +- .../Accessibility/AccessibilityExample.js | 72 +++ .../js/examples/FlatList/FlatListExample.js | 23 +- .../js/examples/Linking/LinkingExample.js | 23 +- .../js/examples/Modal/ModalOnShow.js | 2 +- .../js/examples/Text/TextExample.android.js | 76 ++- react.gradle | 30 +- repo-config/package.json | 4 +- scripts/bump-oss-version.js | 4 + scripts/generate-specs-cli.js | 4 +- scripts/generate-specs.sh | 97 ++-- scripts/react-native-xcode.sh | 2 +- scripts/react_native_pods.rb | 97 +++- scripts/test-manual-e2e.sh | 47 +- settings.gradle.kts | 7 + template/_flowconfig | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../ios/HelloWorld.xcodeproj/project.pbxproj | 4 +- template/ios/Podfile | 1 + yarn.lock | 35 +- 268 files changed, 3314 insertions(+), 2866 deletions(-) delete mode 100644 Libraries/Components/DatePickerAndroid/DatePickerAndroid.android.js delete mode 100644 Libraries/Components/DatePickerAndroid/DatePickerAndroid.ios.js delete mode 100644 Libraries/Components/DatePickerAndroid/DatePickerAndroidTypes.js delete mode 100644 ReactAndroid/src/androidTest/java/com/facebook/react/tests/DatePickerDialogTestCase.java delete mode 100644 ReactAndroid/src/androidTest/js/DatePickerDialogTestModule.js create mode 100644 ReactAndroid/src/main/java/com/facebook/react/bridge/ReactCxxErrorHandler.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/bridge/RuntimeScheduler.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogModule.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DismissableDatePickerDialog.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/BUCK delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/RuntimeSchedulerManager.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/Android.mk delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/BUCK delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/OnLoad.cpp delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.cpp delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.h create mode 100644 ReactAndroid/src/main/jni/react/jni/JReactCxxErrorHandler.cpp create mode 100644 ReactAndroid/src/main/jni/react/jni/JReactCxxErrorHandler.h create mode 100644 ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.cpp create mode 100644 ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.h create mode 100644 ReactCommon/react/test_utils/MockSurfaceHandler.h create mode 100644 flow/HermesInternalType.js delete mode 100644 packages/normalize-color/__tests__/base-test.js create mode 100644 packages/normalize-color/__tests__/normalizeColor-test.js delete mode 100644 packages/normalize-color/base.js create mode 100644 packages/normalize-color/index.js create mode 100644 packages/normalize-color/index.js.flow create mode 100644 packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.jar create mode 100644 packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.properties create mode 100755 packages/react-native-gradle-plugin/gradlew rename ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerMode.java => packages/react-native-gradle-plugin/settings.gradle.kts (58%) create mode 100644 packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec diff --git a/.flowconfig b/.flowconfig index 83fd5987898b6c..e6ad16c7bcc1bf 100644 --- a/.flowconfig +++ b/.flowconfig @@ -71,4 +71,4 @@ untyped-import untyped-type-import [version] -^0.157.0 +^0.159.0 diff --git a/.flowconfig.android b/.flowconfig.android index ba94fee6c7334a..53110b81ff775e 100644 --- a/.flowconfig.android +++ b/.flowconfig.android @@ -71,4 +71,4 @@ untyped-import untyped-type-import [version] -^0.157.0 +^0.159.0 diff --git a/.gitignore b/.gitignore index de6bcc3d45d957..747bb762be951a 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,8 @@ project.xcworkspace /ReactAndroid/gradle/ /ReactAndroid/gradlew /ReactAndroid/gradlew.bat +/template/android/app/build/ +/template/android/build/ # Buck .buckd @@ -103,6 +105,7 @@ package-lock.json /React/FBReactNativeSpec/FBReactNativeSpec /packages/react-native-codegen/lib /ReactCommon/react/renderer/components/rncore/ +/packages/rn-tester/NativeModuleExample/ScreenshotManagerSpec # Visual studio .vscode diff --git a/BUCK b/BUCK index b315295c974f53..8c53560e33308f 100644 --- a/BUCK +++ b/BUCK @@ -376,6 +376,7 @@ rn_xplat_cxx_library2( "$SDKROOT/System/Library/Frameworks/CFNetwork.framework", "$SDKROOT/System/Library/Frameworks/CoreGraphics.framework", "$SDKROOT/System/Library/Frameworks/CoreLocation.framework", + "$SDKROOT/System/Library/Frameworks/CoreText.framework", "$SDKROOT/System/Library/Frameworks/Foundation.framework", "$SDKROOT/System/Library/Frameworks/MapKit.framework", "$SDKROOT/System/Library/Frameworks/QuartzCore.framework", diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index d1abc700d28d83..3a44dc2513d1b9 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -67,8 +67,8 @@ members of the project's leadership. ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, +available at https://www.contributor-covenant.org/version/2/1/code_of_conduct/ [homepage]: https://www.contributor-covenant.org diff --git a/Libraries/Animated/NativeAnimatedHelper.js b/Libraries/Animated/NativeAnimatedHelper.js index 297b53c68c7b97..6bac8cb1fbd88a 100644 --- a/Libraries/Animated/NativeAnimatedHelper.js +++ b/Libraries/Animated/NativeAnimatedHelper.js @@ -24,7 +24,7 @@ import invariant from 'invariant'; // TODO T69437152 @petetheheat - Delete this fork when Fabric ships to 100%. const NativeAnimatedModule = - Platform.OS === 'ios' && global.RN$Bridgeless + Platform.OS === 'ios' && global.RN$Bridgeless === true ? NativeAnimatedTurboModule : NativeAnimatedNonTurboModule; diff --git a/Libraries/Components/DatePicker/DatePickerIOS.ios.js b/Libraries/Components/DatePicker/DatePickerIOS.ios.js index 30cc13ad55f0b0..8295e3aeded250 100644 --- a/Libraries/Components/DatePicker/DatePickerIOS.ios.js +++ b/Libraries/Components/DatePicker/DatePickerIOS.ios.js @@ -117,10 +117,6 @@ type Props = $ReadOnly<{| * source of truth. */ class DatePickerIOS extends React.Component { - static DefaultProps: {|mode: $TEMPORARY$string<'datetime'>|} = { - mode: 'datetime', - }; - _picker: ?React.ElementRef = null; componentDidUpdate() { @@ -142,6 +138,7 @@ class DatePickerIOS extends React.Component { render(): React.Node { const props = this.props; + const mode = props.mode ?? 'datetime'; invariant( props.date || props.initialDate, 'A selected date or initial date should be specified.', @@ -153,7 +150,7 @@ class DatePickerIOS extends React.Component { ref={picker => { this._picker = picker; }} - style={getHeight(props.pickerStyle, props.mode)} + style={getHeight(props.pickerStyle, mode)} date={ props.date ? props.date.getTime() @@ -172,7 +169,7 @@ class DatePickerIOS extends React.Component { minimumDate={ props.minimumDate ? props.minimumDate.getTime() : undefined } - mode={props.mode} + mode={mode} minuteInterval={props.minuteInterval} timeZoneOffsetInMinutes={props.timeZoneOffsetInMinutes} onChange={this._onChange} diff --git a/Libraries/Components/DatePicker/__tests__/DatePickerIOS-test.js b/Libraries/Components/DatePicker/__tests__/DatePickerIOS-test.js index bcc029c47684d9..79579b82ee5933 100644 --- a/Libraries/Components/DatePicker/__tests__/DatePickerIOS-test.js +++ b/Libraries/Components/DatePicker/__tests__/DatePickerIOS-test.js @@ -32,4 +32,18 @@ describe('DatePickerIOS', () => { }, ); }); + it('should render DatePicker with the datetime mode if no mode is passed inside the props', () => { + ReactNativeTestTools.expectRendersMatchingSnapshot( + 'DatePickerIOS', + () => ( + + ), + () => { + jest.dontMock('../DatePickerIOS'); + }, + ); + }); }); diff --git a/Libraries/Components/DatePicker/__tests__/__snapshots__/DatePickerIOS-test.js.snap b/Libraries/Components/DatePicker/__tests__/__snapshots__/DatePickerIOS-test.js.snap index e463f981914119..55ce6c2067146c 100644 --- a/Libraries/Components/DatePicker/__tests__/__snapshots__/DatePickerIOS-test.js.snap +++ b/Libraries/Components/DatePicker/__tests__/__snapshots__/DatePickerIOS-test.js.snap @@ -1,5 +1,53 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`DatePickerIOS should render DatePicker with the datetime mode if no mode is passed inside the props: should deep render when mocked (please verify output manually) 1`] = ` + + + +`; + +exports[`DatePickerIOS should render DatePicker with the datetime mode if no mode is passed inside the props: should deep render when not mocked (please verify output manually) 1`] = ` + + + +`; + +exports[`DatePickerIOS should render DatePicker with the datetime mode if no mode is passed inside the props: should shallow render as when mocked 1`] = ` + +`; + +exports[`DatePickerIOS should render DatePicker with the datetime mode if no mode is passed inside the props: should shallow render as when not mocked 1`] = ` + +`; + exports[`DatePickerIOS should render as expected: should deep render when mocked (please verify output manually) 1`] = ` { - const optionsMs = options; - if (optionsMs != null) { - _toMillis(optionsMs, 'date'); - _toMillis(optionsMs, 'minDate'); - _toMillis(optionsMs, 'maxDate'); - } - return NativeDatePickerAndroid.open(options); - } - - /** - * A date has been selected. - */ - static +dateSetAction: 'dateSetAction' = 'dateSetAction'; - /** - * The dialog has been dismissed. - */ - static +dismissedAction: 'dismissedAction' = 'dismissedAction'; -} - -module.exports = DatePickerAndroid; diff --git a/Libraries/Components/DatePickerAndroid/DatePickerAndroid.ios.js b/Libraries/Components/DatePickerAndroid/DatePickerAndroid.ios.js deleted file mode 100644 index d16cb2bf610565..00000000000000 --- a/Libraries/Components/DatePickerAndroid/DatePickerAndroid.ios.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow strict-local - */ - -'use strict'; - -import type {Options, DatePickerOpenAction} from './DatePickerAndroidTypes'; - -class DatePickerAndroid { - static async open(options: ?Options): Promise { - throw new Error('DatePickerAndroid is not supported on this platform.'); - } - - /** - * A date has been selected. - */ - static +dateSetAction: 'dateSetAction' = 'dateSetAction'; - /** - * The dialog has been dismissed. - */ - static +dismissedAction: 'dismissedAction' = 'dismissedAction'; -} - -module.exports = DatePickerAndroid; diff --git a/Libraries/Components/DatePickerAndroid/DatePickerAndroidTypes.js b/Libraries/Components/DatePickerAndroid/DatePickerAndroidTypes.js deleted file mode 100644 index 096d7b5e8d9abb..00000000000000 --- a/Libraries/Components/DatePickerAndroid/DatePickerAndroidTypes.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow strict-local - */ - -export type Options = $ReadOnly<{| - date?: ?(Date | number), - minDate?: ?(Date | number), - maxDate?: ?(Date | number), - mode?: ?('calendar' | 'spinner' | 'default'), -|}>; - -export type DatePickerOpenAction = - | {| - action: 'dateSetAction', - year: number, - month: number, - day: number, - |} - | {| - action: 'dismissedAction', - year: void, - month: void, - day: void, - |}; diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index e497288b1b7d92..696781ffbe3def 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -1178,11 +1178,6 @@ class ScrollView extends React.Component { ); } } - if (Platform.OS === 'android') { - if (this.props.keyboardDismissMode === 'on-drag' && this._isTouching) { - dismissKeyboard(); - } - } this._observedScrollSinceBecomingResponder = true; this.props.onScroll && this.props.onScroll(e); }; @@ -1299,6 +1294,14 @@ class ScrollView extends React.Component { */ _handleScrollBeginDrag: (e: ScrollEvent) => void = (e: ScrollEvent) => { FrameRateLogger.beginScroll(); // TODO: track all scrolls after implementing onScrollEndAnimation + + if ( + Platform.OS === 'android' && + this.props.keyboardDismissMode === 'on-drag' + ) { + dismissKeyboard(); + } + this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e); }; diff --git a/Libraries/Components/ScrollView/ScrollViewStickyHeader.js b/Libraries/Components/ScrollView/ScrollViewStickyHeader.js index f530be611602e1..ea21ce221b757e 100644 --- a/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +++ b/Libraries/Components/ScrollView/ScrollViewStickyHeader.js @@ -4,25 +4,29 @@ * 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 + * @flow * @format */ -import type {LayoutEvent} from '../../Types/CoreEventTypes'; -import setAndForwardRef from 'react-native/Libraries/Utilities/setAndForwardRef'; -import Platform from '../../Utilities/Platform'; -import StyleSheet from '../../StyleSheet/StyleSheet'; -import Animated from '../../Animated/Animated'; +import AnimatedImplementation from '../../Animated/AnimatedImplementation'; +import AnimatedAddition from '../../Animated/nodes/AnimatedAddition'; +import AnimatedDiffClamp from '../../Animated/nodes/AnimatedDiffClamp'; +import AnimatedNode from '../../Animated/nodes/AnimatedNode'; + import * as React from 'react'; -import {useEffect, useMemo, useRef, useCallback} from 'react'; +import StyleSheet from '../../StyleSheet/StyleSheet'; +import View from '../View/View'; +import Platform from '../../Utilities/Platform'; + +import type {LayoutEvent} from '../../Types/CoreEventTypes'; -const AnimatedView = Animated.View; +const AnimatedView = AnimatedImplementation.createAnimatedComponent(View); export type Props = $ReadOnly<{ - children?: React.Element<$FlowFixMe>, + children?: React.Element, nextHeaderLayoutY: ?number, onLayout: (event: LayoutEvent) => void, - scrollAnimatedValue: Animated.Value, + scrollAnimatedValue: AnimatedImplementation.Value, // Will cause sticky headers to stick at the bottom of the ScrollView instead // of the top. inverted: ?boolean, @@ -32,275 +36,287 @@ export type Props = $ReadOnly<{ hiddenOnScroll?: ?boolean, }>; -const ScrollViewStickyHeaderWithForwardedRef: React.AbstractComponent< - Props, - $ReadOnly<{ - setNextHeaderY: number => void, - ...$Exact>, - }>, -> = React.forwardRef(function ScrollViewStickyHeader(props, forwardedRef) { - const { - inverted, - scrollViewHeight, - hiddenOnScroll, - scrollAnimatedValue, - nextHeaderLayoutY: _nextHeaderLayoutY, - } = props; +type State = { + measured: boolean, + layoutY: number, + layoutHeight: number, + nextHeaderLayoutY: ?number, + translateY: ?number, + ... +}; - const [measured, setMeasured] = React.useState(false); - const [layoutY, setLayoutY] = React.useState(0); - const [layoutHeight, setLayoutHeight] = React.useState(0); - const [translateY, setTranslateY] = React.useState(null); - const [nextHeaderLayoutY, setNextHeaderLayoutY] = React.useState( - _nextHeaderLayoutY, - ); - const [isFabric, setIsFabric] = React.useState(false); +class ScrollViewStickyHeader extends React.Component { + state: State = { + measured: false, + layoutY: 0, + layoutHeight: 0, + nextHeaderLayoutY: this.props.nextHeaderLayoutY, + translateY: null, + }; - const componentRef = React.useRef>(); - const _setNativeRef = setAndForwardRef({ - getForwardedRef: () => forwardedRef, - setLocalRef: ref => { - componentRef.current = ref; - if (ref) { - ref.setNextHeaderY = value => { - setNextHeaderLayoutY(value); - }; - setIsFabric( - !!( - // An internal transform mangles variables with leading "_" as private. - // eslint-disable-next-line dot-notation - ref['_internalInstanceHandle']?.stateNode?.canonical - ), - ); - } - }, - }); + _translateY: ?AnimatedNode = null; + _shouldRecreateTranslateY: boolean = true; + _haveReceivedInitialZeroTranslateY: boolean = true; + _ref: any; // TODO T53738161: flow type this, and the whole file - const offset = useMemo( - () => - hiddenOnScroll === true - ? Animated.diffClamp( - scrollAnimatedValue - .interpolate({ - extrapolateLeft: 'clamp', - inputRange: [layoutY, layoutY + 1], - outputRange: ([0, 1]: Array), - }) - .interpolate({ - inputRange: [0, 1], - outputRange: ([0, -1]: Array), - }), - -layoutHeight, - 0, - ) - : null, - [scrollAnimatedValue, layoutHeight, layoutY, hiddenOnScroll], - ); + // Fabric-only: + _timer: ?TimeoutID; + _animatedValueListenerId: string; + _animatedValueListener: (valueObject: $ReadOnly<{|value: number|}>) => void; + _debounceTimeout: number = Platform.OS === 'android' ? 15 : 64; - const [ - animatedTranslateY, - setAnimatedTranslateY, - ] = React.useState(() => { - const inputRange: Array = [-1, 0]; - const outputRange: Array = [0, 0]; - const initialTranslateY: Animated.Interpolation = scrollAnimatedValue.interpolate( - { - inputRange, - outputRange, - }, - ); + setNextHeaderY: (y: number) => void = (y: number): void => { + this._shouldRecreateTranslateY = true; + this.setState({nextHeaderLayoutY: y}); + }; - if (offset != null) { - return Animated.add(initialTranslateY, offset); + componentWillUnmount() { + if (this._translateY != null && this._animatedValueListenerId != null) { + this._translateY.removeListener(this._animatedValueListenerId); + } + if (this._timer) { + clearTimeout(this._timer); } - return initialTranslateY; - }); + } - const _haveReceivedInitialZeroTranslateY = useRef(true); - const _timer = useRef(null); + UNSAFE_componentWillReceiveProps(nextProps: Props) { + if ( + nextProps.scrollViewHeight !== this.props.scrollViewHeight || + nextProps.scrollAnimatedValue !== this.props.scrollAnimatedValue || + nextProps.inverted !== this.props.inverted + ) { + this._shouldRecreateTranslateY = true; + } + } - useEffect(() => { - if (translateY !== 0 && translateY != null) { - _haveReceivedInitialZeroTranslateY.current = false; + updateTranslateListener( + translateY: AnimatedImplementation.Interpolation, + isFabric: boolean, + offset: AnimatedDiffClamp | null, + ) { + if (this._translateY != null && this._animatedValueListenerId != null) { + this._translateY.removeListener(this._animatedValueListenerId); } - }, [translateY]); + offset + ? (this._translateY = new AnimatedAddition(translateY, offset)) + : (this._translateY = translateY); - // This is called whenever the (Interpolated) Animated Value - // updates, which is several times per frame during scrolling. - // To ensure that the Fabric ShadowTree has the most recent - // translate style of this node, we debounce the value and then - // pass it through to the underlying node during render. - // This is: - // 1. Only an issue in Fabric. - // 2. Worse in Android than iOS. In Android, but not iOS, you - // can touch and move your finger slightly and still trigger - // a "tap" event. In iOS, moving will cancel the tap in - // both Fabric and non-Fabric. On Android when you move - // your finger, the hit-detection moves from the Android - // platform to JS, so we need the ShadowTree to have knowledge - // of the current position. - const animatedValueListener = useCallback( - ({value}) => { - const _debounceTimeout: number = Platform.OS === 'android' ? 15 : 64; - // When the AnimatedInterpolation is recreated, it always initializes - // to a value of zero and emits a value change of 0 to its listeners. - if (value === 0 && !_haveReceivedInitialZeroTranslateY.current) { - _haveReceivedInitialZeroTranslateY.current = true; - return; - } - if (_timer.current != null) { - clearTimeout(_timer.current); - } - _timer.current = setTimeout(() => { - if (value !== translateY) { - setTranslateY(value); - } - }, _debounceTimeout); - }, - [translateY], - ); + this._shouldRecreateTranslateY = false; - useEffect(() => { - const inputRange: Array = [-1, 0]; - const outputRange: Array = [0, 0]; + if (!isFabric) { + return; + } - if (measured) { - if (inverted === true) { - // The interpolation looks like: - // - Negative scroll: no translation - // - `stickStartPoint` is the point at which the header will start sticking. - // It is calculated using the ScrollView viewport height so it is a the bottom. - // - Headers that are in the initial viewport will never stick, `stickStartPoint` - // will be negative. - // - From 0 to `stickStartPoint` no translation. This will cause the header - // to scroll normally until it reaches the top of the scroll view. - // - From `stickStartPoint` to when the next header y hits the bottom edge of the header: translate - // equally to scroll. This will cause the header to stay at the top of the scroll view. - // - Past the collision with the next header y: no more translation. This will cause the - // header to continue scrolling up and make room for the next sticky header. - // In the case that there is no next header just translate equally to - // scroll indefinitely. - if (scrollViewHeight != null) { - const stickStartPoint = layoutY + layoutHeight - scrollViewHeight; - if (stickStartPoint > 0) { - inputRange.push(stickStartPoint); - outputRange.push(0); - inputRange.push(stickStartPoint + 1); - outputRange.push(1); - // If the next sticky header has not loaded yet (probably windowing) or is the last - // we can just keep it sticked forever. - const collisionPoint = - (nextHeaderLayoutY || 0) - layoutHeight - scrollViewHeight; - if (collisionPoint > stickStartPoint) { - inputRange.push(collisionPoint, collisionPoint + 1); - outputRange.push( - collisionPoint - stickStartPoint, - collisionPoint - stickStartPoint, - ); - } - } + if (!this._animatedValueListener) { + // This is called whenever the (Interpolated) Animated Value + // updates, which is several times per frame during scrolling. + // To ensure that the Fabric ShadowTree has the most recent + // translate style of this node, we debounce the value and then + // pass it through to the underlying node during render. + // This is: + // 1. Only an issue in Fabric. + // 2. Worse in Android than iOS. In Android, but not iOS, you + // can touch and move your finger slightly and still trigger + // a "tap" event. In iOS, moving will cancel the tap in + // both Fabric and non-Fabric. On Android when you move + // your finger, the hit-detection moves from the Android + // platform to JS, so we need the ShadowTree to have knowledge + // of the current position. + this._animatedValueListener = ({value}) => { + // When the AnimatedInterpolation is recreated, it always initializes + // to a value of zero and emits a value change of 0 to its listeners. + if (value === 0 && !this._haveReceivedInitialZeroTranslateY) { + this._haveReceivedInitialZeroTranslateY = true; + return; } - } else { - // The interpolation looks like: - // - Negative scroll: no translation - // - From 0 to the y of the header: no translation. This will cause the header - // to scroll normally until it reaches the top of the scroll view. - // - From header y to when the next header y hits the bottom edge of the header: translate - // equally to scroll. This will cause the header to stay at the top of the scroll view. - // - Past the collision with the next header y: no more translation. This will cause the - // header to continue scrolling up and make room for the next sticky header. - // In the case that there is no next header just translate equally to - // scroll indefinitely. - inputRange.push(layoutY); - outputRange.push(0); - // If the next sticky header has not loaded yet (probably windowing) or is the last - // we can just keep it sticked forever. - const collisionPoint = (nextHeaderLayoutY || 0) - layoutHeight; - if (collisionPoint >= layoutY) { - inputRange.push(collisionPoint, collisionPoint + 1); - outputRange.push(collisionPoint - layoutY, collisionPoint - layoutY); - } else { - inputRange.push(layoutY + 1); - outputRange.push(1); + if (this._timer) { + clearTimeout(this._timer); } - } - } - - let newAnimatedTranslateY: Animated.Node = scrollAnimatedValue.interpolate({ - inputRange, - outputRange, - }); - - if (offset != null) { - newAnimatedTranslateY = Animated.add(newAnimatedTranslateY, offset); + this._timer = setTimeout(() => { + if (value !== this.state.translateY) { + this.setState({ + translateY: value, + }); + } + }, this._debounceTimeout); + }; } - - // add the event listener - let animatedListenerId; - if (isFabric) { - animatedListenerId = newAnimatedTranslateY.addListener( - animatedValueListener, - ); + if (this.state.translateY !== 0 && this.state.translateY != null) { + this._haveReceivedInitialZeroTranslateY = false; } + this._animatedValueListenerId = translateY.addListener( + this._animatedValueListener, + ); + } - setAnimatedTranslateY(newAnimatedTranslateY); + _onLayout = event => { + const layoutY = event.nativeEvent.layout.y; + const layoutHeight = event.nativeEvent.layout.height; + const measured = true; - // clean up the event listener and timer - return () => { - if (animatedListenerId) { - newAnimatedTranslateY.removeListener(animatedListenerId); - } - if (_timer.current != null) { - clearTimeout(_timer.current); - } - }; - }, [nextHeaderLayoutY, measured, layoutHeight, layoutY, scrollViewHeight, scrollAnimatedValue, inverted, offset, animatedValueListener, isFabric]); + if ( + layoutY !== this.state.layoutY || + layoutHeight !== this.state.layoutHeight || + measured !== this.state.measured + ) { + this._shouldRecreateTranslateY = true; + } - const _onLayout = (event: LayoutEvent) => { - setLayoutY(event.nativeEvent.layout.y); - setLayoutHeight(event.nativeEvent.layout.height); - setMeasured(true); + this.setState({ + measured, + layoutY, + layoutHeight, + }); - props.onLayout(event); - const child = React.Children.only(props.children); + this.props.onLayout(event); + const child = React.Children.only(this.props.children); if (child.props.onLayout) { child.props.onLayout(event); } }; - const child = React.Children.only(props.children); + _setComponentRef = ref => { + this._ref = ref; + }; + + render(): React.Node { + // Fabric Detection + const isFabric = !!( + // An internal transform mangles variables with leading "_" as private. + // eslint-disable-next-line dot-notation + (this._ref && this._ref['_internalInstanceHandle']?.stateNode?.canonical) + ); + // Initially and in the case of updated props or layout, we + // recreate this interpolated value. Otherwise, we do not recreate + // when there are state changes. + if (this._shouldRecreateTranslateY) { + const {inverted, scrollViewHeight} = this.props; + const {measured, layoutHeight, layoutY, nextHeaderLayoutY} = this.state; + const inputRange: Array = [-1, 0]; + const outputRange: Array = [0, 0]; - // TODO T68319535: remove this if NativeAnimated is rewritten for Fabric - const passthroughAnimatedPropExplicitValues = - isFabric && translateY != null - ? { - style: {transform: [{translateY: translateY}]}, + if (measured) { + if (inverted) { + // The interpolation looks like: + // - Negative scroll: no translation + // - `stickStartPoint` is the point at which the header will start sticking. + // It is calculated using the ScrollView viewport height so it is a the bottom. + // - Headers that are in the initial viewport will never stick, `stickStartPoint` + // will be negative. + // - From 0 to `stickStartPoint` no translation. This will cause the header + // to scroll normally until it reaches the top of the scroll view. + // - From `stickStartPoint` to when the next header y hits the bottom edge of the header: translate + // equally to scroll. This will cause the header to stay at the top of the scroll view. + // - Past the collision with the next header y: no more translation. This will cause the + // header to continue scrolling up and make room for the next sticky header. + // In the case that there is no next header just translate equally to + // scroll indefinitely. + if (scrollViewHeight != null) { + const stickStartPoint = layoutY + layoutHeight - scrollViewHeight; + if (stickStartPoint > 0) { + inputRange.push(stickStartPoint); + outputRange.push(0); + inputRange.push(stickStartPoint + 1); + outputRange.push(1); + // If the next sticky header has not loaded yet (probably windowing) or is the last + // we can just keep it sticked forever. + const collisionPoint = + (nextHeaderLayoutY || 0) - layoutHeight - scrollViewHeight; + if (collisionPoint > stickStartPoint) { + inputRange.push(collisionPoint, collisionPoint + 1); + outputRange.push( + collisionPoint - stickStartPoint, + collisionPoint - stickStartPoint, + ); + } + } + } + } else { + // The interpolation looks like: + // - Negative scroll: no translation + // - From 0 to the y of the header: no translation. This will cause the header + // to scroll normally until it reaches the top of the scroll view. + // - From header y to when the next header y hits the bottom edge of the header: translate + // equally to scroll. This will cause the header to stay at the top of the scroll view. + // - Past the collision with the next header y: no more translation. This will cause the + // header to continue scrolling up and make room for the next sticky header. + // In the case that there is no next header just translate equally to + // scroll indefinitely. + inputRange.push(layoutY); + outputRange.push(0); + // If the next sticky header has not loaded yet (probably windowing) or is the last + // we can just keep it sticked forever. + const collisionPoint = (nextHeaderLayoutY || 0) - layoutHeight; + if (collisionPoint >= layoutY) { + inputRange.push(collisionPoint, collisionPoint + 1); + outputRange.push( + collisionPoint - layoutY, + collisionPoint - layoutY, + ); + } else { + inputRange.push(layoutY + 1); + outputRange.push(1); + } } - : null; + } - return ( - /* $FlowFixMe[prop-missing] passthroughAnimatedPropExplicitValues isn't properly - included in the Animated.View flow type. */ - - {React.cloneElement(child, { - style: styles.fill, // We transfer the child style to the wrapper. - onLayout: undefined, // we call this manually through our this._onLayout - })} - - ); -}); + this.updateTranslateListener( + this.props.scrollAnimatedValue.interpolate({ + inputRange, + outputRange, + }), + isFabric, + this.props.hiddenOnScroll + ? new AnimatedDiffClamp( + this.props.scrollAnimatedValue + .interpolate({ + extrapolateLeft: 'clamp', + inputRange: [layoutY, layoutY + 1], + outputRange: ([0, 1]: Array), + }) + .interpolate({ + inputRange: [0, 1], + outputRange: ([0, -1]: Array), + }), + -this.state.layoutHeight, + 0, + ) + : null, + ); + } + + const child = React.Children.only(this.props.children); + + // TODO T68319535: remove this if NativeAnimated is rewritten for Fabric + const passthroughAnimatedPropExplicitValues = + isFabric && this.state.translateY != null + ? { + style: {transform: [{translateY: this.state.translateY}]}, + } + : null; + + return ( + + {React.cloneElement(child, { + style: styles.fill, // We transfer the child style to the wrapper. + onLayout: undefined, // we call this manually through our this._onLayout + })} + + ); + } +} const styles = StyleSheet.create({ header: { @@ -312,4 +328,4 @@ const styles = StyleSheet.create({ }, }); -export default ScrollViewStickyHeaderWithForwardedRef; +module.exports = ScrollViewStickyHeader; diff --git a/Libraries/Components/View/ViewAccessibility.js b/Libraries/Components/View/ViewAccessibility.js index 47c99e27a9ae85..4debbe4da3ed6f 100644 --- a/Libraries/Components/View/ViewAccessibility.js +++ b/Libraries/Components/View/ViewAccessibility.js @@ -39,6 +39,7 @@ export type AccessibilityRole = | 'spinbutton' | 'switch' | 'tab' + | 'tabbar' | 'tablist' | 'timer' | 'list' diff --git a/Libraries/Core/ExceptionsManager.js b/Libraries/Core/ExceptionsManager.js index 6e64a40ad48a66..d4826d4b54ab6a 100644 --- a/Libraries/Core/ExceptionsManager.js +++ b/Libraries/Core/ExceptionsManager.js @@ -76,7 +76,9 @@ function reportException( e.jsEngine == null ? message : `${message}, js engine: ${e.jsEngine}`; const isHandledByLogBox = - e.forceRedbox !== true && !global.RN$Bridgeless && !global.RN$Express; + e.forceRedbox !== true && + global.RN$Bridgeless !== true && + !global.RN$Express; const data = preprocessException({ message, diff --git a/Libraries/Core/polyfillPromise.js b/Libraries/Core/polyfillPromise.js index 6551745bf52c5d..f83fea90248b9d 100644 --- a/Libraries/Core/polyfillPromise.js +++ b/Libraries/Core/polyfillPromise.js @@ -29,7 +29,7 @@ if (global?.HermesInternal?.hasPromise?.()) { if (typeof HermesPromise !== 'function') { console.error('HermesPromise does not exist'); } - global.HermesInternal.enablePromiseRejectionTracker( + global.HermesInternal?.enablePromiseRejectionTracker?.( require('../promiseRejectionTrackingOptions').default, ); } diff --git a/Libraries/Core/setUpBatchedBridge.js b/Libraries/Core/setUpBatchedBridge.js index 49747fd7576c9d..0f16dd84e74c54 100644 --- a/Libraries/Core/setUpBatchedBridge.js +++ b/Libraries/Core/setUpBatchedBridge.js @@ -11,7 +11,7 @@ 'use strict'; let registerModule; -if (global.RN$Bridgeless && global.RN$registerCallableModule) { +if (global.RN$Bridgeless === true && global.RN$registerCallableModule) { registerModule = global.RN$registerCallableModule; } else { const BatchedBridge = require('../BatchedBridge/BatchedBridge'); diff --git a/Libraries/Core/setUpGlobals.js b/Libraries/Core/setUpGlobals.js index ea6da8fbbbe3f1..a8ce63d132367a 100644 --- a/Libraries/Core/setUpGlobals.js +++ b/Libraries/Core/setUpGlobals.js @@ -19,10 +19,12 @@ if (global.GLOBAL === undefined) { } if (global.window === undefined) { + // $FlowFixMe[cannot-write] global.window = global; } if (global.self === undefined) { + // $FlowFixMe[cannot-write] global.self = global; } diff --git a/Libraries/Core/setUpTimers.js b/Libraries/Core/setUpTimers.js index d257dfa0168d96..7048b32c4fdf50 100644 --- a/Libraries/Core/setUpTimers.js +++ b/Libraries/Core/setUpTimers.js @@ -21,14 +21,14 @@ if (__DEV__) { // Currently, Hermes `Promise` is implemented via Internal Bytecode. const hasHermesPromiseQueuedToJSVM = - global?.HermesInternal?.hasPromise?.() && - global?.HermesInternal?.useEngineQueue?.(); + global.HermesInternal?.hasPromise?.() === true && + global.HermesInternal?.useEngineQueue?.() === true; const hasNativePromise = isNativeFunction(Promise); const hasPromiseQueuedToJSVM = hasNativePromise || hasHermesPromiseQueuedToJSVM; // In bridgeless mode, timers are host functions installed from cpp. -if (!global.RN$Bridgeless) { +if (global.RN$Bridgeless !== true) { /** * Set up timers. * You can use this module directly, or just require InitializeCore. @@ -65,7 +65,7 @@ if (hasPromiseQueuedToJSVM) { // When promise was polyfilled hence is queued to the RN microtask queue, // we polyfill the immediate APIs as aliases to the ReactNativeMicrotask APIs. // Note that in bridgeless mode, immediate APIs are installed from cpp. - if (!global.RN$Bridgeless) { + if (global.RN$Bridgeless !== true) { polyfillGlobal( 'setImmediate', () => require('./Timers/JSTimers').queueReactNativeMicrotask, @@ -83,7 +83,7 @@ if (hasPromiseQueuedToJSVM) { */ if (hasHermesPromiseQueuedToJSVM) { // Fast path for Hermes. - polyfillGlobal('queueMicrotask', () => global.HermesInternal.enqueueJob); + polyfillGlobal('queueMicrotask', () => global.HermesInternal?.enqueueJob); } else { // Polyfill it with promise (regardless it's polyfiled or native) otherwise. polyfillGlobal( diff --git a/Libraries/Image/Image.ios.js b/Libraries/Image/Image.ios.js index 5cadc1db9dcbbb..3dab5cc8c1f7f0 100644 --- a/Libraries/Image/Image.ios.js +++ b/Libraries/Image/Image.ios.js @@ -12,6 +12,7 @@ import DeprecatedImagePropType from '../DeprecatedPropTypes/DeprecatedImagePropT import * as React from 'react'; import StyleSheet from '../StyleSheet/StyleSheet'; +import ImageInjection from './ImageInjection'; import ImageAnalyticsTagContext from './ImageAnalyticsTagContext'; import flattenStyle from '../StyleSheet/flattenStyle'; import resolveAssetSource from './resolveAssetSource'; @@ -168,6 +169,11 @@ Image = React.forwardRef< ImagePropsType, React.ElementRef, >(Image); + +if (ImageInjection.unstable_createImageComponent != null) { + Image = ImageInjection.unstable_createImageComponent(Image); +} + Image.displayName = 'Image'; /** diff --git a/Libraries/Image/ImageBackground.js b/Libraries/Image/ImageBackground.js index b4b6223b846b61..84bb98551f07a0 100644 --- a/Libraries/Image/ImageBackground.js +++ b/Libraries/Image/ImageBackground.js @@ -74,8 +74,8 @@ class ImageBackground extends React.Component<$FlowFixMeProps> { // So, we have to proxy/reapply these styles explicitly for actual component. // This workaround should be removed after implementing proper support of // intrinsic content size of the . - width: style.width, - height: style.height, + width: style?.width, + height: style?.height, }, imageStyle, ]} diff --git a/Libraries/Image/ImageSource.js b/Libraries/Image/ImageSource.js index fd7a92c9761f01..903b144b9ac889 100644 --- a/Libraries/Image/ImageSource.js +++ b/Libraries/Image/ImageSource.js @@ -13,7 +13,7 @@ /** * Keep this in sync with `DeprecatedImageSourcePropType.js`. * - * This type is intentinoally inexact in order to permit call sites that supply + * This type is intentionally inexact in order to permit call sites that supply * extra properties. */ export interface ImageURISource { diff --git a/Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m b/Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m index 102234798bbc0d..91acd7dcbaede7 100644 --- a/Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m +++ b/Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m @@ -16,7 +16,6 @@ @implementation RCTPropsAnimatedNode { NSNumber *_connectedViewTag; - NSNumber *_rootTag; NSString *_connectedViewName; __weak RCTBridge *_bridge; __weak id _surfacePresenter; @@ -48,7 +47,6 @@ - (void)connectToView:(NSNumber *)viewTag _connectedViewTag = viewTag; _connectedViewName = viewName; _managedByFabric = RCTUIManagerTypeForTagIsFabric(viewTag); - _rootTag = nil; } - (void)disconnectFromView:(NSNumber *)viewTag @@ -58,7 +56,6 @@ - (void)disconnectFromView:(NSNumber *)viewTag _connectedViewTag = nil; _connectedViewName = nil; _managedByFabric = NO; - _rootTag = nil; } - (void)updateView diff --git a/Libraries/PermissionsAndroid/NativePermissionsAndroid.js b/Libraries/PermissionsAndroid/NativePermissionsAndroid.js index 64d55e5f334264..358882c8ec4820 100644 --- a/Libraries/PermissionsAndroid/NativePermissionsAndroid.js +++ b/Libraries/PermissionsAndroid/NativePermissionsAndroid.js @@ -43,7 +43,8 @@ export type PermissionType = | 'android.permission.READ_EXTERNAL_STORAGE' | 'android.permission.WRITE_EXTERNAL_STORAGE' | 'android.permission.BLUETOOTH_CONNECT' - | 'android.permission.BLUETOOTH_SCAN'; + | 'android.permission.BLUETOOTH_SCAN' + | 'android.permission.BLUETOOTH_ADVERTISE'; */ export interface Spec extends TurboModule { diff --git a/Libraries/PermissionsAndroid/PermissionsAndroid.js b/Libraries/PermissionsAndroid/PermissionsAndroid.js index c538dfd803549b..1006cd3192451d 100644 --- a/Libraries/PermissionsAndroid/PermissionsAndroid.js +++ b/Libraries/PermissionsAndroid/PermissionsAndroid.js @@ -61,6 +61,7 @@ const PERMISSIONS = Object.freeze({ WRITE_EXTERNAL_STORAGE: 'android.permission.WRITE_EXTERNAL_STORAGE', BLUETOOTH_CONNECT: 'android.permission.BLUETOOTH_CONNECT', BLUETOOTH_SCAN: 'android.permission.BLUETOOTH_SCAN', + BLUETOOTH_ADVERTISE: 'android.permission.BLUETOOTH_ADVERTISE', }); /** @@ -75,6 +76,7 @@ class PermissionsAndroid { ACCESS_COARSE_LOCATION: string, ACCESS_FINE_LOCATION: string, ADD_VOICEMAIL: string, + BLUETOOTH_ADVERTISE: string, BLUETOOTH_CONNECT: string, BLUETOOTH_SCAN: string, BODY_SENSORS: string, diff --git a/Libraries/Pressability/Pressability.js b/Libraries/Pressability/Pressability.js index 9ffab69aa01c30..2c43fe6cd1fabb 100644 --- a/Libraries/Pressability/Pressability.js +++ b/Libraries/Pressability/Pressability.js @@ -631,6 +631,7 @@ export default class Pressability { PressabilityPerformanceEventEmitter.emitEvent(() => { return { signal, + nativeTimestamp: event.nativeEvent.timestamp, touchDelayMs: Date.now() - event.nativeEvent.timestamp, }; }); diff --git a/Libraries/Pressability/PressabilityPerformanceEventEmitter.js b/Libraries/Pressability/PressabilityPerformanceEventEmitter.js index 832b1ee270e7e0..302baf5e8744ba 100644 --- a/Libraries/Pressability/PressabilityPerformanceEventEmitter.js +++ b/Libraries/Pressability/PressabilityPerformanceEventEmitter.js @@ -12,6 +12,7 @@ import {type PressabilityTouchSignal as TouchSignal} from './PressabilityTypes.j export type PressabilityPerformanceEvent = $ReadOnly<{| signal: TouchSignal, + nativeTimestamp: number, touchDelayMs: number, |}>; export type PressabilityPerformanceEventListener = PressabilityPerformanceEvent => void; diff --git a/Libraries/ReactNative/PaperUIManager.js b/Libraries/ReactNative/PaperUIManager.js index c468958e566320..87cc101db310d4 100644 --- a/Libraries/ReactNative/PaperUIManager.js +++ b/Libraries/ReactNative/PaperUIManager.js @@ -34,6 +34,7 @@ function getConstants(): Object { function getViewManagerConfig(viewManagerName: string): any { if ( viewManagerConfigs[viewManagerName] === undefined && + global.nativeCallSyncHook && // If we're in the Chrome Debugger, let's not even try calling the sync method NativeUIManager.getConstantsForViewManager ) { try { diff --git a/Libraries/Renderer/REVISION b/Libraries/Renderer/REVISION index e66862ad93184a..280c372baf4449 100644 --- a/Libraries/Renderer/REVISION +++ b/Libraries/Renderer/REVISION @@ -1 +1 @@ -424fe587087d05302259d6d5ebb359675387f3b1 \ No newline at end of file +bd5bf555e1167e7088a4391e5cd419dccb39714c \ No newline at end of file diff --git a/Libraries/Renderer/implementations/ReactFabric-dev.fb.js b/Libraries/Renderer/implementations/ReactFabric-dev.fb.js index 64e8db3a78214a..7d7d9908ca0cb4 100644 --- a/Libraries/Renderer/implementations/ReactFabric-dev.fb.js +++ b/Libraries/Renderer/implementations/ReactFabric-dev.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<903768081f51a5abfed30db7d6f33dd7>> + * @generated SignedSource<<0105b67942f03415395650d296aa846a>> */ 'use strict'; @@ -2939,7 +2939,7 @@ var MountPassiveDev = 4194304; // Groups of flags that are used in the commit phase to skip over trees that // don't contain effects, by checking subtreeFlags. -var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visiblity +var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility // flag logic (see #20043) Update | Snapshot | 0; var MutationMask = @@ -2953,7 +2953,7 @@ var MutationMask = var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask var PassiveMask = Passive | ChildDeletion; // Union of tags that don't get reset on clones. -// This allows certain concepts to persist without recalculting them, +// This allows certain concepts to persist without recalculating them, // e.g. whether a subtree contains passive effects or portals. var StaticMask = LayoutStatic | PassiveStatic | RefStatic; @@ -4988,8 +4988,10 @@ function createTextInstance( hostContext, internalInstanceHandle ) { - if (!hostContext.isInAParentText) { - throw Error("Text strings must be rendered within a component."); + { + if (!hostContext.isInAParentText) { + error("Text strings must be rendered within a component."); + } } var tag = nextReactTag; @@ -5859,7 +5861,7 @@ function flushSyncCallbacksOnlyInLegacyMode() { } function flushSyncCallbacks() { if (!isFlushingSyncQueue && syncQueue !== null) { - // Prevent re-entrancy. + // Prevent re-entrance. isFlushingSyncQueue = true; var i = 0; var previousUpdatePriority = getCurrentUpdatePriority(); @@ -5898,22 +5900,7 @@ function flushSyncCallbacks() { return null; } -var NoFlags$1 = - /* */ - 0; // Represents whether effect should fire. - -var HasEffect = - /* */ - 1; // Represents the phase in which the effect (not the clean-up) fires. - -var Layout = - /* */ - 2; -var Passive$1 = - /* */ - 4; - -var ReactVersion = "18.0.0-424fe5870-20210816"; +var ReactVersion = "18.0.0-bd5bf555e-20210823"; var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; var NoTransition = 0; @@ -6710,7 +6697,7 @@ function readContext(context) { // An array of all update queues that received updates during the current // render. When this render exits, either because it finishes or because it is -// interrupted, the interleaved updates will be transfered onto the main part +// interrupted, the interleaved updates will be transferred onto the main part // of the queue. var interleavedQueues = null; function pushInterleavedQueue(queue) { @@ -6823,7 +6810,7 @@ function enqueueUpdate(fiber, update, lane) { if (interleaved === null) { // This is the first update. Create a circular list. update.next = update; // At the end of the current render, this queue's interleaved updates will - // be transfered to the pending queue. + // be transferred to the pending queue. pushInterleavedQueue(sharedQueue); } else { @@ -9866,6 +9853,21 @@ function findFirstSuspended(row) { return null; } +var NoFlags$1 = + /* */ + 0; // Represents whether effect should fire. + +var HasEffect = + /* */ + 1; // Represents the phase in which the effect (not the clean-up) fires. + +var Layout = + /* */ + 2; +var Passive$1 = + /* */ + 4; + var isHydrating = false; function enterHydrationState(fiber) { @@ -10234,7 +10236,7 @@ function renderWithHooks( children = Component(props, secondArg); } while (didScheduleRenderPhaseUpdateDuringThisPass); } // We can assume the previous dispatcher is always this one, since we set it - // at the beginning of the render phase and there's no re-entrancy. + // at the beginning of the render phase and there's no re-entrance. ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; @@ -10302,7 +10304,7 @@ function bailoutHooks(current, workInProgress, lanes) { } function resetHooksAfterThrow() { // We can assume the previous dispatcher is always this one, since we set it - // at the beginning of the render phase and there's no re-entrancy. + // at the beginning of the render phase and there's no re-entrance. ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; if (didScheduleRenderPhaseUpdate) { @@ -10667,7 +10669,7 @@ function rerenderReducer(reducer, initialArg, init) { return [newState, dispatch]; } -function readFromUnsubcribedMutableSource(root, source, getSnapshot) { +function readFromUnsubscribedMutableSource(root, source, getSnapshot) { { warnAboutMultipleRenderersDEV(source); } @@ -10799,7 +10801,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { var dispatcher = ReactCurrentDispatcher$1.current; // eslint-disable-next-line prefer-const var _dispatcher$useState = dispatcher.useState(function() { - return readFromUnsubcribedMutableSource(root, source, getSnapshot); + return readFromUnsubscribedMutableSource(root, source, getSnapshot); }), currentSnapshot = _dispatcher$useState[0], setSnapshot = _dispatcher$useState[1]; @@ -10928,7 +10930,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { ); stateHook.queue = newQueue; stateHook.baseQueue = null; - snapshot = readFromUnsubcribedMutableSource(root, source, getSnapshot); + snapshot = readFromUnsubscribedMutableSource(root, source, getSnapshot); stateHook.memoizedState = stateHook.baseState = snapshot; } @@ -11454,7 +11456,7 @@ function dispatchAction(fiber, queue, action) { if (interleaved === null) { // This is the first update. Create a circular list. update.next = update; // At the end of the current render, this queue's interleaved updates will - // be transfered to the pending queue. + // be transferred to the pending queue. pushInterleavedQueue(queue); } else { @@ -13835,7 +13837,7 @@ function completeWork(current, workInProgress, renderLanes) { workInProgress.flags |= DidCapture; cutOffTailIfNeeded(renderState, false); // If this is a newly suspended tree, it might not get committed as // part of the second pass. In that case nothing will subscribe to - // its thennables. Instead, we'll transfer its thennables to the + // its thenables. Instead, we'll transfer its thenables to the // SuspenseList so that it can retry if they resolve. // There might be multiple of these in the list but since we're // going to wait for all of them anyway, it doesn't really matter @@ -13846,10 +13848,10 @@ function completeWork(current, workInProgress, renderLanes) { // doesn't matter since that means that the other boundaries that // we did find already has their listeners attached. - var newThennables = suspended.updateQueue; + var newThenables = suspended.updateQueue; - if (newThennables !== null) { - workInProgress.updateQueue = newThennables; + if (newThenables !== null) { + workInProgress.updateQueue = newThenables; workInProgress.flags |= Update; } // Rerender the whole list, but this time, we'll force fallbacks // to stay in place. @@ -13905,10 +13907,10 @@ function completeWork(current, workInProgress, renderLanes) { didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't // get lost if this row ends up dropped during a second pass. - var _newThennables = _suspended.updateQueue; + var _newThenables = _suspended.updateQueue; - if (_newThennables !== null) { - workInProgress.updateQueue = _newThennables; + if (_newThenables !== null) { + workInProgress.updateQueue = _newThenables; workInProgress.flags |= Update; } @@ -15455,7 +15457,7 @@ function shouldRemainOnFallback( var suspenseState = current.memoizedState; if (suspenseState === null) { - // Currently showing content. Don't hide it, even if ForceSuspenseFallack + // Currently showing content. Don't hide it, even if ForceSuspenseFallback // is true. More precise name might be "ForceRemainSuspenseFallback". // Note: This is a factoring smell. Can't remain on a fallback if there's // no fallback to remain on. @@ -15507,7 +15509,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); pushSuspenseContext(workInProgress, suspenseContext); // OK, the next part is confusing. We're about to reconcile the Suspense - // boundary's children. This involves some custom reconcilation logic. Two + // boundary's children. This involves some custom reconciliation logic. Two // main reasons this is so complicated. // // First, Legacy Mode has different semantics for backwards compatibility. The @@ -18356,7 +18358,7 @@ function commitMutationEffectsOnFiber(finishedWork, root) { // TODO: The factoring of this phase could probably be improved. Consider // switching on the type of work before checking the flags. That's what // we do in all the other phases. I think this one is only different - // because of the shared reconcilation logic below. + // because of the shared reconciliation logic below. var flags = finishedWork.flags; if (flags & Ref) { @@ -19003,10 +19005,7 @@ var nestedPassiveUpdateCount = 0; // If two updates are scheduled within the sam // between the first and second call. var currentEventTime = NoTimestamp; -var currentEventTransitionLane = NoLanes; // Dev only flag that tracks if passive effects are currently being flushed. -// We warn about state updates for unmounted components differently in this case. - -var isFlushingPassiveEffects = false; +var currentEventTransitionLane = NoLanes; function getWorkInProgressRoot() { return workInProgressRoot; } @@ -19104,7 +19103,6 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { var root = markUpdateLaneFromFiberToRoot(fiber, lane); if (root === null) { - warnAboutUpdateOnUnmountedFiberInDEV(fiber); return null; } @@ -20429,10 +20427,6 @@ function flushPassiveEffectsImpl() { throw Error("Cannot flush passive effects while already rendering."); } - { - isFlushingPassiveEffects = true; - } - var prevExecutionContext = executionContext; executionContext |= CommitContext; commitPassiveUnmountEffects(root.current); @@ -20448,10 +20442,6 @@ function flushPassiveEffectsImpl() { } } - { - isFlushingPassiveEffects = false; - } - { commitDoubleInvokeEffectsInDEV(root.current, true); } @@ -20831,86 +20821,6 @@ function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { } } -var didWarnStateUpdateForUnmountedComponent = null; - -function warnAboutUpdateOnUnmountedFiberInDEV(fiber) { - { - var tag = fiber.tag; - - if ( - tag !== HostRoot && - tag !== ClassComponent && - tag !== FunctionComponent && - tag !== ForwardRef && - tag !== MemoComponent && - tag !== SimpleMemoComponent - ) { - // Only warn for user-defined components, not internal ones like Suspense. - return; - } - - if ((fiber.flags & PassiveStatic) !== NoFlags) { - var updateQueue = fiber.updateQueue; - - if (updateQueue !== null) { - var lastEffect = updateQueue.lastEffect; - - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; - - do { - if (effect.destroy !== undefined) { - if ((effect.tag & Passive$1) !== NoFlags$1) { - return; - } - } - - effect = effect.next; - } while (effect !== firstEffect); - } - } - } // We show the whole stack but dedupe on the top component's name because - // the problematic code almost always lies inside that component. - - var componentName = getComponentNameFromFiber(fiber) || "ReactComponent"; - - if (didWarnStateUpdateForUnmountedComponent !== null) { - if (didWarnStateUpdateForUnmountedComponent.has(componentName)) { - return; - } - - didWarnStateUpdateForUnmountedComponent.add(componentName); - } else { - didWarnStateUpdateForUnmountedComponent = new Set([componentName]); - } - - if (isFlushingPassiveEffects); - else { - var previousFiber = current; - - try { - setCurrentFiber(fiber); - - error( - "Can't perform a React state update on an unmounted component. This " + - "is a no-op, but it indicates a memory leak in your application. To " + - "fix, cancel all subscriptions and asynchronous tasks in %s.", - tag === ClassComponent - ? "the componentWillUnmount method" - : "a useEffect cleanup function" - ); - } finally { - if (previousFiber) { - setCurrentFiber(fiber); - } else { - resetCurrentFiber(); - } - } - } - } -} - var beginWork$1; { diff --git a/Libraries/Renderer/implementations/ReactFabric-prod.fb.js b/Libraries/Renderer/implementations/ReactFabric-prod.fb.js index 9f511d0cc9f7d8..1269db5791b921 100644 --- a/Libraries/Renderer/implementations/ReactFabric-prod.fb.js +++ b/Libraries/Renderer/implementations/ReactFabric-prod.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<> + * @generated SignedSource<<64b88a48c0e9e26ebfbee2286b912b78>> */ "use strict"; @@ -1946,8 +1946,6 @@ function createTextInstance( hostContext, internalInstanceHandle ) { - if (!hostContext.isInAParentText) - throw Error("Text strings must be rendered within a component."); hostContext = nextReactTag; nextReactTag += 2; return { @@ -3536,7 +3534,7 @@ function rerenderReducer(reducer) { } return [newState, dispatch]; } -function readFromUnsubcribedMutableSource(root, source, getSnapshot) { +function readFromUnsubscribedMutableSource(root, source, getSnapshot) { var getVersion = source._getVersion; getVersion = getVersion(source._source); var JSCompiler_inline_result = source._workInProgressVersionSecondary; @@ -3563,7 +3561,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { version = getVersion(source._source), dispatcher = ReactCurrentDispatcher$1.current, _dispatcher$useState = dispatcher.useState(function() { - return readFromUnsubcribedMutableSource(root, source, getSnapshot); + return readFromUnsubscribedMutableSource(root, source, getSnapshot); }), setSnapshot = _dispatcher$useState[1], snapshot = _dispatcher$useState[0]; @@ -3626,7 +3624,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { )), (_dispatcher$useState.queue = hook), (_dispatcher$useState.baseQueue = null), - (snapshot = readFromUnsubcribedMutableSource(root, source, getSnapshot)), + (snapshot = readFromUnsubscribedMutableSource(root, source, getSnapshot)), (_dispatcher$useState.memoizedState = _dispatcher$useState.baseState = snapshot)); return snapshot; } @@ -7935,7 +7933,7 @@ var roots = new Map(), devToolsConfig$jscomp$inline_948 = { findFiberByHostInstance: getInstanceFromInstance, bundleType: 0, - version: "18.0.0-424fe5870-20210816", + version: "18.0.0-bd5bf555e-20210823", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -7977,7 +7975,7 @@ var internals$jscomp$inline_1189 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.0.0-424fe5870-20210816" + reconcilerVersion: "18.0.0-bd5bf555e-20210823" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_1190 = __REACT_DEVTOOLS_GLOBAL_HOOK__; diff --git a/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js b/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js index 6d11b263d2840c..9f9e059864013e 100644 --- a/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js +++ b/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<0a406a6dac4993a931e2decfc7b53f27>> + * @generated SignedSource<> */ "use strict"; @@ -1994,8 +1994,6 @@ function createTextInstance( hostContext, internalInstanceHandle ) { - if (!hostContext.isInAParentText) - throw Error("Text strings must be rendered within a component."); hostContext = nextReactTag; nextReactTag += 2; return { @@ -3584,7 +3582,7 @@ function rerenderReducer(reducer) { } return [newState, dispatch]; } -function readFromUnsubcribedMutableSource(root, source, getSnapshot) { +function readFromUnsubscribedMutableSource(root, source, getSnapshot) { var getVersion = source._getVersion; getVersion = getVersion(source._source); var JSCompiler_inline_result = source._workInProgressVersionSecondary; @@ -3611,7 +3609,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { version = getVersion(source._source), dispatcher = ReactCurrentDispatcher$1.current, _dispatcher$useState = dispatcher.useState(function() { - return readFromUnsubcribedMutableSource(root, source, getSnapshot); + return readFromUnsubscribedMutableSource(root, source, getSnapshot); }), setSnapshot = _dispatcher$useState[1], snapshot = _dispatcher$useState[0]; @@ -3674,7 +3672,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { )), (_dispatcher$useState.queue = hook), (_dispatcher$useState.baseQueue = null), - (snapshot = readFromUnsubcribedMutableSource(root, source, getSnapshot)), + (snapshot = readFromUnsubscribedMutableSource(root, source, getSnapshot)), (_dispatcher$useState.memoizedState = _dispatcher$useState.baseState = snapshot)); return snapshot; } @@ -8380,7 +8378,7 @@ var roots = new Map(), devToolsConfig$jscomp$inline_978 = { findFiberByHostInstance: getInstanceFromInstance, bundleType: 0, - version: "18.0.0-424fe5870-20210816", + version: "18.0.0-bd5bf555e-20210823", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -8422,7 +8420,7 @@ var internals$jscomp$inline_1239 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.0.0-424fe5870-20210816" + reconcilerVersion: "18.0.0-bd5bf555e-20210823" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_1240 = __REACT_DEVTOOLS_GLOBAL_HOOK__; diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js b/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js index 248c4ec9e36553..65eb780282e50c 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<> + * @generated SignedSource<<121565373640523240f808b242fb487f>> */ 'use strict'; @@ -3226,7 +3226,7 @@ var MountPassiveDev = 4194304; // Groups of flags that are used in the commit phase to skip over trees that // don't contain effects, by checking subtreeFlags. -var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visiblity +var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility // flag logic (see #20043) Update | Snapshot | 0; var MutationMask = @@ -3240,7 +3240,7 @@ var MutationMask = var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask var PassiveMask = Passive | ChildDeletion; // Union of tags that don't get reset on clones. -// This allows certain concepts to persist without recalculting them, +// This allows certain concepts to persist without recalculating them, // e.g. whether a subtree contains passive effects or portals. var StaticMask = LayoutStatic | PassiveStatic | RefStatic; @@ -6095,7 +6095,7 @@ function flushSyncCallbacksOnlyInLegacyMode() { } function flushSyncCallbacks() { if (!isFlushingSyncQueue && syncQueue !== null) { - // Prevent re-entrancy. + // Prevent re-entrance. isFlushingSyncQueue = true; var i = 0; var previousUpdatePriority = getCurrentUpdatePriority(); @@ -6134,22 +6134,7 @@ function flushSyncCallbacks() { return null; } -var NoFlags$1 = - /* */ - 0; // Represents whether effect should fire. - -var HasEffect = - /* */ - 1; // Represents the phase in which the effect (not the clean-up) fires. - -var Layout = - /* */ - 2; -var Passive$1 = - /* */ - 4; - -var ReactVersion = "18.0.0-424fe5870-20210816"; +var ReactVersion = "18.0.0-bd5bf555e-20210823"; var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; var NoTransition = 0; @@ -6946,7 +6931,7 @@ function readContext(context) { // An array of all update queues that received updates during the current // render. When this render exits, either because it finishes or because it is -// interrupted, the interleaved updates will be transfered onto the main part +// interrupted, the interleaved updates will be transferred onto the main part // of the queue. var interleavedQueues = null; function pushInterleavedQueue(queue) { @@ -7059,7 +7044,7 @@ function enqueueUpdate(fiber, update, lane) { if (interleaved === null) { // This is the first update. Create a circular list. update.next = update; // At the end of the current render, this queue's interleaved updates will - // be transfered to the pending queue. + // be transferred to the pending queue. pushInterleavedQueue(sharedQueue); } else { @@ -10102,6 +10087,21 @@ function findFirstSuspended(row) { return null; } +var NoFlags$1 = + /* */ + 0; // Represents whether effect should fire. + +var HasEffect = + /* */ + 1; // Represents the phase in which the effect (not the clean-up) fires. + +var Layout = + /* */ + 2; +var Passive$1 = + /* */ + 4; + var isHydrating = false; function enterHydrationState(fiber) { @@ -10470,7 +10470,7 @@ function renderWithHooks( children = Component(props, secondArg); } while (didScheduleRenderPhaseUpdateDuringThisPass); } // We can assume the previous dispatcher is always this one, since we set it - // at the beginning of the render phase and there's no re-entrancy. + // at the beginning of the render phase and there's no re-entrance. ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; @@ -10538,7 +10538,7 @@ function bailoutHooks(current, workInProgress, lanes) { } function resetHooksAfterThrow() { // We can assume the previous dispatcher is always this one, since we set it - // at the beginning of the render phase and there's no re-entrancy. + // at the beginning of the render phase and there's no re-entrance. ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; if (didScheduleRenderPhaseUpdate) { @@ -10903,7 +10903,7 @@ function rerenderReducer(reducer, initialArg, init) { return [newState, dispatch]; } -function readFromUnsubcribedMutableSource(root, source, getSnapshot) { +function readFromUnsubscribedMutableSource(root, source, getSnapshot) { { warnAboutMultipleRenderersDEV(source); } @@ -11035,7 +11035,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { var dispatcher = ReactCurrentDispatcher$1.current; // eslint-disable-next-line prefer-const var _dispatcher$useState = dispatcher.useState(function() { - return readFromUnsubcribedMutableSource(root, source, getSnapshot); + return readFromUnsubscribedMutableSource(root, source, getSnapshot); }), currentSnapshot = _dispatcher$useState[0], setSnapshot = _dispatcher$useState[1]; @@ -11164,7 +11164,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { ); stateHook.queue = newQueue; stateHook.baseQueue = null; - snapshot = readFromUnsubcribedMutableSource(root, source, getSnapshot); + snapshot = readFromUnsubscribedMutableSource(root, source, getSnapshot); stateHook.memoizedState = stateHook.baseState = snapshot; } @@ -11704,7 +11704,7 @@ function dispatchAction(fiber, queue, action) { if (interleaved === null) { // This is the first update. Create a circular list. update.next = update; // At the end of the current render, this queue's interleaved updates will - // be transfered to the pending queue. + // be transferred to the pending queue. pushInterleavedQueue(queue); } else { @@ -13892,7 +13892,7 @@ function completeWork(current, workInProgress, renderLanes) { workInProgress.flags |= DidCapture; cutOffTailIfNeeded(renderState, false); // If this is a newly suspended tree, it might not get committed as // part of the second pass. In that case nothing will subscribe to - // its thennables. Instead, we'll transfer its thennables to the + // its thenables. Instead, we'll transfer its thenables to the // SuspenseList so that it can retry if they resolve. // There might be multiple of these in the list but since we're // going to wait for all of them anyway, it doesn't really matter @@ -13903,10 +13903,10 @@ function completeWork(current, workInProgress, renderLanes) { // doesn't matter since that means that the other boundaries that // we did find already has their listeners attached. - var newThennables = suspended.updateQueue; + var newThenables = suspended.updateQueue; - if (newThennables !== null) { - workInProgress.updateQueue = newThennables; + if (newThenables !== null) { + workInProgress.updateQueue = newThenables; workInProgress.flags |= Update; } // Rerender the whole list, but this time, we'll force fallbacks // to stay in place. @@ -13962,10 +13962,10 @@ function completeWork(current, workInProgress, renderLanes) { didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't // get lost if this row ends up dropped during a second pass. - var _newThennables = _suspended.updateQueue; + var _newThenables = _suspended.updateQueue; - if (_newThennables !== null) { - workInProgress.updateQueue = _newThennables; + if (_newThenables !== null) { + workInProgress.updateQueue = _newThenables; workInProgress.flags |= Update; } @@ -15515,7 +15515,7 @@ function shouldRemainOnFallback( var suspenseState = current.memoizedState; if (suspenseState === null) { - // Currently showing content. Don't hide it, even if ForceSuspenseFallack + // Currently showing content. Don't hide it, even if ForceSuspenseFallback // is true. More precise name might be "ForceRemainSuspenseFallback". // Note: This is a factoring smell. Can't remain on a fallback if there's // no fallback to remain on. @@ -15567,7 +15567,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); pushSuspenseContext(workInProgress, suspenseContext); // OK, the next part is confusing. We're about to reconcile the Suspense - // boundary's children. This involves some custom reconcilation logic. Two + // boundary's children. This involves some custom reconciliation logic. Two // main reasons this is so complicated. // // First, Legacy Mode has different semantics for backwards compatibility. The @@ -18772,7 +18772,7 @@ function commitMutationEffectsOnFiber(finishedWork, root) { // TODO: The factoring of this phase could probably be improved. Consider // switching on the type of work before checking the flags. That's what // we do in all the other phases. I think this one is only different - // because of the shared reconcilation logic below. + // because of the shared reconciliation logic below. var flags = finishedWork.flags; if (flags & ContentReset) { @@ -19436,10 +19436,7 @@ var nestedPassiveUpdateCount = 0; // If two updates are scheduled within the sam // between the first and second call. var currentEventTime = NoTimestamp; -var currentEventTransitionLane = NoLanes; // Dev only flag that tracks if passive effects are currently being flushed. -// We warn about state updates for unmounted components differently in this case. - -var isFlushingPassiveEffects = false; +var currentEventTransitionLane = NoLanes; function getWorkInProgressRoot() { return workInProgressRoot; } @@ -19537,7 +19534,6 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { var root = markUpdateLaneFromFiberToRoot(fiber, lane); if (root === null) { - warnAboutUpdateOnUnmountedFiberInDEV(fiber); return null; } @@ -20862,10 +20858,6 @@ function flushPassiveEffectsImpl() { throw Error("Cannot flush passive effects while already rendering."); } - { - isFlushingPassiveEffects = true; - } - var prevExecutionContext = executionContext; executionContext |= CommitContext; commitPassiveUnmountEffects(root.current); @@ -20881,10 +20873,6 @@ function flushPassiveEffectsImpl() { } } - { - isFlushingPassiveEffects = false; - } - { commitDoubleInvokeEffectsInDEV(root.current, true); } @@ -21264,86 +21252,6 @@ function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { } } -var didWarnStateUpdateForUnmountedComponent = null; - -function warnAboutUpdateOnUnmountedFiberInDEV(fiber) { - { - var tag = fiber.tag; - - if ( - tag !== HostRoot && - tag !== ClassComponent && - tag !== FunctionComponent && - tag !== ForwardRef && - tag !== MemoComponent && - tag !== SimpleMemoComponent - ) { - // Only warn for user-defined components, not internal ones like Suspense. - return; - } - - if ((fiber.flags & PassiveStatic) !== NoFlags) { - var updateQueue = fiber.updateQueue; - - if (updateQueue !== null) { - var lastEffect = updateQueue.lastEffect; - - if (lastEffect !== null) { - var firstEffect = lastEffect.next; - var effect = firstEffect; - - do { - if (effect.destroy !== undefined) { - if ((effect.tag & Passive$1) !== NoFlags$1) { - return; - } - } - - effect = effect.next; - } while (effect !== firstEffect); - } - } - } // We show the whole stack but dedupe on the top component's name because - // the problematic code almost always lies inside that component. - - var componentName = getComponentNameFromFiber(fiber) || "ReactComponent"; - - if (didWarnStateUpdateForUnmountedComponent !== null) { - if (didWarnStateUpdateForUnmountedComponent.has(componentName)) { - return; - } - - didWarnStateUpdateForUnmountedComponent.add(componentName); - } else { - didWarnStateUpdateForUnmountedComponent = new Set([componentName]); - } - - if (isFlushingPassiveEffects); - else { - var previousFiber = current; - - try { - setCurrentFiber(fiber); - - error( - "Can't perform a React state update on an unmounted component. This " + - "is a no-op, but it indicates a memory leak in your application. To " + - "fix, cancel all subscriptions and asynchronous tasks in %s.", - tag === ClassComponent - ? "the componentWillUnmount method" - : "a useEffect cleanup function" - ); - } finally { - if (previousFiber) { - setCurrentFiber(fiber); - } else { - resetCurrentFiber(); - } - } - } - } -} - var beginWork$1; { diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js b/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js index c75a0b0818d649..e4a6a9d53ff250 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<31a717b21f9596e634345cda771448c2>> + * @generated SignedSource<<4b2938a7eccbcb5ebcaad8eeb6f50cee>> */ "use strict"; @@ -3505,7 +3505,7 @@ function rerenderReducer(reducer) { } return [newState, dispatch]; } -function readFromUnsubcribedMutableSource(root, source, getSnapshot) { +function readFromUnsubscribedMutableSource(root, source, getSnapshot) { var getVersion = source._getVersion; getVersion = getVersion(source._source); var JSCompiler_inline_result = source._workInProgressVersionPrimary; @@ -3532,7 +3532,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { version = getVersion(source._source), dispatcher = ReactCurrentDispatcher$1.current, _dispatcher$useState = dispatcher.useState(function() { - return readFromUnsubcribedMutableSource(root, source, getSnapshot); + return readFromUnsubscribedMutableSource(root, source, getSnapshot); }), setSnapshot = _dispatcher$useState[1], snapshot = _dispatcher$useState[0]; @@ -3595,7 +3595,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { )), (_dispatcher$useState.queue = hook), (_dispatcher$useState.baseQueue = null), - (snapshot = readFromUnsubcribedMutableSource(root, source, getSnapshot)), + (snapshot = readFromUnsubscribedMutableSource(root, source, getSnapshot)), (_dispatcher$useState.memoizedState = _dispatcher$useState.baseState = snapshot)); return snapshot; } @@ -8024,7 +8024,7 @@ var roots = new Map(), devToolsConfig$jscomp$inline_984 = { findFiberByHostInstance: getInstanceFromTag, bundleType: 0, - version: "18.0.0-424fe5870-20210816", + version: "18.0.0-bd5bf555e-20210823", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -8066,7 +8066,7 @@ var internals$jscomp$inline_1237 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.0.0-424fe5870-20210816" + reconcilerVersion: "18.0.0-bd5bf555e-20210823" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_1238 = __REACT_DEVTOOLS_GLOBAL_HOOK__; diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js b/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js index c7797d66121821..285eb62ebf971d 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<> + * @generated SignedSource<<0c9b6f8df4fa2dc914b10ed49e47e8c7>> */ "use strict"; @@ -3553,7 +3553,7 @@ function rerenderReducer(reducer) { } return [newState, dispatch]; } -function readFromUnsubcribedMutableSource(root, source, getSnapshot) { +function readFromUnsubscribedMutableSource(root, source, getSnapshot) { var getVersion = source._getVersion; getVersion = getVersion(source._source); var JSCompiler_inline_result = source._workInProgressVersionPrimary; @@ -3580,7 +3580,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { version = getVersion(source._source), dispatcher = ReactCurrentDispatcher$1.current, _dispatcher$useState = dispatcher.useState(function() { - return readFromUnsubcribedMutableSource(root, source, getSnapshot); + return readFromUnsubscribedMutableSource(root, source, getSnapshot); }), setSnapshot = _dispatcher$useState[1], snapshot = _dispatcher$useState[0]; @@ -3643,7 +3643,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { )), (_dispatcher$useState.queue = hook), (_dispatcher$useState.baseQueue = null), - (snapshot = readFromUnsubcribedMutableSource(root, source, getSnapshot)), + (snapshot = readFromUnsubscribedMutableSource(root, source, getSnapshot)), (_dispatcher$useState.memoizedState = _dispatcher$useState.baseState = snapshot)); return snapshot; } @@ -8457,7 +8457,7 @@ var roots = new Map(), devToolsConfig$jscomp$inline_1014 = { findFiberByHostInstance: getInstanceFromTag, bundleType: 0, - version: "18.0.0-424fe5870-20210816", + version: "18.0.0-bd5bf555e-20210823", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -8499,7 +8499,7 @@ var internals$jscomp$inline_1287 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.0.0-424fe5870-20210816" + reconcilerVersion: "18.0.0-bd5bf555e-20210823" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_1288 = __REACT_DEVTOOLS_GLOBAL_HOOK__; diff --git a/Libraries/StyleSheet/__tests__/normalizeColor-test.js b/Libraries/StyleSheet/__tests__/normalizeColor-test.js index 5421edccd23319..f07498751e2829 100644 --- a/Libraries/StyleSheet/__tests__/normalizeColor-test.js +++ b/Libraries/StyleSheet/__tests__/normalizeColor-test.js @@ -13,13 +13,11 @@ const {OS} = require('../../Utilities/Platform'); const normalizeColor = require('../normalizeColor'); -it('forwards calls to @react-native/normalize-color/base', () => { - jest - .resetModules() - .mock('@react-native/normalize-color/base', () => jest.fn()); +it('forwards calls to @react-native/normalize-color', () => { + jest.resetModules().mock('@react-native/normalize-color', () => jest.fn()); expect(require('../normalizeColor')('#abc')).not.toBe(null); - expect(require('@react-native/normalize-color/base')).toBeCalled(); + expect(require('@react-native/normalize-color')).toBeCalled(); }); describe('iOS', () => { diff --git a/Libraries/StyleSheet/normalizeColor.js b/Libraries/StyleSheet/normalizeColor.js index 4ba0dae0085f11..89a672c4567ddc 100755 --- a/Libraries/StyleSheet/normalizeColor.js +++ b/Libraries/StyleSheet/normalizeColor.js @@ -10,7 +10,7 @@ /* eslint no-bitwise: 0 */ -import normalizeColorBase from '@react-native/normalize-color/base'; +import _normalizeColor from '@react-native/normalize-color'; import type {ColorValue} from './StyleSheet'; import type {ProcessedColorValue} from './processColor'; @@ -27,7 +27,7 @@ function normalizeColor( } if (typeof color === 'string' || typeof color === 'number') { - return normalizeColorBase(color); + return _normalizeColor(color); } } diff --git a/Libraries/Text/TextProps.js b/Libraries/Text/TextProps.js index b2a39e58df768e..3942a5998cd343 100644 --- a/Libraries/Text/TextProps.js +++ b/Libraries/Text/TextProps.js @@ -66,13 +66,7 @@ export type TextProps = $ReadOnly<{| * Set hyphenation strategy on Android. * */ - android_hyphenationFrequency?: ?( - | 'normal' - | 'none' - | 'full' - | 'high' - | 'balanced' - ), + android_hyphenationFrequency?: ?('normal' | 'none' | 'full'), children?: ?Node, /** diff --git a/Libraries/TurboModule/TurboModuleRegistry.js b/Libraries/TurboModule/TurboModuleRegistry.js index 90e30dd081591a..9e2f762937cce3 100644 --- a/Libraries/TurboModule/TurboModuleRegistry.js +++ b/Libraries/TurboModule/TurboModuleRegistry.js @@ -16,7 +16,7 @@ const turboModuleProxy = global.__turboModuleProxy; function requireModule(name: string): ?T { // Bridgeless mode requires TurboModules - if (!global.RN$Bridgeless) { + if (global.RN$Bridgeless !== true) { // Backward compatibility layer during migration. const legacyModule = NativeModules[name]; if (legacyModule != null) { diff --git a/Libraries/UTFSequence.js b/Libraries/UTFSequence.js index 65a548df756787..dabcaff86662d1 100644 --- a/Libraries/UTFSequence.js +++ b/Libraries/UTFSequence.js @@ -16,7 +16,7 @@ const deepFreezeAndThrowOnMutationInDev = require('./Utilities/deepFreezeAndThro * A collection of Unicode sequences for various characters and emoji. * * - More explicit than using the sequences directly in code. - * - Source code should be limitted to ASCII. + * - Source code should be limited to ASCII. * - Less chance of typos. */ const UTFSequence: {| diff --git a/Libraries/Utilities/HMRClient.js b/Libraries/Utilities/HMRClient.js index 7405010b5d95bf..e1d8f56c49ab30 100644 --- a/Libraries/Utilities/HMRClient.js +++ b/Libraries/Utilities/HMRClient.js @@ -48,6 +48,7 @@ export type HMRClientNativeInterface = {| host: string, port: number | string, isEnabled: boolean, + scheme?: string, ): void, |}; @@ -118,7 +119,7 @@ const HMRClient: HMRClientNativeInterface = { JSON.stringify({ type: 'log', level, - mode: global.RN$Bridgeless ? 'NOBRIDGE' : 'BRIDGE', + mode: global.RN$Bridgeless === true ? 'NOBRIDGE' : 'BRIDGE', data: data.map(item => typeof item === 'string' ? item @@ -146,6 +147,7 @@ const HMRClient: HMRClientNativeInterface = { host: string, port: number | string, isEnabled: boolean, + scheme?: string = 'http', ) { invariant(platform, 'Missing required parameter `platform`'); invariant(bundleEntry, 'Missing required parameter `bundleEntry`'); @@ -155,8 +157,12 @@ const HMRClient: HMRClientNativeInterface = { // Moving to top gives errors due to NativeModules not being initialized const LoadingView = require('./LoadingView'); - const wsHost = port !== null && port !== '' ? `${host}:${port}` : host; - const client = new MetroHMRClient(`ws://${wsHost}/hot`); + const serverHost = port !== null && port !== '' ? `${host}:${port}` : host; + + const serverScheme = scheme; + + const client = new MetroHMRClient(`${serverScheme}://${serverHost}/hot`); + hmrClient = client; const {fullBundleUrl} = getDevServer(); @@ -165,9 +171,7 @@ const HMRClient: HMRClientNativeInterface = { // there are any important URL parameters we can't reconstruct from // `setup()`'s arguments. fullBundleUrl ?? - // The ws://.../hot?bundleEntry= format is an alternative to specifying - // a regular HTTP bundle URL. - `ws://${wsHost}/hot?bundleEntry=${bundleEntry}&platform=${platform}`, + `${serverScheme}://${serverHost}/hot?bundleEntry=${bundleEntry}&platform=${platform}`, ); client.on('connection-error', e => { diff --git a/Libraries/Utilities/MatrixMath.js b/Libraries/Utilities/MatrixMath.js index f316bea68611fc..d2d6421106b53b 100755 --- a/Libraries/Utilities/MatrixMath.js +++ b/Libraries/Utilities/MatrixMath.js @@ -71,7 +71,7 @@ const MatrixMath = { * This create a perspective projection towards negative z * Clipping the z range of [-near, -far] * - * @param fovInRadians - field of view in randians + * @param fovInRadians - field of view in radians */ createPerspective: function(fovInRadians, aspect, near, far) { const h = 1 / Math.tan(fovInRadians / 2); diff --git a/Libraries/Utilities/deprecatedPropType.js b/Libraries/Utilities/deprecatedPropType.js index 454b9bc855e982..0a0fc69aab2a0e 100644 --- a/Libraries/Utilities/deprecatedPropType.js +++ b/Libraries/Utilities/deprecatedPropType.js @@ -20,8 +20,8 @@ function deprecatedPropType( return function validate(props, propName, componentName, ...rest) { // Don't warn for native components. if ( - !global.RN$Bridgeless && - UIManager.hasViewManagerConfig(componentName) && + global.RN$Bridgeless !== true && + !UIManager.hasViewManagerConfig(componentName) && props[propName] !== undefined ) { console.warn( diff --git a/Libraries/vendor/emitter/_EventSubscriptionVendor.js b/Libraries/vendor/emitter/_EventSubscriptionVendor.js index ace97393e42537..9ac31438f305ad 100644 --- a/Libraries/vendor/emitter/_EventSubscriptionVendor.js +++ b/Libraries/vendor/emitter/_EventSubscriptionVendor.js @@ -58,7 +58,7 @@ class EventSubscriptionVendor { * Removes a bulk set of the subscriptions. * * @param {?string} eventType - Optional name of the event type whose - * registered supscriptions to remove, if null remove all subscriptions. + * registered subscriptions to remove, if null remove all subscriptions. */ removeAllSubscriptions>(eventType: ?K): void { if (eventType == null) { diff --git a/React/Base/RCTBridge+Private.h b/React/Base/RCTBridge+Private.h index 70a20f0b00f632..9dd96a5cd140d2 100644 --- a/React/Base/RCTBridge+Private.h +++ b/React/Base/RCTBridge+Private.h @@ -7,6 +7,7 @@ #import +@class RCTModuleRegistry; @class RCTModuleData; @protocol RCTJavaScriptExecutor; @@ -62,6 +63,13 @@ RCT_EXTERN void RCTRegisterModule(Class); */ @property (nonatomic, strong, readwrite) NSURL *bundleURL; +/** + * An object that allows one to require NativeModules/TurboModules. + * RCTModuleRegistry is implemented in bridgeless mode and bridge mode. + * Used by RCTRootView. + */ +@property (nonatomic, strong, readonly) RCTModuleRegistry *moduleRegistry; + @end @interface RCTBridge (RCTCxxBridge) diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index 850c78c135adea..10503261d72b96 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -257,6 +257,11 @@ - (void)didReceiveReloadCommand }); } +- (RCTModuleRegistry *)moduleRegistry +{ + return self.batchedBridge.moduleRegistry; +} + - (NSArray *)moduleClasses { return self.batchedBridge.moduleClasses; diff --git a/React/Base/RCTBundleURLProvider.h b/React/Base/RCTBundleURLProvider.h index 890f8c3819a163..1192f973790702 100644 --- a/React/Base/RCTBundleURLProvider.h +++ b/React/Base/RCTBundleURLProvider.h @@ -52,6 +52,13 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed); */ + (BOOL)isPackagerRunning:(NSString *)hostPort; +/** + * Returns if there's a packager running at the given scheme://host:port. + * The port is optional, if not specified, kRCTBundleURLProviderDefaultPort will be used + * The scheme is also optional, if not specified, a default http protocol will be used + */ ++ (BOOL)isPackagerRunning:(NSString *)hostPort scheme:(NSString *)scheme; + /** * Returns the jsBundleURL for a given bundle entrypoint and * the fallback offline JS bundle if the packager is not running. @@ -99,9 +106,15 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed); * The IP address or hostname of the packager. */ @property (nonatomic, copy) NSString *jsLocation; + @property (nonatomic, assign) BOOL enableMinification; @property (nonatomic, assign) BOOL enableDev; +/** + * The scheme/protocol used of the packager, the default is the http protocol + */ +@property (nonatomic, copy) NSString *packagerScheme; + + (instancetype)sharedSettings; /** @@ -129,6 +142,13 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed); modulesOnly:(BOOL)modulesOnly runModule:(BOOL)runModule; ++ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot + packagerHost:(NSString *)packagerHost + packagerScheme:(NSString *)scheme + enableDev:(BOOL)enableDev + enableMinification:(BOOL)enableMinification + modulesOnly:(BOOL)modulesOnly + runModule:(BOOL)runModule; /** * Given a hostname for the packager and a resource path (including "/"), return the URL to the resource. * In general, please use the instance method to decide if the packager is running and fallback to the pre-packaged @@ -136,4 +156,9 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed); */ + (NSURL *)resourceURLForResourcePath:(NSString *)path packagerHost:(NSString *)packagerHost query:(NSString *)query; ++ (NSURL *)resourceURLForResourcePath:(NSString *)path + packagerHost:(NSString *)packagerHost + scheme:(NSString *)scheme + query:(NSString *)query; + @end diff --git a/React/Base/RCTBundleURLProvider.mm b/React/Base/RCTBundleURLProvider.mm index 393ca5631026ff..d819e1b99d3ce8 100644 --- a/React/Base/RCTBundleURLProvider.mm +++ b/React/Base/RCTBundleURLProvider.mm @@ -22,7 +22,7 @@ void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed) kRCTAllowPackagerAccess = allowed; } #endif - +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"; @@ -65,20 +65,29 @@ - (void)resetToDefaults [self settingsUpdated]; } -static NSURL *serverRootWithHostPort(NSString *hostPort) +static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme) { + if (![scheme length]) { + scheme = @"http"; + } if ([hostPort rangeOfString:@":"].location != NSNotFound) { - return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/", hostPort]]; + return [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/", scheme, hostPort]]; } - return [NSURL - URLWithString:[NSString - stringWithFormat:@"http://%@:%lu/", hostPort, (unsigned long)kRCTBundleURLProviderDefaultPort]]; + return [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@:%lu/", + scheme, + hostPort, + (unsigned long)kRCTBundleURLProviderDefaultPort]]; } #if RCT_DEV_MENU + (BOOL)isPackagerRunning:(NSString *)hostPort { - NSURL *url = [serverRootWithHostPort(hostPort) URLByAppendingPathComponent:@"status"]; + return [RCTBundleURLProvider isPackagerRunning:hostPort scheme:nil]; +} + ++ (BOOL)isPackagerRunning:(NSString *)hostPort scheme:(NSString *)scheme +{ + NSURL *url = [serverRootWithHostPort(hostPort, scheme) URLByAppendingPathComponent:@"status"]; NSURLSession *session = [NSURLSession sharedSession]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; @@ -120,6 +129,11 @@ + (BOOL)isPackagerRunning:(NSString *)hostPort { return false; } + ++ (BOOL)isPackagerRunning:(NSString *)hostPort scheme:(NSString *)scheme +{ + return false; +} #endif - (NSString *)packagerServerHost @@ -144,7 +158,8 @@ - (NSString *)packagerServerHostPort #endif NSString *location = [self jsLocation]; #if RCT_DEV_MENU - if ([location length] && ![RCTBundleURLProvider isPackagerRunning:location]) { + NSString *scheme = [self packagerScheme]; + if ([location length] && ![RCTBundleURLProvider isPackagerRunning:location scheme:scheme]) { location = nil; } #endif @@ -168,8 +183,11 @@ - (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot fallbackURLProvider:( } else { return [RCTBundleURLProvider jsBundleURLForBundleRoot:bundleRoot packagerHost:packagerServerHostPort + packagerScheme:[self packagerScheme] enableDev:[self enableDev] - enableMinification:[self enableMinification]]; + enableMinification:[self enableMinification] + modulesOnly:NO + runModule:YES]; } } @@ -177,6 +195,7 @@ - (NSURL *)jsBundleURLForSplitBundleRoot:(NSString *)bundleRoot { return [RCTBundleURLProvider jsBundleURLForBundleRoot:bundleRoot packagerHost:[self packagerServerHostPort] + packagerScheme:[self packagerScheme] enableDev:[self enableDev] enableMinification:[self enableMinification] modulesOnly:YES @@ -211,13 +230,17 @@ - (NSURL *)resourceURLForResourceRoot:(NSString *)root offlineBundle:(NSBundle *)offlineBundle { NSString *packagerServerHostPort = [self packagerServerHostPort]; + NSString *packagerServerScheme = [self packagerScheme]; if (!packagerServerHostPort) { // Serve offline bundle (local file) NSBundle *bundle = offlineBundle ?: [NSBundle mainBundle]; return [bundle URLForResource:name withExtension:extension]; } NSString *path = [NSString stringWithFormat:@"/%@/%@.%@", root, name, extension]; - return [[self class] resourceURLForResourcePath:path packagerHost:packagerServerHostPort query:nil]; + return [[self class] resourceURLForResourcePath:path + packagerHost:packagerServerHostPort + scheme:packagerServerScheme + query:nil]; } + (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot @@ -240,6 +263,23 @@ + (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot enableMinification:(BOOL)enableMinification modulesOnly:(BOOL)modulesOnly runModule:(BOOL)runModule +{ + return [[self class] jsBundleURLForBundleRoot:bundleRoot + packagerHost:packagerHost + packagerScheme:nil + enableDev:enableDev + enableMinification:enableMinification + modulesOnly:modulesOnly + runModule:runModule]; +} + ++ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot + packagerHost:(NSString *)packagerHost + packagerScheme:(NSString *)scheme + enableDev:(BOOL)enableDev + enableMinification:(BOOL)enableMinification + modulesOnly:(BOOL)modulesOnly + runModule:(BOOL)runModule { NSString *path = [NSString stringWithFormat:@"/%@.bundle", bundleRoot]; #ifdef HERMES_BYTECODE_VERSION @@ -260,12 +300,20 @@ + (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot if (bundleID) { query = [NSString stringWithFormat:@"%@&app=%@", query, bundleID]; } - return [[self class] resourceURLForResourcePath:path packagerHost:packagerHost query:query]; + return [[self class] resourceURLForResourcePath:path packagerHost:packagerHost scheme:scheme query:query]; } + (NSURL *)resourceURLForResourcePath:(NSString *)path packagerHost:(NSString *)packagerHost query:(NSString *)query { - NSURLComponents *components = [NSURLComponents componentsWithURL:serverRootWithHostPort(packagerHost) + return [[self class] resourceURLForResourcePath:path packagerHost:packagerHost scheme:nil query:query]; +} + ++ (NSURL *)resourceURLForResourcePath:(NSString *)path + packagerHost:(NSString *)packagerHost + scheme:(NSString *)scheme + query:(NSString *)query +{ + NSURLComponents *components = [NSURLComponents componentsWithURL:serverRootWithHostPort(packagerHost, scheme) resolvingAgainstBaseURL:NO]; components.path = path; if (query != nil) { @@ -296,6 +344,15 @@ - (NSString *)jsLocation return [[NSUserDefaults standardUserDefaults] stringForKey:kRCTJsLocationKey]; } +- (NSString *)packagerScheme +{ + NSString *packagerScheme = [[NSUserDefaults standardUserDefaults] stringForKey:kRCTPackagerSchemeKey]; + if (![packagerScheme length]) { + return @"http"; + } + return packagerScheme; +} + - (void)setEnableDev:(BOOL)enableDev { [self updateValue:@(enableDev) forKey:kRCTEnableDevKey]; @@ -311,6 +368,11 @@ - (void)setEnableMinification:(BOOL)enableMinification [self updateValue:@(enableMinification) forKey:kRCTEnableMinificationKey]; } +- (void)setPackagerScheme:(NSString *)packagerScheme +{ + [self updateValue:packagerScheme forKey:kRCTPackagerSchemeKey]; +} + + (instancetype)sharedSettings { static RCTBundleURLProvider *sharedInstance; diff --git a/React/Base/RCTConstants.h b/React/Base/RCTConstants.h index c92fc1041c9aef..06fbc7597cae46 100644 --- a/React/Base/RCTConstants.h +++ b/React/Base/RCTConstants.h @@ -16,6 +16,12 @@ RCT_EXTERN NSString *const RCTUserInterfaceStyleDidChangeNotificationTraitCollec RCT_EXTERN BOOL RCTExperimentGetPreemptiveViewAllocationDisabled(void); RCT_EXTERN void RCTExperimentSetPreemptiveViewAllocationDisabled(BOOL value); +/* + * Initial maximum surface size + */ +RCT_EXTERN BOOL RCTGetInitialMaxSizeEnabled(void); +RCT_EXTERN void RCTSetInitialMaxSizeEnabled(BOOL value); + /* * Remove clipped subviews */ diff --git a/React/Base/RCTConstants.m b/React/Base/RCTConstants.m index 38947bb170f1a7..f734a3384a68e1 100644 --- a/React/Base/RCTConstants.m +++ b/React/Base/RCTConstants.m @@ -25,6 +25,21 @@ void RCTExperimentSetPreemptiveViewAllocationDisabled(BOOL value) RCTExperimentPreemptiveViewAllocationDisabled = value; } +/* + * Initial maximum surface size + */ +static BOOL RCTInitialMaxSizeEnabled = NO; + +BOOL RCTGetInitialMaxSizeEnabled() +{ + return RCTInitialMaxSizeEnabled; +} + +void RCTSetInitialMaxSizeEnabled(BOOL value) +{ + RCTInitialMaxSizeEnabled = value; +} + /* * Remove clipped subviews */ diff --git a/React/Base/RCTCxxConvert.h b/React/Base/RCTCxxConvert.h index b0432caae248c5..261e61f6096223 100644 --- a/React/Base/RCTCxxConvert.h +++ b/React/Base/RCTCxxConvert.h @@ -10,7 +10,7 @@ /** * This class provides a collection of conversion functions for mapping * JSON objects to cxx types. Extensible via categories. - * Convert methods are expected to return cxx objects wraped in RCTManagedPointer. + * Convert methods are expected to return cxx objects wrapped in RCTManagedPointer. */ @interface RCTCxxConvert : NSObject diff --git a/React/Base/RCTEventDispatcherProtocol.h b/React/Base/RCTEventDispatcherProtocol.h index 9e54ccbf187ed8..913cf85228356b 100644 --- a/React/Base/RCTEventDispatcherProtocol.h +++ b/React/Base/RCTEventDispatcherProtocol.h @@ -81,6 +81,8 @@ typedef NS_ENUM(NSInteger, RCTTextEventType) { */ @protocol RCTEventDispatcherProtocol +- (void)sendViewEventWithName:(NSString *)name reactTag:(NSNumber *)reactTag; + /** * Deprecated, do not use. */ diff --git a/React/Base/RCTRootView.h b/React/Base/RCTRootView.h index f555e234c71395..dd563453153110 100644 --- a/React/Base/RCTRootView.h +++ b/React/Base/RCTRootView.h @@ -8,6 +8,8 @@ #import #import +#import +#import @protocol RCTRootViewDelegate; @@ -75,6 +77,19 @@ extern initialProperties:(nullable NSDictionary *)initialProperties launchOptions:(nullable NSDictionary *)launchOptions; +/** + * This API allows RCTRootView users to know if the root view is backed by the bridge. + */ +@property (nonatomic, readonly) BOOL hasBridge; + +/** + * This API allows users of RCTRootView to access other NativeModules, without + * directly accessing the bridge. + */ +@property (nonatomic, strong, readonly) RCTModuleRegistry *moduleRegistry; + +@property (nonatomic, strong, readonly) id eventDispatcher; + /** * The name of the JavaScript module to execute within the * specified scriptURL (required). Setting this will not have diff --git a/React/Base/RCTRootView.m b/React/Base/RCTRootView.m index 7e8a3804d1db65..4da26ee42b1093 100644 --- a/React/Base/RCTRootView.m +++ b/React/Base/RCTRootView.m @@ -116,6 +116,21 @@ - (instancetype)initWithBundleURL:(NSURL *)bundleURL RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame) RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder) +- (BOOL)hasBridge +{ + return _bridge != nil; +} + +- (RCTModuleRegistry *)moduleRegistry +{ + return _bridge.moduleRegistry; +} + +- (id)eventDispatcher +{ + return [self.moduleRegistry moduleForName:"EventDispatcher"]; +} + #pragma mark - passThroughTouches - (BOOL)passThroughTouches diff --git a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h index 8e34cd7583c226..7a42041d0fdc18 100644 --- a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h +++ b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h @@ -26,6 +26,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy, readonly) NSString *moduleName; @property (nonatomic, strong, readonly) RCTBridge *bridge; +@property (nonatomic, readonly) BOOL hasBridge; +@property (nonatomic, strong, readonly) RCTModuleRegistry *moduleRegistry; +@property (nonatomic, strong, readonly) id eventDispatcher; @property (nonatomic, copy, readwrite) NSDictionary *appProperties; @property (nonatomic, assign) RCTRootViewSizeFlexibility sizeFlexibility; @property (nonatomic, weak) id delegate; diff --git a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm index 50f4e745fb167e..ad12ace6ddc5a5 100644 --- a/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm +++ b/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm @@ -10,6 +10,7 @@ #import #import "RCTAssert.h" +#import "RCTBridge+Private.h" #import "RCTBridge.h" #import "RCTLog.h" #import "RCTPerformanceLogger.h" @@ -93,6 +94,21 @@ - (instancetype)initWithBundleURL:(NSURL *)bundleURL return [self initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties]; } +- (BOOL)hasBridge +{ + return _bridge != nil; +} + +- (RCTModuleRegistry *)moduleRegistry +{ + return _bridge.moduleRegistry; +} + +- (id)eventDispatcher +{ + return [self.moduleRegistry moduleForName:"EventDispatcher"]; +} + RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame) RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder) diff --git a/React/CoreModules/RCTDevSettings.mm b/React/CoreModules/RCTDevSettings.mm index 9bc27bd22fb974..9bba3d8d993a54 100644 --- a/React/CoreModules/RCTDevSettings.mm +++ b/React/CoreModules/RCTDevSettings.mm @@ -448,14 +448,16 @@ - (void)addHandler:(id)handler forPackagerMethod:(NSStr - (void)setupHMRClientWithBundleURL:(NSURL *)bundleURL { if (bundleURL && !bundleURL.fileURL) { - NSString *const path = [bundleURL.path substringFromIndex:1]; // Strip initial slash. - NSString *const host = bundleURL.host; - NSNumber *const port = bundleURL.port; + NSURLComponents *urlComponents = [[NSURLComponents alloc] initWithURL:bundleURL resolvingAgainstBaseURL:NO]; + NSString *const path = [urlComponents.path substringFromIndex:1]; // Strip initial slash. + NSString *const host = urlComponents.host; + NSNumber *const port = urlComponents.port; + NSString *const scheme = urlComponents.scheme; BOOL isHotLoadingEnabled = self.isHotLoadingEnabled; if (self.callableJSModules) { [self.callableJSModules invokeModule:@"HMRClient" method:@"setup" - withArgs:@[ @"ios", path, host, RCTNullIfNil(port), @(isHotLoadingEnabled) ]]; + withArgs:@[ @"ios", path, host, RCTNullIfNil(port), @(isHotLoadingEnabled), scheme ]]; } } } diff --git a/React/CoreModules/RCTEventDispatcher.mm b/React/CoreModules/RCTEventDispatcher.mm index d9c690538967b0..5b2dad2d61baaa 100644 --- a/React/CoreModules/RCTEventDispatcher.mm +++ b/React/CoreModules/RCTEventDispatcher.mm @@ -56,6 +56,11 @@ - (void)initialize _observersLock = [NSLock new]; } +- (void)sendViewEventWithName:(NSString *)name reactTag:(NSNumber *)reactTag +{ + [_callableJSModules invokeModule:@"RCTViewEventEmitter" method:@"emit" withArgs:@[ name, RCTNullIfNil(reactTag) ]]; +} + - (void)sendAppEventWithName:(NSString *)name body:(id)body { [_callableJSModules invokeModule:@"RCTNativeAppEventEmitter" diff --git a/React/CoreModules/RCTLogBox.mm b/React/CoreModules/RCTLogBox.mm index 87c5a5bd546f6b..141daf8214caab 100644 --- a/React/CoreModules/RCTLogBox.mm +++ b/React/CoreModules/RCTLogBox.mm @@ -43,18 +43,22 @@ + (BOOL)requiresMainQueueSetup if (!strongSelf) { return; } - if (!strongSelf->_view) { - if (self->_bridge) { - strongSelf->_view = [[RCTLogBoxView alloc] initWithFrame:[UIScreen mainScreen].bounds bridge:self->_bridge]; - } else { - NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:strongSelf, @"logbox", nil]; - [[NSNotificationCenter defaultCenter] postNotificationName:@"CreateLogBoxSurface" - object:nil - userInfo:userInfo]; - return; + + if (strongSelf->_view) { + [strongSelf->_view show]; + return; + } + + if (strongSelf->_bridge) { + if (strongSelf->_bridge.valid) { + strongSelf->_view = [[RCTLogBoxView alloc] initWithFrame:[UIScreen mainScreen].bounds + bridge:strongSelf->_bridge]; + [strongSelf->_view show]; } + } else { + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:strongSelf, @"logbox", nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:@"CreateLogBoxSurface" object:nil userInfo:userInfo]; } - [strongSelf->_view show]; }); } } diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index 0f1a601f4a6ec0..a33b656d9cfb4e 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -244,6 +244,11 @@ @implementation RCTCxxBridge { @synthesize performanceLogger = _performanceLogger; @synthesize valid = _valid; +- (RCTModuleRegistry *)moduleRegistry +{ + return _objCModuleRegistry; +} + - (void)setRCTTurboModuleRegistry:(id)turboModuleRegistry { _turboModuleRegistry = turboModuleRegistry; diff --git a/React/DevSupport/RCTPackagerConnection.mm b/React/DevSupport/RCTPackagerConnection.mm index 4a9ed5b9995314..bffd8b5a64152a 100644 --- a/React/DevSupport/RCTPackagerConnection.mm +++ b/React/DevSupport/RCTPackagerConnection.mm @@ -41,6 +41,7 @@ @implementation RCTPackagerConnection { RCTReconnectingWebSocket *_socket; BOOL _socketConnected; NSString *_serverHostPortForSocket; + NSString *_serverSchemeForSocket; id _bundleURLChangeObserver; uint32_t _nextToken; std::vector> _notificationRegistrations; @@ -63,7 +64,8 @@ - (instancetype)init if (self = [super init]) { _nextToken = 1; // Prevent randomly erasing a handler if you pass a bogus 0 token _serverHostPortForSocket = [[RCTBundleURLProvider sharedSettings] packagerServerHostPort]; - _socket = socketForLocation(_serverHostPortForSocket); + _serverSchemeForSocket = [[RCTBundleURLProvider sharedSettings] packagerScheme]; + _socket = socketForLocation(_serverHostPortForSocket, _serverSchemeForSocket); _socket.delegate = self; [_socket start]; @@ -79,7 +81,7 @@ - (instancetype)init return self; } -static RCTReconnectingWebSocket *socketForLocation(NSString *const serverHostPort) +static RCTReconnectingWebSocket *socketForLocation(NSString *const serverHostPort, NSString *scheme) { NSString *serverHost; NSString *serverPort; @@ -90,9 +92,12 @@ - (instancetype)init if ([locationComponents count] > 1) { serverPort = locationComponents[1]; } + if (![scheme length]) { + scheme = @"http"; + } NSURLComponents *const components = [NSURLComponents new]; components.host = serverHost ?: @"localhost"; - components.scheme = @"http"; + components.scheme = scheme; components.port = serverPort ? @(serverPort.integerValue) : @(kRCTBundleURLProviderDefaultPort); components.path = @"/message"; components.queryItems = @[ [NSURLQueryItem queryItemWithName:@"role" value:@"ios"] ]; @@ -128,14 +133,16 @@ - (void)bundleURLSettingsChanged } NSString *const serverHostPort = [[RCTBundleURLProvider sharedSettings] packagerServerHostPort]; - if ([serverHostPort isEqual:_serverHostPortForSocket]) { + NSString *const serverScheme = [[RCTBundleURLProvider sharedSettings] packagerScheme]; + if ([serverHostPort isEqual:_serverHostPortForSocket] && [serverScheme isEqual:_serverSchemeForSocket]) { return; // unchanged } _socket.delegate = nil; [_socket stop]; _serverHostPortForSocket = serverHostPort; - _socket = socketForLocation(serverHostPort); + _serverSchemeForSocket = serverScheme; + _socket = socketForLocation(serverHostPort, serverScheme); _socket.delegate = self; [_socket start]; } diff --git a/React/FBReactNativeSpec/FBReactNativeSpec.podspec b/React/FBReactNativeSpec/FBReactNativeSpec.podspec index 32a4bf8cb41960..bdbf1023319ea9 100644 --- a/React/FBReactNativeSpec/FBReactNativeSpec.podspec +++ b/React/FBReactNativeSpec/FBReactNativeSpec.podspec @@ -4,7 +4,9 @@ # LICENSE file in the root directory of this source tree. require "json" -require_relative "../../scripts/react_native_pods.rb" + +react_native_path = "../.." +require_relative "#{react_native_path}/scripts/react_native_pods.rb" package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json"))) version = package['version'] @@ -46,5 +48,13 @@ Pod::Spec.new do |s| s.dependency "React-jsi", version s.dependency "ReactCommon/turbomodule/core", version - use_react_native_codegen! (s) + use_react_native_codegen!(s, { + :react_native_path => react_native_path, + :js_srcs_dir => "#{react_native_path}/Libraries", + :library_name => "FBReactNativeSpec", + :output_dir => "#{react_native_path}/React/FBReactNativeSpec", + :component_library_name => "rncore", + # TODO: component_output_dir should be programmatically specified, and may change with use_frameworks! support. + :component_output_dir => "#{react_native_path}/ReactCommon/react/renderer/components/" + }) end diff --git a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index 885e8636f180ea..37468a85b11e8b 100644 --- a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -133,6 +133,15 @@ - (void)dealloc [self.scrollViewDelegateSplitter removeAllDelegates]; } +- (void)layoutSubviews +{ + [super layoutSubviews]; + + if (_subviewClippingEnabled) { + [self _remountChildren]; + } +} + - (RCTGenericDelegateSplitter> *)scrollViewDelegateSplitter { return ((RCTEnhancedScrollView *)_scrollView).delegateSplitter; diff --git a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm index 9379c20cb6cb79..8fe5537da5c39b 100644 --- a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm @@ -89,6 +89,7 @@ - (void)didMoveToWindow } _didMoveToWindow = YES; } + [self _restoreTextSelection]; } #pragma mark - RCTViewComponentView overrides @@ -208,7 +209,6 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & if (newTextInputProps.inputAccessoryViewID != oldTextInputProps.inputAccessoryViewID) { _backedTextInputView.inputAccessoryViewID = RCTNSStringFromString(newTextInputProps.inputAccessoryViewID); } - [super updateProps:props oldProps:oldProps]; [self setDefaultInputAccessoryView]; @@ -526,13 +526,27 @@ - (void)_updateState return AttributedString::Range{(int)start, (int)(end - start)}; } +- (void)_restoreTextSelection +{ + const auto selection = std::dynamic_pointer_cast(_props)->selection.get_pointer(); + if (selection == nullptr) { + return; + } + auto start = [_backedTextInputView positionFromPosition:_backedTextInputView.beginningOfDocument + offset:selection->start]; + auto end = [_backedTextInputView positionFromPosition:_backedTextInputView.beginningOfDocument offset:selection->end]; + auto range = [_backedTextInputView textRangeFromPosition:start toPosition:end]; + [_backedTextInputView setSelectedTextRange:range notifyDelegate:YES]; +} + - (void)_setAttributedString:(NSAttributedString *)attributedString { + if ([self _textOf:attributedString equals:_backedTextInputView.attributedText]) { + return; + } UITextRange *selectedRange = _backedTextInputView.selectedTextRange; NSInteger oldTextLength = _backedTextInputView.attributedText.string.length; - if (![self _textOf:attributedString equals:_backedTextInputView.attributedText]) { - _backedTextInputView.attributedText = attributedString; - } + _backedTextInputView.attributedText = attributedString; if (selectedRange.empty) { // Maintaining a cursor position relative to the end of the old text. NSInteger offsetStart = [_backedTextInputView offsetFromPosition:_backedTextInputView.beginningOfDocument @@ -544,6 +558,7 @@ - (void)_setAttributedString:(NSAttributedString *)attributedString [_backedTextInputView setSelectedTextRange:[_backedTextInputView textRangeFromPosition:position toPosition:position] notifyDelegate:YES]; } + [self _restoreTextSelection]; _lastStringStateWasUpdatedWith = attributedString; } diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index de103e10e10fae..86748bcfe6b7b7 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -336,6 +336,24 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & #endif } + // `accessibilityValue` + if (oldViewProps.accessibilityValue != newViewProps.accessibilityValue) { + if (newViewProps.accessibilityValue.text.hasValue()) { + self.accessibilityElement.accessibilityValue = + RCTNSStringFromStringNilIfEmpty(newViewProps.accessibilityValue.text.value()); + } else if ( + newViewProps.accessibilityValue.now.hasValue() && newViewProps.accessibilityValue.min.hasValue() && + newViewProps.accessibilityValue.max.hasValue()) { + CGFloat val = (CGFloat)(newViewProps.accessibilityValue.now.value()) / + (newViewProps.accessibilityValue.max.value() - newViewProps.accessibilityValue.min.value()); + self.accessibilityElement.accessibilityValue = + [NSNumberFormatter localizedStringFromNumber:@(val) numberStyle:NSNumberFormatterPercentStyle]; + ; + } else { + self.accessibilityElement.accessibilityValue = nil; + } + } + // `testId` if (oldViewProps.testId != newViewProps.testId) { self.accessibilityIdentifier = RCTNSStringFromString(newViewProps.testId); diff --git a/React/Fabric/Mounting/RCTMountingManager.mm b/React/Fabric/Mounting/RCTMountingManager.mm index beb1ed2b660e3c..f09ae72ce41ade 100644 --- a/React/Fabric/Mounting/RCTMountingManager.mm +++ b/React/Fabric/Mounting/RCTMountingManager.mm @@ -10,6 +10,7 @@ #import #import +#import #import #import #import @@ -26,6 +27,18 @@ using namespace facebook::react; +static SurfaceId RCTSurfaceIdForView(UIView *view) +{ + do { + if (RCTIsReactRootView(@(view.tag))) { + return view.tag; + } + view = view.superview; + } while (view != nil); + + return -1; +} + static void RCTPerformMountInstructions( ShadowViewMutationList const &mutations, RCTComponentViewRegistry *registry, @@ -282,9 +295,10 @@ - (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag { RCTAssertMainQueue(); UIView *componentView = [_componentViewRegistry findComponentViewWithTag:reactTag]; + SurfaceId surfaceId = RCTSurfaceIdForView(componentView); SharedProps oldProps = [componentView props]; SharedProps newProps = componentDescriptor.cloneProps( - PropsParserContext{-1, *_contextContainer.get()}, oldProps, RawProps(convertIdToFollyDynamic(props))); + PropsParserContext{surfaceId, *_contextContainer.get()}, oldProps, RawProps(convertIdToFollyDynamic(props))); NSSet *propKeys = componentView.propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN ?: [NSSet new]; propKeys = [propKeys setByAddingObjectsFromArray:props.allKeys]; diff --git a/React/Fabric/RCTConversions.h b/React/Fabric/RCTConversions.h index d8169ec2cffc91..495198b9709317 100644 --- a/React/Fabric/RCTConversions.h +++ b/React/Fabric/RCTConversions.h @@ -141,6 +141,9 @@ inline UIAccessibilityTraits RCTUIAccessibilityTraitsFromAccessibilityTraits( if ((accessibilityTraits & AccessibilityTraits::Switch) != AccessibilityTraits::None) { result |= AccessibilityTraitSwitch; } + if ((accessibilityTraits & AccessibilityTraits::TabBar) != AccessibilityTraits::None) { + result |= UIAccessibilityTraitTabBar; + } return result; }; diff --git a/React/Fabric/RCTSurfacePresenter.mm b/React/Fabric/RCTSurfacePresenter.mm index e3deefef3d2156..0c3d987ba1bc80 100644 --- a/React/Fabric/RCTSurfacePresenter.mm +++ b/React/Fabric/RCTSurfacePresenter.mm @@ -27,9 +27,6 @@ #import #import -#import -#import -#import #import #import #import @@ -262,6 +259,10 @@ - (RCTScheduler *)_createScheduler RCTSetRemoveClippedSubviewsEnabled(YES); } + if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:enable_initial_max_size_ios")) { + RCTSetInitialMaxSizeEnabled(YES); + } + auto componentRegistryFactory = [factory = wrapManagedObject(_mountingManager.componentViewRegistry.componentViewFactory)]( EventDispatcher::Weak const &eventDispatcher, ContextContainer::Shared const &contextContainer) { diff --git a/React/Fabric/RCTSurfacePresenterBridgeAdapter.h b/React/Fabric/RCTSurfacePresenterBridgeAdapter.h index 8d08c3a7ca72c3..da2eedb3a2e6a2 100644 --- a/React/Fabric/RCTSurfacePresenterBridgeAdapter.h +++ b/React/Fabric/RCTSurfacePresenterBridgeAdapter.h @@ -34,7 +34,7 @@ facebook::react::RuntimeExecutor RCTRuntimeExecutorFromBridge(RCTBridge *bridge) /* * Controls a stored instance of the Bridge. A consumer can re-set the stored Bridge using that method; the class is - * responsible to coordinate this change with a SurfacePresetner accordingly. + * responsible to coordinate this change with a SurfacePresenter accordingly. */ @property (nonatomic, weak) RCTBridge *bridge; diff --git a/React/Fabric/RCTSurfaceRegistry.h b/React/Fabric/RCTSurfaceRegistry.h index 405d16728a7b83..07fb4062f9264d 100644 --- a/React/Fabric/RCTSurfaceRegistry.h +++ b/React/Fabric/RCTSurfaceRegistry.h @@ -17,7 +17,7 @@ typedef void (^RCTSurfaceEnumeratorBlock)(NSEnumerator *enum /** * Registry of Surfaces. - * Incapsulates storing Surface objects and querying them by root tag. + * Encapsulates storing Surface objects and querying them by root tag. * All methods of the registry are thread-safe. * The registry stores Surface objects as weak references. */ diff --git a/React/Fabric/Surface/RCTFabricSurface.mm b/React/Fabric/Surface/RCTFabricSurface.mm index f806c801aff0e9..e18ee5a5f2beeb 100644 --- a/React/Fabric/Surface/RCTFabricSurface.mm +++ b/React/Fabric/Surface/RCTFabricSurface.mm @@ -10,6 +10,7 @@ #import #import +#import #import #import #import @@ -60,6 +61,10 @@ - (instancetype)initWithSurfacePresenter:(RCTSurfacePresenter *)surfacePresenter [_surfacePresenter registerSurface:self]; + if (RCTGetInitialMaxSizeEnabled()) { + [self setMinimumSize:CGSizeZero maximumSize:RCTViewportSize()]; + } + [self _updateLayoutContext]; [[NSNotificationCenter defaultCenter] addObserver:self diff --git a/React/Profiler/RCTProfileTrampoline-arm.S b/React/Profiler/RCTProfileTrampoline-arm.S index 47934922303115..f304932c92313a 100644 --- a/React/Profiler/RCTProfileTrampoline-arm.S +++ b/React/Profiler/RCTProfileTrampoline-arm.S @@ -89,7 +89,7 @@ SYMBOL_NAME(RCTProfileTrampoline): pop {lr} // pop the caller pop {r0} // pop the return value - bx lr // jump to the calleer + bx lr // jump to the caller trap diff --git a/React/Profiler/RCTProfileTrampoline-arm64.S b/React/Profiler/RCTProfileTrampoline-arm64.S index 8aa24ffd107849..c858371f33060e 100644 --- a/React/Profiler/RCTProfileTrampoline-arm64.S +++ b/React/Profiler/RCTProfileTrampoline-arm64.S @@ -41,7 +41,7 @@ SYMBOL_NAME(RCTProfileTrampoline): /** * Allocate 16-bytes for the values that have to be preserved across the call * to the actual function, since the stack has to be in the exact initial - * state. During its lifetimewe use it to store the initial value of the + * state. During its lifetime we use it to store the initial value of the * callee saved registers we use to point the memory, the actual address of * the implementation and the caller address. */ @@ -119,7 +119,7 @@ SYMBOL_NAME(RCTProfileTrampoline): // restore the stack pointer add sp, sp, #0x20 - // jump to the calleer, without a link + // jump to the caller, without a link br lr #endif diff --git a/React/Views/RCTFont.mm b/React/Views/RCTFont.mm index 93e1a803c7ca0f..7a8cbbb19abe01 100644 --- a/React/Views/RCTFont.mm +++ b/React/Views/RCTFont.mm @@ -11,18 +11,16 @@ #import -#import - typedef CGFloat RCTFontWeight; static RCTFontWeight weightOfFont(UIFont *font) { - static NSArray *fontNames; - static NSArray *fontWeights; + static NSArray *weightSuffixes; + static NSArray *fontWeights; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // We use two arrays instead of one map because // the order is important for suffix matching. - fontNames = @[ + weightSuffixes = @[ @"normal", @"ultralight", @"thin", @@ -54,28 +52,29 @@ static RCTFontWeight weightOfFont(UIFont *font) ]; }); - for (NSInteger i = 0; i < 0 || i < (unsigned)fontNames.count; i++) { - if ([font.fontName.lowercaseString hasSuffix:fontNames[i]]) { - return (RCTFontWeight)[fontWeights[i] doubleValue]; + NSString *fontName = font.fontName; + NSInteger i = 0; + for (NSString *suffix in weightSuffixes) { + // CFStringFind is much faster than any variant of rangeOfString: because it does not use a locale. + auto options = kCFCompareCaseInsensitive | kCFCompareAnchored | kCFCompareBackwards; + if (CFStringFind((CFStringRef)fontName, (CFStringRef)suffix, options).location != kCFNotFound) { + return (RCTFontWeight)fontWeights[i].doubleValue; } + i++; } - NSDictionary *traits = [font.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute]; + auto traits = (__bridge_transfer NSDictionary *)CTFontCopyTraits((CTFontRef)font); return (RCTFontWeight)[traits[UIFontWeightTrait] doubleValue]; } static BOOL isItalicFont(UIFont *font) { - NSDictionary *traits = [font.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute]; - UIFontDescriptorSymbolicTraits symbolicTraits = [traits[UIFontSymbolicTrait] unsignedIntValue]; - return (symbolicTraits & UIFontDescriptorTraitItalic) != 0; + return (CTFontGetSymbolicTraits((CTFontRef)font) & kCTFontTraitItalic) != 0; } static BOOL isCondensedFont(UIFont *font) { - NSDictionary *traits = [font.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute]; - UIFontDescriptorSymbolicTraits symbolicTraits = [traits[UIFontSymbolicTrait] unsignedIntValue]; - return (symbolicTraits & UIFontDescriptorTraitCondensed) != 0; + return (CTFontGetSymbolicTraits((CTFontRef)font) & kCTFontTraitCondensed) != 0; } static RCTFontHandler defaultFontHandler; @@ -130,18 +129,16 @@ static inline BOOL CompareFontWeights(UIFontWeight firstWeight, UIFontWeight sec static UIFont *cachedSystemFont(CGFloat size, RCTFontWeight weight) { - static NSCache *fontCache; - static std::mutex *fontCacheMutex = new std::mutex; - - NSString *cacheKey = [NSString stringWithFormat:@"%.1f/%.2f", size, weight]; - UIFont *font; - { - std::lock_guard lock(*fontCacheMutex); - if (!fontCache) { - fontCache = [NSCache new]; - } - font = [fontCache objectForKey:cacheKey]; - } + static NSCache *fontCache = [NSCache new]; + + struct __attribute__((__packed__)) CacheKey { + CGFloat size; + RCTFontWeight weight; + }; + + CacheKey key{size, weight}; + NSValue *cacheKey = [[NSValue alloc] initWithBytes:&key objCType:@encode(CacheKey)]; + UIFont *font = [fontCache objectForKey:cacheKey]; if (!font) { if (defaultFontHandler) { @@ -151,15 +148,36 @@ static inline BOOL CompareFontWeights(UIFontWeight firstWeight, UIFontWeight sec font = [UIFont systemFontOfSize:size weight:weight]; } - { - std::lock_guard lock(*fontCacheMutex); - [fontCache setObject:font forKey:cacheKey]; - } + [fontCache setObject:font forKey:cacheKey]; } return font; } +// Caching wrapper around expensive +[UIFont fontNamesForFamilyName:] +static NSArray *fontNamesForFamilyName(NSString *familyName) +{ + static NSCache *> *cache; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + cache = [NSCache new]; + [NSNotificationCenter.defaultCenter + addObserverForName:(NSNotificationName)kCTFontManagerRegisteredFontsChangedNotification + object:nil + queue:nil + usingBlock:^(NSNotification *) { + [cache removeAllObjects]; + }]; + }); + + auto names = [cache objectForKey:familyName]; + if (!names) { + names = [UIFont fontNamesForFamilyName:familyName]; + [cache setObject:names forKey:familyName]; + } + return names; +} + @implementation RCTConvert (RCTFont) + (UIFont *)UIFont:(id)json @@ -315,7 +333,7 @@ + (UIFont *)updateFont:(UIFont *)font // Gracefully handle being given a font name rather than font family, for // example: "Helvetica Light Oblique" rather than just "Helvetica". - if (!didFindFont && [UIFont fontNamesForFamilyName:familyName].count == 0) { + if (!didFindFont && fontNamesForFamilyName(familyName).count == 0) { font = [UIFont fontWithName:familyName size:fontSize]; if (font) { // It's actually a font name, not a font family name, @@ -339,7 +357,8 @@ + (UIFont *)updateFont:(UIFont *)font // Get the closest font that matches the given weight for the fontFamily CGFloat closestWeight = INFINITY; - for (NSString *name in [UIFont fontNamesForFamilyName:familyName]) { + NSArray *names = fontNamesForFamilyName(familyName); + for (NSString *name in names) { UIFont *match = [UIFont fontWithName:name size:fontSize]; if (isItalic == isItalicFont(match) && isCondensed == isCondensedFont(match)) { CGFloat testWeight = weightOfFont(match); @@ -352,11 +371,8 @@ + (UIFont *)updateFont:(UIFont *)font // If we still don't have a match at least return the first font in the fontFamily // This is to support built-in font Zapfino and other custom single font families like Impact - if (!font) { - NSArray *names = [UIFont fontNamesForFamilyName:familyName]; - if (names.count > 0) { - font = [UIFont fontWithName:names[0] size:fontSize]; - } + if (!font && names.count > 0) { + font = [UIFont fontWithName:names[0] size:fontSize]; } // Apply font variants to font object diff --git a/React/Views/RCTViewManager.m b/React/Views/RCTViewManager.m index 799e60a0793747..72e195c556b9c5 100644 --- a/React/Views/RCTViewManager.m +++ b/React/Views/RCTViewManager.m @@ -51,13 +51,14 @@ @implementation RCTConvert (UIAccessibilityTraits) @"menu" : @(UIAccessibilityTraitNone), @"menubar" : @(UIAccessibilityTraitNone), @"menuitem" : @(UIAccessibilityTraitNone), - @"progressbar" : @(UIAccessibilityTraitNone), + @"progressbar" : @(UIAccessibilityTraitUpdatesFrequently), @"radio" : @(UIAccessibilityTraitNone), @"radiogroup" : @(UIAccessibilityTraitNone), @"scrollbar" : @(UIAccessibilityTraitNone), @"spinbutton" : @(UIAccessibilityTraitNone), @"switch" : @(SwitchAccessibilityTrait), @"tab" : @(UIAccessibilityTraitNone), + @"tabbar" : @(UIAccessibilityTraitTabBar), @"tablist" : @(UIAccessibilityTraitNone), @"timer" : @(UIAccessibilityTraitNone), @"toolbar" : @(UIAccessibilityTraitNone), @@ -171,7 +172,8 @@ - (RCTShadowView *)shadowView const UIAccessibilityTraits AccessibilityRolesMask = UIAccessibilityTraitNone | UIAccessibilityTraitButton | UIAccessibilityTraitLink | UIAccessibilityTraitSearchField | UIAccessibilityTraitImage | UIAccessibilityTraitKeyboardKey | UIAccessibilityTraitStaticText | UIAccessibilityTraitAdjustable | - UIAccessibilityTraitHeader | UIAccessibilityTraitSummaryElement | SwitchAccessibilityTrait; + UIAccessibilityTraitHeader | UIAccessibilityTraitSummaryElement | UIAccessibilityTraitTabBar | + UIAccessibilityTraitUpdatesFrequently | SwitchAccessibilityTrait; view.reactAccessibilityElement.accessibilityTraits = view.reactAccessibilityElement.accessibilityTraits & ~AccessibilityRolesMask; UIAccessibilityTraits newTraits = json ? [RCTConvert UIAccessibilityTraits:json] : defaultView.accessibilityTraits; diff --git a/ReactAndroid/Android-prebuilt.mk b/ReactAndroid/Android-prebuilt.mk index fa41a5594e0ba4..18f8c266204588 100644 --- a/ReactAndroid/Android-prebuilt.mk +++ b/ReactAndroid/Android-prebuilt.mk @@ -156,6 +156,14 @@ LOCAL_EXPORT_C_INCLUDES := \ $(REACT_COMMON_DIR)/react/renderer/components/view include $(PREBUILT_SHARED_LIBRARY) +# jsi +include $(CLEAR_VARS) +LOCAL_MODULE := jsi +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libjsi.so +LOCAL_EXPORT_C_INCLUDES := \ + $(REACT_COMMON_DIR)/jsi +include $(PREBUILT_SHARED_LIBRARY) + # react_codegen_rncore include $(CLEAR_VARS) LOCAL_MODULE := react_codegen_rncore diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index edadad219f3b40..7d2e903790e3fb 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -56,7 +56,6 @@ task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) { task prepareBoost(dependsOn: boostPath ? [] : [downloadBoost], type: Copy) { from(boostPath ?: tarTree(resources.gzip(downloadBoost.dest))) - from("src/main/jni/third-party/boost/Android.mk") from("src/main/jni/third-party/boost") include("Android.mk", "boost_${BOOST_VERSION}/boost/**/*.hpp", "boost/boost/**/*.hpp", "asm/**/*.S") includeEmptyDirs = false @@ -171,6 +170,7 @@ task downloadGlog(dependsOn: createNativeDepsDirectories, type: Download) { // Prepare glog sources to be compiled, this task will perform steps that normally should've been // executed by automake. This way we can avoid dependencies on make/automake task prepareGlog(dependsOn: dependenciesPath ? [] : [downloadGlog], type: Copy) { + duplicatesStrategy("warn") from(dependenciesPath ?: tarTree(downloadGlog.dest)) from("src/main/jni/third-party/glog/") include("glog-${GLOG_VERSION}/src/**/*", "Android.mk", "config.h") @@ -362,7 +362,8 @@ def buildReactNdkLib = tasks.register("buildReactNdkLib", Exec) { inputs.dir("src/main/java/com/facebook/react/turbomodule/core/jni") inputs.dir("src/main/java/com/facebook/react/modules/blob") outputs.dir("$buildDir/react-ndk/all") - commandLine(getNdkBuildFullPath(), + def commandLineArgs = [ + getNdkBuildFullPath(), "APP_ABI=${reactNativeArchitectures()}", "NDK_DEBUG=" + (nativeBuildType.equalsIgnoreCase("debug") ? "1" : "0"), "NDK_PROJECT_PATH=null", @@ -375,7 +376,12 @@ def buildReactNdkLib = tasks.register("buildReactNdkLib", Exec) { "REACT_SRC_DIR=$projectDir/src/main/java/com/facebook/react", "-C", file("src/main/jni/react/jni").absolutePath, "--jobs", project.findProperty("jobs") ?: Runtime.runtime.availableProcessors() - ) + ] + if (Os.isFamily(Os.FAMILY_MAC)) { + // This flag will suppress "fcntl(): Bad file descriptor" warnings on local builds. + commandLineArgs.add("--output-sync=none") + } + commandLine(commandLineArgs) } def cleanReactNdkLib = tasks.register("cleanReactNdkLib", Exec) { diff --git a/ReactAndroid/src/androidTest/buck-runner/BUCK b/ReactAndroid/src/androidTest/buck-runner/BUCK index d8fc2604af7f4a..c27596ee462c3e 100644 --- a/ReactAndroid/src/androidTest/buck-runner/BUCK +++ b/ReactAndroid/src/androidTest/buck-runner/BUCK @@ -14,6 +14,7 @@ rn_android_binary( use_split_dex = True, deps = [ react_native_dep("libraries/soloader/java/com/facebook/soloader:soloader"), + react_native_dep("third-party/java/testing-support-lib:exposed-instrumentation-api"), react_native_integration_tests_target("assets:assets"), react_native_integration_tests_target("java/com/facebook/react/tests:tests"), react_native_target("java/com/facebook/react/devsupport:devsupport"), diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/BUCK b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/BUCK index a3dc3dde1ad199..d410f7c5f3a09c 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/BUCK +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/BUCK @@ -1,4 +1,3 @@ -# BUILD FILE SYNTAX: SKYLARK load( "//tools/build_defs/oss:rn_defs.bzl", "IS_OSS_BUILD", @@ -16,7 +15,7 @@ rn_android_library( visibility = [ "PUBLIC", ], - deps = ([ + deps = [ react_native_dep("third-party/android/androidx:test-espresso-core"), react_native_dep("third-party/java/jsr-305:jsr-305"), react_native_dep("third-party/java/junit:junit"), @@ -37,8 +36,8 @@ rn_android_library( react_native_target("java/com/facebook/react/modules/core:core"), react_native_target("java/com/facebook/react/shell:shell"), react_native_target("java/com/facebook/react/uimanager:uimanager"), - ]) + ([ + ] + [ react_native_dep("java/com/facebook/testing/instrumentation:instrumentation"), react_native_dep("java/com/facebook/testing/instrumentation/base:base"), - ]) if not IS_OSS_BUILD else [], + ] if not IS_OSS_BUILD else [], ) diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK index 451cd7413b9686..131dd4af63c3a2 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK @@ -25,7 +25,6 @@ rn_android_library( react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/modules/appstate:appstate"), react_native_target("java/com/facebook/react/modules/core:core"), - react_native_target("java/com/facebook/react/modules/datepicker:datepicker"), react_native_target("java/com/facebook/react/modules/deviceinfo:deviceinfo"), react_native_target("java/com/facebook/react/modules/share:share"), react_native_target("java/com/facebook/react/modules/systeminfo:systeminfo"), diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/DatePickerDialogTestCase.java b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/DatePickerDialogTestCase.java deleted file mode 100644 index 93d3568fa24e2e..00000000000000 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/DatePickerDialogTestCase.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.tests; - -import android.app.DatePickerDialog; -import android.content.DialogInterface; -import android.widget.DatePicker; -import androidx.fragment.app.DialogFragment; -import androidx.fragment.app.Fragment; -import com.facebook.react.bridge.BaseJavaModule; -import com.facebook.react.bridge.JavaScriptModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.bridge.WritableNativeMap; -import com.facebook.react.modules.datepicker.DatePickerDialogModule; -import com.facebook.react.testing.ReactAppInstrumentationTestCase; -import com.facebook.react.testing.ReactInstanceSpecForTest; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; - -/** Test case for {@link DatePickerDialogModule} options and callbacks. */ -public class DatePickerDialogTestCase extends ReactAppInstrumentationTestCase { - - private static interface DatePickerDialogTestModule extends JavaScriptModule { - public void showDatePickerDialog(WritableMap options); - } - - private static class DatePickerDialogRecordingModule extends BaseJavaModule { - - private final List mDates = new ArrayList(); - private int mDismissed = 0; - private int mErrors = 0; - - @Override - public String getName() { - return "DatePickerDialogRecordingModule"; - } - - @ReactMethod - public void recordDate(int year, int month, int day) { - mDates.add(new Integer[] {year, month, day}); - } - - @ReactMethod - public void recordDismissed() { - mDismissed++; - } - - @ReactMethod - public void recordError() { - mErrors++; - } - - public List getDates() { - return new ArrayList(mDates); - } - - public int getDismissed() { - return mDismissed; - } - - public int getErrors() { - return mErrors; - } - } - - final DatePickerDialogRecordingModule mRecordingModule = new DatePickerDialogRecordingModule(); - - @Override - protected ReactInstanceSpecForTest createReactInstanceSpecForTest() { - return super.createReactInstanceSpecForTest().addNativeModule(mRecordingModule); - } - - @Override - protected String getReactApplicationKeyUnderTest() { - return "DatePickerDialogTestApp"; - } - - private static long getDateInMillis(int year, int month, int date) { - final Calendar c = Calendar.getInstance(); - c.set(Calendar.YEAR, year); - c.set(Calendar.MONTH, month); - c.set(Calendar.DATE, date); - return c.getTimeInMillis(); - } - - private DatePickerDialogTestModule getTestModule() { - return getReactContext().getCatalystInstance().getJSModule(DatePickerDialogTestModule.class); - } - - private DialogFragment showDialog(WritableMap options) { - getTestModule().showDatePickerDialog(options); - - waitForBridgeAndUIIdle(); - getInstrumentation().waitForIdleSync(); - - return (DialogFragment) - getActivity() - .getSupportFragmentManager() - .findFragmentByTag(DatePickerDialogModule.FRAGMENT_TAG); - } - - public void testShowBasicDatePicker() { - final Fragment datePickerFragment = showDialog(null); - - assertNotNull(datePickerFragment); - } - - public void testPresetDate() { - final WritableMap options = new WritableNativeMap(); - options.putDouble("date", getDateInMillis(2020, 5, 6)); - - final DialogFragment datePickerFragment = showDialog(options); - final DatePicker datePicker = - ((DatePickerDialog) datePickerFragment.getDialog()).getDatePicker(); - - assertEquals(2020, datePicker.getYear()); - assertEquals(5, datePicker.getMonth()); - assertEquals(6, datePicker.getDayOfMonth()); - } - - public void testCallback() throws Throwable { - final WritableMap options = new WritableNativeMap(); - options.putDouble("date", getDateInMillis(2020, 5, 6)); - - final DialogFragment datePickerFragment = showDialog(options); - - runTestOnUiThread( - new Runnable() { - @Override - public void run() { - ((DatePickerDialog) datePickerFragment.getDialog()) - .getButton(DialogInterface.BUTTON_POSITIVE) - .performClick(); - } - }); - - getInstrumentation().waitForIdleSync(); - waitForBridgeAndUIIdle(); - - assertEquals(0, mRecordingModule.getErrors()); - assertEquals(1, mRecordingModule.getDates().size()); - assertEquals(2020, (int) mRecordingModule.getDates().get(0)[0]); - assertEquals(5, (int) mRecordingModule.getDates().get(0)[1]); - assertEquals(6, (int) mRecordingModule.getDates().get(0)[2]); - } - - public void testDismissCallback() throws Throwable { - final DialogFragment datePickerFragment = showDialog(null); - - runTestOnUiThread( - new Runnable() { - @Override - public void run() { - datePickerFragment.getDialog().dismiss(); - } - }); - - getInstrumentation().waitForIdleSync(); - waitForBridgeAndUIIdle(); - - assertEquals(0, mRecordingModule.getErrors()); - assertEquals(0, mRecordingModule.getDates().size()); - assertEquals(1, mRecordingModule.getDismissed()); - } -} diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/core/BUCK b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/core/BUCK index 65b8da3ee02b3f..8ce6ba218f7c76 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/core/BUCK +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/core/BUCK @@ -1,4 +1,3 @@ -# BUILD FILE SYNTAX: SKYLARK load( "//tools/build_defs/oss:rn_defs.bzl", "IS_OSS_BUILD", @@ -13,7 +12,7 @@ rn_android_library( srcs = glob(["*.java"]), autoglob = False, is_androidx = True, - deps = ([ + deps = [ react_native_dep("third-party/android/androidx:test-espresso-core"), react_native_dep("third-party/java/fest:fest"), react_native_dep("third-party/java/junit:junit"), @@ -28,7 +27,7 @@ rn_android_library( react_native_target("java/com/facebook/react/module/model:model"), react_native_target("java/com/facebook/react/shell:shell"), react_native_target("java/com/facebook/react/uimanager:uimanager"), - ]) + ([ + ] + [ react_native_dep("java/com/facebook/fbreact/testing:testing"), - ]) if not IS_OSS_BUILD else [], + ] if not IS_OSS_BUILD else [], ) diff --git a/ReactAndroid/src/androidTest/js/DatePickerDialogTestModule.js b/ReactAndroid/src/androidTest/js/DatePickerDialogTestModule.js deleted file mode 100644 index 5c23e61a5ec5ae..00000000000000 --- a/ReactAndroid/src/androidTest/js/DatePickerDialogTestModule.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -'use strict'; - -const React = require('react'); -const {DatePickerAndroid, NativeModules, View} = require('react-native'); -const BatchedBridge = require('react-native/Libraries/BatchedBridge/BatchedBridge'); - -const {DatePickerDialogRecordingModule: RecordingModule} = NativeModules; - -class DatePickerDialogTestApp extends React.Component { - render() { - return ; - } -} - -const DatePickerDialogTestModule = { - DatePickerDialogTestApp: DatePickerDialogTestApp, - showDatePickerDialog: function(options) { - DatePickerAndroid.open(options).then( - ({action, year, month, day}) => { - if (action === DatePickerAndroid.dateSetAction) { - RecordingModule.recordDate(year, month, day); - } else if (action === DatePickerAndroid.dismissedAction) { - RecordingModule.recordDismissed(); - } - }, - ({code, message}) => RecordingModule.recordError(), - ); - }, -}; - -BatchedBridge.registerCallableModule( - 'DatePickerDialogTestModule', - DatePickerDialogTestModule, -); - -module.exports = DatePickerDialogTestModule; diff --git a/ReactAndroid/src/androidTest/js/TestBundle.js b/ReactAndroid/src/androidTest/js/TestBundle.js index 709f469b118d45..b81937503589ae 100644 --- a/ReactAndroid/src/androidTest/js/TestBundle.js +++ b/ReactAndroid/src/androidTest/js/TestBundle.js @@ -20,9 +20,7 @@ require('./TestJSLocaleModule'); require('./TestJSToJavaParametersModule'); require('./TestJavaToJSReturnValuesModule'); require('./UIManagerTestModule'); - require('./CatalystRootViewTestModule'); -require('./DatePickerDialogTestModule'); require('./MeasureLayoutTestModule'); require('./ScrollViewTestModule'); require('./ShareTestModule'); @@ -43,11 +41,6 @@ const apps = [ component: () => require('./CatalystRootViewTestModule').CatalystRootViewTestApp, }, - { - appKey: 'DatePickerDialogTestApp', - component: () => - require('./DatePickerDialogTestModule').DatePickerDialogTestApp, - }, { appKey: 'JSResponderTestApp', component: () => require('./JSResponderTestApp'), diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/Android.mk b/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/Android.mk index 3548e86abd3c93..651168243ef04e 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/Android.mk +++ b/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/Android.mk @@ -18,8 +18,8 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH) $(REACT_NATIVE)/ReactCommon/jsi $(call find-no LOCAL_CPP_FEATURES := exceptions -LOCAL_STATIC_LIBRARIES := libjsireact libjsi -LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libreactnativejni libhermes +LOCAL_STATIC_LIBRARIES := libjsireact +LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libreactnativejni libhermes libjsi include $(BUILD_SHARED_LIBRARY) diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/Android.mk b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/Android.mk index ff05e4c14824cf..7716394c31f78b 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/Android.mk +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/Android.mk @@ -17,8 +17,8 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH) $(REACT_NATIVE)/ReactCommon/jsi $(call find-no LOCAL_CPP_FEATURES := exceptions -LOCAL_STATIC_LIBRARIES := libjsireact libjsi libhermes-executor-common-release -LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libreactnativejni libhermes +LOCAL_STATIC_LIBRARIES := libjsireact libhermes-executor-common-release +LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libreactnativejni libhermes libjsi include $(BUILD_SHARED_LIBRARY) @@ -34,7 +34,7 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH) $(REACT_NATIVE)/ReactCommon/jsi $(call find-no LOCAL_CPP_FEATURES := exceptions -LOCAL_STATIC_LIBRARIES := libjsireact libjsi libhermes-executor-common-debug libhermes-inspector -LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libreactnativejni libhermes +LOCAL_STATIC_LIBRARIES := libjsireact libhermes-executor-common-debug libhermes-inspector +LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libreactnativejni libhermes libjsi include $(BUILD_SHARED_LIBRARY) diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java index 976af80b1eeb66..ce09abba961109 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutorFactory.java @@ -17,7 +17,7 @@ public class HermesExecutorFactory implements JavaScriptExecutorFactory { private final RuntimeConfig mConfig; public HermesExecutorFactory() { - this(new RuntimeConfig(1024)); + this(null); } public HermesExecutorFactory(RuntimeConfig config) { diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java index fec7c457bc8b98..a3e91b8cce6ff9 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java @@ -10,10 +10,4 @@ /** Holds runtime configuration for a Hermes VM instance (master or snapshot). */ public final class RuntimeConfig { public long heapSizeMB; - - RuntimeConfig() {} - - RuntimeConfig(long heapSizeMB) { - this.heapSizeMB = heapSizeMB; - } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/BUCK b/ReactAndroid/src/main/java/com/facebook/react/BUCK index b550756ae1baa2..a32feeb61c9820 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/BUCK @@ -49,7 +49,6 @@ rn_android_library( react_native_target("java/com/facebook/react/config:config"), react_native_target("java/com/facebook/react/turbomodule/core:core"), react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"), - react_native_target("java/com/facebook/react/runtimescheduler:runtimescheduler"), ], exported_deps = [ react_native_target("java/com/facebook/react/modules/core:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index dd1601bd10e592..6df4dd1bd976bf 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -65,6 +65,7 @@ import com.facebook.react.bridge.ProxyJavaScriptExecutor; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.ReactCxxErrorHandler; import com.facebook.react.bridge.ReactMarker; import com.facebook.react.bridge.ReactMarkerConstants; import com.facebook.react.bridge.ReactNoCrashSoftException; @@ -91,7 +92,6 @@ import com.facebook.react.modules.debug.interfaces.DeveloperSettings; import com.facebook.react.modules.fabric.ReactFabric; import com.facebook.react.packagerconnection.RequestHandler; -import com.facebook.react.runtimescheduler.RuntimeSchedulerManager; import com.facebook.react.surface.ReactStage; import com.facebook.react.turbomodule.core.TurboModuleManager; import com.facebook.react.turbomodule.core.TurboModuleManagerDelegate; @@ -107,6 +107,7 @@ import com.facebook.soloader.SoLoader; import com.facebook.systrace.Systrace; import com.facebook.systrace.SystraceMessage; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -156,14 +157,15 @@ public interface ReactInstanceEventListener { /* accessed from any thread */ private final JavaScriptExecutorFactory mJavaScriptExecutorFactory; + // See {@code ReactInstanceManagerBuilder} for description of all flags here. private @Nullable List mViewManagerNames = null; private final @Nullable JSBundleLoader mBundleLoader; private final @Nullable String mJSMainModulePath; /* path to JS bundle root on Metro */ private final List mPackages; private final DevSupportManager mDevSupportManager; private final boolean mUseDeveloperSupport; + private final boolean mRequireActivity; private @Nullable ComponentNameResolverManager mComponentNameResolverManager; - private @Nullable RuntimeSchedulerManager mRuntimeSchedulerManager; private final @Nullable NotThreadSafeBridgeIdleDebugListener mBridgeIdleDebugListener; private final Object mReactContextLock = new Object(); private @Nullable volatile ReactContext mCurrentReactContext; @@ -216,6 +218,7 @@ public static ReactInstanceManagerBuilder builder() { @Nullable String jsMainModulePath, List packages, boolean useDeveloperSupport, + boolean requireActivity, @Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener, LifecycleState initialLifecycleState, @Nullable UIImplementationProvider mUIImplementationProvider, @@ -233,6 +236,7 @@ public static ReactInstanceManagerBuilder builder() { DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(applicationContext); + // See {@code ReactInstanceManagerBuilder} for description of all flags here. mApplicationContext = applicationContext; mCurrentActivity = currentActivity; mDefaultBackButtonImpl = defaultHardwareBackBtnHandler; @@ -241,6 +245,7 @@ public static ReactInstanceManagerBuilder builder() { mJSMainModulePath = jsMainModulePath; mPackages = new ArrayList<>(); mUseDeveloperSupport = useDeveloperSupport; + mRequireActivity = requireActivity; Systrace.beginSection( Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstanceManager.initDevSupportManager"); mDevSupportManager = @@ -286,6 +291,8 @@ public void invokeDefaultOnBackPressed() { if (mUseDeveloperSupport) { mDevSupportManager.startInspector(); } + + registerCxxErrorHandlerFunc(); } private ReactInstanceDevHelper createDevHelperInterface() { @@ -359,6 +366,22 @@ public List getPackages() { return new ArrayList<>(mPackages); } + public void handleCxxError(Exception e) { + mDevSupportManager.handleException(e); + } + + public void registerCxxErrorHandlerFunc() { + Class[] parameterTypes = new Class[1]; + parameterTypes[0] = Exception.class; + Method handleCxxErrorFunc = null; + try { + handleCxxErrorFunc = ReactInstanceManager.class.getMethod("handleCxxError", parameterTypes); + } catch (NoSuchMethodException e) { + FLog.e("ReactInstanceHolder", "Failed to set cxx error hanlder function", e); + } + ReactCxxErrorHandler.setHandleErrorFunc(this, handleCxxErrorFunc); + } + static void initializeSoLoaderIfNecessary(Context applicationContext) { // Call SoLoader.initialize here, this is required for apps that does not use exopackage and // does not use SoLoader for loading other native code except from the one used by React Native @@ -558,16 +581,20 @@ public void onHostPause() { * @param activity the activity being paused */ @ThreadConfined(UI) - public void onHostPause(Activity activity) { - Assertions.assertNotNull(mCurrentActivity); - Assertions.assertCondition( - activity == mCurrentActivity, - "Pausing an activity that is not the current activity, this is incorrect! " - + "Current activity: " - + mCurrentActivity.getClass().getSimpleName() - + " " - + "Paused activity: " - + activity.getClass().getSimpleName()); + public void onHostPause(@Nullable Activity activity) { + if (mRequireActivity) { + Assertions.assertCondition(mCurrentActivity != null); + } + if (mCurrentActivity != null) { + Assertions.assertCondition( + activity == mCurrentActivity, + "Pausing an activity that is not the current activity, this is incorrect! " + + "Current activity: " + + mCurrentActivity.getClass().getSimpleName() + + " " + + "Paused activity: " + + activity.getClass().getSimpleName()); + } onHostPause(); } @@ -583,7 +610,8 @@ public void onHostPause(Activity activity) { * this instance of {@link ReactInstanceManager}. */ @ThreadConfined(UI) - public void onHostResume(Activity activity, DefaultHardwareBackBtnHandler defaultBackButtonImpl) { + public void onHostResume( + @Nullable Activity activity, DefaultHardwareBackBtnHandler defaultBackButtonImpl) { UiThreadUtil.assertOnUiThread(); mDefaultBackButtonImpl = defaultBackButtonImpl; @@ -592,40 +620,47 @@ public void onHostResume(Activity activity, DefaultHardwareBackBtnHandler defaul /** Use this method when the activity resumes. */ @ThreadConfined(UI) - public void onHostResume(Activity activity) { + public void onHostResume(@Nullable Activity activity) { UiThreadUtil.assertOnUiThread(); mCurrentActivity = activity; if (mUseDeveloperSupport) { - // Resume can be called from one of two different states: + // Resume can be called from one of three different states: // a) when activity was paused // b) when activity has just been created + // c) when there is no activity // In case of (a) the activity is attached to window and it is ok to add new views to it or // open dialogs. In case of (b) there is often a slight delay before such a thing happens. // As dev support manager can add views or open dialogs immediately after it gets enabled // (e.g. in the case when JS bundle is being fetched in background) we only want to enable // it once we know for sure the current activity is attached. + // We want to enable the various devsupport tools in case of (c) even without any activity + + if (mCurrentActivity != null) { + // We check if activity is attached to window by checking if decor view is attached + final View decorView = mCurrentActivity.getWindow().getDecorView(); + if (!ViewCompat.isAttachedToWindow(decorView)) { + decorView.addOnAttachStateChangeListener( + new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + // we can drop listener now that we know the view is attached + decorView.removeOnAttachStateChangeListener(this); + mDevSupportManager.setDevSupportEnabled(true); + } - // We check if activity is attached to window by checking if decor view is attached - final View decorView = mCurrentActivity.getWindow().getDecorView(); - if (!ViewCompat.isAttachedToWindow(decorView)) { - decorView.addOnAttachStateChangeListener( - new View.OnAttachStateChangeListener() { - @Override - public void onViewAttachedToWindow(View v) { - // we can drop listener now that we know the view is attached - decorView.removeOnAttachStateChangeListener(this); - mDevSupportManager.setDevSupportEnabled(true); - } - - @Override - public void onViewDetachedFromWindow(View v) { - // do nothing - } - }); - } else { - // activity is attached to window, we can enable dev support immediately + @Override + public void onViewDetachedFromWindow(View v) { + // do nothing + } + }); + } else { + // activity is attached to window, we can enable dev support immediately + mDevSupportManager.setDevSupportEnabled(true); + } + } else if (!mRequireActivity) { + // there is no activity, but we can enable dev support mDevSupportManager.setDevSupportEnabled(true); } } @@ -659,7 +694,9 @@ public void onHostDestroy() { * @param activity the activity being destroyed */ @ThreadConfined(UI) - public void onHostDestroy(Activity activity) { + public void onHostDestroy(@Nullable Activity activity) { + // In some cases, Activity may (correctly) be null. + // See mRequireActivity flag. if (activity == mCurrentActivity) { onHostDestroy(); } @@ -720,7 +757,6 @@ public void destroy() { mViewManagerNames = null; } mComponentNameResolverManager = null; - mRuntimeSchedulerManager = null; FLog.d(ReactConstants.TAG, "ReactInstanceManager has been destroyed"); } @@ -1324,6 +1360,10 @@ private ReactApplicationContext createReactContext( } } + if (ReactFeatureFlags.enableRuntimeScheduler) { + catalystInstance.installRuntimeScheduler(); + } + if (mJSIModulePackage != null) { catalystInstance.addJSIModules( mJSIModulePackage.getJSIModules( @@ -1355,9 +1395,6 @@ public String[] getComponentNames() { }); catalystInstance.setGlobalVariable("__fbStaticViewConfig", "true"); } - if (ReactFeatureFlags.enableRuntimeScheduler) { - mRuntimeSchedulerManager = new RuntimeSchedulerManager(catalystInstance.getRuntimeExecutor()); - } ReactMarker.logMarker(ReactMarkerConstants.PRE_RUN_JS_BUNDLE_START); Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "runJSBundle"); diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java index c06f71b9a5945f..36f700e497631c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java @@ -45,6 +45,7 @@ public class ReactInstanceManagerBuilder { private @Nullable NotThreadSafeBridgeIdleDebugListener mBridgeIdleDebugListener; private @Nullable Application mApplication; private boolean mUseDeveloperSupport; + private boolean mRequireActivity; private @Nullable LifecycleState mInitialLifecycleState; private @Nullable UIImplementationProvider mUIImplementationProvider; private @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler; @@ -171,6 +172,16 @@ public ReactInstanceManagerBuilder setUseDeveloperSupport(boolean useDeveloperSu return this; } + /** + * When {@code false}, indicates that correct usage of React Native will NOT involve an Activity. + * For the vast majority of Android apps in the ecosystem, this will not need to change. Unless + * you really know what you're doing, you should probably not change this! + */ + public ReactInstanceManagerBuilder setRequireActivity(boolean requireActivity) { + mRequireActivity = requireActivity; + return this; + } + /** * Sets the initial lifecycle state of the host. For example, if the host is already resumed at * creation time, we wouldn't expect an onResume call until we get an onPause call. @@ -283,6 +294,7 @@ public ReactInstanceManager build() { mJSMainModulePath, mPackages, mUseDeveloperSupport, + mRequireActivity, mBridgeIdleDebugListener, Assertions.assertNotNull(mInitialLifecycleState, "Initial lifecycle state was not set"), mUIImplementationProvider, diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java b/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java index d4c457ff87de9c..dc313d33bc0f6e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java @@ -68,6 +68,7 @@ protected ReactInstanceManager createReactInstanceManager() { .setApplication(mApplication) .setJSMainModulePath(getJSMainModuleName()) .setUseDeveloperSupport(getUseDeveloperSupport()) + .setRequireActivity(getShouldRequireActivity()) .setRedBoxHandler(getRedBoxHandler()) .setJavaScriptExecutorFactory(getJavaScriptExecutorFactory()) .setUIImplementationProvider(getUIImplementationProvider()) @@ -124,6 +125,11 @@ protected UIImplementationProvider getUIImplementationProvider() { return null; } + /** Returns whether or not to treat it as normal if Activity is null. */ + public boolean getShouldRequireActivity() { + return true; + } + /** * Returns the name of the main module. Determines the URL used to fetch the JS bundle from Metro. * It is only used when dev support is enabled. This is the first file to be executed once the diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java index 1a5067b7edb358..09eb2c70183682 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java @@ -111,6 +111,10 @@ public interface CatalystInstance RuntimeExecutor getRuntimeExecutor(); + RuntimeScheduler getRuntimeScheduler(); + + void installRuntimeScheduler(); + void addJSIModules(List jsiModules); /** diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java index baffa40aabbe83..d5a9b97571b76f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java @@ -558,6 +558,10 @@ public JavaScriptContextHolder getJavaScriptContextHolder() { public native RuntimeExecutor getRuntimeExecutor(); + public native RuntimeScheduler getRuntimeScheduler(); + + public native void installRuntimeScheduler(); + @Override public void addJSIModules(List jsiModules) { mJSIModuleRegistry.registerModules(jsiModules); diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactCxxErrorHandler.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactCxxErrorHandler.java new file mode 100644 index 00000000000000..f5efbf1fadf930 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactCxxErrorHandler.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.bridge; + +import com.facebook.common.logging.FLog; +import com.facebook.proguard.annotations.DoNotStrip; +import java.lang.reflect.Method; + +@DoNotStrip +public class ReactCxxErrorHandler { + + private static Method mHandleErrorFunc; + private static Object mObject; + + @DoNotStrip + public static void setHandleErrorFunc(Object object, Method handleErrorFunc) { + mObject = object; + mHandleErrorFunc = handleErrorFunc; + } + + @DoNotStrip + // For use from within the C++ JReactCxxErrorHandler + private static void handleError(final String message) { + if (mHandleErrorFunc != null) { + try { + Object[] parameters = new Object[1]; + parameters[0] = new Exception(message); + mHandleErrorFunc.invoke(mObject, parameters); + } catch (Exception e) { + FLog.e("ReactCxxErrorHandler", "Failed to invole error hanlder function", e); + } + } + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/RuntimeScheduler.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/RuntimeScheduler.java new file mode 100644 index 00000000000000..7270c65c6bfa1f --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/RuntimeScheduler.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.bridge; + +import com.facebook.jni.HybridData; +import com.facebook.proguard.annotations.DoNotStrip; + +/** A Java holder for a C++ RuntimeScheduler. */ +public class RuntimeScheduler { + + @DoNotStrip private HybridData mHybridData; + + public RuntimeScheduler(HybridData hybridData) { + mHybridData = hybridData; + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/jni/BUCK b/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/jni/BUCK index 50560598d1088f..0e5d2d726d91e9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/jni/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/jni/BUCK @@ -19,7 +19,7 @@ rn_xplat_cxx_library( ], fbandroid_allow_jni_merging = True, labels = ["supermodule:xplat/default/public.react_native.infra"], - platforms = (ANDROID), + platforms = ANDROID, preprocessor_flags = [ "-DLOG_TAG=\"ReactNative\"", "-DWITH_FBSYSTRACE=1", diff --git a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index 8513e6c0ccd423..077eb5fd7b26bd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -25,6 +25,12 @@ public class ReactFeatureFlags { */ public static volatile boolean useTurboModules = false; + /** + * Should this application use the new (Fabric) Renderer? If yes, all rendering in this app will + * use Fabric instead of the legacy renderer. + */ + public static volatile boolean enableFabricRenderer = false; + /** * After TurboModules and Fabric are enabled, we need to ensure that the legacy NativeModule isn't * isn't used. So, turn this flag on to trigger warnings whenever the legacy NativeModule system diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java index 6449ef07579550..e02f4188f5d16e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java @@ -9,11 +9,13 @@ import android.annotation.SuppressLint; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.facebook.jni.HybridData; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.NativeMap; import com.facebook.react.bridge.ReadableNativeMap; import com.facebook.react.bridge.RuntimeExecutor; +import com.facebook.react.bridge.RuntimeScheduler; import com.facebook.react.bridge.queue.MessageQueueThread; import com.facebook.react.fabric.events.EventBeatManager; import com.facebook.react.fabric.events.EventEmitterWrapper; @@ -37,6 +39,7 @@ public Binding() { private native void installFabricUIManager( RuntimeExecutor runtimeExecutor, + RuntimeScheduler runtimeScheduler, Object uiManager, EventBeatManager eventBeatManager, MessageQueueThread jsMessageQueueThread, @@ -83,6 +86,7 @@ public native ReadableNativeMap getInspectorDataForInstance( public void register( @NonNull RuntimeExecutor runtimeExecutor, + @Nullable RuntimeScheduler runtimeScheduler, @NonNull FabricUIManager fabricUIManager, @NonNull EventBeatManager eventBeatManager, @NonNull MessageQueueThread jsMessageQueueThread, @@ -91,6 +95,7 @@ public void register( fabricUIManager.setBinding(this); installFabricUIManager( runtimeExecutor, + runtimeScheduler, fabricUIManager, eventBeatManager, jsMessageQueueThread, diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java index 84bea4d85f6181..c4a6fbfb5c71b5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java @@ -55,6 +55,7 @@ public UIManager get() { binding.register( mReactApplicationContext.getCatalystInstance().getRuntimeExecutor(), + mReactApplicationContext.getCatalystInstance().getRuntimeScheduler(), uiManager, eventBeatManager, jsMessageQueueThread, diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk index 827112595cefa4..1c2bde705d6f19 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk @@ -11,7 +11,7 @@ LOCAL_MODULE := fabricjni LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) -LOCAL_SHARED_LIBRARIES := libreactconfig librrc_slider librrc_progressbar librrc_switch librrc_modal libyoga libglog libfb libfbjni libglog_init libfolly_json libfolly_futures libreact_render_mounting libreactnativeutilsjni libreact_utils libreact_render_debug libreact_render_graphics libreact_render_core react_render_componentregistry librrc_view librrc_unimplementedview librrc_root librrc_scrollview libbetter libreact_render_attributedstring libreact_render_uimanager libreact_render_templateprocessor libreact_render_scheduler libreact_render_animations libreact_render_imagemanager libreact_render_textlayoutmanager libreact_codegen_rncore rrc_text librrc_image librrc_textinput libreact_debug libreact_render_mapbuffer libmapbufferjni libreact_render_telemetry +LOCAL_SHARED_LIBRARIES := libjsi libreactconfig librrc_slider librrc_progressbar librrc_switch librrc_modal libyoga libglog libfb libfbjni libglog_init libfolly_json libfolly_futures libreact_render_mounting libreactnativeutilsjni libreact_utils libreact_render_debug libreact_render_graphics libreact_render_core react_render_componentregistry librrc_view librrc_unimplementedview librrc_root librrc_scrollview libbetter libreact_render_attributedstring libreact_render_uimanager libreact_render_templateprocessor libreact_render_scheduler libreact_render_animations libreact_render_imagemanager libreact_render_textlayoutmanager libreact_codegen_rncore rrc_text librrc_image librrc_textinput libreact_debug libreact_render_mapbuffer libmapbufferjni libreact_render_telemetry libreact_render_runtimescheduler LOCAL_STATIC_LIBRARIES := @@ -56,6 +56,7 @@ $(call import-module,react/renderer/graphics) $(call import-module,react/renderer/imagemanager) $(call import-module,react/renderer/mapbuffer) $(call import-module,react/renderer/mounting) +$(call import-module,react/renderer/runtimescheduler) $(call import-module,react/renderer/scheduler) $(call import-module,react/renderer/templateprocessor) $(call import-module,react/renderer/textlayoutmanager) diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK index e45bf4618f2f56..a534958295f9aa 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK @@ -19,7 +19,7 @@ rn_xplat_cxx_library( ], fbandroid_allow_jni_merging = True, labels = ["supermodule:xplat/default/public.react_native.infra"], - platforms = (ANDROID), + platforms = ANDROID, preprocessor_flags = [ "-DLOG_TAG=\"ReactNative\"", "-DWITH_FBSYSTRACE=1", diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp index d7fb074d31ccd5..7c9d43bee01dd3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp @@ -493,6 +493,7 @@ bool isMapBufferSerializationEnabled() { void Binding::installFabricUIManager( jni::alias_ref runtimeExecutorHolder, + jni::alias_ref runtimeSchedulerHolder, jni::alias_ref javaUIManager, EventBeatManager *eventBeatManager, jni::alias_ref jsMessageQueueThread, @@ -527,6 +528,19 @@ void Binding::installFabricUIManager( std::make_shared(jsMessageQueueThread); auto runtimeExecutor = runtimeExecutorHolder->cthis()->get(); + if (runtimeSchedulerHolder) { + auto runtimeScheduler = runtimeSchedulerHolder->cthis()->get(); + if (runtimeScheduler) { + runtimeScheduler->setEnableYielding(config->getBool( + "react_native_new_architecture:runtimescheduler_enable_yielding_android")); + runtimeExecutor = + [runtimeScheduler]( + std::function &&callback) { + runtimeScheduler->scheduleWork(std::move(callback)); + }; + } + } + // TODO: T31905686 Create synchronous Event Beat jni::global_ref localJavaUIManager = javaUIManager_; EventBeat::Factory synchronousBeatFactory = diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.h b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.h index d3045b0e1b1a43..5ae4f0189e29ba 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.h +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -105,6 +106,7 @@ class Binding : public jni::HybridClass, void installFabricUIManager( jni::alias_ref runtimeExecutorHolder, + jni::alias_ref runtimeSchedulerHolder, jni::alias_ref javaUIManager, EventBeatManager *eventBeatManager, jni::alias_ref jsMessageQueueThread, diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java index 2370e84ba2fa97..ca2c7df44f148c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java @@ -13,6 +13,7 @@ import static com.facebook.react.fabric.FabricUIManager.IS_DEVELOPMENT_ENVIRONMENT; import android.os.SystemClock; +import android.view.View; import androidx.annotation.AnyThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -274,10 +275,17 @@ private boolean dispatchMountItems() { executeOrEnqueue(mountItem); } catch (Throwable e) { // If there's an exception, we want to log diagnostics in prod and rethrow. - FLog.e(TAG, "dispatchMountItems: caught exception, displaying all MountItems", e); + FLog.e(TAG, "dispatchMountItems: caught exception, displaying mount state", e); for (MountItem m : mountItemsToDispatch) { printMountItem(m, "dispatchMountItems: mountItem"); } + if (mountItem.getSurfaceId() != View.NO_ID) { + SurfaceMountingManager surfaceManager = + mMountingManager.getSurfaceManager(mountItem.getSurfaceId()); + if (surfaceManager != null) { + surfaceManager.printSurfaceState(); + } + } if (ReactIgnorableMountingException.isIgnorable(e)) { ReactSoftExceptionLogger.logSoftException(TAG, e); diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java index 1f05f824c8f6ec..f93d1c20dcadf8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java @@ -963,6 +963,25 @@ public View getView(int reactTag) { return (ViewGroupManager) viewState.mViewManager; } + public void printSurfaceState() { + FLog.e(TAG, "Views created for surface {%d}:", getSurfaceId()); + for (ViewState viewState : mTagToViewState.values()) { + String viewManagerName = + viewState.mViewManager != null ? viewState.mViewManager.getName() : null; + @Nullable View view = viewState.mView; + @Nullable View parent = view != null ? (View) view.getParent() : null; + @Nullable Integer parentTag = parent != null ? parent.getId() : null; + + FLog.e( + TAG, + "<%s id=%d parentTag=%s isRoot=%b />", + viewManagerName, + viewState.mReactTag, + parentTag, + viewState.mIsRoot); + } + } + /** * This class holds view state for react tags. Objects of this class are stored into the {@link * #mTagToViewState}, and they should be updated in the same thread. diff --git a/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/Android.mk b/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/Android.mk index c521147677c16d..19a28eee5af259 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/Android.mk +++ b/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/Android.mk @@ -15,7 +15,7 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH) LOCAL_CFLAGS += -fvisibility=hidden -fexceptions -frtti -LOCAL_STATIC_LIBRARIES := libjsi libjsireact jscruntime -LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libreactnativejni +LOCAL_STATIC_LIBRARIES := libjsireact jscruntime +LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libreactnativejni libjsi include $(BUILD_SHARED_LIBRARY) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/Android.mk b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/Android.mk index 53fb0c2bf557ef..6c5a7224c78a97 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/Android.mk +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/Android.mk @@ -15,7 +15,7 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH) LOCAL_CFLAGS += -fvisibility=hidden -fexceptions -frtti -LOCAL_STATIC_LIBRARIES := libjsi libjsireact -LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libreactnativejni +LOCAL_STATIC_LIBRARIES := libjsireact +LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libreactnativejni libjsi include $(BUILD_SHARED_LIBRARY) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK deleted file mode 100644 index 80a1af4bb9ac75..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK +++ /dev/null @@ -1,27 +0,0 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") - -rn_android_library( - name = "datepicker", - srcs = glob(["**/*.java"]), - autoglob = False, - is_androidx = True, - labels = ["supermodule:xplat/default/public.react_native.infra"], - provided_deps = [ - react_native_dep("third-party/android/androidx:annotation"), - react_native_dep("third-party/android/androidx:core"), - react_native_dep("third-party/android/androidx:fragment"), - react_native_dep("third-party/android/androidx:legacy-support-core-ui"), - react_native_dep("third-party/android/androidx:legacy-support-core-utils"), - ], - visibility = [ - "PUBLIC", - ], - deps = [ - react_native_dep("third-party/java/infer-annotations:infer-annotations"), - react_native_dep("third-party/java/jsr-305:jsr-305"), - react_native_target("java/com/facebook/react/bridge:bridge"), - react_native_target("java/com/facebook/react/common:common"), - react_native_target("java/com/facebook/react/module/annotations:annotations"), - ], - exported_deps = [react_native_root_target(":FBReactNativeSpec")], -) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java deleted file mode 100644 index f3d190b4432e22..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.modules.datepicker; - -import android.annotation.SuppressLint; -import android.app.DatePickerDialog; -import android.app.DatePickerDialog.OnDateSetListener; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnDismissListener; -import android.graphics.drawable.ColorDrawable; -import android.os.Bundle; -import android.widget.DatePicker; -import androidx.annotation.Nullable; -import androidx.fragment.app.DialogFragment; -import java.util.Calendar; -import java.util.Locale; - -@SuppressLint("ValidFragment") -public class DatePickerDialogFragment extends DialogFragment { - - /** Minimum date supported by {@link DatePicker}, 01 Jan 1900 */ - private static final long DEFAULT_MIN_DATE = -2208988800001l; - - @Nullable private OnDateSetListener mOnDateSetListener; - @Nullable private OnDismissListener mOnDismissListener; - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - Bundle args = getArguments(); - return createDialog(args, getActivity(), mOnDateSetListener); - } - - /*package*/ static Dialog createDialog( - Bundle args, Context activityContext, @Nullable OnDateSetListener onDateSetListener) { - final Calendar c = Calendar.getInstance(); - if (args != null && args.containsKey(DatePickerDialogModule.ARG_DATE)) { - c.setTimeInMillis(args.getLong(DatePickerDialogModule.ARG_DATE)); - } - final int year = c.get(Calendar.YEAR); - final int month = c.get(Calendar.MONTH); - final int day = c.get(Calendar.DAY_OF_MONTH); - - DatePickerMode mode = DatePickerMode.DEFAULT; - if (args != null && args.getString(DatePickerDialogModule.ARG_MODE, null) != null) { - mode = - DatePickerMode.valueOf( - args.getString(DatePickerDialogModule.ARG_MODE).toUpperCase(Locale.US)); - } - - DatePickerDialog dialog = null; - - switch (mode) { - case CALENDAR: - dialog = - new DismissableDatePickerDialog( - activityContext, - activityContext - .getResources() - .getIdentifier( - "CalendarDatePickerDialog", "style", activityContext.getPackageName()), - onDateSetListener, - year, - month, - day); - break; - case SPINNER: - dialog = - new DismissableDatePickerDialog( - activityContext, - android.R.style.Theme_Holo_Light_Dialog, - onDateSetListener, - year, - month, - day); - dialog - .getWindow() - .setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT)); - break; - case DEFAULT: - dialog = - new DismissableDatePickerDialog(activityContext, onDateSetListener, year, month, day); - break; - } - - final DatePicker datePicker = dialog.getDatePicker(); - - if (args != null && args.containsKey(DatePickerDialogModule.ARG_MINDATE)) { - // Set minDate to the beginning of the day. We need this because of clowniness in datepicker - // that causes it to throw an exception if minDate is greater than the internal timestamp - // that it generates from the y/m/d passed in the constructor. - c.setTimeInMillis(args.getLong(DatePickerDialogModule.ARG_MINDATE)); - c.set(Calendar.HOUR_OF_DAY, 0); - c.set(Calendar.MINUTE, 0); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - datePicker.setMinDate(c.getTimeInMillis()); - } else { - // This is to work around a bug in DatePickerDialog where it doesn't display a title showing - // the date under certain conditions. - datePicker.setMinDate(DEFAULT_MIN_DATE); - } - if (args != null && args.containsKey(DatePickerDialogModule.ARG_MAXDATE)) { - // Set maxDate to the end of the day, same reason as for minDate. - c.setTimeInMillis(args.getLong(DatePickerDialogModule.ARG_MAXDATE)); - c.set(Calendar.HOUR_OF_DAY, 23); - c.set(Calendar.MINUTE, 59); - c.set(Calendar.SECOND, 59); - c.set(Calendar.MILLISECOND, 999); - datePicker.setMaxDate(c.getTimeInMillis()); - } - - return dialog; - } - - @Override - public void onDismiss(DialogInterface dialog) { - super.onDismiss(dialog); - if (mOnDismissListener != null) { - mOnDismissListener.onDismiss(dialog); - } - } - - /*package*/ void setOnDateSetListener(@Nullable OnDateSetListener onDateSetListener) { - mOnDateSetListener = onDateSetListener; - } - - /*package*/ void setOnDismissListener(@Nullable OnDismissListener onDismissListener) { - mOnDismissListener = onDismissListener; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogModule.java deleted file mode 100644 index e6971464889241..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogModule.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.modules.datepicker; - -import android.app.Activity; -import android.app.DatePickerDialog.OnDateSetListener; -import android.content.DialogInterface; -import android.content.DialogInterface.OnDismissListener; -import android.os.Bundle; -import android.widget.DatePicker; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.DialogFragment; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; -import com.facebook.fbreact.specs.NativeDatePickerAndroidSpec; -import com.facebook.react.bridge.*; -import com.facebook.react.common.annotations.VisibleForTesting; -import com.facebook.react.module.annotations.ReactModule; - -/** - * {@link NativeModule} that allows JS to show a native date picker dialog and get called back when - * the user selects a date. - */ -@ReactModule(name = DatePickerDialogModule.FRAGMENT_TAG) -public class DatePickerDialogModule extends NativeDatePickerAndroidSpec { - - @VisibleForTesting public static final String FRAGMENT_TAG = "DatePickerAndroid"; - - private static final String ERROR_NO_ACTIVITY = "E_NO_ACTIVITY"; - - /* package */ static final String ARG_DATE = "date"; - /* package */ static final String ARG_MINDATE = "minDate"; - /* package */ static final String ARG_MAXDATE = "maxDate"; - /* package */ static final String ARG_MODE = "mode"; - - /* package */ static final String ACTION_DATE_SET = "dateSetAction"; - /* package */ static final String ACTION_DISMISSED = "dismissedAction"; - - public DatePickerDialogModule(ReactApplicationContext reactContext) { - super(reactContext); - } - - public @NonNull String getName() { - return DatePickerDialogModule.FRAGMENT_TAG; - } - - private class DatePickerDialogListener implements OnDateSetListener, OnDismissListener { - - private final Promise mPromise; - private boolean mPromiseResolved = false; - - public DatePickerDialogListener(final Promise promise) { - mPromise = promise; - } - - @Override - public void onDateSet(DatePicker view, int year, int month, int day) { - if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) { - WritableMap result = new WritableNativeMap(); - result.putString("action", ACTION_DATE_SET); - result.putInt("year", year); - result.putInt("month", month); - result.putInt("day", day); - mPromise.resolve(result); - mPromiseResolved = true; - } - } - - @Override - public void onDismiss(DialogInterface dialog) { - if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) { - WritableMap result = new WritableNativeMap(); - result.putString("action", ACTION_DISMISSED); - mPromise.resolve(result); - mPromiseResolved = true; - } - } - } - - /** - * Show a date picker dialog. - * - * @param options a map containing options. Available keys are: - *
    - *
  • {@code date} (timestamp in milliseconds) the date to show by default - *
  • {@code minDate} (timestamp in milliseconds) the minimum date the user should be - * allowed to select - *
  • {@code maxDate} (timestamp in milliseconds) the maximum date the user should be - * allowed to select - *
  • {@code mode} To set the date picker mode to 'calendar/spinner/default' - *
- * - * @param promise This will be invoked with parameters action, year, month (0-11), day, where - * action is {@code dateSetAction} or {@code dismissedAction}, depending on what the user did. - * If the action is dismiss, year, month and date are undefined. - */ - @Override - public void open(@Nullable final ReadableMap options, final Promise promise) { - Activity raw_activity = getCurrentActivity(); - if (raw_activity == null || !(raw_activity instanceof FragmentActivity)) { - promise.reject( - ERROR_NO_ACTIVITY, - "Tried to open a DatePicker dialog while not attached to a FragmentActivity"); - return; - } - - FragmentActivity activity = (FragmentActivity) raw_activity; - - final FragmentManager fragmentManager = activity.getSupportFragmentManager(); - DialogFragment oldFragment = (DialogFragment) fragmentManager.findFragmentByTag(FRAGMENT_TAG); - if (oldFragment != null) { - oldFragment.dismiss(); - } - activity.runOnUiThread( - new Runnable() { - @Override - public void run() { - DatePickerDialogFragment fragment = new DatePickerDialogFragment(); - if (options != null) { - final Bundle args = createFragmentArguments(options); - fragment.setArguments(args); - } - final DatePickerDialogListener listener = new DatePickerDialogListener(promise); - fragment.setOnDismissListener(listener); - fragment.setOnDateSetListener(listener); - fragment.show(fragmentManager, FRAGMENT_TAG); - } - }); - } - - private Bundle createFragmentArguments(ReadableMap options) { - final Bundle args = new Bundle(); - if (options.hasKey(ARG_DATE) && !options.isNull(ARG_DATE)) { - args.putLong(ARG_DATE, (long) options.getDouble(ARG_DATE)); - } - if (options.hasKey(ARG_MINDATE) && !options.isNull(ARG_MINDATE)) { - args.putLong(ARG_MINDATE, (long) options.getDouble(ARG_MINDATE)); - } - if (options.hasKey(ARG_MAXDATE) && !options.isNull(ARG_MAXDATE)) { - args.putLong(ARG_MAXDATE, (long) options.getDouble(ARG_MAXDATE)); - } - if (options.hasKey(ARG_MODE) && !options.isNull(ARG_MODE)) { - args.putString(ARG_MODE, options.getString(ARG_MODE)); - } - return args; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DismissableDatePickerDialog.java b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DismissableDatePickerDialog.java deleted file mode 100644 index cfcc1fd3c77488..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DismissableDatePickerDialog.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.modules.datepicker; - -import android.app.DatePickerDialog; -import android.content.Context; -import android.content.res.TypedArray; -import android.os.Build; -import android.util.AttributeSet; -import android.widget.DatePicker; -import androidx.annotation.Nullable; -import java.lang.reflect.Field; -import java.lang.reflect.Method; - -public class DismissableDatePickerDialog extends DatePickerDialog { - - public DismissableDatePickerDialog( - Context context, - @Nullable DatePickerDialog.OnDateSetListener callback, - int year, - int monthOfYear, - int dayOfMonth) { - super(context, callback, year, monthOfYear, dayOfMonth); - fixSpinner(context, year, monthOfYear, dayOfMonth); - } - - public DismissableDatePickerDialog( - Context context, - int theme, - @Nullable DatePickerDialog.OnDateSetListener callback, - int year, - int monthOfYear, - int dayOfMonth) { - super(context, theme, callback, year, monthOfYear, dayOfMonth); - fixSpinner(context, year, monthOfYear, dayOfMonth); - } - - private void fixSpinner(Context context, int year, int month, int dayOfMonth) { - if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N) { - try { - // Get the theme's android:datePickerMode - final int MODE_SPINNER = 2; - Class styleableClass = Class.forName("com.android.internal.R$styleable"); - Field datePickerStyleableField = styleableClass.getField("DatePicker"); - int[] datePickerStyleable = (int[]) datePickerStyleableField.get(null); - - final TypedArray a = - context.obtainStyledAttributes( - null, datePickerStyleable, android.R.attr.datePickerStyle, 0); - Field datePickerModeStyleableField = styleableClass.getField("DatePicker_datePickerMode"); - int datePickerModeStyleable = datePickerModeStyleableField.getInt(null); - final int mode = a.getInt(datePickerModeStyleable, MODE_SPINNER); - a.recycle(); - - if (mode == MODE_SPINNER) { - DatePicker datePicker = - (DatePicker) - findField(DatePickerDialog.class, DatePicker.class, "mDatePicker").get(this); - Class delegateClass = Class.forName("android.widget.DatePickerSpinnerDelegate"); - Field delegateField = findField(DatePicker.class, delegateClass, "mDelegate"); - Object delegate = delegateField.get(datePicker); - Class spinnerDelegateClass; - spinnerDelegateClass = Class.forName("android.widget.DatePickerSpinnerDelegate"); - - // In 7.0 Nougat for some reason the datePickerMode is ignored and the delegate is - // DatePickerClockDelegate - if (delegate.getClass() != spinnerDelegateClass) { - delegateField.set(datePicker, null); // throw out the DatePickerClockDelegate! - datePicker.removeAllViews(); // remove the DatePickerClockDelegate views - Method createSpinnerUIDelegate = - DatePicker.class.getDeclaredMethod( - "createSpinnerUIDelegate", - Context.class, - AttributeSet.class, - int.class, - int.class); - createSpinnerUIDelegate.setAccessible(true); - - // Instantiate a DatePickerSpinnerDelegate throughout createSpinnerUIDelegate method - delegate = - createSpinnerUIDelegate.invoke( - datePicker, context, null, android.R.attr.datePickerStyle, 0); - delegateField.set( - datePicker, delegate); // set the DatePicker.mDelegate to the spinner delegate - datePicker.setCalendarViewShown(false); - // Initialize the date for the DatePicker delegate again - datePicker.init(year, month, dayOfMonth, this); - } - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - private static Field findField(Class objectClass, Class fieldClass, String expectedName) { - try { - Field field = objectClass.getDeclaredField(expectedName); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException e) { - } // ignore - // search for it if it wasn't found under the expected ivar name - for (Field searchField : objectClass.getDeclaredFields()) { - if (searchField.getType() == fieldClass) { - searchField.setAccessible(true); - return searchField; - } - } - return null; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/BUCK b/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/BUCK deleted file mode 100644 index a68079db767f6c..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/BUCK +++ /dev/null @@ -1,20 +0,0 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") - -rn_android_library( - name = "runtimescheduler", - srcs = glob(["**/*.java"]), - autoglob = False, - is_androidx = True, - labels = ["supermodule:xplat/default/public.react_native.infra"], - visibility = [ - "PUBLIC", - ], - deps = [ - react_native_target("java/com/facebook/react/runtimescheduler/jni:jni"), - react_native_dep("third-party/android/androidx:annotation"), - react_native_dep("third-party/java/infer-annotations:infer-annotations"), - react_native_dep("libraries/fbjni:java"), - react_native_target("java/com/facebook/react/bridge:bridge"), - react_native_dep("libraries/soloader/java/com/facebook/soloader:soloader"), - ], -) diff --git a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/RuntimeSchedulerManager.java b/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/RuntimeSchedulerManager.java deleted file mode 100644 index d7846b568c4091..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/RuntimeSchedulerManager.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.runtimescheduler; - -import com.facebook.jni.HybridData; -import com.facebook.proguard.annotations.DoNotStrip; -import com.facebook.proguard.annotations.DoNotStripAny; -import com.facebook.react.bridge.RuntimeExecutor; -import com.facebook.soloader.SoLoader; - -@DoNotStripAny -public class RuntimeSchedulerManager { - - static { - staticInit(); - } - - @DoNotStrip - @SuppressWarnings("unused") - private final HybridData mHybridData; - - public RuntimeSchedulerManager(RuntimeExecutor runtimeExecutor) { - mHybridData = initHybrid(runtimeExecutor); - installJSIBindings(); - } - - private native HybridData initHybrid(RuntimeExecutor runtimeExecutor); - - private native void installJSIBindings(); - - private static void staticInit() { - SoLoader.loadLibrary("runtimeschedulerjni"); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/Android.mk b/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/Android.mk deleted file mode 100644 index bb4e32011288ca..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/Android.mk +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := runtimeschedulerjni - -LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) - -LOCAL_SHARED_LIBRARIES := libglog libfb libfbjni libglog_init libreact_render_runtimescheduler librrc_native - -LOCAL_STATIC_LIBRARIES := - -LOCAL_C_INCLUDES := $(LOCAL_PATH)/ - -LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ - -LOCAL_CFLAGS := \ - -DLOG_TAG=\"ReacTNative\" - -LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall - -include $(BUILD_SHARED_LIBRARY) - -$(call import-module,fbgloginit) -$(call import-module,fb) -$(call import-module,fbjni) -$(call import-module,glog) - -$(call import-module,react/renderer/runtimescheduler) diff --git a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/BUCK b/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/BUCK deleted file mode 100644 index a694309d58bf5b..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/BUCK +++ /dev/null @@ -1,35 +0,0 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "react_native_target", "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob") - -rn_xplat_cxx_library( - name = "jni", - srcs = glob(["*.cpp"]), - headers = glob(["*.h"]), - header_namespace = "", - exported_headers = subdir_glob( - [ - ("", "**/*.h"), - ], - prefix = "react/runtimescheduler", - ), - compiler_flags = [ - "-fexceptions", - "-frtti", - "-std=c++17", - "-Wall", - ], - fbandroid_allow_jni_merging = True, - labels = ["supermodule:xplat/default/public.react_native.infra"], - platforms = (ANDROID), - preprocessor_flags = [ - "-DLOG_TAG=\"ReactNative\"", - "-DWITH_FBSYSTRACE=1", - ], - soname = "libruntimeschedulerjni.$(ext)", - visibility = ["PUBLIC"], - deps = [ - react_native_xplat_target("react/renderer/runtimescheduler:runtimescheduler"), - react_native_xplat_target("runtimeexecutor:runtimeexecutor"), - react_native_target("jni/react/jni:jni"), - FBJNI_TARGET, - ], -) diff --git a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/OnLoad.cpp b/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/OnLoad.cpp deleted file mode 100644 index 189de80dfce801..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/OnLoad.cpp +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include - -#include "RuntimeSchedulerManager.h" - -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { - return facebook::jni::initialize( - vm, [] { facebook::react::RuntimeSchedulerManager::registerNatives(); }); -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.cpp b/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.cpp deleted file mode 100644 index 2b0d89337035ca..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include -#include -#include -#include - -#include "RuntimeSchedulerManager.h" - -namespace facebook { -namespace react { - -RuntimeSchedulerManager::RuntimeSchedulerManager( - RuntimeExecutor runtimeExecutor) - : runtimeExecutor_(runtimeExecutor) {} - -jni::local_ref -RuntimeSchedulerManager::initHybrid( - jni::alias_ref, - jni::alias_ref runtimeExecutor) { - return makeCxxInstance(runtimeExecutor->cthis()->get()); -} - -void RuntimeSchedulerManager::registerNatives() { - registerHybrid({ - makeNativeMethod("initHybrid", RuntimeSchedulerManager::initHybrid), - makeNativeMethod( - "installJSIBindings", RuntimeSchedulerManager::installJSIBindings), - }); -} - -void RuntimeSchedulerManager::installJSIBindings() { - runtimeExecutor_([runtimeExecutor = runtimeExecutor_](jsi::Runtime &runtime) { - auto runtimeScheduler = std::make_shared(runtimeExecutor); - RuntimeSchedulerBinding::createAndInstallIfNeeded( - runtime, runtimeScheduler); - }); -} - -} // namespace react -} // namespace facebook diff --git a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.h b/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.h deleted file mode 100644 index 6456c7176fabf9..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include - -namespace facebook { -namespace react { - -class RuntimeSchedulerManager - : public facebook::jni::HybridClass { - public: - static auto constexpr kJavaDescriptor = - "Lcom/facebook/react/runtimescheduler/RuntimeSchedulerManager;"; - - static facebook::jni::local_ref initHybrid( - jni::alias_ref, - facebook::jni::alias_ref runtimeExecutor); - - static void registerNatives(); - - private: - friend HybridBase; - RuntimeExecutor runtimeExecutor_; - - void installJSIBindings(); - - explicit RuntimeSchedulerManager(RuntimeExecutor runtimeExecutor); -}; - -} // namespace react -} // namespace facebook diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK b/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK index a5bb7403e8f6d5..84138c4394d914 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK @@ -34,7 +34,6 @@ rn_android_library( react_native_target("java/com/facebook/react/modules/camera:camera"), react_native_target("java/com/facebook/react/modules/clipboard:clipboard"), react_native_target("java/com/facebook/react/modules/core:core"), - react_native_target("java/com/facebook/react/modules/datepicker:datepicker"), react_native_target("java/com/facebook/react/modules/debug:debug"), react_native_target("java/com/facebook/react/modules/dialog:dialog"), react_native_target("java/com/facebook/react/modules/fresco:fresco"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java index 0dd8f31c54525c..34dc28005784dd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java +++ b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java @@ -23,7 +23,6 @@ import com.facebook.react.modules.blob.FileReaderModule; import com.facebook.react.modules.camera.ImageStoreManager; import com.facebook.react.modules.clipboard.ClipboardModule; -import com.facebook.react.modules.datepicker.DatePickerDialogModule; import com.facebook.react.modules.dialog.DialogModule; import com.facebook.react.modules.fresco.FrescoModule; import com.facebook.react.modules.i18nmanager.I18nManagerModule; @@ -72,7 +71,6 @@ FileReaderModule.class, AsyncStorageModule.class, ClipboardModule.class, - DatePickerDialogModule.class, DialogModule.class, FrescoModule.class, I18nManagerModule.class, @@ -117,8 +115,6 @@ public MainReactPackage(MainPackageConfig config) { return new AsyncStorageModule(context); case ClipboardModule.NAME: return new ClipboardModule(context); - case DatePickerDialogModule.FRAGMENT_TAG: - return new DatePickerDialogModule(context); case DialogModule.NAME: return new DialogModule(context); case FrescoModule.NAME: @@ -199,7 +195,6 @@ public ReactModuleInfoProvider getReactModuleInfoProvider() { FileReaderModule.class, AsyncStorageModule.class, ClipboardModule.class, - DatePickerDialogModule.class, DialogModule.class, FrescoModule.class, I18nManagerModule.class, diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/jni/BUCK b/ReactAndroid/src/main/java/com/facebook/react/uimanager/jni/BUCK index 40d5eba1cdb280..de2375642909a9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/jni/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/jni/BUCK @@ -19,7 +19,7 @@ rn_xplat_cxx_library( ], fbandroid_allow_jni_merging = True, labels = ["supermodule:xplat/default/public.react_native.infra"], - platforms = (ANDROID), + platforms = ANDROID, preprocessor_flags = [ "-DLOG_TAG=\"ReactNative\"", "-DWITH_FBSYSTRACE=1", diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java index ffc8655c0a47c1..6ee067cb661a58 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java @@ -110,10 +110,6 @@ public void setAndroidHyphenationFrequency(ReactTextView view, @Nullable String view.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE); } else if (frequency.equals("full")) { view.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL); - } else if (frequency.equals("balanced")) { - view.setHyphenationFrequency(Layout.BREAK_STRATEGY_BALANCED); - } else if (frequency.equals("high")) { - view.setHyphenationFrequency(Layout.BREAK_STRATEGY_HIGH_QUALITY); } else if (frequency.equals("normal")) { view.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL); } else { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java index 95468c3a8fe510..26257ebe938814 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java @@ -32,6 +32,7 @@ import com.facebook.react.uimanager.UIViewOperationQueue; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.events.RCTEventEmitter; +import com.facebook.yoga.YogaBaselineFunction; import com.facebook.yoga.YogaConstants; import com.facebook.yoga.YogaDirection; import com.facebook.yoga.YogaMeasureFunction; @@ -159,6 +160,20 @@ public long measure( } }; + private final YogaBaselineFunction mTextBaselineFunction = + new YogaBaselineFunction() { + @Override + public float baseline(YogaNode node, float width, float height) { + Spannable text = + Assertions.assertNotNull( + mPreparedSpannableText, + "Spannable element has not been prepared in onBeforeLayout"); + + Layout layout = measureSpannedText(text, width, YogaMeasureMode.EXACTLY); + return layout.getLineBaseline(layout.getLineCount() - 1); + } + }; + public ReactTextShadowNode() { this(null); } @@ -171,6 +186,7 @@ public ReactTextShadowNode(@Nullable ReactTextViewManagerCallback reactTextViewM private void initMeasureFunction() { if (!isVirtual()) { setMeasureFunction(mTextMeasureFunction); + setBaselineFunction(mTextBaselineFunction); } } @@ -327,6 +343,11 @@ public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) { mJustificationMode); uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), reactTextUpdate); } + + if (mAdjustsFontSizeToFit) { + // Nodes with `adjustsFontSizeToFit` enabled need to be remeasured on every relayout. + markUpdated(); + } } @ReactProp(name = "onTextLayout") 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 7ce861de7bfdff..64135eda4f5eca 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 @@ -56,6 +56,7 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie private boolean mAdjustsFontSizeToFit = false; private int mLinkifyMaskType = 0; private boolean mNotifyOnInlineViewLayout; + private boolean mTextIsSelectable = false; private ReactViewBackgroundManager mReactBackgroundManager; private Spannable mSpanned; @@ -433,9 +434,16 @@ public void onStartTemporaryDetach() { } } + @Override + public void setTextIsSelectable(boolean selectable) { + mTextIsSelectable = selectable; + super.setTextIsSelectable(selectable); + } + @Override public void onAttachedToWindow() { super.onAttachedToWindow(); + setTextIsSelectable(mTextIsSelectable); if (mContainsImages && getText() instanceof Spanned) { Spanned text = (Spanned) getText(); TextInlineImageSpan[] spans = text.getSpans(0, text.length(), TextInlineImageSpan.class); 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 13311fef41bb2d..6c93d200e85797 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 @@ -68,9 +68,10 @@ public class TextAttributeProps { private static final int DEFAULT_TEXT_SHADOW_COLOR = 0x55000000; private static final int DEFAULT_JUSTIFICATION_MODE = (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) ? 0 : Layout.JUSTIFICATION_MODE_NONE; - private static final int DEFAULT_BREAK_STRATEGY = (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) ? 0 : Layout.BREAK_STRATEGY_HIGH_QUALITY; + private static final int DEFAULT_HYPHENATION_FREQUENCY = + (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) ? 0 : Layout.HYPHENATION_FREQUENCY_NONE; protected float mLineHeight = Float.NaN; protected boolean mIsColorSet = false; @@ -568,4 +569,22 @@ public static int getTextBreakStrategy(@Nullable String textBreakStrategy) { } return androidTextBreakStrategy; } + + public static int getHyphenationFrequency(@Nullable String hyphenationFrequency) { + int androidHyphenationFrequency = DEFAULT_HYPHENATION_FREQUENCY; + if (hyphenationFrequency != null) { + switch (hyphenationFrequency) { + case "none": + androidHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE; + break; + case "normal": + androidHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NORMAL; + break; + default: + androidHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_FULL; + break; + } + } + return androidHyphenationFrequency; + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java index b0715e7d6be174..f31eee22e30062 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java @@ -64,6 +64,7 @@ public class TextLayoutManager { private static final boolean DEFAULT_INCLUDE_FONT_PADDING = true; private static final String INCLUDE_FONT_PADDING_KEY = "includeFontPadding"; private static final String TEXT_BREAK_STRATEGY_KEY = "textBreakStrategy"; + private static final String HYPHENATION_FREQUENCY_KEY = "android_hyphenationFrequency"; private static final String MAXIMUM_NUMBER_OF_LINES_KEY = "maximumNumberOfLines"; private static final LruCache sSpannableCache = new LruCache<>(spannableCacheSize); @@ -250,7 +251,8 @@ private static Layout createLayout( float width, YogaMeasureMode widthYogaMeasureMode, boolean includeFontPadding, - int textBreakStrategy) { + int textBreakStrategy, + int hyphenationFrequency) { Layout layout; int spanLength = text.length(); boolean unconstrainedWidth = widthYogaMeasureMode == YogaMeasureMode.UNDEFINED || width < 0; @@ -281,10 +283,9 @@ private static Layout createLayout( .setLineSpacing(0.f, 1.f) .setIncludePad(includeFontPadding) .setBreakStrategy(textBreakStrategy) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) + .setHyphenationFrequency(hyphenationFrequency) .build(); } - } else if (boring != null && (unconstrainedWidth || boring.width <= width)) { int boringLayoutWidth = boring.width; if (boring.width < 0) { @@ -325,7 +326,7 @@ private static Layout createLayout( .setLineSpacing(0.f, 1.f) .setIncludePad(includeFontPadding) .setBreakStrategy(textBreakStrategy) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL); + .setHyphenationFrequency(hyphenationFrequency); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { builder.setUseLineSpacingFromFallbacks(true); @@ -378,6 +379,9 @@ public static long measureText( paragraphAttributes.hasKey(INCLUDE_FONT_PADDING_KEY) ? paragraphAttributes.getBoolean(INCLUDE_FONT_PADDING_KEY) : DEFAULT_INCLUDE_FONT_PADDING; + int hyphenationFrequency = + TextAttributeProps.getHyphenationFrequency( + paragraphAttributes.getString(HYPHENATION_FREQUENCY_KEY)); if (text == null) { throw new IllegalStateException("Spannable element has not been prepared in onBeforeLayout"); @@ -387,7 +391,13 @@ public static long measureText( Layout layout = createLayout( - text, boring, width, widthYogaMeasureMode, includeFontPadding, textBreakStrategy); + text, + boring, + width, + widthYogaMeasureMode, + includeFontPadding, + textBreakStrategy, + hyphenationFrequency); int maximumNumberOfLines = paragraphAttributes.hasKey(MAXIMUM_NUMBER_OF_LINES_KEY) @@ -539,10 +549,19 @@ public static WritableArray measureLines( paragraphAttributes.hasKey(INCLUDE_FONT_PADDING_KEY) ? paragraphAttributes.getBoolean(INCLUDE_FONT_PADDING_KEY) : DEFAULT_INCLUDE_FONT_PADDING; + int hyphenationFrequency = + TextAttributeProps.getTextBreakStrategy( + paragraphAttributes.getString(HYPHENATION_FREQUENCY_KEY)); Layout layout = createLayout( - text, boring, width, YogaMeasureMode.EXACTLY, includeFontPadding, textBreakStrategy); + text, + boring, + width, + YogaMeasureMode.EXACTLY, + includeFontPadding, + textBreakStrategy, + hyphenationFrequency); return FontMetricsUtil.getFontMetrics(text, layout, sTextPaintInstance, context); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java index 1e5287708a0c04..ee86e49d97e426 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java @@ -61,6 +61,7 @@ public class TextLayoutManagerMapBuffer { public static final short PA_KEY_TEXT_BREAK_STRATEGY = 2; public static final short PA_KEY_ADJUST_FONT_SIZE_TO_FIT = 3; public static final short PA_KEY_INCLUDE_FONT_PADDING = 4; + public static final short PA_KEY_HYPHENATION_FREQUENCY = 5; private static final boolean ENABLE_MEASURE_LOGGING = ReactBuildConfig.DEBUG && false; @@ -264,7 +265,8 @@ private static Layout createLayout( float width, YogaMeasureMode widthYogaMeasureMode, boolean includeFontPadding, - int textBreakStrategy) { + int textBreakStrategy, + int hyphenationFrequency) { Layout layout; int spanLength = text.length(); boolean unconstrainedWidth = widthYogaMeasureMode == YogaMeasureMode.UNDEFINED || width < 0; @@ -295,7 +297,7 @@ private static Layout createLayout( .setLineSpacing(0.f, 1.f) .setIncludePad(includeFontPadding) .setBreakStrategy(textBreakStrategy) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) + .setHyphenationFrequency(hyphenationFrequency) .build(); } @@ -338,7 +340,7 @@ private static Layout createLayout( .setLineSpacing(0.f, 1.f) .setIncludePad(includeFontPadding) .setBreakStrategy(textBreakStrategy) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL); + .setHyphenationFrequency(hyphenationFrequency); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { builder.setUseLineSpacingFromFallbacks(true); @@ -391,6 +393,9 @@ public static long measureText( paragraphAttributes.hasKey(PA_KEY_INCLUDE_FONT_PADDING) ? paragraphAttributes.getBoolean(PA_KEY_INCLUDE_FONT_PADDING) : DEFAULT_INCLUDE_FONT_PADDING; + int hyphenationFrequency = + TextAttributeProps.getTextBreakStrategy( + paragraphAttributes.getString(PA_KEY_HYPHENATION_FREQUENCY)); if (text == null) { throw new IllegalStateException("Spannable element has not been prepared in onBeforeLayout"); @@ -404,7 +409,13 @@ public static long measureText( Layout layout = createLayout( - text, boring, width, widthYogaMeasureMode, includeFontPadding, textBreakStrategy); + text, + boring, + width, + widthYogaMeasureMode, + includeFontPadding, + textBreakStrategy, + hyphenationFrequency); int maximumNumberOfLines = paragraphAttributes.hasKey(PA_KEY_MAX_NUMBER_OF_LINES) @@ -561,10 +572,19 @@ public static WritableArray measureLines( paragraphAttributes.hasKey(PA_KEY_INCLUDE_FONT_PADDING) ? paragraphAttributes.getBoolean(PA_KEY_INCLUDE_FONT_PADDING) : DEFAULT_INCLUDE_FONT_PADDING; + int hyphenationFrequency = + TextAttributeProps.getTextBreakStrategy( + paragraphAttributes.getString(PA_KEY_HYPHENATION_FREQUENCY)); Layout layout = createLayout( - text, boring, width, YogaMeasureMode.EXACTLY, includeFontPadding, textBreakStrategy); + text, + boring, + width, + YogaMeasureMode.EXACTLY, + includeFontPadding, + textBreakStrategy, + hyphenationFrequency); return FontMetricsUtil.getFontMetrics(text, layout, sTextPaintInstance, context); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextInputConnectionWrapper.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextInputConnectionWrapper.java index 55ae040054b92e..aa2f9a6462e524 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextInputConnectionWrapper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextInputConnectionWrapper.java @@ -131,10 +131,13 @@ public boolean deleteSurroundingText(int beforeLength, int afterLength) { @Override public boolean sendKeyEvent(KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { + boolean isNumberKey = event.getUnicodeChar() < 58 && event.getUnicodeChar() > 47; if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) { dispatchKeyEvent(BACKSPACE_KEY_VALUE); } else if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) { dispatchKeyEvent(ENTER_KEY_VALUE); + } else if (isNumberKey) { + dispatchKeyEvent(String.valueOf(event.getNumber())); } } return super.sendKeyEvent(event); diff --git a/ReactAndroid/src/main/jni/react/jni/Android.mk b/ReactAndroid/src/main/jni/react/jni/Android.mk index 82445d00ec04d2..af2077b5a66319 100644 --- a/ReactAndroid/src/main/jni/react/jni/Android.mk +++ b/ReactAndroid/src/main/jni/react/jni/Android.mk @@ -27,7 +27,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -Wno-unused-lambda-capture LOCAL_LDLIBS += -landroid # The dynamic libraries (.so files) that this module depends on. -LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libglog_init libyoga +LOCAL_SHARED_LIBRARIES := libfolly_json libfb libfbjni libglog_init libyoga libreact_render_runtimescheduler # The static libraries (.a files) that this module depends on. LOCAL_STATIC_LIBRARIES := libreactnative libcallinvokerholder libruntimeexecutor @@ -77,7 +77,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -Wno-unused-lambda-capture LOCAL_LDLIBS += -landroid # The dynamic libraries (.so files) that this module depends on. -LOCAL_SHARED_LIBRARIES := libreactnativeutilsjni libfolly_json libfb libfbjni libglog_init libyoga logger +LOCAL_SHARED_LIBRARIES := libreactnativeutilsjni libfolly_json libfb libfbjni libglog_init libyoga logger libreact_render_runtimescheduler # The static libraries (.a files) that this module depends on. LOCAL_STATIC_LIBRARIES := libreactnative libruntimeexecutor libcallinvokerholder @@ -129,6 +129,7 @@ $(call import-module,callinvoker) $(call import-module,reactperflogger) $(call import-module,hermes) $(call import-module,runtimeexecutor) +$(call import-module,react/renderer/runtimescheduler) $(call import-module,react/nativemodule/core) include $(REACT_SRC_DIR)/reactperflogger/jni/Android.mk diff --git a/ReactAndroid/src/main/jni/react/jni/BUCK b/ReactAndroid/src/main/jni/react/jni/BUCK index a53691bf91ee93..99160d55a3c45e 100644 --- a/ReactAndroid/src/main/jni/react/jni/BUCK +++ b/ReactAndroid/src/main/jni/react/jni/BUCK @@ -20,6 +20,7 @@ EXPORTED_HEADERS = [ "ReadableNativeArray.h", "ReadableNativeMap.h", "JRuntimeExecutor.h", + "JRuntimeScheduler.h", "WritableNativeArray.h", "WritableNativeMap.h", ] @@ -54,7 +55,7 @@ rn_xplat_cxx_library( visibility = [ "PUBLIC", ], - deps = ([ + deps = [ "//xplat/third-party/linker_lib:android", "//xplat/third-party/linker_lib:atomic", "//third-party/glog:glog", @@ -67,8 +68,9 @@ rn_xplat_cxx_library( react_native_xplat_target("cxxreact:module"), react_native_xplat_target("jsinspector:jsinspector"), react_native_xplat_target("runtimeexecutor:runtimeexecutor"), + react_native_xplat_target("react/renderer/runtimescheduler:runtimescheduler"), react_native_xplat_target("logger:logger"), react_native_xplat_dep("jsi:jsi"), FBJNI_TARGET, - ]) if not IS_OSS_BUILD else [], + ] if not IS_OSS_BUILD else [], ) diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp index d9e5ac34b41124..e5b36b30dd1a22 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp @@ -27,11 +27,14 @@ #include #include #include +#include +#include #include #include "CxxModuleWrapper.h" #include "JNativeRunnable.h" +#include "JReactCxxErrorHandler.h" #include "JReactSoftExceptionLogger.h" #include "JavaScriptExecutorHolder.h" #include "JniJSModulesUnbundle.h" @@ -135,6 +138,11 @@ void CatalystInstanceImpl::registerNatives() { CatalystInstanceImpl::handleMemoryPressure), makeNativeMethod( "getRuntimeExecutor", CatalystInstanceImpl::getRuntimeExecutor), + makeNativeMethod( + "getRuntimeScheduler", CatalystInstanceImpl::getRuntimeScheduler), + makeNativeMethod( + "installRuntimeScheduler", + CatalystInstanceImpl::installRuntimeScheduler), makeNativeMethod( "warnOnLegacyNativeModuleSystemUse", CatalystInstanceImpl::warnOnLegacyNativeModuleSystemUse), @@ -155,6 +163,7 @@ void log(ReactNativeLogLevel level, const char *message) { break; case ReactNativeLogLevelError: LOG(ERROR) << message; + JReactCxxErrorHandler::handleError(message); break; case ReactNativeLogLevelFatal: LOG(FATAL) << message; @@ -386,5 +395,25 @@ CatalystInstanceImpl::getRuntimeExecutor() { return runtimeExecutor_; } +jni::alias_ref +CatalystInstanceImpl::getRuntimeScheduler() { + return runtimeScheduler_; +} + +void CatalystInstanceImpl::installRuntimeScheduler() { + if (!runtimeScheduler_) { + auto runtimeExecutor = instance_->getRuntimeExecutor(); + auto runtimeScheduler = std::make_shared(runtimeExecutor); + + runtimeScheduler_ = + jni::make_global(JRuntimeScheduler::newObjectCxxArgs(runtimeScheduler)); + + runtimeExecutor([runtimeScheduler](jsi::Runtime &runtime) { + RuntimeSchedulerBinding::createAndInstallIfNeeded( + runtime, runtimeScheduler); + }); + } +} + } // namespace react } // namespace facebook diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h index cc4006b26b07c4..66daec3e34b05c 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h @@ -15,6 +15,7 @@ #include "CxxModuleWrapper.h" #include "JMessageQueueThread.h" #include "JRuntimeExecutor.h" +#include "JRuntimeScheduler.h" #include "JSLoader.h" #include "JavaModuleWrapper.h" #include "ModuleRegistryBuilder.h" @@ -98,6 +99,8 @@ class CatalystInstanceImpl : public jni::HybridClass { jni::alias_ref getJSCallInvokerHolder(); jni::alias_ref getNativeCallInvokerHolder(); jni::alias_ref getRuntimeExecutor(); + jni::alias_ref getRuntimeScheduler(); + void installRuntimeScheduler(); void setGlobalVariable(std::string propName, std::string &&jsonValue); jlong getJavaScriptContext(); void handleMemoryPressure(int pressureLevel); @@ -110,6 +113,7 @@ class CatalystInstanceImpl : public jni::HybridClass { jni::global_ref jsCallInvokerHolder_; jni::global_ref nativeCallInvokerHolder_; jni::global_ref runtimeExecutor_; + jni::global_ref runtimeScheduler_; }; } // namespace react diff --git a/ReactAndroid/src/main/jni/react/jni/JReactCxxErrorHandler.cpp b/ReactAndroid/src/main/jni/react/jni/JReactCxxErrorHandler.cpp new file mode 100644 index 00000000000000..5b3409eb1b47b3 --- /dev/null +++ b/ReactAndroid/src/main/jni/react/jni/JReactCxxErrorHandler.cpp @@ -0,0 +1,18 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "JReactCxxErrorHandler.h" + +using namespace facebook::react; + +void JReactCxxErrorHandler::handleError(std::string message) { + static const auto handleError = + javaClassStatic()->getStaticMethod( + "handleError"); + + return handleError(javaClassStatic(), message); +} diff --git a/ReactAndroid/src/main/jni/react/jni/JReactCxxErrorHandler.h b/ReactAndroid/src/main/jni/react/jni/JReactCxxErrorHandler.h new file mode 100644 index 00000000000000..0ed379b9f139d3 --- /dev/null +++ b/ReactAndroid/src/main/jni/react/jni/JReactCxxErrorHandler.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +namespace facebook { +namespace react { + +class JReactCxxErrorHandler : public jni::JavaClass { + public: + static constexpr const char *kJavaDescriptor = + "Lcom/facebook/react/bridge/ReactCxxErrorHandler;"; + + static void handleError(std::string message); +}; + +} // namespace react +} // namespace facebook diff --git a/ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.cpp b/ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.cpp new file mode 100644 index 00000000000000..3b059ec89c1efc --- /dev/null +++ b/ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "JRuntimeScheduler.h" + +namespace facebook { +namespace react { + +JRuntimeScheduler::JRuntimeScheduler( + std::shared_ptr const &runtimeScheduler) + : runtimeScheduler_(runtimeScheduler) {} + +std::shared_ptr JRuntimeScheduler::get() { + return runtimeScheduler_; +} + +} // namespace react +} // namespace facebook diff --git a/ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.h b/ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.h new file mode 100644 index 00000000000000..fb58c7ef7775cc --- /dev/null +++ b/ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +namespace facebook { +namespace react { + +class JRuntimeScheduler : public jni::HybridClass { + public: + static auto constexpr kJavaDescriptor = + "Lcom/facebook/react/bridge/RuntimeScheduler;"; + + std::shared_ptr get(); + + private: + friend HybridBase; + JRuntimeScheduler(std::shared_ptr const &runtimeScheduler); + std::shared_ptr runtimeScheduler_; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactAndroid/src/main/third-party/android/androidx/BUCK b/ReactAndroid/src/main/third-party/android/androidx/BUCK index d8dc38c7e5afba..d8398497d33652 100644 --- a/ReactAndroid/src/main/third-party/android/androidx/BUCK +++ b/ReactAndroid/src/main/third-party/android/androidx/BUCK @@ -299,6 +299,25 @@ fb_native.android_library( ], ) +fb_native.android_library( + name = "test-runner", + visibility = ["PUBLIC"], + exported_deps = [ + ":annotation", + ":test-monitor", + ":test-runner-binary", + ], +) + +fb_native.android_library( + name = "test-rules", + visibility = ["PUBLIC"], + exported_deps = [ + ":test-rules-binary", + ":test-runner", + ], +) + fb_native.android_library( name = "vectordrawable", visibility = ["PUBLIC"], @@ -476,6 +495,16 @@ fb_native.android_prebuilt_aar( aar = ":test-monitor-binary-aar", ) +fb_native.android_prebuilt_aar( + name = "test-rules-binary", + aar = ":test-rules-binary-aar", +) + +fb_native.android_prebuilt_aar( + name = "test-runner-binary", + aar = ":test-runner-binary-aar", +) + fb_native.android_prebuilt_aar( name = "vectordrawable-binary", aar = ":vectordrawable-binary-aar", @@ -661,8 +690,20 @@ fb_native.remote_file( fb_native.remote_file( name = "test-monitor-binary-aar", - sha1 = "d2f75d117c055f35c8ebbd4f96fabc2137df9e4d", - url = "mvn:androidx.test:monitor:aar:1.2.0", + sha1 = "4f3c15d0a1e0c943b233b0dc5d8f1e690cfe7c0a", + url = "mvn:androidx.test:monitor:aar:1.4.0", +) + +fb_native.remote_file( + name = "test-rules-binary-aar", + sha1 = "0984e8b5505f08489993c783702236af7a4a18c8", + url = "mvn:androidx.test:rules:aar:1.4.0", +) + +fb_native.remote_file( + name = "test-runner-binary-aar", + sha1 = "44d79420baf7ac208e33b35df8756f0e912ced38", + url = "mvn:androidx.test:runner:aar:1.4.0", ) fb_native.remote_file( diff --git a/ReactAndroid/src/main/third-party/java/testing-support-lib/BUCK b/ReactAndroid/src/main/third-party/java/testing-support-lib/BUCK index 43692052e1fdf1..bdcb72d5fcdbe3 100644 --- a/ReactAndroid/src/main/third-party/java/testing-support-lib/BUCK +++ b/ReactAndroid/src/main/third-party/java/testing-support-lib/BUCK @@ -1,36 +1,5 @@ load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") -fb_native.android_library( - name = "runner", - exported_deps = [ - ":monitor-binary", - ":runner-binary", - ], - visibility = ["PUBLIC"], -) - -fb_native.android_prebuilt_aar( - name = "monitor-binary", - aar = ":monitor-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "runner-binary", - aar = ":runner-binary-aar", -) - -fb_native.remote_file( - name = "monitor-binary-aar", - sha1 = "443c2f33d4e19f868cd4e4437909ec8dcf43f053", - url = "mvn:androidx.test:monitor:aar:1.1.1", -) - -fb_native.remote_file( - name = "runner-binary-aar", - sha1 = "810a7aacb5106d92cdf648b2497694c4ebf73500", - url = "mvn:androidx.test:runner:aar:1.1.1", -) - fb_native.android_prebuilt_aar( name = "exposed-instrumentation-api", aar = ":testing-support-instrumentation", diff --git a/ReactCommon/hermes/executor/Android.mk b/ReactCommon/hermes/executor/Android.mk index 491100c33a99e3..52b4d25085f74e 100644 --- a/ReactCommon/hermes/executor/Android.mk +++ b/ReactCommon/hermes/executor/Android.mk @@ -16,8 +16,8 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) LOCAL_C_INCLUDES := $(LOCAL_PATH) $(REACT_NATIVE)/ReactCommon/jsi $(call find-node-module,$(LOCAL_PATH),hermes-engine)/android/include LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) -LOCAL_STATIC_LIBRARIES := libjsi libjsireact -LOCAL_SHARED_LIBRARIES := libhermes +LOCAL_STATIC_LIBRARIES := libjsireact +LOCAL_SHARED_LIBRARIES := libhermes libjsi include $(BUILD_SHARED_LIBRARY) @@ -31,7 +31,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) LOCAL_C_INCLUDES := $(LOCAL_PATH) $(REACT_NATIVE)/ReactCommon/jsi $(call find-node-module,$(LOCAL_PATH),hermes-engine)/android/include LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) -LOCAL_STATIC_LIBRARIES := libjsi libjsireact libhermes-inspector -LOCAL_SHARED_LIBRARIES := libhermes +LOCAL_STATIC_LIBRARIES := libjsireact libhermes-inspector +LOCAL_SHARED_LIBRARIES := libhermes libjsi include $(BUILD_SHARED_LIBRARY) diff --git a/ReactCommon/hermes/inspector/Android.mk b/ReactCommon/hermes/inspector/Android.mk index a6692943e17deb..461b10aaac3323 100644 --- a/ReactCommon/hermes/inspector/Android.mk +++ b/ReactCommon/hermes/inspector/Android.mk @@ -21,7 +21,6 @@ LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_ROOT) LOCAL_CPP_FEATURES := exceptions -LOCAL_STATIC_LIBRARIES := libjsi -LOCAL_SHARED_LIBRARIES := jsinspector libfb libfbjni libfolly_futures libfolly_json libhermes +LOCAL_SHARED_LIBRARIES := jsinspector libfb libfbjni libfolly_futures libfolly_json libhermes libjsi libglog include $(BUILD_SHARED_LIBRARY) diff --git a/ReactCommon/jsi/Android.mk b/ReactCommon/jsi/Android.mk index 6bc98f1b35fcc9..3fce2059e2d759 100644 --- a/ReactCommon/jsi/Android.mk +++ b/ReactCommon/jsi/Android.mk @@ -17,7 +17,7 @@ LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) LOCAL_CFLAGS := -fexceptions -frtti -O3 LOCAL_SHARED_LIBRARIES := libfolly_json glog -include $(BUILD_STATIC_LIBRARY) +include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) diff --git a/ReactCommon/jsi/BUCK b/ReactCommon/jsi/BUCK index ac266ae81bf83a..1fc3de0f7d8cb9 100644 --- a/ReactCommon/jsi/BUCK +++ b/ReactCommon/jsi/BUCK @@ -1,5 +1,3 @@ -# BUILD FILE SYNTAX: SKYLARK - load("//tools/build_defs/oss:rn_defs.bzl", "APPLE", "IOS", "MACOSX", "react_native_xplat_dep", "rn_xplat_cxx_library") rn_xplat_cxx_library( diff --git a/ReactCommon/jsiexecutor/Android.mk b/ReactCommon/jsiexecutor/Android.mk index 74ae7a65cef20e..e0661538e6664c 100644 --- a/ReactCommon/jsiexecutor/Android.mk +++ b/ReactCommon/jsiexecutor/Android.mk @@ -16,7 +16,7 @@ LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) LOCAL_CFLAGS := -fexceptions -frtti -O3 -LOCAL_STATIC_LIBRARIES := libjsi reactnative reactperflogger -LOCAL_SHARED_LIBRARIES := libfolly_json glog +LOCAL_STATIC_LIBRARIES := reactnative reactperflogger +LOCAL_SHARED_LIBRARIES := libfolly_json glog libjsi include $(BUILD_STATIC_LIBRARY) diff --git a/ReactCommon/react/nativemodule/core/Android.mk b/ReactCommon/react/nativemodule/core/Android.mk index 9fbfdb4759d50a..bb2a0d79c7749c 100644 --- a/ReactCommon/react/nativemodule/core/Android.mk +++ b/ReactCommon/react/nativemodule/core/Android.mk @@ -15,9 +15,9 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/ReactCommon/*.cpp) $(wildcard $(LOCA LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/platform/android/ -LOCAL_SHARED_LIBRARIES := libfbjni libfolly_json libreactnativejni libreact_debug +LOCAL_SHARED_LIBRARIES := libfbjni libfolly_json libreactnativejni libreact_debug libjsi -LOCAL_STATIC_LIBRARIES := libjsi libreactperflogger +LOCAL_STATIC_LIBRARIES := libreactperflogger LOCAL_CFLAGS := \ -DLOG_TAG=\"ReactNative\" diff --git a/ReactCommon/react/nativemodule/samples/platform/android/Android.mk b/ReactCommon/react/nativemodule/samples/platform/android/Android.mk index 9694d7a07380f0..a000332e34c3e9 100644 --- a/ReactCommon/react/nativemodule/samples/platform/android/Android.mk +++ b/ReactCommon/react/nativemodule/samples/platform/android/Android.mk @@ -10,7 +10,7 @@ LOCAL_MODULE := sampleturbomodule LOCAL_C_INCLUDES := $(LOCAL_PATH) LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/ReactCommon/*.cpp) LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) -LOCAL_SHARED_LIBRARIES := libfbjni libreact_nativemodule_core +LOCAL_SHARED_LIBRARIES := libfbjni libreact_nativemodule_core libjsi LOCAL_CFLAGS := \ -DLOG_TAG=\"ReactNative\" LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall diff --git a/ReactCommon/react/renderer/animations/LayoutAnimationDriver.cpp b/ReactCommon/react/renderer/animations/LayoutAnimationDriver.cpp index 1d807cf9327bb4..1c0888f77388ab 100644 --- a/ReactCommon/react/renderer/animations/LayoutAnimationDriver.cpp +++ b/ReactCommon/react/renderer/animations/LayoutAnimationDriver.cpp @@ -11,7 +11,6 @@ #include #include -#include #include #include #include diff --git a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp index ecf5c3568d58aa..2467b5fa7f77ac 100644 --- a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp +++ b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -1094,13 +1093,11 @@ LayoutAnimationKeyFrameManager::pullTransaction( getComponentDescriptorForShadowView(baselineShadowView) .cloneProps(propsParserContext, viewStart.props, {}); - // Dynamic cast, because - we don't know the type of this - // ShadowNode, it could be Image or Text or something else with - // different base props. - const auto viewProps = - dynamic_cast(props.get()); - if (viewProps != nullptr) { - const_cast(viewProps)->opacity = 0; + if (baselineShadowView.traits.check( + ShadowNodeTraits::Trait::ViewKind)) { + auto const &viewProps = + *std::static_pointer_cast(props); + const_cast(viewProps).opacity = 0; } react_native_assert(props != nullptr); @@ -1119,13 +1116,11 @@ LayoutAnimationKeyFrameManager::pullTransaction( getComponentDescriptorForShadowView(baselineShadowView) .cloneProps(propsParserContext, viewStart.props, {}); - // Dynamic cast, because - we don't know the type of this - // ShadowNode, it could be Image or Text or something else with - // different base props. - const auto viewProps = - dynamic_cast(props.get()); - if (viewProps != nullptr) { - const_cast(viewProps)->transform = + if (baselineShadowView.traits.check( + ShadowNodeTraits::Trait::ViewKind)) { + auto const &viewProps = + *std::static_pointer_cast(props); + const_cast(viewProps).transform = Transform::Scale(isScaleX ? 0 : 1, isScaleY ? 0 : 1, 1); } @@ -1222,13 +1217,11 @@ LayoutAnimationKeyFrameManager::pullTransaction( getComponentDescriptorForShadowView(baselineShadowView) .cloneProps(propsParserContext, viewFinal.props, {}); - // Dynamic cast, because - we don't know the type of this - // ShadowNode, it could be Image or Text or something else with - // different base props. - const auto viewProps = - dynamic_cast(props.get()); - if (viewProps != nullptr) { - const_cast(viewProps)->opacity = 0; + if (baselineShadowView.traits.check( + ShadowNodeTraits::Trait::ViewKind)) { + auto const &viewProps = + *std::static_pointer_cast(props); + const_cast(viewProps).opacity = 0; } react_native_assert(props != nullptr); @@ -1249,13 +1242,11 @@ LayoutAnimationKeyFrameManager::pullTransaction( getComponentDescriptorForShadowView(baselineShadowView) .cloneProps(propsParserContext, viewFinal.props, {}); - // Dynamic cast, because - we don't know the type of this - // ShadowNode, it could be Image or Text or something else with - // different base props. - const auto viewProps = - dynamic_cast(props.get()); - if (viewProps != nullptr) { - const_cast(viewProps)->transform = + if (baselineShadowView.traits.check( + ShadowNodeTraits::Trait::ViewKind)) { + auto const &viewProps = + *std::static_pointer_cast(props); + const_cast(viewProps).transform = Transform::Scale(isScaleX ? 0 : 1, isScaleY ? 0 : 1, 1); } diff --git a/ReactCommon/react/renderer/attributedstring/AttributedString.h b/ReactCommon/react/renderer/attributedstring/AttributedString.h index f3ed7922383722..a1058c510bb267 100644 --- a/ReactCommon/react/renderer/attributedstring/AttributedString.h +++ b/ReactCommon/react/renderer/attributedstring/AttributedString.h @@ -11,7 +11,6 @@ #include #include -#include #include #include #include diff --git a/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp b/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp index fe64a462aa3e84..d5251fa907b903 100644 --- a/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp +++ b/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp @@ -21,13 +21,15 @@ bool ParagraphAttributes::operator==(const ParagraphAttributes &rhs) const { ellipsizeMode, textBreakStrategy, adjustsFontSizeToFit, - includeFontPadding) == + includeFontPadding, + android_hyphenationFrequency) == std::tie( rhs.maximumNumberOfLines, rhs.ellipsizeMode, rhs.textBreakStrategy, rhs.adjustsFontSizeToFit, - rhs.includeFontPadding) && + rhs.includeFontPadding, + rhs.android_hyphenationFrequency) && floatEquality(minimumFontSize, rhs.minimumFontSize) && floatEquality(maximumFontSize, rhs.maximumFontSize); } @@ -47,7 +49,9 @@ SharedDebugStringConvertibleList ParagraphAttributes::getDebugProps() const { debugStringConvertibleItem("adjustsFontSizeToFit", adjustsFontSizeToFit), debugStringConvertibleItem("minimumFontSize", minimumFontSize), debugStringConvertibleItem("maximumFontSize", maximumFontSize), - debugStringConvertibleItem("includeFontPadding", includeFontPadding)}; + debugStringConvertibleItem("includeFontPadding", includeFontPadding), + debugStringConvertibleItem( + "android_hyphenationFrequency", android_hyphenationFrequency)}; } #endif diff --git a/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h b/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h index a5666035eff6fb..22f65af3ea4dcf 100644 --- a/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h +++ b/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h @@ -42,7 +42,10 @@ class ParagraphAttributes : public DebugStringConvertible { */ EllipsizeMode ellipsizeMode{}; - TextBreakStrategy textBreakStrategy{}; + /* + * (Android only) Break strategy for breaking paragraphs into lines. + */ + TextBreakStrategy textBreakStrategy{TextBreakStrategy::HighQuality}; /* * Enables font size adjustment to fit constrained boundaries. @@ -55,6 +58,12 @@ class ParagraphAttributes : public DebugStringConvertible { */ bool includeFontPadding{true}; + /* + * (Android only) Frequency of automatic hyphenation to use when determining + * word breaks. + */ + HyphenationFrequency android_hyphenationFrequency{}; + /* * In case of font size adjustment enabled, defines minimum and maximum * font sizes. @@ -89,7 +98,8 @@ struct hash { attributes.adjustsFontSizeToFit, attributes.minimumFontSize, attributes.maximumFontSize, - attributes.includeFontPadding); + attributes.includeFontPadding, + attributes.android_hyphenationFrequency); } }; } // namespace std diff --git a/ReactCommon/react/renderer/attributedstring/TextAttributes.h b/ReactCommon/react/renderer/attributedstring/TextAttributes.h index 87bbffc30e2692..b7f07b962dae77 100644 --- a/ReactCommon/react/renderer/attributedstring/TextAttributes.h +++ b/ReactCommon/react/renderer/attributedstring/TextAttributes.h @@ -10,8 +10,8 @@ #include #include +#include #include -#include #include #include #include diff --git a/ReactCommon/react/renderer/attributedstring/conversions.h b/ReactCommon/react/renderer/attributedstring/conversions.h index 57fa61af975eec..56ab6bdef9438a 100644 --- a/ReactCommon/react/renderer/attributedstring/conversions.h +++ b/ReactCommon/react/renderer/attributedstring/conversions.h @@ -96,7 +96,7 @@ inline std::string toString(const TextBreakStrategy &textBreakStrategy) { LOG(ERROR) << "Unsupported TextBreakStrategy value"; react_native_assert(false); - return "simple"; + return "highQuality"; } inline void fromRawValue( @@ -116,14 +116,14 @@ inline void fromRawValue( // sane default LOG(ERROR) << "Unsupported TextBreakStrategy value: " << string; react_native_assert(false); - result = TextBreakStrategy::Simple; + result = TextBreakStrategy::HighQuality; } return; } LOG(ERROR) << "Unsupported TextBreakStrategy type"; react_native_assert(false); - result = TextBreakStrategy::Simple; + result = TextBreakStrategy::HighQuality; } inline void fromRawValue( @@ -618,6 +618,8 @@ inline std::string toString(const AccessibilityRole &accessibilityRole) { return "switch"; case AccessibilityRole::Tab: return "tab"; + case AccessibilityRole::TabBar: + return "tabbar"; case AccessibilityRole::Tablist: return "tablist"; case AccessibilityRole::Timer: @@ -687,6 +689,8 @@ inline void fromRawValue( result = AccessibilityRole::Switch; } else if (string == "tab") { result = AccessibilityRole::Tab; + } else if (string == "tabbar") { + result = AccessibilityRole::TabBar; } else if (string == "tablist") { result = AccessibilityRole::Tablist; } else if (string == "timer") { @@ -708,6 +712,48 @@ inline void fromRawValue( result = AccessibilityRole::None; } +inline std::string toString(const HyphenationFrequency &hyphenationFrequency) { + switch (hyphenationFrequency) { + case HyphenationFrequency::None: + return "none"; + case HyphenationFrequency::Normal: + return "normal"; + case HyphenationFrequency::Full: + return "full"; + } + + LOG(ERROR) << "Unsupported HyphenationFrequency value"; + react_native_assert(false); + return "none"; +} + +inline void fromRawValue( + const PropsParserContext &context, + const RawValue &value, + HyphenationFrequency &result) { + react_native_assert(value.hasType()); + if (value.hasType()) { + auto string = (std::string)value; + if (string == "none") { + result = HyphenationFrequency::None; + } else if (string == "normal") { + result = HyphenationFrequency::Normal; + } else if (string == "full") { + result = HyphenationFrequency::Full; + } else { + // sane default + LOG(ERROR) << "Unsupported HyphenationFrequency value: " << string; + react_native_assert(false); + result = HyphenationFrequency::None; + } + return; + } + + LOG(ERROR) << "Unsupported HyphenationFrequency type"; + react_native_assert(false); + result = HyphenationFrequency::None; +} + inline ParagraphAttributes convertRawProp( const PropsParserContext &context, RawProps const &rawProps, @@ -757,6 +803,12 @@ inline ParagraphAttributes convertRawProp( "includeFontPadding", sourceParagraphAttributes.includeFontPadding, defaultParagraphAttributes.includeFontPadding); + paragraphAttributes.android_hyphenationFrequency = convertRawProp( + context, + rawProps, + "android_hyphenationFrequency", + sourceParagraphAttributes.android_hyphenationFrequency, + defaultParagraphAttributes.android_hyphenationFrequency); return paragraphAttributes; } @@ -792,6 +844,9 @@ inline folly::dynamic toDynamic( values("textBreakStrategy", toString(paragraphAttributes.textBreakStrategy)); values("adjustsFontSizeToFit", paragraphAttributes.adjustsFontSizeToFit); values("includeFontPadding", paragraphAttributes.includeFontPadding); + values( + "android_hyphenationFrequency", + toString(paragraphAttributes.android_hyphenationFrequency)); return values; } @@ -989,6 +1044,7 @@ constexpr static Key PA_KEY_ELLIPSIZE_MODE = 1; constexpr static Key PA_KEY_TEXT_BREAK_STRATEGY = 2; constexpr static Key PA_KEY_ADJUST_FONT_SIZE_TO_FIT = 3; constexpr static Key PA_KEY_INCLUDE_FONT_PADDING = 4; +constexpr static Key PA_KEY_HYPHENATION_FREQUENCY = 5; inline MapBuffer toMapBuffer(const ParagraphAttributes ¶graphAttributes) { auto builder = MapBufferBuilder(); @@ -1003,6 +1059,9 @@ inline MapBuffer toMapBuffer(const ParagraphAttributes ¶graphAttributes) { PA_KEY_ADJUST_FONT_SIZE_TO_FIT, paragraphAttributes.adjustsFontSizeToFit); builder.putBool( PA_KEY_INCLUDE_FONT_PADDING, paragraphAttributes.includeFontPadding); + builder.putString( + PA_KEY_HYPHENATION_FREQUENCY, + toString(paragraphAttributes.android_hyphenationFrequency)); return builder.build(); } diff --git a/ReactCommon/react/renderer/attributedstring/primitives.h b/ReactCommon/react/renderer/attributedstring/primitives.h index deeb40b11a72b3..d4be52366132d3 100644 --- a/ReactCommon/react/renderer/attributedstring/primitives.h +++ b/ReactCommon/react/renderer/attributedstring/primitives.h @@ -53,7 +53,11 @@ enum class EllipsizeMode { Middle // Truncate middle of line: "ab...yz". }; -enum class TextBreakStrategy { Simple, Balanced, HighQuality }; +enum class TextBreakStrategy { + Simple, // Simple strategy. + HighQuality, // High-quality strategy, including hyphenation. + Balanced // Balances line lengths. +}; enum class TextAlignment { Natural, // Indicates the default alignment for script. @@ -112,6 +116,7 @@ enum class AccessibilityRole { Spinbutton, Switch, Tab, + TabBar, Tablist, Timer, Toolbar, @@ -125,6 +130,12 @@ enum class TextTransform { Unset, }; +enum class HyphenationFrequency { + None, // No hyphenation. + Normal, // Less frequent hyphenation. + Full // Standard amount of hyphenation. +}; + } // namespace react } // namespace facebook @@ -212,4 +223,11 @@ struct hash { return hash()(static_cast(v)); } }; + +template <> +struct hash { + size_t operator()(const facebook::react::HyphenationFrequency &v) const { + return hash()(static_cast(v)); + } +}; } // namespace std diff --git a/ReactCommon/react/renderer/components/image/Android.mk b/ReactCommon/react/renderer/components/image/Android.mk index 1d7fdcc85bae91..8c3fbcabda9c02 100644 --- a/ReactCommon/react/renderer/components/image/Android.mk +++ b/ReactCommon/react/renderer/components/image/Android.mk @@ -21,7 +21,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall LOCAL_STATIC_LIBRARIES := -LOCAL_SHARED_LIBRARIES := libyoga glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics librrc_view libreact_render_imagemanager libreact_debug libreact_render_mapbuffer +LOCAL_SHARED_LIBRARIES := libjsi libyoga glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics librrc_view libreact_render_imagemanager libreact_debug libreact_render_mapbuffer include $(BUILD_SHARED_LIBRARY) diff --git a/ReactCommon/react/renderer/components/inputaccessory/BUCK b/ReactCommon/react/renderer/components/inputaccessory/BUCK index 57297985967e5c..3cddfd26afe743 100644 --- a/ReactCommon/react/renderer/components/inputaccessory/BUCK +++ b/ReactCommon/react/renderer/components/inputaccessory/BUCK @@ -34,7 +34,7 @@ rn_xplat_cxx_library( fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), force_static = True, labels = ["supermodule:xplat/default/public.react_native.infra"], - platforms = (APPLE), + platforms = APPLE, preprocessor_flags = [ "-DLOG_TAG=\"ReactNative\"", "-DWITH_FBSYSTRACE=1", diff --git a/ReactCommon/react/renderer/components/legacyviewmanagerinterop/BUCK b/ReactCommon/react/renderer/components/legacyviewmanagerinterop/BUCK index 9b6a4eca2f85e7..93ee20de397b7e 100644 --- a/ReactCommon/react/renderer/components/legacyviewmanagerinterop/BUCK +++ b/ReactCommon/react/renderer/components/legacyviewmanagerinterop/BUCK @@ -37,7 +37,7 @@ rn_xplat_cxx_library( fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), force_static = True, labels = ["supermodule:xplat/default/public.react_native.infra"], - platforms = (APPLE), + platforms = APPLE, preprocessor_flags = [ "-DLOG_TAG=\"ReactNative\"", "-DWITH_FBSYSTRACE=1", diff --git a/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm b/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm index b84e3799b2404e..8c44bc24653834 100644 --- a/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm +++ b/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include "LegacyViewManagerInteropState.h" diff --git a/ReactCommon/react/renderer/components/safeareaview/BUCK b/ReactCommon/react/renderer/components/safeareaview/BUCK index 1af6a6f752e655..fcb7febca179a3 100644 --- a/ReactCommon/react/renderer/components/safeareaview/BUCK +++ b/ReactCommon/react/renderer/components/safeareaview/BUCK @@ -34,7 +34,7 @@ rn_xplat_cxx_library( fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), force_static = True, labels = ["supermodule:xplat/default/public.react_native.infra"], - platforms = (APPLE), + platforms = APPLE, preprocessor_flags = [ "-DLOG_TAG=\"ReactNative\"", "-DWITH_FBSYSTRACE=1", diff --git a/ReactCommon/react/renderer/components/scrollview/Android.mk b/ReactCommon/react/renderer/components/scrollview/Android.mk index a0bbbf75425d0b..9b02ae73f04215 100644 --- a/ReactCommon/react/renderer/components/scrollview/Android.mk +++ b/ReactCommon/react/renderer/components/scrollview/Android.mk @@ -21,7 +21,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall LOCAL_STATIC_LIBRARIES := -LOCAL_SHARED_LIBRARIES := libyoga libfolly_futures glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics librrc_view libreact_debug libreact_render_mapbuffer +LOCAL_SHARED_LIBRARIES := libjsi libyoga libfolly_futures glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics librrc_view libreact_debug libreact_render_mapbuffer include $(BUILD_SHARED_LIBRARY) diff --git a/ReactCommon/react/renderer/components/text/Android.mk b/ReactCommon/react/renderer/components/text/Android.mk index 4e082f6dd9912f..33bfdb78a96362 100644 --- a/ReactCommon/react/renderer/components/text/Android.mk +++ b/ReactCommon/react/renderer/components/text/Android.mk @@ -21,7 +21,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall LOCAL_STATIC_LIBRARIES := -LOCAL_SHARED_LIBRARIES := libyoga glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics libreact_render_uimanager libreact_render_textlayoutmanager libreact_render_attributedstring libreact_render_mounting librrc_view libreact_utils libreact_debug libreact_render_mapbuffer +LOCAL_SHARED_LIBRARIES := libjsi libyoga glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics libreact_render_uimanager libreact_render_textlayoutmanager libreact_render_attributedstring libreact_render_mounting librrc_view libreact_utils libreact_debug libreact_render_mapbuffer include $(BUILD_SHARED_LIBRARY) diff --git a/ReactCommon/react/renderer/components/text/RawTextShadowNode.h b/ReactCommon/react/renderer/components/text/RawTextShadowNode.h index 0a2b76e70b1412..8dbde86c996e93 100644 --- a/ReactCommon/react/renderer/components/text/RawTextShadowNode.h +++ b/ReactCommon/react/renderer/components/text/RawTextShadowNode.h @@ -39,9 +39,6 @@ inline RawTextShadowNode const &traitCast( ShadowNode const &shadowNode) { bool castable = shadowNode.getTraits().check(ShadowNodeTraits::Trait::RawText); - react_native_assert( - castable == - (dynamic_cast(&shadowNode) != nullptr)); react_native_assert(castable); (void)castable; return static_cast(shadowNode); @@ -55,9 +52,6 @@ inline RawTextShadowNode const *traitCast( } bool castable = shadowNode->getTraits().check(ShadowNodeTraits::Trait::RawText); - react_native_assert( - castable == - (dynamic_cast(shadowNode) != nullptr)); if (!castable) { return nullptr; } diff --git a/ReactCommon/react/renderer/components/text/TextShadowNode.h b/ReactCommon/react/renderer/components/text/TextShadowNode.h index 9e9a9f6b079c91..57e3f25076ba23 100644 --- a/ReactCommon/react/renderer/components/text/TextShadowNode.h +++ b/ReactCommon/react/renderer/components/text/TextShadowNode.h @@ -62,9 +62,6 @@ template <> inline TextShadowNode const &traitCast( ShadowNode const &shadowNode) { bool castable = shadowNode.getTraits().check(ShadowNodeTraits::Trait::Text); - react_native_assert( - castable == - (dynamic_cast(&shadowNode) != nullptr)); react_native_assert(castable); (void)castable; return static_cast(shadowNode); @@ -77,9 +74,6 @@ inline TextShadowNode const *traitCast( return nullptr; } bool castable = shadowNode->getTraits().check(ShadowNodeTraits::Trait::Text); - react_native_assert( - castable == - (dynamic_cast(shadowNode) != nullptr)); if (!castable) { return nullptr; } diff --git a/ReactCommon/react/renderer/components/textinput/Android.mk b/ReactCommon/react/renderer/components/textinput/Android.mk index 70e44891ddfb16..c45affab7b9b83 100644 --- a/ReactCommon/react/renderer/components/textinput/Android.mk +++ b/ReactCommon/react/renderer/components/textinput/Android.mk @@ -21,7 +21,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall LOCAL_STATIC_LIBRARIES := -LOCAL_SHARED_LIBRARIES := libyoga glog libfolly_json libglog_init libreact_render_core libreact_render_mounting libreact_render_componentregistry libreact_render_debug libreact_render_graphics libreact_render_uimanager libreact_render_imagemanager libreact_render_textlayoutmanager libreact_render_attributedstring librrc_text librrc_image librrc_view libreact_utils libreact_debug libreact_render_mapbuffer +LOCAL_SHARED_LIBRARIES := libjsi libyoga glog libfolly_json libglog_init libreact_render_core libreact_render_mounting libreact_render_componentregistry libreact_render_debug libreact_render_graphics libreact_render_uimanager libreact_render_imagemanager libreact_render_textlayoutmanager libreact_render_attributedstring librrc_text librrc_image librrc_view libreact_utils libreact_debug libreact_render_mapbuffer include $(BUILD_SHARED_LIBRARY) diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.cpp b/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.cpp index d7e4c3f93f195f..9e13cb97bb0574 100644 --- a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.cpp +++ b/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.cpp @@ -82,6 +82,12 @@ TextInputProps::TextInputProps( "autoFocus", sourceProps.autoFocus, {})), + selection(convertRawProp( + context, + rawProps, + "selection", + sourceProps.selection, + better::optional())), inputAccessoryViewID(convertRawProp( context, rawProps, @@ -115,13 +121,5 @@ ParagraphAttributes TextInputProps::getEffectiveParagraphAttributes() const { return result; } -#ifdef ANDROID -folly::dynamic TextInputProps::getDynamic() const { - folly::dynamic props = folly::dynamic::object(); - props["value"] = value; - return props; -} -#endif - } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.h b/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.h index 50b054e0b3ebb8..9fb44a4b2c1724 100644 --- a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.h +++ b/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.h @@ -58,6 +58,7 @@ class TextInputProps final : public ViewProps, public BaseTextProps { int const mostRecentEventCount{0}; bool autoFocus{false}; + better::optional selection{}; std::string const inputAccessoryViewID{}; @@ -66,10 +67,6 @@ class TextInputProps final : public ViewProps, public BaseTextProps { */ TextAttributes getEffectiveTextAttributes(Float fontSizeMultiplier) const; ParagraphAttributes getEffectiveParagraphAttributes() const; - -#ifdef ANDROID - folly::dynamic getDynamic() const; -#endif }; } // namespace react diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/primitives.h b/ReactCommon/react/renderer/components/textinput/iostextinput/primitives.h index f13e9b44a32e92..f3b0fc2dfc5899 100644 --- a/ReactCommon/react/renderer/components/textinput/iostextinput/primitives.h +++ b/ReactCommon/react/renderer/components/textinput/iostextinput/primitives.h @@ -77,6 +77,12 @@ enum class KeyboardType { VisiblePassword, }; +class Selection final { + public: + int start{0}; + int end{0}; +}; + /* * Controls features of text inputs. */ diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/propsConversions.h b/ReactCommon/react/renderer/components/textinput/iostextinput/propsConversions.h index cfd0675c407c81..162e989112474c 100644 --- a/ReactCommon/react/renderer/components/textinput/iostextinput/propsConversions.h +++ b/ReactCommon/react/renderer/components/textinput/iostextinput/propsConversions.h @@ -145,5 +145,38 @@ static TextInputTraits convertRawProp( return traits; } +inline void fromRawValue( + const PropsParserContext &context, + const RawValue &value, + Selection &result) { + if (value.hasType>()) { + auto map = (better::map)value; + for (const auto &pair : map) { + if (pair.first == "start") { + result.start = pair.second; + } else if (pair.first == "end") { + result.end = pair.second; + } else { + LOG(ERROR) << "Unsupported Selection map key: " << pair.first; + react_native_assert(false); + } + } + return; + } + + react_native_assert(value.hasType>()); + if (value.hasType>()) { + auto array = (std::vector)value; + react_native_assert(array.size() == 2); + if (array.size() >= 2) { + result = {array.at(0), array.at(1)}; + } else { + result = {0, 0}; + LOG(ERROR) << "Unsupported Selection vector size: " << array.size(); + } + } else { + LOG(ERROR) << "Unsupported Selection type"; + } +} } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/components/unimplementedview/Android.mk b/ReactCommon/react/renderer/components/unimplementedview/Android.mk index f533321b94d212..959500fb70d131 100644 --- a/ReactCommon/react/renderer/components/unimplementedview/Android.mk +++ b/ReactCommon/react/renderer/components/unimplementedview/Android.mk @@ -21,7 +21,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall LOCAL_STATIC_LIBRARIES := -LOCAL_SHARED_LIBRARIES := libyoga libfolly_futures glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics librrc_view libreact_debug +LOCAL_SHARED_LIBRARIES := libjsi libyoga libfolly_futures glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics librrc_view libreact_debug include $(BUILD_SHARED_LIBRARY) diff --git a/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h b/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h index b9306c2967d49a..23999ae4d28f54 100644 --- a/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h +++ b/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h @@ -33,6 +33,7 @@ enum class AccessibilityTraits : uint32_t { CausesPageTurn = (1 << 14), Header = (1 << 15), Switch = (1 << 16), + TabBar = (1 << 17), }; constexpr enum AccessibilityTraits operator|( @@ -74,6 +75,26 @@ constexpr bool operator!=( return !(rhs == lhs); } +struct AccessibilityValue { + better::optional min; + better::optional max; + better::optional now; + better::optional text{}; +}; + +constexpr bool operator==( + AccessibilityValue const &lhs, + AccessibilityValue const &rhs) { + return lhs.min == rhs.min && lhs.max == rhs.max && lhs.now == rhs.now && + lhs.text == rhs.text; +} + +constexpr bool operator!=( + AccessibilityValue const &lhs, + AccessibilityValue const &rhs) { + return !(rhs == lhs); +} + enum class ImportantForAccessibility { Auto, Yes, diff --git a/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp b/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp index d681a387ad431b..4dda5214c6dfb5 100644 --- a/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp +++ b/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp @@ -49,6 +49,12 @@ AccessibilityProps::AccessibilityProps( "accessibilityHint", sourceProps.accessibilityHint, "")), + accessibilityValue(convertRawProp( + context, + rawProps, + "accessibilityValue", + sourceProps.accessibilityValue, + {})), accessibilityActions(convertRawProp( context, rawProps, diff --git a/ReactCommon/react/renderer/components/view/AccessibilityProps.h b/ReactCommon/react/renderer/components/view/AccessibilityProps.h index 39330c082b5162..eab78469660526 100644 --- a/ReactCommon/react/renderer/components/view/AccessibilityProps.h +++ b/ReactCommon/react/renderer/components/view/AccessibilityProps.h @@ -31,6 +31,7 @@ class AccessibilityProps { AccessibilityState accessibilityState; std::string accessibilityLabel{""}; std::string accessibilityHint{""}; + AccessibilityValue accessibilityValue; std::vector accessibilityActions{}; bool accessibilityViewIsModal{false}; bool accessibilityElementsHidden{false}; diff --git a/ReactCommon/react/renderer/components/view/Android.mk b/ReactCommon/react/renderer/components/view/Android.mk index 877f17bd1c84fd..1e05d18f6b0250 100644 --- a/ReactCommon/react/renderer/components/view/Android.mk +++ b/ReactCommon/react/renderer/components/view/Android.mk @@ -21,7 +21,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall LOCAL_STATIC_LIBRARIES := -LOCAL_SHARED_LIBRARIES := libyoga glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics libreact_debug logger +LOCAL_SHARED_LIBRARIES := libyoga glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics libreact_debug logger libjsi include $(BUILD_SHARED_LIBRARY) diff --git a/ReactCommon/react/renderer/components/view/ViewPropsInterpolation.h b/ReactCommon/react/renderer/components/view/ViewPropsInterpolation.h index ddbf1d5367df38..c2352460b2f291 100644 --- a/ReactCommon/react/renderer/components/view/ViewPropsInterpolation.h +++ b/ReactCommon/react/renderer/components/view/ViewPropsInterpolation.h @@ -24,13 +24,6 @@ static inline void interpolateViewProps( const SharedProps &oldPropsShared, const SharedProps &newPropsShared, SharedProps &interpolatedPropsShared) { - // Verify the static_casts below are safe - react_native_assert( - dynamic_cast(oldPropsShared.get()) != nullptr && - dynamic_cast(newPropsShared.get()) != nullptr && - dynamic_cast(interpolatedPropsShared.get()) != - nullptr); - ViewProps const *oldViewProps = static_cast(oldPropsShared.get()); ViewProps const *newViewProps = diff --git a/ReactCommon/react/renderer/components/view/ViewShadowNode.h b/ReactCommon/react/renderer/components/view/ViewShadowNode.h index 0ccf2116e4477a..20ccc04d5f4504 100644 --- a/ReactCommon/react/renderer/components/view/ViewShadowNode.h +++ b/ReactCommon/react/renderer/components/view/ViewShadowNode.h @@ -24,7 +24,7 @@ class ViewShadowNode final : public ConcreteViewShadowNode< ViewEventEmitter> { public: static ShadowNodeTraits BaseTraits() { - auto traits = BaseShadowNode::BaseTraits(); + auto traits = ConcreteViewShadowNode::BaseTraits(); traits.set(ShadowNodeTraits::Trait::View); return traits; } diff --git a/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp b/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp index d0ec01182bc32b..0c5ccdf083c796 100644 --- a/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +++ b/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp @@ -23,6 +23,41 @@ namespace facebook { namespace react { +static int FabricDefaultYogaLog( + const YGConfigRef, + const YGNodeRef, + YGLogLevel level, + const char *format, + va_list args) { + va_list args_copy; + va_copy(args_copy, args); + + // Adding 1 to add space for terminating null character. + int size_s = vsnprintf(NULL, 0, format, args); + auto size = static_cast(size_s); + std::vector buffer(size); + + vsnprintf(buffer.data(), size, format, args_copy); + switch (level) { + case YGLogLevelError: + react_native_log_error(buffer.data()); + break; + case YGLogLevelFatal: + react_native_log_fatal(buffer.data()); + break; + case YGLogLevelWarn: + react_native_log_warn(buffer.data()); + break; + case YGLogLevelInfo: + case YGLogLevelDebug: + case YGLogLevelVerbose: + default: + react_native_log_info(buffer.data()); + } + + return size_s; +} + thread_local LayoutContext threadLocalLayoutContext; ShadowNodeTraits YogaLayoutableShadowNode::BaseTraits() { @@ -36,7 +71,7 @@ YogaLayoutableShadowNode::YogaLayoutableShadowNode( ShadowNodeFamily::Shared const &family, ShadowNodeTraits traits) : LayoutableShadowNode(fragment, family, traits), - yogaConfig_(nullptr), + yogaConfig_(FabricDefaultYogaLog), yogaNode_(&initializeYogaConfig(yogaConfig_)) { yogaNode_.setContext(this); @@ -62,7 +97,7 @@ YogaLayoutableShadowNode::YogaLayoutableShadowNode( ShadowNode const &sourceShadowNode, ShadowNodeFragment const &fragment) : LayoutableShadowNode(sourceShadowNode, fragment), - yogaConfig_(nullptr), + yogaConfig_(FabricDefaultYogaLog), yogaNode_( static_cast(sourceShadowNode) .yogaNode_, @@ -412,7 +447,6 @@ void YogaLayoutableShadowNode::layoutTree( { SystraceSection s("YogaLayoutableShadowNode::YGNodeCalculateLayout"); - YGNodeCalculateLayout(&yogaNode_, ownerWidth, ownerHeight, direction); } @@ -572,28 +606,12 @@ YGSize YogaLayoutableShadowNode::yogaNodeMeasureCallbackConnector( yogaFloatFromFloat(size.width), yogaFloatFromFloat(size.height)}; } -#ifdef RN_DEBUG_YOGA_LOGGER -static int YogaLog( - const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args) { - int result = vsnprintf(NULL, 0, format, args); - std::vector buffer(1 + result); - vsnprintf(buffer.data(), buffer.size(), format, args); - LOG(ERROR) << "RNYogaLogger " << buffer.data(); - return result; -} -#endif - YGConfig &YogaLayoutableShadowNode::initializeYogaConfig(YGConfig &config) { config.setCloneNodeCallback( YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector); config.useLegacyStretchBehaviour = true; #ifdef RN_DEBUG_YOGA_LOGGER config.printTree = true; - config.setLogger(&YogaLog); #endif return config; } diff --git a/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h b/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h index 7fd6edf4f80a70..77ba8131145891 100644 --- a/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h +++ b/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h @@ -186,9 +186,6 @@ inline YogaLayoutableShadowNode const & traitCast(ShadowNode const &shadowNode) { bool castable = shadowNode.getTraits().check(ShadowNodeTraits::Trait::YogaLayoutableKind); - react_native_assert( - castable == - (dynamic_cast(&shadowNode) != nullptr)); react_native_assert(castable); (void)castable; return static_cast(shadowNode); @@ -202,9 +199,6 @@ traitCast(ShadowNode const *shadowNode) { } bool castable = shadowNode->getTraits().check( ShadowNodeTraits::Trait::YogaLayoutableKind); - react_native_assert( - castable == - (dynamic_cast(shadowNode) != nullptr)); if (!castable) { return nullptr; } diff --git a/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h b/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h index 37b8961a0ca52f..92c52527cd55da 100644 --- a/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h +++ b/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h @@ -94,6 +94,14 @@ inline void fromString(const std::string &string, AccessibilityTraits &result) { result = AccessibilityTraits::Switch; return; } + if (string == "tabbar") { + result = AccessibilityTraits::TabBar; + return; + } + if (string == "progressbar") { + result = AccessibilityTraits::UpdatesFrequently; + return; + } result = AccessibilityTraits::None; } @@ -220,5 +228,40 @@ inline void fromRawValue( } } +inline void fromRawValue( + const PropsParserContext &, + const RawValue &value, + AccessibilityValue &result) { + auto map = (better::map)value; + + auto min = map.find("min"); + if (min != map.end()) { + if (min->second.hasType()) { + result.min = (int)min->second; + } + } + + auto max = map.find("max"); + if (max != map.end()) { + if (max->second.hasType()) { + result.max = (int)max->second; + } + } + + auto now = map.find("now"); + if (now != map.end()) { + if (now->second.hasType()) { + result.now = (int)now->second; + } + } + + auto text = map.find("text"); + if (text != map.end()) { + if (text->second.hasType()) { + result.text = (std::string)text->second; + } + } +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/core/Android.mk b/ReactCommon/react/renderer/core/Android.mk index 9ae13e652c0176..32a8ddf5efe2cb 100644 --- a/ReactCommon/react/renderer/core/Android.mk +++ b/ReactCommon/react/renderer/core/Android.mk @@ -15,7 +15,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../../ -LOCAL_SHARED_LIBRARIES := libfolly_json libjsi libfolly_futures libreact_utils libreact_debug libreact_render_debug libreact_render_graphics +LOCAL_SHARED_LIBRARIES := libfolly_json libjsi libfolly_futures libreact_utils libreact_debug libreact_render_debug libreact_render_graphics libglog LOCAL_CFLAGS := \ -DLOG_TAG=\"Fabric\" diff --git a/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h b/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h index 45625c8f5ebbb4..a66f8e2573b5e4 100644 --- a/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h +++ b/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h @@ -79,10 +79,6 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { ShadowNode::Unshared cloneShadowNode( const ShadowNode &sourceShadowNode, const ShadowNodeFragment &fragment) const override { - react_native_assert( - dynamic_cast(&sourceShadowNode) && - "Provided `sourceShadowNode` has an incompatible type."); - auto shadowNode = std::make_shared(sourceShadowNode, fragment); adopt(shadowNode); @@ -92,10 +88,6 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { void appendChild( const ShadowNode::Shared &parentShadowNode, const ShadowNode::Shared &childShadowNode) const override { - react_native_assert( - dynamic_cast(parentShadowNode.get()) && - "Provided `parentShadowNode` has an incompatible type."); - auto concreteParentShadowNode = std::static_pointer_cast(parentShadowNode); auto concreteNonConstParentShadowNode = @@ -107,11 +99,6 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { const PropsParserContext &context, const SharedProps &props, const RawProps &rawProps) const override { - react_native_assert( - !props || - dynamic_cast(props.get()) && - "Provided `props` has an incompatible type."); - // Optimization: // Quite often nodes are constructed with default/empty props: the base // `props` object is `null` (there no base because it's not cloning) and the diff --git a/ReactCommon/react/renderer/core/ConcreteShadowNode.h b/ReactCommon/react/renderer/core/ConcreteShadowNode.h index d441f326a0b2c5..8ad8820f59e46a 100644 --- a/ReactCommon/react/renderer/core/ConcreteShadowNode.h +++ b/ReactCommon/react/renderer/core/ConcreteShadowNode.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include diff --git a/ReactCommon/react/renderer/core/LayoutableShadowNode.h b/ReactCommon/react/renderer/core/LayoutableShadowNode.h index 3ffb162198e70d..b816b54a2cfcad 100644 --- a/ReactCommon/react/renderer/core/LayoutableShadowNode.h +++ b/ReactCommon/react/renderer/core/LayoutableShadowNode.h @@ -170,9 +170,6 @@ inline LayoutableShadowNode const &traitCast( ShadowNode const &shadowNode) { bool castable = shadowNode.getTraits().check(ShadowNodeTraits::Trait::LayoutableKind); - react_native_assert( - castable == - (dynamic_cast(&shadowNode) != nullptr)); react_native_assert(castable); (void)castable; return static_cast(shadowNode); @@ -186,9 +183,6 @@ inline LayoutableShadowNode const *traitCast( } bool castable = shadowNode->getTraits().check(ShadowNodeTraits::Trait::LayoutableKind); - react_native_assert( - castable == - (dynamic_cast(shadowNode) != nullptr)); if (!castable) { return nullptr; } diff --git a/ReactCommon/react/renderer/core/Props.h b/ReactCommon/react/renderer/core/Props.h index 3321310b433f16..5d99a0139a1e85 100644 --- a/ReactCommon/react/renderer/core/Props.h +++ b/ReactCommon/react/renderer/core/Props.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include diff --git a/ReactCommon/react/renderer/core/PropsParserContext.h b/ReactCommon/react/renderer/core/PropsParserContext.h index 9b9d10d2dcb2fe..df4b16d70a5966 100644 --- a/ReactCommon/react/renderer/core/PropsParserContext.h +++ b/ReactCommon/react/renderer/core/PropsParserContext.h @@ -7,6 +7,7 @@ #pragma once +#include #include namespace facebook { @@ -20,8 +21,8 @@ struct PropsParserContext { PropsParserContext(const PropsParserContext &) = delete; PropsParserContext &operator=(const PropsParserContext &) = delete; - int surfaceId; // TODO: use SurfaceId type - const ContextContainer &contextContainer; + SurfaceId const surfaceId; + ContextContainer const &contextContainer; }; } // namespace react diff --git a/ReactCommon/react/renderer/core/RawPropsKey.cpp b/ReactCommon/react/renderer/core/RawPropsKey.cpp index cdaab91f7d5e20..35c8283f5e24a4 100644 --- a/ReactCommon/react/renderer/core/RawPropsKey.cpp +++ b/ReactCommon/react/renderer/core/RawPropsKey.cpp @@ -51,10 +51,18 @@ RawPropsKey::operator std::string() const noexcept { return std::string{buffer, length}; } +static bool areFieldsEqual(char const *lhs, char const *rhs) { + if (lhs == nullptr || rhs == nullptr) { + return lhs == rhs; + } + return std::string(lhs) == std::string(rhs); +} + bool operator==(RawPropsKey const &lhs, RawPropsKey const &rhs) noexcept { // Note: We check the name first. - return lhs.name == rhs.name && lhs.prefix == rhs.prefix && - lhs.suffix == rhs.suffix; + return areFieldsEqual(lhs.name, rhs.name) && + areFieldsEqual(lhs.prefix, rhs.prefix) && + areFieldsEqual(lhs.suffix, rhs.suffix); } bool operator!=(RawPropsKey const &lhs, RawPropsKey const &rhs) noexcept { diff --git a/ReactCommon/react/renderer/core/ReactPrimitives.h b/ReactCommon/react/renderer/core/ReactPrimitives.h index 4954fcfff9b2d0..28738394bf9e9d 100644 --- a/ReactCommon/react/renderer/core/ReactPrimitives.h +++ b/ReactCommon/react/renderer/core/ReactPrimitives.h @@ -8,8 +8,6 @@ #pragma once #include -#include -#include #include #include diff --git a/ReactCommon/react/renderer/core/ShadowNodeFamily.h b/ReactCommon/react/renderer/core/ShadowNodeFamily.h index 2f57666c179438..07746e35501be6 100644 --- a/ReactCommon/react/renderer/core/ShadowNodeFamily.h +++ b/ReactCommon/react/renderer/core/ShadowNodeFamily.h @@ -10,6 +10,7 @@ #include #include +#include #include #include diff --git a/ReactCommon/react/renderer/mapbuffer/BUCK b/ReactCommon/react/renderer/mapbuffer/BUCK index f3f426baff9ee9..3c946f02fa4410 100644 --- a/ReactCommon/react/renderer/mapbuffer/BUCK +++ b/ReactCommon/react/renderer/mapbuffer/BUCK @@ -40,7 +40,7 @@ rn_xplat_cxx_library( force_static = True, labels = ["supermodule:xplat/default/public.react_native.infra"], macosx_tests_override = [], - platforms = (ANDROID), + platforms = ANDROID, preprocessor_flags = [ "-DLOG_TAG=\"ReactNative\"", "-DWITH_FBSYSTRACE=1", @@ -67,7 +67,7 @@ fb_xplat_cxx_test( "-Wall", ], contacts = ["oncall+react_native@xmail.facebook.com"], - platforms = (ANDROID), + platforms = ANDROID, deps = [ "//xplat/folly:molly", "//xplat/third-party/gmock:gtest", diff --git a/ReactCommon/react/renderer/mounting/Android.mk b/ReactCommon/react/renderer/mounting/Android.mk index d8a4360c17edae..f1383e722e4e91 100644 --- a/ReactCommon/react/renderer/mounting/Android.mk +++ b/ReactCommon/react/renderer/mounting/Android.mk @@ -21,7 +21,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall LOCAL_STATIC_LIBRARIES := -LOCAL_SHARED_LIBRARIES := libbetter libyoga libfolly_futures glog libfolly_json libglog_init libreact_render_core libreact_render_debug librrc_view librrc_root libreact_utils libreact_debug libreact_render_telemetry +LOCAL_SHARED_LIBRARIES := libjsi libbetter libyoga libfolly_futures glog libfolly_json libglog_init libreact_render_core libreact_render_debug librrc_view librrc_root libreact_utils libreact_debug libreact_render_telemetry include $(BUILD_SHARED_LIBRARY) diff --git a/ReactCommon/react/renderer/runtimescheduler/Android.mk b/ReactCommon/react/renderer/runtimescheduler/Android.mk index 2e81b329eab5e3..010cced3849e6b 100644 --- a/ReactCommon/react/renderer/runtimescheduler/Android.mk +++ b/ReactCommon/react/renderer/runtimescheduler/Android.mk @@ -15,7 +15,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../../ -LOCAL_SHARED_LIBRARIES := libruntimeexecutor libreact_render_core libreact_debug +LOCAL_SHARED_LIBRARIES := libruntimeexecutor libreact_render_core libreact_debug libjsi LOCAL_CFLAGS := \ -DLOG_TAG=\"Fabric\" diff --git a/ReactCommon/react/renderer/runtimescheduler/BUCK b/ReactCommon/react/renderer/runtimescheduler/BUCK index 7cdf02a7637560..83037289820edb 100644 --- a/ReactCommon/react/renderer/runtimescheduler/BUCK +++ b/ReactCommon/react/renderer/runtimescheduler/BUCK @@ -50,7 +50,6 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ - react_native_xplat_target("react/renderer/core:core"), react_native_xplat_target("runtimeexecutor:runtimeexecutor"), react_native_xplat_target("react/renderer/debug:debug"), react_native_xplat_target("better:better"), diff --git a/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp b/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp index d1550bc85b1acc..fd47ab43033f5d 100644 --- a/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp +++ b/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp @@ -7,7 +7,8 @@ #include "RuntimeScheduler.h" -namespace facebook::react { +namespace facebook { +namespace react { #pragma mark - Public @@ -113,4 +114,5 @@ void RuntimeScheduler::startWorkLoop(jsi::Runtime &runtime) const { isPerformingWork_ = false; } -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h b/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h index b5dad38ae2ad0b..5d18a7d9ea8a85 100644 --- a/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h +++ b/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h @@ -14,7 +14,8 @@ #include #include -namespace facebook::react { +namespace facebook { +namespace react { class RuntimeScheduler final { public: @@ -100,4 +101,5 @@ class RuntimeScheduler final { mutable bool isPerformingWork_{false}; }; -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp b/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp index 05a3d3395a4c8a..92525118e282d8 100644 --- a/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp +++ b/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp @@ -10,11 +10,11 @@ #include "primitives.h" #include -#include #include #include -namespace facebook::react { +namespace facebook { +namespace react { std::shared_ptr RuntimeSchedulerBinding::createAndInstallIfNeeded( @@ -167,4 +167,5 @@ jsi::Value RuntimeSchedulerBinding::get( return jsi::Value::undefined(); } -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h b/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h index cc4544d6a8f17b..27c1ad9f31dff5 100644 --- a/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h +++ b/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h @@ -10,7 +10,8 @@ #include #include -namespace facebook::react { +namespace facebook { +namespace react { /* * Exposes RuntimeScheduler to JavaScript realm. @@ -39,4 +40,5 @@ class RuntimeSchedulerBinding : public jsi::HostObject { std::shared_ptr runtimeScheduler_; }; -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerClock.h b/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerClock.h index 25e8b327db8f89..51652ee0a070d3 100644 --- a/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerClock.h +++ b/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerClock.h @@ -9,7 +9,8 @@ #include -namespace facebook::react { +namespace facebook { +namespace react { /* * Represents a monotonic clock suitable for measuring intervals. @@ -19,4 +20,5 @@ using RuntimeSchedulerClock = std::chrono::steady_clock; using RuntimeSchedulerTimePoint = RuntimeSchedulerClock::time_point; using RuntimeSchedulerDuration = RuntimeSchedulerClock::duration; -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h b/ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h index 4b5a1b7eab2f4e..329fe252aa3860 100644 --- a/ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h +++ b/ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h @@ -8,10 +8,10 @@ #pragma once #include -#include #include -namespace facebook::react { +namespace facebook { +namespace react { enum class SchedulerPriority : int { ImmediatePriority = 1, @@ -61,4 +61,5 @@ static inline std::chrono::milliseconds timeoutForSchedulerPriority( } } -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/Task.cpp b/ReactCommon/react/renderer/runtimescheduler/Task.cpp index b44d9719a10d3d..bd87944afa37ab 100644 --- a/ReactCommon/react/renderer/runtimescheduler/Task.cpp +++ b/ReactCommon/react/renderer/runtimescheduler/Task.cpp @@ -7,7 +7,8 @@ #include "RuntimeScheduler.h" -namespace facebook::react { +namespace facebook { +namespace react { Task::Task( SchedulerPriority priority, @@ -32,4 +33,5 @@ jsi::Value Task::execute(jsi::Runtime &runtime) { return result; } -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/Task.h b/ReactCommon/react/renderer/runtimescheduler/Task.h index 74c387636e78d2..87676d5db737b9 100644 --- a/ReactCommon/react/renderer/runtimescheduler/Task.h +++ b/ReactCommon/react/renderer/runtimescheduler/Task.h @@ -12,7 +12,8 @@ #include #include -namespace facebook::react { +namespace facebook { +namespace react { class RuntimeScheduler; class TaskPriorityComparer; @@ -43,4 +44,5 @@ class TaskPriorityComparer { } }; -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/runtimescheduler/primitives.h b/ReactCommon/react/renderer/runtimescheduler/primitives.h index 76794941452ee1..2283b4cad27104 100644 --- a/ReactCommon/react/renderer/runtimescheduler/primitives.h +++ b/ReactCommon/react/renderer/runtimescheduler/primitives.h @@ -11,7 +11,8 @@ #include #include -namespace facebook::react { +namespace facebook { +namespace react { struct TaskWrapper : public jsi::HostObject { TaskWrapper(std::shared_ptr const &task) : task(task) {} @@ -36,4 +37,5 @@ inline static std::shared_ptr taskFromValue( return value.getObject(runtime).getHostObject(runtime)->task; } -} // namespace facebook::react +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/scheduler/SurfaceHandler.h b/ReactCommon/react/renderer/scheduler/SurfaceHandler.h index a606167c370960..c0ae0e60bdc797 100644 --- a/ReactCommon/react/renderer/scheduler/SurfaceHandler.h +++ b/ReactCommon/react/renderer/scheduler/SurfaceHandler.h @@ -34,7 +34,7 @@ class UIManager; * ensure the logical consistency of some methods (e.g. calling `stop` for * non-running surface will crash). */ -class SurfaceHandler final { +class SurfaceHandler { public: /* * Represents a status of the `SurfaceHandler` instance. @@ -62,7 +62,7 @@ class SurfaceHandler final { * Can be constructed anytime with a `moduleName` and a `surfaceId`. */ SurfaceHandler(std::string const &moduleName, SurfaceId surfaceId) noexcept; - ~SurfaceHandler() noexcept; + virtual ~SurfaceHandler() noexcept; /* * Movable-only. @@ -95,10 +95,10 @@ class SurfaceHandler final { void stop() const noexcept; /* - * Sets (and gets) the runnnig mode. + * Sets (and gets) the running mode. * The running mode can be changed anytime (even for `Unregistered` surface). */ - void setDisplayMode(DisplayMode displayMode) const noexcept; + virtual void setDisplayMode(DisplayMode displayMode) const noexcept; DisplayMode getDisplayMode() const noexcept; #pragma mark - Accessors diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.h b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.h index 373e78daac3292..3a8ff540741bbb 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.h +++ b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.h @@ -35,6 +35,8 @@ NSAttributedString *RCTNSAttributedStringFromAttributedStringBox( facebook::react::AttributedStringBox RCTAttributedStringBoxFromNSAttributedString( NSAttributedString *nsAttributedString); +NSString *RCTNSStringFromStringApplyingTextTransform(NSString *string, facebook::react::TextTransform textTransform); + @interface RCTWeakEventEmitterWrapper : NSObject @property (nonatomic, assign) facebook::react::SharedEventEmitter eventEmitter; @end diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm index 496ae69979b4a9..7e63b2df90b3c8 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm +++ b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm @@ -288,6 +288,9 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex case AccessibilityRole::Tab: attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("tab"); break; + case AccessibilityRole::TabBar: + attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("tabbar"); + break; case AccessibilityRole::Tablist: attributes[RCTTextAttributesAccessibilityRoleAttributeName] = @("tablist"); break; @@ -332,6 +335,11 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex } else { NSString *string = [NSString stringWithCString:fragment.string.c_str() encoding:NSUTF8StringEncoding]; + if (fragment.textAttributes.textTransform.hasValue()) { + auto textTransform = fragment.textAttributes.textTransform.value(); + string = RCTNSStringFromStringApplyingTextTransform(string, textTransform); + } + nsAttributedStringFragment = [[NSMutableAttributedString alloc] initWithString:string attributes:RCTNSTextAttributesFromTextAttributes(fragment.textAttributes)]; @@ -370,3 +378,17 @@ AttributedStringBox RCTAttributedStringBoxFromNSAttributedString(NSAttributedStr { return nsAttributedString.length ? AttributedStringBox{wrapManagedObject(nsAttributedString)} : AttributedStringBox{}; } + +NSString *RCTNSStringFromStringApplyingTextTransform(NSString *string, TextTransform textTransform) +{ + switch (textTransform) { + case TextTransform::Uppercase: + return [string uppercaseString]; + case TextTransform::Lowercase: + return [string lowercaseString]; + case TextTransform::Capitalize: + return [string capitalizedString]; + default: + return string; + } +} diff --git a/ReactCommon/react/test_utils/BUCK b/ReactCommon/react/test_utils/BUCK index 52bae03fe6c520..8cd75144aaaa58 100644 --- a/ReactCommon/react/test_utils/BUCK +++ b/ReactCommon/react/test_utils/BUCK @@ -51,4 +51,7 @@ rn_xplat_cxx_library( react_native_xplat_target("better:better"), react_native_xplat_target("react/debug:debug"), ], + exported_deps = [ + "//xplat/third-party/gmock:gmock", + ], ) diff --git a/ReactCommon/react/test_utils/MockSurfaceHandler.h b/ReactCommon/react/test_utils/MockSurfaceHandler.h new file mode 100644 index 00000000000000..c6f678ce484871 --- /dev/null +++ b/ReactCommon/react/test_utils/MockSurfaceHandler.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#include + +namespace facebook { +namespace react { + +class MockSurfaceHandler : public SurfaceHandler { + public: + MockSurfaceHandler() : SurfaceHandler("moduleName", 0){}; + + MOCK_QUALIFIED_METHOD1(setDisplayMode, const noexcept, void(DisplayMode)); +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/utils/ContextContainer.h b/ReactCommon/react/utils/ContextContainer.h index f0e2613fdb9931..1431fe1af83190 100644 --- a/ReactCommon/react/utils/ContextContainer.h +++ b/ReactCommon/react/utils/ContextContainer.h @@ -45,10 +45,6 @@ class ContextContainer final { std::unique_lock lock(mutex_); instances_.insert({key, std::make_shared(instance)}); - -#ifdef REACT_NATIVE_DEBUG - typeNames_.insert({key, typeid(T).name()}); -#endif } /* @@ -59,10 +55,6 @@ class ContextContainer final { std::unique_lock lock(mutex_); instances_.erase(key); - -#ifdef REACT_NATIVE_DEBUG - typeNames_.erase(key); -#endif } /* @@ -76,11 +68,6 @@ class ContextContainer final { for (auto const &pair : contextContainer.instances_) { instances_.erase(pair.first); instances_.insert(pair); -#ifdef REACT_NATIVE_DEBUG - typeNames_.erase(pair.first); - typeNames_.insert( - {pair.first, contextContainer.typeNames_.at(pair.first)}); -#endif } } @@ -96,11 +83,6 @@ class ContextContainer final { react_native_assert( instances_.find(key) != instances_.end() && "ContextContainer doesn't have an instance for given key."); -#ifdef REACT_NATIVE_DEBUG - react_native_assert( - typeNames_.at(key) == typeid(T).name() && - "ContextContainer stores an instance of different type for given key."); -#endif return *std::static_pointer_cast(instances_.at(key)); } @@ -118,12 +100,6 @@ class ContextContainer final { return {}; } -#ifdef REACT_NATIVE_DEBUG - react_native_assert( - typeNames_.at(key) == typeid(T).name() && - "ContextContainer stores an instance of different type for given key."); -#endif - return *std::static_pointer_cast(iterator->second); } @@ -131,9 +107,6 @@ class ContextContainer final { mutable better::shared_mutex mutex_; // Protected by mutex_`. mutable better::map> instances_; -#ifdef REACT_NATIVE_DEBUG - mutable better::map typeNames_; -#endif }; } // namespace react diff --git a/flow/HermesInternalType.js b/flow/HermesInternalType.js new file mode 100644 index 00000000000000..c9d11b1d0f56cb --- /dev/null +++ b/flow/HermesInternalType.js @@ -0,0 +1,114 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +// Declarations for functionality exposed by the Hermes VM. +// +// For backwards-compatibility, code that uses such functionality must also +// check explicitly at run-time whether the object(s) and method(s) exist, and +// fail safely if not. + +/** + * HermesInternalType is an object containing functions used to interact with + * the VM in a way that is not standardized by the JS spec. + * There are limited guarantees about these functions, and they should not be + * widely used. Consult with the Hermes team before using any of these. + * There may be other visible properties on this object; however, those are + * only exposed for testing purposes: do not use them. + */ +declare type $HermesInternalType = { + // All members are optional because they may not exist when OTA'd to older + // VMs. + + +getNumGCs?: () => number, + +getGCTime?: () => number, + +getNativeCallTime?: () => number, + +getNativeCallCount?: () => number, + +getGCCPUTime?: () => number, + + /** + * Hermes can embed an "epilogue" to the bytecode file with arbitrary bytes. + * At most one epilogue will exist per bytecode module (which can be + * different than a JS module). + * Calling this function will return all such epilogues and convert the + * bytes to numbers in the range of 0-255. + */ + +getEpilogues?: () => Array>, + + /** + * Query the VM for various statistics about performance. + * There are no guarantees about what keys exist in it, but they can be + * printed for informational purposes. + * @return An object that maps strings to various types of performance + * statistics. + */ + +getInstrumentedStats?: () => {[string]: number | string, ...}, + + /** + * Query the VM for any sort of runtime properties that it wants to report. + * There are no guarantees about what keys exist in it, but they can be + * printed for informational purposes. + * @return An object that maps strings to various types of runtime properties. + */ + +getRuntimeProperties?: () => { + 'OSS Release Version': string, + Build: string, + [string]: mixed, + }, + + /** + * Tell Hermes that at this point the surface has transitioned from TTI to + * post-TTI. The VM can change some of its internal behavior to optimize for + * post-TTI scenarios. + * This can be called several times but will have no effect after the first + * call. + */ + +ttiReached?: () => void, + + /** + * Tell Hermes that at this point the surface has transitioned from TTRC to + * post-TTRC. The VM can change some of its internal behavior to optimize for + * post-TTRC scenarios. + * This can be called several times but will have no effect after the first + * call. + */ + +ttrcReached?: () => void, + + /** + * Query the VM to see whether or not it enabled Promise. + */ + +hasPromise?: () => boolean, + + /** + * Enable promise rejection tracking with the given options. + * The API mirrored the `promise` npm package, therefore it's typed same as + * the `enable` function of module `promise/setimmediate/rejection-tracking` + * declared in ./flow-typed/npm/promise_v8.x.x.js. + */ + +enablePromiseRejectionTracker?: ( + options: ?{ + whitelist?: ?Array, + allRejections?: ?boolean, + onUnhandled?: ?(number, mixed) => void, + onHandled?: ?(number, mixed) => void, + }, + ) => void, + + /** + * Query the VM to see whether or not it use the engine Job queue. + */ + +useEngineQueue?: () => boolean, + + /** + * Enqueue a JavaScript callback function as a Job into the engine Job queue. + */ + +enqueueJob?: >( + jobCallback: (...args: TArguments) => mixed, + ) => void, +}; diff --git a/flow/global.js b/flow/global.js index 8d7b7ee01c952f..b2e76fe8d23271 100644 --- a/flow/global.js +++ b/flow/global.js @@ -16,6 +16,53 @@ * writeability (`+`) when defining types. */ declare var global: { + // setUpGlobals + +window: typeof global, + +self: typeof global, + + // setXHR + +XMLHttpRequest: typeof XMLHttpRequest, + +FormData: typeof FormData, + +fetch: typeof fetch, + +Headers: typeof Headers, + +Request: typeof Request, + +Response: typeof Response, + +WebSocket: typeof WebSocket, + +Blob: typeof Blob, + +File: typeof File, + +FileReader: typeof FileReader, + +URL: typeof URL, + +URLSearchParams: typeof URLSearchParams, + +AbortController: typeof AbortController, + +AbortSignal: typeof AbortSignal, + + // setUpAlert + +alert: typeof alert, + + // setUpTimers + +clearInterval: typeof clearInterval, + +clearTimeout: typeof clearTimeout, + +setInterval: typeof setInterval, + +setTimeout: typeof setTimeout, + +requestAnimationFrame: typeof requestAnimationFrame, + +cancelAnimationFrame: typeof cancelAnimationFrame, + +requestIdleCallback: typeof requestIdleCallback, + +cancelIdleCallback: typeof cancelIdleCallback, + +setTimeout: typeof setTimeout, + // TODO(T97509743): use `typeof` when the next Flow release is available. + +queueMicrotask: >( + jobCallback: (...args: TArguments) => mixed, + ) => void, + + +console: typeof console, + + // JavaScript environments specific + +HermesInternal: ?$HermesInternalType, + + // Internal-specific + +__DEV__?: boolean, + +RN$Bridgeless?: boolean, + // Undeclared properties are implicitly `any`. [string | symbol]: any, }; diff --git a/gradle.properties b/gradle.properties index e785ec12c912ef..223dcfb79c24c1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,4 +6,4 @@ org.gradle.parallel=true ANDROID_NDK_VERSION=21.4.7075529 android.useAndroidX=true -kotlin_version=1.4.21 +kotlin_version=1.4.32 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7665b0fa93ae75..af7be50b1015cb 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/index.js b/index.js index 545554b3b39ab0..7ce52d8a460371 100644 --- a/index.js +++ b/index.js @@ -55,7 +55,6 @@ import typeof AppState from './Libraries/AppState/AppState'; import typeof AsyncStorage from './Libraries/Storage/AsyncStorage'; import typeof BackHandler from './Libraries/Utilities/BackHandler'; import typeof Clipboard from './Libraries/Components/Clipboard/Clipboard'; -import typeof DatePickerAndroid from './Libraries/Components/DatePickerAndroid/DatePickerAndroid'; import typeof DeviceInfo from './Libraries/Utilities/DeviceInfo'; import typeof DevSettings from './Libraries/Utilities/DevSettings'; import typeof Dimensions from './Libraries/Utilities/Dimensions'; @@ -297,15 +296,6 @@ module.exports = { ); return require('./Libraries/Components/Clipboard/Clipboard'); }, - get DatePickerAndroid(): DatePickerAndroid { - warnOnce( - 'DatePickerAndroid-merged', - 'DatePickerAndroid has been merged with DatePickerIOS and will be removed in a future release. ' + - "It can now be installed and imported from '@react-native-community/datetimepicker' instead of 'react-native'. " + - 'See https://github.com/react-native-datetimepicker/datetimepicker', - ); - return require('./Libraries/Components/DatePickerAndroid/DatePickerAndroid'); - }, get DeviceInfo(): DeviceInfo { return require('./Libraries/Utilities/DeviceInfo'); }, @@ -717,4 +707,19 @@ if (__DEV__) { ); }, }); + /* $FlowFixMe[prop-missing] This is intentional: Flow will error when + * attempting to access DatePickerAndroid. */ + /* $FlowFixMe[invalid-export] This is intentional: Flow will error when + * attempting to access DatePickerAndroid. */ + Object.defineProperty(module.exports, 'DatePickerAndroid', { + configurable: true, + get() { + invariant( + false, + 'DatePickerAndroid has been removed from React Native. ' + + "It can now be installed and imported from '@react-native-community/datetimepicker' instead of 'react-native'. " + + 'See https://github.com/react-native-datetimepicker/datetimepicker', + ); + }, + }); } diff --git a/jest/setup.js b/jest/setup.js index 9a439f81537530..912b5f78dcee58 100644 --- a/jest/setup.js +++ b/jest/setup.js @@ -23,6 +23,7 @@ global.performance = { global.Promise = jest.requireActual('promise'); global.regeneratorRuntime = jest.requireActual('regenerator-runtime/runtime'); +global.window = global; global.requestAnimationFrame = function(callback) { return setTimeout(callback, 0); diff --git a/package.json b/package.json index 1a66ec4192f189..97747f06de0c3d 100644 --- a/package.json +++ b/package.json @@ -94,13 +94,13 @@ "@react-native-community/cli-platform-android": "^6.0.0", "@react-native-community/cli-platform-ios": "^6.0.0", "@react-native/assets": "1.0.0", - "@react-native/normalize-color": "1.0.0", - "@react-native/polyfills": "1.0.0", + "@react-native/normalize-color": "2.0.0", + "@react-native/polyfills": "2.0.0", "abort-controller": "^3.0.0", "anser": "^1.4.9", "base64-js": "^1.1.2", "event-target-shim": "^5.0.1", - "hermes-engine": "~0.8.0", + "hermes-engine": "~0.9.0", "invariant": "^2.2.4", "jsc-android": "^250230.2.1", "metro-babel-register": "0.66.2", @@ -121,7 +121,7 @@ "ws": "^6.1.4" }, "devDependencies": { - "flow-bin": "^0.157.0", + "flow-bin": "^0.159.0", "react": "17.0.2" }, "detox": { diff --git a/packages/eslint-config-react-native-community/index.js b/packages/eslint-config-react-native-community/index.js index 320ef4daf2b16c..be539660939161 100644 --- a/packages/eslint-config-react-native-community/index.js +++ b/packages/eslint-config-react-native-community/index.js @@ -114,6 +114,7 @@ module.exports = { setImmediate: true, setInterval: false, setTimeout: false, + queueMicrotask: true, URL: false, URLSearchParams: false, WebSocket: true, diff --git a/packages/eslint-config-react-native-community/package.json b/packages/eslint-config-react-native-community/package.json index ef00ef62dff922..bf80d296770fcc 100644 --- a/packages/eslint-config-react-native-community/package.json +++ b/packages/eslint-config-react-native-community/package.json @@ -1,6 +1,6 @@ { "name": "@react-native-community/eslint-config", - "version": "3.0.0", + "version": "3.0.1", "description": "ESLint config for React Native", "main": "index.js", "license": "MIT", @@ -26,9 +26,11 @@ "prettier": "^2.0.2" }, "peerDependencies": { - "eslint": ">=7" + "eslint": ">=7", + "prettier": ">=2" }, "devDependencies": { - "eslint": "7.12.0" + "eslint": "7.12.0", + "prettier": "^2.3.2" } } diff --git a/packages/normalize-color/__tests__/base-test.js b/packages/normalize-color/__tests__/base-test.js deleted file mode 100644 index c37c9af5ff0a7f..00000000000000 --- a/packages/normalize-color/__tests__/base-test.js +++ /dev/null @@ -1,129 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @emails oncall+react_native - */ - -'use strict'; - -const normalizeColorBase = require('../base'); - -it('should accept only spec compliant colors', () => { - expect(normalizeColorBase('#abc')).not.toBe(null); - expect(normalizeColorBase('#abcd')).not.toBe(null); - expect(normalizeColorBase('#abcdef')).not.toBe(null); - expect(normalizeColorBase('#abcdef01')).not.toBe(null); - expect(normalizeColorBase('rgb(1,2,3)')).not.toBe(null); - expect(normalizeColorBase('rgb(1, 2, 3)')).not.toBe(null); - expect(normalizeColorBase('rgb( 1 , 2 , 3 )')).not.toBe(null); - expect(normalizeColorBase('rgb(-1, -2, -3)')).not.toBe(null); - expect(normalizeColorBase('rgba(0, 0, 0, 1)')).not.toBe(null); - expect(normalizeColorBase(0x01234567 + 0.5)).toBe(null); - expect(normalizeColorBase(-1)).toBe(null); - expect(normalizeColorBase(0xffffffff + 1)).toBe(null); -}); - -it('should temporarily accept floating point values for rgb', () => { - expect(normalizeColorBase('rgb(1.1, 2.1, 3.1)')).toBe(0x010203ff); - expect(normalizeColorBase('rgba(1.1, 2.1, 3.1, 1.0)')).toBe(0x010203ff); -}); - -it('should refuse non spec compliant colors', () => { - expect(normalizeColorBase('#00gg00')).toBe(null); - expect(normalizeColorBase('rgb(1, 2, 3,)')).toBe(null); - expect(normalizeColorBase('rgb(1, 2, 3')).toBe(null); - - // Used to be accepted by normalizeColorBase - expect(normalizeColorBase('abc')).toBe(null); - expect(normalizeColorBase(' #abc ')).toBe(null); - expect(normalizeColorBase('##abc')).toBe(null); - expect(normalizeColorBase('rgb 255 0 0')).toBe(null); - expect(normalizeColorBase('RGBA(0, 1, 2)')).toBe(null); - expect(normalizeColorBase('rgb (0, 1, 2)')).toBe(null); - expect(normalizeColorBase('hsv(0, 1, 2)')).toBe(null); - expect(normalizeColorBase({r: 10, g: 10, b: 10})).toBe(null); - expect(normalizeColorBase('hsl(1%, 2, 3)')).toBe(null); - expect(normalizeColorBase('rgb(1%, 2%, 3%)')).toBe(null); -}); - -it('should handle hex6 properly', () => { - expect(normalizeColorBase('#000000')).toBe(0x000000ff); - expect(normalizeColorBase('#ffffff')).toBe(0xffffffff); - expect(normalizeColorBase('#ff00ff')).toBe(0xff00ffff); - expect(normalizeColorBase('#abcdef')).toBe(0xabcdefff); - expect(normalizeColorBase('#012345')).toBe(0x012345ff); -}); - -it('should handle hex3 properly', () => { - expect(normalizeColorBase('#000')).toBe(0x000000ff); - expect(normalizeColorBase('#fff')).toBe(0xffffffff); - expect(normalizeColorBase('#f0f')).toBe(0xff00ffff); -}); - -it('should handle hex8 properly', () => { - expect(normalizeColorBase('#00000000')).toBe(0x00000000); - expect(normalizeColorBase('#ffffffff')).toBe(0xffffffff); - expect(normalizeColorBase('#ffff00ff')).toBe(0xffff00ff); - expect(normalizeColorBase('#abcdef01')).toBe(0xabcdef01); - expect(normalizeColorBase('#01234567')).toBe(0x01234567); -}); - -it('should handle rgb properly', () => { - expect(normalizeColorBase('rgb(0, 0, 0)')).toBe(0x000000ff); - expect(normalizeColorBase('rgb(-1, -2, -3)')).toBe(0x000000ff); - expect(normalizeColorBase('rgb(0, 0, 255)')).toBe(0x0000ffff); - expect(normalizeColorBase('rgb(100, 15, 69)')).toBe(0x640f45ff); - expect(normalizeColorBase('rgb(255, 255, 255)')).toBe(0xffffffff); - expect(normalizeColorBase('rgb(256, 256, 256)')).toBe(0xffffffff); -}); - -it('should handle rgba properly', () => { - expect(normalizeColorBase('rgba(0, 0, 0, 0.0)')).toBe(0x00000000); - expect(normalizeColorBase('rgba(0, 0, 0, 0)')).toBe(0x00000000); - expect(normalizeColorBase('rgba(0, 0, 0, -0.5)')).toBe(0x00000000); - expect(normalizeColorBase('rgba(0, 0, 0, 1.0)')).toBe(0x000000ff); - expect(normalizeColorBase('rgba(0, 0, 0, 1)')).toBe(0x000000ff); - expect(normalizeColorBase('rgba(0, 0, 0, 1.5)')).toBe(0x000000ff); - expect(normalizeColorBase('rgba(100, 15, 69, 0.5)')).toBe(0x640f4580); -}); - -it('should handle hsl properly', () => { - expect(normalizeColorBase('hsl(0, 0%, 0%)')).toBe(0x000000ff); - expect(normalizeColorBase('hsl(360, 100%, 100%)')).toBe(0xffffffff); - expect(normalizeColorBase('hsl(180, 50%, 50%)')).toBe(0x40bfbfff); - expect(normalizeColorBase('hsl(540, 50%, 50%)')).toBe(0x40bfbfff); - expect(normalizeColorBase('hsl(70, 25%, 75%)')).toBe(0xcacfafff); - expect(normalizeColorBase('hsl(70, 100%, 75%)')).toBe(0xeaff80ff); - expect(normalizeColorBase('hsl(70, 110%, 75%)')).toBe(0xeaff80ff); - expect(normalizeColorBase('hsl(70, 0%, 75%)')).toBe(0xbfbfbfff); - expect(normalizeColorBase('hsl(70, -10%, 75%)')).toBe(0xbfbfbfff); -}); - -it('should handle hsla properly', () => { - expect(normalizeColorBase('hsla(0, 0%, 0%, 0)')).toBe(0x00000000); - expect(normalizeColorBase('hsla(360, 100%, 100%, 1)')).toBe(0xffffffff); - expect(normalizeColorBase('hsla(360, 100%, 100%, 0)')).toBe(0xffffff00); - expect(normalizeColorBase('hsla(180, 50%, 50%, 0.2)')).toBe(0x40bfbf33); -}); - -it('should handle named colors properly', () => { - expect(normalizeColorBase('red')).toBe(0xff0000ff); - expect(normalizeColorBase('transparent')).toBe(0x00000000); - expect(normalizeColorBase('peachpuff')).toBe(0xffdab9ff); -}); - -it('should handle number colors properly', () => { - expect(normalizeColorBase(0x00000000)).toBe(0x00000000); - expect(normalizeColorBase(0xff0000ff)).toBe(0xff0000ff); - expect(normalizeColorBase(0xffffffff)).toBe(0xffffffff); - expect(normalizeColorBase(0x01234567)).toBe(0x01234567); -}); - -it("should return the same color when it's already normalized", () => { - const normalizedColor = normalizeColorBase('red') || 0; - expect(normalizeColorBase(normalizedColor)).toBe(normalizedColor); -}); diff --git a/packages/normalize-color/__tests__/normalizeColor-test.js b/packages/normalize-color/__tests__/normalizeColor-test.js new file mode 100644 index 00000000000000..fc68e4c95ba953 --- /dev/null +++ b/packages/normalize-color/__tests__/normalizeColor-test.js @@ -0,0 +1,131 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @emails oncall+react_native + * @flow stroct + * @format + */ + +'use strict'; + +import normalizeColor from '..'; + +it('accepts only spec compliant colors', () => { + expect(normalizeColor('#abc')).not.toBe(null); + expect(normalizeColor('#abcd')).not.toBe(null); + expect(normalizeColor('#abcdef')).not.toBe(null); + expect(normalizeColor('#abcdef01')).not.toBe(null); + expect(normalizeColor('rgb(1,2,3)')).not.toBe(null); + expect(normalizeColor('rgb(1, 2, 3)')).not.toBe(null); + expect(normalizeColor('rgb( 1 , 2 , 3 )')).not.toBe(null); + expect(normalizeColor('rgb(-1, -2, -3)')).not.toBe(null); + expect(normalizeColor('rgba(0, 0, 0, 1)')).not.toBe(null); + expect(normalizeColor(0x01234567 + 0.5)).toBe(null); + expect(normalizeColor(-1)).toBe(null); + expect(normalizeColor(0xffffffff + 1)).toBe(null); +}); + +it('temporarilys accept floating point values for rgb', () => { + expect(normalizeColor('rgb(1.1, 2.1, 3.1)')).toBe(0x010203ff); + expect(normalizeColor('rgba(1.1, 2.1, 3.1, 1.0)')).toBe(0x010203ff); +}); + +it('refuses non-spec compliant colors', () => { + expect(normalizeColor('#00gg00')).toBe(null); + expect(normalizeColor('rgb(1, 2, 3,)')).toBe(null); + expect(normalizeColor('rgb(1, 2, 3')).toBe(null); + + // Used to be accepted by normalizeColor + expect(normalizeColor('abc')).toBe(null); + expect(normalizeColor(' #abc ')).toBe(null); + expect(normalizeColor('##abc')).toBe(null); + expect(normalizeColor('rgb 255 0 0')).toBe(null); + expect(normalizeColor('RGBA(0, 1, 2)')).toBe(null); + expect(normalizeColor('rgb (0, 1, 2)')).toBe(null); + expect(normalizeColor('hsv(0, 1, 2)')).toBe(null); + // $FlowExpectedError - Intentionally malformed argument. + expect(normalizeColor({r: 10, g: 10, b: 10})).toBe(null); + expect(normalizeColor('hsl(1%, 2, 3)')).toBe(null); + expect(normalizeColor('rgb(1%, 2%, 3%)')).toBe(null); +}); + +it('handles hex6 properly', () => { + expect(normalizeColor('#000000')).toBe(0x000000ff); + expect(normalizeColor('#ffffff')).toBe(0xffffffff); + expect(normalizeColor('#ff00ff')).toBe(0xff00ffff); + expect(normalizeColor('#abcdef')).toBe(0xabcdefff); + expect(normalizeColor('#012345')).toBe(0x012345ff); +}); + +it('handles hex3 properly', () => { + expect(normalizeColor('#000')).toBe(0x000000ff); + expect(normalizeColor('#fff')).toBe(0xffffffff); + expect(normalizeColor('#f0f')).toBe(0xff00ffff); +}); + +it('handles hex8 properly', () => { + expect(normalizeColor('#00000000')).toBe(0x00000000); + expect(normalizeColor('#ffffffff')).toBe(0xffffffff); + expect(normalizeColor('#ffff00ff')).toBe(0xffff00ff); + expect(normalizeColor('#abcdef01')).toBe(0xabcdef01); + expect(normalizeColor('#01234567')).toBe(0x01234567); +}); + +it('handles rgb properly', () => { + expect(normalizeColor('rgb(0, 0, 0)')).toBe(0x000000ff); + expect(normalizeColor('rgb(-1, -2, -3)')).toBe(0x000000ff); + expect(normalizeColor('rgb(0, 0, 255)')).toBe(0x0000ffff); + expect(normalizeColor('rgb(100, 15, 69)')).toBe(0x640f45ff); + expect(normalizeColor('rgb(255, 255, 255)')).toBe(0xffffffff); + expect(normalizeColor('rgb(256, 256, 256)')).toBe(0xffffffff); +}); + +it('handles rgba properly', () => { + expect(normalizeColor('rgba(0, 0, 0, 0.0)')).toBe(0x00000000); + expect(normalizeColor('rgba(0, 0, 0, 0)')).toBe(0x00000000); + expect(normalizeColor('rgba(0, 0, 0, -0.5)')).toBe(0x00000000); + expect(normalizeColor('rgba(0, 0, 0, 1.0)')).toBe(0x000000ff); + expect(normalizeColor('rgba(0, 0, 0, 1)')).toBe(0x000000ff); + expect(normalizeColor('rgba(0, 0, 0, 1.5)')).toBe(0x000000ff); + expect(normalizeColor('rgba(100, 15, 69, 0.5)')).toBe(0x640f4580); +}); + +it('handles hsl properly', () => { + expect(normalizeColor('hsl(0, 0%, 0%)')).toBe(0x000000ff); + expect(normalizeColor('hsl(360, 100%, 100%)')).toBe(0xffffffff); + expect(normalizeColor('hsl(180, 50%, 50%)')).toBe(0x40bfbfff); + expect(normalizeColor('hsl(540, 50%, 50%)')).toBe(0x40bfbfff); + expect(normalizeColor('hsl(70, 25%, 75%)')).toBe(0xcacfafff); + expect(normalizeColor('hsl(70, 100%, 75%)')).toBe(0xeaff80ff); + expect(normalizeColor('hsl(70, 110%, 75%)')).toBe(0xeaff80ff); + expect(normalizeColor('hsl(70, 0%, 75%)')).toBe(0xbfbfbfff); + expect(normalizeColor('hsl(70, -10%, 75%)')).toBe(0xbfbfbfff); +}); + +it('handles hsla properly', () => { + expect(normalizeColor('hsla(0, 0%, 0%, 0)')).toBe(0x00000000); + expect(normalizeColor('hsla(360, 100%, 100%, 1)')).toBe(0xffffffff); + expect(normalizeColor('hsla(360, 100%, 100%, 0)')).toBe(0xffffff00); + expect(normalizeColor('hsla(180, 50%, 50%, 0.2)')).toBe(0x40bfbf33); +}); + +it('handles named colors properly', () => { + expect(normalizeColor('red')).toBe(0xff0000ff); + expect(normalizeColor('transparent')).toBe(0x00000000); + expect(normalizeColor('peachpuff')).toBe(0xffdab9ff); +}); + +it('handles number colors properly', () => { + expect(normalizeColor(0x00000000)).toBe(0x00000000); + expect(normalizeColor(0xff0000ff)).toBe(0xff0000ff); + expect(normalizeColor(0xffffffff)).toBe(0xffffffff); + expect(normalizeColor(0x01234567)).toBe(0x01234567); +}); + +it('returns the same color when it is already normalized', () => { + const normalizedColor = normalizeColor('red') || 0; + expect(normalizeColor(normalizedColor)).toBe(normalizedColor); +}); diff --git a/packages/normalize-color/base.js b/packages/normalize-color/base.js deleted file mode 100644 index b8e88e942065d0..00000000000000 --- a/packages/normalize-color/base.js +++ /dev/null @@ -1,387 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow - */ - -/* eslint no-bitwise: 0 */ - -'use strict'; - -function normalizeColorBase(color: ?string | number): null | number { - const matchers = getMatchers(); - let match; - - if (typeof color === 'number') { - if (color >>> 0 === color && color >= 0 && color <= 0xffffffff) { - return color; - } - return null; - } - - if (typeof color !== 'string') { - return null; - } - - // Ordered based on occurrences on Facebook codebase - if ((match = matchers.hex6.exec(color))) { - return parseInt(match[1] + 'ff', 16) >>> 0; - } - - if (names.hasOwnProperty(color)) { - return names[color]; - } - - if ((match = matchers.rgb.exec(color))) { - return ( - // b - ((parse255(match[1]) << 24) | // r - // $FlowFixMe[incompatible-use] - (parse255(match[2]) << 16) | // g - // $FlowFixMe[incompatible-use] - (parse255(match[3]) << 8) | - 0x000000ff) >>> // a - 0 - ); - } - - if ((match = matchers.rgba.exec(color))) { - return ( - // b - ((parse255(match[1]) << 24) | // r - // $FlowFixMe[incompatible-use] - (parse255(match[2]) << 16) | // g - // $FlowFixMe[incompatible-use] - (parse255(match[3]) << 8) | - // $FlowFixMe[incompatible-use] - parse1(match[4])) >>> // a - 0 - ); - } - - if ((match = matchers.hex3.exec(color))) { - return ( - parseInt( - match[1] + - match[1] + // r - match[2] + - match[2] + // g - match[3] + - match[3] + // b - 'ff', // a - 16, - ) >>> 0 - ); - } - - // https://drafts.csswg.org/css-color-4/#hex-notation - if ((match = matchers.hex8.exec(color))) { - return parseInt(match[1], 16) >>> 0; - } - - if ((match = matchers.hex4.exec(color))) { - return ( - parseInt( - match[1] + - match[1] + // r - match[2] + - match[2] + // g - match[3] + - match[3] + // b - match[4] + - match[4], // a - 16, - ) >>> 0 - ); - } - - if ((match = matchers.hsl.exec(color))) { - return ( - (hslToRgb( - parse360(match[1]), // h - // $FlowFixMe[incompatible-use] - parsePercentage(match[2]), // s - // $FlowFixMe[incompatible-use] - parsePercentage(match[3]), // l - ) | - 0x000000ff) >>> // a - 0 - ); - } - - if ((match = matchers.hsla.exec(color))) { - return ( - (hslToRgb( - parse360(match[1]), // h - // $FlowFixMe[incompatible-use] - parsePercentage(match[2]), // s - // $FlowFixMe[incompatible-use] - parsePercentage(match[3]), // l - ) | - // $FlowFixMe[incompatible-use] - parse1(match[4])) >>> // a - 0 - ); - } - - return null; -} - -function hue2rgb(p: number, q: number, t: number): number { - if (t < 0) { - t += 1; - } - if (t > 1) { - t -= 1; - } - if (t < 1 / 6) { - return p + (q - p) * 6 * t; - } - if (t < 1 / 2) { - return q; - } - if (t < 2 / 3) { - return p + (q - p) * (2 / 3 - t) * 6; - } - return p; -} - -function hslToRgb(h: number, s: number, l: number): number { - const q = l < 0.5 ? l * (1 + s) : l + s - l * s; - const p = 2 * l - q; - const r = hue2rgb(p, q, h + 1 / 3); - const g = hue2rgb(p, q, h); - const b = hue2rgb(p, q, h - 1 / 3); - - return ( - (Math.round(r * 255) << 24) | - (Math.round(g * 255) << 16) | - (Math.round(b * 255) << 8) - ); -} - -// var INTEGER = '[-+]?\\d+'; -const NUMBER = '[-+]?\\d*\\.?\\d+'; -const PERCENTAGE = NUMBER + '%'; - -function call(...args) { - return '\\(\\s*(' + args.join(')\\s*,\\s*(') + ')\\s*\\)'; -} - -let cachedMatchers; - -function getMatchers() { - if (cachedMatchers === undefined) { - cachedMatchers = { - rgb: new RegExp('rgb' + call(NUMBER, NUMBER, NUMBER)), - rgba: new RegExp('rgba' + call(NUMBER, NUMBER, NUMBER, NUMBER)), - hsl: new RegExp('hsl' + call(NUMBER, PERCENTAGE, PERCENTAGE)), - hsla: new RegExp('hsla' + call(NUMBER, PERCENTAGE, PERCENTAGE, NUMBER)), - hex3: /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, - hex4: /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, - hex6: /^#([0-9a-fA-F]{6})$/, - hex8: /^#([0-9a-fA-F]{8})$/, - }; - } - return cachedMatchers; -} - -function parse255(str: string): number { - const int = parseInt(str, 10); - if (int < 0) { - return 0; - } - if (int > 255) { - return 255; - } - return int; -} - -function parse360(str: string): number { - const int = parseFloat(str); - return (((int % 360) + 360) % 360) / 360; -} - -function parse1(str: string): number { - const num = parseFloat(str); - if (num < 0) { - return 0; - } - if (num > 1) { - return 255; - } - return Math.round(num * 255); -} - -function parsePercentage(str: string): number { - // parseFloat conveniently ignores the final % - const int = parseFloat(str); - if (int < 0) { - return 0; - } - if (int > 100) { - return 1; - } - return int / 100; -} - -const names = { - transparent: 0x00000000, - - // http://www.w3.org/TR/css3-color/#svg-color - aliceblue: 0xf0f8ffff, - antiquewhite: 0xfaebd7ff, - aqua: 0x00ffffff, - aquamarine: 0x7fffd4ff, - azure: 0xf0ffffff, - beige: 0xf5f5dcff, - bisque: 0xffe4c4ff, - black: 0x000000ff, - blanchedalmond: 0xffebcdff, - blue: 0x0000ffff, - blueviolet: 0x8a2be2ff, - brown: 0xa52a2aff, - burlywood: 0xdeb887ff, - burntsienna: 0xea7e5dff, - cadetblue: 0x5f9ea0ff, - chartreuse: 0x7fff00ff, - chocolate: 0xd2691eff, - coral: 0xff7f50ff, - cornflowerblue: 0x6495edff, - cornsilk: 0xfff8dcff, - crimson: 0xdc143cff, - cyan: 0x00ffffff, - darkblue: 0x00008bff, - darkcyan: 0x008b8bff, - darkgoldenrod: 0xb8860bff, - darkgray: 0xa9a9a9ff, - darkgreen: 0x006400ff, - darkgrey: 0xa9a9a9ff, - darkkhaki: 0xbdb76bff, - darkmagenta: 0x8b008bff, - darkolivegreen: 0x556b2fff, - darkorange: 0xff8c00ff, - darkorchid: 0x9932ccff, - darkred: 0x8b0000ff, - darksalmon: 0xe9967aff, - darkseagreen: 0x8fbc8fff, - darkslateblue: 0x483d8bff, - darkslategray: 0x2f4f4fff, - darkslategrey: 0x2f4f4fff, - darkturquoise: 0x00ced1ff, - darkviolet: 0x9400d3ff, - deeppink: 0xff1493ff, - deepskyblue: 0x00bfffff, - dimgray: 0x696969ff, - dimgrey: 0x696969ff, - dodgerblue: 0x1e90ffff, - firebrick: 0xb22222ff, - floralwhite: 0xfffaf0ff, - forestgreen: 0x228b22ff, - fuchsia: 0xff00ffff, - gainsboro: 0xdcdcdcff, - ghostwhite: 0xf8f8ffff, - gold: 0xffd700ff, - goldenrod: 0xdaa520ff, - gray: 0x808080ff, - green: 0x008000ff, - greenyellow: 0xadff2fff, - grey: 0x808080ff, - honeydew: 0xf0fff0ff, - hotpink: 0xff69b4ff, - indianred: 0xcd5c5cff, - indigo: 0x4b0082ff, - ivory: 0xfffff0ff, - khaki: 0xf0e68cff, - lavender: 0xe6e6faff, - lavenderblush: 0xfff0f5ff, - lawngreen: 0x7cfc00ff, - lemonchiffon: 0xfffacdff, - lightblue: 0xadd8e6ff, - lightcoral: 0xf08080ff, - lightcyan: 0xe0ffffff, - lightgoldenrodyellow: 0xfafad2ff, - lightgray: 0xd3d3d3ff, - lightgreen: 0x90ee90ff, - lightgrey: 0xd3d3d3ff, - lightpink: 0xffb6c1ff, - lightsalmon: 0xffa07aff, - lightseagreen: 0x20b2aaff, - lightskyblue: 0x87cefaff, - lightslategray: 0x778899ff, - lightslategrey: 0x778899ff, - lightsteelblue: 0xb0c4deff, - lightyellow: 0xffffe0ff, - lime: 0x00ff00ff, - limegreen: 0x32cd32ff, - linen: 0xfaf0e6ff, - magenta: 0xff00ffff, - maroon: 0x800000ff, - mediumaquamarine: 0x66cdaaff, - mediumblue: 0x0000cdff, - mediumorchid: 0xba55d3ff, - mediumpurple: 0x9370dbff, - mediumseagreen: 0x3cb371ff, - mediumslateblue: 0x7b68eeff, - mediumspringgreen: 0x00fa9aff, - mediumturquoise: 0x48d1ccff, - mediumvioletred: 0xc71585ff, - midnightblue: 0x191970ff, - mintcream: 0xf5fffaff, - mistyrose: 0xffe4e1ff, - moccasin: 0xffe4b5ff, - navajowhite: 0xffdeadff, - navy: 0x000080ff, - oldlace: 0xfdf5e6ff, - olive: 0x808000ff, - olivedrab: 0x6b8e23ff, - orange: 0xffa500ff, - orangered: 0xff4500ff, - orchid: 0xda70d6ff, - palegoldenrod: 0xeee8aaff, - palegreen: 0x98fb98ff, - paleturquoise: 0xafeeeeff, - palevioletred: 0xdb7093ff, - papayawhip: 0xffefd5ff, - peachpuff: 0xffdab9ff, - peru: 0xcd853fff, - pink: 0xffc0cbff, - plum: 0xdda0ddff, - powderblue: 0xb0e0e6ff, - purple: 0x800080ff, - rebeccapurple: 0x663399ff, - red: 0xff0000ff, - rosybrown: 0xbc8f8fff, - royalblue: 0x4169e1ff, - saddlebrown: 0x8b4513ff, - salmon: 0xfa8072ff, - sandybrown: 0xf4a460ff, - seagreen: 0x2e8b57ff, - seashell: 0xfff5eeff, - sienna: 0xa0522dff, - silver: 0xc0c0c0ff, - skyblue: 0x87ceebff, - slateblue: 0x6a5acdff, - slategray: 0x708090ff, - slategrey: 0x708090ff, - snow: 0xfffafaff, - springgreen: 0x00ff7fff, - steelblue: 0x4682b4ff, - tan: 0xd2b48cff, - teal: 0x008080ff, - thistle: 0xd8bfd8ff, - tomato: 0xff6347ff, - turquoise: 0x40e0d0ff, - violet: 0xee82eeff, - wheat: 0xf5deb3ff, - white: 0xffffffff, - whitesmoke: 0xf5f5f5ff, - yellow: 0xffff00ff, - yellowgreen: 0x9acd32ff, -}; - -module.exports = normalizeColorBase; diff --git a/packages/normalize-color/index.js b/packages/normalize-color/index.js new file mode 100644 index 00000000000000..15f50bd788f6bf --- /dev/null +++ b/packages/normalize-color/index.js @@ -0,0 +1,378 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @noflow + */ + +/* eslint no-bitwise: 0 */ + +'use strict'; + +function normalizeColor(color) { + if (typeof color === 'number') { + if (color >>> 0 === color && color >= 0 && color <= 0xffffffff) { + return color; + } + return null; + } + + if (typeof color !== 'string') { + return null; + } + + const matchers = getMatchers(); + let match; + + // Ordered based on occurrences on Facebook codebase + if ((match = matchers.hex6.exec(color))) { + return parseInt(match[1] + 'ff', 16) >>> 0; + } + + const colorFromKeyword = normalizeKeyword(color); + if (colorFromKeyword != null) { + return colorFromKeyword; + } + + if ((match = matchers.rgb.exec(color))) { + return ( + ((parse255(match[1]) << 24) | // r + (parse255(match[2]) << 16) | // g + (parse255(match[3]) << 8) | // b + 0x000000ff) >>> // a + 0 + ); + } + + if ((match = matchers.rgba.exec(color))) { + return ( + ((parse255(match[1]) << 24) | // r + (parse255(match[2]) << 16) | // g + (parse255(match[3]) << 8) | // b + parse1(match[4])) >>> // a + 0 + ); + } + + if ((match = matchers.hex3.exec(color))) { + return ( + parseInt( + match[1] + + match[1] + // r + match[2] + + match[2] + // g + match[3] + + match[3] + // b + 'ff', // a + 16, + ) >>> 0 + ); + } + + // https://drafts.csswg.org/css-color-4/#hex-notation + if ((match = matchers.hex8.exec(color))) { + return parseInt(match[1], 16) >>> 0; + } + + if ((match = matchers.hex4.exec(color))) { + return ( + parseInt( + match[1] + + match[1] + // r + match[2] + + match[2] + // g + match[3] + + match[3] + // b + match[4] + + match[4], // a + 16, + ) >>> 0 + ); + } + + if ((match = matchers.hsl.exec(color))) { + return ( + (hslToRgb( + parse360(match[1]), // h + parsePercentage(match[2]), // s + parsePercentage(match[3]), // l + ) | + 0x000000ff) >>> // a + 0 + ); + } + + if ((match = matchers.hsla.exec(color))) { + return ( + (hslToRgb( + parse360(match[1]), // h + parsePercentage(match[2]), // s + parsePercentage(match[3]), // l + ) | + parse1(match[4])) >>> // a + 0 + ); + } + + return null; +} + +function hue2rgb(p, q, t) { + if (t < 0) { + t += 1; + } + if (t > 1) { + t -= 1; + } + if (t < 1 / 6) { + return p + (q - p) * 6 * t; + } + if (t < 1 / 2) { + return q; + } + if (t < 2 / 3) { + return p + (q - p) * (2 / 3 - t) * 6; + } + return p; +} + +function hslToRgb(h, s, l) { + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = 2 * l - q; + const r = hue2rgb(p, q, h + 1 / 3); + const g = hue2rgb(p, q, h); + const b = hue2rgb(p, q, h - 1 / 3); + + return ( + (Math.round(r * 255) << 24) | + (Math.round(g * 255) << 16) | + (Math.round(b * 255) << 8) + ); +} + +const NUMBER = '[-+]?\\d*\\.?\\d+'; +const PERCENTAGE = NUMBER + '%'; + +function call(...args) { + return '\\(\\s*(' + args.join(')\\s*,\\s*(') + ')\\s*\\)'; +} + +let cachedMatchers; + +function getMatchers() { + if (cachedMatchers === undefined) { + cachedMatchers = { + rgb: new RegExp('rgb' + call(NUMBER, NUMBER, NUMBER)), + rgba: new RegExp('rgba' + call(NUMBER, NUMBER, NUMBER, NUMBER)), + hsl: new RegExp('hsl' + call(NUMBER, PERCENTAGE, PERCENTAGE)), + hsla: new RegExp('hsla' + call(NUMBER, PERCENTAGE, PERCENTAGE, NUMBER)), + hex3: /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex4: /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex6: /^#([0-9a-fA-F]{6})$/, + hex8: /^#([0-9a-fA-F]{8})$/, + }; + } + return cachedMatchers; +} + +function parse255(str) { + const int = parseInt(str, 10); + if (int < 0) { + return 0; + } + if (int > 255) { + return 255; + } + return int; +} + +function parse360(str) { + const int = parseFloat(str); + return (((int % 360) + 360) % 360) / 360; +} + +function parse1(str) { + const num = parseFloat(str); + if (num < 0) { + return 0; + } + if (num > 1) { + return 255; + } + return Math.round(num * 255); +} + +function parsePercentage(str) { + // parseFloat conveniently ignores the final % + const int = parseFloat(str); + if (int < 0) { + return 0; + } + if (int > 100) { + return 1; + } + return int / 100; +} + +function normalizeKeyword(name) { + // prettier-ignore + switch (name) { + case 'transparent': return 0x00000000; + // http://www.w3.org/TR/css3-color/#svg-color + case 'aliceblue': return 0xf0f8ffff; + case 'antiquewhite': return 0xfaebd7ff; + case 'aqua': return 0x00ffffff; + case 'aquamarine': return 0x7fffd4ff; + case 'azure': return 0xf0ffffff; + case 'beige': return 0xf5f5dcff; + case 'bisque': return 0xffe4c4ff; + case 'black': return 0x000000ff; + case 'blanchedalmond': return 0xffebcdff; + case 'blue': return 0x0000ffff; + case 'blueviolet': return 0x8a2be2ff; + case 'brown': return 0xa52a2aff; + case 'burlywood': return 0xdeb887ff; + case 'burntsienna': return 0xea7e5dff; + case 'cadetblue': return 0x5f9ea0ff; + case 'chartreuse': return 0x7fff00ff; + case 'chocolate': return 0xd2691eff; + case 'coral': return 0xff7f50ff; + case 'cornflowerblue': return 0x6495edff; + case 'cornsilk': return 0xfff8dcff; + case 'crimson': return 0xdc143cff; + case 'cyan': return 0x00ffffff; + case 'darkblue': return 0x00008bff; + case 'darkcyan': return 0x008b8bff; + case 'darkgoldenrod': return 0xb8860bff; + case 'darkgray': return 0xa9a9a9ff; + case 'darkgreen': return 0x006400ff; + case 'darkgrey': return 0xa9a9a9ff; + case 'darkkhaki': return 0xbdb76bff; + case 'darkmagenta': return 0x8b008bff; + case 'darkolivegreen': return 0x556b2fff; + case 'darkorange': return 0xff8c00ff; + case 'darkorchid': return 0x9932ccff; + case 'darkred': return 0x8b0000ff; + case 'darksalmon': return 0xe9967aff; + case 'darkseagreen': return 0x8fbc8fff; + case 'darkslateblue': return 0x483d8bff; + case 'darkslategray': return 0x2f4f4fff; + case 'darkslategrey': return 0x2f4f4fff; + case 'darkturquoise': return 0x00ced1ff; + case 'darkviolet': return 0x9400d3ff; + case 'deeppink': return 0xff1493ff; + case 'deepskyblue': return 0x00bfffff; + case 'dimgray': return 0x696969ff; + case 'dimgrey': return 0x696969ff; + case 'dodgerblue': return 0x1e90ffff; + case 'firebrick': return 0xb22222ff; + case 'floralwhite': return 0xfffaf0ff; + case 'forestgreen': return 0x228b22ff; + case 'fuchsia': return 0xff00ffff; + case 'gainsboro': return 0xdcdcdcff; + case 'ghostwhite': return 0xf8f8ffff; + case 'gold': return 0xffd700ff; + case 'goldenrod': return 0xdaa520ff; + case 'gray': return 0x808080ff; + case 'green': return 0x008000ff; + case 'greenyellow': return 0xadff2fff; + case 'grey': return 0x808080ff; + case 'honeydew': return 0xf0fff0ff; + case 'hotpink': return 0xff69b4ff; + case 'indianred': return 0xcd5c5cff; + case 'indigo': return 0x4b0082ff; + case 'ivory': return 0xfffff0ff; + case 'khaki': return 0xf0e68cff; + case 'lavender': return 0xe6e6faff; + case 'lavenderblush': return 0xfff0f5ff; + case 'lawngreen': return 0x7cfc00ff; + case 'lemonchiffon': return 0xfffacdff; + case 'lightblue': return 0xadd8e6ff; + case 'lightcoral': return 0xf08080ff; + case 'lightcyan': return 0xe0ffffff; + case 'lightgoldenrodyellow': return 0xfafad2ff; + case 'lightgray': return 0xd3d3d3ff; + case 'lightgreen': return 0x90ee90ff; + case 'lightgrey': return 0xd3d3d3ff; + case 'lightpink': return 0xffb6c1ff; + case 'lightsalmon': return 0xffa07aff; + case 'lightseagreen': return 0x20b2aaff; + case 'lightskyblue': return 0x87cefaff; + case 'lightslategray': return 0x778899ff; + case 'lightslategrey': return 0x778899ff; + case 'lightsteelblue': return 0xb0c4deff; + case 'lightyellow': return 0xffffe0ff; + case 'lime': return 0x00ff00ff; + case 'limegreen': return 0x32cd32ff; + case 'linen': return 0xfaf0e6ff; + case 'magenta': return 0xff00ffff; + case 'maroon': return 0x800000ff; + case 'mediumaquamarine': return 0x66cdaaff; + case 'mediumblue': return 0x0000cdff; + case 'mediumorchid': return 0xba55d3ff; + case 'mediumpurple': return 0x9370dbff; + case 'mediumseagreen': return 0x3cb371ff; + case 'mediumslateblue': return 0x7b68eeff; + case 'mediumspringgreen': return 0x00fa9aff; + case 'mediumturquoise': return 0x48d1ccff; + case 'mediumvioletred': return 0xc71585ff; + case 'midnightblue': return 0x191970ff; + case 'mintcream': return 0xf5fffaff; + case 'mistyrose': return 0xffe4e1ff; + case 'moccasin': return 0xffe4b5ff; + case 'navajowhite': return 0xffdeadff; + case 'navy': return 0x000080ff; + case 'oldlace': return 0xfdf5e6ff; + case 'olive': return 0x808000ff; + case 'olivedrab': return 0x6b8e23ff; + case 'orange': return 0xffa500ff; + case 'orangered': return 0xff4500ff; + case 'orchid': return 0xda70d6ff; + case 'palegoldenrod': return 0xeee8aaff; + case 'palegreen': return 0x98fb98ff; + case 'paleturquoise': return 0xafeeeeff; + case 'palevioletred': return 0xdb7093ff; + case 'papayawhip': return 0xffefd5ff; + case 'peachpuff': return 0xffdab9ff; + case 'peru': return 0xcd853fff; + case 'pink': return 0xffc0cbff; + case 'plum': return 0xdda0ddff; + case 'powderblue': return 0xb0e0e6ff; + case 'purple': return 0x800080ff; + case 'rebeccapurple': return 0x663399ff; + case 'red': return 0xff0000ff; + case 'rosybrown': return 0xbc8f8fff; + case 'royalblue': return 0x4169e1ff; + case 'saddlebrown': return 0x8b4513ff; + case 'salmon': return 0xfa8072ff; + case 'sandybrown': return 0xf4a460ff; + case 'seagreen': return 0x2e8b57ff; + case 'seashell': return 0xfff5eeff; + case 'sienna': return 0xa0522dff; + case 'silver': return 0xc0c0c0ff; + case 'skyblue': return 0x87ceebff; + case 'slateblue': return 0x6a5acdff; + case 'slategray': return 0x708090ff; + case 'slategrey': return 0x708090ff; + case 'snow': return 0xfffafaff; + case 'springgreen': return 0x00ff7fff; + case 'steelblue': return 0x4682b4ff; + case 'tan': return 0xd2b48cff; + case 'teal': return 0x008080ff; + case 'thistle': return 0xd8bfd8ff; + case 'tomato': return 0xff6347ff; + case 'turquoise': return 0x40e0d0ff; + case 'violet': return 0xee82eeff; + case 'wheat': return 0xf5deb3ff; + case 'white': return 0xffffffff; + case 'whitesmoke': return 0xf5f5f5ff; + case 'yellow': return 0xffff00ff; + case 'yellowgreen': return 0x9acd32ff; + } + return null; +} + +module.exports = normalizeColor; diff --git a/packages/normalize-color/index.js.flow b/packages/normalize-color/index.js.flow new file mode 100644 index 00000000000000..c6199ff6deeb26 --- /dev/null +++ b/packages/normalize-color/index.js.flow @@ -0,0 +1,10 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + */ + +declare module.exports: (color: ?(string | number)) => null | number; diff --git a/packages/normalize-color/package.json b/packages/normalize-color/package.json index 9ff2e8a0733d9f..7ecb89c6b89cbe 100644 --- a/packages/normalize-color/package.json +++ b/packages/normalize-color/package.json @@ -1,7 +1,7 @@ { "name": "@react-native/normalize-color", - "version": "1.0.0", - "description": "Color normalization code for React Native.", + "version": "2.0.0", + "description": "Color normalization for React Native.", "repository": { "type": "git", "url": "git@github.com:facebook/react-native.git", diff --git a/packages/polyfills/package.json b/packages/polyfills/package.json index 6f00c64c7fca72..58a2b3a70494eb 100644 --- a/packages/polyfills/package.json +++ b/packages/polyfills/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/polyfills", - "version": "1.0.0", + "version": "2.0.0", "description": "Polyfills for React Native.", "repository": { "type": "git", diff --git a/packages/react-native-codegen/BUCK b/packages/react-native-codegen/BUCK index bc1c5d4528d109..c0c516ad621c6b 100644 --- a/packages/react-native-codegen/BUCK +++ b/packages/react-native-codegen/BUCK @@ -85,7 +85,7 @@ rn_xplat_cxx_library( "-std=c++17", "-Wall", ], - platforms = (APPLE), + platforms = APPLE, preprocessor_flags = [ "-DLOG_TAG=\"ReactNative\"", "-DWITH_FBSYSTRACE=1", diff --git a/packages/react-native-codegen/android/gradle/wrapper/gradle-wrapper.properties b/packages/react-native-codegen/android/gradle/wrapper/gradle-wrapper.properties index 7665b0fa93ae75..af7be50b1015cb 100644 --- a/packages/react-native-codegen/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/react-native-codegen/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js index 4298a8d16d378b..a893fea829f116 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js @@ -80,9 +80,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/${libraryName} -LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug - -LOCAL_STATIC_LIBRARIES := libjsi +LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug LOCAL_CFLAGS := \\ -DLOG_TAG=\\"ReactNative\\" diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap index 6bb1b8b9a9485f..5f68533849b14c 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap @@ -52,9 +52,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/complex_objects -LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug - -LOCAL_STATIC_LIBRARIES := libjsi +LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug LOCAL_CFLAGS := \\\\ -DLOG_TAG=\\\\\\"ReactNative\\\\\\" @@ -118,9 +116,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/empty_native_modules -LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug - -LOCAL_STATIC_LIBRARIES := libjsi +LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug LOCAL_CFLAGS := \\\\ -DLOG_TAG=\\\\\\"ReactNative\\\\\\" @@ -184,9 +180,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/native_modules_with_type_aliases -LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug - -LOCAL_STATIC_LIBRARIES := libjsi +LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug LOCAL_CFLAGS := \\\\ -DLOG_TAG=\\\\\\"ReactNative\\\\\\" @@ -258,9 +252,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/real_module_example -LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug - -LOCAL_STATIC_LIBRARIES := libjsi +LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug LOCAL_CFLAGS := \\\\ -DLOG_TAG=\\\\\\"ReactNative\\\\\\" @@ -324,9 +316,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/simple_native_modules -LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug - -LOCAL_STATIC_LIBRARIES := libjsi +LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug LOCAL_CFLAGS := \\\\ -DLOG_TAG=\\\\\\"ReactNative\\\\\\" @@ -398,9 +388,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/two_modules_different_files -LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug - -LOCAL_STATIC_LIBRARIES := libjsi +LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug LOCAL_CFLAGS := \\\\ -DLOG_TAG=\\\\\\"ReactNative\\\\\\" diff --git a/packages/react-native-gradle-plugin/build.gradle.kts b/packages/react-native-gradle-plugin/build.gradle.kts index 75a8bb54da3fb9..4dc4d68f7b2d26 100644 --- a/packages/react-native-gradle-plugin/build.gradle.kts +++ b/packages/react-native-gradle-plugin/build.gradle.kts @@ -6,8 +6,8 @@ */ plugins { - `java-gradle-plugin` - `kotlin-dsl` + kotlin("jvm") version "1.4.21" + id("java-gradle-plugin") } repositories { @@ -25,5 +25,6 @@ gradlePlugin { } dependencies { + implementation(gradleApi()) implementation("com.android.tools.build:gradle:4.2.2") } diff --git a/packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.jar b/packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..7454180f2ae8848c63b8b4dea2cb829da983f2fa GIT binary patch literal 59536 zcma&NbC71ylI~qywr$(CZQJHswz}-9F59+k+g;UV+cs{`J?GrGXYR~=-ydruB3JCa zB64N^cILAcWk5iofq)<(fq;O7{th4@;QxID0)qN`mJ?GIqLY#rX8-|G{5M0pdVW5^ zzXk$-2kQTAC?_N@B`&6-N-rmVFE=$QD?>*=4<|!MJu@}isLc4AW#{m2if&A5T5g&~ ziuMQeS*U5sL6J698wOd)K@oK@1{peP5&Esut<#VH^u)gp`9H4)`uE!2$>RTctN+^u z=ASkePDZA-X8)rp%D;p*~P?*a_=*Kwc<^>QSH|^<0>o37lt^+Mj1;4YvJ(JR-Y+?%Nu}JAYj5 z_Qc5%Ao#F?q32i?ZaN2OSNhWL;2oDEw_({7ZbgUjna!Fqn3NzLM@-EWFPZVmc>(fZ z0&bF-Ch#p9C{YJT9Rcr3+Y_uR^At1^BxZ#eo>$PLJF3=;t_$2|t+_6gg5(j{TmjYU zK12c&lE?Eh+2u2&6Gf*IdKS&6?rYbSEKBN!rv{YCm|Rt=UlPcW9j`0o6{66#y5t9C zruFA2iKd=H%jHf%ypOkxLnO8#H}#Zt{8p!oi6)7#NqoF({t6|J^?1e*oxqng9Q2Cc zg%5Vu!em)}Yuj?kaP!D?b?(C*w!1;>R=j90+RTkyEXz+9CufZ$C^umX^+4|JYaO<5 zmIM3#dv`DGM;@F6;(t!WngZSYzHx?9&$xEF70D1BvfVj<%+b#)vz)2iLCrTeYzUcL z(OBnNoG6Le%M+@2oo)&jdOg=iCszzv59e zDRCeaX8l1hC=8LbBt|k5?CXgep=3r9BXx1uR8!p%Z|0+4Xro=xi0G!e{c4U~1j6!) zH6adq0}#l{%*1U(Cb%4AJ}VLWKBPi0MoKFaQH6x?^hQ!6em@993xdtS%_dmevzeNl z(o?YlOI=jl(`L9^ z0O+H9k$_@`6L13eTT8ci-V0ljDMD|0ifUw|Q-Hep$xYj0hTO@0%IS^TD4b4n6EKDG z??uM;MEx`s98KYN(K0>c!C3HZdZ{+_53DO%9k5W%pr6yJusQAv_;IA}925Y%;+!tY z%2k!YQmLLOr{rF~!s<3-WEUs)`ix_mSU|cNRBIWxOox_Yb7Z=~Q45ZNe*u|m^|)d* zog=i>`=bTe!|;8F+#H>EjIMcgWcG2ORD`w0WD;YZAy5#s{65~qfI6o$+Ty&-hyMyJ z3Ra~t>R!p=5ZpxA;QkDAoPi4sYOP6>LT+}{xp}tk+<0k^CKCFdNYG(Es>p0gqD)jP zWOeX5G;9(m@?GOG7g;e74i_|SmE?`B2i;sLYwRWKLy0RLW!Hx`=!LH3&k=FuCsM=9M4|GqzA)anEHfxkB z?2iK-u(DC_T1};KaUT@3nP~LEcENT^UgPvp!QC@Dw&PVAhaEYrPey{nkcn(ro|r7XUz z%#(=$7D8uP_uU-oPHhd>>^adbCSQetgSG`e$U|7mr!`|bU0aHl_cmL)na-5x1#OsVE#m*+k84Y^+UMeSAa zbrVZHU=mFwXEaGHtXQq`2ZtjfS!B2H{5A<3(nb-6ARVV8kEmOkx6D2x7~-6hl;*-*}2Xz;J#a8Wn;_B5=m zl3dY;%krf?i-Ok^Pal-}4F`{F@TYPTwTEhxpZK5WCpfD^UmM_iYPe}wpE!Djai6_{ z*pGO=WB47#Xjb7!n2Ma)s^yeR*1rTxp`Mt4sfA+`HwZf%!7ZqGosPkw69`Ix5Ku6G z@Pa;pjzV&dn{M=QDx89t?p?d9gna*}jBly*#1!6}5K<*xDPJ{wv4& zM$17DFd~L*Te3A%yD;Dp9UGWTjRxAvMu!j^Tbc}2v~q^59d4bz zvu#!IJCy(BcWTc`;v$9tH;J%oiSJ_i7s;2`JXZF+qd4C)vY!hyCtl)sJIC{ebI*0> z@x>;EzyBv>AI-~{D6l6{ST=em*U( z(r$nuXY-#CCi^8Z2#v#UXOt`dbYN1z5jzNF2 z411?w)whZrfA20;nl&C1Gi+gk<`JSm+{|*2o<< zqM#@z_D`Cn|0H^9$|Tah)0M_X4c37|KQ*PmoT@%xHc3L1ZY6(p(sNXHa&49Frzto& zR`c~ClHpE~4Z=uKa5S(-?M8EJ$zt0&fJk~p$M#fGN1-y$7!37hld`Uw>Urri(DxLa;=#rK0g4J)pXMC zxzraOVw1+kNWpi#P=6(qxf`zSdUC?D$i`8ZI@F>k6k zz21?d+dw7b&i*>Kv5L(LH-?J%@WnqT7j#qZ9B>|Zl+=> z^U-pV@1y_ptHo4hl^cPRWewbLQ#g6XYQ@EkiP z;(=SU!yhjHp%1&MsU`FV1Z_#K1&(|5n(7IHbx&gG28HNT)*~-BQi372@|->2Aw5It z0CBpUcMA*QvsPy)#lr!lIdCi@1k4V2m!NH)%Px(vu-r(Q)HYc!p zJ^$|)j^E#q#QOgcb^pd74^JUi7fUmMiNP_o*lvx*q%_odv49Dsv$NV;6J z9GOXKomA{2Pb{w}&+yHtH?IkJJu~}Z?{Uk++2mB8zyvh*xhHKE``99>y#TdD z&(MH^^JHf;g(Tbb^&8P*;_i*2&fS$7${3WJtV7K&&(MBV2~)2KB3%cWg#1!VE~k#C z!;A;?p$s{ihyojEZz+$I1)L}&G~ml=udD9qh>Tu(ylv)?YcJT3ihapi!zgPtWb*CP zlLLJSRCj-^w?@;RU9aL2zDZY1`I3d<&OMuW=c3$o0#STpv_p3b9Wtbql>w^bBi~u4 z3D8KyF?YE?=HcKk!xcp@Cigvzy=lnFgc^9c%(^F22BWYNAYRSho@~*~S)4%AhEttv zvq>7X!!EWKG?mOd9&n>vvH1p4VzE?HCuxT-u+F&mnsfDI^}*-d00-KAauEaXqg3k@ zy#)MGX!X;&3&0s}F3q40ZmVM$(H3CLfpdL?hB6nVqMxX)q=1b}o_PG%r~hZ4gUfSp zOH4qlEOW4OMUc)_m)fMR_rl^pCfXc{$fQbI*E&mV77}kRF z&{<06AJyJ!e863o-V>FA1a9Eemx6>^F$~9ppt()ZbPGfg_NdRXBWoZnDy2;#ODgf! zgl?iOcF7Meo|{AF>KDwTgYrJLb$L2%%BEtO>T$C?|9bAB&}s;gI?lY#^tttY&hfr# zKhC+&b-rpg_?~uVK%S@mQleU#_xCsvIPK*<`E0fHE1&!J7!xD#IB|SSPW6-PyuqGn3^M^Rz%WT{e?OI^svARX&SAdU77V(C~ zM$H{Kg59op{<|8ry9ecfP%=kFm(-!W&?U0@<%z*+!*<e0XesMxRFu9QnGqun6R_%T+B%&9Dtk?*d$Q zb~>84jEAPi@&F@3wAa^Lzc(AJz5gsfZ7J53;@D<;Klpl?sK&u@gie`~vTsbOE~Cd4 z%kr56mI|#b(Jk&;p6plVwmNB0H@0SmgdmjIn5Ne@)}7Vty(yb2t3ev@22AE^s!KaN zyQ>j+F3w=wnx7w@FVCRe+`vUH)3gW%_72fxzqX!S&!dchdkRiHbXW1FMrIIBwjsai8`CB2r4mAbwp%rrO>3B$Zw;9=%fXI9B{d(UzVap7u z6piC-FQ)>}VOEuPpuqznpY`hN4dGa_1Xz9rVg(;H$5Te^F0dDv*gz9JS<|>>U0J^# z6)(4ICh+N_Q`Ft0hF|3fSHs*?a=XC;e`sJaU9&d>X4l?1W=|fr!5ShD|nv$GK;j46@BV6+{oRbWfqOBRb!ir88XD*SbC(LF}I1h#6@dvK%Toe%@ zhDyG$93H8Eu&gCYddP58iF3oQH*zLbNI;rN@E{T9%A8!=v#JLxKyUe}e}BJpB{~uN zqgxRgo0*-@-iaHPV8bTOH(rS(huwK1Xg0u+e!`(Irzu@Bld&s5&bWgVc@m7;JgELd zimVs`>vQ}B_1(2#rv#N9O`fJpVfPc7V2nv34PC);Dzbb;p!6pqHzvy?2pD&1NE)?A zt(t-ucqy@wn9`^MN5apa7K|L=9>ISC>xoc#>{@e}m#YAAa1*8-RUMKwbm|;5p>T`Z zNf*ph@tnF{gmDa3uwwN(g=`Rh)4!&)^oOy@VJaK4lMT&5#YbXkl`q?<*XtsqD z9PRK6bqb)fJw0g-^a@nu`^?71k|m3RPRjt;pIkCo1{*pdqbVs-Yl>4E>3fZx3Sv44grW=*qdSoiZ9?X0wWyO4`yDHh2E!9I!ZFi zVL8|VtW38}BOJHW(Ax#KL_KQzarbuE{(%TA)AY)@tY4%A%P%SqIU~8~-Lp3qY;U-} z`h_Gel7;K1h}7$_5ZZT0&%$Lxxr-<89V&&TCsu}LL#!xpQ1O31jaa{U34~^le*Y%L za?7$>Jk^k^pS^_M&cDs}NgXlR>16AHkSK-4TRaJSh#h&p!-!vQY%f+bmn6x`4fwTp z$727L^y`~!exvmE^W&#@uY!NxJi`g!i#(++!)?iJ(1)2Wk;RN zFK&O4eTkP$Xn~4bB|q8y(btx$R#D`O@epi4ofcETrx!IM(kWNEe42Qh(8*KqfP(c0 zouBl6>Fc_zM+V;F3znbo{x#%!?mH3`_ANJ?y7ppxS@glg#S9^MXu|FM&ynpz3o&Qh z2ujAHLF3($pH}0jXQsa#?t--TnF1P73b?4`KeJ9^qK-USHE)4!IYgMn-7z|=ALF5SNGkrtPG@Y~niUQV2?g$vzJN3nZ{7;HZHzWAeQ;5P|@Tl3YHpyznGG4-f4=XflwSJY+58-+wf?~Fg@1p1wkzuu-RF3j2JX37SQUc? zQ4v%`V8z9ZVZVqS8h|@@RpD?n0W<=hk=3Cf8R?d^9YK&e9ZybFY%jdnA)PeHvtBe- zhMLD+SSteHBq*q)d6x{)s1UrsO!byyLS$58WK;sqip$Mk{l)Y(_6hEIBsIjCr5t>( z7CdKUrJTrW%qZ#1z^n*Lb8#VdfzPw~OIL76aC+Rhr<~;4Tl!sw?Rj6hXj4XWa#6Tp z@)kJ~qOV)^Rh*-?aG>ic2*NlC2M7&LUzc9RT6WM%Cpe78`iAowe!>(T0jo&ivn8-7 zs{Qa@cGy$rE-3AY0V(l8wjI^uB8Lchj@?L}fYal^>T9z;8juH@?rG&g-t+R2dVDBe zq!K%{e-rT5jX19`(bP23LUN4+_zh2KD~EAYzhpEO3MUG8@}uBHH@4J zd`>_(K4q&>*k82(dDuC)X6JuPrBBubOg7qZ{?x!r@{%0);*`h*^F|%o?&1wX?Wr4b z1~&cy#PUuES{C#xJ84!z<1tp9sfrR(i%Tu^jnXy;4`Xk;AQCdFC@?V%|; zySdC7qS|uQRcH}EFZH%mMB~7gi}a0utE}ZE_}8PQH8f;H%PN41Cb9R%w5Oi5el^fd z$n{3SqLCnrF##x?4sa^r!O$7NX!}&}V;0ZGQ&K&i%6$3C_dR%I7%gdQ;KT6YZiQrW zk%q<74oVBV>@}CvJ4Wj!d^?#Zwq(b$E1ze4$99DuNg?6t9H}k_|D7KWD7i0-g*EO7 z;5{hSIYE4DMOK3H%|f5Edx+S0VI0Yw!tsaRS2&Il2)ea^8R5TG72BrJue|f_{2UHa z@w;^c|K3da#$TB0P3;MPlF7RuQeXT$ zS<<|C0OF(k)>fr&wOB=gP8!Qm>F41u;3esv7_0l%QHt(~+n; zf!G6%hp;Gfa9L9=AceiZs~tK+Tf*Wof=4!u{nIO90jH@iS0l+#%8=~%ASzFv7zqSB^?!@N7)kp0t&tCGLmzXSRMRyxCmCYUD2!B`? zhs$4%KO~m=VFk3Buv9osha{v+mAEq=ik3RdK@;WWTV_g&-$U4IM{1IhGX{pAu%Z&H zFfwCpUsX%RKg);B@7OUzZ{Hn{q6Vv!3#8fAg!P$IEx<0vAx;GU%}0{VIsmFBPq_mb zpe^BChDK>sc-WLKl<6 zwbW|e&d&dv9Wu0goueyu>(JyPx1mz0v4E?cJjFuKF71Q1)AL8jHO$!fYT3(;U3Re* zPPOe%*O+@JYt1bW`!W_1!mN&=w3G9ru1XsmwfS~BJ))PhD(+_J_^N6j)sx5VwbWK| zwRyC?W<`pOCY)b#AS?rluxuuGf-AJ=D!M36l{ua?@SJ5>e!IBr3CXIxWw5xUZ@Xrw z_R@%?{>d%Ld4p}nEsiA@v*nc6Ah!MUs?GA7e5Q5lPpp0@`%5xY$C;{%rz24$;vR#* zBP=a{)K#CwIY%p} zXVdxTQ^HS@O&~eIftU+Qt^~(DGxrdi3k}DdT^I7Iy5SMOp$QuD8s;+93YQ!OY{eB24%xY7ml@|M7I(Nb@K_-?F;2?et|CKkuZK_>+>Lvg!>JE~wN`BI|_h6$qi!P)+K-1Hh(1;a`os z55)4Q{oJiA(lQM#;w#Ta%T0jDNXIPM_bgESMCDEg6rM33anEr}=|Fn6)|jBP6Y}u{ zv9@%7*#RI9;fv;Yii5CI+KrRdr0DKh=L>)eO4q$1zmcSmglsV`*N(x=&Wx`*v!!hn6X-l0 zP_m;X??O(skcj+oS$cIdKhfT%ABAzz3w^la-Ucw?yBPEC+=Pe_vU8nd-HV5YX6X8r zZih&j^eLU=%*;VzhUyoLF;#8QsEfmByk+Y~caBqSvQaaWf2a{JKB9B>V&r?l^rXaC z8)6AdR@Qy_BxQrE2Fk?ewD!SwLuMj@&d_n5RZFf7=>O>hzVE*seW3U?_p|R^CfoY`?|#x9)-*yjv#lo&zP=uI`M?J zbzC<^3x7GfXA4{FZ72{PE*-mNHyy59Q;kYG@BB~NhTd6pm2Oj=_ zizmD?MKVRkT^KmXuhsk?eRQllPo2Ubk=uCKiZ&u3Xjj~<(!M94c)Tez@9M1Gfs5JV z->@II)CDJOXTtPrQudNjE}Eltbjq>6KiwAwqvAKd^|g!exgLG3;wP+#mZYr`cy3#39e653d=jrR-ulW|h#ddHu(m9mFoW~2yE zz5?dB%6vF}+`-&-W8vy^OCxm3_{02royjvmwjlp+eQDzFVEUiyO#gLv%QdDSI#3W* z?3!lL8clTaNo-DVJw@ynq?q!%6hTQi35&^>P85G$TqNt78%9_sSJt2RThO|JzM$iL zg|wjxdMC2|Icc5rX*qPL(coL!u>-xxz-rFiC!6hD1IR%|HSRsV3>Kq~&vJ=s3M5y8SG%YBQ|{^l#LGlg!D?E>2yR*eV%9m$_J6VGQ~AIh&P$_aFbh zULr0Z$QE!QpkP=aAeR4ny<#3Fwyw@rZf4?Ewq`;mCVv}xaz+3ni+}a=k~P+yaWt^L z@w67!DqVf7D%7XtXX5xBW;Co|HvQ8WR1k?r2cZD%U;2$bsM%u8{JUJ5Z0k= zZJARv^vFkmWx15CB=rb=D4${+#DVqy5$C%bf`!T0+epLJLnh1jwCdb*zuCL}eEFvE z{rO1%gxg>1!W(I!owu*mJZ0@6FM(?C+d*CeceZRW_4id*D9p5nzMY&{mWqrJomjIZ z97ZNnZ3_%Hx8dn;H>p8m7F#^2;T%yZ3H;a&N7tm=Lvs&lgJLW{V1@h&6Vy~!+Ffbb zv(n3+v)_D$}dqd!2>Y2B)#<+o}LH#%ogGi2-?xRIH)1!SD)u-L65B&bsJTC=LiaF+YOCif2dUX6uAA|#+vNR z>U+KQekVGon)Yi<93(d!(yw1h3&X0N(PxN2{%vn}cnV?rYw z$N^}_o!XUB!mckL`yO1rnUaI4wrOeQ(+&k?2mi47hzxSD`N#-byqd1IhEoh!PGq>t z_MRy{5B0eKY>;Ao3z$RUU7U+i?iX^&r739F)itdrTpAi-NN0=?^m%?{A9Ly2pVv>Lqs6moTP?T2-AHqFD-o_ znVr|7OAS#AEH}h8SRPQ@NGG47dO}l=t07__+iK8nHw^(AHx&Wb<%jPc$$jl6_p(b$ z)!pi(0fQodCHfM)KMEMUR&UID>}m^(!{C^U7sBDOA)$VThRCI0_+2=( zV8mMq0R(#z;C|7$m>$>`tX+T|xGt(+Y48@ZYu#z;0pCgYgmMVbFb!$?%yhZqP_nhn zy4<#3P1oQ#2b51NU1mGnHP$cf0j-YOgAA}A$QoL6JVLcmExs(kU{4z;PBHJD%_=0F z>+sQV`mzijSIT7xn%PiDKHOujX;n|M&qr1T@rOxTdxtZ!&u&3HHFLYD5$RLQ=heur zb>+AFokUVQeJy-#LP*^)spt{mb@Mqe=A~-4p0b+Bt|pZ+@CY+%x}9f}izU5;4&QFE zO1bhg&A4uC1)Zb67kuowWY4xbo&J=%yoXlFB)&$d*-}kjBu|w!^zbD1YPc0-#XTJr z)pm2RDy%J3jlqSMq|o%xGS$bPwn4AqitC6&e?pqWcjWPt{3I{>CBy;hg0Umh#c;hU3RhCUX=8aR>rmd` z7Orw(5tcM{|-^J?ZAA9KP|)X6n9$-kvr#j5YDecTM6n z&07(nD^qb8hpF0B^z^pQ*%5ePYkv&FabrlI61ntiVp!!C8y^}|<2xgAd#FY=8b*y( zuQOuvy2`Ii^`VBNJB&R!0{hABYX55ooCAJSSevl4RPqEGb)iy_0H}v@vFwFzD%>#I>)3PsouQ+_Kkbqy*kKdHdfkN7NBcq%V{x^fSxgXpg7$bF& zj!6AQbDY(1u#1_A#1UO9AxiZaCVN2F0wGXdY*g@x$ByvUA?ePdide0dmr#}udE%K| z3*k}Vv2Ew2u1FXBaVA6aerI36R&rzEZeDDCl5!t0J=ug6kuNZzH>3i_VN`%BsaVB3 zQYw|Xub_SGf{)F{$ZX5`Jc!X!;eybjP+o$I{Z^Hsj@D=E{MnnL+TbC@HEU2DjG{3-LDGIbq()U87x4eS;JXnSh;lRlJ z>EL3D>wHt-+wTjQF$fGyDO$>d+(fq@bPpLBS~xA~R=3JPbS{tzN(u~m#Po!?H;IYv zE;?8%^vle|%#oux(Lj!YzBKv+Fd}*Ur-dCBoX*t{KeNM*n~ZPYJ4NNKkI^MFbz9!v z4(Bvm*Kc!-$%VFEewYJKz-CQN{`2}KX4*CeJEs+Q(!kI%hN1!1P6iOq?ovz}X0IOi z)YfWpwW@pK08^69#wSyCZkX9?uZD?C^@rw^Y?gLS_xmFKkooyx$*^5#cPqntNTtSG zlP>XLMj2!VF^0k#ole7`-c~*~+_T5ls?x4)ah(j8vo_ zwb%S8qoaZqY0-$ZI+ViIA_1~~rAH7K_+yFS{0rT@eQtTAdz#8E5VpwnW!zJ_^{Utv zlW5Iar3V5t&H4D6A=>?mq;G92;1cg9a2sf;gY9pJDVKn$DYdQlvfXq}zz8#LyPGq@ z+`YUMD;^-6w&r-82JL7mA8&M~Pj@aK!m{0+^v<|t%APYf7`}jGEhdYLqsHW-Le9TL z_hZZ1gbrz7$f9^fAzVIP30^KIz!!#+DRLL+qMszvI_BpOSmjtl$hh;&UeM{ER@INV zcI}VbiVTPoN|iSna@=7XkP&-4#06C};8ajbxJ4Gcq8(vWv4*&X8bM^T$mBk75Q92j z1v&%a;OSKc8EIrodmIiw$lOES2hzGDcjjB`kEDfJe{r}yE6`eZL zEB`9u>Cl0IsQ+t}`-cx}{6jqcANucqIB>Qmga_&<+80E2Q|VHHQ$YlAt{6`Qu`HA3 z03s0-sSlwbvgi&_R8s={6<~M^pGvBNjKOa>tWenzS8s zR>L7R5aZ=mSU{f?ib4Grx$AeFvtO5N|D>9#)ChH#Fny2maHWHOf2G=#<9Myot#+4u zWVa6d^Vseq_0=#AYS(-m$Lp;*8nC_6jXIjEM`omUmtH@QDs3|G)i4j*#_?#UYVZvJ z?YjT-?!4Q{BNun;dKBWLEw2C-VeAz`%?A>p;)PL}TAZn5j~HK>v1W&anteARlE+~+ zj>c(F;?qO3pXBb|#OZdQnm<4xWmn~;DR5SDMxt0UK_F^&eD|KZ=O;tO3vy4@4h^;2 zUL~-z`-P1aOe?|ZC1BgVsL)2^J-&vIFI%q@40w0{jjEfeVl)i9(~bt2z#2Vm)p`V_ z1;6$Ae7=YXk#=Qkd24Y23t&GvRxaOoad~NbJ+6pxqzJ>FY#Td7@`N5xp!n(c!=RE& z&<<@^a$_Ys8jqz4|5Nk#FY$~|FPC0`*a5HH!|Gssa9=~66&xG9)|=pOOJ2KE5|YrR zw!w6K2aC=J$t?L-;}5hn6mHd%hC;p8P|Dgh6D>hGnXPgi;6r+eA=?f72y9(Cf_ho{ zH6#)uD&R=73^$$NE;5piWX2bzR67fQ)`b=85o0eOLGI4c-Tb@-KNi2pz=Ke@SDcPn za$AxXib84`!Sf;Z3B@TSo`Dz7GM5Kf(@PR>Ghzi=BBxK8wRp>YQoXm+iL>H*Jo9M3 z6w&E?BC8AFTFT&Tv8zf+m9<&S&%dIaZ)Aoqkak_$r-2{$d~0g2oLETx9Y`eOAf14QXEQw3tJne;fdzl@wV#TFXSLXM2428F-Q}t+n2g%vPRMUzYPvzQ9f# zu(liiJem9P*?0%V@RwA7F53r~|I!Ty)<*AsMX3J{_4&}{6pT%Tpw>)^|DJ)>gpS~1rNEh z0$D?uO8mG?H;2BwM5a*26^7YO$XjUm40XmBsb63MoR;bJh63J;OngS5sSI+o2HA;W zdZV#8pDpC9Oez&L8loZO)MClRz!_!WD&QRtQxnazhT%Vj6Wl4G11nUk8*vSeVab@N#oJ}`KyJv+8Mo@T1-pqZ1t|?cnaVOd;1(h9 z!$DrN=jcGsVYE-0-n?oCJ^4x)F}E;UaD-LZUIzcD?W^ficqJWM%QLy6QikrM1aKZC zi{?;oKwq^Vsr|&`i{jIphA8S6G4)$KGvpULjH%9u(Dq247;R#l&I0{IhcC|oBF*Al zvLo7Xte=C{aIt*otJD}BUq)|_pdR>{zBMT< z(^1RpZv*l*m*OV^8>9&asGBo8h*_4q*)-eCv*|Pq=XNGrZE)^(SF7^{QE_~4VDB(o zVcPA_!G+2CAtLbl+`=Q~9iW`4ZRLku!uB?;tWqVjB0lEOf}2RD7dJ=BExy=<9wkb- z9&7{XFA%n#JsHYN8t5d~=T~5DcW4$B%3M+nNvC2`0!#@sckqlzo5;hhGi(D9=*A4` z5ynobawSPRtWn&CDLEs3Xf`(8^zDP=NdF~F^s&={l7(aw&EG}KWpMjtmz7j_VLO;@ zM2NVLDxZ@GIv7*gzl1 zjq78tv*8#WSY`}Su0&C;2F$Ze(q>F(@Wm^Gw!)(j;dk9Ad{STaxn)IV9FZhm*n+U} zi;4y*3v%A`_c7a__DJ8D1b@dl0Std3F||4Wtvi)fCcBRh!X9$1x!_VzUh>*S5s!oq z;qd{J_r79EL2wIeiGAqFstWtkfIJpjVh%zFo*=55B9Zq~y0=^iqHWfQl@O!Ak;(o*m!pZqe9 z%U2oDOhR)BvW8&F70L;2TpkzIutIvNQaTjjs5V#8mV4!NQ}zN=i`i@WI1z0eN-iCS z;vL-Wxc^Vc_qK<5RPh(}*8dLT{~GzE{w2o$2kMFaEl&q zP{V=>&3kW7tWaK-Exy{~`v4J0U#OZBk{a9{&)&QG18L@6=bsZ1zC_d{{pKZ-Ey>I> z;8H0t4bwyQqgu4hmO`3|4K{R*5>qnQ&gOfdy?z`XD%e5+pTDzUt3`k^u~SaL&XMe= z9*h#kT(*Q9jO#w2Hd|Mr-%DV8i_1{J1MU~XJ3!WUplhXDYBpJH><0OU`**nIvPIof z|N8@I=wA)sf45SAvx||f?Z5uB$kz1qL3Ky_{%RPdP5iN-D2!p5scq}buuC00C@jom zhfGKm3|f?Z0iQ|K$Z~!`8{nmAS1r+fp6r#YDOS8V*;K&Gs7Lc&f^$RC66O|)28oh`NHy&vq zJh+hAw8+ybTB0@VhWN^0iiTnLsCWbS_y`^gs!LX!Lw{yE``!UVzrV24tP8o;I6-65 z1MUiHw^{bB15tmrVT*7-#sj6cs~z`wk52YQJ*TG{SE;KTm#Hf#a~|<(|ImHH17nNM z`Ub{+J3dMD!)mzC8b(2tZtokKW5pAwHa?NFiso~# z1*iaNh4lQ4TS)|@G)H4dZV@l*Vd;Rw;-;odDhW2&lJ%m@jz+Panv7LQm~2Js6rOW3 z0_&2cW^b^MYW3)@o;neZ<{B4c#m48dAl$GCc=$>ErDe|?y@z`$uq3xd(%aAsX)D%l z>y*SQ%My`yDP*zof|3@_w#cjaW_YW4BdA;#Glg1RQcJGY*CJ9`H{@|D+*e~*457kd z73p<%fB^PV!Ybw@)Dr%(ZJbX}xmCStCYv#K3O32ej{$9IzM^I{6FJ8!(=azt7RWf4 z7ib0UOPqN40X!wOnFOoddd8`!_IN~9O)#HRTyjfc#&MCZ zZAMzOVB=;qwt8gV?{Y2?b=iSZG~RF~uyx18K)IDFLl})G1v@$(s{O4@RJ%OTJyF+Cpcx4jmy|F3euCnMK!P2WTDu5j z{{gD$=M*pH!GGzL%P)V2*ROm>!$Y=z|D`!_yY6e7SU$~a5q8?hZGgaYqaiLnkK%?0 zs#oI%;zOxF@g*@(V4p!$7dS1rOr6GVs6uYCTt2h)eB4?(&w8{#o)s#%gN@BBosRUe z)@P@8_Zm89pr~)b>e{tbPC~&_MR--iB{=)y;INU5#)@Gix-YpgP<-c2Ms{9zuCX|3 z!p(?VaXww&(w&uBHzoT%!A2=3HAP>SDxcljrego7rY|%hxy3XlODWffO_%g|l+7Y_ zqV(xbu)s4lV=l7M;f>vJl{`6qBm>#ZeMA}kXb97Z)?R97EkoI?x6Lp0yu1Z>PS?2{ z0QQ(8D)|lc9CO3B~e(pQM&5(1y&y=e>C^X$`)_&XuaI!IgDTVqt31wX#n+@!a_A0ZQkA zCJ2@M_4Gb5MfCrm5UPggeyh)8 zO9?`B0J#rkoCx(R0I!ko_2?iO@|oRf1;3r+i)w-2&j?=;NVIdPFsB)`|IC0zk6r9c zRrkfxWsiJ(#8QndNJj@{@WP2Ackr|r1VxV{7S&rSU(^)-M8gV>@UzOLXu9K<{6e{T zXJ6b92r$!|lwjhmgqkdswY&}c)KW4A)-ac%sU;2^fvq7gfUW4Bw$b!i@duy1CAxSn z(pyh$^Z=&O-q<{bZUP+$U}=*#M9uVc>CQVgDs4swy5&8RAHZ~$)hrTF4W zPsSa~qYv_0mJnF89RnnJTH`3}w4?~epFl=D(35$ zWa07ON$`OMBOHgCmfO(9RFc<)?$x)N}Jd2A(<*Ll7+4jrRt9w zwGxExUXd9VB#I|DwfxvJ;HZ8Q{37^wDhaZ%O!oO(HpcqfLH%#a#!~;Jl7F5>EX_=8 z{()l2NqPz>La3qJR;_v+wlK>GsHl;uRA8%j`A|yH@k5r%55S9{*Cp%uw6t`qc1!*T za2OeqtQj7sAp#Q~=5Fs&aCR9v>5V+s&RdNvo&H~6FJOjvaj--2sYYBvMq;55%z8^o z|BJDA4vzfow#DO#ZQHh;Oq_{r+qP{R9ox2TOgwQiv7Ow!zjN+A@BN;0tA2lUb#+zO z(^b89eV)D7UVE+h{mcNc6&GtpOqDn_?VAQ)Vob$hlFwW%xh>D#wml{t&Ofmm_d_+; zKDxzdr}`n2Rw`DtyIjrG)eD0vut$}dJAZ0AohZ+ZQdWXn_Z@dI_y=7t3q8x#pDI-K z2VVc&EGq445Rq-j0=U=Zx`oBaBjsefY;%)Co>J3v4l8V(T8H?49_@;K6q#r~Wwppc z4XW0(4k}cP=5ex>-Xt3oATZ~bBWKv)aw|I|Lx=9C1s~&b77idz({&q3T(Y(KbWO?+ zmcZ6?WeUsGk6>km*~234YC+2e6Zxdl~<_g2J|IE`GH%n<%PRv-50; zH{tnVts*S5*_RxFT9eM0z-pksIb^drUq4>QSww=u;UFCv2AhOuXE*V4z?MM`|ABOC4P;OfhS(M{1|c%QZ=!%rQTDFx`+}?Kdx$&FU?Y<$x;j7z=(;Lyz+?EE>ov!8vvMtSzG!nMie zsBa9t8as#2nH}n8xzN%W%U$#MHNXmDUVr@GX{?(=yI=4vks|V)!-W5jHsU|h_&+kY zS_8^kd3jlYqOoiI`ZqBVY!(UfnAGny!FowZWY_@YR0z!nG7m{{)4OS$q&YDyw6vC$ zm4!$h>*|!2LbMbxS+VM6&DIrL*X4DeMO!@#EzMVfr)e4Tagn~AQHIU8?e61TuhcKD zr!F4(kEebk(Wdk-?4oXM(rJwanS>Jc%<>R(siF+>+5*CqJLecP_we33iTFTXr6W^G z7M?LPC-qFHK;E!fxCP)`8rkxZyFk{EV;G-|kwf4b$c1k0atD?85+|4V%YATWMG|?K zLyLrws36p%Qz6{}>7b>)$pe>mR+=IWuGrX{3ZPZXF3plvuv5Huax86}KX*lbPVr}L z{C#lDjdDeHr~?l|)Vp_}T|%$qF&q#U;ClHEPVuS+Jg~NjC1RP=17=aQKGOcJ6B3mp z8?4*-fAD~}sX*=E6!}^u8)+m2j<&FSW%pYr_d|p_{28DZ#Cz0@NF=gC-o$MY?8Ca8 zr5Y8DSR^*urS~rhpX^05r30Ik#2>*dIOGxRm0#0YX@YQ%Mg5b6dXlS!4{7O_kdaW8PFSdj1=ryI-=5$fiieGK{LZ+SX(1b=MNL!q#lN zv98?fqqTUH8r8C7v(cx#BQ5P9W>- zmW93;eH6T`vuJ~rqtIBg%A6>q>gnWb3X!r0wh_q;211+Om&?nvYzL1hhtjB zK_7G3!n7PL>d!kj){HQE zE8(%J%dWLh1_k%gVXTZt zEdT09XSKAx27Ncaq|(vzL3gm83q>6CAw<$fTnMU05*xAe&rDfCiu`u^1)CD<>sx0i z*hr^N_TeN89G(nunZoLBf^81#pmM}>JgD@Nn1l*lN#a=B=9pN%tmvYFjFIoKe_(GF z-26x{(KXdfsQL7Uv6UtDuYwV`;8V3w>oT_I<`Ccz3QqK9tYT5ZQzbop{=I=!pMOCb zCU68`n?^DT%^&m>A%+-~#lvF!7`L7a{z<3JqIlk1$<||_J}vW1U9Y&eX<}l8##6i( zZcTT@2`9(Mecptm@{3A_Y(X`w9K0EwtPq~O!16bq{7c0f7#(3wn-^)h zxV&M~iiF!{-6A@>o;$RzQ5A50kxXYj!tcgme=Qjrbje~;5X2xryU;vH|6bE(8z^<7 zQ>BG7_c*JG8~K7Oe68i#0~C$v?-t@~@r3t2inUnLT(c=URpA9kA8uq9PKU(Ps(LVH zqgcqW>Gm?6oV#AldDPKVRcEyQIdTT`Qa1j~vS{<;SwyTdr&3*t?J)y=M7q*CzucZ&B0M=joT zBbj@*SY;o2^_h*>R0e({!QHF0=)0hOj^B^d*m>SnRrwq>MolNSgl^~r8GR#mDWGYEIJA8B<|{{j?-7p zVnV$zancW3&JVDtVpIlI|5djKq0(w$KxEFzEiiL=h5Jw~4Le23@s(mYyXWL9SX6Ot zmb)sZaly_P%BeX_9 zw&{yBef8tFm+%=--m*J|o~+Xg3N+$IH)t)=fqD+|fEk4AAZ&!wcN5=mi~Vvo^i`}> z#_3ahR}Ju)(Px7kev#JGcSwPXJ2id9%Qd2A#Uc@t8~egZ8;iC{e! z%=CGJOD1}j!HW_sgbi_8suYnn4#Ou}%9u)dXd3huFIb!ytlX>Denx@pCS-Nj$`VO&j@(z!kKSP0hE4;YIP#w9ta=3DO$7f*x zc9M4&NK%IrVmZAe=r@skWD`AEWH=g+r|*13Ss$+{c_R!b?>?UaGXlw*8qDmY#xlR= z<0XFbs2t?8i^G~m?b|!Hal^ZjRjt<@a? z%({Gn14b4-a|#uY^=@iiKH+k?~~wTj5K1A&hU z2^9-HTC)7zpoWK|$JXaBL6C z#qSNYtY>65T@Zs&-0cHeu|RX(Pxz6vTITdzJdYippF zC-EB+n4}#lM7`2Ry~SO>FxhKboIAF#Z{1wqxaCb{#yEFhLuX;Rx(Lz%T`Xo1+a2M}7D+@wol2)OJs$TwtRNJ={( zD@#zTUEE}#Fz#&(EoD|SV#bayvr&E0vzmb%H?o~46|FAcx?r4$N z&67W3mdip-T1RIxwSm_&(%U|+WvtGBj*}t69XVd&ebn>KOuL(7Y8cV?THd-(+9>G7*Nt%T zcH;`p={`SOjaf7hNd(=37Lz3-51;58JffzIPgGs_7xIOsB5p2t&@v1mKS$2D$*GQ6 zM(IR*j4{nri7NMK9xlDy-hJW6sW|ZiDRaFiayj%;(%51DN!ZCCCXz+0Vm#};70nOx zJ#yA0P3p^1DED;jGdPbQWo0WATN=&2(QybbVdhd=Vq*liDk`c7iZ?*AKEYC#SY&2g z&Q(Ci)MJ{mEat$ZdSwTjf6h~roanYh2?9j$CF@4hjj_f35kTKuGHvIs9}Re@iKMxS-OI*`0S z6s)fOtz}O$T?PLFVSeOjSO26$@u`e<>k(OSP!&YstH3ANh>)mzmKGNOwOawq-MPXe zy4xbeUAl6tamnx))-`Gi2uV5>9n(73yS)Ukma4*7fI8PaEwa)dWHs6QA6>$}7?(L8 ztN8M}?{Tf!Zu22J5?2@95&rQ|F7=FK-hihT-vDp!5JCcWrVogEnp;CHenAZ)+E+K5 z$Cffk5sNwD_?4+ymgcHR(5xgt20Z8M`2*;MzOM#>yhk{r3x=EyM226wb&!+j`W<%* zSc&|`8!>dn9D@!pYow~(DsY_naSx7(Z4i>cu#hA5=;IuI88}7f%)bRkuY2B;+9Uep zpXcvFWkJ!mQai63BgNXG26$5kyhZ2&*3Q_tk)Ii4M>@p~_~q_cE!|^A;_MHB;7s#9 zKzMzK{lIxotjc};k67^Xsl-gS!^*m*m6kn|sbdun`O?dUkJ{0cmI0-_2y=lTAfn*Y zKg*A-2sJq)CCJgY0LF-VQvl&6HIXZyxo2#!O&6fOhbHXC?%1cMc6y^*dOS{f$=137Ds1m01qs`>iUQ49JijsaQ( zksqV9@&?il$|4Ua%4!O15>Zy&%gBY&wgqB>XA3!EldQ%1CRSM(pp#k~-pkcCg4LAT zXE=puHbgsw)!xtc@P4r~Z}nTF=D2~j(6D%gTBw$(`Fc=OOQ0kiW$_RDd=hcO0t97h zb86S5r=>(@VGy1&#S$Kg_H@7G^;8Ue)X5Y+IWUi`o;mpvoV)`fcVk4FpcT|;EG!;? zHG^zrVVZOm>1KFaHlaogcWj(v!S)O(Aa|Vo?S|P z5|6b{qkH(USa*Z7-y_Uvty_Z1|B{rTS^qmEMLEYUSk03_Fg&!O3BMo{b^*`3SHvl0 zhnLTe^_vVIdcSHe)SQE}r~2dq)VZJ!aSKR?RS<(9lzkYo&dQ?mubnWmgMM37Nudwo z3Vz@R{=m2gENUE3V4NbIzAA$H1z0pagz94-PTJyX{b$yndsdKptmlKQKaaHj@3=ED zc7L?p@%ui|RegVYutK$64q4pe9+5sv34QUpo)u{1ci?)_7gXQd{PL>b0l(LI#rJmN zGuO+%GO`xneFOOr4EU(Wg}_%bhzUf;d@TU+V*2#}!2OLwg~%D;1FAu=Un>OgjPb3S z7l(riiCwgghC=Lm5hWGf5NdGp#01xQ59`HJcLXbUR3&n%P(+W2q$h2Qd z*6+-QXJ*&Kvk9ht0f0*rO_|FMBALen{j7T1l%=Q>gf#kma zQlg#I9+HB+z*5BMxdesMND`_W;q5|FaEURFk|~&{@qY32N$G$2B=&Po{=!)x5b!#n zxLzblkq{yj05#O7(GRuT39(06FJlalyv<#K4m}+vs>9@q-&31@1(QBv82{}Zkns~K ze{eHC_RDX0#^A*JQTwF`a=IkE6Ze@j#-8Q`tTT?k9`^ZhA~3eCZJ-Jr{~7Cx;H4A3 zcZ+Zj{mzFZbVvQ6U~n>$U2ZotGsERZ@}VKrgGh0xM;Jzt29%TX6_&CWzg+YYMozrM z`nutuS)_0dCM8UVaKRj804J4i%z2BA_8A4OJRQ$N(P9Mfn-gF;4#q788C@9XR0O3< zsoS4wIoyt046d+LnSCJOy@B@Uz*#GGd#+Ln1ek5Dv>(ZtD@tgZlPnZZJGBLr^JK+!$$?A_fA3LOrkoDRH&l7 zcMcD$Hsjko3`-{bn)jPL6E9Ds{WskMrivsUu5apD z?grQO@W7i5+%X&E&p|RBaEZ(sGLR@~(y^BI@lDMot^Ll?!`90KT!JXUhYS`ZgX3jnu@Ja^seA*M5R@f`=`ynQV4rc$uT1mvE?@tz)TN<=&H1%Z?5yjxcpO+6y_R z6EPuPKM5uxKpmZfT(WKjRRNHs@ib)F5WAP7QCADvmCSD#hPz$V10wiD&{NXyEwx5S z6NE`3z!IS^$s7m}PCwQutVQ#~w+V z=+~->DI*bR2j0^@dMr9`p>q^Ny~NrAVxrJtX2DUveic5vM%#N*XO|?YAWwNI$Q)_) zvE|L(L1jP@F%gOGtnlXtIv2&1i8q<)Xfz8O3G^Ea~e*HJsQgBxWL(yuLY+jqUK zRE~`-zklrGog(X}$9@ZVUw!8*=l`6mzYLtsg`AvBYz(cxmAhr^j0~(rzXdiOEeu_p zE$sf2(w(BPAvO5DlaN&uQ$4@p-b?fRs}d7&2UQ4Fh?1Hzu*YVjcndqJLw0#q@fR4u zJCJ}>_7-|QbvOfylj+e^_L`5Ep9gqd>XI3-O?Wp z-gt*P29f$Tx(mtS`0d05nHH=gm~Po_^OxxUwV294BDKT>PHVlC5bndncxGR!n(OOm znsNt@Q&N{TLrmsoKFw0&_M9$&+C24`sIXGWgQaz=kY;S{?w`z^Q0JXXBKFLj0w0U6P*+jPKyZHX9F#b0D1$&(- zrm8PJd?+SrVf^JlfTM^qGDK&-p2Kdfg?f>^%>1n8bu&byH(huaocL>l@f%c*QkX2i znl}VZ4R1en4S&Bcqw?$=Zi7ohqB$Jw9x`aM#>pHc0x z0$!q7iFu zZ`tryM70qBI6JWWTF9EjgG@>6SRzsd}3h+4D8d~@CR07P$LJ}MFsYi-*O%XVvD@yT|rJ+Mk zDllJ7$n0V&A!0flbOf)HE6P_afPWZmbhpliqJuw=-h+r;WGk|ntkWN(8tKlYpq5Ow z(@%s>IN8nHRaYb*^d;M(D$zGCv5C|uqmsDjwy4g=Lz>*OhO3z=)VD}C<65;`89Ye} zSCxrv#ILzIpEx1KdLPlM&%Cctf@FqTKvNPXC&`*H9=l=D3r!GLM?UV zOxa(8ZsB`&+76S-_xuj?G#wXBfDY@Z_tMpXJS7^mp z@YX&u0jYw2A+Z+bD#6sgVK5ZgdPSJV3>{K^4~%HV?rn~4D)*2H!67Y>0aOmzup`{D zzDp3c9yEbGCY$U<8biJ_gB*`jluz1ShUd!QUIQJ$*1;MXCMApJ^m*Fiv88RZ zFopLViw}{$Tyhh_{MLGIE2~sZ)t0VvoW%=8qKZ>h=adTe3QM$&$PO2lfqH@brt!9j ziePM8$!CgE9iz6B<6_wyTQj?qYa;eC^{x_0wuwV~W+^fZmFco-o%wsKSnjXFEx02V zF5C2t)T6Gw$Kf^_c;Ei3G~uC8SM-xyycmXyC2hAVi-IfXqhu$$-C=*|X?R0~hu z8`J6TdgflslhrmDZq1f?GXF7*ALeMmOEpRDg(s*H`4>_NAr`2uqF;k;JQ+8>A|_6ZNsNLECC%NNEb1Y1dP zbIEmNpK)#XagtL4R6BC{C5T(+=yA-(Z|Ap}U-AfZM#gwVpus3(gPn}Q$CExObJ5AC z)ff9Yk?wZ}dZ-^)?cbb9Fw#EjqQ8jxF4G3=L?Ra zg_)0QDMV1y^A^>HRI$x?Op@t;oj&H@1xt4SZ9(kifQ zb59B*`M99Td7@aZ3UWvj1rD0sE)d=BsBuW*KwkCds7ay(7*01_+L}b~7)VHI>F_!{ zyxg-&nCO?v#KOUec0{OOKy+sjWA;8rTE|Lv6I9H?CI?H(mUm8VXGwU$49LGpz&{nQp2}dinE1@lZ1iox6{ghN&v^GZv9J${7WaXj)<0S4g_uiJ&JCZ zr8-hsu`U%N;+9N^@&Q0^kVPB3)wY(rr}p7{p0qFHb3NUUHJb672+wRZs`gd1UjKPX z4o6zljKKA+Kkj?H>Ew63o%QjyBk&1!P22;MkD>sM0=z_s-G{mTixJCT9@_|*(p^bz zJ8?ZZ&;pzV+7#6Mn`_U-)k8Pjg?a;|Oe^us^PoPY$Va~yi8|?+&=y$f+lABT<*pZr zP}D{~Pq1Qyni+@|aP;ixO~mbEW9#c0OU#YbDZIaw=_&$K%Ep2f%hO^&P67hApZe`x zv8b`Mz@?M_7-)b!lkQKk)JXXUuT|B8kJlvqRmRpxtQDgvrHMXC1B$M@Y%Me!BSx3P z#2Eawl$HleZhhTS6Txm>lN_+I`>eV$&v9fOg)%zVn3O5mI*lAl>QcHuW6!Kixmq`X zBCZ*Ck6OYtDiK!N47>jxI&O2a9x7M|i^IagRr-fmrmikEQGgw%J7bO|)*$2FW95O4 zeBs>KR)izRG1gRVL;F*sr8A}aRHO0gc$$j&ds8CIO1=Gwq1%_~E)CWNn9pCtBE}+`Jelk4{>S)M)`Ll=!~gnn1yq^EX(+y*ik@3Ou0qU`IgYi3*doM+5&dU!cho$pZ zn%lhKeZkS72P?Cf68<#kll_6OAO26bIbueZx**j6o;I0cS^XiL`y+>{cD}gd%lux} z)3N>MaE24WBZ}s0ApfdM;5J_Ny}rfUyxfkC``Awo2#sgLnGPewK};dORuT?@I6(5~ z?kE)Qh$L&fwJXzK){iYx!l5$Tt|^D~MkGZPA}(o6f7w~O2G6Vvzdo*a;iXzk$B66$ zwF#;wM7A+(;uFG4+UAY(2`*3XXx|V$K8AYu#ECJYSl@S=uZW$ksfC$~qrrbQj4??z-)uz0QL}>k^?fPnJTPw% zGz)~?B4}u0CzOf@l^um}HZzbaIwPmb<)< zi_3@E9lc)Qe2_`*Z^HH;1CXOceL=CHpHS{HySy3T%<^NrWQ}G0i4e1xm_K3(+~oi$ zoHl9wzb?Z4j#90DtURtjtgvi7uw8DzHYmtPb;?%8vb9n@bszT=1qr)V_>R%s!92_` zfnHQPANx z<#hIjIMm#*(v*!OXtF+w8kLu`o?VZ5k7{`vw{Yc^qYclpUGIM_PBN1+c{#Vxv&E*@ zxg=W2W~JuV{IuRYw3>LSI1)a!thID@R=bU+cU@DbR^_SXY`MC7HOsCN z!dO4OKV7(E_Z8T#8MA1H`99?Z!r0)qKW_#|29X3#Jb+5+>qUidbeP1NJ@)(qi2S-X zao|f0_tl(O+$R|Qwd$H{_ig|~I1fbp_$NkI!0E;Y z6JrnU{1Ra6^on{9gUUB0mwzP3S%B#h0fjo>JvV~#+X0P~JV=IG=yHG$O+p5O3NUgG zEQ}z6BTp^Fie)Sg<){Z&I8NwPR(=mO4joTLHkJ>|Tnk23E(Bo`FSbPc05lF2-+)X? z6vV3*m~IBHTy*^E!<0nA(tCOJW2G4DsH7)BxLV8kICn5lu6@U*R`w)o9;Ro$i8=Q^V%uH8n3q=+Yf;SFRZu z!+F&PKcH#8cG?aSK_Tl@K9P#8o+jry@gdexz&d(Q=47<7nw@e@FFfIRNL9^)1i@;A z28+$Z#rjv-wj#heI|<&J_DiJ*s}xd-f!{J8jfqOHE`TiHHZVIA8CjkNQ_u;Ery^^t zl1I75&u^`1_q)crO+JT4rx|z2ToSC>)Or@-D zy3S>jW*sNIZR-EBsfyaJ+Jq4BQE4?SePtD2+jY8*%FsSLZ9MY>+wk?}}}AFAw)vr{ml)8LUG-y9>^t!{~|sgpxYc0Gnkg`&~R z-pilJZjr@y5$>B=VMdZ73svct%##v%wdX~9fz6i3Q-zOKJ9wso+h?VME7}SjL=!NUG{J?M&i!>ma`eoEa@IX`5G>B1(7;%}M*%-# zfhJ(W{y;>MRz!Ic8=S}VaBKqh;~7KdnGEHxcL$kA-6E~=!hrN*zw9N+_=odt<$_H_8dbo;0=42wcAETPCVGUr~v(`Uai zb{=D!Qc!dOEU6v)2eHSZq%5iqK?B(JlCq%T6av$Cb4Rko6onlG&?CqaX7Y_C_cOC3 zYZ;_oI(}=>_07}Oep&Ws7x7-R)cc8zfe!SYxJYP``pi$FDS)4Fvw5HH=FiU6xfVqIM!hJ;Rx8c0cB7~aPtNH(Nmm5Vh{ibAoU#J6 zImRCr?(iyu_4W_6AWo3*vxTPUw@vPwy@E0`(>1Qi=%>5eSIrp^`` zK*Y?fK_6F1W>-7UsB)RPC4>>Ps9)f+^MqM}8AUm@tZ->j%&h1M8s*s!LX5&WxQcAh z8mciQej@RPm?660%>{_D+7er>%zX_{s|$Z+;G7_sfNfBgY(zLB4Ey}J9F>zX#K0f6 z?dVNIeEh?EIShmP6>M+d|0wMM85Sa4diw1hrg|ITJ}JDg@o8y>(rF9mXk5M z2@D|NA)-7>wD&wF;S_$KS=eE84`BGw3g0?6wGxu8ys4rwI?9U=*^VF22t3%mbGeOh z`!O-OpF7#Vceu~F`${bW0nYVU9ecmk31V{tF%iv&5hWofC>I~cqAt@u6|R+|HLMMX zVxuSlMFOK_EQ86#E8&KwxIr8S9tj_goWtLv4f@!&h8;Ov41{J~496vp9vX=(LK#j! zAwi*21RAV-LD>9Cw3bV_9X(X3)Kr0-UaB*7Y>t82EQ%!)(&(XuAYtTsYy-dz+w=$ir)VJpe!_$ z6SGpX^i(af3{o=VlFPC);|J8#(=_8#vdxDe|Cok+ANhYwbE*FO`Su2m1~w+&9<_9~ z-|tTU_ACGN`~CNW5WYYBn^B#SwZ(t4%3aPp z;o)|L6Rk569KGxFLUPx@!6OOa+5OjQLK5w&nAmwxkC5rZ|m&HT8G%GVZxB_@ME z>>{rnXUqyiJrT(8GMj_ap#yN_!9-lO5e8mR3cJiK3NE{_UM&=*vIU`YkiL$1%kf+1 z4=jk@7EEj`u(jy$HnzE33ZVW_J4bj}K;vT?T91YlO(|Y0FU4r+VdbmQ97%(J5 zkK*Bed8+C}FcZ@HIgdCMioV%A<*4pw_n}l*{Cr4}a(lq|injK#O?$tyvyE`S%(1`H z_wwRvk#13ElkZvij2MFGOj`fhy?nC^8`Zyo%yVcUAfEr8x&J#A{|moUBAV_^f$hpaUuyQeY3da^ zS9iRgf87YBwfe}>BO+T&Fl%rfpZh#+AM?Dq-k$Bq`vG6G_b4z%Kbd&v>qFjow*mBl z-OylnqOpLg}or7_VNwRg2za3VBK6FUfFX{|TD z`Wt0Vm2H$vdlRWYQJqDmM?JUbVqL*ZQY|5&sY*?!&%P8qhA~5+Af<{MaGo(dl&C5t zE%t!J0 zh6jqANt4ABdPxSTrVV}fLsRQal*)l&_*rFq(Ez}ClEH6LHv{J#v?+H-BZ2)Wy{K@9 z+ovXHq~DiDvm>O~r$LJo!cOuwL+Oa--6;UFE2q@g3N8Qkw5E>ytz^(&($!O47+i~$ zKM+tkAd-RbmP{s_rh+ugTD;lriL~`Xwkad#;_aM?nQ7L_muEFI}U_4$phjvYgleK~`Fo`;GiC07&Hq1F<%p;9Q;tv5b?*QnR%8DYJH3P>Svmv47Y>*LPZJy8_{9H`g6kQpyZU{oJ`m%&p~D=K#KpfoJ@ zn-3cqmHsdtN!f?~w+(t+I`*7GQA#EQC^lUA9(i6=i1PqSAc|ha91I%X&nXzjYaM{8$s&wEx@aVkQ6M{E2 zfzId#&r(XwUNtPcq4Ngze^+XaJA1EK-%&C9j>^9(secqe{}z>hR5CFNveMsVA)m#S zk)_%SidkY-XmMWlVnQ(mNJ>)ooszQ#vaK;!rPmGKXV7am^_F!Lz>;~{VrIO$;!#30XRhE1QqO_~#+Ux;B_D{Nk=grn z8Y0oR^4RqtcYM)7a%@B(XdbZCOqnX#fD{BQTeLvRHd(irHKq=4*jq34`6@VAQR8WG z^%)@5CXnD_T#f%@-l${>y$tfb>2LPmc{~5A82|16mH)R?&r#KKLs7xpN-D`=&Cm^R zvMA6#Ahr<3X>Q7|-qfTY)}32HkAz$_mibYV!I)u>bmjK`qwBe(>za^0Kt*HnFbSdO z1>+ryKCNxmm^)*$XfiDOF2|{-v3KKB?&!(S_Y=Ht@|ir^hLd978xuI&N{k>?(*f8H z=ClxVJK_%_z1TH0eUwm2J+2To7FK4o+n_na)&#VLn1m;!+CX+~WC+qg1?PA~KdOlC zW)C@pw75_xoe=w7i|r9KGIvQ$+3K?L{7TGHwrQM{dCp=Z*D}3kX7E-@sZnup!BImw z*T#a=+WcTwL78exTgBn|iNE3#EsOorO z*kt)gDzHiPt07fmisA2LWN?AymkdqTgr?=loT7z@d`wnlr6oN}@o|&JX!yPzC*Y8d zu6kWlTzE1)ckyBn+0Y^HMN+GA$wUO_LN6W>mxCo!0?oiQvT`z$jbSEu&{UHRU0E8# z%B^wOc@S!yhMT49Y)ww(Xta^8pmPCe@eI5C*ed96)AX9<>))nKx0(sci8gwob_1}4 z0DIL&vsJ1_s%<@y%U*-eX z5rN&(zef-5G~?@r79oZGW1d!WaTqQn0F6RIOa9tJ=0(kdd{d1{<*tHT#cCvl*i>YY zH+L7jq8xZNcTUBqj(S)ztTU!TM!RQ}In*n&Gn<>(60G7}4%WQL!o>hbJqNDSGwl#H z`4k+twp0cj%PsS+NKaxslAEu9!#U3xT1|_KB6`h=PI0SW`P9GTa7caD1}vKEglV8# zjKZR`pluCW19c2fM&ZG)c3T3Um;ir3y(tSCJ7Agl6|b524dy5El{^EQBG?E61H0XY z`bqg!;zhGhyMFl&(o=JWEJ8n~z)xI}A@C0d2hQGvw7nGv)?POU@(kS1m=%`|+^ika zXl8zjS?xqW$WlO?Ewa;vF~XbybHBor$f<%I&*t$F5fynwZlTGj|IjZtVfGa7l&tK} zW>I<69w(cZLu)QIVG|M2xzW@S+70NinQzk&Y0+3WT*cC)rx~04O-^<{JohU_&HL5XdUKW!uFy|i$FB|EMu0eUyW;gsf`XfIc!Z0V zeK&*hPL}f_cX=@iv>K%S5kL;cl_$v?n(Q9f_cChk8Lq$glT|=e+T*8O4H2n<=NGmn z+2*h+v;kBvF>}&0RDS>)B{1!_*XuE8A$Y=G8w^qGMtfudDBsD5>T5SB;Qo}fSkkiV ze^K^M(UthkwrD!&*tTsu>Dacdj_q`~V%r_twr$(Ct&_dKeeXE?fA&4&yASJWJ*}~- zel=@W)tusynfC_YqH4ll>4Eg`Xjs5F7Tj>tTLz<0N3)X<1px_d2yUY>X~y>>93*$) z5PuNMQLf9Bu?AAGO~a_|J2akO1M*@VYN^VxvP0F$2>;Zb9;d5Yfd8P%oFCCoZE$ z4#N$^J8rxYjUE_6{T%Y>MmWfHgScpuGv59#4u6fpTF%~KB^Ae`t1TD_^Ud#DhL+Dm zbY^VAM#MrAmFj{3-BpVSWph2b_Y6gCnCAombVa|1S@DU)2r9W<> zT5L8BB^er3zxKt1v(y&OYk!^aoQisqU zH(g@_o)D~BufUXcPt!Ydom)e|aW{XiMnes2z&rE?og>7|G+tp7&^;q?Qz5S5^yd$i z8lWr4g5nctBHtigX%0%XzIAB8U|T6&JsC4&^hZBw^*aIcuNO47de?|pGXJ4t}BB`L^d8tD`H`i zqrP8?#J@8T#;{^B!KO6J=@OWKhAerih(phML`(Rg7N1XWf1TN>=Z3Do{l_!d~DND&)O)D>ta20}@Lt77qSnVsA7>)uZAaT9bsB>u&aUQl+7GiY2|dAEg@%Al3i316y;&IhQL^8fw_nwS>f60M_-m+!5)S_6EPM7Y)(Nq^8gL7(3 zOiot`6Wy6%vw~a_H?1hLVzIT^i1;HedHgW9-P#)}Y6vF%C=P70X0Tk^z9Te@kPILI z_(gk!k+0%CG)%!WnBjjw*kAKs_lf#=5HXC00s-}oM-Q1aXYLj)(1d!_a7 z*Gg4Fe6F$*ujVjI|79Z5+Pr`us%zW@ln++2l+0hsngv<{mJ%?OfSo_3HJXOCys{Ug z00*YR-(fv<=&%Q!j%b-_ppA$JsTm^_L4x`$k{VpfLI(FMCap%LFAyq;#ns5bR7V+x zO!o;c5y~DyBPqdVQX)8G^G&jWkBy2|oWTw>)?5u}SAsI$RjT#)lTV&Rf8;>u*qXnb z8F%Xb=7#$m)83z%`E;49)t3fHInhtc#kx4wSLLms!*~Z$V?bTyUGiS&m>1P(952(H zuHdv=;o*{;5#X-uAyon`hP}d#U{uDlV?W?_5UjJvf%11hKwe&(&9_~{W)*y1nR5f_ z!N(R74nNK`y8>B!0Bt_Vr!;nc3W>~RiKtGSBkNlsR#-t^&;$W#)f9tTlZz>n*+Fjz z3zXZ;jf(sTM(oDzJt4FJS*8c&;PLTW(IQDFs_5QPy+7yhi1syPCarvqrHFcf&yTy)^O<1EBx;Ir`5W{TIM>{8w&PB>ro4;YD<5LF^TjTb0!zAP|QijA+1Vg>{Afv^% zmrkc4o6rvBI;Q8rj4*=AZacy*n8B{&G3VJc)so4$XUoie0)vr;qzPZVbb<#Fc=j+8CGBWe$n|3K& z_@%?{l|TzKSlUEO{U{{%Fz_pVDxs7i9H#bnbCw7@4DR=}r_qV!Zo~CvD4ZI*+j3kO zW6_=|S`)(*gM0Z;;}nj`73OigF4p6_NPZQ-Od~e$c_);;4-7sR>+2u$6m$Gf%T{aq zle>e3(*Rt(TPD}03n5)!Ca8Pu!V}m6v0o1;5<1h$*|7z|^(3$Y&;KHKTT}hV056wuF0Xo@mK-52~r=6^SI1NC%c~CC?n>yX6wPTgiWYVz!Sx^atLby9YNn1Rk{g?|pJaxD4|9cUf|V1_I*w zzxK)hRh9%zOl=*$?XUjly5z8?jPMy%vEN)f%T*|WO|bp5NWv@B(K3D6LMl!-6dQg0 zXNE&O>Oyf%K@`ngCvbGPR>HRg5!1IV$_}m@3dWB7x3t&KFyOJn9pxRXCAzFr&%37wXG;z^xaO$ekR=LJG ztIHpY8F5xBP{mtQidqNRoz= z@){+N3(VO5bD+VrmS^YjG@+JO{EOIW)9=F4v_$Ed8rZtHvjpiEp{r^c4F6Ic#ChlC zJX^DtSK+v(YdCW)^EFcs=XP7S>Y!4=xgmv>{S$~@h=xW-G4FF9?I@zYN$e5oF9g$# zb!eVU#J+NjLyX;yb)%SY)xJdvGhsnE*JEkuOVo^k5PyS=o#vq!KD46UTW_%R=Y&0G zFj6bV{`Y6)YoKgqnir2&+sl+i6foAn-**Zd1{_;Zb7Ki=u394C5J{l^H@XN`_6XTKY%X1AgQM6KycJ+= zYO=&t#5oSKB^pYhNdzPgH~aEGW2=ec1O#s-KG z71}LOg@4UEFtp3GY1PBemXpNs6UK-ax*)#$J^pC_me;Z$Je(OqLoh|ZrW*mAMBFn< zHttjwC&fkVfMnQeen8`Rvy^$pNRFVaiEN4Pih*Y3@jo!T0nsClN)pdrr9AYLcZxZ| zJ5Wlj+4q~($hbtuY zVQ7hl>4-+@6g1i`1a)rvtp-;b0>^`Dloy(#{z~ytgv=j4q^Kl}wD>K_Y!l~ zp(_&7sh`vfO(1*MO!B%<6E_bx1)&s+Ae`O)a|X=J9y~XDa@UB`m)`tSG4AUhoM=5& znWoHlA-(z@3n0=l{E)R-p8sB9XkV zZ#D8wietfHL?J5X0%&fGg@MH~(rNS2`GHS4xTo7L$>TPme+Is~!|79=^}QbPF>m%J zFMkGzSndiPO|E~hrhCeo@&Ea{M(ieIgRWMf)E}qeTxT8Q#g-!Lu*x$v8W^M^>?-g= zwMJ$dThI|~M06rG$Sv@C@tWR>_YgaG&!BAbkGggVQa#KdtDB)lMLNVLN|51C@F^y8 zCRvMB^{GO@j=cHfmy}_pCGbP%xb{pNN>? z?7tBz$1^zVaP|uaatYaIN+#xEN4jBzwZ|YI_)p(4CUAz1ZEbDk>J~Y|63SZaak~#0 zoYKruYsWHoOlC1(MhTnsdUOwQfz5p6-D0}4;DO$B;7#M{3lSE^jnTT;ns`>!G%i*F?@pR1JO{QTuD0U+~SlZxcc8~>IB{)@8p`P&+nDxNj`*gh|u?yrv$phpQcW)Us)bi`kT%qLj(fi{dWRZ%Es2!=3mI~UxiW0$-v3vUl?#g{p6eF zMEUAqo5-L0Ar(s{VlR9g=j7+lt!gP!UN2ICMokAZ5(Agd>})#gkA2w|5+<%-CuEP# zqgcM}u@3(QIC^Gx<2dbLj?cFSws_f3e%f4jeR?4M^M3cx1f+Qr6ydQ>n)kz1s##2w zk}UyQc+Z5G-d-1}{WzjkLXgS-2P7auWSJ%pSnD|Uivj5u!xk0 z_^-N9r9o;(rFDt~q1PvE#iJZ_f>J3gcP$)SOqhE~pD2|$=GvpL^d!r z6u=sp-CrMoF7;)}Zd7XO4XihC4ji?>V&(t^?@3Q&t9Mx=qex6C9d%{FE6dvU6%d94 zIE;hJ1J)cCqjv?F``7I*6bc#X)JW2b4f$L^>j{*$R`%5VHFi*+Q$2;nyieduE}qdS{L8y8F08yLs?w}{>8>$3236T-VMh@B zq-nujsb_1aUv_7g#)*rf9h%sFj*^mIcImRV*k~Vmw;%;YH(&ylYpy!&UjUVqqtfG` zox3esju?`unJJA_zKXRJP)rA3nXc$m^{S&-p|v|-0x9LHJm;XIww7C#R$?00l&Yyj z=e}gKUOpsImwW?N)+E(awoF@HyP^EhL+GlNB#k?R<2>95hz!h9sF@U20DHSB3~WMa zk90+858r@-+vWwkawJ)8ougd(i#1m3GLN{iSTylYz$brAsP%=&m$mQQrH$g%3-^VR zE%B`Vi&m8f3T~&myTEK28BDWCVzfWir1I?03;pX))|kY5ClO^+bae z*7E?g=3g7EiisYOrE+lA)2?Ln6q2*HLNpZEWMB|O-JI_oaHZB%CvYB(%=tU= zE*OY%QY58fW#RG5=gm0NR#iMB=EuNF@)%oZJ}nmm=tsJ?eGjia{e{yuU0l3{d^D@)kVDt=1PE)&tf_hHC%0MB znL|CRCPC}SeuVTdf>-QV70`0(EHizc21s^sU>y%hW0t!0&y<7}Wi-wGy>m%(-jsDj zP?mF|>p_K>liZ6ZP(w5(|9Ga%>tLgb$|doDDfkdW>Z z`)>V2XC?NJT26mL^@ zf+IKr27TfM!UbZ@?zRddC7#6ss1sw%CXJ4FWC+t3lHZupzM77m^=9 z&(a?-LxIq}*nvv)y?27lZ{j zifdl9hyJudyP2LpU$-kXctshbJDKS{WfulP5Dk~xU4Le4c#h^(YjJit4#R8_khheS z|8(>2ibaHES4+J|DBM7I#QF5u-*EdN{n=Kt@4Zt?@Tv{JZA{`4 zU#kYOv{#A&gGPwT+$Ud}AXlK3K7hYzo$(fBSFjrP{QQ zeaKg--L&jh$9N}`pu{Bs>?eDFPaWY4|9|foN%}i;3%;@4{dc+iw>m}{3rELqH21G! z`8@;w-zsJ1H(N3%|1B@#ioLOjib)j`EiJqPQVSbPSPVHCj6t5J&(NcWzBrzCiDt{4 zdlPAUKldz%6x5II1H_+jv)(xVL+a;P+-1hv_pM>gMRr%04@k;DTokASSKKhU1Qms| zrWh3a!b(J3n0>-tipg{a?UaKsP7?+|@A+1WPDiQIW1Sf@qDU~M_P65_s}7(gjTn0X zucyEm)o;f8UyshMy&>^SC3I|C6jR*R_GFwGranWZe*I>K+0k}pBuET&M~ z;Odo*ZcT?ZpduHyrf8E%IBFtv;JQ!N_m>!sV6ly$_1D{(&nO~w)G~Y`7sD3#hQk%^ zp}ucDF_$!6DAz*PM8yE(&~;%|=+h(Rn-=1Wykas_-@d&z#=S}rDf`4w(rVlcF&lF! z=1)M3YVz7orwk^BXhslJ8jR);sh^knJW(Qmm(QdSgIAIdlN4Te5KJisifjr?eB{FjAX1a0AB>d?qY4Wx>BZ8&}5K0fA+d{l8 z?^s&l8#j7pR&ijD?0b%;lL9l$P_mi2^*_OL+b}4kuLR$GAf85sOo02?Y#90}CCDiS zZ%rbCw>=H~CBO=C_JVV=xgDe%b4FaEFtuS7Q1##y686r%F6I)s-~2(}PWK|Z8M+Gu zl$y~5@#0Ka%$M<&Cv%L`a8X^@tY&T7<0|(6dNT=EsRe0%kp1Qyq!^43VAKYnr*A5~ zsI%lK1ewqO;0TpLrT9v}!@vJK{QoVa_+N4FYT#h?Y8rS1S&-G+m$FNMP?(8N`MZP zels(*?kK{{^g9DOzkuZXJ2;SrOQsp9T$hwRB1(phw1c7`!Q!by?Q#YsSM#I12RhU{$Q+{xj83axHcftEc$mNJ8_T7A-BQc*k(sZ+~NsO~xAA zxnbb%dam_fZlHvW7fKXrB~F&jS<4FD2FqY?VG?ix*r~MDXCE^WQ|W|WM;gsIA4lQP zJ2hAK@CF*3*VqPr2eeg6GzWFlICi8S>nO>5HvWzyZTE)hlkdC_>pBej*>o0EOHR|) z$?};&I4+_?wvL*g#PJ9)!bc#9BJu1(*RdNEn>#Oxta(VWeM40ola<0aOe2kSS~{^P zDJBd}0L-P#O-CzX*%+$#v;(x%<*SPgAje=F{Zh-@ucd2DA(yC|N_|ocs*|-!H%wEw z@Q!>siv2W;C^^j^59OAX03&}&D*W4EjCvfi(ygcL#~t8XGa#|NPO+*M@Y-)ctFA@I z-p7npT1#5zOLo>7q?aZpCZ=iecn3QYklP;gF0bq@>oyBq94f6C=;Csw3PkZ|5q=(c zfs`aw?II0e(h=|7o&T+hq&m$; zBrE09Twxd9BJ2P+QPN}*OdZ-JZV7%av@OM7v!!NL8R;%WFq*?{9T3{ct@2EKgc8h) zMxoM$SaF#p<`65BwIDfmXG6+OiK0e)`I=!A3E`+K@61f}0e z!2a*FOaDrOe>U`q%K!QN`&=&0C~)CaL3R4VY(NDt{Xz(Xpqru5=r#uQN1L$Je1*dkdqQ*=lofQaN%lO!<5z9ZlHgxt|`THd>2 zsWfU$9=p;yLyJyM^t zS2w9w?Bpto`@H^xJpZDKR1@~^30Il6oFGfk5%g6w*C+VM)+%R@gfIwNprOV5{F^M2 zO?n3DEzpT+EoSV-%OdvZvNF+pDd-ZVZ&d8 zKeIyrrfPN=EcFRCPEDCVflX#3-)Ik_HCkL(ejmY8vzcf-MTA{oHk!R2*36`O68$7J zf}zJC+bbQk--9Xm!u#lgLvx8TXx2J258E5^*IZ(FXMpq$2LUUvhWQPs((z1+2{Op% z?J}9k5^N=z;7ja~zi8a_-exIqWUBJwohe#4QJ`|FF*$C{lM18z^#hX6!5B8KAkLUX ziP=oti-gpV(BsLD{0(3*dw}4JxK23Y7M{BeFPucw!sHpY&l%Ws4pSm`+~V7;bZ%Dx zeI)MK=4vC&5#;2MT7fS?^ch9?2;%<8Jlu-IB&N~gg8t;6S-#C@!NU{`p7M8@2iGc& zg|JPg%@gCoCQ&s6JvDU&`X2S<57f(k8nJ1wvBu{8r?;q3_kpZZ${?|( z+^)UvR33sjSd)aT!UPkA;ylO6{aE3MQa{g%Mcf$1KONcjO@&g5zPHWtzM1rYC{_K> zgQNcs<{&X{OA=cEWw5JGqpr0O>x*Tfak2PE9?FuWtz^DDNI}rwAaT0(bdo-<+SJ6A z&}S%boGMWIS0L}=S>|-#kRX;e^sUsotry(MjE|3_9duvfc|nwF#NHuM-w7ZU!5ei8 z6Mkf>2)WunY2eU@C-Uj-A zG(z0Tz2YoBk>zCz_9-)4a>T46$(~kF+Y{#sA9MWH%5z#zNoz)sdXq7ZR_+`RZ%0(q zC7&GyS_|BGHNFl8Xa%@>iWh%Gr?=J5<(!OEjauj5jyrA-QXBjn0OAhJJ9+v=!LK`` z@g(`^*84Q4jcDL`OA&ZV60djgwG`|bcD*i50O}Q{9_noRg|~?dj%VtKOnyRs$Uzqg z191aWoR^rDX#@iSq0n z?9Sg$WSRPqSeI<}&n1T3!6%Wj@5iw5`*`Btni~G=&;J+4`7g#OQTa>u`{4ZZ(c@s$ zK0y;ySOGD-UTjREKbru{QaS>HjN<2)R%Nn-TZiQ(Twe4p@-saNa3~p{?^V9Nixz@a zykPv~<@lu6-Ng9i$Lrk(xi2Tri3q=RW`BJYOPC;S0Yly%77c727Yj-d1vF!Fuk{Xh z)lMbA69y7*5ufET>P*gXQrxsW+ zz)*MbHZv*eJPEXYE<6g6_M7N%#%mR{#awV3i^PafNv(zyI)&bH?F}2s8_rR(6%!V4SOWlup`TKAb@ee>!9JKPM=&8g#BeYRH9FpFybxBXQI2|g}FGJfJ+ zY-*2hB?o{TVL;Wt_ek;AP5PBqfDR4@Z->_182W z{P@Mc27j6jE*9xG{R$>6_;i=y{qf(c`5w9fa*`rEzX6t!KJ(p1H|>J1pC-2zqWENF zmm=Z5B4u{cY2XYl(PfrInB*~WGWik3@1oRhiMOS|D;acnf-Bs(QCm#wR;@Vf!hOPJ zgjhDCfDj$HcyVLJ=AaTbQ{@vIv14LWWF$=i-BDoC11}V;2V8A`S>_x)vIq44-VB-v z*w-d}$G+Ql?En8j!~ZkCpQ$|cA0|+rrY>tiCeWxkRGPoarxlGU2?7%k#F693RHT24 z-?JsiXlT2PTqZqNb&sSc>$d;O4V@|b6VKSWQb~bUaWn1Cf0+K%`Q&Wc<>mQ>*iEGB zbZ;aYOotBZ{vH3y<0A*L0QVM|#rf*LIsGx(O*-7)r@yyBIzJnBFSKBUSl1e|8lxU* zzFL+YDVVkIuzFWeJ8AbgN&w(4-7zbiaMn{5!JQXu)SELk*CNL+Fro|2v|YO)1l15t zs(0^&EB6DPMyaqvY>=KL>)tEpsn;N5Q#yJj<9}ImL((SqErWN3Q=;tBO~ExTCs9hB z2E$7eN#5wX4<3m^5pdjm#5o>s#eS_Q^P)tm$@SawTqF*1dj_i#)3};JslbLKHXl_N z)Fxzf>FN)EK&Rz&*|6&%Hs-^f{V|+_vL1S;-1K-l$5xiC@}%uDuwHYhmsV?YcOUlk zOYkG5v2+`+UWqpn0aaaqrD3lYdh0*!L`3FAsNKu=Q!vJu?Yc8n|CoYyDo_`r0mPoo z8>XCo$W4>l(==h?2~PoRR*kEe)&IH{1sM41mO#-36`02m#nTX{r*r`Q5rZ2-sE|nA zhnn5T#s#v`52T5|?GNS`%HgS2;R(*|^egNPDzzH_z^W)-Q98~$#YAe)cEZ%vge965AS_am#DK#pjPRr-!^za8>`kksCAUj(Xr*1NW5~e zpypt_eJpD&4_bl_y?G%>^L}=>xAaV>KR6;^aBytqpiHe%!j;&MzI_>Sx7O%F%D*8s zSN}cS^<{iiK)=Ji`FpO#^zY!_|D)qeRNAtgmH)m;qC|mq^j(|hL`7uBz+ULUj37gj zksdbnU+LSVo35riSX_4z{UX=%n&}7s0{WuZYoSfwAP`8aKN9P@%e=~1`~1ASL-z%# zw>DO&ixr}c9%4InGc*_y42bdEk)ZdG7-mTu0bD@_vGAr*NcFoMW;@r?@LUhRI zCUJgHb`O?M3!w)|CPu~ej%fddw20lod?Ufp8Dmt0PbnA0J%KE^2~AIcnKP()025V> zG>noSM3$5Btmc$GZoyP^v1@Poz0FD(6YSTH@aD0}BXva?LphAiSz9f&Y(aDAzBnUh z?d2m``~{z;{}kZJ>a^wYI?ry(V9hIoh;|EFc0*-#*`$T0DRQ1;WsqInG;YPS+I4{g zJGpKk%%Sdc5xBa$Q^_I~(F97eqDO7AN3EN0u)PNBAb+n+ zWBTxQx^;O9o0`=g+Zrt_{lP!sgWZHW?8bLYS$;1a@&7w9rD9|Ge;Gb?sEjFoF9-6v z#!2)t{DMHZ2@0W*fCx;62d#;jouz`R5Y(t{BT=$N4yr^^o$ON8d{PQ=!O zX17^CrdM~7D-;ZrC!||<+FEOxI_WI3CA<35va%4v>gc zEX-@h8esj=a4szW7x{0g$hwoWRQG$yK{@3mqd-jYiVofJE!Wok1* znV7Gm&Ssq#hFuvj1sRyHg(6PFA5U*Q8Rx>-blOs=lb`qa{zFy&n4xY;sd$fE+<3EI z##W$P9M{B3c3Si9gw^jlPU-JqD~Cye;wr=XkV7BSv#6}DrsXWFJ3eUNrc%7{=^sP> zrp)BWKA9<}^R9g!0q7yWlh;gr_TEOD|#BmGq<@IV;ueg+D2}cjpp+dPf&Q(36sFU&K8}hA85U61faW&{ zlB`9HUl-WWCG|<1XANN3JVAkRYvr5U4q6;!G*MTdSUt*Mi=z_y3B1A9j-@aK{lNvx zK%p23>M&=KTCgR!Ee8c?DAO2_R?B zkaqr6^BSP!8dHXxj%N1l+V$_%vzHjqvu7p@%Nl6;>y*S}M!B=pz=aqUV#`;h%M0rU zHfcog>kv3UZAEB*g7Er@t6CF8kHDmKTjO@rejA^ULqn!`LwrEwOVmHx^;g|5PHm#B zZ+jjWgjJ!043F+&#_;D*mz%Q60=L9Ove|$gU&~As5^uz@2-BfQ!bW)Khn}G+Wyjw- z19qI#oB(RSNydn0t~;tAmK!P-d{b-@@E5|cdgOS#!>%#Rj6ynkMvaW@37E>@hJP^8 z2zk8VXx|>#R^JCcWdBCy{0nPmYFOxN55#^-rlqobe0#L6)bi?E?SPymF*a5oDDeSd zO0gx?#KMoOd&G(2O@*W)HgX6y_aa6iMCl^~`{@UR`nMQE`>n_{_aY5nA}vqU8mt8H z`oa=g0SyiLd~BxAj2~l$zRSDHxvDs;I4>+M$W`HbJ|g&P+$!U7-PHX4RAcR0szJ*( ze-417=bO2q{492SWrqDK+L3#ChUHtz*@MP)e^%@>_&#Yk^1|tv@j4%3T)diEX zATx4K*hcO`sY$jk#jN5WD<=C3nvuVsRh||qDHnc~;Kf59zr0;c7VkVSUPD%NnnJC_ zl3F^#f_rDu8l}l8qcAz0FFa)EAt32IUy_JLIhU_J^l~FRH&6-ivSpG2PRqzDdMWft>Zc(c)#tb%wgmWN%>IOPm zZi-noqS!^Ftb81pRcQi`X#UhWK70hy4tGW1mz|+vI8c*h@ zfFGJtW3r>qV>1Z0r|L>7I3un^gcep$AAWfZHRvB|E*kktY$qQP_$YG60C@X~tTQjB3%@`uz!qxtxF+LE!+=nrS^07hn` zEgAp!h|r03h7B!$#OZW#ACD+M;-5J!W+{h|6I;5cNnE(Y863%1(oH}_FTW})8zYb$7czP zg~Szk1+_NTm6SJ0MS_|oSz%e(S~P-&SFp;!k?uFayytV$8HPwuyELSXOs^27XvK-D zOx-Dl!P|28DK6iX>p#Yb%3`A&CG0X2S43FjN%IB}q(!hC$fG}yl1y9W&W&I@KTg6@ zK^kpH8=yFuP+vI^+59|3%Zqnb5lTDAykf z9S#X`3N(X^SpdMyWQGOQRjhiwlj!0W-yD<3aEj^&X%=?`6lCy~?`&WSWt z?U~EKFcCG_RJ(Qp7j=$I%H8t)Z@6VjA#>1f@EYiS8MRHZphp zMA_5`znM=pzUpBPO)pXGYpQ6gkine{6u_o!P@Q+NKJ}k!_X7u|qfpAyIJb$_#3@wJ z<1SE2Edkfk9C!0t%}8Yio09^F`YGzpaJHGk*-ffsn85@)%4@`;Fv^8q(-Wk7r=Q8p zT&hD`5(f?M{gfzGbbwh8(}G#|#fDuk7v1W)5H9wkorE0ZZjL0Q1=NRGY>zwgfm81DdoaVwNH;or{{eSyybt)m<=zXoA^RALYG-2t zouH|L*BLvmm9cdMmn+KGopyR@4*=&0&4g|FLoreZOhRmh=)R0bg~ zT2(8V_q7~42-zvb)+y959OAv!V$u(O3)%Es0M@CRFmG{5sovIq4%8Ahjk#*5w{+)+ zMWQoJI_r$HxL5km1#6(e@{lK3Udc~n0@g`g$s?VrnQJ$!oPnb?IHh-1qA`Rz$)Ai< z6w$-MJW-gKNvOhL+XMbE7&mFt`x1KY>k4(!KbbpZ`>`K@1J<(#vVbjx@Z@(6Q}MF# zMnbr-f55(cTa^q4+#)=s+ThMaV~E`B8V=|W_fZWDwiso8tNMTNse)RNBGi=gVwgg% zbOg8>mbRN%7^Um-7oj4=6`$|(K7!+t^90a{$18Z>}<#!bm%ZEFQ{X(yBZMc>lCz0f1I2w9Sq zuGh<9<=AO&g6BZte6hn>Qmvv;Rt)*cJfTr2=~EnGD8P$v3R|&1RCl&7)b+`=QGapi zPbLg_pxm`+HZurtFZ;wZ=`Vk*do~$wB zxoW&=j0OTbQ=Q%S8XJ%~qoa3Ea|au5o}_(P;=!y-AjFrERh%8la!z6Fn@lR?^E~H12D?8#ht=1F;7@o4$Q8GDj;sSC%Jfn01xgL&%F2 zwG1|5ikb^qHv&9hT8w83+yv&BQXOQyMVJSBL(Ky~p)gU3#%|blG?IR9rP^zUbs7rOA0X52Ao=GRt@C&zlyjNLv-} z9?*x{y(`509qhCV*B47f2hLrGl^<@SuRGR!KwHei?!CM10Tq*YDIoBNyRuO*>3FU? zHjipIE#B~y3FSfOsMfj~F9PNr*H?0oHyYB^G(YyNh{SxcE(Y-`x5jFMKb~HO*m+R% zrq|ic4fzJ#USpTm;X7K+E%xsT_3VHKe?*uc4-FsILUH;kL>_okY(w`VU*8+l>o>Jm ziU#?2^`>arnsl#)*R&nf_%>A+qwl%o{l(u)M?DK1^mf260_oteV3#E_>6Y4!_hhVD zM8AI6MM2V*^_M^sQ0dmHu11fy^kOqXqzpr?K$`}BKWG`=Es(9&S@K@)ZjA{lj3ea7_MBP zk(|hBFRjHVMN!sNUkrB;(cTP)T97M$0Dtc&UXSec<+q?y>5=)}S~{Z@ua;1xt@=T5 zI7{`Z=z_X*no8s>mY;>BvEXK%b`a6(DTS6t&b!vf_z#HM{Uoy_5fiB(zpkF{})ruka$iX*~pq1ZxD?q68dIo zIZSVls9kFGsTwvr4{T_LidcWtt$u{kJlW7moRaH6+A5hW&;;2O#$oKyEN8kx`LmG)Wfq4ykh+q{I3|RfVpkR&QH_x;t41Uw z`P+tft^E2B$domKT@|nNW`EHwyj>&}K;eDpe z1bNOh=fvIfk`&B61+S8ND<(KC%>y&?>opCnY*r5M+!UrWKxv0_QvTlJc>X#AaI^xo zaRXL}t5Ej_Z$y*|w*$6D+A?Lw-CO-$itm^{2Ct82-<0IW)0KMNvJHgBrdsIR0v~=H z?n6^}l{D``Me90`^o|q!olsF?UX3YSq^6Vu>Ijm>>PaZI8G@<^NGw{Cx&%|PwYrfw zR!gX_%AR=L3BFsf8LxI|K^J}deh0ZdV?$3r--FEX`#INxsOG6_=!v)DI>0q|BxT)z z-G6kzA01M?rba+G_mwNMQD1mbVbNTWmBi*{s_v_Ft9m2Avg!^78(QFu&n6mbRJ2bA zv!b;%yo{g*9l2)>tsZJOOp}U~8VUH`}$ z8p_}t*XIOehezolNa-a2x0BS})Y9}&*TPgua{Ewn-=wVrmJUeU39EKx+%w%=ixQWK zDLpwaNJs65#6o7Ln7~~X+p_o2BR1g~VCfxLzxA{HlWAI6^H;`juI=&r1jQrUv_q0Z z1Ja-tjdktrrP>GOC*#p?*xfQU5MqjMsBe!9lh(u8)w$e@Z|>aUHI5o;MGw*|Myiz3 z-f0;pHg~Q#%*Kx8MxH%AluVXjG2C$)WL-K63@Q`#y9_k_+}eR(x4~dp7oV-ek0H>I zgy8p#i4GN{>#v=pFYUQT(g&b$OeTy-X_#FDgNF8XyfGY6R!>inYn8IR2RDa&O!(6< znXs{W!bkP|s_YI*Yx%4stI`=ZO45IK6rBs`g7sP40ic}GZ58s?Mc$&i`kq_tfci>N zIHrC0H+Qpam1bNa=(`SRKjixBTtm&e`j9porEci!zdlg1RI0Jw#b(_Tb@RQK1Zxr_ z%7SUeH6=TrXt3J@js`4iDD0=IoHhK~I7^W8^Rcp~Yaf>2wVe|Hh1bUpX9ATD#moByY57-f2Ef1TP^lBi&p5_s7WGG9|0T}dlfxOx zXvScJO1Cnq`c`~{Dp;{;l<-KkCDE+pmexJkd}zCgE{eF=)K``-qC~IT6GcRog_)!X z?fK^F8UDz$(zFUrwuR$qro5>qqn>+Z%<5>;_*3pZ8QM|yv9CAtrAx;($>4l^_$_-L z*&?(77!-=zvnCVW&kUcZMb6;2!83si518Y%R*A3JZ8Is|kUCMu`!vxDgaWjs7^0j( ziTaS4HhQ)ldR=r)_7vYFUr%THE}cPF{0H45FJ5MQW^+W>P+eEX2kLp3zzFe*-pFVA zdDZRybv?H|>`9f$AKVjFWJ=wegO7hOOIYCtd?Vj{EYLT*^gl35|HQ`R=ti+ADm{jyQE7K@kdjuqJhWVSks>b^ zxha88-h3s;%3_5b1TqFCPTxVjvuB5U>v=HyZ$?JSk+&I%)M7KE*wOg<)1-Iy)8-K! z^XpIt|0ibmk9RtMmlUd7#Ap3Q!q9N4atQy)TmrhrFhfx1DAN`^vq@Q_SRl|V z#lU<~n67$mT)NvHh`%als+G-)x1`Y%4Bp*6Un5Ri9h=_Db zA-AdP!f>f0m@~>7X#uBM?diI@)Egjuz@jXKvm zJo+==juc9_<;CqeRaU9_Mz@;3e=E4=6TK+c`|uu#pIqhSyNm`G(X)&)B`8q0RBv#> z`gGlw(Q=1Xmf55VHj%C#^1lpc>LY8kfA@|rlC1EA<1#`iuyNO z(=;irt{_&K=i4)^x%;U(Xv<)+o=dczC5H3W~+e|f~{*ucxj@{Yi-cw^MqYr3fN zF5D+~!wd$#al?UfMnz(@K#wn`_5na@rRr8XqN@&M&FGEC@`+OEv}sI1hw>Up0qAWf zL#e4~&oM;TVfjRE+10B_gFlLEP9?Q-dARr3xi6nQqnw>k-S;~b z;!0s2VS4}W8b&pGuK=7im+t(`nz@FnT#VD|!)eQNp-W6)@>aA+j~K*H{$G`y2|QHY z|Hmy+CR@#jWY4~)lr1qBJB_RfHJFfP<}pK5(#ZZGSqcpyS&}01LnTWk5fzmXMGHkJ zTP6L^B+uj;lmB_W<~4=${+v0>z31M!-_O@o-O9GyW)j_mjx}!0@br_LE-7SIuPP84 z;5=O(U*g_um0tyG|61N@d9lEuOeiRd+#NY^{nd5;-CVlw&Ap7J?qwM^?E29wvS}2d zbzar4Fz&RSR(-|s!Z6+za&Z zY#D<5q_JUktIzvL0)yq_kLWG6DO{ri=?c!y!f(Dk%G{8)k`Gym%j#!OgXVDD3;$&v@qy#ISJfp=Vm>pls@9-mapVQChAHHd-x+OGx)(*Yr zC1qDUTZ6mM(b_hi!TuFF2k#8uI2;kD70AQ&di$L*4P*Y-@p`jdm%_c3f)XhYD^6M8&#Y$ZpzQMcR|6nsH>b=*R_Von!$BTRj7yGCXokoAQ z&ANvx0-Epw`QIEPgI(^cS2f(Y85yV@ygI{ewyv5Frng)e}KCZF7JbR(&W618_dcEh(#+^zZFY;o<815<5sOHQdeax9_!PyM&;{P zkBa5xymca0#)c#tke@3KNEM8a_mT&1gm;p&&JlMGH(cL(b)BckgMQ^9&vRwj!~3@l zY?L5}=Jzr080OGKb|y`ee(+`flQg|!lo6>=H)X4`$Gz~hLmu2a%kYW_Uu8x09Pa0J zKZ`E$BKJ=2GPj_3l*TEcZ*uYRr<*J^#5pILTT;k_cgto1ZL-%slyc16J~OH-(RgDA z%;EjEnoUkZ&acS{Q8`{i6T5^nywgqQI5bDIymoa7CSZG|WWVk>GM9)zy*bNih|QIm z%0+(Nnc*a_xo;$=!HQYaapLms>J1ToyjtFByY`C2H1wT#178#4+|{H0BBqtCdd$L% z_3Hc60j@{t9~MjM@LBalR&6@>B;9?r<7J~F+WXyYu*y3?px*=8MAK@EA+jRX8{CG?GI-< z54?Dc9CAh>QTAvyOEm0^+x;r2BWX|{3$Y7)L5l*qVE*y0`7J>l2wCmW zL1?|a`pJ-l{fb_N;R(Z9UMiSj6pQjOvQ^%DvhIJF!+Th7jO2~1f1N+(-TyCFYQZYw z4)>7caf^Ki_KJ^Zx2JUb z&$3zJy!*+rCV4%jqwyuNY3j1ZEiltS0xTzd+=itTb;IPYpaf?8Y+RSdVdpacB(bVQ zC(JupLfFp8y43%PMj2}T|VS@%LVp>hv4Y!RPMF?pp8U_$xCJ)S zQx!69>bphNTIb9yn*_yfj{N%bY)t{L1cs8<8|!f$;UQ*}IN=2<6lA;x^(`8t?;+ST zh)z4qeYYgZkIy{$4x28O-pugO&gauRh3;lti9)9Pvw+^)0!h~%m&8Q!AKX%urEMnl z?yEz?g#ODn$UM`+Q#$Q!6|zsq_`dLO5YK-6bJM6ya>}H+vnW^h?o$z;V&wvuM$dR& zeEq;uUUh$XR`TWeC$$c&Jjau2it3#%J-y}Qm>nW*s?En?R&6w@sDXMEr#8~$=b(gk zwDC3)NtAP;M2BW_lL^5ShpK$D%@|BnD{=!Tq)o(5@z3i7Z){} zGr}Exom_qDO{kAVkZ*MbLNHE666Kina#D{&>Jy%~w7yX$oj;cYCd^p9zy z8*+wgSEcj$4{WxKmCF(5o7U4jqwEvO&dm1H#7z}%VXAbW&W24v-tS6N3}qrm1OnE)fUkoE8yMMn9S$?IswS88tQWm4#Oid#ckgr6 zRtHm!mfNl-`d>O*1~d7%;~n+{Rph6BBy^95zqI{K((E!iFQ+h*C3EsbxNo_aRm5gj zKYug($r*Q#W9`p%Bf{bi6;IY0v`pB^^qu)gbg9QHQ7 zWBj(a1YSu)~2RK8Pi#C>{DMlrqFb9e_RehEHyI{n?e3vL_}L>kYJC z_ly$$)zFi*SFyNrnOt(B*7E$??s67EO%DgoZL2XNk8iVx~X_)o++4oaK1M|ou73vA0K^503j@uuVmLcHH4ya-kOIDfM%5%(E z+Xpt~#7y2!KB&)PoyCA+$~DXqxPxxALy!g-O?<9+9KTk4Pgq4AIdUkl`1<1#j^cJg zgU3`0hkHj_jxV>`Y~%LAZl^3o0}`Sm@iw7kwff{M%VwtN)|~!p{AsfA6vB5UolF~d zHWS%*uBDt<9y!9v2Xe|au&1j&iR1HXCdyCjxSgG*L{wmTD4(NQ=mFjpa~xooc6kju z`~+d{j7$h-;HAB04H!Zscu^hZffL#9!p$)9>sRI|Yovm)g@F>ZnosF2EgkU3ln0bR zTA}|+E(tt)!SG)-bEJi_0m{l+(cAz^pi}`9=~n?y&;2eG;d9{M6nj>BHGn(KA2n|O zt}$=FPq!j`p&kQ8>cirSzkU0c08%8{^Qyqi-w2LoO8)^E7;;I1;HQ6B$u0nNaX2CY zSmfi)F`m94zL8>#zu;8|{aBui@RzRKBlP1&mfFxEC@%cjl?NBs`cr^nm){>;$g?rhKr$AO&6qV_Wbn^}5tfFBry^e1`%du2~o zs$~dN;S_#%iwwA_QvmMjh%Qo?0?rR~6liyN5Xmej8(*V9ym*T`xAhHih-v$7U}8=dfXi2i*aAB!xM(Xekg*ix@r|ymDw*{*s0?dlVys2e)z62u1 z+k3esbJE=-P5S$&KdFp+2H7_2e=}OKDrf( z9-207?6$@f4m4B+9E*e((Y89!q?zH|mz_vM>kp*HGXldO0Hg#!EtFhRuOm$u8e~a9 z5(roy7m$Kh+zjW6@zw{&20u?1f2uP&boD}$#Zy)4o&T;vyBoqFiF2t;*g=|1=)PxB z8eM3Mp=l_obbc?I^xyLz?4Y1YDWPa+nm;O<$Cn;@ane616`J9OO2r=rZr{I_Kizyc zP#^^WCdIEp*()rRT+*YZK>V@^Zs=ht32x>Kwe zab)@ZEffz;VM4{XA6e421^h~`ji5r%)B{wZu#hD}f3$y@L0JV9f3g{-RK!A?vBUA}${YF(vO4)@`6f1 z-A|}e#LN{)(eXloDnX4Vs7eH|<@{r#LodP@Nz--$Dg_Par%DCpu2>2jUnqy~|J?eZ zBG4FVsz_A+ibdwv>mLp>P!(t}E>$JGaK$R~;fb{O3($y1ssQQo|5M;^JqC?7qe|hg zu0ZOqeFcp?qVn&Qu7FQJ4hcFi&|nR!*j)MF#b}QO^lN%5)4p*D^H+B){n8%VPUzi! zDihoGcP71a6!ab`l^hK&*dYrVYzJ0)#}xVrp!e;lI!+x+bfCN0KXwUAPU9@#l7@0& QuEJmfE|#`Dqx|px0L@K;Y5)KL literal 0 HcmV?d00001 diff --git a/packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.properties b/packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000000..af7be50b1015cb --- /dev/null +++ b/packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/packages/react-native-gradle-plugin/gradlew b/packages/react-native-gradle-plugin/gradlew new file mode 100755 index 00000000000000..744e882ed57263 --- /dev/null +++ b/packages/react-native-gradle-plugin/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MSYS* | MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerMode.java b/packages/react-native-gradle-plugin/settings.gradle.kts similarity index 58% rename from ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerMode.java rename to packages/react-native-gradle-plugin/settings.gradle.kts index 3ed6f114724c8c..7e74af1ef9702a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerMode.java +++ b/packages/react-native-gradle-plugin/settings.gradle.kts @@ -5,11 +5,9 @@ * LICENSE file in the root directory of this source tree. */ -package com.facebook.react.modules.datepicker; - -/** Date picker modes */ -public enum DatePickerMode { - CALENDAR, - SPINNER, - DEFAULT +pluginManagement { + repositories { + gradlePluginPortal() + google() + } } diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/AndroidConfiguration.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/AndroidConfiguration.kt index 0e5cf8f75f273e..b7de384df6d23b 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/AndroidConfiguration.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/AndroidConfiguration.kt @@ -16,7 +16,7 @@ fun Project.configureDevPorts(androidExt: BaseExtension) { project.properties["reactNativeInspectorProxyPort"]?.toString() ?: devServerPort androidExt.buildTypes.all { - resValue("integer", "react_native_dev_server_port", devServerPort) - resValue("integer", "react_native_inspector_proxy_port", inspectorProxyPort) + it.resValue("integer", "react_native_dev_server_port", devServerPort) + it.resValue("integer", "react_native_inspector_proxy_port", inspectorProxyPort) } } diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactAppPlugin.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactAppPlugin.kt index 7b06e9067d1314..54ff34e50950e4 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactAppPlugin.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactAppPlugin.kt @@ -12,25 +12,23 @@ import com.android.build.gradle.BaseExtension import com.android.build.gradle.LibraryExtension import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.kotlin.dsl.create -import org.gradle.kotlin.dsl.getByType class ReactAppPlugin : Plugin { override fun apply(project: Project) { - val config = project.extensions.create("reactApp", project) + val config = project.extensions.create("reactApp", ReactAppExtension::class.java, project) project.afterEvaluate { - val androidConfiguration = extensions.getByType() - configureDevPorts(androidConfiguration) + val androidConfiguration = project.extensions.getByType(BaseExtension::class.java) + project.configureDevPorts(androidConfiguration) - val isAndroidLibrary = plugins.hasPlugin("com.android.library") + val isAndroidLibrary = project.plugins.hasPlugin("com.android.library") val variants = if (isAndroidLibrary) { - extensions.getByType().libraryVariants + project.extensions.getByType(LibraryExtension::class.java).libraryVariants } else { - extensions.getByType().applicationVariants + project.extensions.getByType(AppExtension::class.java).applicationVariants } - variants.all { configureReactTasks(variant = this, config = config) } + variants.all { project.configureReactTasks(variant = it, config = config) } } } } 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 e518d780497ca8..d1a6b4be07bac6 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 @@ -16,8 +16,6 @@ import com.facebook.react.tasks.HermesBinaryTask import java.io.File import org.gradle.api.Project import org.gradle.api.tasks.Copy -import org.gradle.kotlin.dsl.extra -import org.gradle.kotlin.dsl.register private const val REACT_GROUP = "react" @@ -49,17 +47,17 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE val bundleEnabled = variant.checkBundleEnabled(config) val bundleTask = - tasks.register("createBundle${targetName}JsAndAssets") { - val task = this - task.group = REACT_GROUP - task.description = "create JS bundle and assets for $targetName." - - task.reactRoot = config.reactRoot - task.sources = fileTree(config.reactRoot) { setExcludes(config.inputExcludes) } - task.execCommand = execCommand - task.bundleCommand = config.bundleCommand - task.devEnabled = !(variant.name in config.devDisabledInVariants || isRelease) - task.entryFile = config.detectedEntryFile + tasks.register("createBundle${targetName}JsAndAssets", BundleJsAndAssetsTask::class.java) { + it.group = REACT_GROUP + it.description = "create JS bundle and assets for $targetName." + + it.reactRoot = config.reactRoot + it.sources = + fileTree(config.reactRoot) { fileTree -> fileTree.setExcludes(config.inputExcludes) } + it.execCommand = execCommand + it.bundleCommand = config.bundleCommand + it.devEnabled = !(variant.name in config.devDisabledInVariants || isRelease) + it.entryFile = config.detectedEntryFile val extraArgs = mutableListOf() @@ -69,56 +67,54 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE } // Hermes doesn't require JS minification. - if (enableHermes && !devEnabled) { + if (enableHermes && !it.devEnabled) { extraArgs.add("--minify") extraArgs.add("false") } extraArgs.addAll(config.extraPackagerArgs) - task.extraArgs = emptyList() + it.extraArgs = emptyList() - task.jsBundleDir = jsBundleDir - task.jsBundleFile = jsBundleFile - task.resourcesDir = resourcesDir - task.jsIntermediateSourceMapsDir = jsIntermediateSourceMapsDir - task.jsSourceMapsDir = jsSourceMapsDir - task.jsSourceMapsFile = if (enableHermes) jsPackagerSourceMapFile else jsOutputSourceMapFile + it.jsBundleDir = jsBundleDir + it.jsBundleFile = jsBundleFile + it.resourcesDir = resourcesDir + it.jsIntermediateSourceMapsDir = jsIntermediateSourceMapsDir + it.jsSourceMapsDir = jsSourceMapsDir + it.jsSourceMapsFile = if (enableHermes) jsPackagerSourceMapFile else jsOutputSourceMapFile - task.enabled = bundleEnabled + it.enabled = bundleEnabled } val hermesTask = - tasks.register("emit${targetName}HermesResources") { - val task = this - task.group = REACT_GROUP - task.description = "bundle hermes resources for $targetName" - - task.reactRoot = config.reactRoot - task.hermesCommand = config.osAwareHermesCommand - task.hermesFlags = if (isRelease) config.hermesFlagsRelease else config.hermesFlagsDebug - task.jsBundleFile = jsBundleFile - task.composeSourceMapsCommand = nodeExecutableAndArgs + config.composeSourceMapsPath - task.jsPackagerSourceMapFile = jsPackagerSourceMapFile - task.jsCompilerSourceMapFile = jsCompilerSourceMapFile - task.jsOutputSourceMapFile = jsOutputSourceMapFile - - task.dependsOn(bundleTask) - - task.enabled = bundleEnabled && enableHermes + tasks.register("emit${targetName}HermesResources", HermesBinaryTask::class.java) { + it.group = REACT_GROUP + it.description = "bundle hermes resources for $targetName" + + it.reactRoot = config.reactRoot + it.hermesCommand = config.osAwareHermesCommand + it.hermesFlags = if (isRelease) config.hermesFlagsRelease else config.hermesFlagsDebug + it.jsBundleFile = jsBundleFile + it.composeSourceMapsCommand = nodeExecutableAndArgs + config.composeSourceMapsPath + it.jsPackagerSourceMapFile = jsPackagerSourceMapFile + it.jsCompilerSourceMapFile = jsCompilerSourceMapFile + it.jsOutputSourceMapFile = jsOutputSourceMapFile + + it.dependsOn(bundleTask) + + it.enabled = bundleEnabled && enableHermes } val aggregatedBundleTask = tasks.register("bundle${targetName}JsAndAssets") { - val task = this - task.group = REACT_GROUP - task.description = "bundle JS and resources for $targetName" + it.group = REACT_GROUP + it.description = "bundle JS and resources for $targetName" - task.dependsOn(bundleTask, hermesTask) + it.dependsOn(bundleTask, hermesTask) // this was exposed before, do we still need it? - task.extra["generatedResFolders"] = files(resourcesDir).builtBy(task) - task.extra["generatedAssetsFolders"] = files(jsBundleDir).builtBy(task) + it.extensions.extraProperties["generatedResFolders"] = files(resourcesDir).builtBy(it) + it.extensions.extraProperties["generatedAssetsFolders"] = files(jsBundleDir).builtBy(it) } val generatedResFolders = files(resourcesDir).builtBy(aggregatedBundleTask) @@ -140,16 +136,16 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE val resourcesDirConfigValue = config.resourcesDir[variant.name] if (resourcesDirConfigValue != null) { val currentCopyResTask = - tasks.register("copy${targetName}BundledResources") { - group = "react" - description = "copy bundled resources into custom location for $targetName." + tasks.register("copy${targetName}BundledResources", Copy::class.java) { + it.group = "react" + it.description = "copy bundled resources into custom location for $targetName." - from(resourcesDir) - into(file(resourcesDirConfigValue)) + it.from(resourcesDir) + it.into(file(resourcesDirConfigValue)) - dependsOn(bundleTask) + it.dependsOn(bundleTask) - enabled = bundleEnabled + it.enabled = bundleEnabled } packageTask.dependsOn(currentCopyResTask) @@ -158,27 +154,27 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE packageTask.configure { if (config.enableVmCleanup) { - doFirst { cleanupVMFiles(enableHermes, isRelease, targetPath) } + it.doFirst { cleanupVMFiles(enableHermes, isRelease, targetPath) } } } val currentAssetsCopyTask = - tasks.register("copy${targetName}BundledJs") { - group = "react" - description = "copy bundled JS into $targetName." + tasks.register("copy${targetName}BundledJs", Copy::class.java) { + it.group = "react" + it.description = "copy bundled JS into $targetName." - from(jsBundleDir) + it.from(jsBundleDir) val jsBundleDirConfigValue = config.jsBundleDir[targetName] if (jsBundleDirConfigValue != null) { - into(jsBundleDirConfigValue) + it.into(jsBundleDirConfigValue) } else { - into(mergeAssetsTask.map { it.outputDir.get() }) + it.into(mergeAssetsTask.map { mergeFoldersTask -> mergeFoldersTask.outputDir.get() }) } - dependsOn(mergeAssetsTask) + it.dependsOn(mergeAssetsTask) - enabled = bundleEnabled + it.enabled = bundleEnabled } // mergeResources task runs before the bundle file is copied to the intermediate asset directory @@ -200,27 +196,27 @@ private fun Project.cleanupVMFiles(enableHermes: Boolean, isRelease: Boolean, ta fileTree(libDir) { if (enableHermes) { // For Hermes, delete all the libjsc* files - include("**/libjsc*.so") + it.include("**/libjsc*.so") if (isRelease) { // Reduce size by deleting the debugger/inspector - include("**/libhermes-inspector.so") - include("**/libhermes-executor-debug.so") + it.include("**/libhermes-inspector.so") + it.include("**/libhermes-executor-debug.so") } else { // Release libs take precedence and must be removed // to allow debugging - include("**/libhermes-executor-release.so") + it.include("**/libhermes-executor-release.so") } } else { // For JSC, delete all the libhermes* files - include("**/libhermes*.so") + it.include("**/libhermes*.so") } } - .visit { + .visit { visit -> val targetVariant = ".*/transforms/[^/]*/$targetPath/.*".toRegex() - val path = file.absolutePath.replace(File.separatorChar, '/') - if (path.matches(targetVariant) && file.isFile()) { - file.delete() + val path = visit.file.absolutePath.replace(File.separatorChar, '/') + if (path.matches(targetVariant) && visit.file.isFile) { + visit.file.delete() } } } diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleJsAndAssetsTask.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleJsAndAssetsTask.kt index 086f2515f98d13..d5f10172767f66 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleJsAndAssetsTask.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleJsAndAssetsTask.kt @@ -11,13 +11,16 @@ import java.io.File import org.gradle.api.DefaultTask import org.gradle.api.file.FileTree import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction open class BundleJsAndAssetsTask : DefaultTask() { - internal lateinit var reactRoot: File + + @get:Internal internal lateinit var reactRoot: File @get:InputFiles @Suppress("UNUSED") // used to invalidate caches @@ -25,7 +28,7 @@ open class BundleJsAndAssetsTask : DefaultTask() { @get:Input internal lateinit var execCommand: List @get:Input internal lateinit var bundleCommand: String @get:Input internal var devEnabled: Boolean = true - @get:Input internal lateinit var entryFile: File + @get:InputFile internal lateinit var entryFile: File @get:Input internal var extraArgs: List = emptyList() @get:OutputDirectory internal lateinit var jsBundleDir: File @@ -50,10 +53,10 @@ open class BundleJsAndAssetsTask : DefaultTask() { private fun executeBundleCommand() { project.exec { - workingDir(reactRoot) + it.workingDir(reactRoot) @Suppress("SpreadOperator") - windowsAwareCommandLine( + it.windowsAwareCommandLine( *execCommand.toTypedArray(), bundleCommand, "--platform", diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/HermesBinaryTask.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/HermesBinaryTask.kt index 0e641dea7ad8ad..9a410462dde643 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/HermesBinaryTask.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/HermesBinaryTask.kt @@ -11,18 +11,20 @@ import java.io.File import org.gradle.api.DefaultTask import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.Internal import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction open class HermesBinaryTask : DefaultTask() { - internal lateinit var reactRoot: File + + @get:Internal internal lateinit var reactRoot: File @get:Input internal lateinit var hermesCommand: String @get:Input internal var hermesFlags: List = emptyList() @get:InputFile internal lateinit var jsBundleFile: File @get:Input internal lateinit var composeSourceMapsCommand: List - @get:Input internal lateinit var jsPackagerSourceMapFile: File + @get:InputFile internal lateinit var jsPackagerSourceMapFile: File @get:OutputFile internal lateinit var jsCompilerSourceMapFile: File @get:OutputFile internal lateinit var jsOutputSourceMapFile: File @@ -43,7 +45,7 @@ open class HermesBinaryTask : DefaultTask() { private fun emitHermesBinary(outputFile: File) { project.exec { @Suppress("SpreadOperator") - windowsAwareCommandLine( + it.windowsAwareCommandLine( hermesCommand, "-emit-binary", "-out", @@ -55,10 +57,10 @@ open class HermesBinaryTask : DefaultTask() { private fun composeSourceMaps() { project.exec { - workingDir(reactRoot) + it.workingDir(reactRoot) @Suppress("SpreadOperator") - windowsAwareCommandLine( + it.windowsAwareCommandLine( *composeSourceMapsCommand.toTypedArray(), jsPackagerSourceMapFile, jsCompilerSourceMapFile, diff --git a/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec b/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec new file mode 100644 index 00000000000000..bfa423f63e04fa --- /dev/null +++ b/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec @@ -0,0 +1,39 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +require "json" + +package = JSON.parse(File.read(File.join(__dir__, "../package.json"))) + +folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' +folly_version = '2021.06.28.00' + +Pod::Spec.new do |s| + s.name = "ScreenshotManager" + s.version = package["version"] + s.summary = package["description"] + s.description = "ScreenshotManager" + s.homepage = "https://github.com/facebook/react-native.git" + s.license = "MIT" + s.platforms = { :ios => "11.0", :tvos => "11.0" } + s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' + s.author = "Facebook, Inc. and its affiliates" + s.source = { :git => "https://github.com/facebook/react-native.git", :tag => "#{s.version}" } + + s.source_files = "**/*.{h,m,mm,swift}" + s.requires_arc = true + + s.dependency "React" + s.dependency "RCT-Folly", folly_version + + # s.dependency "..." + + # Enable codegen for this library + use_react_native_codegen!(s, { + :react_native_path => "../../..", + :js_srcs_dir => "./", + :output_dir => "./" + }) +end diff --git a/packages/rn-tester/Podfile b/packages/rn-tester/Podfile index ae885b01454857..b7492364d7204e 100644 --- a/packages/rn-tester/Podfile +++ b/packages/rn-tester/Podfile @@ -37,6 +37,9 @@ def pods() pod 'React-RCTPushNotification', :path => "#{prefix_path}/Libraries/PushNotificationIOS" pod 'Yoga', :path => "#{prefix_path}/ReactCommon/yoga", :modular_headers => true # Additional Pods which are classed as unstable + + # RNTester native modules and components + pod 'ScreenshotManager', :path => "NativeModuleExample" end target 'RNTester' do @@ -58,4 +61,5 @@ end post_install do |installer| react_native_post_install(installer) + __apply_Xcode_12_5_M1_post_install_workaround(installer) end diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 52b05d0344bba5..265d84a18552fd 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -704,6 +704,9 @@ PODS: - React-logger (= 1000.0.0) - React-perflogger (= 1000.0.0) - ReactCommon/turbomodule/core (= 1000.0.0) + - ScreenshotManager (0.0.1): + - RCT-Folly (= 2021.06.28.00) + - React - Yoga (1.14.0) - YogaKit (1.18.1): - Yoga (~> 1.14) @@ -735,6 +738,7 @@ DEPENDENCIES: - FlipperKit/FlipperKitUserDefaultsPlugin (= 0.99.0) - FlipperKit/SKIOSNetworkPlugin (= 0.99.0) - glog (from `../../third-party-podspecs/glog.podspec`) + - OpenSSL-Universal (= 1.1.180) - RCT-Folly (from `../../third-party-podspecs/RCT-Folly.podspec`) - RCT-Folly/Fabric (from `../../third-party-podspecs/RCT-Folly.podspec`) - RCTRequired (from `../../Libraries/RCTRequired`) @@ -769,6 +773,7 @@ DEPENDENCIES: - React-runtimeexecutor (from `../../ReactCommon/runtimeexecutor`) - ReactCommon/turbomodule/core (from `../../ReactCommon`) - ReactCommon/turbomodule/samples (from `../../ReactCommon`) + - ScreenshotManager (from `NativeModuleExample`) - Yoga (from `../../ReactCommon/yoga`) SPEC REPOS: @@ -857,6 +862,8 @@ EXTERNAL SOURCES: :path: "../../ReactCommon/runtimeexecutor" ReactCommon: :path: "../../ReactCommon" + ScreenshotManager: + :path: NativeModuleExample Yoga: :path: "../../ReactCommon/yoga" @@ -908,9 +915,10 @@ SPEC CHECKSUMS: React-RCTVibration: 1a58f6ab1ae5fad004119979b676cb5e912f2e44 React-runtimeexecutor: 4b0c6eb341c7d3ceb5e2385cb0fdb9bf701024f3 ReactCommon: 632474905edd9a20ec4f4084142ff4b4a4f3fd8b + ScreenshotManager: a23f618c2a205e3087f29b05154a7c3d6e515d8a Yoga: c0d06f5380d34e939f55420669a60fe08b79bd75 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: 6e910a576b7db9347c60dfc58f7852f692200116 +PODFILE CHECKSUM: 5cc47caddf8a8bf3fe9ea873886352846aee027a COCOAPODS: 1.10.1 diff --git a/packages/rn-tester/README.md b/packages/rn-tester/README.md index 3043578eddc190..5f5e1d7c2065dc 100644 --- a/packages/rn-tester/README.md +++ b/packages/rn-tester/README.md @@ -24,9 +24,12 @@ You'll need to have all the [prerequisites](https://github.com/facebook/react-na Start an Android emulator. - cd react-native - ./gradlew :packages:rn-tester:android:app:installJscDebug - ./scripts/packager.sh +```sh +cd react-native +# In order to use Hermes engine, run `installHermesDebug` instead. +./gradlew :packages:rn-tester:android:app:installJscDebug +./scripts/packager.sh +``` _Note: Building for the first time can take a while._ diff --git a/packages/rn-tester/RNTester/AppDelegate.mm b/packages/rn-tester/RNTester/AppDelegate.mm index dc5d65c1cfaddd..74a8c35dd83125 100644 --- a/packages/rn-tester/RNTester/AppDelegate.mm +++ b/packages/rn-tester/RNTester/AppDelegate.mm @@ -206,6 +206,7 @@ - (Class)getModuleClassFromName:(const char *)name - (id)getModuleInstanceFromClass:(Class)moduleClass { + // Set up the default RCTImageLoader and RCTNetworking modules. if (moduleClass == RCTImageLoader.class) { return [[moduleClass alloc] initWithRedirectDelegate:nil loadersProvider:^NSArray> *(RCTModuleRegistry * moduleRegistry) { diff --git a/packages/rn-tester/RNTester/Info.plist b/packages/rn-tester/RNTester/Info.plist index 13573d49b86602..788e4d6193c8d5 100644 --- a/packages/rn-tester/RNTester/Info.plist +++ b/packages/rn-tester/RNTester/Info.plist @@ -2,6 +2,14 @@ + LSApplicationQueriesSchemes + + tel + telprompt + http + fb + geo + UIStatusBarStyle UIStatusBarStyleBlackTranslucent CFBundleDevelopmentRegion diff --git a/packages/rn-tester/RNTesterIntegrationTests/RCTRootViewIntegrationTests.m b/packages/rn-tester/RNTesterIntegrationTests/RCTRootViewIntegrationTests.m index a6d374f935a2c7..336168197f1c8d 100644 --- a/packages/rn-tester/RNTesterIntegrationTests/RCTRootViewIntegrationTests.m +++ b/packages/rn-tester/RNTesterIntegrationTests/RCTRootViewIntegrationTests.m @@ -48,9 +48,9 @@ - (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [rootView.bridge.eventDispatcher sendAppEventWithName:@"rootViewDidChangeIntrinsicSize" - body:@{@"width": @(rootView.intrinsicSize.width), - @"height": @(rootView.intrinsicSize.height)}]; + [rootView.eventDispatcher sendAppEventWithName:@"rootViewDidChangeIntrinsicSize" + body:@{@"width": @(rootView.intrinsicSize.width), + @"height": @(rootView.intrinsicSize.height)}]; #pragma clang diagnostic pop } diff --git a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj index 334d7ae082ad04..51a0c03e36c040 100644 --- a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj +++ b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj @@ -321,7 +321,6 @@ C38CB0C2095A8FFDE13321E5 /* Pods-RNTesterUnitTests.debug.xcconfig */, 8735BC063632C9712E25C7D9 /* Pods-RNTesterUnitTests.release.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -610,7 +609,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -e\n\nexport NODE_BINARY=node\nexport PROJECT_ROOT=\"$SRCROOT/../../\"\nexport SOURCEMAP_FILE=../sourcemap.ios.map\n# export FORCE_BUNDLING=true\n\"$SRCROOT/../../scripts/react-native-xcode.sh\" $SRCROOT/../../packages/rn-tester/js/RNTesterApp.ios.js\n"; + shellScript = "set -e\n\nexport NODE_BINARY=node\nexport PROJECT_ROOT=\"$SRCROOT/../../\"\nexport ENTRY_FILE=\"$SRCROOT/js/RNTesterApp.ios.js\"\nexport SOURCEMAP_FILE=../sourcemap.ios.map\n# export FORCE_BUNDLING=true\n\"$SRCROOT/../../scripts/react-native-xcode.sh\"\n"; }; A2FBDDDD0C26B4EFA3726B6C /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; @@ -784,6 +783,7 @@ "@executable_path/Frameworks", ); LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", "$(inherited)", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", @@ -818,6 +818,7 @@ "@executable_path/Frameworks", ); LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", "$(inherited)", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", diff --git a/packages/rn-tester/RNTesterUnitTests/RCTBundleURLProviderTests.m b/packages/rn-tester/RNTesterUnitTests/RCTBundleURLProviderTests.m index 774aa2c6859816..309ccaa6a15663 100644 --- a/packages/rn-tester/RNTesterUnitTests/RCTBundleURLProviderTests.m +++ b/packages/rn-tester/RNTesterUnitTests/RCTBundleURLProviderTests.m @@ -97,7 +97,7 @@ - (void)testLocalhostURL - (void)testIPURL { id classMock = OCMClassMock([RCTBundleURLProvider class]); - [[[classMock stub] andReturnValue:@YES] isPackagerRunning:[OCMArg any]]; + [[[classMock stub] andReturnValue:@YES] isPackagerRunning:[OCMArg any] scheme:[OCMArg any]]; RCTBundleURLProvider *settings = [RCTBundleURLProvider sharedSettings]; settings.jsLocation = @"192.168.1.1"; NSURL *URL = [settings jsBundleURLForBundleRoot:testFile fallbackResource:nil]; diff --git a/packages/rn-tester/RNTesterUnitTests/RCTFontTests.m b/packages/rn-tester/RNTesterUnitTests/RCTFontTests.m index bb8f19b0383535..650b14f5151484 100644 --- a/packages/rn-tester/RNTesterUnitTests/RCTFontTests.m +++ b/packages/rn-tester/RNTesterUnitTests/RCTFontTests.m @@ -20,7 +20,7 @@ @implementation RCTFontTests // will be different objects, but the same font, so this macro now explicitly // checks that fontName (which includes the style) and pointSize are equal. #define RCTAssertEqualFonts(font1, font2) { \ - XCTAssertTrue([font1.fontName isEqualToString:font2.fontName]); \ + XCTAssertEqualObjects(font1.fontName, font2.fontName); \ XCTAssertEqual(font1.pointSize,font2.pointSize); \ } diff --git a/packages/rn-tester/android/app/build.gradle b/packages/rn-tester/android/app/build.gradle index 7f04213604bfff..503ada4fd87eef 100644 --- a/packages/rn-tester/android/app/build.gradle +++ b/packages/rn-tester/android/app/build.gradle @@ -288,6 +288,7 @@ if (enableCodegen) { def packageReactNdkLibs = tasks.register("packageReactNdkLibs", Copy) { // TODO: handle extracting .so from prebuilt :ReactAndroid. dependsOn(":ReactAndroid:packageReactNdkLibs") + dependsOn("generateCodegenSchemaFromJavaScript") from("$reactAndroidBuildDir/react-ndk/exported") into("$buildDir/react-ndk/exported") } diff --git a/packages/rn-tester/js/components/ListExampleShared.js b/packages/rn-tester/js/components/ListExampleShared.js index 2312ee69c22f93..158590e4ad3e6d 100644 --- a/packages/rn-tester/js/components/ListExampleShared.js +++ b/packages/rn-tester/js/components/ListExampleShared.js @@ -57,13 +57,14 @@ class ItemComponent extends React.PureComponent<{ onPress: (key: string) => void, onShowUnderlay?: () => void, onHideUnderlay?: () => void, + textSelectable?: ?boolean, ... }> { _onPress = () => { this.props.onPress(this.props.item.key); }; render(): React.Node { - const {fixedHeight, horizontal, item} = this.props; + const {fixedHeight, horizontal, item, textSelectable} = this.props; const itemHash = Math.abs(hashCode(item.title)); const imgSource = THUMB_URLS[itemHash % THUMB_URLS.length]; return ( @@ -81,6 +82,7 @@ class ItemComponent extends React.PureComponent<{ {!item.noImage && } {item.title} - {item.text} diff --git a/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js b/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js index 001464fd63d91e..6133080a4adfd0 100644 --- a/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js +++ b/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js @@ -1024,6 +1024,72 @@ class EnabledExample extends React.Component< } } +class DisplayOptionsStatusExample extends React.Component<{}> { + render(): React.Node { + const isAndroid = Platform.OS === 'android'; + return ( + + + + {isAndroid ? null : ( + <> + + + + + + )} + + ); + } +} + +function DisplayOptionStatusExample({optionName, optionChecker, notification}) { + const [statusEnabled, setStatusEnabled] = React.useState(false); + React.useEffect(() => { + AccessibilityInfo.addEventListener(notification, setStatusEnabled); + optionChecker().then(isEnabled => { + setStatusEnabled(isEnabled); + }); + return function cleanup() { + AccessibilityInfo.removeEventListener(notification, setStatusEnabled); + }; + }, [optionChecker, notification]); + return ( + + + {optionName} + {' is '} + {statusEnabled ? 'enabled' : 'disabled'}. + + + ); +} + exports.title = 'Accessibility'; exports.documentationURL = 'https://reactnative.dev/docs/accessibilityinfo'; exports.description = 'Examples of using Accessibility APIs.'; @@ -1058,6 +1124,12 @@ exports.examples = [ return ; }, }, + { + title: 'Check if the display options are enabled', + render(): React.Element { + return ; + }, + }, { title: 'Check if the screen reader announces', render(): React.Element { diff --git a/packages/rn-tester/js/examples/FlatList/FlatListExample.js b/packages/rn-tester/js/examples/FlatList/FlatListExample.js index 4606d68090c628..93d7eb2de4be32 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatListExample.js +++ b/packages/rn-tester/js/examples/FlatList/FlatListExample.js @@ -59,6 +59,8 @@ type State = {| empty: boolean, useFlatListItemComponent: boolean, fadingEdgeLength: number, + onPressDisabled: boolean, + textSelectable: boolean, |}; class FlatListExample extends React.PureComponent { @@ -74,6 +76,8 @@ class FlatListExample extends React.PureComponent { empty: false, useFlatListItemComponent: false, fadingEdgeLength: 0, + onPressDisabled: false, + textSelectable: true, }; _onChangeFilterText = filterText => { @@ -161,6 +165,16 @@ class FlatListExample extends React.PureComponent { this.state.debug, this._setBooleanValue('debug'), )} + {renderSmallSwitchOption( + 'onPress Disabled', + this.state.onPressDisabled, + this._setBooleanValue('onPressDisabled'), + )} + {renderSmallSwitchOption( + 'Text Selectable', + this.state.textSelectable, + this._setBooleanValue('textSelectable'), + )} {renderSmallSwitchOption( 'Use FlatListItemComponent', this.state.useFlatListItemComponent, @@ -236,6 +250,12 @@ class FlatListExample extends React.PureComponent { data: state.data.concat(genItemData(100, state.data.length)), })); }; + _onPressCallback = () => { + const {onPressDisabled} = this.state; + const warning = () => console.log('onPress disabled'); + const onPressAction = onPressDisabled ? warning : this._pressItem; + return onPressAction; + }; _onRefresh = () => Alert.alert('onRefresh: nothing to refresh :P'); _renderItemComponent = () => { const flatListPropKey = this.state.useFlatListItemComponent @@ -253,9 +273,10 @@ class FlatListExample extends React.PureComponent { item={item} horizontal={this.state.horizontal} fixedHeight={this.state.fixedHeight} - onPress={this._pressItem} + onPress={this._onPressCallback()} onShowUnderlay={separators.highlight} onHideUnderlay={separators.unhighlight} + textSelectable={this.state.textSelectable} /> ); }, diff --git a/packages/rn-tester/js/examples/Linking/LinkingExample.js b/packages/rn-tester/js/examples/Linking/LinkingExample.js index 02f883a644dbd4..cd0c9eabf8ebe2 100644 --- a/packages/rn-tester/js/examples/Linking/LinkingExample.js +++ b/packages/rn-tester/js/examples/Linking/LinkingExample.js @@ -11,6 +11,7 @@ const React = require('react'); const { + Button, Linking, Platform, StyleSheet, @@ -48,6 +49,16 @@ class OpenURLButton extends React.Component { } } +class OpenSettingsExample extends React.Component { + openSettings() { + Linking.openSettings(); + } + + render() { + return