diff --git a/.pnp.cjs b/.pnp.cjs index 6070fdc83ec6..0343890d3d9d 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -253,7 +253,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@babel/preset-env", "virtual:e470d99b1e4fdf4c5db5d090ff5472cdeba0404b7ffd31cd2efab3493dd184c67bc45f60c2ef1c040e2c41afe38c6280bffc5df2fbe3aefaa2b6eacf685ab07c#npm:7.23.3"],\ ["@babel/preset-react", "virtual:e470d99b1e4fdf4c5db5d090ff5472cdeba0404b7ffd31cd2efab3493dd184c67bc45f60c2ef1c040e2c41afe38c6280bffc5df2fbe3aefaa2b6eacf685ab07c#npm:7.23.3"],\ ["@babel/preset-typescript", "virtual:e470d99b1e4fdf4c5db5d090ff5472cdeba0404b7ffd31cd2efab3493dd184c67bc45f60c2ef1c040e2c41afe38c6280bffc5df2fbe3aefaa2b6eacf685ab07c#npm:7.23.3"],\ - ["@babel/register", "virtual:e470d99b1e4fdf4c5db5d090ff5472cdeba0404b7ffd31cd2efab3493dd184c67bc45f60c2ef1c040e2c41afe38c6280bffc5df2fbe3aefaa2b6eacf685ab07c#npm:7.22.15"],\ ["@types/jest", "npm:28.1.8"],\ ["@types/node", "npm:18.7.6"],\ ["@yarnpkg/cli", "virtual:712d04b0098634bdb13868ff8f85b327022bd7d3880873ada8c0ae56847ed36cf9da1fd74a88519380129cec528fe2bd2201426bc28ac9d4a8cc6734ff25c538#workspace:packages/yarnpkg-cli"],\ @@ -261,8 +260,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@yarnpkg/eslint-config", "virtual:e470d99b1e4fdf4c5db5d090ff5472cdeba0404b7ffd31cd2efab3493dd184c67bc45f60c2ef1c040e2c41afe38c6280bffc5df2fbe3aefaa2b6eacf685ab07c#workspace:packages/eslint-config"],\ ["@yarnpkg/sdks", "workspace:packages/yarnpkg-sdks"],\ ["clipanion", "virtual:576bf3e379b293160348e4cadfbd6541796e6f78477b0875c4437065090cec6f78b6ec2281b8e15d1c870d61578dc7dee16a5ae49a65701fec83e592ce2ebdeb#npm:3.2.0-rc.4"],\ + ["esbuild-wasm", "npm:0.17.5"],\ ["eslint", "npm:8.2.0"],\ ["jest", "virtual:e470d99b1e4fdf4c5db5d090ff5472cdeba0404b7ffd31cd2efab3493dd184c67bc45f60c2ef1c040e2c41afe38c6280bffc5df2fbe3aefaa2b6eacf685ab07c#npm:28.1.3"],\ + ["pirates", "npm:4.0.6"],\ ["tslib", "npm:1.13.0"],\ ["typescript", "patch:typescript@npm%3A5.2.0-beta#~builtin::version=5.2.0-beta&hash=14eedb"]\ ],\ @@ -4931,33 +4932,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ - ["@babel/register", [\ - ["npm:7.22.15", {\ - "packageLocation": "./.yarn/cache/@babel-register-npm-7.22.15-13445da448-5497be6773.zip/node_modules/@babel/register/",\ - "packageDependencies": [\ - ["@babel/register", "npm:7.22.15"]\ - ],\ - "linkType": "SOFT"\ - }],\ - ["virtual:e470d99b1e4fdf4c5db5d090ff5472cdeba0404b7ffd31cd2efab3493dd184c67bc45f60c2ef1c040e2c41afe38c6280bffc5df2fbe3aefaa2b6eacf685ab07c#npm:7.22.15", {\ - "packageLocation": "./.yarn/__virtual__/@babel-register-virtual-fbeeb65d78/0/cache/@babel-register-npm-7.22.15-13445da448-5497be6773.zip/node_modules/@babel/register/",\ - "packageDependencies": [\ - ["@babel/register", "virtual:e470d99b1e4fdf4c5db5d090ff5472cdeba0404b7ffd31cd2efab3493dd184c67bc45f60c2ef1c040e2c41afe38c6280bffc5df2fbe3aefaa2b6eacf685ab07c#npm:7.22.15"],\ - ["@babel/core", "npm:7.23.3"],\ - ["@types/babel__core", null],\ - ["clone-deep", "npm:4.0.1"],\ - ["find-cache-dir", "npm:2.1.0"],\ - ["make-dir", "npm:2.1.0"],\ - ["pirates", "npm:4.0.6"],\ - ["source-map-support", "npm:0.5.20"]\ - ],\ - "packagePeers": [\ - "@babel/core",\ - "@types/babel__core"\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@babel/regjsgen", [\ ["npm:0.8.0", {\ "packageLocation": "./.yarn/cache/@babel-regjsgen-npm-0.8.0-b0fbdbf644-89c338fee7.zip/node_modules/@babel/regjsgen/",\ @@ -11278,7 +11252,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@babel/preset-env", "virtual:e470d99b1e4fdf4c5db5d090ff5472cdeba0404b7ffd31cd2efab3493dd184c67bc45f60c2ef1c040e2c41afe38c6280bffc5df2fbe3aefaa2b6eacf685ab07c#npm:7.23.3"],\ ["@babel/preset-react", "virtual:e470d99b1e4fdf4c5db5d090ff5472cdeba0404b7ffd31cd2efab3493dd184c67bc45f60c2ef1c040e2c41afe38c6280bffc5df2fbe3aefaa2b6eacf685ab07c#npm:7.23.3"],\ ["@babel/preset-typescript", "virtual:e470d99b1e4fdf4c5db5d090ff5472cdeba0404b7ffd31cd2efab3493dd184c67bc45f60c2ef1c040e2c41afe38c6280bffc5df2fbe3aefaa2b6eacf685ab07c#npm:7.23.3"],\ - ["@babel/register", "virtual:e470d99b1e4fdf4c5db5d090ff5472cdeba0404b7ffd31cd2efab3493dd184c67bc45f60c2ef1c040e2c41afe38c6280bffc5df2fbe3aefaa2b6eacf685ab07c#npm:7.22.15"],\ ["@types/jest", "npm:28.1.8"],\ ["@types/node", "npm:18.7.6"],\ ["@yarnpkg/cli", "virtual:712d04b0098634bdb13868ff8f85b327022bd7d3880873ada8c0ae56847ed36cf9da1fd74a88519380129cec528fe2bd2201426bc28ac9d4a8cc6734ff25c538#workspace:packages/yarnpkg-cli"],\ @@ -11286,8 +11259,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@yarnpkg/eslint-config", "virtual:e470d99b1e4fdf4c5db5d090ff5472cdeba0404b7ffd31cd2efab3493dd184c67bc45f60c2ef1c040e2c41afe38c6280bffc5df2fbe3aefaa2b6eacf685ab07c#workspace:packages/eslint-config"],\ ["@yarnpkg/sdks", "workspace:packages/yarnpkg-sdks"],\ ["clipanion", "virtual:576bf3e379b293160348e4cadfbd6541796e6f78477b0875c4437065090cec6f78b6ec2281b8e15d1c870d61578dc7dee16a5ae49a65701fec83e592ce2ebdeb#npm:3.2.0-rc.4"],\ + ["esbuild-wasm", "npm:0.17.5"],\ ["eslint", "npm:8.2.0"],\ ["jest", "virtual:e470d99b1e4fdf4c5db5d090ff5472cdeba0404b7ffd31cd2efab3493dd184c67bc45f60c2ef1c040e2c41afe38c6280bffc5df2fbe3aefaa2b6eacf685ab07c#npm:28.1.3"],\ + ["pirates", "npm:4.0.6"],\ ["tslib", "npm:1.13.0"],\ ["typescript", "patch:typescript@npm%3A5.2.0-beta#~builtin::version=5.2.0-beta&hash=14eedb"]\ ],\ @@ -21478,6 +21453,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["esbuild-wasm", "npm:0.15.15"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.17.5", {\ + "packageLocation": "./.yarn/cache/esbuild-wasm-npm-0.17.5-9d427259bd-b7ed5d29bf.zip/node_modules/esbuild-wasm/",\ + "packageDependencies": [\ + ["esbuild-wasm", "npm:0.17.5"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["escalade", [\ diff --git a/.yarn/cache/@babel-register-npm-7.22.15-13445da448-5497be6773.zip b/.yarn/cache/@babel-register-npm-7.22.15-13445da448-5497be6773.zip deleted file mode 100644 index c7c76ca5048c..000000000000 Binary files a/.yarn/cache/@babel-register-npm-7.22.15-13445da448-5497be6773.zip and /dev/null differ diff --git a/.yarn/cache/esbuild-wasm-npm-0.17.5-9d427259bd-b7ed5d29bf.zip b/.yarn/cache/esbuild-wasm-npm-0.17.5-9d427259bd-b7ed5d29bf.zip new file mode 100644 index 000000000000..f545149ed192 Binary files /dev/null and b/.yarn/cache/esbuild-wasm-npm-0.17.5-9d427259bd-b7ed5d29bf.zip differ diff --git a/package.json b/package.json index ea0327d43e33..305a609c7acf 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "@babel/preset-env": "^7.23.3", "@babel/preset-react": "^7.23.3", "@babel/preset-typescript": "^7.23.3", - "@babel/register": "^7.22.15", "@types/jest": "^28.1.6", "@types/node": "^18.7.6", "@yarnpkg/cli": "workspace:^", @@ -19,8 +18,10 @@ "@yarnpkg/eslint-config": "workspace:^", "@yarnpkg/sdks": "workspace:^", "clipanion": "3.2.0-rc.4", + "esbuild-wasm": "0.17.5", "eslint": "^8.2.0", "jest": "^28.1.3", + "pirates": "^4.0.5", "tslib": "^1.13.0", "typescript": "5.2.0-beta" }, diff --git a/scripts/setup-ts-execution.js b/scripts/setup-ts-execution.js index 80a6aead3d1e..d53f64f4a9ab 100644 --- a/scripts/setup-ts-execution.js +++ b/scripts/setup-ts-execution.js @@ -1,27 +1,134 @@ +const crypto = require(`crypto`); +const esbuild = require(`esbuild-wasm`); +const fs = require(`fs`); const path = require(`path`); -const babel = require(`@babel/core`); -const os = require(`os`); -const root = path.dirname(__dirname); +const pirates = require(`pirates`); +const v8 = require(`v8`); +const zlib = require(`zlib`); -// The cache in @babel/register never clears itself and will therefore grow -// forever causing massive slowdowns if left unchecked for a while -// this ensures a new cache key is generated every week -const weeksSinceUNIXEpoch = Math.floor(Date.now() / 604800000); +/** + * There is an issue on Windows with Node.js v14 (tested v14.19.2 and v14.21.2) where + * ```sh + * node esbuild-wasm\bin\esbuild --service=0.17.5 --ping + * ``` + * uses up to 400% CPU and 3.62 GB RAM for a while when an ESM loader is enabled. + * + * ```console + * $ time NODE_OPTIONS="--require ./.pnp.cjs --loader ./.pnp.loader.mjs" node -p "require('esbuild-wasm').transformSync('let foo = 0;')" + * { + * warnings: [], + * code: 'let foo = 0;\n', + * map: '', + * mangleCache: undefined, + * legalComments: undefined + * } + * + * ________________________________________________________ + * Executed in 54.99 secs fish external + * usr time 0.00 micros 0.00 micros 0.00 micros + * sys time 0.00 micros 0.00 micros 0.00 micros + * ``` + * + * Reported upstream in https://github.com/evanw/esbuild/issues/2888 and seems to boil down to https://github.com/nodejs/node/issues/36616. + * + * To workaround this issue we remove the loader from the NODE_OPTIONS since it's not needed in this case. + */ -if (!process.env.BABEL_CACHE_PATH) - process.env.BABEL_CACHE_PATH = path.join(os.tmpdir(), `babel`, `.babel.${babel.version}.${babel.getEnv()}.${weeksSinceUNIXEpoch}.json`); +if (process.env.NODE_OPTIONS) { + const esmLoaderExpression = /\s*--experimental-loader\s+\S*\.pnp\.loader\.mjs\s*/; + process.env.NODE_OPTIONS = process.env.NODE_OPTIONS.replace(esmLoaderExpression, ` `); +} -require(`@babel/register`)({ - root, - extensions: [`.tsx`, `.ts`, `.js`], - only: [ - p => { - if (p && p.endsWith(`.js`)) { - const normalizedP = p.replace(/\\/g, `/`); - return normalizedP.includes(`packages/yarnpkg-pnp/sources/node`) || normalizedP.endsWith(`packages/yarnpkg-pnp/sources/loader/node-options.js`); - } - - return true; +// Needed by the worker spawned by esbuild +if (process.versions.pnp) + process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS || ``} -r ${JSON.stringify(require.resolve(`pnpapi`))}`; + +const resolveVirtual = process.versions.pnp + ? require(`pnpapi`).resolveVirtual + : undefined; + +// esbuild only supports major.minor.patch, no pre-release (nightly) specifier is allowed +// so we reduce the version down to major.minor +const NODE_VERSION = process.versions.node.split(`.`, 2).join(`.`); + +const cache = { + version: `${esbuild.version}\0${NODE_VERSION}`, + files: new Map(), + isDirty: false, +}; + +const cachePath = path.join(__dirname, `../node_modules/.cache/yarn/esbuild-transpile-cache.bin`); +try { + const cacheData = v8.deserialize(zlib.brotliDecompressSync(fs.readFileSync(cachePath))); + if (cacheData.version === cache.version) { + cache.files = cacheData.files; + } +} catch {} + +function persistCache() { + if (!cache.isDirty) + return; + + cache.isDirty = false; + + const data = v8.serialize({ + version: cache.version, + files: cache.files, + }); + + fs.mkdirSync(path.dirname(cachePath), {recursive: true}); + + const tmpPath = cachePath + crypto.randomBytes(8).toString(`hex`); + fs.writeFileSync(tmpPath, zlib.brotliCompressSync(data, { + params: { + [zlib.constants.BROTLI_PARAM_QUALITY]: 4, + }, + })); + + fs.renameSync(tmpPath, cachePath); +} + +process.once(`exit`, persistCache); +process.nextTick(persistCache); + +process.setSourceMapsEnabled && process.setSourceMapsEnabled(true); + +function compileFile(sourceCode, filename) { + filename = (resolveVirtual && resolveVirtual(filename)) || filename; + + const cacheEntry = cache.files.get(filename); + if (cacheEntry && cacheEntry.source === sourceCode) + return cacheEntry.code; + + const res = esbuild.transformSync(sourceCode, { + target: `node${NODE_VERSION}`, + loader: path.extname(filename).slice(1), + sourcefile: filename, + sourcemap: `inline`, + platform: `node`, + format: `cjs`, + supported: { + 'dynamic-import': false, }, - ], + }); + + cache.isDirty = true; + cache.files.set(filename, { + source: sourceCode, + code: res.code, + }); + + return res.code; +} + +pirates.addHook(compileFile, { + extensions: [`.tsx`, `.ts`, `.js`], + matcher(p) { + if (p && p.endsWith(`.js`)) { + const normalizedP = p.replace(/\\/g, `/`); + return normalizedP.includes(`packages/yarnpkg-pnp/sources/node`) || normalizedP.endsWith(`packages/yarnpkg-pnp/sources/loader/node-options.js`); + } + + return true; + }, }); diff --git a/yarn.lock b/yarn.lock index 6d1bc89ccdbc..6778b191d913 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1803,21 +1803,6 @@ __metadata: languageName: node linkType: hard -"@babel/register@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/register@npm:7.22.15" - dependencies: - clone-deep: ^4.0.1 - find-cache-dir: ^2.0.0 - make-dir: ^2.1.0 - pirates: ^4.0.5 - source-map-support: ^0.5.16 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f - languageName: node - linkType: hard - "@babel/regjsgen@npm:^0.8.0": version: 0.8.0 resolution: "@babel/regjsgen@npm:0.8.0" @@ -5997,7 +5982,6 @@ __metadata: "@babel/preset-env": ^7.23.3 "@babel/preset-react": ^7.23.3 "@babel/preset-typescript": ^7.23.3 - "@babel/register": ^7.22.15 "@types/jest": ^28.1.6 "@types/node": ^18.7.6 "@yarnpkg/cli": "workspace:^" @@ -6005,8 +5989,10 @@ __metadata: "@yarnpkg/eslint-config": "workspace:^" "@yarnpkg/sdks": "workspace:^" clipanion: 3.2.0-rc.4 + esbuild-wasm: 0.17.5 eslint: ^8.2.0 jest: ^28.1.3 + pirates: ^4.0.5 tslib: ^1.13.0 typescript: 5.2.0-beta dependenciesMeta: @@ -11202,6 +11188,15 @@ __metadata: languageName: node linkType: hard +"esbuild-wasm@npm:0.17.5": + version: 0.17.5 + resolution: "esbuild-wasm@npm:0.17.5" + bin: + esbuild: bin/esbuild + checksum: b7ed5d29bfb4aaa64374ec70b26fc325f26f80f3192195ac55681abc7ffe49e1844398055ad7c80e7544aa9db3dde5fd3e204ee6f6304ec378678036ddc1fef4 + languageName: node + linkType: hard + "esbuild@npm:esbuild-wasm@^0.15.15": version: 0.15.15 resolution: "esbuild-wasm@npm:0.15.15" @@ -12409,7 +12404,7 @@ __metadata: languageName: node linkType: hard -"find-cache-dir@npm:^2.0.0, find-cache-dir@npm:^2.1.0": +"find-cache-dir@npm:^2.1.0": version: 2.1.0 resolution: "find-cache-dir@npm:2.1.0" dependencies: @@ -17807,7 +17802,7 @@ __metadata: languageName: node linkType: hard -"make-dir@npm:^2.0.0, make-dir@npm:^2.1.0": +"make-dir@npm:^2.0.0": version: 2.1.0 resolution: "make-dir@npm:2.1.0" dependencies: @@ -23979,7 +23974,7 @@ resolve@^2.0.0-next.3: languageName: node linkType: hard -"source-map-support@npm:^0.5.16, source-map-support@npm:^0.5.17, source-map-support@npm:^0.5.19, source-map-support@npm:~0.5.12, source-map-support@npm:~0.5.20": +"source-map-support@npm:^0.5.17, source-map-support@npm:^0.5.19, source-map-support@npm:~0.5.12, source-map-support@npm:~0.5.20": version: 0.5.20 resolution: "source-map-support@npm:0.5.20" dependencies: