From dd9974bbb86f14898c3f352672dd7232492802a2 Mon Sep 17 00:00:00 2001 From: lauren Date: Tue, 25 Feb 2025 12:08:46 -0500 Subject: [PATCH 01/18] [forgive] Scaffold workspaces (#31917) Basic workspace setup for Forgive. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/31917). * #31918 * #31927 * __->__ #31917 --- .github/workflows/compiler_typescript.yml | 3 + .../react-forgive/client/package.json | 22 + .../packages/react-forgive/client/yarn.lock | 59 +++ compiler/packages/react-forgive/package.json | 57 +++ .../react-forgive/server/package.json | 20 + .../react-forgive/server/src/index.ts | 6 + .../react-forgive/server/tsconfig.json | 13 + .../packages/react-forgive/server/yarn.lock | 33 ++ compiler/yarn.lock | 460 +++++++++++++++++- 9 files changed, 672 insertions(+), 1 deletion(-) create mode 100644 compiler/packages/react-forgive/client/package.json create mode 100644 compiler/packages/react-forgive/client/yarn.lock create mode 100644 compiler/packages/react-forgive/package.json create mode 100644 compiler/packages/react-forgive/server/package.json create mode 100644 compiler/packages/react-forgive/server/src/index.ts create mode 100644 compiler/packages/react-forgive/server/tsconfig.json create mode 100644 compiler/packages/react-forgive/server/yarn.lock diff --git a/.github/workflows/compiler_typescript.yml b/.github/workflows/compiler_typescript.yml index 95f8f1f26e112..6d9fa973350af 100644 --- a/.github/workflows/compiler_typescript.yml +++ b/.github/workflows/compiler_typescript.yml @@ -93,4 +93,7 @@ jobs: path: "**/node_modules" key: compiler-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }} - run: yarn install --frozen-lockfile + - run: xvfb-run -a yarn workspace ${{ matrix.workspace_name }} test + if: runner.os == 'Linux' && matrix.workspace_name == 'react-forgive' - run: yarn workspace ${{ matrix.workspace_name }} test + if: runner.os != 'Linux' && matrix.workspace_name != 'react-forgive' diff --git a/compiler/packages/react-forgive/client/package.json b/compiler/packages/react-forgive/client/package.json new file mode 100644 index 0000000000000..c90cee4b423d9 --- /dev/null +++ b/compiler/packages/react-forgive/client/package.json @@ -0,0 +1,22 @@ +{ + "private": "true", + "name": "react-forgive-client", + "version": "0.0.0", + "description": "Experimental LSP client", + "license": "MIT", + "scripts": { + "build": "echo 'no build'", + "test": "echo 'no tests'" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/facebook/react.git", + "directory": "compiler/packages/react-forgive-client" + }, + "dependencies": { + "vscode-languageclient": "^9.0.1" + }, + "devDependencies": { + "@types/vscode": "^1.95.0" + } +} diff --git a/compiler/packages/react-forgive/client/yarn.lock b/compiler/packages/react-forgive/client/yarn.lock new file mode 100644 index 0000000000000..b96751788c77b --- /dev/null +++ b/compiler/packages/react-forgive/client/yarn.lock @@ -0,0 +1,59 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/vscode@^1.95.0": + version "1.96.0" + resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.96.0.tgz#3181004bf25d71677ae4aacdd7605a3fd7edf08e" + integrity sha512-qvZbSZo+K4ZYmmDuaodMbAa67Pl6VDQzLKFka6rq+3WUTY4Kro7Bwoi0CuZLO/wema0ygcmpwow7zZfPJTs5jg== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +minimatch@^5.1.0: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +semver@^7.3.7: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +vscode-jsonrpc@8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz#f43dfa35fb51e763d17cd94dcca0c9458f35abf9" + integrity sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA== + +vscode-languageclient@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz#cdfe20267726c8d4db839dc1e9d1816e1296e854" + integrity sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA== + dependencies: + minimatch "^5.1.0" + semver "^7.3.7" + vscode-languageserver-protocol "3.17.5" + +vscode-languageserver-protocol@3.17.5: + version "3.17.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz#864a8b8f390835572f4e13bd9f8313d0e3ac4bea" + integrity sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg== + dependencies: + vscode-jsonrpc "8.2.0" + vscode-languageserver-types "3.17.5" + +vscode-languageserver-types@3.17.5: + version "3.17.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a" + integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg== diff --git a/compiler/packages/react-forgive/package.json b/compiler/packages/react-forgive/package.json new file mode 100644 index 0000000000000..30aec4235523e --- /dev/null +++ b/compiler/packages/react-forgive/package.json @@ -0,0 +1,57 @@ +{ + "name": "react-forgive", + "displayName": "React Analyzer", + "description": "React LSP", + "license": "MIT", + "version": "0.0.0", + "repository": { + "type": "git", + "url": "git+https://github.com/facebook/react.git", + "directory": "compiler/packages/react-forgive" + }, + "categories": [ + "Programming Languages" + ], + "keywords": [ + "react", + "react analyzer", + "react compiler" + ], + "publisher": "Meta", + "engines": { + "vscode": "^1.75.0" + }, + "activationEvents": [ + "onLanguage:javascriptreact", + "onLanguage:typescriptreact" + ], + "main": "./dist/extension.js", + "contributes": { + "commands": [ + { + "command": "react-forgive.toggleAll", + "title": "React Analyzer: Toggle on/off" + } + ] + }, + "scripts": { + "compile": "yarn run esbuild-base -- --sourcemap", + "dev": "yarn run package && yarn run install-ext", + "esbuild-base": "esbuild ./src/extension.ts --bundle --outfile=dist/extension.js --external:vscode --format=cjs --platform=node", + "install-ext": "code --install-extension vscode-react-compiler-0.0.1.vsix", + "lint": "echo 'no tests'", + "package": "vsce package", + "postinstall": "cd client && yarn install && cd ../server && yarn install && cd ..", + "pretest": "yarn run compile && yarn run lint", + "test": "echo 'no tests'", + "test-compile": "tsc -p ./", + "vscode:prepublish": "yarn run esbuild-base -- --minify", + "watch": "yarn run esbuild-base -- --sourcemap --watch" + }, + "devDependencies": { + "@eslint/js": "^9.13.0", + "@types/node": "^20", + "eslint": "^9.13.0", + "typescript-eslint": "^8.16.0" + } +} diff --git a/compiler/packages/react-forgive/server/package.json b/compiler/packages/react-forgive/server/package.json new file mode 100644 index 0000000000000..4e4d54debbaa5 --- /dev/null +++ b/compiler/packages/react-forgive/server/package.json @@ -0,0 +1,20 @@ +{ + "private": "true", + "name": "react-forgive-server", + "version": "0.0.0", + "description": "Experimental LSP server", + "license": "MIT", + "scripts": { + "build": "echo 'no build'", + "test": "echo 'no tests'" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/facebook/react.git", + "directory": "compiler/packages/react-forgive-server" + }, + "dependencies": { + "vscode-languageserver": "^9.0.1", + "vscode-languageserver-textdocument": "^1.0.12" + } +} diff --git a/compiler/packages/react-forgive/server/src/index.ts b/compiler/packages/react-forgive/server/src/index.ts new file mode 100644 index 0000000000000..a265a953eed3d --- /dev/null +++ b/compiler/packages/react-forgive/server/src/index.ts @@ -0,0 +1,6 @@ +/** + * 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. + */ diff --git a/compiler/packages/react-forgive/server/tsconfig.json b/compiler/packages/react-forgive/server/tsconfig.json new file mode 100644 index 0000000000000..ccd17f5dff457 --- /dev/null +++ b/compiler/packages/react-forgive/server/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/strictest/tsconfig.json", + "compilerOptions": { + "module": "CommonJS", + "moduleResolution": "node", + "outDir": "dist", + "jsx": "react-jsxdev", + "lib": ["ES2020"], + "target": "ES2020", + }, + "exclude": ["node_modules", ".vscode-test"], + "include": ["src/**/*.ts"], +} diff --git a/compiler/packages/react-forgive/server/yarn.lock b/compiler/packages/react-forgive/server/yarn.lock new file mode 100644 index 0000000000000..fd60ddd6ad5f1 --- /dev/null +++ b/compiler/packages/react-forgive/server/yarn.lock @@ -0,0 +1,33 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +vscode-jsonrpc@8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz#f43dfa35fb51e763d17cd94dcca0c9458f35abf9" + integrity sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA== + +vscode-languageserver-protocol@3.17.5: + version "3.17.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz#864a8b8f390835572f4e13bd9f8313d0e3ac4bea" + integrity sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg== + dependencies: + vscode-jsonrpc "8.2.0" + vscode-languageserver-types "3.17.5" + +vscode-languageserver-textdocument@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz#457ee04271ab38998a093c68c2342f53f6e4a631" + integrity sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA== + +vscode-languageserver-types@3.17.5: + version "3.17.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a" + integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg== + +vscode-languageserver@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz#500aef82097eb94df90d008678b0b6b5f474015b" + integrity sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g== + dependencies: + vscode-languageserver-protocol "3.17.5" diff --git a/compiler/yarn.lock b/compiler/yarn.lock index b5bd5f8eaf7b4..fe1d22eac864c 100644 --- a/compiler/yarn.lock +++ b/compiler/yarn.lock @@ -1714,86 +1714,171 @@ enabled "2.0.x" kuler "^2.0.0" +"@esbuild/aix-ppc64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz#b57697945b50e99007b4c2521507dc613d4a648c" + integrity sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw== + "@esbuild/aix-ppc64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz#499600c5e1757a524990d5d92601f0ac3ce87f64" integrity sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ== +"@esbuild/android-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz#1add7e0af67acefd556e407f8497e81fddad79c0" + integrity sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w== + "@esbuild/android-arm64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz#b9b8231561a1dfb94eb31f4ee056b92a985c324f" integrity sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g== +"@esbuild/android-arm@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.0.tgz#ab7263045fa8e090833a8e3c393b60d59a789810" + integrity sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew== + "@esbuild/android-arm@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.0.tgz#ca6e7888942505f13e88ac9f5f7d2a72f9facd2b" integrity sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g== +"@esbuild/android-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.0.tgz#e8f8b196cfdfdd5aeaebbdb0110983460440e705" + integrity sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ== + "@esbuild/android-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.0.tgz#e765ea753bac442dfc9cb53652ce8bd39d33e163" integrity sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg== +"@esbuild/darwin-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz#2d0d9414f2acbffd2d86e98253914fca603a53dd" + integrity sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw== + "@esbuild/darwin-arm64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz#fa394164b0d89d4fdc3a8a21989af70ef579fa2c" integrity sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw== +"@esbuild/darwin-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz#33087aab31a1eb64c89daf3d2cf8ce1775656107" + integrity sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA== + "@esbuild/darwin-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz#91979d98d30ba6e7d69b22c617cc82bdad60e47a" integrity sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg== +"@esbuild/freebsd-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz#bb76e5ea9e97fa3c753472f19421075d3a33e8a7" + integrity sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA== + "@esbuild/freebsd-arm64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz#b97e97073310736b430a07b099d837084b85e9ce" integrity sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w== +"@esbuild/freebsd-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz#e0e2ce9249fdf6ee29e5dc3d420c7007fa579b93" + integrity sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ== + "@esbuild/freebsd-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz#f3b694d0da61d9910ec7deff794d444cfbf3b6e7" integrity sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A== +"@esbuild/linux-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz#d1b2aa58085f73ecf45533c07c82d81235388e75" + integrity sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g== + "@esbuild/linux-arm64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz#f921f699f162f332036d5657cad9036f7a993f73" integrity sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg== +"@esbuild/linux-arm@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz#8e4915df8ea3e12b690a057e77a47b1d5935ef6d" + integrity sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw== + "@esbuild/linux-arm@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz#cc49305b3c6da317c900688995a4050e6cc91ca3" integrity sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg== +"@esbuild/linux-ia32@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz#8200b1110666c39ab316572324b7af63d82013fb" + integrity sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA== + "@esbuild/linux-ia32@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz#3e0736fcfab16cff042dec806247e2c76e109e19" integrity sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg== +"@esbuild/linux-loong64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz#6ff0c99cf647504df321d0640f0d32e557da745c" + integrity sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g== + "@esbuild/linux-loong64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz#ea2bf730883cddb9dfb85124232b5a875b8020c7" integrity sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw== +"@esbuild/linux-mips64el@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz#3f720ccd4d59bfeb4c2ce276a46b77ad380fa1f3" + integrity sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA== + "@esbuild/linux-mips64el@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz#4cababb14eede09248980a2d2d8b966464294ff1" integrity sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ== +"@esbuild/linux-ppc64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz#9d6b188b15c25afd2e213474bf5f31e42e3aa09e" + integrity sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ== + "@esbuild/linux-ppc64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz#8860a4609914c065373a77242e985179658e1951" integrity sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw== +"@esbuild/linux-riscv64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz#f989fdc9752dfda286c9cd87c46248e4dfecbc25" + integrity sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw== + "@esbuild/linux-riscv64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz#baf26e20bb2d38cfb86ee282dff840c04f4ed987" integrity sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA== +"@esbuild/linux-s390x@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz#29ebf87e4132ea659c1489fce63cd8509d1c7319" + integrity sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g== + "@esbuild/linux-s390x@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz#8323afc0d6cb1b6dc6e9fd21efd9e1542c3640a4" integrity sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA== +"@esbuild/linux-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz#4af48c5c0479569b1f359ffbce22d15f261c0cef" + integrity sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA== + "@esbuild/linux-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz#08fcf60cb400ed2382e9f8e0f5590bac8810469a" @@ -1804,36 +1889,71 @@ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz#935c6c74e20f7224918fbe2e6c6fe865b6c6ea5b" integrity sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw== +"@esbuild/netbsd-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz#1ae73d23cc044a0ebd4f198334416fb26c31366c" + integrity sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg== + "@esbuild/netbsd-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz#414677cef66d16c5a4d210751eb2881bb9c1b62b" integrity sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA== +"@esbuild/openbsd-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz#5d904a4f5158c89859fd902c427f96d6a9e632e2" + integrity sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg== + "@esbuild/openbsd-arm64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz#8fd55a4d08d25cdc572844f13c88d678c84d13f7" integrity sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw== +"@esbuild/openbsd-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz#4c8aa88c49187c601bae2971e71c6dc5e0ad1cdf" + integrity sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q== + "@esbuild/openbsd-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz#0c48ddb1494bbc2d6bcbaa1429a7f465fa1dedde" integrity sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg== +"@esbuild/sunos-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz#8ddc35a0ea38575fa44eda30a5ee01ae2fa54dd4" + integrity sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA== + "@esbuild/sunos-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz#86ff9075d77962b60dd26203d7352f92684c8c92" integrity sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg== +"@esbuild/win32-arm64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz#6e79c8543f282c4539db684a207ae0e174a9007b" + integrity sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA== + "@esbuild/win32-arm64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz#849c62327c3229467f5b5cd681bf50588442e96c" integrity sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw== +"@esbuild/win32-ia32@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz#057af345da256b7192d18b676a02e95d0fa39103" + integrity sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw== + "@esbuild/win32-ia32@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz#f62eb480cd7cca088cb65bb46a6db25b725dc079" integrity sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA== +"@esbuild/win32-x64@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz#168ab1c7e1c318b922637fad8f339d48b01e1244" + integrity sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA== + "@esbuild/win32-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz#c8e119a30a7c8d60b9d2e22d2073722dde3b710b" @@ -1851,11 +1971,32 @@ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.1.tgz#a547badfc719eb3e5f4b556325e542fbe9d7a18f" integrity sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q== +"@eslint-community/regexpp@^4.12.1": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + "@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": version "4.10.0" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== +"@eslint/config-array@^0.19.0": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.1.tgz#734aaea2c40be22bbb1f2a9dac687c57a6a4c984" + integrity sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA== + dependencies: + "@eslint/object-schema" "^2.1.5" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/core@^0.9.0": + version "0.9.1" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.9.1.tgz#31763847308ef6b7084a4505573ac9402c51f9d1" + integrity sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q== + dependencies: + "@types/json-schema" "^7.0.15" + "@eslint/eslintrc@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" @@ -1871,6 +2012,21 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" +"@eslint/eslintrc@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c" + integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + "@eslint/js@8.57.0": version "8.57.0" resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" @@ -1881,6 +2037,23 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== +"@eslint/js@9.17.0", "@eslint/js@^9.13.0": + version "9.17.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.17.0.tgz#1523e586791f80376a6f8398a3964455ecc651ec" + integrity sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w== + +"@eslint/object-schema@^2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.5.tgz#8670a8f6258a2be5b2c620ff314a1d984c23eb2e" + integrity sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ== + +"@eslint/plugin-kit@^0.2.3": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz#2b78e7bb3755784bb13faa8932a1d994d6537792" + integrity sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg== + dependencies: + levn "^0.4.1" + "@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" @@ -1893,6 +2066,19 @@ dependencies: "@hapi/hoek" "^9.0.0" +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.6" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e" + integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.3.0" + "@humanwhocodes/config-array@^0.11.14": version "0.11.14" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" @@ -1926,6 +2112,16 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@humanwhocodes/retry@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" + integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== + +"@humanwhocodes/retry@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b" + integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== + "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" @@ -2812,6 +3008,11 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== +"@types/estree@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== + "@types/fbt@^1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@types/fbt/-/fbt-1.0.4.tgz#0d9e427f91fcff46bdcf2ca42a63343096565451" @@ -2891,7 +3092,7 @@ "@types/tough-cookie" "*" parse5 "^7.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.12": +"@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.15": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -2906,6 +3107,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.19.tgz#ad83aa9b7af470fab7e0f562be87e97dc8ffe08e" integrity sha512-Sq1itGUKUX1ap7GgZlrzdBydjbsJL/NSQt/4wkAxUJ7/OS5c2WkoN6WSpWc2Yc5wtKMZOUA0VCs/j2XJadN3HA== +"@types/node@^20": + version "20.17.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.10.tgz#3f7166190aece19a0d1d364d75c8b0b5778c1e18" + integrity sha512-/jrvh5h6NXhEauFFexRin69nA0uHJ5gwk4iDivp/DeoEua3uwCUto6PC86IpRITBOs4+6i2I56K5x5b6WYGXHA== + dependencies: + undici-types "~6.19.2" + "@types/node@^20.2.5": version "20.2.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb" @@ -2981,6 +3189,21 @@ dependencies: "@types/yargs-parser" "*" +"@typescript-eslint/eslint-plugin@8.18.1": + version "8.18.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.1.tgz#992e5ac1553ce20d0d46aa6eccd79dc36dedc805" + integrity sha512-Ncvsq5CT3Gvh+uJG0Lwlho6suwDfUXH0HztslDf5I+F2wAFAZMRwYLEorumpKLzmO2suAXZ/td1tBg4NZIi9CQ== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.18.1" + "@typescript-eslint/type-utils" "8.18.1" + "@typescript-eslint/utils" "8.18.1" + "@typescript-eslint/visitor-keys" "8.18.1" + graphemer "^1.4.0" + ignore "^5.3.1" + natural-compare "^1.4.0" + ts-api-utils "^1.3.0" + "@typescript-eslint/eslint-plugin@^7.4.0": version "7.4.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz#de61c3083842fc6ac889d2fc83c9a96b55ab8328" @@ -3013,6 +3236,17 @@ natural-compare "^1.4.0" ts-api-utils "^1.3.0" +"@typescript-eslint/parser@8.18.1": + version "8.18.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.18.1.tgz#c258bae062778b7696793bc492249027a39dfb95" + integrity sha512-rBnTWHCdbYM2lh7hjyXqxk70wvon3p2FyaniZuey5TrcGBpfhVp0OxOa6gxr9Q9YhZFKyfbEnxc24ZnVbbUkCA== + dependencies: + "@typescript-eslint/scope-manager" "8.18.1" + "@typescript-eslint/types" "8.18.1" + "@typescript-eslint/typescript-estree" "8.18.1" + "@typescript-eslint/visitor-keys" "8.18.1" + debug "^4.3.4" + "@typescript-eslint/parser@^7.4.0": version "7.4.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.4.0.tgz#540f4321de1e52b886c0fa68628af1459954c1f1" @@ -3043,6 +3277,14 @@ "@typescript-eslint/types" "7.4.0" "@typescript-eslint/visitor-keys" "7.4.0" +"@typescript-eslint/scope-manager@8.18.1": + version "8.18.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.18.1.tgz#52cedc3a8178d7464a70beffed3203678648e55b" + integrity sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ== + dependencies: + "@typescript-eslint/types" "8.18.1" + "@typescript-eslint/visitor-keys" "8.18.1" + "@typescript-eslint/scope-manager@8.7.0": version "8.7.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz#90ee7bf9bc982b9260b93347c01a8bc2b595e0b8" @@ -3061,6 +3303,16 @@ debug "^4.3.4" ts-api-utils "^1.0.1" +"@typescript-eslint/type-utils@8.18.1": + version "8.18.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.18.1.tgz#10f41285475c0bdee452b79ff7223f0e43a7781e" + integrity sha512-jAhTdK/Qx2NJPNOTxXpMwlOiSymtR2j283TtPqXkKBdH8OAMmhiUfP0kJjc/qSE51Xrq02Gj9NY7MwK+UxVwHQ== + dependencies: + "@typescript-eslint/typescript-estree" "8.18.1" + "@typescript-eslint/utils" "8.18.1" + debug "^4.3.4" + ts-api-utils "^1.3.0" + "@typescript-eslint/type-utils@8.7.0": version "8.7.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz#d56b104183bdcffcc434a23d1ce26cde5e42df93" @@ -3076,6 +3328,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.4.0.tgz#ee9dafa75c99eaee49de6dcc9348b45d354419b6" integrity sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw== +"@typescript-eslint/types@8.18.1": + version "8.18.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.18.1.tgz#d7f4f94d0bba9ebd088de840266fcd45408a8fff" + integrity sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw== + "@typescript-eslint/types@8.7.0": version "8.7.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.7.0.tgz#21d987201c07b69ce7ddc03451d7196e5445ad19" @@ -3095,6 +3352,20 @@ semver "^7.5.4" ts-api-utils "^1.0.1" +"@typescript-eslint/typescript-estree@8.18.1": + version "8.18.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.1.tgz#2a86cd64b211a742f78dfa7e6f4860413475367e" + integrity sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg== + dependencies: + "@typescript-eslint/types" "8.18.1" + "@typescript-eslint/visitor-keys" "8.18.1" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" + "@typescript-eslint/typescript-estree@8.7.0": version "8.7.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz#6c7db6baa4380b937fa81466c546d052f362d0e8" @@ -3122,6 +3393,16 @@ "@typescript-eslint/typescript-estree" "7.4.0" semver "^7.5.4" +"@typescript-eslint/utils@8.18.1": + version "8.18.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.18.1.tgz#c4199ea23fc823c736e2c96fd07b1f7235fa92d5" + integrity sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "8.18.1" + "@typescript-eslint/types" "8.18.1" + "@typescript-eslint/typescript-estree" "8.18.1" + "@typescript-eslint/utils@8.7.0": version "8.7.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.7.0.tgz#cef3f70708b5b5fd7ed8672fc14714472bd8a011" @@ -3140,6 +3421,14 @@ "@typescript-eslint/types" "7.4.0" eslint-visitor-keys "^3.4.1" +"@typescript-eslint/visitor-keys@8.18.1": + version "8.18.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.1.tgz#344b4f6bc83f104f514676facf3129260df7610a" + integrity sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ== + dependencies: + "@typescript-eslint/types" "8.18.1" + eslint-visitor-keys "^4.2.0" + "@typescript-eslint/visitor-keys@8.7.0": version "8.7.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz#5e46f1777f9d69360a883c1a56ac3c511c9659a8" @@ -3186,6 +3475,11 @@ acorn@^7.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn@^8.14.0: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== + acorn@^8.4.1, acorn@^8.7.1: version "8.8.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" @@ -3867,6 +4161,15 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + cssom@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36" @@ -4105,6 +4408,36 @@ es5-ext@0.8.x: resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.8.2.tgz#aba8d9e1943a895ac96837a62a39b3f55ecd94ab" integrity sha512-H19ompyhnKiBdjHR1DPHvf5RHgHPmJaY9JNzFGbMbPgdsUkvnUCN1Ke8J4Y0IMyTwFM2M9l4h2GoHwzwpSmXbA== +esbuild@^0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.24.0.tgz#f2d470596885fcb2e91c21eb3da3b3c89c0b55e7" + integrity sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ== + optionalDependencies: + "@esbuild/aix-ppc64" "0.24.0" + "@esbuild/android-arm" "0.24.0" + "@esbuild/android-arm64" "0.24.0" + "@esbuild/android-x64" "0.24.0" + "@esbuild/darwin-arm64" "0.24.0" + "@esbuild/darwin-x64" "0.24.0" + "@esbuild/freebsd-arm64" "0.24.0" + "@esbuild/freebsd-x64" "0.24.0" + "@esbuild/linux-arm" "0.24.0" + "@esbuild/linux-arm64" "0.24.0" + "@esbuild/linux-ia32" "0.24.0" + "@esbuild/linux-loong64" "0.24.0" + "@esbuild/linux-mips64el" "0.24.0" + "@esbuild/linux-ppc64" "0.24.0" + "@esbuild/linux-riscv64" "0.24.0" + "@esbuild/linux-s390x" "0.24.0" + "@esbuild/linux-x64" "0.24.0" + "@esbuild/netbsd-x64" "0.24.0" + "@esbuild/openbsd-arm64" "0.24.0" + "@esbuild/openbsd-x64" "0.24.0" + "@esbuild/sunos-x64" "0.24.0" + "@esbuild/win32-arm64" "0.24.0" + "@esbuild/win32-ia32" "0.24.0" + "@esbuild/win32-x64" "0.24.0" + esbuild@^0.25.0: version "0.25.0" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.0.tgz#0de1787a77206c5a79eeb634a623d39b5006ce92" @@ -4181,6 +4514,14 @@ eslint-scope@^7.2.2: esrecurse "^4.3.0" estraverse "^5.2.0" +eslint-scope@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442" + integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + eslint-visitor-keys@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" @@ -4196,6 +4537,11 @@ eslint-visitor-keys@^3.4.3: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== +eslint-visitor-keys@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" + integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== + eslint@8.57.0: version "8.57.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" @@ -4284,6 +4630,55 @@ eslint@^8.57.1: strip-ansi "^6.0.1" text-table "^0.2.0" +eslint@^9.13.0: + version "9.17.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.17.0.tgz#faa1facb5dd042172fdc520106984b5c2421bb0c" + integrity sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.19.0" + "@eslint/core" "^0.9.0" + "@eslint/eslintrc" "^3.2.0" + "@eslint/js" "9.17.0" + "@eslint/plugin-kit" "^0.2.3" + "@humanfs/node" "^0.16.6" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.4.1" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.6" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.2.0" + eslint-visitor-keys "^4.2.0" + espree "^10.3.0" + esquery "^1.5.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^8.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + json-stable-stringify-without-jsonify "^1.0.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + +espree@^10.0.1, espree@^10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" + integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== + dependencies: + acorn "^8.14.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.0" + espree@^9.6.0, espree@^9.6.1: version "9.6.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" @@ -4305,6 +4700,13 @@ esquery@^1.4.2: dependencies: estraverse "^5.1.0" +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" @@ -4470,6 +4872,13 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + fill-range@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" @@ -4535,11 +4944,24 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + flatted@^3.1.0: version "3.2.7" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== +flatted@^3.2.9: + version "3.3.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27" + integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA== + flow-enums-runtime@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.4.tgz#038635c679030d08d4c197db29a2fad62722072f" @@ -4714,6 +5136,11 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" @@ -6277,6 +6704,11 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + json-diff@^0.5.4: version "0.5.5" resolved "https://registry.yarnpkg.com/json-diff/-/json-diff-0.5.5.tgz#24658ad200dbdd64ae8a56baf4d87b2b33d7196e" @@ -6318,6 +6750,13 @@ keypress@~0.2.1: resolved "https://registry.yarnpkg.com/keypress/-/keypress-0.2.1.tgz#1e80454250018dbad4c3fe94497d6e67b6269c77" integrity sha512-HjorDJFNhnM4SicvaUXac0X77NiskggxJdesG72+O5zBKpSqKFCrqmndKVqpu3pFqkla0St6uGk8Ju0sCurrmg== +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + kind-of@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" @@ -7747,11 +8186,30 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== +typescript-eslint@^8.16.0: + version "8.18.1" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.18.1.tgz#197b284b6769678ed77d9868df180eeaf61108eb" + integrity sha512-Mlaw6yxuaDEPQvb/2Qwu3/TfgeBHy9iTJ3mTwe7OvpPmF6KPQjVOfGyEJpPv6Ez2C34OODChhXrzYw/9phI0MQ== + dependencies: + "@typescript-eslint/eslint-plugin" "8.18.1" + "@typescript-eslint/parser" "8.18.1" + "@typescript-eslint/utils" "8.18.1" + typescript@^5.4.3: version "5.4.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff" integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== +typescript@^5.7.2: + version "5.7.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6" + integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" From 58def9f2e6ddd2ae3dfa9606711f1aea63a220c1 Mon Sep 17 00:00:00 2001 From: lauren Date: Tue, 25 Feb 2025 12:16:10 -0500 Subject: [PATCH 02/18] [forgive] Add build scripts (#31927) Adds basic build scripts. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/31927). * #31918 * __->__ #31927 --- compiler/packages/react-forgive/.vscodeignore | 4 ++ compiler/packages/react-forgive/package.json | 16 ++--- .../packages/react-forgive/scripts/build.mjs | 58 +++++++++++++++++++ .../packages/react-forgive/scripts/client.mjs | 39 +++++++++++++ .../packages/react-forgive/scripts/server.mjs | 39 +++++++++++++ 5 files changed, 148 insertions(+), 8 deletions(-) create mode 100644 compiler/packages/react-forgive/.vscodeignore create mode 100755 compiler/packages/react-forgive/scripts/build.mjs create mode 100644 compiler/packages/react-forgive/scripts/client.mjs create mode 100644 compiler/packages/react-forgive/scripts/server.mjs diff --git a/compiler/packages/react-forgive/.vscodeignore b/compiler/packages/react-forgive/.vscodeignore new file mode 100644 index 0000000000000..91f9572794cd5 --- /dev/null +++ b/compiler/packages/react-forgive/.vscodeignore @@ -0,0 +1,4 @@ +**/node_modules +client +server +scripts diff --git a/compiler/packages/react-forgive/package.json b/compiler/packages/react-forgive/package.json index 30aec4235523e..bc5f7310e98fe 100644 --- a/compiler/packages/react-forgive/package.json +++ b/compiler/packages/react-forgive/package.json @@ -35,23 +35,23 @@ ] }, "scripts": { - "compile": "yarn run esbuild-base -- --sourcemap", + "build": "yarn run compile", + "compile": "rimraf dist && concurrently -n server,client \"scripts/build.mjs -t server\" \"scripts/build.mjs -t client\"", "dev": "yarn run package && yarn run install-ext", - "esbuild-base": "esbuild ./src/extension.ts --bundle --outfile=dist/extension.js --external:vscode --format=cjs --platform=node", - "install-ext": "code --install-extension vscode-react-compiler-0.0.1.vsix", + "install-ext": "code --install-extension react-forgive-0.0.0.vsix", "lint": "echo 'no tests'", - "package": "vsce package", + "package": "rm -f react-forgive-0.0.0.vsix && vsce package --yarn", "postinstall": "cd client && yarn install && cd ../server && yarn install && cd ..", "pretest": "yarn run compile && yarn run lint", "test": "echo 'no tests'", - "test-compile": "tsc -p ./", - "vscode:prepublish": "yarn run esbuild-base -- --minify", - "watch": "yarn run esbuild-base -- --sourcemap --watch" + "vscode:prepublish": "yarn run compile", + "watch": "scripts/build.mjs --watch" }, "devDependencies": { "@eslint/js": "^9.13.0", "@types/node": "^20", "eslint": "^9.13.0", - "typescript-eslint": "^8.16.0" + "typescript-eslint": "^8.16.0", + "yargs": "^17.7.2" } } diff --git a/compiler/packages/react-forgive/scripts/build.mjs b/compiler/packages/react-forgive/scripts/build.mjs new file mode 100755 index 0000000000000..5fc8828e6e749 --- /dev/null +++ b/compiler/packages/react-forgive/scripts/build.mjs @@ -0,0 +1,58 @@ +#!/usr/bin/env node + +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import * as esbuild from 'esbuild'; +import yargs from 'yargs'; +import * as Server from './server.mjs'; +import * as Client from './client.mjs'; +import path from 'path'; +import {fileURLToPath} from 'url'; + +const IS_DEV = process.env.NODE_ENV === 'development'; +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const argv = yargs(process.argv.slice(2)) + .choices('t', ['client', 'server']) + .options('w', { + alias: 'watch', + default: false, + type: 'boolean', + }) + .parse(); + +async function main() { + if (argv.w) { + const serverCtx = await esbuild.context(Server.config); + const clientCtx = await esbuild.context(Client.config); + await Promise.all([serverCtx.watch(), clientCtx.watch()]); + console.log('watching for changes...'); + } else { + switch (argv.t) { + case 'server': { + await esbuild.build({ + sourcemap: IS_DEV, + minify: IS_DEV === false, + ...Server.config, + }); + break; + } + case 'client': { + await esbuild.build({ + sourcemap: IS_DEV, + minify: IS_DEV === false, + ...Client.config, + }); + break; + } + } + } +} + +main(); diff --git a/compiler/packages/react-forgive/scripts/client.mjs b/compiler/packages/react-forgive/scripts/client.mjs new file mode 100644 index 0000000000000..9a8987061b391 --- /dev/null +++ b/compiler/packages/react-forgive/scripts/client.mjs @@ -0,0 +1,39 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import path from 'path'; +import {fileURLToPath} from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export const entryPoint = path.join(__dirname, '../client/src/extension.ts'); +export const outfile = path.join(__dirname, '../dist/extension.js'); +export const config = { + entryPoints: [entryPoint], + outfile, + bundle: true, + external: ['vscode'], + format: 'cjs', + platform: 'node', + banner: { + js: `/** + * 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. + * + * @lightSyntaxTransform + * @noflow + * @nolint + * @preventMunge + * @preserve-invariant-messages + */ + +`, + }, +}; diff --git a/compiler/packages/react-forgive/scripts/server.mjs b/compiler/packages/react-forgive/scripts/server.mjs new file mode 100644 index 0000000000000..95afe8770d44b --- /dev/null +++ b/compiler/packages/react-forgive/scripts/server.mjs @@ -0,0 +1,39 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import path from 'path'; +import {fileURLToPath} from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export const entryPoint = path.join(__dirname, '../server/src/index.ts'); +export const outfile = path.join(__dirname, '../dist/extension.js'); +export const config = { + entryPoints: [entryPoint], + outfile, + bundle: true, + external: ['vscode'], + format: 'cjs', + platform: 'node', + banner: { + js: `/** + * 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. + * + * @lightSyntaxTransform + * @noflow + * @nolint + * @preventMunge + * @preserve-invariant-messages + */ + +`, + }, +}; From d42a90cf4f8a9eb9f41939c7d095a6a93b8816dc Mon Sep 17 00:00:00 2001 From: lauren Date: Tue, 25 Feb 2025 12:19:11 -0500 Subject: [PATCH 03/18] [forgive] Init (#31918) Init basic LSP. At the moment the extension doesn't do anything interesting, but it does compile successfully. --- .gitignore | 1 + compiler/.gitignore | 6 +- .../packages/react-forgive/.vscode-test.mjs | 3 + compiler/packages/react-forgive/.yarnrc | 1 + compiler/packages/react-forgive/LICENSE | 21 + .../react-forgive/client/package.json | 2 +- .../react-forgive/client/src/extension.ts | 60 ++ compiler/packages/react-forgive/package.json | 9 +- .../packages/react-forgive/scripts/server.mjs | 2 +- .../react-forgive/server/package.json | 10 +- .../server/src/compiler/index.ts | 58 ++ .../server/src/compiler/options.ts | 25 + .../react-forgive/server/src/index.ts | 87 +++ .../react-forgive/server/tsconfig.json | 14 +- .../packages/react-forgive/server/yarn.lock | 377 ++++++++++ compiler/yarn.lock | 707 +++++++++++++----- 16 files changed, 1184 insertions(+), 199 deletions(-) create mode 100644 compiler/packages/react-forgive/.vscode-test.mjs create mode 100644 compiler/packages/react-forgive/.yarnrc create mode 100644 compiler/packages/react-forgive/LICENSE create mode 100644 compiler/packages/react-forgive/client/src/extension.ts create mode 100644 compiler/packages/react-forgive/server/src/compiler/index.ts create mode 100644 compiler/packages/react-forgive/server/src/compiler/options.ts diff --git a/.gitignore b/.gitignore index 2a20fc2427c98..6432df4f054d8 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ packages/react-devtools-fusebox/dist packages/react-devtools-inline/dist packages/react-devtools-shell/dist packages/react-devtools-timeline/dist + diff --git a/compiler/.gitignore b/compiler/.gitignore index 01003c659c622..d41f59333aa09 100644 --- a/compiler/.gitignore +++ b/compiler/.gitignore @@ -21,4 +21,8 @@ dist .spr.yml testfilter.txt -bundle-oss.sh \ No newline at end of file +bundle-oss.sh + +# forgive +*.vsix +.vscode-test diff --git a/compiler/packages/react-forgive/.vscode-test.mjs b/compiler/packages/react-forgive/.vscode-test.mjs new file mode 100644 index 0000000000000..738bfc71b9ced --- /dev/null +++ b/compiler/packages/react-forgive/.vscode-test.mjs @@ -0,0 +1,3 @@ +import {defineConfig} from '@vscode/test-cli'; + +export default defineConfig({files: 'dist/test/**/*.test.js'}); diff --git a/compiler/packages/react-forgive/.yarnrc b/compiler/packages/react-forgive/.yarnrc new file mode 100644 index 0000000000000..123ac74a0a3de --- /dev/null +++ b/compiler/packages/react-forgive/.yarnrc @@ -0,0 +1 @@ +ignore-engines true diff --git a/compiler/packages/react-forgive/LICENSE b/compiler/packages/react-forgive/LICENSE new file mode 100644 index 0000000000000..b93be90515ccd --- /dev/null +++ b/compiler/packages/react-forgive/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Meta Platforms, Inc. and affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/compiler/packages/react-forgive/client/package.json b/compiler/packages/react-forgive/client/package.json index c90cee4b423d9..a975439726f23 100644 --- a/compiler/packages/react-forgive/client/package.json +++ b/compiler/packages/react-forgive/client/package.json @@ -11,7 +11,7 @@ "repository": { "type": "git", "url": "git+https://github.com/facebook/react.git", - "directory": "compiler/packages/react-forgive-client" + "directory": "compiler/packages/react-forgive" }, "dependencies": { "vscode-languageclient": "^9.0.1" diff --git a/compiler/packages/react-forgive/client/src/extension.ts b/compiler/packages/react-forgive/client/src/extension.ts new file mode 100644 index 0000000000000..402f298fd74c5 --- /dev/null +++ b/compiler/packages/react-forgive/client/src/extension.ts @@ -0,0 +1,60 @@ +import * as path from 'path'; +import {ExtensionContext, window as Window} from 'vscode'; + +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind, +} from 'vscode-languageclient/node'; + +let client: LanguageClient; + +export function activate(context: ExtensionContext) { + const serverModule = context.asAbsolutePath(path.join('dist', 'server.js')); + + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used + const serverOptions: ServerOptions = { + run: { + module: serverModule, + transport: TransportKind.ipc, + }, + debug: { + module: serverModule, + transport: TransportKind.ipc, + }, + }; + + const clientOptions: LanguageClientOptions = { + documentSelector: [ + {scheme: 'file', language: 'javascriptreact'}, + {scheme: 'file', language: 'typescriptreact'}, + ], + progressOnInitialization: true, + }; + + // Create the language client and start the client. + try { + client = new LanguageClient( + 'react-forgive', + 'React Analyzer', + serverOptions, + clientOptions, + ); + } catch { + Window.showErrorMessage( + `React Analyzer couldn't be started. See the output channel for details.`, + ); + return; + } + + client.registerProposedFeatures(); + client.start(); +} + +export function deactivate(): Thenable | undefined { + if (client !== undefined) { + return client.stop(); + } +} diff --git a/compiler/packages/react-forgive/package.json b/compiler/packages/react-forgive/package.json index bc5f7310e98fe..0bf48e232ecf4 100644 --- a/compiler/packages/react-forgive/package.json +++ b/compiler/packages/react-forgive/package.json @@ -19,7 +19,7 @@ ], "publisher": "Meta", "engines": { - "vscode": "^1.75.0" + "vscode": "^1.96.0" }, "activationEvents": [ "onLanguage:javascriptreact", @@ -43,14 +43,19 @@ "package": "rm -f react-forgive-0.0.0.vsix && vsce package --yarn", "postinstall": "cd client && yarn install && cd ../server && yarn install && cd ..", "pretest": "yarn run compile && yarn run lint", - "test": "echo 'no tests'", + "test": "vscode-test", "vscode:prepublish": "yarn run compile", "watch": "scripts/build.mjs --watch" }, "devDependencies": { "@eslint/js": "^9.13.0", + "@types/mocha": "^10.0.10", "@types/node": "^20", + "@types/vscode": "^1.96.0", + "@vscode/test-cli": "^0.0.10", + "@vscode/test-electron": "^2.4.1", "eslint": "^9.13.0", + "mocha": "^11.0.1", "typescript-eslint": "^8.16.0", "yargs": "^17.7.2" } diff --git a/compiler/packages/react-forgive/scripts/server.mjs b/compiler/packages/react-forgive/scripts/server.mjs index 95afe8770d44b..e6d120e341af9 100644 --- a/compiler/packages/react-forgive/scripts/server.mjs +++ b/compiler/packages/react-forgive/scripts/server.mjs @@ -12,7 +12,7 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); export const entryPoint = path.join(__dirname, '../server/src/index.ts'); -export const outfile = path.join(__dirname, '../dist/extension.js'); +export const outfile = path.join(__dirname, '../dist/server.js'); export const config = { entryPoints: [entryPoint], outfile, diff --git a/compiler/packages/react-forgive/server/package.json b/compiler/packages/react-forgive/server/package.json index 4e4d54debbaa5..fb6f4feebd7ac 100644 --- a/compiler/packages/react-forgive/server/package.json +++ b/compiler/packages/react-forgive/server/package.json @@ -5,15 +5,21 @@ "description": "Experimental LSP server", "license": "MIT", "scripts": { - "build": "echo 'no build'", + "build": "rimraf dist && rollup --config --bundleConfigAsCjs", "test": "echo 'no tests'" }, "repository": { "type": "git", "url": "git+https://github.com/facebook/react.git", - "directory": "compiler/packages/react-forgive-server" + "directory": "compiler/packages/react-forgive" }, "dependencies": { + "@babel/core": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/plugin-syntax-typescript": "^7.25.9", + "@babel/types": "^7.26.0", + "cosmiconfig": "^9.0.0", + "prettier": "^3.3.3", "vscode-languageserver": "^9.0.1", "vscode-languageserver-textdocument": "^1.0.12" } diff --git a/compiler/packages/react-forgive/server/src/compiler/index.ts b/compiler/packages/react-forgive/server/src/compiler/index.ts new file mode 100644 index 0000000000000..be2cca94ca154 --- /dev/null +++ b/compiler/packages/react-forgive/server/src/compiler/index.ts @@ -0,0 +1,58 @@ +/** + * 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. + */ + +import type * as BabelCore from '@babel/core'; +import {parseAsync, transformFromAstAsync} from '@babel/core'; +import BabelPluginReactCompiler, { + type PluginOptions, +} from 'babel-plugin-react-compiler/src'; +import * as babelParser from 'prettier/plugins/babel.js'; +import * as estreeParser from 'prettier/plugins/estree'; +import * as typescriptParser from 'prettier/plugins/typescript'; +import * as prettier from 'prettier/standalone'; + +type CompileOptions = { + text: string; + file: string; + options: PluginOptions | null; +}; +export async function compile({ + text, + file, + options, +}: CompileOptions): Promise { + const ast = await parseAsync(text, { + sourceFileName: file, + parserOpts: { + plugins: ['typescript', 'jsx'], + }, + sourceType: 'module', + }); + const plugins = + options != null + ? [[BabelPluginReactCompiler, options]] + : [[BabelPluginReactCompiler]]; + const result = await transformFromAstAsync(ast, text, { + filename: file, + highlightCode: false, + retainLines: true, + plugins, + sourceType: 'module', + sourceFileName: file, + }); + if (result?.code == null) { + throw new Error( + `Expected BabelPluginReactCompiler to compile successfully, got ${result}`, + ); + } + result.code = await prettier.format(result.code, { + semi: false, + parser: 'babel-ts', + plugins: [babelParser, estreeParser, typescriptParser], + }); + return result; +} diff --git a/compiler/packages/react-forgive/server/src/compiler/options.ts b/compiler/packages/react-forgive/server/src/compiler/options.ts new file mode 100644 index 0000000000000..226be799d3abc --- /dev/null +++ b/compiler/packages/react-forgive/server/src/compiler/options.ts @@ -0,0 +1,25 @@ +/** + * 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. + */ + +import { + parsePluginOptions, + type PluginOptions, +} from 'babel-plugin-react-compiler/src'; +import {cosmiconfigSync} from 'cosmiconfig'; + +export function resolveReactConfig(projectPath: string): PluginOptions | null { + const explorerSync = cosmiconfigSync('react', { + searchStrategy: 'project', + cache: true, + }); + const result = explorerSync.search(projectPath); + if (result != null) { + return parsePluginOptions(result.config); + } else { + return null; + } +} diff --git a/compiler/packages/react-forgive/server/src/index.ts b/compiler/packages/react-forgive/server/src/index.ts index a265a953eed3d..057df617c8d10 100644 --- a/compiler/packages/react-forgive/server/src/index.ts +++ b/compiler/packages/react-forgive/server/src/index.ts @@ -4,3 +4,90 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ + +import {TextDocument} from 'vscode-languageserver-textdocument'; +import { + createConnection, + type InitializeParams, + type InitializeResult, + ProposedFeatures, + TextDocuments, + TextDocumentSyncKind, +} from 'vscode-languageserver/node'; +import {compile} from './compiler'; +import {type PluginOptions} from 'babel-plugin-react-compiler/src'; +import {resolveReactConfig} from './compiler/options'; +import {type BabelFileResult} from '@babel/core'; + +const SUPPORTED_LANGUAGE_IDS = new Set([ + 'javascript', + 'javascriptreact', + 'typescript', + 'typescriptreact', +]); + +const connection = createConnection(ProposedFeatures.all); +const documents = new TextDocuments(TextDocument); + +let compilerOptions: PluginOptions | null = null; +let lastResult: BabelFileResult | null = null; + +connection.onInitialize((_params: InitializeParams) => { + // TODO(@poteto) get config fr + compilerOptions = resolveReactConfig('.'); + const result: InitializeResult = { + capabilities: { + textDocumentSync: TextDocumentSyncKind.Full, + codeLensProvider: {resolveProvider: true}, + }, + }; + return result; +}); + +connection.onInitialized(() => { + connection.console.log('initialized'); +}); + +documents.onDidOpen(async event => { + if (SUPPORTED_LANGUAGE_IDS.has(event.document.languageId)) { + const text = event.document.getText(); + const result = await compile({ + text, + file: event.document.uri, + options: compilerOptions, + }); + if (result.code != null) { + lastResult = result; + } + } +}); + +documents.onDidChangeContent(async event => { + if (SUPPORTED_LANGUAGE_IDS.has(event.document.languageId)) { + const text = event.document.getText(); + const result = await compile({ + text, + file: event.document.uri, + options: compilerOptions, + }); + if (result.code != null) { + lastResult = result; + } + } +}); + +connection.onDidChangeWatchedFiles(change => { + connection.console.log( + change.changes.map(c => `File changed: ${c.uri}`).join('\n'), + ); +}); + +connection.onCodeLens(params => { + connection.console.log('lastResult: ' + JSON.stringify(lastResult, null, 2)); + connection.console.log('params: ' + JSON.stringify(params, null, 2)); + return []; +}); + +documents.listen(connection); +connection.listen(); +connection.console.info(`React Analyzer running in node ${process.version}`); diff --git a/compiler/packages/react-forgive/server/tsconfig.json b/compiler/packages/react-forgive/server/tsconfig.json index ccd17f5dff457..52efba4ebe5af 100644 --- a/compiler/packages/react-forgive/server/tsconfig.json +++ b/compiler/packages/react-forgive/server/tsconfig.json @@ -1,13 +1,15 @@ { "extends": "@tsconfig/strictest/tsconfig.json", "compilerOptions": { - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", + "module": "ES2015", + "moduleResolution": "Bundler", + "rootDir": "../../..", + "noEmit": true, "jsx": "react-jsxdev", - "lib": ["ES2020"], - "target": "ES2020", + "target": "ES2015", + "sourceMap": false, + "removeComments": true, }, "exclude": ["node_modules", ".vscode-test"], - "include": ["src/**/*.ts"], + "include": ["src/**/*.ts"] } diff --git a/compiler/packages/react-forgive/server/yarn.lock b/compiler/packages/react-forgive/server/yarn.lock index fd60ddd6ad5f1..b72063294ff08 100644 --- a/compiler/packages/react-forgive/server/yarn.lock +++ b/compiler/packages/react-forgive/server/yarn.lock @@ -2,6 +2,378 @@ # yarn lockfile v1 +"@ampproject/remapping@^2.2.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0", "@babel/code-frame@^7.26.2": + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" + integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== + dependencies: + "@babel/helper-validator-identifier" "^7.25.9" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/compat-data@^7.25.9": + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.3.tgz#99488264a56b2aded63983abd6a417f03b92ed02" + integrity sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g== + +"@babel/core@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.0.tgz#d78b6023cc8f3114ccf049eb219613f74a747b40" + integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.26.0" + "@babel/generator" "^7.26.0" + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-module-transforms" "^7.26.0" + "@babel/helpers" "^7.26.0" + "@babel/parser" "^7.26.0" + "@babel/template" "^7.25.9" + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.26.0" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.26.0", "@babel/generator@^7.26.3": + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.3.tgz#ab8d4360544a425c90c248df7059881f4b2ce019" + integrity sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ== + dependencies: + "@babel/parser" "^7.26.3" + "@babel/types" "^7.26.3" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" + +"@babel/helper-compilation-targets@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz#55af025ce365be3cdc0c1c1e56c6af617ce88875" + integrity sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ== + dependencies: + "@babel/compat-data" "^7.25.9" + "@babel/helper-validator-option" "^7.25.9" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-module-imports@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" + integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/helper-module-transforms@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" + integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== + dependencies: + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/helper-plugin-utils@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz#9cbdd63a9443a2c92a725cca7ebca12cc8dd9f46" + integrity sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw== + +"@babel/helper-string-parser@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" + integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== + +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + +"@babel/helper-validator-option@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" + integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== + +"@babel/helpers@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.0.tgz#30e621f1eba5aa45fe6f4868d2e9154d884119a4" + integrity sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw== + dependencies: + "@babel/template" "^7.25.9" + "@babel/types" "^7.26.0" + +"@babel/parser@^7.25.9", "@babel/parser@^7.26.0", "@babel/parser@^7.26.3": + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.3.tgz#8c51c5db6ddf08134af1ddbacf16aaab48bac234" + integrity sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA== + dependencies: + "@babel/types" "^7.26.3" + +"@babel/plugin-syntax-typescript@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz#67dda2b74da43727cf21d46cf9afef23f4365399" + integrity sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/template@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.9.tgz#ecb62d81a8a6f5dc5fe8abfc3901fc52ddf15016" + integrity sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg== + dependencies: + "@babel/code-frame" "^7.25.9" + "@babel/parser" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/traverse@^7.25.9": + version "7.26.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.4.tgz#ac3a2a84b908dde6d463c3bfa2c5fdc1653574bd" + integrity sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/generator" "^7.26.3" + "@babel/parser" "^7.26.3" + "@babel/template" "^7.25.9" + "@babel/types" "^7.26.3" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.25.9", "@babel/types@^7.26.0", "@babel/types@^7.26.3": + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.3.tgz#37e79830f04c2b5687acc77db97fbc75fb81f3c0" + integrity sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA== + dependencies: + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.8" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" + integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +browserslist@^4.24.0: + version "4.24.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.3.tgz#5fc2725ca8fb3c1432e13dac278c7cc103e026d2" + integrity sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA== + dependencies: + caniuse-lite "^1.0.30001688" + electron-to-chromium "^1.5.73" + node-releases "^2.0.19" + update-browserslist-db "^1.1.1" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +caniuse-lite@^1.0.30001688: + version "1.0.30001690" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz#f2d15e3aaf8e18f76b2b8c1481abde063b8104c8" + integrity sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +cosmiconfig@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d" + integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg== + dependencies: + env-paths "^2.2.1" + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + +debug@^4.1.0, debug@^4.3.1: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + +electron-to-chromium@^1.5.73: + version "1.5.74" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.74.tgz#cb886b504a6467e4c00bea3317edb38393c53413" + integrity sha512-ck3//9RC+6oss/1Bh9tiAVFy5vfSKbRHAFh7Z3/eTRkEqJeWgymloShB17Vg3Z4nmDNp35vAd1BZ6CMW4Wt6Iw== + +env-paths@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +gensync@^1.0.0-beta.2: + version "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== + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +import-fresh@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +node-releases@^2.0.19: + version "2.0.19" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" + integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +picocolors@^1.0.0, picocolors@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +prettier@^3.3.3: + version "3.4.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.4.2.tgz#a5ce1fb522a588bf2b78ca44c6e6fe5aa5a2b13f" + integrity sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +update-browserslist-db@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" + integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.0" + vscode-jsonrpc@8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz#f43dfa35fb51e763d17cd94dcca0c9458f35abf9" @@ -31,3 +403,8 @@ vscode-languageserver@^9.0.1: integrity sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g== dependencies: vscode-languageserver-protocol "3.17.5" + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== diff --git a/compiler/yarn.lock b/compiler/yarn.lock index fe1d22eac864c..9c25b35b34b81 100644 --- a/compiler/yarn.lock +++ b/compiler/yarn.lock @@ -1714,171 +1714,86 @@ enabled "2.0.x" kuler "^2.0.0" -"@esbuild/aix-ppc64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz#b57697945b50e99007b4c2521507dc613d4a648c" - integrity sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw== - "@esbuild/aix-ppc64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz#499600c5e1757a524990d5d92601f0ac3ce87f64" integrity sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ== -"@esbuild/android-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz#1add7e0af67acefd556e407f8497e81fddad79c0" - integrity sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w== - "@esbuild/android-arm64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz#b9b8231561a1dfb94eb31f4ee056b92a985c324f" integrity sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g== -"@esbuild/android-arm@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.0.tgz#ab7263045fa8e090833a8e3c393b60d59a789810" - integrity sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew== - "@esbuild/android-arm@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.0.tgz#ca6e7888942505f13e88ac9f5f7d2a72f9facd2b" integrity sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g== -"@esbuild/android-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.0.tgz#e8f8b196cfdfdd5aeaebbdb0110983460440e705" - integrity sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ== - "@esbuild/android-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.0.tgz#e765ea753bac442dfc9cb53652ce8bd39d33e163" integrity sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg== -"@esbuild/darwin-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz#2d0d9414f2acbffd2d86e98253914fca603a53dd" - integrity sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw== - "@esbuild/darwin-arm64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz#fa394164b0d89d4fdc3a8a21989af70ef579fa2c" integrity sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw== -"@esbuild/darwin-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz#33087aab31a1eb64c89daf3d2cf8ce1775656107" - integrity sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA== - "@esbuild/darwin-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz#91979d98d30ba6e7d69b22c617cc82bdad60e47a" integrity sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg== -"@esbuild/freebsd-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz#bb76e5ea9e97fa3c753472f19421075d3a33e8a7" - integrity sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA== - "@esbuild/freebsd-arm64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz#b97e97073310736b430a07b099d837084b85e9ce" integrity sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w== -"@esbuild/freebsd-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz#e0e2ce9249fdf6ee29e5dc3d420c7007fa579b93" - integrity sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ== - "@esbuild/freebsd-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz#f3b694d0da61d9910ec7deff794d444cfbf3b6e7" integrity sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A== -"@esbuild/linux-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz#d1b2aa58085f73ecf45533c07c82d81235388e75" - integrity sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g== - "@esbuild/linux-arm64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz#f921f699f162f332036d5657cad9036f7a993f73" integrity sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg== -"@esbuild/linux-arm@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz#8e4915df8ea3e12b690a057e77a47b1d5935ef6d" - integrity sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw== - "@esbuild/linux-arm@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz#cc49305b3c6da317c900688995a4050e6cc91ca3" integrity sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg== -"@esbuild/linux-ia32@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz#8200b1110666c39ab316572324b7af63d82013fb" - integrity sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA== - "@esbuild/linux-ia32@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz#3e0736fcfab16cff042dec806247e2c76e109e19" integrity sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg== -"@esbuild/linux-loong64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz#6ff0c99cf647504df321d0640f0d32e557da745c" - integrity sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g== - "@esbuild/linux-loong64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz#ea2bf730883cddb9dfb85124232b5a875b8020c7" integrity sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw== -"@esbuild/linux-mips64el@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz#3f720ccd4d59bfeb4c2ce276a46b77ad380fa1f3" - integrity sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA== - "@esbuild/linux-mips64el@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz#4cababb14eede09248980a2d2d8b966464294ff1" integrity sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ== -"@esbuild/linux-ppc64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz#9d6b188b15c25afd2e213474bf5f31e42e3aa09e" - integrity sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ== - "@esbuild/linux-ppc64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz#8860a4609914c065373a77242e985179658e1951" integrity sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw== -"@esbuild/linux-riscv64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz#f989fdc9752dfda286c9cd87c46248e4dfecbc25" - integrity sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw== - "@esbuild/linux-riscv64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz#baf26e20bb2d38cfb86ee282dff840c04f4ed987" integrity sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA== -"@esbuild/linux-s390x@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz#29ebf87e4132ea659c1489fce63cd8509d1c7319" - integrity sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g== - "@esbuild/linux-s390x@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz#8323afc0d6cb1b6dc6e9fd21efd9e1542c3640a4" integrity sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA== -"@esbuild/linux-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz#4af48c5c0479569b1f359ffbce22d15f261c0cef" - integrity sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA== - "@esbuild/linux-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz#08fcf60cb400ed2382e9f8e0f5590bac8810469a" @@ -1889,71 +1804,36 @@ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz#935c6c74e20f7224918fbe2e6c6fe865b6c6ea5b" integrity sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw== -"@esbuild/netbsd-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz#1ae73d23cc044a0ebd4f198334416fb26c31366c" - integrity sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg== - "@esbuild/netbsd-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz#414677cef66d16c5a4d210751eb2881bb9c1b62b" integrity sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA== -"@esbuild/openbsd-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz#5d904a4f5158c89859fd902c427f96d6a9e632e2" - integrity sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg== - "@esbuild/openbsd-arm64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz#8fd55a4d08d25cdc572844f13c88d678c84d13f7" integrity sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw== -"@esbuild/openbsd-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz#4c8aa88c49187c601bae2971e71c6dc5e0ad1cdf" - integrity sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q== - "@esbuild/openbsd-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz#0c48ddb1494bbc2d6bcbaa1429a7f465fa1dedde" integrity sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg== -"@esbuild/sunos-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz#8ddc35a0ea38575fa44eda30a5ee01ae2fa54dd4" - integrity sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA== - "@esbuild/sunos-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz#86ff9075d77962b60dd26203d7352f92684c8c92" integrity sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg== -"@esbuild/win32-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz#6e79c8543f282c4539db684a207ae0e174a9007b" - integrity sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA== - "@esbuild/win32-arm64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz#849c62327c3229467f5b5cd681bf50588442e96c" integrity sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw== -"@esbuild/win32-ia32@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz#057af345da256b7192d18b676a02e95d0fa39103" - integrity sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw== - "@esbuild/win32-ia32@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz#f62eb480cd7cca088cb65bb46a6db25b725dc079" integrity sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA== -"@esbuild/win32-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz#168ab1c7e1c318b922637fad8f339d48b01e1244" - integrity sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA== - "@esbuild/win32-x64@0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz#c8e119a30a7c8d60b9d2e22d2073722dde3b710b" @@ -2145,7 +2025,7 @@ js-yaml "^3.13.1" resolve-from "^5.0.0" -"@istanbuljs/schema@^0.1.2": +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": version "0.1.3" resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== @@ -3102,6 +2982,11 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== +"@types/mocha@^10.0.10", "@types/mocha@^10.0.2": + version "10.0.10" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.10.tgz#91f62905e8d23cbd66225312f239454a23bebfa0" + integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== + "@types/node@*", "@types/node@^18.7.18": version "18.7.19" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.19.tgz#ad83aa9b7af470fab7e0f562be87e97dc8ffe08e" @@ -3170,6 +3055,11 @@ resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.5.tgz#74fef9ffbaa198eb8b588be029f38b00299caa2c" integrity sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw== +"@types/vscode@^1.96.0": + version "1.96.0" + resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.96.0.tgz#3181004bf25d71677ae4aacdd7605a3fd7edf08e" + integrity sha512-qvZbSZo+K4ZYmmDuaodMbAa67Pl6VDQzLKFka6rq+3WUTY4Kro7Bwoi0CuZLO/wema0ygcmpwow7zZfPJTs5jg== + "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" @@ -3442,6 +3332,32 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== +"@vscode/test-cli@^0.0.10": + version "0.0.10" + resolved "https://registry.yarnpkg.com/@vscode/test-cli/-/test-cli-0.0.10.tgz#35f0e81c2e0ff8daceb223e99d1b65306c15822c" + integrity sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA== + dependencies: + "@types/mocha" "^10.0.2" + c8 "^9.1.0" + chokidar "^3.5.3" + enhanced-resolve "^5.15.0" + glob "^10.3.10" + minimatch "^9.0.3" + mocha "^10.2.0" + supports-color "^9.4.0" + yargs "^17.7.2" + +"@vscode/test-electron@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@vscode/test-electron/-/test-electron-2.4.1.tgz#5c2760640bf692efbdaa18bafcd35fb519688941" + integrity sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ== + dependencies: + http-proxy-agent "^7.0.2" + https-proxy-agent "^7.0.5" + jszip "^3.10.1" + ora "^7.0.1" + semver "^7.6.2" + abab@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" @@ -3497,6 +3413,11 @@ agent-base@6: dependencies: debug "4" +agent-base@^7.1.0, agent-base@^7.1.2: + version "7.1.3" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.3.tgz#29435eb821bc4194633a5b89e5bc4703bafc25a1" + integrity sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw== + ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -3507,6 +3428,11 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + ansi-escapes@^4.2.1: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -3561,6 +3487,14 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -3820,6 +3754,11 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + bl@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" @@ -3829,6 +3768,15 @@ bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" +bl@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-5.1.0.tgz#183715f678c7188ecef9fe475d90209400624273" + integrity sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ== + dependencies: + buffer "^6.0.3" + inherits "^2.0.4" + readable-stream "^3.4.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -3844,7 +3792,7 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.3: +braces@^3.0.3, braces@~3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== @@ -3856,6 +3804,11 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== +browser-stdout@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + browserslist@^4.21.3, browserslist@^4.21.5: version "4.21.7" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.7.tgz#e2b420947e5fb0a58e8f4668ae6e23488127e551" @@ -3903,6 +3856,31 @@ buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +c8@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/c8/-/c8-9.1.0.tgz#0e57ba3ab9e5960ab1d650b4a86f71e53cb68112" + integrity sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@istanbuljs/schema" "^0.1.3" + find-up "^5.0.0" + foreground-child "^3.1.1" + istanbul-lib-coverage "^3.2.0" + istanbul-lib-report "^3.0.1" + istanbul-reports "^3.1.6" + test-exclude "^6.0.0" + v8-to-istanbul "^9.0.0" + yargs "^17.7.2" + yargs-parser "^21.1.1" + call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -3926,7 +3904,7 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.2.0: +camelcase@^6.0.0, camelcase@^6.2.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== @@ -3958,11 +3936,31 @@ chalk@4, chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^5.0.0, chalk@^5.3.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.4.1.tgz#1b48bf0963ec158dce2aacf69c093ae2dd2092d8" + integrity sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w== + char-regex@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +chokidar@^3.5.3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + ci-info@^3.2.0: version "3.4.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.4.0.tgz#b28484fd436cbc267900364f096c9dc185efb251" @@ -3987,7 +3985,14 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-spinners@^2.5.0: +cli-cursor@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" + integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg== + dependencies: + restore-cursor "^4.0.0" + +cli-spinners@^2.5.0, cli-spinners@^2.9.0: version "2.9.2" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== @@ -4147,6 +4152,11 @@ core-js-compat@^3.30.1, core-js-compat@^3.30.2: dependencies: browserslist "^4.21.5" +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -4231,11 +4241,23 @@ debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, d dependencies: ms "2.1.2" +debug@^4.3.5: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + decimal.js@^10.3.1: version "10.4.1" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.1.tgz#be75eeac4a2281aace80c1a8753587c27ef053e7" @@ -4311,6 +4333,11 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diff@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + difflib@~0.2.1: version "0.2.4" resolved "https://registry.yarnpkg.com/difflib/-/difflib-0.2.4.tgz#b5e30361a6db023176d562892db85940a718f47e" @@ -4376,6 +4403,11 @@ emittery@^0.13.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== +emoji-regex@^10.2.1: + version "10.4.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.4.0.tgz#03553afea80b3975749cfcb36f776ca268e413d4" + integrity sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -4391,6 +4423,14 @@ enabled@2.0.x: resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== +enhanced-resolve@^5.15.0: + version "5.18.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz#91eb1db193896b9801251eeff1c6980278b1e404" + integrity sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + entities@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" @@ -4408,36 +4448,6 @@ es5-ext@0.8.x: resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.8.2.tgz#aba8d9e1943a895ac96837a62a39b3f55ecd94ab" integrity sha512-H19ompyhnKiBdjHR1DPHvf5RHgHPmJaY9JNzFGbMbPgdsUkvnUCN1Ke8J4Y0IMyTwFM2M9l4h2GoHwzwpSmXbA== -esbuild@^0.24.0: - version "0.24.0" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.24.0.tgz#f2d470596885fcb2e91c21eb3da3b3c89c0b55e7" - integrity sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ== - optionalDependencies: - "@esbuild/aix-ppc64" "0.24.0" - "@esbuild/android-arm" "0.24.0" - "@esbuild/android-arm64" "0.24.0" - "@esbuild/android-x64" "0.24.0" - "@esbuild/darwin-arm64" "0.24.0" - "@esbuild/darwin-x64" "0.24.0" - "@esbuild/freebsd-arm64" "0.24.0" - "@esbuild/freebsd-x64" "0.24.0" - "@esbuild/linux-arm" "0.24.0" - "@esbuild/linux-arm64" "0.24.0" - "@esbuild/linux-ia32" "0.24.0" - "@esbuild/linux-loong64" "0.24.0" - "@esbuild/linux-mips64el" "0.24.0" - "@esbuild/linux-ppc64" "0.24.0" - "@esbuild/linux-riscv64" "0.24.0" - "@esbuild/linux-s390x" "0.24.0" - "@esbuild/linux-x64" "0.24.0" - "@esbuild/netbsd-x64" "0.24.0" - "@esbuild/openbsd-arm64" "0.24.0" - "@esbuild/openbsd-x64" "0.24.0" - "@esbuild/sunos-x64" "0.24.0" - "@esbuild/win32-arm64" "0.24.0" - "@esbuild/win32-ia32" "0.24.0" - "@esbuild/win32-x64" "0.24.0" - esbuild@^0.25.0: version "0.25.0" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.0.tgz#0de1787a77206c5a79eeb634a623d39b5006ce92" @@ -4952,6 +4962,11 @@ flat-cache@^4.0.0: flatted "^3.2.9" keyv "^4.5.4" +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + flatted@^3.1.0: version "3.2.7" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" @@ -4993,6 +5008,14 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" +foreground-child@^3.1.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" + integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -5021,6 +5044,11 @@ fsevents@^2.3.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -5055,7 +5083,7 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -glob-parent@^5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -5080,7 +5108,7 @@ glob@^10.3.10: minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-scurry "^1.10.1" -glob@^10.3.7: +glob@^10.3.7, glob@^10.4.5: version "10.4.5" resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== @@ -5104,6 +5132,17 @@ glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" @@ -5153,7 +5192,7 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -graceful-fs@^4.1.2, graceful-fs@^4.1.6: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.4: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -5197,6 +5236,11 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + "heap@>= 0.2.0": version "0.2.7" resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc" @@ -5263,6 +5307,14 @@ http-proxy-agent@^5.0.0: agent-base "6" debug "4" +http-proxy-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + https-proxy-agent@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -5271,6 +5323,14 @@ https-proxy-agent@^5.0.1: agent-base "6" debug "4" +https-proxy-agent@^7.0.5: + version "7.0.6" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" + integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== + dependencies: + agent-base "^7.1.2" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -5283,7 +5343,7 @@ iconv-lite@0.6.3: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -ieee754@^1.1.13: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -5303,6 +5363,11 @@ ignore@^5.3.1: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== + import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -5332,7 +5397,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@^2.0.4: +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -5359,6 +5424,13 @@ is-arrayish@^0.3.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-core-module@^2.11.0: version "2.12.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" @@ -5388,7 +5460,7 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -5400,6 +5472,11 @@ is-interactive@^1.0.0: resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== +is-interactive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-2.0.0.tgz#40c57614593826da1100ade6059778d597f16e90" + integrity sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ== + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -5410,6 +5487,11 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -5432,11 +5514,21 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is-unicode-supported@^1.1.0, is-unicode-supported@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz#d824984b616c292a2e198207d4a609983842f714" + integrity sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ== + is-windows@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -5472,6 +5564,15 @@ istanbul-lib-report@^3.0.0: make-dir "^3.0.0" supports-color "^7.1.0" +istanbul-lib-report@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + istanbul-lib-source-maps@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" @@ -5489,6 +5590,14 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +istanbul-reports@^3.1.6: + version "3.1.7" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" + integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + jackspeak@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" @@ -6745,6 +6854,16 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jszip@^3.10.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" + integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== + dependencies: + lie "~3.3.0" + pako "~1.0.2" + readable-stream "~2.3.6" + setimmediate "^1.0.5" + keypress@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/keypress/-/keypress-0.2.1.tgz#1e80454250018dbad4c3fe94497d6e67b6269c77" @@ -6798,6 +6917,13 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lie@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" + integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== + dependencies: + immediate "~3.0.5" + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -6853,6 +6979,14 @@ log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" +log-symbols@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-5.1.0.tgz#a20e3b9a5f53fac6aeb8e2bb22c07cf2c8f16d93" + integrity sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA== + dependencies: + chalk "^5.0.0" + is-unicode-supported "^1.1.0" + logform@^2.6.0, logform@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/logform/-/logform-2.7.0.tgz#cfca97528ef290f2e125a08396805002b2d060d1" @@ -6916,6 +7050,13 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + make-error@1.x, make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" @@ -6982,20 +7123,20 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^9.0.4: - version "9.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" - integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== - dependencies: - brace-expansion "^2.0.1" - -minimatch@~5.1.2: +minimatch@^5.0.1, minimatch@^5.1.6, minimatch@~5.1.2: version "5.1.6" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.3, minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.0, minimist@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" @@ -7016,6 +7157,58 @@ mkdirp@3.0.1: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== +mocha@^10.2.0: + version "10.8.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.8.2.tgz#8d8342d016ed411b12a429eb731b825f961afb96" + integrity sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg== + dependencies: + ansi-colors "^4.1.3" + browser-stdout "^1.3.1" + chokidar "^3.5.3" + debug "^4.3.5" + diff "^5.2.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^8.1.0" + he "^1.2.0" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^5.1.6" + ms "^2.1.3" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^6.5.1" + yargs "^16.2.0" + yargs-parser "^20.2.9" + yargs-unparser "^2.0.0" + +mocha@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-11.0.1.tgz#85c1c0e806275fe2479245be4ac4a0d81f533aa8" + integrity sha512-+3GkODfsDG71KSCQhc4IekSW+ItCK/kiez1Z28ksWvYhKXV/syxMlerR/sC7whDp7IyreZ4YxceMLdTs5hQE8A== + dependencies: + ansi-colors "^4.1.3" + browser-stdout "^1.3.1" + chokidar "^3.5.3" + debug "^4.3.5" + diff "^5.2.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^10.4.5" + he "^1.2.0" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^5.1.6" + ms "^2.1.3" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^6.5.1" + yargs "^16.2.0" + yargs-parser "^20.2.9" + yargs-unparser "^2.0.0" + mri@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.4.tgz#7cb1dd1b9b40905f1fac053abe25b6720f44744a" @@ -7026,7 +7219,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1: +ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -7073,7 +7266,7 @@ node-releases@^2.0.19: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== -normalize-path@^3.0.0: +normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== @@ -7219,6 +7412,21 @@ ora@5.4.1: strip-ansi "^6.0.0" wcwidth "^1.0.1" +ora@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-7.0.1.tgz#cdd530ecd865fe39e451a0e7697865669cb11930" + integrity sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw== + dependencies: + chalk "^5.3.0" + cli-cursor "^4.0.0" + cli-spinners "^2.9.0" + is-interactive "^2.0.0" + is-unicode-supported "^1.3.0" + log-symbols "^5.1.0" + stdin-discarder "^0.1.0" + string-width "^6.1.0" + strip-ansi "^7.1.0" + p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -7264,6 +7472,11 @@ package-json-from-dist@^1.0.0: resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== +pako@~1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -7356,7 +7569,7 @@ picocolors@^1.1.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== -picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -7456,6 +7669,11 @@ pretty-format@^29.5.0: ansi-styles "^5.0.0" react-is "^18.0.0" +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + prompt-promise@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/prompt-promise/-/prompt-promise-1.0.3.tgz#78ce4fcb9a14a108c49174f2d808c440d1bde265" @@ -7512,6 +7730,13 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + react-dom@0.0.0-experimental-4beb1fd8-20241118: version "0.0.0-experimental-4beb1fd8-20241118" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-0.0.0-experimental-4beb1fd8-20241118.tgz#bf51483d52faea0618abef7d7eab681eea328ac7" @@ -7553,6 +7778,26 @@ readable-stream@^3.4.0, readable-stream@^3.6.2: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + readline@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c" @@ -7682,6 +7927,14 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" +restore-cursor@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" + integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -7713,16 +7966,16 @@ rxjs@^7.0.0, rxjs@^7.8.1: dependencies: tslib "^2.1.0" -safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@~5.2.0: +safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + safe-stable-stringify@^2.3.1: version "2.5.0" resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" @@ -7774,11 +8027,18 @@ semver@^7.5.3, semver@^7.5.4: dependencies: lru-cache "^6.0.0" -semver@^7.6.0: +semver@^7.6.0, semver@^7.6.2: version "7.6.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +serialize-javascript@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + serializerr@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/serializerr/-/serializerr-1.0.3.tgz#12d4c5aa1c3ffb8f6d1dc5f395aa9455569c3f91" @@ -7791,6 +8051,11 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + shallow-clone@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" @@ -7890,6 +8155,13 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" +stdin-discarder@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz#22b3e400393a8e28ebf53f9958f3880622efde21" + integrity sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ== + dependencies: + bl "^5.0.0" + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -7925,6 +8197,15 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" +string-width@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-6.1.0.tgz#96488d6ed23f9ad5d82d13522af9e4c4c3fd7518" + integrity sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^10.2.1" + strip-ansi "^7.0.1" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -7932,6 +8213,13 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + "strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -7946,7 +8234,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.1: +strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== @@ -7982,13 +8270,18 @@ supports-color@^7.0.0, supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -supports-color@^8.0.0, supports-color@^8.1.0: +supports-color@^8.0.0, supports-color@^8.1.0, supports-color@^8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: has-flag "^4.0.0" +supports-color@^9.4.0: + version "9.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.4.0.tgz#17bfcf686288f531db3dea3215510621ccb55954" + integrity sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw== + supports-hyperlinks@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" @@ -8007,6 +8300,11 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + terminal-link@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" @@ -8200,11 +8498,6 @@ typescript@^5.4.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff" integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== -typescript@^5.7.2: - version "5.7.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6" - integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg== - undici-types@~6.19.2: version "6.19.8" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" @@ -8274,7 +8567,7 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" -util-deprecate@^1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== @@ -8284,6 +8577,15 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +v8-to-istanbul@^9.0.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" + integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + v8-to-istanbul@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz#b6f994b0b5d4ef255e17a0d17dc444a9f5132fa4" @@ -8427,6 +8729,11 @@ wordwrap@>=0.0.2: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== +workerpool@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" + integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -8519,11 +8826,26 @@ yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^20.2.2, yargs-parser@^20.2.9: + version "20.2.9" + 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, yargs-parser@^21.0.1, yargs-parser@^21.1.1: 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-unparser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + yargs@^15.3.1: version "15.4.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" @@ -8541,6 +8863,19 @@ yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.2" +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + yargs@^17.3.1: version "17.5.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.5.1.tgz#e109900cab6fcb7fd44b1d8249166feb0b36e58e" From 2e4db3344f030fe622152ecc231a7c99a81a9c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= Date: Tue, 25 Feb 2025 12:45:18 -0500 Subject: [PATCH 04/18] Use valid CSS selectors in useId format (#32001) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the `useId` algorithm we used colon `:` before and after. https://github.com/facebook/react/pull/23360 This avoids collisions in general by using an unusual characters. It also avoids collisions when concatenated with some other ID. Unfortunately, `:` is not a valid character in `view-transition-name`. This PR swaps the format from: ``` :r123: ``` To the unicode: ``` «r123» ``` Which is valid CSS selectors. This also allows them being used for `querySelector()` which we didn't really find a legit use for but seems ok-ish. That way you can get a view-transition-name that you can manually reference. E.g. to generate styles: ```js const id = useId(); return <> ... ; ``` --- .../ReactHooksInspectionIntegration-test.js | 2 +- .../src/server/ReactFizzConfigDOM.js | 4 +-- .../src/__tests__/ReactDOMUseId-test.js | 30 +++++++++---------- .../react-reconciler/src/ReactFiberHooks.js | 11 +++++-- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js b/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js index 87f98b99f2534..79ec20c3c2975 100644 --- a/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js +++ b/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js @@ -1553,7 +1553,7 @@ describe('ReactHooksInspectionIntegration', () => { expect(tree[0].id).toEqual(0); expect(tree[0].isStateEditable).toEqual(false); expect(tree[0].name).toEqual('Id'); - expect(String(tree[0].value).startsWith(':r')).toBe(true); + expect(String(tree[0].value).startsWith('\u00ABr')).toBe(true); expect(normalizeSourceLoc(tree)[1]).toMatchInlineSnapshot(` { diff --git a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js index 6a86cbb2652fa..963f516b15308 100644 --- a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js +++ b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js @@ -858,7 +858,7 @@ export function makeId( ): string { const idPrefix = resumableState.idPrefix; - let id = ':' + idPrefix + 'R' + treeId; + let id = '\u00AB' + idPrefix + 'R' + treeId; // Unless this is the first id at this level, append a number at the end // that represents the position of this useId hook among all the useId @@ -867,7 +867,7 @@ export function makeId( id += 'H' + localId.toString(32); } - return id + ':'; + return id + '\u00BB'; } function encodeHTMLTextNode(text: string): string { diff --git a/packages/react-dom/src/__tests__/ReactDOMUseId-test.js b/packages/react-dom/src/__tests__/ReactDOMUseId-test.js index af5dbdd355294..7738994fb1e1e 100644 --- a/packages/react-dom/src/__tests__/ReactDOMUseId-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMUseId-test.js @@ -96,7 +96,7 @@ describe('useId', () => { } function normalizeTreeIdForTesting(id) { - const result = id.match(/:(R|r)([a-z0-9]*)(H([0-9]*))?:/); + const result = id.match(/\u00AB(R|r)([a-z0-9]*)(H([0-9]*))?\u00BB/); if (result === undefined) { throw new Error('Invalid id format'); } @@ -285,7 +285,7 @@ describe('useId', () => { // 'R:' prefix, and the first character after that, which may not correspond // to a complete set of 5 bits. // - // Example: :Rclalalalalalalala...: + // Example: «Rclalalalalalalala...: // // We can use this pattern to test large ids that exceed the bitwise // safe range (32 bits). The algorithm should theoretically support ids @@ -320,8 +320,8 @@ describe('useId', () => { // Confirm that every id matches the expected pattern for (let i = 0; i < divs.length; i++) { - // Example: :Rclalalalalalalala...: - expect(divs[i].id).toMatch(/^:R.(((al)*a?)((la)*l?))*:$/); + // Example: «Rclalalalalalalala...: + expect(divs[i].id).toMatch(/^\u00ABR.(((al)*a?)((la)*l?))*\u00BB$/); } }); @@ -345,7 +345,7 @@ describe('useId', () => {
- :R0:, :R0H1:, :R0H2: + «R0», «R0H1», «R0H2»
`); }); @@ -370,7 +370,7 @@ describe('useId', () => {
- :R0: + «R0»
`); }); @@ -608,10 +608,10 @@ describe('useId', () => { id="container" >
- :custom-prefix-R1: + «custom-prefix-R1»
- :custom-prefix-R2: + «custom-prefix-R2»
`); @@ -625,13 +625,13 @@ describe('useId', () => { id="container" >
- :custom-prefix-R1: + «custom-prefix-R1»
- :custom-prefix-R2: + «custom-prefix-R2»
- :custom-prefix-r0: + «custom-prefix-r0»
`); @@ -672,11 +672,11 @@ describe('useId', () => { id="container" >
- :R0: + «R0»
- :R7: + «R7»
@@ -690,11 +690,11 @@ describe('useId', () => { id="container" >
- :R0: + «R0»
- :R7: + «R7»
diff --git a/packages/react-reconciler/src/ReactFiberHooks.js b/packages/react-reconciler/src/ReactFiberHooks.js index ddf051bcdb94f..50424e9d7b4db 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.js +++ b/packages/react-reconciler/src/ReactFiberHooks.js @@ -3595,7 +3595,7 @@ function mountId(): string { const treeId = getTreeId(); // Use a captial R prefix for server-generated ids. - id = ':' + identifierPrefix + 'R' + treeId; + id = '\u00AB' + identifierPrefix + 'R' + treeId; // Unless this is the first id at this level, append a number at the end // that represents the position of this useId hook among all the useId @@ -3605,11 +3605,16 @@ function mountId(): string { id += 'H' + localId.toString(32); } - id += ':'; + id += '\u00BB'; } else { // Use a lowercase r prefix for client-generated ids. const globalClientId = globalClientIdCounter++; - id = ':' + identifierPrefix + 'r' + globalClientId.toString(32) + ':'; + id = + '\u00AB' + + identifierPrefix + + 'r' + + globalClientId.toString(32) + + '\u00BB'; } hook.memoizedState = id; From 403d4fb852384b820a8fe405413891d8c74bbf5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= Date: Tue, 25 Feb 2025 12:45:44 -0500 Subject: [PATCH 05/18] Move ViewTransitions helpers to ReactFiberCommitViewTransitions (#32462) This doesn't change anything. It just moves some functions. This moves the view transitions helper functions into its own file. This is similar to how I already moved ReactFiberCommitEffects and ReactFiberCommitHostEffects out of ReactFiberCommitWork. This makes it a bit easier to navigate and get an overview of ReactFiberCommitWork but another motivation is also so that I can refer to these helpers from [ReactFiberApplyGesture](https://github.com/facebook/react/pull/32451/files#diff-42297cf327dee8e01d83c85314b8965953b9674e7c4615ce6c430464dcc8550b). --- .../src/ReactFiberCommitViewTransitions.js | 831 ++++++++++++++++++ .../src/ReactFiberCommitWork.js | 819 +---------------- .../src/ReactFiberWorkLoop.js | 2 +- 3 files changed, 861 insertions(+), 791 deletions(-) create mode 100644 packages/react-reconciler/src/ReactFiberCommitViewTransitions.js diff --git a/packages/react-reconciler/src/ReactFiberCommitViewTransitions.js b/packages/react-reconciler/src/ReactFiberCommitViewTransitions.js new file mode 100644 index 0000000000000..22b9d11ac67d2 --- /dev/null +++ b/packages/react-reconciler/src/ReactFiberCommitViewTransitions.js @@ -0,0 +1,831 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +import type {Instance, InstanceMeasurement, Props} from './ReactFiberConfig'; +import type {Fiber} from './ReactInternalTypes'; +import type { + ViewTransitionProps, + ViewTransitionState, +} from './ReactFiberViewTransitionComponent'; + +import { + HostComponent, + OffscreenComponent, + ViewTransitionComponent, +} from './ReactWorkTags'; +import { + NoFlags, + Update, + ViewTransitionStatic, + AffectedParentLayout, + ViewTransitionNamedStatic, +} from './ReactFiberFlags'; +import { + supportsMutation, + applyViewTransitionName, + restoreViewTransitionName, + measureInstance, + hasInstanceChanged, + hasInstanceAffectedParent, + wasInstanceInViewport, +} from './ReactFiberConfig'; +import {scheduleViewTransitionEvent} from './ReactFiberWorkLoop'; +import { + getViewTransitionName, + getViewTransitionClassName, +} from './ReactFiberViewTransitionComponent'; + +export let shouldStartViewTransition: boolean = false; + +export function resetShouldStartViewTransition(): void { + shouldStartViewTransition = false; +} + +// This tracks named ViewTransition components found in the accumulateSuspenseyCommit +// phase that might need to find deleted pairs in the beforeMutation phase. +let appearingViewTransitions: Map | null = null; + +export function resetAppearingViewTransitions(): void { + appearingViewTransitions = null; +} + +export function trackAppearingViewTransition( + name: string, + state: ViewTransitionState, +): void { + if (appearingViewTransitions === null) { + appearingViewTransitions = new Map(); + } + appearingViewTransitions.set(name, state); +} + +// We can't cancel view transition children until we know that their parent also +// don't need to transition. +export let viewTransitionCancelableChildren: null | Array< + Instance | string | Props, +> = null; // tupled array where each entry is [instance: Instance, oldName: string, props: Props] + +export function setViewTransitionCancelableChildren( + children: null | Array, +): void { + viewTransitionCancelableChildren = children; +} + +let viewTransitionHostInstanceIdx = 0; + +function applyViewTransitionToHostInstances( + child: null | Fiber, + name: string, + className: ?string, + collectMeasurements: null | Array, + stopAtNestedViewTransitions: boolean, +): boolean { + if (!supportsMutation) { + return false; + } + let inViewport = false; + while (child !== null) { + if (child.tag === HostComponent) { + shouldStartViewTransition = true; + const instance: Instance = child.stateNode; + if (collectMeasurements !== null) { + const measurement = measureInstance(instance); + collectMeasurements.push(measurement); + if (wasInstanceInViewport(measurement)) { + inViewport = true; + } + } else if (!inViewport) { + if (wasInstanceInViewport(measureInstance(instance))) { + inViewport = true; + } + } + applyViewTransitionName( + instance, + viewTransitionHostInstanceIdx === 0 + ? name + : // If we have multiple Host Instances below, we add a suffix to the name to give + // each one a unique name. + name + '_' + viewTransitionHostInstanceIdx, + className, + ); + viewTransitionHostInstanceIdx++; + } else if ( + child.tag === OffscreenComponent && + child.memoizedState !== null + ) { + // Skip any hidden subtrees. They were or are effectively not there. + } else if ( + child.tag === ViewTransitionComponent && + stopAtNestedViewTransitions + ) { + // Skip any nested view transitions for updates since in that case the + // inner most one is the one that handles the update. + } else { + if ( + applyViewTransitionToHostInstances( + child.child, + name, + className, + collectMeasurements, + stopAtNestedViewTransitions, + ) + ) { + inViewport = true; + } + } + child = child.sibling; + } + return inViewport; +} + +function restoreViewTransitionOnHostInstances( + child: null | Fiber, + stopAtNestedViewTransitions: boolean, +): void { + if (!supportsMutation) { + return; + } + while (child !== null) { + if (child.tag === HostComponent) { + const instance: Instance = child.stateNode; + restoreViewTransitionName(instance, child.memoizedProps); + } else if ( + child.tag === OffscreenComponent && + child.memoizedState !== null + ) { + // Skip any hidden subtrees. They were or are effectively not there. + } else if ( + child.tag === ViewTransitionComponent && + stopAtNestedViewTransitions + ) { + // Skip any nested view transitions for updates since in that case the + // inner most one is the one that handles the update. + } else { + restoreViewTransitionOnHostInstances( + child.child, + stopAtNestedViewTransitions, + ); + } + child = child.sibling; + } +} + +function commitAppearingPairViewTransitions(placement: Fiber): void { + if ((placement.subtreeFlags & ViewTransitionNamedStatic) === NoFlags) { + // This has no named view transitions in its subtree. + return; + } + let child = placement.child; + while (child !== null) { + if (child.tag === OffscreenComponent && child.memoizedState === null) { + // This tree was already hidden so we skip it. + } else { + commitAppearingPairViewTransitions(child); + if ( + child.tag === ViewTransitionComponent && + (child.flags & ViewTransitionNamedStatic) !== NoFlags + ) { + const instance: ViewTransitionState = child.stateNode; + if (instance.paired) { + const props: ViewTransitionProps = child.memoizedProps; + if (props.name == null || props.name === 'auto') { + throw new Error( + 'Found a pair with an auto name. This is a bug in React.', + ); + } + const name = props.name; + const className: ?string = getViewTransitionClassName( + props.className, + props.share, + ); + if (className !== 'none') { + // We found a new appearing view transition with the same name as this deletion. + // We'll transition between them. + viewTransitionHostInstanceIdx = 0; + const inViewport = applyViewTransitionToHostInstances( + child.child, + name, + className, + null, + false, + ); + if (!inViewport) { + // This boundary is exiting within the viewport but is going to leave the viewport. + // Instead, we treat this as an exit of the previous entry by reverting the new name. + // Ideally we could undo the old transition but it's now too late. It's also on its + // on snapshot. We have know was for it to paint onto the original group. + // TODO: This will lead to things unexpectedly having exit animations that normally + // wouldn't happen. Consider if we should just let this fly off the screen instead. + restoreViewTransitionOnHostInstances(child.child, false); + } + } + } + } + } + child = child.sibling; + } +} + +export function commitEnterViewTransitions(placement: Fiber): void { + if (placement.tag === ViewTransitionComponent) { + const state: ViewTransitionState = placement.stateNode; + const props: ViewTransitionProps = placement.memoizedProps; + const name = getViewTransitionName(props, state); + const className: ?string = getViewTransitionClassName( + props.className, + state.paired ? props.share : props.enter, + ); + if (className !== 'none') { + viewTransitionHostInstanceIdx = 0; + const inViewport = applyViewTransitionToHostInstances( + placement.child, + name, + className, + null, + false, + ); + if (!inViewport) { + // TODO: If this was part of a pair we will still run the onShare callback. + // Revert the transition names. This boundary is not in the viewport + // so we won't bother animating it. + restoreViewTransitionOnHostInstances(placement.child, false); + // TODO: Should we still visit the children in case a named one was in the viewport? + } else { + commitAppearingPairViewTransitions(placement); + + if (!state.paired) { + scheduleViewTransitionEvent(placement, props.onEnter); + } + } + } else { + commitAppearingPairViewTransitions(placement); + } + } else if ((placement.subtreeFlags & ViewTransitionStatic) !== NoFlags) { + let child = placement.child; + while (child !== null) { + commitEnterViewTransitions(child); + child = child.sibling; + } + } else { + commitAppearingPairViewTransitions(placement); + } +} + +function commitDeletedPairViewTransitions(deletion: Fiber): void { + if ( + appearingViewTransitions === null || + appearingViewTransitions.size === 0 + ) { + // We've found all. + return; + } + const pairs = appearingViewTransitions; + if ((deletion.subtreeFlags & ViewTransitionNamedStatic) === NoFlags) { + // This has no named view transitions in its subtree. + return; + } + let child = deletion.child; + while (child !== null) { + if (child.tag === OffscreenComponent && child.memoizedState === null) { + // This tree was already hidden so we skip it. + } else { + if ( + child.tag === ViewTransitionComponent && + (child.flags & ViewTransitionNamedStatic) !== NoFlags + ) { + const props: ViewTransitionProps = child.memoizedProps; + const name = props.name; + if (name != null && name !== 'auto') { + const pair = pairs.get(name); + if (pair !== undefined) { + const className: ?string = getViewTransitionClassName( + props.className, + props.share, + ); + if (className !== 'none') { + // We found a new appearing view transition with the same name as this deletion. + viewTransitionHostInstanceIdx = 0; + const inViewport = applyViewTransitionToHostInstances( + child.child, + name, + className, + null, + false, + ); + if (!inViewport) { + // This boundary is not in the viewport so we won't treat it as a matched pair. + // Revert the transition names. This avoids it flying onto the screen which can + // be disruptive and doesn't really preserve any continuity anyway. + restoreViewTransitionOnHostInstances(child.child, false); + } else { + // We'll transition between them. + const oldinstance: ViewTransitionState = child.stateNode; + const newInstance: ViewTransitionState = pair; + newInstance.paired = oldinstance; + // Note: If the other side ends up outside the viewport, we'll still run this. + // Therefore it's possible for onShare to be called with only an old snapshot. + scheduleViewTransitionEvent(child, props.onShare); + } + } + // Delete the entry so that we know when we've found all of them + // and can stop searching (size reaches zero). + pairs.delete(name); + if (pairs.size === 0) { + break; + } + } + } + } + commitDeletedPairViewTransitions(child); + } + child = child.sibling; + } +} + +export function commitExitViewTransitions(deletion: Fiber): void { + if (deletion.tag === ViewTransitionComponent) { + const props: ViewTransitionProps = deletion.memoizedProps; + const name = getViewTransitionName(props, deletion.stateNode); + const pair = + appearingViewTransitions !== null + ? appearingViewTransitions.get(name) + : undefined; + const className: ?string = getViewTransitionClassName( + props.className, + pair !== undefined ? props.share : props.exit, + ); + if (className !== 'none') { + viewTransitionHostInstanceIdx = 0; + const inViewport = applyViewTransitionToHostInstances( + deletion.child, + name, + className, + null, + false, + ); + if (!inViewport) { + // Revert the transition names. This boundary is not in the viewport + // so we won't bother animating it. + restoreViewTransitionOnHostInstances(deletion.child, false); + // TODO: Should we still visit the children in case a named one was in the viewport? + } else if (pair !== undefined) { + // We found a new appearing view transition with the same name as this deletion. + // We'll transition between them instead of running the normal exit. + const oldinstance: ViewTransitionState = deletion.stateNode; + const newInstance: ViewTransitionState = pair; + newInstance.paired = oldinstance; + // Delete the entry so that we know when we've found all of them + // and can stop searching (size reaches zero). + // $FlowFixMe[incompatible-use]: Refined by the pair. + appearingViewTransitions.delete(name); + // Note: If the other side ends up outside the viewport, we'll still run this. + // Therefore it's possible for onShare to be called with only an old snapshot. + scheduleViewTransitionEvent(deletion, props.onShare); + } else { + scheduleViewTransitionEvent(deletion, props.onExit); + } + } + if (appearingViewTransitions !== null) { + // Look for more pairs deeper in the tree. + commitDeletedPairViewTransitions(deletion); + } + } else if ((deletion.subtreeFlags & ViewTransitionStatic) !== NoFlags) { + let child = deletion.child; + while (child !== null) { + commitExitViewTransitions(child); + child = child.sibling; + } + } else { + if (appearingViewTransitions !== null) { + commitDeletedPairViewTransitions(deletion); + } + } +} + +export function commitBeforeUpdateViewTransition( + current: Fiber, + finishedWork: Fiber, +): void { + // The way we deal with multiple HostInstances as children of a View Transition in an + // update can get tricky. The important bit is that if you swap out n HostInstances + // from n HostInstances then they match up in order. Similarly, if you don't swap + // any HostInstances each instance just transitions as is. + // + // We call this function twice. First we apply the view transition names on the + // "current" tree in the snapshot phase. Then in the mutation phase we apply view + // transition names to the "finishedWork" tree. + // + // This means that if there were insertions or deletions before an updated Instance + // that same Instance might get different names in the "old" and the "new" state. + // For example if you swap two HostInstances inside a ViewTransition they don't + // animate to swap position but rather cross-fade into the other instance. This might + // be unexpected but it is in line with the semantics that the ViewTransition is its + // own layer that cross-fades its content when it updates. If you want to reorder then + // each child needs its own ViewTransition. + const oldProps: ViewTransitionProps = current.memoizedProps; + const oldName = getViewTransitionName(oldProps, current.stateNode); + const newProps: ViewTransitionProps = finishedWork.memoizedProps; + // This className applies only if there are fewer child DOM nodes than + // before or if this update should've been cancelled but we ended up with + // a parent animating so we need to animate the child too. + // For example, if update="foo" layout="none" and it turns out this was + // a layout only change, then the "foo" class will be applied even though + // it was not actually an update. Which is a bug. + let className: ?string = getViewTransitionClassName( + newProps.className, + newProps.update, + ); + if (className === 'none') { + className = getViewTransitionClassName(newProps.className, newProps.layout); + if (className === 'none') { + // If both update and layout are both "none" then we don't have to + // apply a name. Since we won't animate this boundary. + return; + } + } + viewTransitionHostInstanceIdx = 0; + applyViewTransitionToHostInstances( + current.child, + oldName, + className, + (current.memoizedState = []), + true, + ); +} + +export function commitNestedViewTransitions(changedParent: Fiber): void { + let child = changedParent.child; + while (child !== null) { + if (child.tag === ViewTransitionComponent) { + // In this case the outer ViewTransition component wins but if there + // was an update through this component then the inner one wins. + const props: ViewTransitionProps = child.memoizedProps; + const name = getViewTransitionName(props, child.stateNode); + const className: ?string = getViewTransitionClassName( + props.className, + props.layout, + ); + if (className !== 'none') { + viewTransitionHostInstanceIdx = 0; + applyViewTransitionToHostInstances( + child.child, + name, + className, + (child.memoizedState = []), + false, + ); + } + } else if ((child.subtreeFlags & ViewTransitionStatic) !== NoFlags) { + commitNestedViewTransitions(child); + } + child = child.sibling; + } +} + +function restorePairedViewTransitions(parent: Fiber): void { + if ((parent.subtreeFlags & ViewTransitionNamedStatic) === NoFlags) { + // This has no named view transitions in its subtree. + return; + } + let child = parent.child; + while (child !== null) { + if (child.tag === OffscreenComponent && child.memoizedState === null) { + // This tree was already hidden so we skip it. + } else { + if ( + child.tag === ViewTransitionComponent && + (child.flags & ViewTransitionNamedStatic) !== NoFlags + ) { + const instance: ViewTransitionState = child.stateNode; + if (instance.paired !== null) { + instance.paired = null; + restoreViewTransitionOnHostInstances(child.child, false); + } + } + restorePairedViewTransitions(child); + } + child = child.sibling; + } +} + +export function restoreEnterViewTransitions(placement: Fiber): void { + if (placement.tag === ViewTransitionComponent) { + const instance: ViewTransitionState = placement.stateNode; + instance.paired = null; + restoreViewTransitionOnHostInstances(placement.child, false); + restorePairedViewTransitions(placement); + } else if ((placement.subtreeFlags & ViewTransitionStatic) !== NoFlags) { + let child = placement.child; + while (child !== null) { + restoreEnterViewTransitions(child); + child = child.sibling; + } + } else { + restorePairedViewTransitions(placement); + } +} + +export function restoreExitViewTransitions(deletion: Fiber): void { + if (deletion.tag === ViewTransitionComponent) { + const instance: ViewTransitionState = deletion.stateNode; + instance.paired = null; + restoreViewTransitionOnHostInstances(deletion.child, false); + restorePairedViewTransitions(deletion); + } else if ((deletion.subtreeFlags & ViewTransitionStatic) !== NoFlags) { + let child = deletion.child; + while (child !== null) { + restoreExitViewTransitions(child); + child = child.sibling; + } + } else { + restorePairedViewTransitions(deletion); + } +} + +export function restoreUpdateViewTransition( + current: Fiber, + finishedWork: Fiber, +): void { + finishedWork.memoizedState = null; + restoreViewTransitionOnHostInstances(current.child, true); + restoreViewTransitionOnHostInstances(finishedWork.child, true); +} + +export function restoreNestedViewTransitions(changedParent: Fiber): void { + let child = changedParent.child; + while (child !== null) { + if (child.tag === ViewTransitionComponent) { + child.memoizedState = null; + restoreViewTransitionOnHostInstances(child.child, false); + } else if ((child.subtreeFlags & ViewTransitionStatic) !== NoFlags) { + restoreNestedViewTransitions(child); + } + child = child.sibling; + } +} + +function cancelViewTransitionHostInstances( + currentViewTransition: Fiber, + child: null | Fiber, + stopAtNestedViewTransitions: boolean, +): void { + if (!supportsMutation) { + return; + } + while (child !== null) { + if (child.tag === HostComponent) { + const instance: Instance = child.stateNode; + const oldName = getViewTransitionName( + currentViewTransition.memoizedProps, + currentViewTransition.stateNode, + ); + if (viewTransitionCancelableChildren === null) { + viewTransitionCancelableChildren = []; + } + viewTransitionCancelableChildren.push( + instance, + oldName, + child.memoizedProps, + ); + viewTransitionHostInstanceIdx++; + } else if ( + child.tag === OffscreenComponent && + child.memoizedState !== null + ) { + // Skip any hidden subtrees. They were or are effectively not there. + } else if ( + child.tag === ViewTransitionComponent && + stopAtNestedViewTransitions + ) { + // Skip any nested view transitions for updates since in that case the + // inner most one is the one that handles the update. + } else { + cancelViewTransitionHostInstances( + currentViewTransition, + child.child, + stopAtNestedViewTransitions, + ); + } + child = child.sibling; + } +} + +function measureViewTransitionHostInstances( + currentViewTransition: Fiber, + parentViewTransition: Fiber, + child: null | Fiber, + name: string, + className: ?string, + previousMeasurements: null | Array, + stopAtNestedViewTransitions: boolean, +): boolean { + if (!supportsMutation) { + return true; + } + let inViewport = false; + while (child !== null) { + if (child.tag === HostComponent) { + const instance: Instance = child.stateNode; + if ( + previousMeasurements !== null && + viewTransitionHostInstanceIdx < previousMeasurements.length + ) { + // The previous measurement of the Instance in this location within the ViewTransition. + // Note that this might not be the same exact Instance if the Instances within the + // ViewTransition changed. + const previousMeasurement = + previousMeasurements[viewTransitionHostInstanceIdx]; + const nextMeasurement = measureInstance(instance); + if ( + wasInstanceInViewport(previousMeasurement) || + wasInstanceInViewport(nextMeasurement) + ) { + // If either the old or new state was within the viewport we have to animate this. + // But if it turns out that none of them were we'll be able to skip it. + inViewport = true; + } + if ( + (parentViewTransition.flags & Update) === NoFlags && + hasInstanceChanged(previousMeasurement, nextMeasurement) + ) { + parentViewTransition.flags |= Update; + } + if (hasInstanceAffectedParent(previousMeasurement, nextMeasurement)) { + // If this instance size within its parent has changed it might have caused the + // parent to relayout which needs a cross fade. + parentViewTransition.flags |= AffectedParentLayout; + } + } else { + // If there was an insertion of extra nodes, we have to assume they affected the parent. + // It should have already been marked as an Update due to the mutation. + parentViewTransition.flags |= AffectedParentLayout; + } + if ((parentViewTransition.flags & Update) !== NoFlags) { + // We might update this node so we need to apply its new name for the new state. + applyViewTransitionName( + instance, + viewTransitionHostInstanceIdx === 0 + ? name + : // If we have multiple Host Instances below, we add a suffix to the name to give + // each one a unique name. + name + '_' + viewTransitionHostInstanceIdx, + className, + ); + } + if (!inViewport || (parentViewTransition.flags & Update) === NoFlags) { + // It turns out that we had no other deeper mutations, the child transitions didn't + // affect the parent layout and this instance hasn't changed size. So we can skip + // animating it. However, in the current model this only works if the parent also + // doesn't animate. So we have to queue these and wait until we complete the parent + // to cancel them. + const oldName = getViewTransitionName( + currentViewTransition.memoizedProps, + currentViewTransition.stateNode, + ); + if (viewTransitionCancelableChildren === null) { + viewTransitionCancelableChildren = []; + } + viewTransitionCancelableChildren.push( + instance, + oldName, + child.memoizedProps, + ); + } + viewTransitionHostInstanceIdx++; + } else if ( + child.tag === OffscreenComponent && + child.memoizedState !== null + ) { + // Skip any hidden subtrees. They were or are effectively not there. + } else if ( + child.tag === ViewTransitionComponent && + stopAtNestedViewTransitions + ) { + // Skip any nested view transitions for updates since in that case the + // inner most one is the one that handles the update. + // If this inner boundary resized we need to bubble that information up. + parentViewTransition.flags |= child.flags & AffectedParentLayout; + } else { + if ( + measureViewTransitionHostInstances( + currentViewTransition, + parentViewTransition, + child.child, + name, + className, + previousMeasurements, + stopAtNestedViewTransitions, + ) + ) { + inViewport = true; + } + } + child = child.sibling; + } + return inViewport; +} + +export function measureUpdateViewTransition( + current: Fiber, + finishedWork: Fiber, +): boolean { + const props: ViewTransitionProps = finishedWork.memoizedProps; + const updateClassName: ?string = getViewTransitionClassName( + props.className, + props.update, + ); + const layoutClassName: ?string = getViewTransitionClassName( + props.className, + props.layout, + ); + let className: ?string; + if (updateClassName === 'none') { + if (layoutClassName === 'none') { + // If both update and layout class name were none, then we didn't apply any + // names in the before update phase so we shouldn't now neither. + return false; + } + // We don't care if this is mutated or children layout changed, but we still + // measure each instance to see if it moved and therefore should apply layout. + finishedWork.flags &= ~Update; + className = layoutClassName; + } else if ((finishedWork.flags & Update) !== NoFlags) { + // It was updated and we have an appropriate class name to apply. + className = updateClassName; + } else { + if (layoutClassName === 'none') { + // If we did not update, then all changes are considered a layout. We'll + // attempt to cancel. + viewTransitionHostInstanceIdx = 0; + cancelViewTransitionHostInstances(current, finishedWork.child, true); + return false; + } + // We didn't update but we might still apply layout so we measure each + // instance to see if it moved or resized. + className = layoutClassName; + } + const name = getViewTransitionName(props, finishedWork.stateNode); + // If nothing changed due to a mutation, or children changing size + // and the measurements end up unchanged, we should restore it to not animate. + viewTransitionHostInstanceIdx = 0; + const previousMeasurements = current.memoizedState; + const inViewport = measureViewTransitionHostInstances( + current, + finishedWork, + finishedWork.child, + name, + className, + previousMeasurements, + true, + ); + const previousCount = + previousMeasurements === null ? 0 : previousMeasurements.length; + if (viewTransitionHostInstanceIdx !== previousCount) { + // If we found a different number of child DOM nodes we need to assume that + // the parent layout may have changed as a result. This is not necessarily + // true if those nodes were absolutely positioned. + finishedWork.flags |= AffectedParentLayout; + } + return inViewport; +} + +export function measureNestedViewTransitions(changedParent: Fiber): void { + let child = changedParent.child; + while (child !== null) { + if (child.tag === ViewTransitionComponent) { + const current = child.alternate; + if (current !== null) { + const props: ViewTransitionProps = child.memoizedProps; + const name = getViewTransitionName(props, child.stateNode); + const className: ?string = getViewTransitionClassName( + props.className, + props.layout, + ); + viewTransitionHostInstanceIdx = 0; + const inViewport = measureViewTransitionHostInstances( + current, + child, + child.child, + name, + className, + child.memoizedState, + false, + ); + if ((child.flags & Update) === NoFlags || !inViewport) { + // Nothing changed. + } else { + scheduleViewTransitionEvent(child, props.onLayout); + } + } + } else if ((child.subtreeFlags & ViewTransitionStatic) !== NoFlags) { + measureNestedViewTransitions(child); + } + child = child.sibling; + } +} diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.js b/packages/react-reconciler/src/ReactFiberCommitWork.js index 850f3c67067ff..f5d0987393046 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.js @@ -14,7 +14,6 @@ import type { Container, HoistableRoot, FormInstance, - InstanceMeasurement, Props, } from './ReactFiberConfig'; import type {Fiber, FiberRoot} from './ReactInternalTypes'; @@ -112,9 +111,7 @@ import { PerformedWork, ForceClientRender, DidCapture, - ViewTransitionStatic, AffectedParentLayout, - ViewTransitionNamedStatic, } from './ReactFiberFlags'; import { commitStartTime, @@ -163,15 +160,9 @@ import { suspendResource, resetFormInstance, registerSuspenseInstanceRetry, - applyViewTransitionName, - restoreViewTransitionName, cancelViewTransitionName, cancelRootViewTransitionName, restoreRootViewTransitionName, - measureInstance, - hasInstanceChanged, - hasInstanceAffectedParent, - wasInstanceInViewport, isSingletonScope, } from './ReactFiberConfig'; import { @@ -203,10 +194,6 @@ import { OffscreenDetached, OffscreenPassiveEffectsConnected, } from './ReactFiberActivityComponent'; -import { - getViewTransitionName, - getViewTransitionClassName, -} from './ReactFiberViewTransitionComponent'; import { TransitionRoot, TransitionTracingMarker, @@ -249,6 +236,23 @@ import { commitHostSingletonAcquisition, commitHostSingletonRelease, } from './ReactFiberCommitHostEffects'; +import { + commitEnterViewTransitions, + commitExitViewTransitions, + commitBeforeUpdateViewTransition, + commitNestedViewTransitions, + restoreEnterViewTransitions, + restoreExitViewTransitions, + restoreUpdateViewTransition, + restoreNestedViewTransitions, + measureUpdateViewTransition, + measureNestedViewTransitions, + resetShouldStartViewTransition, + resetAppearingViewTransitions, + trackAppearingViewTransition, + viewTransitionCancelableChildren, + setViewTransitionCancelableChildren, +} from './ReactFiberCommitViewTransitions'; import { viewTransitionMutationContext, pushMutationContext, @@ -274,19 +278,9 @@ let inProgressRoot: FiberRoot | null = null; let focusedInstanceHandle: null | Fiber = null; export let shouldFireAfterActiveInstanceBlur: boolean = false; -export let shouldStartViewTransition: boolean = false; - -// This tracks named ViewTransition components found in the accumulateSuspenseyCommit -// phase that might need to find deleted pairs in the beforeMutation phase. -let appearingViewTransitions: Map | null = null; - // Used during the commit phase to track whether a parent ViewTransition component // might have been affected by any mutations / relayouts below. let viewTransitionContextChanged: boolean = false; -// We can't cancel view transition children until we know that their parent also -// don't need to transition. -let viewTransitionCancelableChildren: null | Array = - null; // tupled array where each entry is [instance: Instance, oldName: string, props: Props] export function commitBeforeMutationEffects( root: FiberRoot, @@ -295,7 +289,8 @@ export function commitBeforeMutationEffects( ): void { focusedInstanceHandle = prepareForCommit(root.containerInfo); shouldFireAfterActiveInstanceBlur = false; - shouldStartViewTransition = false; + + resetShouldStartViewTransition(); const isViewTransitionEligible = enableViewTransition && @@ -307,7 +302,7 @@ export function commitBeforeMutationEffects( // We no longer need to track the active instance fiber focusedInstanceHandle = null; // We've found any matched pairs and can now reset. - appearingViewTransitions = null; + resetAppearingViewTransitions(); } function commitBeforeMutationEffects_begin(isViewTransitionEligible: boolean) { @@ -542,759 +537,6 @@ function commitBeforeMutationEffectsDeletion( } } -let viewTransitionHostInstanceIdx = 0; - -function applyViewTransitionToHostInstances( - child: null | Fiber, - name: string, - className: ?string, - collectMeasurements: null | Array, - stopAtNestedViewTransitions: boolean, -): boolean { - if (!supportsMutation) { - return false; - } - let inViewport = false; - while (child !== null) { - if (child.tag === HostComponent) { - shouldStartViewTransition = true; - const instance: Instance = child.stateNode; - if (collectMeasurements !== null) { - const measurement = measureInstance(instance); - collectMeasurements.push(measurement); - if (wasInstanceInViewport(measurement)) { - inViewport = true; - } - } else if (!inViewport) { - if (wasInstanceInViewport(measureInstance(instance))) { - inViewport = true; - } - } - applyViewTransitionName( - instance, - viewTransitionHostInstanceIdx === 0 - ? name - : // If we have multiple Host Instances below, we add a suffix to the name to give - // each one a unique name. - name + '_' + viewTransitionHostInstanceIdx, - className, - ); - viewTransitionHostInstanceIdx++; - } else if ( - child.tag === OffscreenComponent && - child.memoizedState !== null - ) { - // Skip any hidden subtrees. They were or are effectively not there. - } else if ( - child.tag === ViewTransitionComponent && - stopAtNestedViewTransitions - ) { - // Skip any nested view transitions for updates since in that case the - // inner most one is the one that handles the update. - } else { - if ( - applyViewTransitionToHostInstances( - child.child, - name, - className, - collectMeasurements, - stopAtNestedViewTransitions, - ) - ) { - inViewport = true; - } - } - child = child.sibling; - } - return inViewport; -} - -function restoreViewTransitionOnHostInstances( - child: null | Fiber, - stopAtNestedViewTransitions: boolean, -): void { - if (!supportsMutation) { - return; - } - while (child !== null) { - if (child.tag === HostComponent) { - const instance: Instance = child.stateNode; - restoreViewTransitionName(instance, child.memoizedProps); - } else if ( - child.tag === OffscreenComponent && - child.memoizedState !== null - ) { - // Skip any hidden subtrees. They were or are effectively not there. - } else if ( - child.tag === ViewTransitionComponent && - stopAtNestedViewTransitions - ) { - // Skip any nested view transitions for updates since in that case the - // inner most one is the one that handles the update. - } else { - restoreViewTransitionOnHostInstances( - child.child, - stopAtNestedViewTransitions, - ); - } - child = child.sibling; - } -} - -function commitAppearingPairViewTransitions(placement: Fiber): void { - if ((placement.subtreeFlags & ViewTransitionNamedStatic) === NoFlags) { - // This has no named view transitions in its subtree. - return; - } - let child = placement.child; - while (child !== null) { - if (child.tag === OffscreenComponent && child.memoizedState === null) { - // This tree was already hidden so we skip it. - } else { - commitAppearingPairViewTransitions(child); - if ( - child.tag === ViewTransitionComponent && - (child.flags & ViewTransitionNamedStatic) !== NoFlags - ) { - const instance: ViewTransitionState = child.stateNode; - if (instance.paired) { - const props: ViewTransitionProps = child.memoizedProps; - if (props.name == null || props.name === 'auto') { - throw new Error( - 'Found a pair with an auto name. This is a bug in React.', - ); - } - const name = props.name; - const className: ?string = getViewTransitionClassName( - props.className, - props.share, - ); - if (className !== 'none') { - // We found a new appearing view transition with the same name as this deletion. - // We'll transition between them. - viewTransitionHostInstanceIdx = 0; - const inViewport = applyViewTransitionToHostInstances( - child.child, - name, - className, - null, - false, - ); - if (!inViewport) { - // This boundary is exiting within the viewport but is going to leave the viewport. - // Instead, we treat this as an exit of the previous entry by reverting the new name. - // Ideally we could undo the old transition but it's now too late. It's also on its - // on snapshot. We have know was for it to paint onto the original group. - // TODO: This will lead to things unexpectedly having exit animations that normally - // wouldn't happen. Consider if we should just let this fly off the screen instead. - restoreViewTransitionOnHostInstances(child.child, false); - } - } - } - } - } - child = child.sibling; - } -} - -function commitEnterViewTransitions(placement: Fiber): void { - if (placement.tag === ViewTransitionComponent) { - const state: ViewTransitionState = placement.stateNode; - const props: ViewTransitionProps = placement.memoizedProps; - const name = getViewTransitionName(props, state); - const className: ?string = getViewTransitionClassName( - props.className, - state.paired ? props.share : props.enter, - ); - if (className !== 'none') { - viewTransitionHostInstanceIdx = 0; - const inViewport = applyViewTransitionToHostInstances( - placement.child, - name, - className, - null, - false, - ); - if (!inViewport) { - // TODO: If this was part of a pair we will still run the onShare callback. - // Revert the transition names. This boundary is not in the viewport - // so we won't bother animating it. - restoreViewTransitionOnHostInstances(placement.child, false); - // TODO: Should we still visit the children in case a named one was in the viewport? - } else { - commitAppearingPairViewTransitions(placement); - - if (!state.paired) { - scheduleViewTransitionEvent(placement, props.onEnter); - } - } - } else { - commitAppearingPairViewTransitions(placement); - } - } else if ((placement.subtreeFlags & ViewTransitionStatic) !== NoFlags) { - let child = placement.child; - while (child !== null) { - commitEnterViewTransitions(child); - child = child.sibling; - } - } else { - commitAppearingPairViewTransitions(placement); - } -} - -function commitDeletedPairViewTransitions(deletion: Fiber): void { - if ( - appearingViewTransitions === null || - appearingViewTransitions.size === 0 - ) { - // We've found all. - return; - } - const pairs = appearingViewTransitions; - if ((deletion.subtreeFlags & ViewTransitionNamedStatic) === NoFlags) { - // This has no named view transitions in its subtree. - return; - } - let child = deletion.child; - while (child !== null) { - if (child.tag === OffscreenComponent && child.memoizedState === null) { - // This tree was already hidden so we skip it. - } else { - if ( - child.tag === ViewTransitionComponent && - (child.flags & ViewTransitionNamedStatic) !== NoFlags - ) { - const props: ViewTransitionProps = child.memoizedProps; - const name = props.name; - if (name != null && name !== 'auto') { - const pair = pairs.get(name); - if (pair !== undefined) { - const className: ?string = getViewTransitionClassName( - props.className, - props.share, - ); - if (className !== 'none') { - // We found a new appearing view transition with the same name as this deletion. - viewTransitionHostInstanceIdx = 0; - const inViewport = applyViewTransitionToHostInstances( - child.child, - name, - className, - null, - false, - ); - if (!inViewport) { - // This boundary is not in the viewport so we won't treat it as a matched pair. - // Revert the transition names. This avoids it flying onto the screen which can - // be disruptive and doesn't really preserve any continuity anyway. - restoreViewTransitionOnHostInstances(child.child, false); - } else { - // We'll transition between them. - const oldinstance: ViewTransitionState = child.stateNode; - const newInstance: ViewTransitionState = pair; - newInstance.paired = oldinstance; - // Note: If the other side ends up outside the viewport, we'll still run this. - // Therefore it's possible for onShare to be called with only an old snapshot. - scheduleViewTransitionEvent(child, props.onShare); - } - } - // Delete the entry so that we know when we've found all of them - // and can stop searching (size reaches zero). - pairs.delete(name); - if (pairs.size === 0) { - break; - } - } - } - } - commitDeletedPairViewTransitions(child); - } - child = child.sibling; - } -} - -function commitExitViewTransitions(deletion: Fiber): void { - if (deletion.tag === ViewTransitionComponent) { - const props: ViewTransitionProps = deletion.memoizedProps; - const name = getViewTransitionName(props, deletion.stateNode); - const pair = - appearingViewTransitions !== null - ? appearingViewTransitions.get(name) - : undefined; - const className: ?string = getViewTransitionClassName( - props.className, - pair !== undefined ? props.share : props.exit, - ); - if (className !== 'none') { - viewTransitionHostInstanceIdx = 0; - const inViewport = applyViewTransitionToHostInstances( - deletion.child, - name, - className, - null, - false, - ); - if (!inViewport) { - // Revert the transition names. This boundary is not in the viewport - // so we won't bother animating it. - restoreViewTransitionOnHostInstances(deletion.child, false); - // TODO: Should we still visit the children in case a named one was in the viewport? - } else if (pair !== undefined) { - // We found a new appearing view transition with the same name as this deletion. - // We'll transition between them instead of running the normal exit. - const oldinstance: ViewTransitionState = deletion.stateNode; - const newInstance: ViewTransitionState = pair; - newInstance.paired = oldinstance; - // Delete the entry so that we know when we've found all of them - // and can stop searching (size reaches zero). - // $FlowFixMe[incompatible-use]: Refined by the pair. - appearingViewTransitions.delete(name); - // Note: If the other side ends up outside the viewport, we'll still run this. - // Therefore it's possible for onShare to be called with only an old snapshot. - scheduleViewTransitionEvent(deletion, props.onShare); - } else { - scheduleViewTransitionEvent(deletion, props.onExit); - } - } - if (appearingViewTransitions !== null) { - // Look for more pairs deeper in the tree. - commitDeletedPairViewTransitions(deletion); - } - } else if ((deletion.subtreeFlags & ViewTransitionStatic) !== NoFlags) { - let child = deletion.child; - while (child !== null) { - commitExitViewTransitions(child); - child = child.sibling; - } - } else { - if (appearingViewTransitions !== null) { - commitDeletedPairViewTransitions(deletion); - } - } -} - -function commitBeforeUpdateViewTransition( - current: Fiber, - finishedWork: Fiber, -): void { - // The way we deal with multiple HostInstances as children of a View Transition in an - // update can get tricky. The important bit is that if you swap out n HostInstances - // from n HostInstances then they match up in order. Similarly, if you don't swap - // any HostInstances each instance just transitions as is. - // - // We call this function twice. First we apply the view transition names on the - // "current" tree in the snapshot phase. Then in the mutation phase we apply view - // transition names to the "finishedWork" tree. - // - // This means that if there were insertions or deletions before an updated Instance - // that same Instance might get different names in the "old" and the "new" state. - // For example if you swap two HostInstances inside a ViewTransition they don't - // animate to swap position but rather cross-fade into the other instance. This might - // be unexpected but it is in line with the semantics that the ViewTransition is its - // own layer that cross-fades its content when it updates. If you want to reorder then - // each child needs its own ViewTransition. - const oldProps: ViewTransitionProps = current.memoizedProps; - const oldName = getViewTransitionName(oldProps, current.stateNode); - const newProps: ViewTransitionProps = finishedWork.memoizedProps; - // This className applies only if there are fewer child DOM nodes than - // before or if this update should've been cancelled but we ended up with - // a parent animating so we need to animate the child too. - // For example, if update="foo" layout="none" and it turns out this was - // a layout only change, then the "foo" class will be applied even though - // it was not actually an update. Which is a bug. - let className: ?string = getViewTransitionClassName( - newProps.className, - newProps.update, - ); - if (className === 'none') { - className = getViewTransitionClassName(newProps.className, newProps.layout); - if (className === 'none') { - // If both update and layout are both "none" then we don't have to - // apply a name. Since we won't animate this boundary. - return; - } - } - viewTransitionHostInstanceIdx = 0; - applyViewTransitionToHostInstances( - current.child, - oldName, - className, - (current.memoizedState = []), - true, - ); -} - -function commitNestedViewTransitions(changedParent: Fiber): void { - let child = changedParent.child; - while (child !== null) { - if (child.tag === ViewTransitionComponent) { - // In this case the outer ViewTransition component wins but if there - // was an update through this component then the inner one wins. - const props: ViewTransitionProps = child.memoizedProps; - const name = getViewTransitionName(props, child.stateNode); - const className: ?string = getViewTransitionClassName( - props.className, - props.layout, - ); - if (className !== 'none') { - viewTransitionHostInstanceIdx = 0; - applyViewTransitionToHostInstances( - child.child, - name, - className, - (child.memoizedState = []), - false, - ); - } - } else if ((child.subtreeFlags & ViewTransitionStatic) !== NoFlags) { - commitNestedViewTransitions(child); - } - child = child.sibling; - } -} - -function restorePairedViewTransitions(parent: Fiber): void { - if ((parent.subtreeFlags & ViewTransitionNamedStatic) === NoFlags) { - // This has no named view transitions in its subtree. - return; - } - let child = parent.child; - while (child !== null) { - if (child.tag === OffscreenComponent && child.memoizedState === null) { - // This tree was already hidden so we skip it. - } else { - if ( - child.tag === ViewTransitionComponent && - (child.flags & ViewTransitionNamedStatic) !== NoFlags - ) { - const instance: ViewTransitionState = child.stateNode; - if (instance.paired !== null) { - instance.paired = null; - restoreViewTransitionOnHostInstances(child.child, false); - } - } - restorePairedViewTransitions(child); - } - child = child.sibling; - } -} - -function restoreEnterViewTransitions(placement: Fiber): void { - if (placement.tag === ViewTransitionComponent) { - const instance: ViewTransitionState = placement.stateNode; - instance.paired = null; - restoreViewTransitionOnHostInstances(placement.child, false); - restorePairedViewTransitions(placement); - } else if ((placement.subtreeFlags & ViewTransitionStatic) !== NoFlags) { - let child = placement.child; - while (child !== null) { - restoreEnterViewTransitions(child); - child = child.sibling; - } - } else { - restorePairedViewTransitions(placement); - } -} - -function restoreExitViewTransitions(deletion: Fiber): void { - if (deletion.tag === ViewTransitionComponent) { - const instance: ViewTransitionState = deletion.stateNode; - instance.paired = null; - restoreViewTransitionOnHostInstances(deletion.child, false); - restorePairedViewTransitions(deletion); - } else if ((deletion.subtreeFlags & ViewTransitionStatic) !== NoFlags) { - let child = deletion.child; - while (child !== null) { - restoreExitViewTransitions(child); - child = child.sibling; - } - } else { - restorePairedViewTransitions(deletion); - } -} - -function restoreUpdateViewTransition( - current: Fiber, - finishedWork: Fiber, -): void { - finishedWork.memoizedState = null; - restoreViewTransitionOnHostInstances(current.child, true); - restoreViewTransitionOnHostInstances(finishedWork.child, true); -} - -function restoreNestedViewTransitions(changedParent: Fiber): void { - let child = changedParent.child; - while (child !== null) { - if (child.tag === ViewTransitionComponent) { - child.memoizedState = null; - restoreViewTransitionOnHostInstances(child.child, false); - } else if ((child.subtreeFlags & ViewTransitionStatic) !== NoFlags) { - restoreNestedViewTransitions(child); - } - child = child.sibling; - } -} - -function cancelViewTransitionHostInstances( - currentViewTransition: Fiber, - child: null | Fiber, - stopAtNestedViewTransitions: boolean, -): void { - if (!supportsMutation) { - return; - } - while (child !== null) { - if (child.tag === HostComponent) { - const instance: Instance = child.stateNode; - const oldName = getViewTransitionName( - currentViewTransition.memoizedProps, - currentViewTransition.stateNode, - ); - if (viewTransitionCancelableChildren === null) { - viewTransitionCancelableChildren = []; - } - viewTransitionCancelableChildren.push( - instance, - oldName, - child.memoizedProps, - ); - viewTransitionHostInstanceIdx++; - } else if ( - child.tag === OffscreenComponent && - child.memoizedState !== null - ) { - // Skip any hidden subtrees. They were or are effectively not there. - } else if ( - child.tag === ViewTransitionComponent && - stopAtNestedViewTransitions - ) { - // Skip any nested view transitions for updates since in that case the - // inner most one is the one that handles the update. - } else { - cancelViewTransitionHostInstances( - currentViewTransition, - child.child, - stopAtNestedViewTransitions, - ); - } - child = child.sibling; - } -} - -function measureViewTransitionHostInstances( - currentViewTransition: Fiber, - parentViewTransition: Fiber, - child: null | Fiber, - name: string, - className: ?string, - previousMeasurements: null | Array, - stopAtNestedViewTransitions: boolean, -): boolean { - if (!supportsMutation) { - return true; - } - let inViewport = false; - while (child !== null) { - if (child.tag === HostComponent) { - const instance: Instance = child.stateNode; - if ( - previousMeasurements !== null && - viewTransitionHostInstanceIdx < previousMeasurements.length - ) { - // The previous measurement of the Instance in this location within the ViewTransition. - // Note that this might not be the same exact Instance if the Instances within the - // ViewTransition changed. - const previousMeasurement = - previousMeasurements[viewTransitionHostInstanceIdx]; - const nextMeasurement = measureInstance(instance); - if ( - wasInstanceInViewport(previousMeasurement) || - wasInstanceInViewport(nextMeasurement) - ) { - // If either the old or new state was within the viewport we have to animate this. - // But if it turns out that none of them were we'll be able to skip it. - inViewport = true; - } - if ( - (parentViewTransition.flags & Update) === NoFlags && - hasInstanceChanged(previousMeasurement, nextMeasurement) - ) { - parentViewTransition.flags |= Update; - } - if (hasInstanceAffectedParent(previousMeasurement, nextMeasurement)) { - // If this instance size within its parent has changed it might have caused the - // parent to relayout which needs a cross fade. - parentViewTransition.flags |= AffectedParentLayout; - } - } else { - // If there was an insertion of extra nodes, we have to assume they affected the parent. - // It should have already been marked as an Update due to the mutation. - parentViewTransition.flags |= AffectedParentLayout; - } - if ((parentViewTransition.flags & Update) !== NoFlags) { - // We might update this node so we need to apply its new name for the new state. - applyViewTransitionName( - instance, - viewTransitionHostInstanceIdx === 0 - ? name - : // If we have multiple Host Instances below, we add a suffix to the name to give - // each one a unique name. - name + '_' + viewTransitionHostInstanceIdx, - className, - ); - } - if (!inViewport || (parentViewTransition.flags & Update) === NoFlags) { - // It turns out that we had no other deeper mutations, the child transitions didn't - // affect the parent layout and this instance hasn't changed size. So we can skip - // animating it. However, in the current model this only works if the parent also - // doesn't animate. So we have to queue these and wait until we complete the parent - // to cancel them. - const oldName = getViewTransitionName( - currentViewTransition.memoizedProps, - currentViewTransition.stateNode, - ); - if (viewTransitionCancelableChildren === null) { - viewTransitionCancelableChildren = []; - } - viewTransitionCancelableChildren.push( - instance, - oldName, - child.memoizedProps, - ); - } - viewTransitionHostInstanceIdx++; - } else if ( - child.tag === OffscreenComponent && - child.memoizedState !== null - ) { - // Skip any hidden subtrees. They were or are effectively not there. - } else if ( - child.tag === ViewTransitionComponent && - stopAtNestedViewTransitions - ) { - // Skip any nested view transitions for updates since in that case the - // inner most one is the one that handles the update. - // If this inner boundary resized we need to bubble that information up. - parentViewTransition.flags |= child.flags & AffectedParentLayout; - } else { - if ( - measureViewTransitionHostInstances( - currentViewTransition, - parentViewTransition, - child.child, - name, - className, - previousMeasurements, - stopAtNestedViewTransitions, - ) - ) { - inViewport = true; - } - } - child = child.sibling; - } - return inViewport; -} - -function measureUpdateViewTransition( - current: Fiber, - finishedWork: Fiber, -): boolean { - const props: ViewTransitionProps = finishedWork.memoizedProps; - const updateClassName: ?string = getViewTransitionClassName( - props.className, - props.update, - ); - const layoutClassName: ?string = getViewTransitionClassName( - props.className, - props.layout, - ); - let className: ?string; - if (updateClassName === 'none') { - if (layoutClassName === 'none') { - // If both update and layout class name were none, then we didn't apply any - // names in the before update phase so we shouldn't now neither. - return false; - } - // We don't care if this is mutated or children layout changed, but we still - // measure each instance to see if it moved and therefore should apply layout. - finishedWork.flags &= ~Update; - className = layoutClassName; - } else if ((finishedWork.flags & Update) !== NoFlags) { - // It was updated and we have an appropriate class name to apply. - className = updateClassName; - } else { - if (layoutClassName === 'none') { - // If we did not update, then all changes are considered a layout. We'll - // attempt to cancel. - viewTransitionHostInstanceIdx = 0; - cancelViewTransitionHostInstances(current, finishedWork.child, true); - return false; - } - // We didn't update but we might still apply layout so we measure each - // instance to see if it moved or resized. - className = layoutClassName; - } - const name = getViewTransitionName(props, finishedWork.stateNode); - // If nothing changed due to a mutation, or children changing size - // and the measurements end up unchanged, we should restore it to not animate. - viewTransitionHostInstanceIdx = 0; - const previousMeasurements = current.memoizedState; - const inViewport = measureViewTransitionHostInstances( - current, - finishedWork, - finishedWork.child, - name, - className, - previousMeasurements, - true, - ); - const previousCount = - previousMeasurements === null ? 0 : previousMeasurements.length; - if (viewTransitionHostInstanceIdx !== previousCount) { - // If we found a different number of child DOM nodes we need to assume that - // the parent layout may have changed as a result. This is not necessarily - // true if those nodes were absolutely positioned. - finishedWork.flags |= AffectedParentLayout; - } - return inViewport; -} - -function measureNestedViewTransitions(changedParent: Fiber): void { - let child = changedParent.child; - while (child !== null) { - if (child.tag === ViewTransitionComponent) { - const current = child.alternate; - if (current !== null) { - const props: ViewTransitionProps = child.memoizedProps; - const name = getViewTransitionName(props, child.stateNode); - const className: ?string = getViewTransitionClassName( - props.className, - props.layout, - ); - viewTransitionHostInstanceIdx = 0; - const inViewport = measureViewTransitionHostInstances( - current, - child, - child.child, - name, - className, - child.memoizedState, - false, - ); - if ((child.flags & Update) === NoFlags || !inViewport) { - // Nothing changed. - } else { - scheduleViewTransitionEvent(child, props.onLayout); - } - } - } else if ((child.subtreeFlags & ViewTransitionStatic) !== NoFlags) { - measureNestedViewTransitions(child); - } - child = child.sibling; - } -} - function commitLayoutEffectOnFiber( finishedRoot: FiberRoot, current: Fiber | null, @@ -3204,14 +2446,14 @@ function commitAfterMutationEffectsOnFiber( switch (finishedWork.tag) { case HostRoot: { viewTransitionContextChanged = false; - viewTransitionCancelableChildren = null; + setViewTransitionCancelableChildren(null); recursivelyTraverseAfterMutationEffects(root, finishedWork, lanes); if (!viewTransitionContextChanged) { // If we didn't leak any resizing out to the root, we don't have to transition // the root itself. This means that we can now safely cancel any cancellations // that bubbled all the way up. const cancelableChildren = viewTransitionCancelableChildren; - viewTransitionCancelableChildren = null; + setViewTransitionCancelableChildren(null); if (cancelableChildren !== null) { for (let i = 0; i < cancelableChildren.length; i += 3) { cancelViewTransitionName( @@ -3264,7 +2506,7 @@ function commitAfterMutationEffectsOnFiber( const prevContextChanged = viewTransitionContextChanged; const prevCancelableChildren = viewTransitionCancelableChildren; viewTransitionContextChanged = false; - viewTransitionCancelableChildren = null; + setViewTransitionCancelableChildren(null); recursivelyTraverseAfterMutationEffects(root, finishedWork, lanes); if (viewTransitionContextChanged) { @@ -3287,7 +2529,7 @@ function commitAfterMutationEffectsOnFiber( prevCancelableChildren, viewTransitionCancelableChildren, ); - viewTransitionCancelableChildren = prevCancelableChildren; + setViewTransitionCancelableChildren(prevCancelableChildren); } // TODO: If this doesn't end up canceled, because a parent animates, // then we should probably issue an event since this instance is part of it. @@ -3301,7 +2543,7 @@ function commitAfterMutationEffectsOnFiber( ); // If this boundary did update, we cannot cancel its children so those are dropped. - viewTransitionCancelableChildren = prevCancelableChildren; + setViewTransitionCancelableChildren(prevCancelableChildren); } if ((finishedWork.flags & AffectedParentLayout) !== NoFlags) { @@ -4810,7 +4052,7 @@ export function commitPassiveUnmountEffects(finishedWork: Fiber): void { // pairs. let suspenseyCommitFlag = ShouldSuspendCommit; export function accumulateSuspenseyCommit(finishedWork: Fiber): void { - appearingViewTransitions = null; + resetAppearingViewTransitions(); accumulateSuspenseyCommitOnFiber(finishedWork); } @@ -4897,14 +4139,11 @@ function accumulateSuspenseyCommitOnFiber(fiber: Fiber) { if (name != null && name !== 'auto') { // This is a named ViewTransition being mounted or reappearing. Let's add it to // the map so we can match it with deletions later. - if (appearingViewTransitions === null) { - appearingViewTransitions = new Map(); - } + const state: ViewTransitionState = fiber.stateNode; // Reset the pair in case we didn't end up restoring the instance in previous commits. // This shouldn't really happen anymore but just in case. We could maybe add an invariant. - const instance: ViewTransitionState = fiber.stateNode; - instance.paired = null; - appearingViewTransitions.set(name, instance); + state.paired = null; + trackAppearingViewTransition(name, state); } } recursivelyAccumulateSuspenseyCommit(fiber); diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index b3d1e5371c06c..d5ef003e3dc61 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -226,8 +226,8 @@ import { invokeLayoutEffectUnmountInDEV, invokePassiveEffectUnmountInDEV, accumulateSuspenseyCommit, - shouldStartViewTransition, } from './ReactFiberCommitWork'; +import {shouldStartViewTransition} from './ReactFiberCommitViewTransitions'; import {enqueueUpdate} from './ReactFiberClassUpdateQueue'; import {resetContextDependencies} from './ReactFiberNewContext'; import { From 92e65ca68f6bfc6be515ccacaa918e33b63911df Mon Sep 17 00:00:00 2001 From: lauren Date: Tue, 25 Feb 2025 18:55:49 -0500 Subject: [PATCH 06/18] [forgive] Add basic codelens provider (#32476) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a first codelens provider for successfully compiled functions. A later PR will add an actual command that will fire when the codelens is clicked ![Screenshot 2025-02-25 at 6 40 20 PM](https://github.com/user-attachments/assets/924586e0-f70a-45d1-b0e6-a89af9371c8d) --- .../src/Entrypoint/Options.ts | 77 ++++++++++-------- .../server/src/compiler/compat.ts | 22 +++++ .../server/src/compiler/index.ts | 12 ++- .../react-forgive/server/src/index.ts | 80 +++++++++++++------ 4 files changed, 129 insertions(+), 62 deletions(-) create mode 100644 compiler/packages/react-forgive/server/src/compiler/compat.ts diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts index 35c2c4134eb44..781abd05f35da 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts @@ -176,41 +176,48 @@ export type CompilationMode = z.infer; * babel or other unhandled exceptions). */ export type LoggerEvent = - | { - kind: 'CompileError'; - fnLoc: t.SourceLocation | null; - detail: CompilerErrorDetailOptions; - } - | { - kind: 'CompileDiagnostic'; - fnLoc: t.SourceLocation | null; - detail: Omit, 'suggestions'>; - } - | { - kind: 'CompileSkip'; - fnLoc: t.SourceLocation | null; - reason: string; - loc: t.SourceLocation | null; - } - | { - kind: 'CompileSuccess'; - fnLoc: t.SourceLocation | null; - fnName: string | null; - memoSlots: number; - memoBlocks: number; - memoValues: number; - prunedMemoBlocks: number; - prunedMemoValues: number; - } - | { - kind: 'PipelineError'; - fnLoc: t.SourceLocation | null; - data: string; - } - | { - kind: 'Timing'; - measurement: PerformanceMeasure; - }; + | CompileSuccessEvent + | CompileErrorEvent + | CompileDiagnosticEvent + | CompileSkipEvent + | PipelineErrorEvent + | TimingEvent; + +export type CompileErrorEvent = { + kind: 'CompileError'; + fnLoc: t.SourceLocation | null; + detail: CompilerErrorDetailOptions; +}; +export type CompileDiagnosticEvent = { + kind: 'CompileDiagnostic'; + fnLoc: t.SourceLocation | null; + detail: Omit, 'suggestions'>; +}; +export type CompileSuccessEvent = { + kind: 'CompileSuccess'; + fnLoc: t.SourceLocation | null; + fnName: string | null; + memoSlots: number; + memoBlocks: number; + memoValues: number; + prunedMemoBlocks: number; + prunedMemoValues: number; +}; +export type CompileSkipEvent = { + kind: 'CompileSkip'; + fnLoc: t.SourceLocation | null; + reason: string; + loc: t.SourceLocation | null; +}; +export type PipelineErrorEvent = { + kind: 'PipelineError'; + fnLoc: t.SourceLocation | null; + data: string; +}; +export type TimingEvent = { + kind: 'Timing'; + measurement: PerformanceMeasure; +}; export type Logger = { logEvent: (filename: string | null, event: LoggerEvent) => void; diff --git a/compiler/packages/react-forgive/server/src/compiler/compat.ts b/compiler/packages/react-forgive/server/src/compiler/compat.ts new file mode 100644 index 0000000000000..8b13f1df886ea --- /dev/null +++ b/compiler/packages/react-forgive/server/src/compiler/compat.ts @@ -0,0 +1,22 @@ +import {SourceLocation} from 'babel-plugin-react-compiler/src'; +import {type Range} from 'vscode-languageserver'; + +export function babelLocationToRange(loc: SourceLocation): Range | null { + if (typeof loc === 'symbol') { + return null; + } + return { + start: {line: loc.start.line - 1, character: loc.start.column}, + end: {line: loc.end.line - 1, character: loc.end.column}, + }; +} + +/** + * Refine range to only the first character. + */ +export function getRangeFirstCharacter(range: Range): Range { + return { + start: range.start, + end: range.start, + }; +} diff --git a/compiler/packages/react-forgive/server/src/compiler/index.ts b/compiler/packages/react-forgive/server/src/compiler/index.ts index be2cca94ca154..3723785cfbebd 100644 --- a/compiler/packages/react-forgive/server/src/compiler/index.ts +++ b/compiler/packages/react-forgive/server/src/compiler/index.ts @@ -11,10 +11,12 @@ import BabelPluginReactCompiler, { type PluginOptions, } from 'babel-plugin-react-compiler/src'; import * as babelParser from 'prettier/plugins/babel.js'; -import * as estreeParser from 'prettier/plugins/estree'; +import estreeParser from 'prettier/plugins/estree'; import * as typescriptParser from 'prettier/plugins/typescript'; import * as prettier from 'prettier/standalone'; +export let lastResult: BabelCore.BabelFileResult | null = null; + type CompileOptions = { text: string; file: string; @@ -24,7 +26,7 @@ export async function compile({ text, file, options, -}: CompileOptions): Promise { +}: CompileOptions): Promise { const ast = await parseAsync(text, { sourceFileName: file, parserOpts: { @@ -32,6 +34,9 @@ export async function compile({ }, sourceType: 'module', }); + if (ast == null) { + return null; + } const plugins = options != null ? [[BabelPluginReactCompiler, options]] @@ -54,5 +59,8 @@ export async function compile({ parser: 'babel-ts', plugins: [babelParser, estreeParser, typescriptParser], }); + if (result.code != null) { + lastResult = result; + } return result; } diff --git a/compiler/packages/react-forgive/server/src/index.ts b/compiler/packages/react-forgive/server/src/index.ts index 057df617c8d10..395969c5e06bf 100644 --- a/compiler/packages/react-forgive/server/src/index.ts +++ b/compiler/packages/react-forgive/server/src/index.ts @@ -7,6 +7,7 @@ import {TextDocument} from 'vscode-languageserver-textdocument'; import { + CodeLens, createConnection, type InitializeParams, type InitializeResult, @@ -14,10 +15,15 @@ import { TextDocuments, TextDocumentSyncKind, } from 'vscode-languageserver/node'; -import {compile} from './compiler'; +import {compile, lastResult} from './compiler'; import {type PluginOptions} from 'babel-plugin-react-compiler/src'; import {resolveReactConfig} from './compiler/options'; -import {type BabelFileResult} from '@babel/core'; +import { + CompileSuccessEvent, + defaultOptions, + LoggerEvent, +} from 'babel-plugin-react-compiler/src/Entrypoint/Options'; +import {babelLocationToRange, getRangeFirstCharacter} from './compiler/compat'; const SUPPORTED_LANGUAGE_IDS = new Set([ 'javascript', @@ -30,11 +36,21 @@ const connection = createConnection(ProposedFeatures.all); const documents = new TextDocuments(TextDocument); let compilerOptions: PluginOptions | null = null; -let lastResult: BabelFileResult | null = null; +let compiledFns: Set = new Set(); connection.onInitialize((_params: InitializeParams) => { // TODO(@poteto) get config fr - compilerOptions = resolveReactConfig('.'); + compilerOptions = resolveReactConfig('.') ?? defaultOptions; + compilerOptions = { + ...compilerOptions, + logger: { + logEvent(_filename: string | null, event: LoggerEvent) { + if (event.kind === 'CompileSuccess') { + compiledFns.add(event); + } + }, + }, + }; const result: InitializeResult = { capabilities: { textDocumentSync: TextDocumentSyncKind.Full, @@ -48,44 +64,58 @@ connection.onInitialized(() => { connection.console.log('initialized'); }); -documents.onDidOpen(async event => { - if (SUPPORTED_LANGUAGE_IDS.has(event.document.languageId)) { - const text = event.document.getText(); - const result = await compile({ - text, - file: event.document.uri, - options: compilerOptions, - }); - if (result.code != null) { - lastResult = result; - } - } -}); - documents.onDidChangeContent(async event => { + connection.console.info(`Changed: ${event.document.uri}`); + compiledFns.clear(); if (SUPPORTED_LANGUAGE_IDS.has(event.document.languageId)) { const text = event.document.getText(); - const result = await compile({ + await compile({ text, file: event.document.uri, options: compilerOptions, }); - if (result.code != null) { - lastResult = result; - } } }); connection.onDidChangeWatchedFiles(change => { + compiledFns.clear(); connection.console.log( change.changes.map(c => `File changed: ${c.uri}`).join('\n'), ); }); connection.onCodeLens(params => { - connection.console.log('lastResult: ' + JSON.stringify(lastResult, null, 2)); - connection.console.log('params: ' + JSON.stringify(params, null, 2)); - return []; + connection.console.info(`Handling codelens for: ${params.textDocument.uri}`); + if (compiledFns.size === 0) { + return; + } + const lenses: Array = []; + for (const compiled of compiledFns) { + if (compiled.fnLoc != null) { + const fnLoc = babelLocationToRange(compiled.fnLoc); + if (fnLoc === null) continue; + const lens = CodeLens.create( + getRangeFirstCharacter(fnLoc), + compiled.fnLoc, + ); + if (lastResult?.code != null) { + lens.command = { + title: 'Optimized by React Compiler', + command: 'todo', + }; + } + lenses.push(lens); + } + } + return lenses; +}); + +connection.onCodeLensResolve(lens => { + connection.console.info(`Resolving codelens for: ${JSON.stringify(lens)}`); + if (lastResult?.code != null) { + connection.console.log(lastResult.code); + } + return lens; }); documents.listen(connection); From ebc22ef7e15bf38dc91b7033782cedc2f43f7d6e Mon Sep 17 00:00:00 2001 From: lauren Date: Tue, 25 Feb 2025 19:09:21 -0500 Subject: [PATCH 07/18] [forgive][ez] Ignore test file (#32477) --- compiler/packages/react-forgive/.vscodeignore | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/packages/react-forgive/.vscodeignore b/compiler/packages/react-forgive/.vscodeignore index 91f9572794cd5..9ef76302ed597 100644 --- a/compiler/packages/react-forgive/.vscodeignore +++ b/compiler/packages/react-forgive/.vscodeignore @@ -2,3 +2,4 @@ client server scripts +.vscode-test.mjs From 2df96224779237f532ca64c8c7e8a8605c06f067 Mon Sep 17 00:00:00 2001 From: lauren Date: Thu, 27 Feb 2025 11:24:30 -0500 Subject: [PATCH 08/18] [release] Update publishing scripts to make publishing allowlisted packages easier (#32486) It's getting unwieldy to list every single package to skip in these commands when you only want to publish one, ie eslint-plugin-react-hooks. This adds a new `onlyPackages` and `publishVersion` option to the publish commands to make that easier. --- .../parse-params.js | 7 +++++++ scripts/release/prepare-release-from-npm.js | 3 +++ scripts/release/publish-commands/parse-params.js | 12 ++++++++++++ scripts/release/publish.js | 12 +++++++++--- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/scripts/release/prepare-release-from-npm-commands/parse-params.js b/scripts/release/prepare-release-from-npm-commands/parse-params.js index b9aa1a4f5e7e8..b08d81e89dc18 100644 --- a/scripts/release/prepare-release-from-npm-commands/parse-params.js +++ b/scripts/release/prepare-release-from-npm-commands/parse-params.js @@ -13,6 +13,13 @@ const paramDefinitions = [ 'Skip NPM and use the build already present in "build/node_modules".', defaultValue: false, }, + { + name: 'onlyPackages', + type: String, + multiple: true, + description: 'Packages to include in publishing', + defaultValue: [], + }, { name: 'skipPackages', type: String, diff --git a/scripts/release/prepare-release-from-npm.js b/scripts/release/prepare-release-from-npm.js index e23ffb39bc1c0..8220fda220b65 100755 --- a/scripts/release/prepare-release-from-npm.js +++ b/scripts/release/prepare-release-from-npm.js @@ -28,6 +28,9 @@ const run = async () => { params.packages = await getPublicPackages(isExperimental); params.packages = params.packages.filter(packageName => { + if (params.onlyPackages.length > 0) { + return params.onlyPackages.includes(packageName); + } return !params.skipPackages.includes(packageName); }); diff --git a/scripts/release/publish-commands/parse-params.js b/scripts/release/publish-commands/parse-params.js index b7196447d4da8..ce9a9b7825c1a 100644 --- a/scripts/release/publish-commands/parse-params.js +++ b/scripts/release/publish-commands/parse-params.js @@ -19,6 +19,13 @@ const paramDefinitions = [ description: 'NPM tags to point to the new release.', defaultValue: ['untagged'], }, + { + name: 'onlyPackages', + type: String, + multiple: true, + description: 'Packages to include in publishing', + defaultValue: [], + }, { name: 'skipPackages', type: String, @@ -32,6 +39,11 @@ const paramDefinitions = [ description: 'Run in automated environment, without interactive prompts.', defaultValue: false, }, + { + name: 'publishVersion', + type: String, + description: 'Version to publish', + }, ]; module.exports = () => { diff --git a/scripts/release/publish.js b/scripts/release/publish.js index dcd31f1de7796..87b9940636b18 100755 --- a/scripts/release/publish.js +++ b/scripts/release/publish.js @@ -23,14 +23,20 @@ const run = async () => { try { const params = parseParams(); - const version = readJsonSync( - './build/node_modules/react/package.json' - ).version; + const version = + params.publishVersion ?? + readJsonSync('./build/node_modules/react/package.json').version; const isExperimental = version.includes('experimental'); params.cwd = join(__dirname, '..', '..'); params.packages = await getPublicPackages(isExperimental); + if (params.onlyPackages.length > 0) { + params.packages = params.packages.filter(packageName => { + return params.onlyPackages.includes(packageName); + }); + } + // Pre-filter any skipped packages to simplify the following commands. // As part of doing this we can also validate that none of the skipped packages were misspelled. params.skipPackages.forEach(packageName => { From 227e8414cc5af227b5de339cace2447d4a81c995 Mon Sep 17 00:00:00 2001 From: lauren Date: Thu, 27 Feb 2025 13:07:52 -0500 Subject: [PATCH 09/18] [ci] Add workflow to publish releases (#32487) Adds a new workflow to publish runtime releases from NPM. Note that I commented out the actual publish command so I can test it out first. --- .../runtime_releases_from_npm_manual.yml | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 .github/workflows/runtime_releases_from_npm_manual.yml diff --git a/.github/workflows/runtime_releases_from_npm_manual.yml b/.github/workflows/runtime_releases_from_npm_manual.yml new file mode 100644 index 0000000000000..0851b38ff97b0 --- /dev/null +++ b/.github/workflows/runtime_releases_from_npm_manual.yml @@ -0,0 +1,91 @@ +name: (Runtime) Publish Releases from NPM Manual + +on: + workflow_dispatch: + inputs: + version_to_promote: + required: true + description: Current npm version (non-experimental) to promote + type: string + version_to_publish: + required: true + description: Version to publish for the specified packages + type: string + only_packages: + description: Space separated list of packages to publish on NPM. Use this OR skip_packages, not together. + type: string + skip_packages: + description: Space separated list of packages to NOT publish on NPM. Use this OR only_packages, not together. + type: string + tags: + description: Space separated list of tags to tag the release with on NPM + type: string + default: "['untagged']" + dry: + required: true + description: Don't actually publish, just run a dry run + type: boolean + default: true + force_notify: + description: Force a Discord notification + type: boolean + default: false + +env: + TZ: /usr/share/zoneinfo/America/Los_Angeles + # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout + SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 + GH_TOKEN: ${{ github.token }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + +jobs: + notify: + if: ${{ inputs.force_notify || inputs.dry == false || inputs.dry == 'false' }} + runs-on: ubuntu-latest + steps: + - name: Discord Webhook Action + uses: tsickert/discord-webhook@v6.0.0 + with: + webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }} + embed-author-name: ${{ github.event.sender.login }} + embed-author-url: ${{ github.event.sender.html_url }} + embed-author-icon-url: ${{ github.event.sender.avatar_url }} + embed-title: '⚠️ Publishing release from NPM' + embed-description: | + ``` + inputs: ${{ toJson(inputs) }} + ``` + embed-url: https://github.com/facebook/react/actions/runs/${{ github.run_id }} + + publish: + name: Publish releases + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + cache: yarn + cache-dependency-path: yarn.lock + - name: Restore cached node_modules + uses: actions/cache@v4 + id: node_modules + with: + path: "**/node_modules" + key: runtime-release-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }} + - name: Ensure clean build directory + run: rm -rf build + - run: yarn install --frozen-lockfile + - run: yarn install --frozen-lockfile + working-directory: scripts/release + - run: cp ./scripts/release/ci-npmrc ~/.npmrc + - if: '${{ inputs.only_packages }}' + run: | + scripts/release/prepare-release-from-npm.js --skipTests --version=${{ inputs.version_to_promote }} --onlyPackages=${{ inputs.only_packages }} + ls -R build/node_modules + # scripts/release/publish.js --ci --tags=${{ inputs.tags }} --publishVersion=${{ inputs.version_to_publish }} --onlyPackages=${{ inputs.only_packages }} --dry=${{ inputs.dry || 'false' }} + - if: '${{ inputs.skip_packages }}' + run: | + scripts/release/prepare-release-from-npm.js --skipTests --version=${{ inputs.version_to_promote }} --skipPackages=${{ inputs.skip_packages }} + ls -R build/node_modules + # scripts/release/publish.js --ci --tags=${{ inputs.tags }} --publishVersion=${{ inputs.version_to_publish }} --skipPackages=${{ inputs.skip_packages }} --dry=${{ inputs.dry || 'false' }} From 4c9392b43e9f39e17c18ef1c2cd0f0a14e85669c Mon Sep 17 00:00:00 2001 From: lauren Date: Thu, 27 Feb 2025 15:24:57 -0500 Subject: [PATCH 10/18] [ci] Prepare publish workflow (#32488) Fixes up a few things in the script and workflow to make it possible to run in CI without interactive prompts. --- .../runtime_releases_from_npm_manual.yml | 56 +++++++++++---- .../confirm-stable-version-numbers.js | 72 ++++++++++--------- .../guess-stable-version-numbers.js | 56 +++++++++------ .../parse-params.js | 11 +++ .../update-stable-version-numbers.js | 10 ++- scripts/release/prepare-release-from-npm.js | 7 ++ .../confirm-version-and-tags.js | 3 + .../publish-commands/publish-to-npm.js | 4 +- scripts/release/publish.js | 7 ++ 9 files changed, 154 insertions(+), 72 deletions(-) diff --git a/.github/workflows/runtime_releases_from_npm_manual.yml b/.github/workflows/runtime_releases_from_npm_manual.yml index 0851b38ff97b0..2759b4e4d8737 100644 --- a/.github/workflows/runtime_releases_from_npm_manual.yml +++ b/.github/workflows/runtime_releases_from_npm_manual.yml @@ -12,22 +12,22 @@ on: description: Version to publish for the specified packages type: string only_packages: - description: Space separated list of packages to publish on NPM. Use this OR skip_packages, not together. + description: Packages to publish (space separated) type: string skip_packages: - description: Space separated list of packages to NOT publish on NPM. Use this OR only_packages, not together. + description: Packages to NOT publish (space separated) type: string tags: - description: Space separated list of tags to tag the release with on NPM + description: NPM tags (space separated) type: string - default: "['untagged']" + default: untagged dry: required: true - description: Don't actually publish, just run a dry run + description: Dry run instead of publish? type: boolean default: true force_notify: - description: Force a Discord notification + description: Force a Discord notification? type: boolean default: false @@ -52,8 +52,8 @@ jobs: embed-author-icon-url: ${{ github.event.sender.avatar_url }} embed-title: '⚠️ Publishing release from NPM' embed-description: | - ``` - inputs: ${{ toJson(inputs) }} + ```json + ${{ toJson(inputs) }} ``` embed-url: https://github.com/facebook/react/actions/runs/${{ github.run_id }} @@ -80,12 +80,44 @@ jobs: working-directory: scripts/release - run: cp ./scripts/release/ci-npmrc ~/.npmrc - if: '${{ inputs.only_packages }}' + name: 'Prepare and publish ${{ inputs.only_packages }}' run: | - scripts/release/prepare-release-from-npm.js --skipTests --version=${{ inputs.version_to_promote }} --onlyPackages=${{ inputs.only_packages }} + echo -e "===== Preparing release from NPM =====\n" + scripts/release/prepare-release-from-npm.js \ + --ci \ + --skipTests \ + --version=${{ inputs.version_to_promote }} \ + --publishVersion=${{ inputs.version_to_publish }} \ + --onlyPackages=${{ inputs.only_packages }} + + echo -e "\n\n===== Check prepared files =====\n" ls -R build/node_modules - # scripts/release/publish.js --ci --tags=${{ inputs.tags }} --publishVersion=${{ inputs.version_to_publish }} --onlyPackages=${{ inputs.only_packages }} --dry=${{ inputs.dry || 'false' }} + + echo -e "\n\n===== Publishing to NPM =====\n" + scripts/release/publish.js \ + --ci \ + --tags=${{ inputs.tags }} \ + --publishVersion=${{ inputs.version_to_publish }} \ + --onlyPackages=${{ inputs.only_packages }} \ + --dry=${{ inputs.dry }} - if: '${{ inputs.skip_packages }}' + name: 'Prepare and publish all packages EXCEPT ${{ inputs.skip_packages }}' run: | - scripts/release/prepare-release-from-npm.js --skipTests --version=${{ inputs.version_to_promote }} --skipPackages=${{ inputs.skip_packages }} + echo -e "===== Preparing release from NPM =====\n" + scripts/release/prepare-release-from-npm.js \ + --ci \ + --skipTests \ + --version=${{ inputs.version_to_promote }} \ + --publishVersion=${{ inputs.version_to_publish }} \ + --skipPackages=${{ inputs.skip_packages }} + + echo -e "\n\n===== Check prepared files =====\n" ls -R build/node_modules - # scripts/release/publish.js --ci --tags=${{ inputs.tags }} --publishVersion=${{ inputs.version_to_publish }} --skipPackages=${{ inputs.skip_packages }} --dry=${{ inputs.dry || 'false' }} + + echo -e "\n\n===== Publishing to NPM =====\n" + scripts/release/publish.js \ + --ci \ + --tags=${{ inputs.tags }} \ + --publishVersion=${{ inputs.version_to_publish }} \ + --skipPackages=${{ inputs.skip_packages }} \ + --dry=${{ inputs.dry }} diff --git a/scripts/release/prepare-release-from-npm-commands/confirm-stable-version-numbers.js b/scripts/release/prepare-release-from-npm-commands/confirm-stable-version-numbers.js index 0b93fba2fc12b..6bf49132149a8 100644 --- a/scripts/release/prepare-release-from-npm-commands/confirm-stable-version-numbers.js +++ b/scripts/release/prepare-release-from-npm-commands/confirm-stable-version-numbers.js @@ -7,7 +7,7 @@ const semver = require('semver'); const theme = require('../theme'); const {confirm} = require('../utils'); -const run = async ({skipPackages}, versionsMap) => { +const run = async ({ci, skipPackages}, versionsMap) => { const groupedVersionsMap = new Map(); // Group packages with the same source versions. @@ -22,44 +22,46 @@ const run = async ({skipPackages}, versionsMap) => { } }); - // Prompt user to confirm or override each version group. - const entries = [...groupedVersionsMap.entries()]; - for (let i = 0; i < entries.length; i++) { - const [bestGuessVersion, packages] = entries[i]; - const packageNames = packages.map(name => theme.package(name)).join(', '); + if (ci !== true) { + // Prompt user to confirm or override each version group if not running in CI. + const entries = [...groupedVersionsMap.entries()]; + for (let i = 0; i < entries.length; i++) { + const [bestGuessVersion, packages] = entries[i]; + const packageNames = packages.map(name => theme.package(name)).join(', '); - let version = bestGuessVersion; - if ( - skipPackages.some(skipPackageName => packages.includes(skipPackageName)) - ) { - await confirm( - theme`{spinnerSuccess ✓} Version for ${packageNames} will remain {version ${bestGuessVersion}}` - ); - } else { - const defaultVersion = bestGuessVersion - ? theme.version(` (default ${bestGuessVersion})`) - : ''; - version = - (await prompt( - theme`{spinnerSuccess ✓} Version for ${packageNames}${defaultVersion}: ` - )) || bestGuessVersion; - prompt.done(); - } + let version = bestGuessVersion; + if ( + skipPackages.some(skipPackageName => packages.includes(skipPackageName)) + ) { + await confirm( + theme`{spinnerSuccess ✓} Version for ${packageNames} will remain {version ${bestGuessVersion}}` + ); + } else { + const defaultVersion = bestGuessVersion + ? theme.version(` (default ${bestGuessVersion})`) + : ''; + version = + (await prompt( + theme`{spinnerSuccess ✓} Version for ${packageNames}${defaultVersion}: ` + )) || bestGuessVersion; + prompt.done(); + } - // Verify a valid version has been supplied. - try { - semver(version); + // Verify a valid version has been supplied. + try { + semver(version); - packages.forEach(packageName => { - versionsMap.set(packageName, version); - }); - } catch (error) { - console.log( - theme`{spinnerError ✘} Version {version ${version}} is invalid.` - ); + packages.forEach(packageName => { + versionsMap.set(packageName, version); + }); + } catch (error) { + console.log( + theme`{spinnerError ✘} Version {version ${version}} is invalid.` + ); - // Prompt again - i--; + // Prompt again + i--; + } } } }; diff --git a/scripts/release/prepare-release-from-npm-commands/guess-stable-version-numbers.js b/scripts/release/prepare-release-from-npm-commands/guess-stable-version-numbers.js index a3cde5d1c4fce..c0072b6637177 100644 --- a/scripts/release/prepare-release-from-npm-commands/guess-stable-version-numbers.js +++ b/scripts/release/prepare-release-from-npm-commands/guess-stable-version-numbers.js @@ -5,7 +5,10 @@ const semver = require('semver'); const {execRead, logPromise} = require('../utils'); -const run = async ({cwd, packages, skipPackages}, versionsMap) => { +const run = async ( + {cwd, packages, skipPackages, ci, publishVersion}, + versionsMap +) => { const branch = await execRead('git branch | grep \\* | cut -d " " -f2', { cwd, }); @@ -13,30 +16,41 @@ const run = async ({cwd, packages, skipPackages}, versionsMap) => { for (let i = 0; i < packages.length; i++) { const packageName = packages[i]; - try { - // In case local package JSONs are outdated, - // guess the next version based on the latest NPM release. - const version = await execRead(`npm show ${packageName} version`); - - if (skipPackages.includes(packageName)) { - versionsMap.set(packageName, version); + if (ci === true) { + if (publishVersion != null) { + versionsMap.set(packageName, publishVersion); } else { - const {major, minor, patch} = semver(version); - - // Guess the next version by incrementing patch. - // The script will confirm this later. - // By default, new releases from mains should increment the minor version number, - // and patch releases should be done from branches. - if (branch === 'main') { - versionsMap.set(packageName, `${major}.${minor + 1}.0`); + console.error( + 'When running in CI mode, a publishVersion must be supplied' + ); + process.exit(1); + } + } else { + try { + // In case local package JSONs are outdated, + // guess the next version based on the latest NPM release. + const version = await execRead(`npm show ${packageName} version`); + + if (skipPackages.includes(packageName)) { + versionsMap.set(packageName, version); } else { - versionsMap.set(packageName, `${major}.${minor}.${patch + 1}`); + const {major, minor, patch} = semver(version); + + // Guess the next version by incrementing patch. + // The script will confirm this later. + // By default, new releases from mains should increment the minor version number, + // and patch releases should be done from branches. + if (branch === 'main') { + versionsMap.set(packageName, `${major}.${minor + 1}.0`); + } else { + versionsMap.set(packageName, `${major}.${minor}.${patch + 1}`); + } } + } catch (error) { + // If the package has not yet been published, + // we'll require a version number to be entered later. + versionsMap.set(packageName, null); } - } catch (error) { - // If the package has not yet been published, - // we'll require a version number to be entered later. - versionsMap.set(packageName, null); } } }; diff --git a/scripts/release/prepare-release-from-npm-commands/parse-params.js b/scripts/release/prepare-release-from-npm-commands/parse-params.js index b08d81e89dc18..ef9c4979b2030 100644 --- a/scripts/release/prepare-release-from-npm-commands/parse-params.js +++ b/scripts/release/prepare-release-from-npm-commands/parse-params.js @@ -39,6 +39,17 @@ const paramDefinitions = [ description: 'Version of published "next" release (e.g. 0.0.0-0e526bcec-20210202)', }, + { + name: 'publishVersion', + type: String, + description: 'Version to publish', + }, + { + name: 'ci', + type: Boolean, + description: 'Run in automated environment, without interactive prompts.', + defaultValue: false, + }, ]; module.exports = () => { diff --git a/scripts/release/prepare-release-from-npm-commands/update-stable-version-numbers.js b/scripts/release/prepare-release-from-npm-commands/update-stable-version-numbers.js index a41d83ac69dbb..f201118890456 100644 --- a/scripts/release/prepare-release-from-npm-commands/update-stable-version-numbers.js +++ b/scripts/release/prepare-release-from-npm-commands/update-stable-version-numbers.js @@ -9,7 +9,7 @@ const {join, relative} = require('path'); const {confirm, execRead, printDiff} = require('../utils'); const theme = require('../theme'); -const run = async ({cwd, packages, version}, versionsMap) => { +const run = async ({cwd, packages, version, ci}, versionsMap) => { const nodeModulesPath = join(cwd, 'build/node_modules'); // Cache all package JSONs for easy lookup below. @@ -107,7 +107,9 @@ const run = async ({cwd, packages, version}, versionsMap) => { printDependencies(packageJSON.dependencies, 'dependency'); printDependencies(packageJSON.peerDependencies, 'peer'); } - await confirm('Do the versions above look correct?'); + if (ci !== true) { + await confirm('Do the versions above look correct?'); + } clear(); @@ -167,7 +169,9 @@ const run = async ({cwd, packages, version}, versionsMap) => { console.log( theme`A full diff is available at {path ${relative(cwd, diffPath)}}.` ); - await confirm('Do the changes above look correct?'); + if (ci !== true) { + await confirm('Do the changes above look correct?'); + } } else { console.log( theme`Skipping React renderer version update because React is not included in the release.` diff --git a/scripts/release/prepare-release-from-npm.js b/scripts/release/prepare-release-from-npm.js index 8220fda220b65..bb67fddd37803 100755 --- a/scripts/release/prepare-release-from-npm.js +++ b/scripts/release/prepare-release-from-npm.js @@ -26,6 +26,13 @@ const run = async () => { params.version = await getLatestNextVersion(); } + if (params.onlyPackages.length > 0 && params.skipPackages.length > 0) { + console.error( + '--onlyPackages and --skipPackages cannot be used together' + ); + process.exit(1); + } + params.packages = await getPublicPackages(isExperimental); params.packages = params.packages.filter(packageName => { if (params.onlyPackages.length > 0) { diff --git a/scripts/release/publish-commands/confirm-version-and-tags.js b/scripts/release/publish-commands/confirm-version-and-tags.js index 6900878da02f6..2c6fed58d1937 100644 --- a/scripts/release/publish-commands/confirm-version-and-tags.js +++ b/scripts/release/publish-commands/confirm-version-and-tags.js @@ -38,6 +38,9 @@ const run = async ({cwd, packages, tags, ci}) => { console.log( theme`• {package ${packageName}} {version ${packageJSON.version}}` ); + if (ci) { + console.log(packageJSON); + } } if (!ci) { diff --git a/scripts/release/publish-commands/publish-to-npm.js b/scripts/release/publish-commands/publish-to-npm.js index d9e3b1902383f..f1e62657c0c38 100644 --- a/scripts/release/publish-commands/publish-to-npm.js +++ b/scripts/release/publish-commands/publish-to-npm.js @@ -27,7 +27,9 @@ const run = async ({cwd, dry, tags, ci}, packageName, otp) => { await confirm('Is this expected?'); } } else { - console.log(theme`{spinnerSuccess ✓} Publishing {package ${packageName}}`); + console.log( + theme`{spinnerSuccess ✓} Publishing {package ${packageName}}${dry ? ' (dry-run)' : ''}` + ); // Publish the package and tag it. if (!dry) { diff --git a/scripts/release/publish.js b/scripts/release/publish.js index 87b9940636b18..f9e450b559208 100755 --- a/scripts/release/publish.js +++ b/scripts/release/publish.js @@ -31,6 +31,13 @@ const run = async () => { params.cwd = join(__dirname, '..', '..'); params.packages = await getPublicPackages(isExperimental); + if (params.onlyPackages.length > 0 && params.skipPackages.length > 0) { + console.error( + '--onlyPackages and --skipPackages cannot be used together' + ); + process.exit(1); + } + if (params.onlyPackages.length > 0) { params.packages = params.packages.filter(packageName => { return params.onlyPackages.includes(packageName); From 5eb20b3007a8fafaf032c2e028c335ab09217d9f Mon Sep 17 00:00:00 2001 From: lauren Date: Thu, 27 Feb 2025 16:01:31 -0500 Subject: [PATCH 11/18] [ci] Fix --dry not being passed correctly (#32489) Boolean params for dry runs are true if the param exists at all, so only add it if we're in dry run mode. --- .../runtime_releases_from_npm_manual.yml | 42 +++++++++---------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/.github/workflows/runtime_releases_from_npm_manual.yml b/.github/workflows/runtime_releases_from_npm_manual.yml index 2759b4e4d8737..3c8cec7f7ac1b 100644 --- a/.github/workflows/runtime_releases_from_npm_manual.yml +++ b/.github/workflows/runtime_releases_from_npm_manual.yml @@ -50,7 +50,7 @@ jobs: embed-author-name: ${{ github.event.sender.login }} embed-author-url: ${{ github.event.sender.html_url }} embed-author-icon-url: ${{ github.event.sender.avatar_url }} - embed-title: '⚠️ Publishing release from NPM' + embed-title: "⚠️ Publishing release from NPM${{ inputs.dry && ' (dry run)' }}" embed-description: | ```json ${{ toJson(inputs) }} @@ -80,44 +80,40 @@ jobs: working-directory: scripts/release - run: cp ./scripts/release/ci-npmrc ~/.npmrc - if: '${{ inputs.only_packages }}' - name: 'Prepare and publish ${{ inputs.only_packages }}' + name: 'Prepare ${{ inputs.only_packages }} from NPM' run: | - echo -e "===== Preparing release from NPM =====\n" scripts/release/prepare-release-from-npm.js \ --ci \ --skipTests \ --version=${{ inputs.version_to_promote }} \ --publishVersion=${{ inputs.version_to_publish }} \ --onlyPackages=${{ inputs.only_packages }} - - echo -e "\n\n===== Check prepared files =====\n" - ls -R build/node_modules - - echo -e "\n\n===== Publishing to NPM =====\n" - scripts/release/publish.js \ - --ci \ - --tags=${{ inputs.tags }} \ - --publishVersion=${{ inputs.version_to_publish }} \ - --onlyPackages=${{ inputs.only_packages }} \ - --dry=${{ inputs.dry }} - if: '${{ inputs.skip_packages }}' - name: 'Prepare and publish all packages EXCEPT ${{ inputs.skip_packages }}' + name: 'Prepare all packages EXCEPT ${{ inputs.skip_packages }} from NPM' run: | - echo -e "===== Preparing release from NPM =====\n" scripts/release/prepare-release-from-npm.js \ --ci \ --skipTests \ --version=${{ inputs.version_to_promote }} \ --publishVersion=${{ inputs.version_to_publish }} \ --skipPackages=${{ inputs.skip_packages }} - - echo -e "\n\n===== Check prepared files =====\n" - ls -R build/node_modules - - echo -e "\n\n===== Publishing to NPM =====\n" + - name: Check prepared files + run: ls -R build/node_modules + - if: '${{ inputs.only_packages }}' + name: 'Publish ${{ inputs.only_packages }}' + run: | + scripts/release/publish.js \ + --ci \ + --tags=${{ inputs.tags }} \ + --publishVersion=${{ inputs.version_to_publish }} \ + --onlyPackages=${{ inputs.only_packages }} ${{ (inputs.dry && '') || '\'}} + ${{ inputs.dry && '--dry'}} + - if: '${{ inputs.skip_packages }}' + name: 'Publish all packages EXCEPT ${{ inputs.skip_packages }}' + run: | scripts/release/publish.js \ --ci \ --tags=${{ inputs.tags }} \ --publishVersion=${{ inputs.version_to_publish }} \ - --skipPackages=${{ inputs.skip_packages }} \ - --dry=${{ inputs.dry }} + --skipPackages=${{ inputs.skip_packages }} ${{ (inputs.dry && '') || '\'}} + ${{ inputs.dry && '--dry'}} From 3607f4838a8f4a87160da36aa26bb1432d7a5f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= Date: Thu, 27 Feb 2025 16:45:18 -0500 Subject: [PATCH 12/18] Add Commit Scaffolding for Gestures (#32451) This adds a `ReactFiberApplyGesture` which is basically intended to be a fork of the phases in `ReactFiberCommitWork` except for the fake commit that `useSwipeTransition` does. So far none of the phases are actually implemented yet. This is just the scaffolding around them so I can fill them in later. The important bit is that we call `startViewTransition` (via the `startGestureTransition` Config) when a gesture starts. We add a paused animation to prevent the transition from committing (even if the ScrollTimeline goes to 100%). This also locks the documents so that we can't commit any other Transitions until it completes. When the gesture completes (scroll end) then we stop the gesture View Transition. If there's no new work scheduled we do that immediately but if there was any new work already scheduled, then we assume that this will potentially commit the new state. So we wait for that to finish. This lets us lock the animation in its state instead of snapping back and then applying the real update. Using this technique we can't actually run a View Transition from the current state to the actual committed state because it would snap back to the beginning and then run the View Transition from there. Therefore any new commit needs to skip View Transitions even if it should've technically animated to that state. We assume that the new state is the same as the optimistic state you already swiped to. An alternative to this technique could be to commit the optimistic state when we cancel and then apply any new updates o top of that. I might explore that in the future. Regardless it's important that the `action` associated with the swipe schedules some work before we cancel. Otherwise it risks reverting first. So I had to update this in the fixture. --- .../src/components/SwipeRecognizer.js | 10 +- packages/react-art/src/ReactFiberConfigART.js | 6 + .../src/client/ReactFiberConfigDOM.js | 74 ++++++- .../src/ReactFiberConfigNative.js | 15 ++ .../src/createReactNoop.js | 15 ++ .../src/ReactFiberApplyGesture.js | 42 ++++ .../src/ReactFiberConfigWithNoMutation.js | 3 + .../src/ReactFiberGestureScheduler.js | 80 ++++++-- .../react-reconciler/src/ReactFiberHooks.js | 2 +- .../react-reconciler/src/ReactFiberRoot.js | 3 +- .../src/ReactFiberWorkLoop.js | 180 +++++++++++++++--- .../src/ReactInternalTypes.js | 3 +- .../src/forks/ReactFiberConfig.custom.js | 3 + .../src/ReactFiberConfigTestHost.js | 15 ++ 14 files changed, 401 insertions(+), 50 deletions(-) create mode 100644 packages/react-reconciler/src/ReactFiberApplyGesture.js diff --git a/fixtures/view-transition/src/components/SwipeRecognizer.js b/fixtures/view-transition/src/components/SwipeRecognizer.js index f332796fc8cdf..8e913dfb4e55f 100644 --- a/fixtures/view-transition/src/components/SwipeRecognizer.js +++ b/fixtures/view-transition/src/components/SwipeRecognizer.js @@ -33,11 +33,6 @@ export default function SwipeRecognizer({ }); } function onScrollEnd() { - if (activeGesture.current !== null) { - const cancelGesture = activeGesture.current; - activeGesture.current = null; - cancelGesture(); - } let changed; const scrollElement = scrollRef.current; if (axis === 'x') { @@ -60,6 +55,11 @@ export default function SwipeRecognizer({ // Trigger side-effects startTransition(action); } + if (activeGesture.current !== null) { + const cancelGesture = activeGesture.current; + activeGesture.current = null; + cancelGesture(); + } } useEffect(() => { diff --git a/packages/react-art/src/ReactFiberConfigART.js b/packages/react-art/src/ReactFiberConfigART.js index a011bdf5c71c7..dc746b0e17d88 100644 --- a/packages/react-art/src/ReactFiberConfigART.js +++ b/packages/react-art/src/ReactFiberConfigART.js @@ -500,6 +500,12 @@ export function startViewTransition() { return false; } +export type RunningGestureTransition = null; + +export function startGestureTransition() {} + +export function stopGestureTransition(transition: RunningGestureTransition) {} + export type ViewTransitionInstance = null | {name: string, ...}; export function createViewTransitionInstance( diff --git a/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js b/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js index 52560d0b006b0..2b288efe46c3f 100644 --- a/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js +++ b/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js @@ -1394,7 +1394,10 @@ export function startViewTransition( transition.ready.then(spawnedWorkCallback, spawnedWorkCallback); transition.finished.then(() => { // $FlowFixMe[prop-missing] - ownerDocument.__reactViewTransition = null; + if (ownerDocument.__reactViewTransition === transition) { + // $FlowFixMe[prop-missing] + ownerDocument.__reactViewTransition = null; + } passiveCallback(); }); return true; @@ -1409,6 +1412,75 @@ export function startViewTransition( } } +export type RunningGestureTransition = { + skipTransition(): void, + ... +}; + +export function startGestureTransition( + rootContainer: Container, + transitionTypes: null | TransitionTypes, + mutationCallback: () => void, + animateCallback: () => void, +): null | RunningGestureTransition { + const ownerDocument: Document = + rootContainer.nodeType === DOCUMENT_NODE + ? (rootContainer: any) + : rootContainer.ownerDocument; + try { + // $FlowFixMe[prop-missing] + const transition = ownerDocument.startViewTransition({ + update: mutationCallback, + types: transitionTypes, + }); + // $FlowFixMe[prop-missing] + ownerDocument.__reactViewTransition = transition; + let blockingAnim = null; + const readyCallback = () => { + // View Transitions with ScrollTimeline has a quirk where they end if the + // ScrollTimeline ever reaches 100% but that doesn't mean we're done because + // you can swipe back again. We can prevent this by adding a paused Animation + // that never stops. This seems to keep all running Animations alive until + // we explicitly abort (or something forces the View Transition to cancel). + const documentElement: Element = (ownerDocument.documentElement: any); + blockingAnim = documentElement.animate([{}, {}], { + pseudoElement: '::view-transition', + duration: 1, + }); + blockingAnim.pause(); + animateCallback(); + }; + transition.ready.then(readyCallback, readyCallback); + transition.finished.then(() => { + if (blockingAnim !== null) { + // In Safari, we need to manually clear this or it'll block future transitions. + blockingAnim.cancel(); + } + // $FlowFixMe[prop-missing] + if (ownerDocument.__reactViewTransition === transition) { + // $FlowFixMe[prop-missing] + ownerDocument.__reactViewTransition = null; + } + }); + return transition; + } catch (x) { + // We use the error as feature detection. + // The only thing that should throw is if startViewTransition is missing + // or if it doesn't accept the object form. Other errors are async. + // I.e. it's before the View Transitions v2 spec. We only support View + // Transitions v2 otherwise we fallback to not animating to ensure that + // we're not animating with the wrong animation mapped. + // Run through the sequence to put state back into a consistent state. + mutationCallback(); + animateCallback(); + return null; + } +} + +export function stopGestureTransition(transition: RunningGestureTransition) { + transition.skipTransition(); +} + interface ViewTransitionPseudoElementType extends Animatable { _scope: HTMLElement; _selector: string; diff --git a/packages/react-native-renderer/src/ReactFiberConfigNative.js b/packages/react-native-renderer/src/ReactFiberConfigNative.js index 00385547f23e7..4a9064c82a83b 100644 --- a/packages/react-native-renderer/src/ReactFiberConfigNative.js +++ b/packages/react-native-renderer/src/ReactFiberConfigNative.js @@ -597,6 +597,21 @@ export function startViewTransition( return false; } +export type RunningGestureTransition = null; + +export function startGestureTransition( + rootContainer: Container, + transitionTypes: null | TransitionTypes, + mutationCallback: () => void, + animateCallback: () => void, +): RunningGestureTransition { + mutationCallback(); + animateCallback(); + return null; +} + +export function stopGestureTransition(transition: RunningGestureTransition) {} + export type ViewTransitionInstance = null | {name: string, ...}; export function createViewTransitionInstance( diff --git a/packages/react-noop-renderer/src/createReactNoop.js b/packages/react-noop-renderer/src/createReactNoop.js index 43853a864fb5e..e392ad7b0c04f 100644 --- a/packages/react-noop-renderer/src/createReactNoop.js +++ b/packages/react-noop-renderer/src/createReactNoop.js @@ -93,6 +93,8 @@ export type TransitionStatus = mixed; export type FormInstance = Instance; +export type RunningGestureTransition = null; + export type ViewTransitionInstance = null | {name: string, ...}; export type GestureTimeline = null; @@ -792,6 +794,19 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { return false; }, + startGestureTransition( + rootContainer: Container, + transitionTypes: null | TransitionTypes, + mutationCallback: () => void, + animateCallback: () => void, + ): RunningGestureTransition { + mutationCallback(); + animateCallback(); + return null; + }, + + stopGestureTransition(transition: RunningGestureTransition) {}, + createViewTransitionInstance(name: string): ViewTransitionInstance { return null; }, diff --git a/packages/react-reconciler/src/ReactFiberApplyGesture.js b/packages/react-reconciler/src/ReactFiberApplyGesture.js new file mode 100644 index 0000000000000..46af2ca4309fa --- /dev/null +++ b/packages/react-reconciler/src/ReactFiberApplyGesture.js @@ -0,0 +1,42 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +import type {Fiber, FiberRoot} from './ReactInternalTypes'; + +import { + cancelRootViewTransitionName, + restoreRootViewTransitionName, +} from './ReactFiberConfig'; + +// Clone View Transition boundaries that have any mutations or might have had their +// layout affected by child insertions. +export function insertDestinationClones( + root: FiberRoot, + finishedWork: Fiber, +): void { + // TODO +} + +// Revert insertions and apply view transition names to the "new" (current) state. +export function applyDepartureTransitions( + root: FiberRoot, + finishedWork: Fiber, +): void { + // TODO + cancelRootViewTransitionName(root.containerInfo); +} + +// Revert transition names and start/adjust animations on the started View Transition. +export function startGestureAnimations( + root: FiberRoot, + finishedWork: Fiber, +): void { + // TODO + restoreRootViewTransitionName(root.containerInfo); +} diff --git a/packages/react-reconciler/src/ReactFiberConfigWithNoMutation.js b/packages/react-reconciler/src/ReactFiberConfigWithNoMutation.js index da34b26084de5..430ad02abc1b1 100644 --- a/packages/react-reconciler/src/ReactFiberConfigWithNoMutation.js +++ b/packages/react-reconciler/src/ReactFiberConfigWithNoMutation.js @@ -46,6 +46,9 @@ export const wasInstanceInViewport = shim; export const hasInstanceChanged = shim; export const hasInstanceAffectedParent = shim; export const startViewTransition = shim; +export type RunningGestureTransition = null; +export const startGestureTransition = shim; +export const stopGestureTransition = shim; export type ViewTransitionInstance = null | {name: string, ...}; export const createViewTransitionInstance = shim; export type GestureTimeline = any; diff --git a/packages/react-reconciler/src/ReactFiberGestureScheduler.js b/packages/react-reconciler/src/ReactFiberGestureScheduler.js index fffb7d524d9e4..33d477f07daec 100644 --- a/packages/react-reconciler/src/ReactFiberGestureScheduler.js +++ b/packages/react-reconciler/src/ReactFiberGestureScheduler.js @@ -8,11 +8,21 @@ */ import type {FiberRoot} from './ReactInternalTypes'; -import type {GestureTimeline} from './ReactFiberConfig'; +import type { + GestureTimeline, + RunningGestureTransition, +} from './ReactFiberConfig'; -import {GestureLane} from './ReactFiberLane'; +import { + GestureLane, + includesBlockingLane, + includesTransitionLane, +} from './ReactFiberLane'; import {ensureRootIsScheduled} from './ReactFiberRootScheduler'; -import {subscribeToGestureDirection} from './ReactFiberConfig'; +import { + subscribeToGestureDirection, + stopGestureTransition, +} from './ReactFiberConfig'; // This type keeps track of any scheduled or active gestures. export type ScheduledGesture = { @@ -23,6 +33,7 @@ export type ScheduledGesture = { rangeCurrent: number, // The starting offset along the timeline. rangeNext: number, // The end along the timeline where the next state is reached. cancel: () => void, // Cancel the subscription to direction change. + running: null | RunningGestureTransition, // Used to cancel the running transition after we're done. prev: null | ScheduledGesture, // The previous scheduled gesture in the queue for this root. next: null | ScheduledGesture, // The next scheduled gesture in the queue for this root. }; @@ -35,7 +46,7 @@ export function scheduleGesture( rangeCurrent: number, rangeNext: number, ): ScheduledGesture { - let prev = root.gestures; + let prev = root.pendingGestures; while (prev !== null) { if (prev.provider === provider) { // Existing instance found. @@ -59,16 +70,16 @@ export function scheduleGesture( } if (gesture.direction !== direction) { gesture.direction = direction; - if (gesture.prev === null && root.gestures !== gesture) { + if (gesture.prev === null && root.pendingGestures !== gesture) { // This gesture is not in the schedule, meaning it was already rendered. // We need to rerender in the new direction. Insert it into the first slot // in case other gestures are queued after the on-going one. - const existing = root.gestures; + const existing = root.pendingGestures; gesture.next = existing; if (existing !== null) { existing.prev = gesture; } - root.gestures = gesture; + root.pendingGestures = gesture; // Schedule the lane on the root. The Fibers will already be marked as // long as the gesture is active on that Hook. root.pendingLanes |= GestureLane; @@ -86,11 +97,12 @@ export function scheduleGesture( rangeCurrent: rangeCurrent, rangeNext: rangeNext, cancel: cancel, + running: null, prev: prev, next: null, }; if (prev === null) { - root.gestures = gesture; + root.pendingGestures = gesture; } else { prev.next = gesture; } @@ -106,10 +118,35 @@ export function cancelScheduledGesture( if (gesture.count === 0) { const cancelDirectionSubscription = gesture.cancel; cancelDirectionSubscription(); - // Delete the scheduled gesture from the queue. + // Delete the scheduled gesture from the pending queue. deleteScheduledGesture(root, gesture); // TODO: If we're currently rendering this gesture, we need to restart the render // on a different gesture or cancel the render.. + // TODO: We might want to pause the View Transition at this point since you should + // no longer be able to update the position of anything but it might be better to + // just commit the gesture state. + const runningTransition = gesture.running; + if (runningTransition !== null) { + const pendingLanesExcludingGestureLane = root.pendingLanes & ~GestureLane; + if ( + includesBlockingLane(pendingLanesExcludingGestureLane) || + includesTransitionLane(pendingLanesExcludingGestureLane) + ) { + // If we have pending work we schedule the gesture to be stopped at the next commit. + // This ensures that we don't snap back to the previous state until we have + // had a chance to commit any resulting updates. + const existing = root.stoppingGestures; + if (existing !== null) { + gesture.next = existing; + existing.prev = gesture; + } + root.stoppingGestures = gesture; + } else { + gesture.running = null; + // If there's no work scheduled so we can stop the View Transition right away. + stopGestureTransition(runningTransition); + } + } } } @@ -118,15 +155,19 @@ export function deleteScheduledGesture( gesture: ScheduledGesture, ): void { if (gesture.prev === null) { - if (root.gestures === gesture) { - root.gestures = gesture.next; - if (root.gestures === null) { + if (root.pendingGestures === gesture) { + root.pendingGestures = gesture.next; + if (root.pendingGestures === null) { // Gestures don't clear their lanes while the gesture is still active but it // might not be scheduled to do any more renders and so we shouldn't schedule // any more gesture lane work until a new gesture is scheduled. root.pendingLanes &= ~GestureLane; } } + if (root.stoppingGestures === gesture) { + // This should not really happen the way we use it now but just in case we start. + root.stoppingGestures = gesture.next; + } } else { gesture.prev.next = gesture.next; if (gesture.next !== null) { @@ -136,3 +177,18 @@ export function deleteScheduledGesture( gesture.next = null; } } + +export function stopCompletedGestures(root: FiberRoot) { + let gesture = root.stoppingGestures; + root.stoppingGestures = null; + while (gesture !== null) { + if (gesture.running !== null) { + stopGestureTransition(gesture.running); + gesture.running = null; + } + const nextGesture = gesture.next; + gesture.next = null; + gesture.prev = null; + gesture = nextGesture; + } +} diff --git a/packages/react-reconciler/src/ReactFiberHooks.js b/packages/react-reconciler/src/ReactFiberHooks.js index 50424e9d7b4db..270cd87d4941c 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.js +++ b/packages/react-reconciler/src/ReactFiberHooks.js @@ -4126,7 +4126,7 @@ function updateSwipeTransition( ); } // We assume that the currently rendering gesture is the one first in the queue. - const rootRenderGesture = root.gestures; + const rootRenderGesture = root.pendingGestures; if (rootRenderGesture !== null) { let update = queue.pending; while (update !== null) { diff --git a/packages/react-reconciler/src/ReactFiberRoot.js b/packages/react-reconciler/src/ReactFiberRoot.js index 03ddde7a5ab5b..41401bac2bd8f 100644 --- a/packages/react-reconciler/src/ReactFiberRoot.js +++ b/packages/react-reconciler/src/ReactFiberRoot.js @@ -99,7 +99,8 @@ function FiberRootNode( this.formState = formState; if (enableSwipeTransition) { - this.gestures = null; + this.pendingGestures = null; + this.stoppingGestures = null; } this.incompleteTransitions = new Map(); diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index d5ef003e3dc61..bf611f73275a7 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -100,6 +100,7 @@ import { resolveUpdatePriority, trackSchedulerEvent, startViewTransition, + startGestureTransition, createViewTransitionInstance, } from './ReactFiberConfig'; @@ -228,6 +229,11 @@ import { accumulateSuspenseyCommit, } from './ReactFiberCommitWork'; import {shouldStartViewTransition} from './ReactFiberCommitViewTransitions'; +import { + insertDestinationClones, + applyDepartureTransitions, + startGestureAnimations, +} from './ReactFiberApplyGesture'; import {enqueueUpdate} from './ReactFiberClassUpdateQueue'; import {resetContextDependencies} from './ReactFiberNewContext'; import { @@ -341,7 +347,10 @@ import { import {getMaskedContext, getUnmaskedContext} from './ReactFiberContext'; import {peekEntangledActionLane} from './ReactFiberAsyncAction'; import {logUncaughtError} from './ReactFiberErrorLogger'; -import {deleteScheduledGesture} from './ReactFiberGestureScheduler'; +import { + deleteScheduledGesture, + stopCompletedGestures, +} from './ReactFiberGestureScheduler'; const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map; @@ -644,7 +653,9 @@ const PENDING_LAYOUT_PHASE = 2; const PENDING_AFTER_MUTATION_PHASE = 3; const PENDING_SPAWNED_WORK = 4; const PENDING_PASSIVE_PHASE = 5; -let pendingEffectsStatus: 0 | 1 | 2 | 3 | 4 | 5 = 0; +const PENDING_GESTURE_MUTATION_PHASE = 6; +const PENDING_GESTURE_ANIMATION_PHASE = 7; +let pendingEffectsStatus: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 = 0; let pendingEffectsRoot: FiberRoot = (null: any); let pendingFinishedWork: Fiber = (null: any); let pendingEffectsLanes: Lanes = NoLanes; @@ -1424,11 +1435,12 @@ function commitRootWhenReady( const subtreeFlags = finishedWork.subtreeFlags; const isViewTransitionEligible = enableViewTransition && includesOnlyViewTransitionEligibleLanes(lanes); // TODO: Use a subtreeFlag to optimize. + const isGestureTransition = enableSwipeTransition && isGestureRender(lanes); const maySuspendCommit = subtreeFlags & ShouldSuspendCommit || (subtreeFlags & BothVisibilityAndMaySuspendCommit) === BothVisibilityAndMaySuspendCommit; - if (isViewTransitionEligible || maySuspendCommit) { + if (isViewTransitionEligible || maySuspendCommit || isGestureTransition) { // Before committing, ask the renderer whether the host tree is ready. // If it's not, we'll wait until it notifies us. startSuspendingCommit(); @@ -1439,8 +1451,12 @@ function commitRootWhenReady( // This will also track any newly added or appearing ViewTransition // components for the purposes of forming pairs. accumulateSuspenseyCommit(finishedWork); - if (isViewTransitionEligible) { - suspendOnActiveViewTransition(root.containerInfo); + if (isViewTransitionEligible || isGestureTransition) { + // If we're stopping gestures we don't have to wait for any pending + // view transition. We'll stop it when we commit. + if (!enableSwipeTransition || root.stoppingGestures === null) { + suspendOnActiveViewTransition(root.containerInfo); + } } // At the end, ask the renderer if it's ready to commit, or if we should // suspend. If it's not ready, it will return a callback to subscribe to @@ -3263,6 +3279,12 @@ function commitRoot( if (enableSchedulingProfiler) { markCommitStopped(); } + if (enableSwipeTransition) { + // Stop any gestures that were completed and is now being reverted. + if (root.stoppingGestures !== null) { + stopCompletedGestures(root); + } + } return; } else { if (__DEV__) { @@ -3291,7 +3313,7 @@ function commitRoot( const concurrentlyUpdatedLanes = getConcurrentlyUpdatedLanes(); remainingLanes = mergeLanes(remainingLanes, concurrentlyUpdatedLanes); - if (enableSwipeTransition && root.gestures === null) { + if (enableSwipeTransition && root.pendingGestures === null) { // Gestures don't clear their lanes while the gesture is still active but it // might not be scheduled to do any more renders and so we shouldn't schedule // any more gesture lane work until a new gesture is scheduled. @@ -3321,21 +3343,6 @@ function commitRoot( // times out. } - if (enableSwipeTransition && isGestureRender(lanes)) { - // This is a special kind of render that doesn't commit regular effects. - commitGestureOnRoot( - root, - finishedWork, - recoverableErrors, - enableProfilerTimer - ? suspendedCommitReason === IMMEDIATE_COMMIT - ? completedRenderEndTime - : commitStartTime - : 0, - ); - return; - } - // workInProgressX might be overwritten, so we want // to store it in pendingPassiveX until they get processed // We need to pass this through as an argument to commitRoot @@ -3354,6 +3361,21 @@ function commitRoot( pendingSuspendedCommitReason = suspendedCommitReason; } + if (enableSwipeTransition && isGestureRender(lanes)) { + // This is a special kind of render that doesn't commit regular effects. + commitGestureOnRoot( + root, + finishedWork, + recoverableErrors, + enableProfilerTimer + ? suspendedCommitReason === IMMEDIATE_COMMIT + ? completedRenderEndTime + : commitStartTime + : 0, + ); + return; + } + // If there are pending passive effects, schedule a callback to process them. // Do this as early as possible, so it is queued before anything else that // might get scheduled in the commit phase. (See #16714.) @@ -3461,10 +3483,23 @@ function commitRoot( ReactSharedInternals.T = prevTransition; } } + + let willStartViewTransition = shouldStartViewTransition; + if (enableSwipeTransition) { + // Stop any gestures that were completed and is now being committed. + if (root.stoppingGestures !== null) { + stopCompletedGestures(root); + // If we are in the process of stopping some gesture we shouldn't start + // a View Transition because that would start from the previous state to + // the next state. + willStartViewTransition = false; + } + } + pendingEffectsStatus = PENDING_MUTATION_PHASE; const startedViewTransition = enableViewTransition && - shouldStartViewTransition && + willStartViewTransition && startViewTransition( root.containerInfo, pendingTransitionTypes, @@ -3633,6 +3668,7 @@ function flushSpawnedWork(): void { } else { pendingEffectsStatus = NO_PENDING_EFFECTS; pendingEffectsRoot = (null: any); // Clear for GC purposes. + pendingFinishedWork = (null: any); // Clear for GC purposes. // There were no passive effects, so we can immediately release the cache // pool for this render. releaseRootPooledCache(root, root.pendingLanes); @@ -3830,20 +3866,103 @@ function flushSpawnedWork(): void { function commitGestureOnRoot( root: FiberRoot, - finishedWork: null | Fiber, + finishedWork: Fiber, recoverableErrors: null | Array>, renderEndTime: number, // Profiling-only ): void { // We assume that the gesture we just rendered was the first one in the queue. - const finishedGesture = root.gestures; + const finishedGesture = root.pendingGestures; if (finishedGesture === null) { - throw new Error( - 'Finished rendering the gesture lane but there were no pending gestures. ' + - 'React should not have started a render in this case. This is a bug in React.', - ); + // We must have already cancelled this gesture before we had a chance to + // render it. Let's schedule work on the next set of lanes. + ensureRootIsScheduled(root); + return; } deleteScheduledGesture(root, finishedGesture); - // TODO: Run the gesture + + const prevTransition = ReactSharedInternals.T; + ReactSharedInternals.T = null; + const previousPriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority(DiscreteEventPriority); + const prevExecutionContext = executionContext; + executionContext |= CommitContext; + try { + insertDestinationClones(root, finishedWork); + } finally { + // Reset the priority to the previous non-sync value. + executionContext = prevExecutionContext; + setCurrentUpdatePriority(previousPriority); + ReactSharedInternals.T = prevTransition; + } + // TODO: Collect transition types. + pendingTransitionTypes = null; + pendingEffectsStatus = PENDING_GESTURE_MUTATION_PHASE; + + finishedGesture.running = startGestureTransition( + root.containerInfo, + pendingTransitionTypes, + flushGestureMutations, + flushGestureAnimations, + ); +} + +function flushGestureMutations(): void { + if (pendingEffectsStatus !== PENDING_GESTURE_MUTATION_PHASE) { + return; + } + pendingEffectsStatus = NO_PENDING_EFFECTS; + const root = pendingEffectsRoot; + const finishedWork = pendingFinishedWork; + + const prevTransition = ReactSharedInternals.T; + ReactSharedInternals.T = null; + const previousPriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority(DiscreteEventPriority); + const prevExecutionContext = executionContext; + executionContext |= CommitContext; + try { + applyDepartureTransitions(root, finishedWork); + } finally { + // Reset the priority to the previous non-sync value. + executionContext = prevExecutionContext; + setCurrentUpdatePriority(previousPriority); + ReactSharedInternals.T = prevTransition; + } + + pendingEffectsStatus = PENDING_GESTURE_ANIMATION_PHASE; +} + +function flushGestureAnimations(): void { + // If we get canceled before we start we might not have applied + // mutations yet. We need to apply them first. + flushGestureMutations(); + if (pendingEffectsStatus !== PENDING_GESTURE_ANIMATION_PHASE) { + return; + } + pendingEffectsStatus = NO_PENDING_EFFECTS; + const root = pendingEffectsRoot; + const finishedWork = pendingFinishedWork; + pendingEffectsRoot = (null: any); // Clear for GC purposes. + pendingFinishedWork = (null: any); // Clear for GC purposes. + pendingEffectsLanes = NoLanes; + + const prevTransition = ReactSharedInternals.T; + ReactSharedInternals.T = null; + const previousPriority = getCurrentUpdatePriority(); + setCurrentUpdatePriority(DiscreteEventPriority); + const prevExecutionContext = executionContext; + executionContext |= CommitContext; + try { + startGestureAnimations(root, finishedWork); + } finally { + // Reset the priority to the previous non-sync value. + executionContext = prevExecutionContext; + setCurrentUpdatePriority(previousPriority); + ReactSharedInternals.T = prevTransition; + } + + // Now that we've rendered this lane. Start working on the next lane. + ensureRootIsScheduled(root); } function makeErrorInfo(componentStack: ?string) { @@ -3879,6 +3998,8 @@ function releaseRootPooledCache(root: FiberRoot, remainingLanes: Lanes) { export function flushPendingEffects(wasDelayedCommit?: boolean): boolean { // Returns whether passive effects were flushed. + flushGestureMutations(); + flushGestureAnimations(); flushMutationEffects(); flushLayoutEffects(); // Skip flushAfterMutation if we're forcing this early. @@ -3932,6 +4053,7 @@ function flushPassiveEffectsImpl(wasDelayedCommit: void | boolean) { const lanes = pendingEffectsLanes; pendingEffectsStatus = NO_PENDING_EFFECTS; pendingEffectsRoot = (null: any); // Clear for GC purposes. + pendingFinishedWork = (null: any); // Clear for GC purposes. // TODO: This is sometimes out of sync with pendingEffectsRoot. // Figure out why and fix it. It's not causing any known issues (probably // because it's only used for profiling), but it's a refactor hazard. diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index 3479eba1b9dd3..be5e9a5c0da69 100644 --- a/packages/react-reconciler/src/ReactInternalTypes.js +++ b/packages/react-reconciler/src/ReactInternalTypes.js @@ -284,7 +284,8 @@ type BaseFiberRootProperties = { formState: ReactFormState | null, // enableSwipeTransition only - gestures: null | ScheduledGesture, + pendingGestures: null | ScheduledGesture, + stoppingGestures: null | ScheduledGesture, }; // The following attributes are only used by DevTools and are only present in DEV builds. diff --git a/packages/react-reconciler/src/forks/ReactFiberConfig.custom.js b/packages/react-reconciler/src/forks/ReactFiberConfig.custom.js index 6b2781c0ab2a5..9569b4a896cee 100644 --- a/packages/react-reconciler/src/forks/ReactFiberConfig.custom.js +++ b/packages/react-reconciler/src/forks/ReactFiberConfig.custom.js @@ -40,6 +40,7 @@ export opaque type NoTimeout = mixed; export opaque type RendererInspectionConfig = mixed; export opaque type TransitionStatus = mixed; export opaque type FormInstance = mixed; +export type RunningGestureTransition = mixed; export type ViewTransitionInstance = null | {name: string, ...}; export opaque type InstanceMeasurement = mixed; export type EventResponder = any; @@ -145,6 +146,8 @@ export const wasInstanceInViewport = $$$config.wasInstanceInViewport; export const hasInstanceChanged = $$$config.hasInstanceChanged; export const hasInstanceAffectedParent = $$$config.hasInstanceAffectedParent; export const startViewTransition = $$$config.startViewTransition; +export const startGestureTransition = $$$config.startGestureTransition; +export const stopGestureTransition = $$$config.stopGestureTransition; export const getCurrentGestureOffset = $$$config.getCurrentGestureOffset; export const subscribeToGestureDirection = $$$config.subscribeToGestureDirection; diff --git a/packages/react-test-renderer/src/ReactFiberConfigTestHost.js b/packages/react-test-renderer/src/ReactFiberConfigTestHost.js index 8f4f81cabb9ce..48939e9ff45ad 100644 --- a/packages/react-test-renderer/src/ReactFiberConfigTestHost.js +++ b/packages/react-test-renderer/src/ReactFiberConfigTestHost.js @@ -375,6 +375,21 @@ export function startViewTransition( return false; } +export type RunningGestureTransition = null; + +export function startGestureTransition( + rootContainer: Container, + transitionTypes: null | TransitionTypes, + mutationCallback: () => void, + animateCallback: () => void, +): RunningGestureTransition { + mutationCallback(); + animateCallback(); + return null; +} + +export function stopGestureTransition(transition: RunningGestureTransition) {} + export type ViewTransitionInstance = null | {name: string, ...}; export function createViewTransitionInstance( From 7e2ea902f839264fd327b0df5fae4f6ad8359952 Mon Sep 17 00:00:00 2001 From: lauren Date: Fri, 28 Feb 2025 10:58:28 -0500 Subject: [PATCH 13/18] [ci] Fix discord notification title (#32491) fun times --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32491). * #32492 * __->__ #32491 --- .github/workflows/runtime_releases_from_npm_manual.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/runtime_releases_from_npm_manual.yml b/.github/workflows/runtime_releases_from_npm_manual.yml index 3c8cec7f7ac1b..2e1047b55df50 100644 --- a/.github/workflows/runtime_releases_from_npm_manual.yml +++ b/.github/workflows/runtime_releases_from_npm_manual.yml @@ -50,7 +50,7 @@ jobs: embed-author-name: ${{ github.event.sender.login }} embed-author-url: ${{ github.event.sender.html_url }} embed-author-icon-url: ${{ github.event.sender.avatar_url }} - embed-title: "⚠️ Publishing release from NPM${{ inputs.dry && ' (dry run)' }}" + embed-title: "⚠️ Publishing release from NPM${{ (inputs.dry && ' (dry run)') || '' }}" embed-description: | ```json ${{ toJson(inputs) }} From 56c7d1070aabe42b955ea0006477ea1ca02dd0c5 Mon Sep 17 00:00:00 2001 From: lauren Date: Fri, 28 Feb 2025 10:58:39 -0500 Subject: [PATCH 14/18] [ci] Upload release for easier debugging (#32492) Uploads the releases that were published in case to help with debugging or verifying a dry run. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32492). * __->__ #32492 * #32491 --- .github/workflows/runtime_releases_from_npm_manual.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/runtime_releases_from_npm_manual.yml b/.github/workflows/runtime_releases_from_npm_manual.yml index 2e1047b55df50..c0b3867e03da0 100644 --- a/.github/workflows/runtime_releases_from_npm_manual.yml +++ b/.github/workflows/runtime_releases_from_npm_manual.yml @@ -117,3 +117,9 @@ jobs: --publishVersion=${{ inputs.version_to_publish }} \ --skipPackages=${{ inputs.skip_packages }} ${{ (inputs.dry && '') || '\'}} ${{ inputs.dry && '--dry'}} + - name: Archive released package for debugging + uses: actions/upload-artifact@v4 + with: + name: build + path: | + ./build/node_modules From 11ca4f6b6934292168f49cc78d3b2360a602febe Mon Sep 17 00:00:00 2001 From: michael faith Date: Fri, 28 Feb 2025 10:07:13 -0600 Subject: [PATCH 15/18] feat(eslint-plugin-react-hooks): update `engines` declaration (#32458) In preparation for the merging of the compiler plugin into this one (#32416), this change proactively updates the plugin's `engines` declaration to require Node versions greater than or equal to 18 BREAKING CHANGE Co-authored-by: lauren --- packages/eslint-plugin-react-hooks/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin-react-hooks/package.json b/packages/eslint-plugin-react-hooks/package.json index d3717b9dee61c..48cb7ae452a8d 100644 --- a/packages/eslint-plugin-react-hooks/package.json +++ b/packages/eslint-plugin-react-hooks/package.json @@ -31,7 +31,7 @@ "main": "./index.js", "types": "./index.d.ts", "engines": { - "node": ">=10" + "node": ">=18" }, "homepage": "https://react.dev/", "peerDependencies": { From d55cc79bcf5cd3bd4cb406381b067d72842f368e Mon Sep 17 00:00:00 2001 From: michael faith Date: Fri, 28 Feb 2025 10:12:10 -0600 Subject: [PATCH 16/18] refactor(eslint-plugin-react-hooks): move rules to `rules` folder (#32411) Since the compiler plugin is going to be merged into the hooks plugin, and ultimately decomposed into several more rules, it would be good to start creating a more traditional folder structure for the plugin. This change just moves the rules into a `rules` folder. Co-authored-by: lauren --- packages/eslint-plugin-react-hooks/README.md | 4 ++-- packages/eslint-plugin-react-hooks/src/index.ts | 4 ++-- .../src/{ => rules}/ExhaustiveDeps.ts | 0 .../eslint-plugin-react-hooks/src/{ => rules}/RulesOfHooks.ts | 0 4 files changed, 4 insertions(+), 4 deletions(-) rename packages/eslint-plugin-react-hooks/src/{ => rules}/ExhaustiveDeps.ts (100%) rename packages/eslint-plugin-react-hooks/src/{ => rules}/RulesOfHooks.ts (100%) diff --git a/packages/eslint-plugin-react-hooks/README.md b/packages/eslint-plugin-react-hooks/README.md index 36f63722f7268..cf54caec986f5 100644 --- a/packages/eslint-plugin-react-hooks/README.md +++ b/packages/eslint-plugin-react-hooks/README.md @@ -36,7 +36,7 @@ If you are still using ESLint below 9.0.0, please continue to use `recommended-l For [ESLint 9.0.0 and above](https://eslint.org/blog/2024/04/eslint-v9.0.0-released/) users, add the `recommended-latest` config. ```js -import reactHooks from 'eslint-plugin-react-hooks'; +import * as reactHooks from 'eslint-plugin-react-hooks'; export default [ // ... @@ -67,7 +67,7 @@ If you want more fine-grained configuration, you can instead add a snippet like #### Flat Config (eslint.config.js) ```js -import reactHooks from 'eslint-plugin-react-hooks'; +import * as reactHooks from 'eslint-plugin-react-hooks'; export default [ { diff --git a/packages/eslint-plugin-react-hooks/src/index.ts b/packages/eslint-plugin-react-hooks/src/index.ts index 42b55320fcd89..5ddbbcbb806fb 100644 --- a/packages/eslint-plugin-react-hooks/src/index.ts +++ b/packages/eslint-plugin-react-hooks/src/index.ts @@ -4,8 +4,8 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -import RulesOfHooks from './RulesOfHooks'; -import ExhaustiveDeps from './ExhaustiveDeps'; +import RulesOfHooks from './rules/RulesOfHooks'; +import ExhaustiveDeps from './rules/ExhaustiveDeps'; import type {ESLint, Linter, Rule} from 'eslint'; // All rules diff --git a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.ts b/packages/eslint-plugin-react-hooks/src/rules/ExhaustiveDeps.ts similarity index 100% rename from packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.ts rename to packages/eslint-plugin-react-hooks/src/rules/ExhaustiveDeps.ts diff --git a/packages/eslint-plugin-react-hooks/src/RulesOfHooks.ts b/packages/eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts similarity index 100% rename from packages/eslint-plugin-react-hooks/src/RulesOfHooks.ts rename to packages/eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts From ca12911d1fbe755b9b2b7d1bf548589317311a82 Mon Sep 17 00:00:00 2001 From: michael faith Date: Fri, 28 Feb 2025 10:22:08 -0600 Subject: [PATCH 17/18] feat(eslint-plugin-react-hooks): make flat config the `recommended` config (#32457) This change swaps which config `recommended` is aliasing. In 5.2.0, the new flat config was introduced as `recommended-latest`, while `recommended` still pointed at the legacy rc-based config, with a note that in the next major version `recommended` would be updated to point at `recommend-latest`. This change makes that swap, and make the default `recommended` experience the flat config. To continue using the legacy rc recommended config, please make the following change in your config ```diff - extends: ['plugin:react-hooks/recommended'] + extends: ['plugin:react-hooks/recommended-legacy'] ``` This change also deprecates `recommended-latest` in favor of `recommended`. `recommended-latest` will be removed in a future major version. The README has been updated to reflect the new usage, and to put the flat config sections before the legacy config sections. I also took the opportunity to change the v9 fixture to use a typescript config, serving as a demonstration for usage as well as a way to validate the types are correct. BREAKING CHANGE --------- Co-authored-by: lauren --- .../{eslint.config.mjs => eslint.config.ts} | 5 +- fixtures/eslint-v9/package.json | 5 +- fixtures/eslint-v9/tsconfig.json | 2 + fixtures/eslint-v9/yarn.lock | 76 +++++++++---------- packages/eslint-plugin-react-hooks/README.md | 59 +++++++------- .../eslint-plugin-react-hooks/src/index.ts | 35 +++++---- 6 files changed, 91 insertions(+), 91 deletions(-) rename fixtures/eslint-v9/{eslint.config.mjs => eslint.config.ts} (76%) create mode 100644 fixtures/eslint-v9/tsconfig.json diff --git a/fixtures/eslint-v9/eslint.config.mjs b/fixtures/eslint-v9/eslint.config.ts similarity index 76% rename from fixtures/eslint-v9/eslint.config.mjs rename to fixtures/eslint-v9/eslint.config.ts index ffc8375265c2b..62ef68671639e 100644 --- a/fixtures/eslint-v9/eslint.config.mjs +++ b/fixtures/eslint-v9/eslint.config.ts @@ -1,3 +1,4 @@ +import type {Linter} from 'eslint'; import * as reactHooks from 'eslint-plugin-react-hooks'; export default [ @@ -12,10 +13,10 @@ export default [ }, }, }, - reactHooks.configs['recommended-latest'], + reactHooks.configs['recommended'], { rules: { 'react-hooks/exhaustive-deps': 'error', }, }, -]; +] satisfies Linter.Config[]; diff --git a/fixtures/eslint-v9/package.json b/fixtures/eslint-v9/package.json index 58d0a94c0c58c..80827a0d1730a 100644 --- a/fixtures/eslint-v9/package.json +++ b/fixtures/eslint-v9/package.json @@ -2,8 +2,9 @@ "private": true, "name": "eslint-v9", "dependencies": { - "eslint": "^9", - "eslint-plugin-react-hooks": "link:../../build/oss-stable/eslint-plugin-react-hooks" + "eslint": "^9.18.0", + "eslint-plugin-react-hooks": "link:../../build/oss-stable/eslint-plugin-react-hooks", + "jiti": "^2.4.2" }, "scripts": { "build": "node build.mjs && yarn", diff --git a/fixtures/eslint-v9/tsconfig.json b/fixtures/eslint-v9/tsconfig.json new file mode 100644 index 0000000000000..2c63c0851048d --- /dev/null +++ b/fixtures/eslint-v9/tsconfig.json @@ -0,0 +1,2 @@ +{ +} diff --git a/fixtures/eslint-v9/yarn.lock b/fixtures/eslint-v9/yarn.lock index 1583b73f14e21..a473b3a4ce165 100644 --- a/fixtures/eslint-v9/yarn.lock +++ b/fixtures/eslint-v9/yarn.lock @@ -14,7 +14,7 @@ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== -"@eslint/config-array@^0.19.0": +"@eslint/config-array@^0.19.2": version "0.19.2" resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.2.tgz#3060b809e111abfc97adb0bb1172778b90cb46aa" integrity sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w== @@ -23,24 +23,17 @@ debug "^4.3.1" minimatch "^3.1.2" -"@eslint/core@^0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.10.0.tgz#23727063c21b335f752dbb3a16450f6f9cbc9091" - integrity sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw== +"@eslint/core@^0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.12.0.tgz#5f960c3d57728be9f6c65bd84aa6aa613078798e" + integrity sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg== dependencies: "@types/json-schema" "^7.0.15" -"@eslint/core@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.11.0.tgz#7a9226e850922e42cbd2ba71361eacbe74352a12" - integrity sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA== - dependencies: - "@types/json-schema" "^7.0.15" - -"@eslint/eslintrc@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c" - integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w== +"@eslint/eslintrc@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.0.tgz#96a558f45842989cca7ea1ecd785ad5491193846" + integrity sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -52,22 +45,22 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.20.0": - version "9.20.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.20.0.tgz#7421bcbe74889fcd65d1be59f00130c289856eb4" - integrity sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ== +"@eslint/js@9.21.0": + version "9.21.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.21.0.tgz#4303ef4e07226d87c395b8fad5278763e9c15c08" + integrity sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw== "@eslint/object-schema@^2.1.6": version "2.1.6" resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== -"@eslint/plugin-kit@^0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz#ee07372035539e7847ef834e3f5e7b79f09e3a81" - integrity sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A== +"@eslint/plugin-kit@^0.2.7": + version "0.2.7" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz#9901d52c136fb8f375906a73dcc382646c3b6a27" + integrity sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g== dependencies: - "@eslint/core" "^0.10.0" + "@eslint/core" "^0.12.0" levn "^0.4.1" "@humanfs/core@^0.19.1": @@ -93,10 +86,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== -"@humanwhocodes/retry@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b" - integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== +"@humanwhocodes/retry@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.2.tgz#1860473de7dfa1546767448f333db80cb0ff2161" + integrity sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ== "@types/estree@^1.0.6": version "1.0.6" @@ -231,21 +224,21 @@ eslint-visitor-keys@^4.2.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== -eslint@^9: - version "9.20.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.20.1.tgz#923924c078f5226832449bac86662dd7e53c91d6" - integrity sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g== +eslint@^9.18.0: + version "9.21.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.21.0.tgz#b1c9c16f5153ff219791f627b94ab8f11f811591" + integrity sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.12.1" - "@eslint/config-array" "^0.19.0" - "@eslint/core" "^0.11.0" - "@eslint/eslintrc" "^3.2.0" - "@eslint/js" "9.20.0" - "@eslint/plugin-kit" "^0.2.5" + "@eslint/config-array" "^0.19.2" + "@eslint/core" "^0.12.0" + "@eslint/eslintrc" "^3.3.0" + "@eslint/js" "9.21.0" + "@eslint/plugin-kit" "^0.2.7" "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" - "@humanwhocodes/retry" "^0.4.1" + "@humanwhocodes/retry" "^0.4.2" "@types/estree" "^1.0.6" "@types/json-schema" "^7.0.15" ajv "^6.12.4" @@ -399,6 +392,11 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +jiti@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.2.tgz#d19b7732ebb6116b06e2038da74a55366faef560" + integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A== + js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" diff --git a/packages/eslint-plugin-react-hooks/README.md b/packages/eslint-plugin-react-hooks/README.md index cf54caec986f5..e4223c18b20e0 100644 --- a/packages/eslint-plugin-react-hooks/README.md +++ b/packages/eslint-plugin-react-hooks/README.md @@ -18,9 +18,22 @@ npm install eslint-plugin-react-hooks --save-dev yarn add eslint-plugin-react-hooks --dev ``` +### Flat Config (eslint.config.js|ts) + +For [ESLint 9.0.0 and above](https://eslint.org/blog/2024/04/eslint-v9.0.0-released/), add the `recommended` config. + +```js +import * as reactHooks from 'eslint-plugin-react-hooks'; + +export default [ + // ... + reactHooks.configs['recommended'], +]; +``` + ### Legacy Config (.eslintrc) -If you are still using ESLint below 9.0.0, please continue to use `recommended-legacy`. To avoid breaking changes, we still support `recommended` as well, but note that this will be changed to alias the flat recommended config in v6. +If you are still using ESLint below 9.0.0, you can use `recommended-legacy` for accessing the recommended config. ```js { @@ -31,25 +44,29 @@ If you are still using ESLint below 9.0.0, please continue to use `recommended-l } ``` -### Flat Config (eslint.config.js) +### Custom Configuration -For [ESLint 9.0.0 and above](https://eslint.org/blog/2024/04/eslint-v9.0.0-released/) users, add the `recommended-latest` config. +If you want more fine-grained configuration, you can instead add a snippet like this to your ESLint configuration file: + +#### Flat Config (eslint.config.js|ts) ```js import * as reactHooks from 'eslint-plugin-react-hooks'; export default [ - // ... - reactHooks.configs['recommended-latest'], + { + files: ['**/*.{js,jsx}'], + plugins: { 'react-hooks': reactHooks }, + // ... + rules: { + 'react-hooks/rules-of-hooks': 'error', + 'react-hooks/exhaustive-deps': 'warn', + } + }, ]; ``` -### Custom Configuration - -If you want more fine-grained configuration, you can instead add a snippet like this to your ESLint configuration file: - #### Legacy Config (.eslintrc) - ```js { "plugins": [ @@ -64,24 +81,6 @@ If you want more fine-grained configuration, you can instead add a snippet like } ``` -#### Flat Config (eslint.config.js) - -```js -import * as reactHooks from 'eslint-plugin-react-hooks'; - -export default [ - { - files: ['**/*.{js,jsx}'], - plugins: { 'react-hooks': reactHooks }, - // ... - rules: { - 'react-hooks/rules-of-hooks': 'error', - 'react-hooks/exhaustive-deps': 'warn', - } - }, -]; -``` - ## Advanced Configuration `exhaustive-deps` can be configured to validate dependencies of custom Hooks with the `additionalHooks` option. @@ -89,10 +88,10 @@ This option accepts a regex to match the names of custom Hooks that have depende ```js { - "rules": { + rules: { // ... "react-hooks/exhaustive-deps": ["warn", { - "additionalHooks": "(useMyCustomHook|useMyOtherCustomHook)" + additionalHooks: "(useMyCustomHook|useMyOtherCustomHook)" }] } } diff --git a/packages/eslint-plugin-react-hooks/src/index.ts b/packages/eslint-plugin-react-hooks/src/index.ts index 5ddbbcbb806fb..61ac62912ddc2 100644 --- a/packages/eslint-plugin-react-hooks/src/index.ts +++ b/packages/eslint-plugin-react-hooks/src/index.ts @@ -20,11 +20,16 @@ const configRules = { 'react-hooks/exhaustive-deps': 'warn', } satisfies Linter.RulesRecord; -// Legacy config -const legacyRecommendedConfig = { - plugins: ['react-hooks'], +// Flat config +const recommendedConfig = { + name: 'react-hooks/recommended', + plugins: { + get 'react-hooks'(): ESLint.Plugin { + return plugin; + }, + }, rules: configRules, -} satisfies Linter.LegacyConfig; +}; // Plugin object const plugin = { @@ -34,24 +39,18 @@ const plugin = { rules, configs: { /** Legacy recommended config, to be used with rc-based configurations */ - 'recommended-legacy': legacyRecommendedConfig, + 'recommended-legacy': { + plugins: ['react-hooks'], + rules: configRules, + }, /** - * 'recommended' is currently aliased to the legacy / rc recommended config) to maintain backwards compatibility. - * This is deprecated and in v6, it will switch to alias the flat recommended config. + * Recommended config, to be used with flat configs. */ - recommended: legacyRecommendedConfig, + recommended: recommendedConfig, - /** Latest recommended config, to be used with flat configurations */ - 'recommended-latest': { - name: 'react-hooks/recommended', - plugins: { - get 'react-hooks'(): ESLint.Plugin { - return plugin; - }, - }, - rules: configRules, - }, + /** @deprecated please use `recommended`; will be removed in v7 */ + 'recommended-latest': recommendedConfig, }, } satisfies ESLint.Plugin; From eda36a1c75ff8ac09fb127f6e04d4af16e49f50f Mon Sep 17 00:00:00 2001 From: lauren Date: Fri, 28 Feb 2025 13:06:40 -0500 Subject: [PATCH 18/18] [ci] Don't erroneously mark failures as successes (#32493) Randomly noticed this when I looked at a recent [DevTools regression test run](https://github.com/facebook/react/actions/runs/13578385011). I don't recall why we added `continue-on-error` previously, but I believe it was to keep all jobs in the matrix running even if one were to fail, in order to fully identify any failures from code changes like build or test failures. There is now a `fail-fast` option which does this. [`continue-on-error`](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idcontinue-on-error) now means: > Prevents a workflow run from failing when a job fails. Set to true to allow a workflow run to pass when this job fails. so it's not correct to use it. --- .github/workflows/compiler_typescript.yml | 2 +- .github/workflows/devtools_regression_tests.yml | 4 ++-- .github/workflows/runtime_build_and_test.yml | 8 +++++--- .github/workflows/runtime_eslint_plugin_e2e.yml | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/compiler_typescript.yml b/.github/workflows/compiler_typescript.yml index 6d9fa973350af..65fb789eccf17 100644 --- a/.github/workflows/compiler_typescript.yml +++ b/.github/workflows/compiler_typescript.yml @@ -75,8 +75,8 @@ jobs: name: Test ${{ matrix.workspace_name }} needs: discover_yarn_workspaces runs-on: ubuntu-latest - continue-on-error: true strategy: + fail-fast: false matrix: workspace_name: ${{ fromJSON(needs.discover_yarn_workspaces.outputs.matrix) }} steps: diff --git a/.github/workflows/devtools_regression_tests.yml b/.github/workflows/devtools_regression_tests.yml index 64d6707aa3688..4babfeefb0f2c 100644 --- a/.github/workflows/devtools_regression_tests.yml +++ b/.github/workflows/devtools_regression_tests.yml @@ -100,6 +100,7 @@ jobs: needs: build_devtools_and_process_artifacts runs-on: ubuntu-latest strategy: + fail-fast: false matrix: version: - "16.0" @@ -108,7 +109,6 @@ jobs: - "17.0" - "18.0" - "18.2" # compiler polyfill - continue-on-error: true steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -135,6 +135,7 @@ jobs: needs: build_devtools_and_process_artifacts runs-on: ubuntu-latest strategy: + fail-fast: false matrix: version: - "16.0" @@ -142,7 +143,6 @@ jobs: - "16.8" # hooks - "17.0" - "18.0" - continue-on-error: true steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 diff --git a/.github/workflows/runtime_build_and_test.yml b/.github/workflows/runtime_build_and_test.yml index 12e341a86fd96..d53e352fbb266 100644 --- a/.github/workflows/runtime_build_and_test.yml +++ b/.github/workflows/runtime_build_and_test.yml @@ -38,8 +38,8 @@ jobs: name: Flow check ${{ matrix.flow_inline_config_shortname }} needs: discover_flow_inline_configs runs-on: ubuntu-latest - continue-on-error: true strategy: + fail-fast: false matrix: flow_inline_config_shortname: ${{ fromJSON(needs.discover_flow_inline_configs.outputs.matrix) }} steps: @@ -117,6 +117,7 @@ jobs: name: yarn test ${{ matrix.params }} (Shard ${{ matrix.shard }}) runs-on: ubuntu-latest strategy: + fail-fast: false matrix: params: - "-r=stable --env=development" @@ -144,7 +145,6 @@ jobs: - 3/5 - 4/5 - 5/5 - continue-on-error: true steps: - uses: actions/checkout@v4 with: @@ -170,6 +170,7 @@ jobs: name: yarn build and lint runs-on: ubuntu-latest strategy: + fail-fast: false matrix: # yml is dumb. update the --total arg to yarn build if you change the number of workers worker_id: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19] @@ -215,6 +216,7 @@ jobs: name: yarn test-build needs: build_and_lint strategy: + fail-fast: false matrix: test_params: [ # Intentionally passing these as strings instead of creating a @@ -250,7 +252,6 @@ jobs: - 1/3 - 2/3 - 3/3 - continue-on-error: true runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -500,6 +501,7 @@ jobs: needs: build_and_lint runs-on: ubuntu-latest strategy: + fail-fast: false matrix: browser: [chrome, firefox, edge] steps: diff --git a/.github/workflows/runtime_eslint_plugin_e2e.yml b/.github/workflows/runtime_eslint_plugin_e2e.yml index edc188f38622e..f8878548c0597 100644 --- a/.github/workflows/runtime_eslint_plugin_e2e.yml +++ b/.github/workflows/runtime_eslint_plugin_e2e.yml @@ -20,13 +20,13 @@ jobs: name: ESLint v${{ matrix.eslint_major }} runs-on: ubuntu-latest strategy: + fail-fast: false matrix: eslint_major: - "6" - "7" - "8" - "9" - continue-on-error: true steps: - uses: actions/checkout@v4 with: