From 527ac2f2c5fc57e1eacae03a021ce78ebfe30270 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Fri, 16 Sep 2022 08:25:34 -0700 Subject: [PATCH 01/54] JS: Upgrade to `yargs@^17.5.1` Summary: Upgrades all of our JavaScript tooling to use `yargs@^17.5.1`. Of all [release notes](https://github.com/yargs/yargs/releases), these are the major version notes: - [v17.0.0](https://github.com/yargs/yargs/releases/tag/v17.0.0) - [v16.0.0](https://github.com/yargs/yargs/releases/tag/v16.0.0) A cursory inspection suggests that these breaking changes are unlikely to seriously impact our use cases (or can be fixed forward). Changelog: [Internal] Reviewed By: huntie Differential Revision: D39550338 fbshipit-source-id: 5b2c5265f8c7a95ab0cc9bab62873f9e4355f32f --- .../inspector/tools/msggen/package.json | 2 +- .../hermes/inspector/tools/msggen/yarn.lock | 138 ++++++++---------- repo-config/package.json | 2 +- yarn.lock | 20 ++- 4 files changed, 84 insertions(+), 78 deletions(-) diff --git a/ReactCommon/hermes/inspector/tools/msggen/package.json b/ReactCommon/hermes/inspector/tools/msggen/package.json index b3dcba4544fbe1..746300c3634403 100644 --- a/ReactCommon/hermes/inspector/tools/msggen/package.json +++ b/ReactCommon/hermes/inspector/tools/msggen/package.json @@ -13,7 +13,7 @@ }, "dependencies": { "devtools-protocol": "0.0.959523", - "yargs": "^14.2.0" + "yargs": "^17.5.1" }, "devDependencies": { "@babel/cli": "^7.2.0", diff --git a/ReactCommon/hermes/inspector/tools/msggen/yarn.lock b/ReactCommon/hermes/inspector/tools/msggen/yarn.lock index cf72d2b1e3fc6b..bafb876d32c76d 100644 --- a/ReactCommon/hermes/inspector/tools/msggen/yarn.lock +++ b/ReactCommon/hermes/inspector/tools/msggen/yarn.lock @@ -1501,17 +1501,17 @@ ansi-escapes@^4.2.1: dependencies: type-fest "^0.21.3" -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - ansi-regex@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== -ansi-styles@^3.2.0, ansi-styles@^3.2.1: +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -2088,15 +2088,6 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - cliui@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" @@ -2106,6 +2097,15 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -2516,11 +2516,6 @@ emittery@^0.7.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.2.tgz#25595908e13af0f5674ab419396e2fb394cdfa82" integrity sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ== -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -2901,7 +2896,7 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -3278,11 +3273,6 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -5400,15 +5390,6 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - string-width@^4.1.0, string-width@^4.2.0: version "4.2.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" @@ -5418,6 +5399,15 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" +string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -5432,13 +5422,6 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - strip-ansi@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" @@ -5446,6 +5429,13 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-bom@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" @@ -5969,15 +5959,6 @@ worker-farm@^1.7.0: dependencies: errno "~0.1.7" -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -5987,6 +5968,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -6027,6 +6017,11 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" @@ -6037,14 +6032,6 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@^15.0.0: - version "15.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.0.tgz#cdd7a97490ec836195f59f3f4dbe5ea9e8f75f08" - integrity sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@^18.1.2: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" @@ -6053,22 +6040,10 @@ yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs@^14.2.0: - version "14.2.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.2.tgz#2769564379009ff8597cdd38fba09da9b493c4b5" - integrity sha512-/4ld+4VV5RnrynMhPZJ/ZpOCGSCeghMykZ3BhdFBDa9Wy/RH6uEGNWDJog+aUlq+9OM1CFTgtYRW5Is1Po9NOA== - dependencies: - cliui "^5.0.0" - decamelize "^1.2.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^15.0.0" +yargs-parser@^21.0.0: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== yargs@^15.4.1: version "15.4.1" @@ -6086,3 +6061,16 @@ yargs@^15.4.1: which-module "^2.0.0" y18n "^4.0.0" yargs-parser "^18.1.2" + +yargs@^17.5.1: + version "17.5.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.5.1.tgz#e109900cab6fcb7fd44b1d8249166feb0b36e58e" + integrity sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.0.0" diff --git a/repo-config/package.json b/repo-config/package.json index 3de138876ac296..596c3a1b0eeda8 100644 --- a/repo-config/package.json +++ b/repo-config/package.json @@ -47,7 +47,7 @@ "shelljs": "^0.8.5", "signedsource": "^1.0.0", "ws": "^6.1.4", - "yargs": "^15.3.1" + "yargs": "^17.5.1" }, "devDependencies": { "mock-fs": "^5.1.4" diff --git a/yarn.lock b/yarn.lock index 2cf6688e509407..a4b2ca2fa3713e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8039,7 +8039,7 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -string-width@^4.1.0, string-width@^4.2.0: +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -8809,6 +8809,11 @@ yargs-parser@^20.2.2: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== +yargs-parser@^21.0.0: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + yargs@^15.1.0, yargs@^15.3.1: version "15.4.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" @@ -8839,6 +8844,19 @@ yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" +yargs@^17.5.1: + version "17.5.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.5.1.tgz#e109900cab6fcb7fd44b1d8249166feb0b36e58e" + integrity sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.0.0" + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" From 2aba3522ab7dfe113ec26131b747f7f6f0486194 Mon Sep 17 00:00:00 2001 From: Adrian Hartanto Date: Fri, 16 Sep 2022 08:54:05 -0700 Subject: [PATCH 02/54] fix: adjust clipboard mock (#34672) Summary: Currently, Clipboard's methods (setString, getString) can't be asserted when writing tests as the mock targeted `Libraries/BatchedBridge/NativeModules` instead of `Libraries/Components/Clipboard/Clipboard` that's used on react-native [entry point](https://github.com/facebook/react-native/blob/main/index.js#L270) so it won't be considered as `mock function`. ## Changelog [General] [Changed] - Update `Clipboard` mock path Pull Request resolved: https://github.com/facebook/react-native/pull/34672 Test Plan: ```js // App-test.js import { Clipboard } from 'react-native'; import React from 'react'; it('renders correctly', () => { Clipboard.setString('string'); expect(Clipboard.setString).toBeCalled(); }); ``` ### before Screen Shot 2022-09-13 at 16 24 30 ### after Screen Shot 2022-09-13 at 16 26 34 Reviewed By: yungsters Differential Revision: D39575916 Pulled By: cortinico fbshipit-source-id: 34a3f93986a18d349ac033bb13a10ed77689935c --- jest/setup.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jest/setup.js b/jest/setup.js index baacd7ebef4e79..3738bd2c61e516 100644 --- a/jest/setup.js +++ b/jest/setup.js @@ -135,6 +135,10 @@ jest getRecommendedTimeoutMillis: jest.fn(), }, })) + .mock('../Libraries/Components/Clipboard/Clipboard', () => ({ + getString: jest.fn(() => ''), + setString: jest.fn(), + })) .mock('../Libraries/Components/RefreshControl/RefreshControl', () => jest.requireActual( '../Libraries/Components/RefreshControl/__mocks__/RefreshControlMock', @@ -201,10 +205,6 @@ jest process.nextTick(() => callback(null, [])), ), }, - Clipboard: { - getString: jest.fn(() => ''), - setString: jest.fn(), - }, DeviceInfo: { getConstants() { return { From c9966e417d9bec2e7f0dafc3094e129e737f7e97 Mon Sep 17 00:00:00 2001 From: Luna Wei Date: Fri, 16 Sep 2022 11:46:00 -0700 Subject: [PATCH 03/54] Alert Summary: Changelog: [Internal] Add flow declaration for Alert. Couldn't figure out how to do type statics on interfaces in Flow. Reviewed By: yungsters Differential Revision: D39186533 fbshipit-source-id: 928ee76080490a133c9773d2330473a688e0612d --- Libraries/Alert/Alert.js.flow | 49 +++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Libraries/Alert/Alert.js.flow diff --git a/Libraries/Alert/Alert.js.flow b/Libraries/Alert/Alert.js.flow new file mode 100644 index 00000000000000..be6f948f557add --- /dev/null +++ b/Libraries/Alert/Alert.js.flow @@ -0,0 +1,49 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + +export type AlertType = + | 'default' + | 'plain-text' + | 'secure-text' + | 'login-password'; +export type AlertButtonStyle = 'default' | 'cancel' | 'destructive'; +export type Buttons = Array<{ + text?: string, + onPress?: ?Function, + isPreferred?: boolean, + style?: AlertButtonStyle, + ... +}>; +type Options = { + cancelable?: ?boolean, + userInterfaceStyle?: 'unspecified' | 'light' | 'dark', + onDismiss?: ?() => void, + ... +}; + +declare class Alert { + static alert( + title: ?string, + message?: ?string, + buttons?: Buttons, + options?: Options, + ): void; + static prompt( + title: ?string, + message?: ?string, + callbackOrButtons?: ?(((text: string) => void) | Buttons), + type?: ?AlertType, + defaultValue?: string, + keyboardType?: string, + options?: Options, + ): void; +} + +module.exports = Alert; From 85e9b073cbaf7dc8b37ea2359cd1f819ccebb6c7 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Fri, 16 Sep 2022 12:33:15 -0700 Subject: [PATCH 04/54] Move react/fabric/components -> react/cxxcomponents Summary: This diff moves Component and ComponentManager classes -> react/cxxcomponents. The purpose is to be able to use these classes from any platform, not only Android changelog: [internal] internal Reviewed By: cortinico Differential Revision: D39531533 fbshipit-source-id: 4732aa7bf59d82dae11441212975f0e225c6d458 --- ReactAndroid/src/main/jni/CMakeLists.txt | 1 + .../src/main/jni/react/cxxcomponents/BUCK | 46 +++++++++++++++++++ .../jni/react/cxxcomponents/CMakeLists.txt | 22 +++++++++ .../{fabric => cxxcomponents}/Component.h | 0 .../ComponentManager.h | 2 +- ReactAndroid/src/main/jni/react/fabric/BUCK | 1 + .../src/main/jni/react/fabric/CMakeLists.txt | 1 + .../react/fabric/ComponentRegistryResolver.h | 2 +- .../jni/react/fabric/CppComponentRegistry.h | 4 +- 9 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 ReactAndroid/src/main/jni/react/cxxcomponents/BUCK create mode 100644 ReactAndroid/src/main/jni/react/cxxcomponents/CMakeLists.txt rename ReactAndroid/src/main/jni/react/{fabric => cxxcomponents}/Component.h (100%) rename ReactAndroid/src/main/jni/react/{fabric => cxxcomponents}/ComponentManager.h (92%) diff --git a/ReactAndroid/src/main/jni/CMakeLists.txt b/ReactAndroid/src/main/jni/CMakeLists.txt index 3eaf2652eccc75..4de03502c658e5 100644 --- a/ReactAndroid/src/main/jni/CMakeLists.txt +++ b/ReactAndroid/src/main/jni/CMakeLists.txt @@ -93,6 +93,7 @@ add_react_android_subdir(src/main/jni/first-party/fbjni) add_react_android_subdir(src/main/jni/first-party/fb) add_react_android_subdir(src/main/jni/first-party/fbgloginit) add_react_android_subdir(src/main/jni/first-party/yogajni) +add_react_android_subdir(src/main/jni/react/cxxcomponents) add_react_android_subdir(src/main/jni/react/jni) add_react_android_subdir(src/main/jni/react/reactperflogger) add_react_android_subdir(src/main/jni/react/jscexecutor) diff --git a/ReactAndroid/src/main/jni/react/cxxcomponents/BUCK b/ReactAndroid/src/main/jni/react/cxxcomponents/BUCK new file mode 100644 index 00000000000000..1f6f4597038d8c --- /dev/null +++ b/ReactAndroid/src/main/jni/react/cxxcomponents/BUCK @@ -0,0 +1,46 @@ +load( + "//tools/build_defs/oss:rn_defs.bzl", + "ANDROID", + "APPLE", + "CXX", + "react_native_xplat_target", + "rn_xplat_cxx_library", + "subdir_glob", +) + +rn_xplat_cxx_library( + name = "components", + srcs = glob( + ["**/*.cpp"], + ), + headers = glob( + ["**/*.h"], + ), + header_namespace = "", + exported_headers = subdir_glob( + [ + ("", "**/*.h"), + ], + prefix = "react/cxxcomponents", + ), + force_static = True, + labels = [ + "pfh:ReactNative_CommonInfrastructurePlaceholder", + "supermodule:xplat/default/public.react_native.infra", + ], + platforms = (APPLE, ANDROID, CXX), + preprocessor_flags = [ + "-DLOG_TAG=\"ReactNative\"", + "-DWITH_FBSYSTRACE=1", + ], + soname = "libcxxcomponents.$(ext)", + tests = [":tests"], + visibility = ["PUBLIC"], + deps = [ + "//third-party/glog:glog", + "//xplat/fbsystrace:fbsystrace", + "//xplat/folly:memory", + "//xplat/folly:molly", + react_native_xplat_target("react/renderer/core:core"), + ], +) diff --git a/ReactAndroid/src/main/jni/react/cxxcomponents/CMakeLists.txt b/ReactAndroid/src/main/jni/react/cxxcomponents/CMakeLists.txt new file mode 100644 index 00000000000000..b60af533acb358 --- /dev/null +++ b/ReactAndroid/src/main/jni/react/cxxcomponents/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +cmake_minimum_required(VERSION 3.13) +set(CMAKE_VERBOSE_MAKEFILE on) + +add_compile_options( + -fexceptions + -frtti + -std=c++17 + -Wall + -Wpedantic + -Wno-gnu-zero-variadic-macro-arguments) + +file(GLOB_RECURSE cxxcomponents_SRC CONFIGURE_DEPENDS *.cpp *.h) + +add_library(cxxcomponents SHARED ${cxxcomponents_SRC}) + +target_include_directories(cxxcomponents PUBLIC .) +set_target_properties(cxxcomponents PROPERTIES LINKER_LANGUAGE CXX) diff --git a/ReactAndroid/src/main/jni/react/fabric/Component.h b/ReactAndroid/src/main/jni/react/cxxcomponents/Component.h similarity index 100% rename from ReactAndroid/src/main/jni/react/fabric/Component.h rename to ReactAndroid/src/main/jni/react/cxxcomponents/Component.h diff --git a/ReactAndroid/src/main/jni/react/fabric/ComponentManager.h b/ReactAndroid/src/main/jni/react/cxxcomponents/ComponentManager.h similarity index 92% rename from ReactAndroid/src/main/jni/react/fabric/ComponentManager.h rename to ReactAndroid/src/main/jni/react/cxxcomponents/ComponentManager.h index b7d5f7087d2baf..3f2123b8977893 100644 --- a/ReactAndroid/src/main/jni/react/fabric/ComponentManager.h +++ b/ReactAndroid/src/main/jni/react/cxxcomponents/ComponentManager.h @@ -7,7 +7,7 @@ #pragma once -#include +#include #include namespace facebook::react { diff --git a/ReactAndroid/src/main/jni/react/fabric/BUCK b/ReactAndroid/src/main/jni/react/fabric/BUCK index 0a9480be3ee662..2ba8a8de664f87 100644 --- a/ReactAndroid/src/main/jni/react/fabric/BUCK +++ b/ReactAndroid/src/main/jni/react/fabric/BUCK @@ -35,6 +35,7 @@ rn_xplat_cxx_library( react_native_xplat_target("react/renderer/componentregistry:componentregistry"), react_native_xplat_target("react/renderer/components/scrollview:scrollview"), react_native_xplat_target("runtimeexecutor:runtimeexecutor"), + "//xplat/js/react-native-github/ReactAndroid/src/main/jni/react/cxxcomponents:components", react_native_target("jni/react/jni:jni"), "//xplat/fbsystrace:fbsystrace", "//xplat/jsi:JSIDynamic", diff --git a/ReactAndroid/src/main/jni/react/fabric/CMakeLists.txt b/ReactAndroid/src/main/jni/react/fabric/CMakeLists.txt index c4d743cfa10e7b..920103e9cb8bd4 100644 --- a/ReactAndroid/src/main/jni/react/fabric/CMakeLists.txt +++ b/ReactAndroid/src/main/jni/react/fabric/CMakeLists.txt @@ -18,6 +18,7 @@ target_include_directories(fabricjni PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries( fabricjni butter + cxxcomponents fb fbjni folly_runtime diff --git a/ReactAndroid/src/main/jni/react/fabric/ComponentRegistryResolver.h b/ReactAndroid/src/main/jni/react/fabric/ComponentRegistryResolver.h index 67eb046f8ff987..5d8adec466aa70 100644 --- a/ReactAndroid/src/main/jni/react/fabric/ComponentRegistryResolver.h +++ b/ReactAndroid/src/main/jni/react/fabric/ComponentRegistryResolver.h @@ -8,7 +8,7 @@ #pragma once #include -#include +#include namespace facebook { namespace react { diff --git a/ReactAndroid/src/main/jni/react/fabric/CppComponentRegistry.h b/ReactAndroid/src/main/jni/react/fabric/CppComponentRegistry.h index f417b386e36417..0354a19cde7791 100644 --- a/ReactAndroid/src/main/jni/react/fabric/CppComponentRegistry.h +++ b/ReactAndroid/src/main/jni/react/fabric/CppComponentRegistry.h @@ -14,8 +14,8 @@ #include #include -#include -#include +#include +#include #include namespace facebook { From 93c6d2a8e56b1ce63e9daaa06b104eb199a27307 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Fri, 16 Sep 2022 12:33:15 -0700 Subject: [PATCH 05/54] update documentation for enableCppRenderSystem feature flag Summary: This diff updates the documentation for enableCppRenderSystem feature flag This is a follow up of D38725771 (https://github.com/facebook/react-native/commit/399907fe4ad843ac6aa0aa2f553ba3aee3c83006) changelog: [internal] internal Reviewed By: cortinico, makovkastar Differential Revision: D39558834 fbshipit-source-id: e079ee688a912dfa2670c66e5adf347a902a45e1 --- Libraries/ReactNative/ReactNativeFeatureFlags.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Libraries/ReactNative/ReactNativeFeatureFlags.js b/Libraries/ReactNative/ReactNativeFeatureFlags.js index 6fecce9a3c8c26..629137ce35b056 100644 --- a/Libraries/ReactNative/ReactNativeFeatureFlags.js +++ b/Libraries/ReactNative/ReactNativeFeatureFlags.js @@ -39,7 +39,8 @@ export type FeatureFlags = {| */ animatedShouldUseSingleOp: () => boolean, /** - * Enables C++ render system. + * This feature flag enables an experimental render system that allows + * to render react components driven by classes written in C++. */ enableCppRenderSystem: () => boolean, |}; From 7003fcd6eb78b7dfa82e578cf3b4cac32dfd4ae3 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Fri, 16 Sep 2022 12:33:15 -0700 Subject: [PATCH 06/54] Delete react/fabric/components folder Summary: Delete react/fabric/components folder as this is not needed anymore changelog: [internal] internal Reviewed By: cortinico, makovkastar Differential Revision: D39560229 fbshipit-source-id: b27ba1acd3bf46472bd022e78e171d7d22d7979d --- .../src/main/jni/react/fabric/components/BUCK | 45 ------------------- .../react/fabric/components/CMakeLists.txt | 12 ----- 2 files changed, 57 deletions(-) delete mode 100644 ReactAndroid/src/main/jni/react/fabric/components/BUCK delete mode 100644 ReactAndroid/src/main/jni/react/fabric/components/CMakeLists.txt diff --git a/ReactAndroid/src/main/jni/react/fabric/components/BUCK b/ReactAndroid/src/main/jni/react/fabric/components/BUCK deleted file mode 100644 index d56de6dc03b759..00000000000000 --- a/ReactAndroid/src/main/jni/react/fabric/components/BUCK +++ /dev/null @@ -1,45 +0,0 @@ -load( - "//tools/build_defs/oss:rn_defs.bzl", - "ANDROID", - "CXX", - "react_native_xplat_target", - "rn_xplat_cxx_library", - "subdir_glob", -) - -rn_xplat_cxx_library( - name = "components", - srcs = glob( - ["**/*.cpp"], - ), - headers = glob( - ["**/*.h"], - ), - header_namespace = "", - exported_headers = subdir_glob( - [ - ("", "*.h"), - ], - prefix = "react/fabric", - ), - force_static = True, - labels = [ - "pfh:ReactNative_CommonInfrastructurePlaceholder", - "supermodule:xplat/default/public.react_native.infra", - ], - platforms = (ANDROID, CXX), - preprocessor_flags = [ - "-DLOG_TAG=\"ReactNative\"", - "-DWITH_FBSYSTRACE=1", - ], - soname = "libfabriccomponentsjni.$(ext)", - tests = [":tests"], - visibility = ["PUBLIC"], - deps = [ - "//third-party/glog:glog", - "//xplat/fbsystrace:fbsystrace", - "//xplat/folly:memory", - "//xplat/folly:molly", - react_native_xplat_target("react/renderer/core:core"), - ], -) diff --git a/ReactAndroid/src/main/jni/react/fabric/components/CMakeLists.txt b/ReactAndroid/src/main/jni/react/fabric/components/CMakeLists.txt deleted file mode 100644 index 91a997e402201c..00000000000000 --- a/ReactAndroid/src/main/jni/react/fabric/components/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -cmake_minimum_required(VERSION 3.13) -set(CMAKE_VERBOSE_MAKEFILE on) - -add_compile_options(-fvisibility=hidden -fexceptions -frtti) - -file(GLOB fabriccomponentsjni_SRC CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) -add_library(fabriccomponentsjni INTERFACE ${fabriccomponentsjni_SRC}) From dc56eb99f1eceeabbc25ba1336f1755bd4c5c6c1 Mon Sep 17 00:00:00 2001 From: Luna Wei Date: Fri, 16 Sep 2022 12:41:06 -0700 Subject: [PATCH 07/54] Fix missing renames from bots to react-native-bots (#34713) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/34713 Changelog: [Internal] - Fix up missing bots usage after we moved everything to packages/react-native-bots in https://github.com/facebook/react-native/commit/767f8e0249618e78c07758c7fd27be6ebaf27610 Reviewed By: NickGerleman Differential Revision: D39583230 fbshipit-source-id: 6cc6b7923e67139dc3c81dfe0c39005dde905248 --- .eslintignore | 1 - .flowconfig | 2 +- .flowconfig.android | 2 +- .github/CODEOWNERS | 2 +- .gitignore | 1 - scripts/circleci/analyze_code.sh | 2 +- scripts/circleci/post-artifacts-link.sh | 2 +- scripts/circleci/report-bundle-size.sh | 2 +- 8 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.eslintignore b/.eslintignore index 11d4192591a096..55ea7e257b58bd 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,6 +1,5 @@ **/main.js **/staticBundle.js -bots/node_modules docs/generatedComponentApiDocs.js flow/ flow-typed/ diff --git a/.flowconfig b/.flowconfig index fde48607350081..774ad3744a2895 100644 --- a/.flowconfig +++ b/.flowconfig @@ -6,7 +6,7 @@ /template/.* ; Ignore the Dangerfile -/bots/dangerfile.js +/packages/react-native-bots/dangerfile.js ; Ignore "BUCK" generated dirs /\.buckd/ diff --git a/.flowconfig.android b/.flowconfig.android index 5c2927b6fa2f3a..3f05b3b1b2f421 100644 --- a/.flowconfig.android +++ b/.flowconfig.android @@ -6,7 +6,7 @@ /template/.* ; Ignore the Dangerfile -/bots/dangerfile.js +/packages/react-native-bots/dangerfile.js ; Ignore "BUCK" generated dirs /\.buckd/ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 38dbd76f893b2b..113169229179c8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -9,7 +9,7 @@ # GitHub Settings, Bots /.github/ @hramos -/bots @hramos +/packages/react-native-bots @hramos # Continuous Integration /.circleci/ @hramos diff --git a/.gitignore b/.gitignore index 98dd6edc4f9481..c0c9c37bdca05b 100644 --- a/.gitignore +++ b/.gitignore @@ -68,7 +68,6 @@ local.properties node_modules *.log .nvm -/bots/node_modules/ package-lock.json # OS X diff --git a/scripts/circleci/analyze_code.sh b/scripts/circleci/analyze_code.sh index 08f9af88eacae2..d2735898149cba 100755 --- a/scripts/circleci/analyze_code.sh +++ b/scripts/circleci/analyze_code.sh @@ -9,7 +9,7 @@ GITHUB_REPO=${CIRCLE_PROJECT_REPONAME:-react-native} export GITHUB_OWNER export GITHUB_REPO -cat <(echo eslint; npm run lint --silent -- --format=json; echo flow; npm run flow-check-ios --silent --json; echo flow; npm run flow-check-android --silent --json; echo google-java-format; node scripts/lint-java.js --diff) | GITHUB_PR_NUMBER="$CIRCLE_PR_NUMBER" node bots/code-analysis-bot.js +cat <(echo eslint; npm run lint --silent -- --format=json; echo flow; npm run flow-check-ios --silent --json; echo flow; npm run flow-check-android --silent --json; echo google-java-format; node scripts/lint-java.js --diff) | GITHUB_PR_NUMBER="$CIRCLE_PR_NUMBER" node packages/react-native-bots/code-analysis-bot.js STATUS=$? if [ $STATUS == 0 ]; then diff --git a/scripts/circleci/post-artifacts-link.sh b/scripts/circleci/post-artifacts-link.sh index ce8c87a841121d..6318dc1e0f624d 100755 --- a/scripts/circleci/post-artifacts-link.sh +++ b/scripts/circleci/post-artifacts-link.sh @@ -8,4 +8,4 @@ GITHUB_OWNER=${CIRCLE_PROJECT_USERNAME:-facebook} \ GITHUB_REPO=${CIRCLE_PROJECT_REPONAME:-react-native} \ GITHUB_PR_NUMBER="${CIRCLE_PR_NUMBER:-${CIRCLE_PULL_REQUEST##*/}}" \ GITHUB_SHA=${CIRCLE_SHA1} \ -exec node bots/post-artifacts-link.js +exec node packages/react-native-bots/post-artifacts-link.js diff --git a/scripts/circleci/report-bundle-size.sh b/scripts/circleci/report-bundle-size.sh index bf1ea43fa318c6..a5b7d703302204 100755 --- a/scripts/circleci/report-bundle-size.sh +++ b/scripts/circleci/report-bundle-size.sh @@ -11,7 +11,7 @@ case $1 in GITHUB_PR_NUMBER="${CIRCLE_PR_NUMBER:-${CIRCLE_PULL_REQUEST##*/}}" \ GITHUB_REF=${CIRCLE_BRANCH} \ GITHUB_SHA=${CIRCLE_SHA1} \ - exec node bots/report-bundle-size.js "$1" + exec node packages/react-native-bots/report-bundle-size.js "$1" ;; *) echo "Syntax: $0 [android | ios]" From d15a82dc3135ece0d394a40a7aae5b451e30df1d Mon Sep 17 00:00:00 2001 From: David Vacca Date: Fri, 16 Sep 2022 16:56:54 -0700 Subject: [PATCH 08/54] Remove test BUCK configuration for cxxcomponents Summary: This diff removes the 'test' BUCK configuration for cxxcomponents, the goal of the diff is to fix a sandcastle issue: https://www.internalfb.com/intern/sandcastle/log/?instance_id=36028797791859555&step_id=36028805144809956&step_index=6&name=Run%20arc%20focus-android build-break overriding_review_checks_triggers_an_audit_and_retroactive_review Oncall Short Name: react_native changelog: [internal] internal Differential Revision: D39589523 fbshipit-source-id: 9cb6ab1e8a5929e7d288771f2f980db00a5a4adb --- ReactAndroid/src/main/jni/react/cxxcomponents/BUCK | 1 - 1 file changed, 1 deletion(-) diff --git a/ReactAndroid/src/main/jni/react/cxxcomponents/BUCK b/ReactAndroid/src/main/jni/react/cxxcomponents/BUCK index 1f6f4597038d8c..3d2775cf0011db 100644 --- a/ReactAndroid/src/main/jni/react/cxxcomponents/BUCK +++ b/ReactAndroid/src/main/jni/react/cxxcomponents/BUCK @@ -34,7 +34,6 @@ rn_xplat_cxx_library( "-DWITH_FBSYSTRACE=1", ], soname = "libcxxcomponents.$(ext)", - tests = [":tests"], visibility = ["PUBLIC"], deps = [ "//third-party/glog:glog", From ab5f26bf027144a1ae7cb86c814994e870c4dfdb Mon Sep 17 00:00:00 2001 From: Luna Wei Date: Sat, 17 Sep 2022 07:05:37 -0700 Subject: [PATCH 09/54] Back out "Fix `Alert` not showing in an app using `UIScene`" Summary: Changelog: [Internal] - Revert https://github.com/facebook/react-native/pull/34562 re: [iOS] [Fixed] - Fix Alert not showing in an app using UIScene Reviewed By: alsun2001 Differential Revision: D39591113 fbshipit-source-id: ba707c11b3fb97eb3a6fee32e57b92403aa8b3d8 --- React/CoreModules/RCTAlertController.h | 1 + React/CoreModules/RCTAlertController.m | 30 +++++++++++++++++++++++++- React/CoreModules/RCTAlertManager.mm | 3 +++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/React/CoreModules/RCTAlertController.h b/React/CoreModules/RCTAlertController.h index 74e183da79125c..62adf2f3ac9e03 100644 --- a/React/CoreModules/RCTAlertController.h +++ b/React/CoreModules/RCTAlertController.h @@ -10,5 +10,6 @@ @interface RCTAlertController : UIAlertController - (void)show:(BOOL)animated completion:(void (^)(void))completion; +- (void)hide; @end diff --git a/React/CoreModules/RCTAlertController.m b/React/CoreModules/RCTAlertController.m index fc531b3a331d5c..02636c3f4a7b8f 100644 --- a/React/CoreModules/RCTAlertController.m +++ b/React/CoreModules/RCTAlertController.m @@ -9,8 +9,24 @@ #import +@interface RCTAlertController () + +@property (nonatomic, strong) UIWindow *alertWindow; + +@end + @implementation RCTAlertController +- (UIWindow *)alertWindow +{ + if (_alertWindow == nil) { + _alertWindow = [[UIWindow alloc] initWithFrame:RCTSharedApplication().keyWindow.bounds]; + _alertWindow.rootViewController = [UIViewController new]; + _alertWindow.windowLevel = UIWindowLevelAlert + 1; + } + return _alertWindow; +} + - (void)show:(BOOL)animated completion:(void (^)(void))completion { if (@available(iOS 13.0, *)) { @@ -18,7 +34,19 @@ - (void)show:(BOOL)animated completion:(void (^)(void))completion RCTSharedApplication().delegate.window.overrideUserInterfaceStyle ?: UIUserInterfaceStyleUnspecified; self.overrideUserInterfaceStyle = style; } - [[RCTKeyWindow() rootViewController] presentViewController:self animated:animated completion:completion]; + [self.alertWindow makeKeyAndVisible]; + [self.alertWindow.rootViewController presentViewController:self animated:animated completion:completion]; +} + +- (void)hide +{ + [_alertWindow setHidden:YES]; + + if (@available(iOS 13, *)) { + _alertWindow.windowScene = nil; + } + + _alertWindow = nil; } @end diff --git a/React/CoreModules/RCTAlertManager.mm b/React/CoreModules/RCTAlertManager.mm index 25ab71f913b73e..532e898faf05a0 100644 --- a/React/CoreModules/RCTAlertManager.mm +++ b/React/CoreModules/RCTAlertManager.mm @@ -185,6 +185,7 @@ - (void)invalidate case RCTAlertViewStylePlainTextInput: case RCTAlertViewStyleSecureTextInput: callback(@[ buttonKey, [weakAlertController.textFields.firstObject text] ]); + [weakAlertController hide]; break; case RCTAlertViewStyleLoginAndPasswordInput: { NSDictionary *loginCredentials = @{ @@ -192,10 +193,12 @@ - (void)invalidate @"password" : [weakAlertController.textFields.lastObject text] }; callback(@[ buttonKey, loginCredentials ]); + [weakAlertController hide]; break; } case RCTAlertViewStyleDefault: callback(@[ buttonKey ]); + [weakAlertController hide]; break; } }]; From 6b2a511cbb1f244133624e37e7b3215d8fed33af Mon Sep 17 00:00:00 2001 From: Luna Wei Date: Mon, 19 Sep 2022 12:26:00 -0700 Subject: [PATCH 10/54] Move TypeScript declarations into react-native (#34614) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: ## Changelog [General] [Added] - Add `types` folder to house TypeScript types. Release TypesScript types with react-native and eventually deprecate [types/react-native](https://www.npmjs.com/package/types/react-native). The current plan is to release types/react-native for 0.70 and 0.71 while also maintaining types here. This will result in some double maintenance until 0.72 but will give community time to move off of types/react-native. After this lands, there have been changes on `main` of types that we need to update. Then, when we release 0.71 from DefinitelyTyped, we can simply copy over the `types` folder from this repo. Pull Request resolved: https://github.com/facebook/react-native/pull/34614 Test Plan: `yarn run test-typescript` for linting types * Created a new project using the TS template and my local clone of `react-native` on this branch. `npx react-native init MyTSApp --version --template react-native-template-typescript` * Updated the `package.json` to remove `types/react-native` * Deleted my node_modules and re-ran yarn * Opened MyTSApp in VSCode and verified the type suggestions appeared and cmd+click to defnitions took me to the node_module dependency `react-native/types` ## Danger is failing on this PR and it's expected as it runs off the changes on `main`. [This is expected](https://docs.github.com/en/github-ae@latest/actions/using-workflows/events-that-trigger-workflows?fbclid=IwAR2_AE0Jwndt8Gu-iTQnxGxLJq7nakbi7sz8jwZ6U62JWLSdcZuvjcQ6WvE#pull_request_target). However testing it locally passes. Once merged, and these changes are on `main`, danger will pass again. ``` $ react-native/packages/react-native-bots ❯ yarn danger pr https://github.com/facebook/react-native/pull/34614 yarn run v1.22.19 $ ..react-native/node_modules/.bin/danger pr https://github.com/facebook/react-native/pull/34614 Starting Danger PR on facebook/react-native#34614 Danger: ✓ found only warnings, not failing the build ## Warnings :lock: package.json - Changes were made to package.json. This will require a manual import by a Facebook employee. ✨ Done in 13.24s. ``` Reviewed By: mdvacca Differential Revision: D39479137 Pulled By: lunaleaps fbshipit-source-id: 1d506f812d566b783b6e79104cd6339b077a42a7 --- .circleci/config.yml | 5 + .eslintrc.js | 12 + package.json | 8 +- repo-config/package.json | 4 + scripts/.npmignore | 2 +- types/BatchedBridge.d.ts | 32 + types/Codegen.d.ts | 74 + types/Devtools.d.ts | 31 + types/LaunchScreen.d.ts | 18 + types/__typetests__/animated.tsx | 242 + .../__typetests__/fabric-component-sample.ts | 55 + types/__typetests__/globals.tsx | 178 + types/__typetests__/index.tsx | 2168 ++++ types/__typetests__/init-example.tsx | 117 + types/__typetests__/legacy-properties.tsx | 13 + types/__typetests__/stylesheet-create.tsx | 33 + types/__typetests__/stylesheet-flatten.tsx | 33 + types/__typetests__/turbo-module-sample.ts | 22 + types/globals.d.ts | 577 + types/index.d.ts | 10702 ++++++++++++++++ types/legacy-properties.d.ts | 245 + types/tsconfig.json | 19 + types/tslint.json | 23 + yarn.lock | 771 +- 24 files changed, 15357 insertions(+), 27 deletions(-) create mode 100644 types/BatchedBridge.d.ts create mode 100644 types/Codegen.d.ts create mode 100644 types/Devtools.d.ts create mode 100644 types/LaunchScreen.d.ts create mode 100644 types/__typetests__/animated.tsx create mode 100644 types/__typetests__/fabric-component-sample.ts create mode 100644 types/__typetests__/globals.tsx create mode 100644 types/__typetests__/index.tsx create mode 100644 types/__typetests__/init-example.tsx create mode 100644 types/__typetests__/legacy-properties.tsx create mode 100644 types/__typetests__/stylesheet-create.tsx create mode 100644 types/__typetests__/stylesheet-flatten.tsx create mode 100644 types/__typetests__/turbo-module-sample.ts create mode 100644 types/globals.d.ts create mode 100644 types/index.d.ts create mode 100644 types/legacy-properties.d.ts create mode 100644 types/tsconfig.json create mode 100644 types/tslint.json diff --git a/.circleci/config.yml b/.circleci/config.yml index 2cc6315c5fc3ee..3c22a29dcdc50a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -345,6 +345,11 @@ jobs: command: yarn flow-check-android when: always + - run: + name: Run TypeScript tests + command: yarn test-typescript + when: always + - run: name: Sanity checks command: | diff --git a/.eslintrc.js b/.eslintrc.js index d07d0d884c0b5c..c2adaccf1a2edc 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -71,5 +71,17 @@ module.exports = { jest: true, }, }, + { + files: ['types/**/*.{ts,tsx}'], + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint/eslint-plugin'], + rules: { + '@typescript-eslint/no-unused-vars': 'off', + 'react-native/no-inline-styles': 'off', + '@typescript-eslint/no-shadow': 'off', + 'no-self-compare': 'off', + 'react/self-closing-comp': 'off', + }, + }, ], }; diff --git a/package.json b/package.json index 31048428246916..d06f635855a182 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "engines": { "node": ">=14" }, + "types": "types", "jest-junit": { "outputDirectory": "reports/junit", "outputName": "js-test-results.xml" @@ -81,8 +82,8 @@ "shellcheck": "./scripts/circleci/analyze_scripts.sh", "clang-format": "clang-format -i --glob=*/**/*.{h,cpp,m,mm}", "format": "npm run prettier && npm run clang-format", - "prettier": "prettier --write \"./**/*.{js,md,yml}\"", - "format-check": "prettier --list-different \"./**/*.{js,md,yml}\"", + "prettier": "prettier --write \"./**/*.{js,md,yml,ts,tsx}\"", + "format-check": "prettier --list-different \"./**/*.{js,md,yml,ts,tsx}\"", "update-lock": "npx yarn-deduplicate", "docker-setup-android": "docker pull reactnativecommunity/react-native-android:5.2", "docker-build-android": "docker build -t reactnativeci/android -f .circleci/Dockerfiles/Dockerfile.android .", @@ -93,7 +94,8 @@ "test-android-instrumentation": "yarn run docker-build-android && yarn run test-android-run-instrumentation", "test-android-unit": "yarn run docker-build-android && yarn run test-android-run-unit", "test-android-e2e": "yarn run docker-build-android && yarn run test-android-run-e2e", - "test-ios": "./scripts/objc-test.sh test" + "test-ios": "./scripts/objc-test.sh test", + "test-typescript": "dtslint types" }, "workspaces": [ "packages/*", diff --git a/repo-config/package.json b/repo-config/package.json index 596c3a1b0eeda8..b4fdb07316b411 100644 --- a/repo-config/package.json +++ b/repo-config/package.json @@ -13,9 +13,12 @@ "@babel/eslint-parser": "^7.18.2", "@babel/generator": "^7.14.0", "@babel/plugin-transform-regenerator": "^7.0.0", + "@definitelytyped/dtslint": "^0.0.127", "@react-native-community/eslint-plugin": "*", "@react-native/eslint-plugin-specs": "^0.71.0", "@reactions/component": "^2.0.2", + "@types/react": "^18.0.18", + "@typescript-eslint/parser": "^5.30.5", "async": "^3.2.2", "clang-format": "^1.8.0", "connect": "^3.6.5", @@ -46,6 +49,7 @@ "react-test-renderer": "18.2.0", "shelljs": "^0.8.5", "signedsource": "^1.0.0", + "typescript": "4.1.3", "ws": "^6.1.4", "yargs": "^17.5.1" }, diff --git a/scripts/.npmignore b/scripts/.npmignore index ee653fdf1e65c8..6f5224b226432e 100644 --- a/scripts/.npmignore +++ b/scripts/.npmignore @@ -1,2 +1,2 @@ # Make sure we never publish __test__ folders (Gradle output) -**/__tests__/ +**/__*tests__/ diff --git a/types/BatchedBridge.d.ts b/types/BatchedBridge.d.ts new file mode 100644 index 00000000000000..c6b2e145a2f38a --- /dev/null +++ b/types/BatchedBridge.d.ts @@ -0,0 +1,32 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +interface SpyData { + type: number; + module?: string | undefined; + method: string | number; + args: any[]; +} + +declare class MessageQueue { + static spy(spyOrToggle: boolean | ((data: SpyData) => void)): void; + + getCallableModule(name: string): Object; + registerCallableModule(name: string, module: Object): void; + registerLazyCallableModule(name: string, factory: () => Object): void; +} + +declare module 'react-native/Libraries/BatchedBridge/BatchedBridge' { + const BatchedBridge: MessageQueue; + export default BatchedBridge; +} + +declare module 'react-native/Libraries/BatchedBridge/MessageQueue' { + export default MessageQueue; +} diff --git a/types/Codegen.d.ts b/types/Codegen.d.ts new file mode 100644 index 00000000000000..24de3b099159cc --- /dev/null +++ b/types/Codegen.d.ts @@ -0,0 +1,74 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +declare module 'react-native/Libraries/Utilities/codegenNativeCommands' { + export interface Options { + readonly supportedCommands: ReadonlyArray; + } + + function codegenNativeCommands( + options: Options, + ): T; + + export default codegenNativeCommands; +} + +declare module 'react-native/Libraries/Utilities/codegenNativeComponent' { + import type {HostComponent} from 'react-native'; + + export interface Options { + readonly interfaceOnly?: boolean; + readonly paperComponentName?: string; + readonly paperComponentNameDeprecated?: string; + readonly excludedPlatforms?: ReadonlyArray<'iOS' | 'android'>; + } + + export type NativeComponentType = HostComponent; + + function codegenNativeComponent( + componentName: string, + options?: Options, + ): NativeComponentType; + + export default codegenNativeComponent; +} + +declare module 'react-native/Libraries/Types/CodegenTypes' { + import type {NativeSyntheticEvent} from 'react-native'; + + // Event types + // We're not using the PaperName, it is only used to codegen view config settings + + export type BubblingEventHandler< + T, + PaperName extends string | never = never, + > = (event: NativeSyntheticEvent) => void | Promise; + export type DirectEventHandler< + T, + PaperName extends string | never = never, + > = (event: NativeSyntheticEvent) => void | Promise; + + // Prop types + export type Double = number; + export type Float = number; + export type Int32 = number; + export type UnsafeObject = object; + + type DefaultTypes = number | boolean | string | ReadonlyArray; + // Default handling, ignore the unused value + // we're only using it for type checking + // + // TODO: (rickhanlonii) T44881457 If a default is provided, it should always be optional + // but that is currently not supported in the codegen since we require a default + + export type WithDefault< + Type extends DefaultTypes, + Value extends Type | string | undefined | null, + > = Type | undefined | null; +} diff --git a/types/Devtools.d.ts b/types/Devtools.d.ts new file mode 100644 index 00000000000000..3a993cf7ab7b5b --- /dev/null +++ b/types/Devtools.d.ts @@ -0,0 +1,31 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +declare module 'react-native/Libraries/Core/Devtools/parseErrorStack' { + export type StackFrame = { + file: string; + methodName: string; + lineNumber: number; + column: number | null; + }; + + export interface ExtendedError extends Error { + framesToPop?: number | undefined; + } + + export default function parseErrorStack(error: ExtendedError): StackFrame[]; +} + +declare module 'react-native/Libraries/Core/Devtools/symbolicateStackTrace' { + import {StackFrame} from 'react-native/Libraries/Core/Devtools/parseErrorStack'; + + export default function symbolicateStackTrace( + stack: ReadonlyArray, + ): Promise; +} diff --git a/types/LaunchScreen.d.ts b/types/LaunchScreen.d.ts new file mode 100644 index 00000000000000..3e816dd065274e --- /dev/null +++ b/types/LaunchScreen.d.ts @@ -0,0 +1,18 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +// Adds the JSX elements used in the launch screen. + +declare module 'react-native/Libraries/NewAppScreen' { + export const Header: any; + export const LearnMoreLinks: any; + export const Colors: any; + export const DebugInstructions: any; + export const ReloadInstructions: any; +} diff --git a/types/__typetests__/animated.tsx b/types/__typetests__/animated.tsx new file mode 100644 index 00000000000000..bee061fb72d2e9 --- /dev/null +++ b/types/__typetests__/animated.tsx @@ -0,0 +1,242 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import * as React from 'react'; + +import { + Animated, + View, + NativeSyntheticEvent, + NativeScrollEvent, + StyleProp, + SectionListData, +} from 'react-native'; + +interface CompProps { + width: number; +} + +class Comp extends React.Component { + f1: () => boolean = () => true; + + render() { + const {width} = this.props; + return ; + } +} + +const ForwardComp = React.forwardRef(({width}, ref) => { + function f1(): boolean { + return true; + } + + return ; +}); + +type X = React.PropsWithoutRef>; + +type Props = React.ComponentPropsWithRef; +const AnimatedWrapperComponent: React.FunctionComponent = ({ + key, // $ExpectType string | number | null | undefined || Key | null | undefined + ...props +}) => ; + +function TestAnimatedAPI() { + // Value + const v1 = new Animated.Value(0); + const v2 = new Animated.Value(0); + + // Ref + const AnimatedViewRef = React.useRef(null); + + AnimatedViewRef.current && + AnimatedViewRef.current.measure(() => { + return; + }); + + const AnimatedComp = Animated.createAnimatedComponent(Comp); + + const AnimatedCompRef = React.useRef(null); + + AnimatedCompRef.current && AnimatedCompRef.current.f1(); + + const AnimatedForwardComp = Animated.createAnimatedComponent(ForwardComp); + + const AnimatedForwardCompRef = + React.useRef>(null); + const ForwardCompRef = React.useRef(null); + + AnimatedForwardCompRef.current && + AnimatedForwardCompRef.current.measure(() => { + return; + }); + + v1.setValue(0.1); + + v1.addListener(e => { + const n: number = e.value; + }); + + const v200 = v1.interpolate({ + inputRange: [0, 1], + outputRange: [0, 200], + }); + + const id = v200.addListener(() => {}); + v200.removeListener(id); + v200.removeAllListeners(); + v200.hasListeners(); + + Animated.timing(v2, { + toValue: v1.interpolate({inputRange: [0, 1], outputRange: [0, 200]}), + useNativeDriver: false, + }); + + // ValueXY + const position = new Animated.ValueXY({x: 0, y: 0}); + + // Animation functions + const spring1 = Animated.spring(v1, { + toValue: 0.5, + tension: 10, + delay: 100, + useNativeDriver: false, + }); + + const springXY = Animated.spring(position, { + toValue: { + x: 1, + y: 2, + }, + useNativeDriver: false, + }); + + spring1.start(); + spring1.stop(); + spring1.reset(); + + Animated.parallel( + [ + Animated.spring(v1, {toValue: 1, useNativeDriver: false}), + Animated.spring(v2, {toValue: 1, useNativeDriver: false}), + ], + { + stopTogether: true, + }, + ); + + Animated.decay(v1, { + velocity: 2, + useNativeDriver: false, + }); + + Animated.timing(v1, { + toValue: 1, + duration: 100, + delay: 100, + easing: v => v, + useNativeDriver: false, + }); + + Animated.add(v1, v2); + Animated.subtract(v1, v2); + Animated.divide(v1, v2); + Animated.multiply(v1, v2); + Animated.modulo(v1, 2); + + Animated.delay(100); + + Animated.sequence([spring1, springXY]); + + Animated.stagger(100, [spring1, springXY]); + + const listener = (e?: NativeSyntheticEvent) => { + if (e) { + console.warn(e.nativeEvent.contentOffset.y); + } + }; + + Animated.event([{nativeEvent: {contentOffset: {y: v1}}}], { + useNativeDriver: true, + listener, + }); + + const AnimatedView = Animated.createAnimatedComponent(View); + const ref = React.useRef(null); + const legacyRef = React.useRef>(null); + + return ( + + + + i has children + + + + + + + + { + const x = event.nativeEvent.layout.x; // $ExpectType number + const y = event.nativeEvent.layout.y; // $ExpectType number + const width = event.nativeEvent.layout.width; // $ExpectType number + const height = event.nativeEvent.layout.height; // $ExpectType number + }} + /> + ; + } + renderItem={info => { + info; // $ExpectType ListRenderItemInfo + return ; + }} + /> + ; + [] + } + renderItem={info => { + /* + * Original expects: + * SectionListRenderItemInfo on TS@3.5, + * SectionListRenderItemInfo on TS@4.0. + * Skip until original is adjusted and type can be asserted + */ + info; // Should expect SectionListRenderItemInfo + info.section.title; // $ExpectType string + return ; + }} + /> + ; + + ); +} diff --git a/types/__typetests__/fabric-component-sample.ts b/types/__typetests__/fabric-component-sample.ts new file mode 100644 index 00000000000000..73d91a6bcee8ee --- /dev/null +++ b/types/__typetests__/fabric-component-sample.ts @@ -0,0 +1,55 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import codegenNativeComponent, { + NativeComponentType, +} from 'react-native/Libraries/Utilities/codegenNativeComponent'; +import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; +import { + WithDefault, + Double, + Float, + Int32, + UnsafeObject, + BubblingEventHandler, + DirectEventHandler, +} from 'react-native/Libraries/Types/CodegenTypes'; +import type {ViewProps} from 'react-native'; + +type Event = Readonly<{ + value: Double; +}>; + +interface NativeProps extends ViewProps { + string?: string; + number?: number; + boolean?: boolean; + default?: WithDefault<'option1' | 'option2', 'option1'>; + double?: Double; + float?: Float; + int32?: Int32; + unsafeObject?: UnsafeObject; + onBubblingEventHandler?: BubblingEventHandler; + onDirectEventHandler?: DirectEventHandler; +} + +export type SampleViewType = NativeComponentType; + +interface NativeCommands { + changeBackgroundColor: ( + viewRef: React.ElementRef, + color: string, + ) => void; +} + +export const Commands: NativeCommands = codegenNativeCommands({ + supportedCommands: ['changeBackgroundColor'], +}); + +export default codegenNativeComponent('SampleView'); diff --git a/types/__typetests__/globals.tsx b/types/__typetests__/globals.tsx new file mode 100644 index 00000000000000..e14a8029d6da27 --- /dev/null +++ b/types/__typetests__/globals.tsx @@ -0,0 +1,178 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +const noop = () => { }; + +function testInterval() { + let handle = setInterval(noop, 0); + clearInterval(handle); + + handle = setInterval((arg1: number, arg2: string) => { + console.log('arg1', arg1); + console.log('arg2', arg2); + }, 0, 100, '200'); + clearInterval(handle); + + handle = setInterval((arg1: number, arg2: string) => { + console.log('arg1', arg1); + console.log('arg2', arg2); + // @ts-expect-error + }, 0, 'wrong-type', '200'); + clearInterval(handle); + + // @ts-expect-error + handle = setInterval((missingArg: any) => { + console.log('missingArg', missingArg); + }, 0); + clearInterval(handle); + + handle = setInterval((arg1: number) => { + console.log('arg1', arg1); + // @ts-expect-error + }, 0, 100, 'missing-arg'); + clearInterval(handle); +} + +function testTimeout() { + let handle = setTimeout(noop, 0); + clearTimeout(handle); + + handle = setTimeout((arg1: number, arg2: string) => { + console.log('arg1', arg1); + console.log('arg2', arg2); + }, 0, 100, '200'); + clearTimeout(handle); + + handle = setTimeout((arg1: number, arg2: string) => { + console.log('arg1', arg1); + console.log('arg2', arg2); + // @ts-expect-error + }, 0, 'wrong-type', '200'); + clearTimeout(handle); + + // @ts-expect-error + handle = setTimeout((missingArg: any) => { + console.log('missingArg', missingArg); + }, 0); + clearTimeout(handle); + + handle = setTimeout((arg1: number) => { + console.log('arg1', arg1); + // @ts-expect-error + }, 0, 100, 'missing-arg'); + clearTimeout(handle); +} + +function testImmediate() { + let handle = setImmediate(noop); + clearImmediate(handle); + + handle = setImmediate((arg1: number, arg2: string) => { + console.log('arg1', arg1); + console.log('arg2', arg2); + }, 100, '200'); + clearImmediate(handle); + + handle = setImmediate((arg1: number, arg2: string) => { + console.log('arg1', arg1); + console.log('arg2', arg2); + // @ts-expect-error + }, 'wrong-type', '200'); + clearImmediate(handle); + + // @ts-expect-error + handle = setImmediate((missingArg: any) => { + console.log('missingArg', missingArg); + }); + clearImmediate(handle); + + handle = setImmediate((arg1: number) => { + console.log('arg1', arg1); + // @ts-expect-error + }, 100, 'missing-arg'); + clearImmediate(handle); +} + +const fetchCopy: WindowOrWorkerGlobalScope['fetch'] = fetch; + +const myHeaders = new Headers(); +myHeaders.append('Content-Type', 'image/jpeg'); + +const myInit: RequestInit = { + method: 'GET', + headers: myHeaders, + mode: 'cors', + signal: new AbortSignal(), +}; + +const myRequest = new Request('flowers.jpg'); + +fetch(myRequest, myInit) + .then(response => { + console.log(response.type); + console.log(response.url); + console.log(response.status); + console.log(response.ok); + console.log(response.statusText); + console.log(response.headers); + + return response.blob(); + }) + .then(blob => { + const init = { status: 200, statusText: 'SuperSmashingGreat!' }; + const myResponse = new Response(blob, init); + }); + +const xmlRequest = new XMLHttpRequest(); + +xmlRequest.addEventListener('load', ev => { + console.log(ev.lengthComputable); + console.log(ev.loaded); + console.log(ev.total); +}); + +const test = new URLSearchParams(); + +const url = new URL('path', 'http://localhost/'); + +const blobA = new Blob(); +const textA = 'i \u2665 dogs'; + +const blob = new Blob([blobA, textA]); + +const reader = new FileReader(); + +reader.onloadend = ev => { + console.log(ev.target); + console.log(ev.loaded); +}; + +reader.readAsText(new Blob()); + +fetch('https://example.org/post-image', { + body: { uri: 'file:///data/tmp/qwerad3.jpg' }, + headers: { + 'Content-Type': 'type', + }, + method: 'POST', +}); + +const socket = new WebSocket('wss://echo.websocket.org'); +socket.send('hello world'); +socket.addEventListener('open', () => console.log('open')); +socket.onopen = () => console.log('open'); +socket.addEventListener('close', e => console.log(e.code)); +socket.onclose = e => console.log(e.code); +socket.addEventListener('message', e => console.log(e.data)); +socket.onmessage = e => console.log(e.data); +socket.addEventListener('error', e => console.log(e.message)); +socket.onerror = e => console.log(e.message); + +const formData = new FormData(); +formData.append('file', { fileName: 'example' }); +console.log(formData.getParts()); +console.log(formData.getAll()); diff --git a/types/__typetests__/index.tsx b/types/__typetests__/index.tsx new file mode 100644 index 00000000000000..b735c71f82de37 --- /dev/null +++ b/types/__typetests__/index.tsx @@ -0,0 +1,2168 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +/* +The content of index.io.js could be something like + + 'use strict'; + + import { AppRegistry } from 'react-native' + import Welcome from './gen/Welcome' + + AppRegistry.registerComponent('MopNative', () => Welcome); + +For a list of complete Typescript examples: check https://github.com/bgrieder/RNTSExplorer +*/ + +import * as PropTypes from 'prop-types'; +import * as React from 'react'; +import { + AccessibilityInfo, + ActionSheetIOS, + AsyncStorage, + Alert, + AppState, + AppStateStatus, + Appearance, + BackHandler, + Button, + ColorValue, + DataSourceAssetCallback, + DatePickerAndroid, + DevSettings, + DeviceEventEmitter, + DeviceEventEmitterStatic, + Dimensions, + DrawerLayoutAndroid, + DrawerSlideEvent, + DynamicColorIOS, + FlatList, + FlatListProps, + GestureResponderEvent, + HostComponent, + I18nManager, + Image, + ImageBackground, + ImageErrorEventData, + ImageLoadEventData, + ImageResizeMode, + ImageResolvedAssetSource, + ImageStyle, + InputAccessoryView, + InteractionManager, + Keyboard, + KeyboardAvoidingView, + LayoutChangeEvent, + Linking, + ListRenderItemInfo, + ListView, + ListViewDataSource, + LogBox, + MaskedViewIOS, + Modal, + NativeEventEmitter, + NativeModule, // Not actually exported, not sure why + NativeModules, + NativeScrollEvent, + NativeSyntheticEvent, + PermissionsAndroid, + Platform, + PlatformColor, + Pressable, + ProgressBarAndroid, + ProgressViewIOS, + PushNotificationIOS, + RefreshControl, + RegisteredStyle, + ScaledSize, + ScrollView, + ScrollViewProps, + SectionList, + SectionListProps, + SectionListRenderItemInfo, + Share, + ShareDismissedAction, + ShareSharedAction, + StatusBar, + StyleProp, + StyleSheet, + Switch, + SwitchIOS, + SwitchChangeEvent, + Systrace, + TabBarIOS, + Text, + TextInput, + TextInputChangeEventData, + TextInputContentSizeChangeEventData, + TextInputEndEditingEventData, + TextInputFocusEventData, + TextInputKeyPressEventData, + TextInputScrollEventData, + TextInputSelectionChangeEventData, + TextInputSubmitEditingEventData, + TextLayoutEventData, + TextProps, + TextStyle, + TimePickerAndroid, + TouchableNativeFeedback, + UIManager, + View, + ViewPagerAndroid, + ViewStyle, + VirtualizedList, + YellowBox, + findNodeHandle, + requireNativeComponent, + useColorScheme, + useWindowDimensions, + SectionListData, + ToastAndroid, + Touchable, + LayoutAnimation, +} from 'react-native'; + +declare module 'react-native' { + interface NativeTypedModule { + someFunction(): void; + someProperty: string; + } + interface NativeModulesStatic { + NativeTypedModule: NativeTypedModule; + } +} + +NativeModules.NativeUntypedModule; + +NativeModules.NativeTypedModule.someFunction(); +NativeModules.NativeTypedModule.someProperty = ''; + +function dimensionsListener(dimensions: { + window: ScaledSize; + screen: ScaledSize; +}) { + console.log('window dimensions: ', dimensions.window); + console.log('screen dimensions: ', dimensions.screen); +} + +function testDimensions() { + const {width, height, scale, fontScale} = Dimensions.get( + 1 === 1 ? 'window' : 'screen', + ); + + const subscription = Dimensions.addEventListener( + 'change', + dimensionsListener, + ); + subscription.remove(); +} + +function TextUseWindowDimensions() { + const {width, height, scale, fontScale} = useWindowDimensions(); +} + +BackHandler.addEventListener('hardwareBackPress', () => true).remove(); +BackHandler.addEventListener('hardwareBackPress', () => false).remove(); +BackHandler.addEventListener('hardwareBackPress', () => undefined).remove(); +BackHandler.addEventListener('hardwareBackPress', () => null).remove(); + +interface LocalStyles { + container: ViewStyle; + welcome: TextStyle; + instructions: TextStyle; +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#F5FCFF', + }, + welcome: { + fontSize: 20, + textAlign: 'center', + margin: 10, + }, + instructions: { + textAlign: 'center', + color: '#333333', + marginBottom: 5, + }, +}); + +//alternative declaration of styles (inline typings) +const stylesAlt = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#F5FCFF', + }, + welcome: { + fontSize: 20, + textAlign: 'center', + margin: 10, + }, + instructions: { + textAlign: 'center', + color: '#333333', + marginBottom: 5, + }, +}); + +StyleSheet.setStyleAttributePreprocessor( + 'fontFamily', + (family: string) => family, +); + +const welcomeFontSize = StyleSheet.flatten(styles.welcome).fontSize; + +const viewStyle: StyleProp = { + backgroundColor: '#F5FCFF', +}; +const textStyle: StyleProp = { + fontSize: 20, +}; +const imageStyle: StyleProp = { + resizeMode: 'contain', +}; +const fontVariantStyle: StyleProp = { + fontVariant: ['tabular-nums'], +}; + +const viewProperty = StyleSheet.flatten(viewStyle).backgroundColor; +const textProperty = StyleSheet.flatten(textStyle).fontSize; +const imageProperty = StyleSheet.flatten(imageStyle).resizeMode; +const fontVariantProperty = StyleSheet.flatten(fontVariantStyle).fontVariant; + +// correct use of the StyleSheet.flatten +const styleArray: StyleProp[] = []; +const flattenStyle = StyleSheet.flatten(styleArray); +const {top} = flattenStyle; + +const s = StyleSheet.create({ + shouldWork: { + fontWeight: '900', // if we comment this line, errors gone + marginTop: 5, // if this line commented, errors also gone + }, +}); +const f1: TextStyle = s.shouldWork; + +// StyleSheet.compose +// It creates a new style object by composing two existing styles +const composeTextStyle: StyleProp = { + color: '#000000', + fontSize: 20, +}; + +const composeImageStyle: StyleProp = { + resizeMode: 'contain', +}; + +// The following use of the compose method is valid +const combinedStyle: StyleProp = StyleSheet.compose( + composeTextStyle, + composeTextStyle, +); + +const combinedStyle1: StyleProp = StyleSheet.compose( + composeImageStyle, + composeImageStyle, +); + +const combinedStyle2: StyleProp> = + StyleSheet.compose([composeTextStyle], [composeTextStyle]); + +const combinedStyle3: StyleProp = StyleSheet.compose( + composeTextStyle, + null, +); + +const combinedStyle4: StyleProp | null> = + StyleSheet.compose([composeTextStyle], null); + +const combinedStyle5: StyleProp = StyleSheet.compose( + composeTextStyle, + Math.random() < 0.5 ? composeTextStyle : null, +); + +const combinedStyle6: StyleProp = StyleSheet.compose( + null, + null, +); + +// The following use of the compose method is invalid: +// @ts-expect-error +const combinedStyle7 = StyleSheet.compose(composeImageStyle, composeTextStyle); + +// @ts-expect-error +const combinedStyle8: StyleProp = StyleSheet.compose( + composeTextStyle, + composeTextStyle, +); + +// @ts-expect-error +const combinedStyle9: StyleProp = StyleSheet.compose( + [composeTextStyle], + null, +); + +// @ts-expect-error +const combinedStyle10: StyleProp = StyleSheet.compose( + Math.random() < 0.5 ? composeTextStyle : null, + null, +); + +const testNativeSyntheticEvent = ( + e: NativeSyntheticEvent, +): void => { + e.isDefaultPrevented(); + e.preventDefault(); + e.isPropagationStopped(); + e.stopPropagation(); + e.persist(); + e.cancelable; + e.bubbles; + e.currentTarget; + e.defaultPrevented; + e.eventPhase; + e.isTrusted; + e.nativeEvent; + e.target; + e.timeStamp; + e.type; + e.nativeEvent; +}; + +function eventHandler(e: T) {} + +function handler(e: GestureResponderEvent) { + eventHandler(e); +} + +type ElementProps = C extends React.Component ? P : never; + +class CustomView extends React.Component { + render() { + return ( + + Custom View + + ); + } +} + +class Welcome extends React.Component & {color: string}> { + rootViewRef = React.useRef(null); + customViewRef = React.useRef(null); + + testNativeMethods() { + if (this.rootViewRef.current != null) { + this.rootViewRef.current.setNativeProps({}); + this.rootViewRef.current.measure( + (x: number, y: number, width: number, height: number) => {}, + ); + } + } + + testFindNodeHandle() { + if (this.rootViewRef.current != null) { + const nativeComponentHandle = findNodeHandle(this.rootViewRef.current); + } + + if (this.customViewRef.current != null) { + const customComponentHandle = findNodeHandle(this.customViewRef.current); + const fromHandle = findNodeHandle(customComponentHandle); + } + } + + render() { + const {color, ...props} = this.props; + return ( + + Welcome to React Native + + To get started, edit index.ios.js + + + Press Cmd+R to reload,{'\n'} + Cmd+D or shake for dev menu + + + + ); + } +} + +export default Welcome; + +// TouchableTest +function TouchableTest() { + function basicUsage() { + if (Touchable.TOUCH_TARGET_DEBUG) { + return Touchable.renderDebugView({ + color: 'mediumspringgreen', + hitSlop: {bottom: 5, top: 5}, + }); + } + } + + function defaultHitSlop() { + return Touchable.renderDebugView({ + color: 'red', + }); + } +} + +// TouchableNativeFeedbackTest +export class TouchableNativeFeedbackTest extends React.Component { + onPressButton = (e: GestureResponderEvent) => { + e.persist(); + e.isPropagationStopped(); + e.isDefaultPrevented(); + }; + + render() { + return ( + <> + + + Button + + + + + Button + + + + + Button + + + + + Button + + + + + Button + + + + + Button + + + + + Button + + + + ); + } +} + +// PressableTest +export class PressableTest extends React.Component<{}> { + private readonly myRef: React.RefObject = React.createRef(); + + onPressButton = (e: GestureResponderEvent) => { + e.persist(); + e.isPropagationStopped(); + e.isDefaultPrevented(); + }; + + render() { + return ( + <> + + + Button + + + {/* Style function */} + ({ + backgroundColor: state.pressed ? 'red' : 'blue', + })}> + + Button + + + {/* Children function */} + ({ + backgroundColor: state.pressed ? 'red' : 'blue', + })}> + {state => + state.pressed ? ( + + Pressed + + ) : ( + + Not Pressed + + ) + } + + {/* Android Ripple */} + + + Button + + + + ); + } +} + +// App State +function appStateListener(state: string) { + console.log('New state: ' + state); +} + +function appStateTest() { + console.log('Current state: ' + AppState.currentState); + AppState.addEventListener('change', appStateListener); + AppState.addEventListener('blur', appStateListener); + AppState.addEventListener('focus', appStateListener); +} + +let appState: AppStateStatus = 'active'; +appState = 'background'; +appState = 'inactive'; +appState = 'unknown'; +appState = 'extension'; + +const AppStateExample = () => { + const appState = React.useRef(AppState.currentState); + const [appStateVisible, setAppStateVisible] = React.useState( + appState.current, + ); + const appStateIsAvailable = AppState.isAvailable; + + React.useEffect(() => { + const subscription = AppState.addEventListener('change', nextAppState => { + if ( + appState.current.match(/inactive|background/) && + nextAppState === 'active' + ) { + console.log('App has come to the foreground!'); + } + + appState.current = nextAppState; + setAppStateVisible(appState.current); + console.log('AppState', appState.current); + }); + + return () => { + subscription.remove(); + }; + }, []); + + return ( + + Current state is: {appStateVisible} + Available: {appStateIsAvailable} + + ); +}; + +// ViewPagerAndroid +export class ViewPagerAndroidTest { + render() { + return ( + { + console.log(`position: ${e.nativeEvent.position}`); + console.log(`offset: ${e.nativeEvent.offset}`); + }} + onPageSelected={e => { + console.log(`position: ${e.nativeEvent.position}`); + }} + /> + ); + } +} + +const profiledJSONParse = Systrace.measure('JSON', 'parse', JSON.parse); +profiledJSONParse('[]'); + +InteractionManager.runAfterInteractions(() => { + // ... +}).then(() => 'done'); + +export class FlatListTest extends React.Component, {}> { + list: FlatList | null = null; + + componentDidMount(): void { + if (this.list) { + this.list.flashScrollIndicators(); + } + } + + _renderItem = (rowData: any) => { + return ( + + {rowData.item} + + ); + }; + _cellRenderer = ({children}: any) => { + return {children}; + }; + + _renderSeparator = () => ( + + ); + + render() { + return ( + (this.list = list)} + data={[1, 2, 3, 4, 5]} + renderItem={this._renderItem} + ItemSeparatorComponent={this._renderSeparator} + ListFooterComponent={null} + ListFooterComponentStyle={[ + {padding: 8}, + [{backgroundColor: 'transparent'}], + ]} + ListHeaderComponent={null} + ListHeaderComponentStyle={[ + {padding: 8}, + [{backgroundColor: 'transparent'}], + ]} + CellRendererComponent={this._cellRenderer} + fadingEdgeLength={200} + /> + ); + } +} + +export class SectionListTest extends React.Component< + SectionListProps, + {} +> { + myList: React.RefObject>; + + constructor(props: SectionListProps) { + super(props); + this.myList = React.createRef(); + } + + scrollMe = () => { + this.myList.current && + this.myList.current.scrollToLocation({itemIndex: 0, sectionIndex: 1}); + }; + + render() { + const sections = [ + { + title: 'Section 1', + data: ['A', 'B', 'C', 'D', 'E'], + }, + { + title: 'Section 2', + data: ['A2', 'B2', 'C2', 'D2', 'E2'], + renderItem: (info: {item: string}) => ( + + {info.item} + + ), + }, + ]; + + const cellRenderer = ({children}: any) => { + return {children}; + }; + + return ( + +