diff --git a/eslint/babel-eslint-parser/package.json b/eslint/babel-eslint-parser/package.json index 2aef94a2c30f..39f351f84b34 100644 --- a/eslint/babel-eslint-parser/package.json +++ b/eslint/babel-eslint-parser/package.json @@ -23,6 +23,7 @@ "type": "commonjs", "exports": { ".": "./lib/index.cjs", + "./experimental-worker": "./lib/experimental-worker.cjs", "./package.json": "./package.json" }, "peerDependencies": { diff --git a/eslint/babel-eslint-parser/src/analyze-scope.cjs b/eslint/babel-eslint-parser/src/analyze-scope.cjs index f9fb7472e8d9..ea1b5f75fe53 100644 --- a/eslint/babel-eslint-parser/src/analyze-scope.cjs +++ b/eslint/babel-eslint-parser/src/analyze-scope.cjs @@ -4,13 +4,11 @@ const OriginalPatternVisitor = require("eslint-scope/lib/pattern-visitor"); const OriginalReferencer = require("eslint-scope/lib/referencer"); const { getKeys: fallback } = require("eslint-visitor-keys"); -const { getTypesInfo, getVisitorKeys } = require("./client.cjs"); - let visitorKeysMap; -function getVisitorValues(nodeType) { +function getVisitorValues(nodeType, client) { if (visitorKeysMap) return visitorKeysMap[nodeType]; - const { FLOW_FLIPPED_ALIAS_KEYS, VISITOR_KEYS } = getTypesInfo(); + const { FLOW_FLIPPED_ALIAS_KEYS, VISITOR_KEYS } = client.getTypesInfo(); const flowFlippedAliasKeys = FLOW_FLIPPED_ALIAS_KEYS.concat([ "ArrayPattern", @@ -63,6 +61,13 @@ class PatternVisitor extends OriginalPatternVisitor { } class Referencer extends OriginalReferencer { + #client; + + constructor(options, scopeManager, client) { + super(options, scopeManager); + this.#client = client; + } + // inherits. visitPattern(node, options, callback) { if (!node) { @@ -264,7 +269,7 @@ class Referencer extends OriginalReferencer { } // get property to check (params, id, etc...) - const visitorValues = getVisitorValues(node.type); + const visitorValues = getVisitorValues(node.type, this.#client); if (!visitorValues) { return; } @@ -328,7 +333,7 @@ class Referencer extends OriginalReferencer { } } -module.exports = function analyzeScope(ast, parserOptions) { +module.exports = function analyzeScope(ast, parserOptions, client) { const options = { ignoreEval: true, optimistic: false, @@ -343,10 +348,10 @@ module.exports = function analyzeScope(ast, parserOptions) { fallback, }; - options.childVisitorKeys = getVisitorKeys(); + options.childVisitorKeys = client.getVisitorKeys(); const scopeManager = new escope.ScopeManager(options); - const referencer = new Referencer(options, scopeManager); + const referencer = new Referencer(options, scopeManager, client); referencer.visit(ast); diff --git a/eslint/babel-eslint-parser/src/client.cjs b/eslint/babel-eslint-parser/src/client.cjs index a4a4777159b9..9bc52be6f48c 100644 --- a/eslint/babel-eslint-parser/src/client.cjs +++ b/eslint/babel-eslint-parser/src/client.cjs @@ -1,67 +1,105 @@ const path = require("path"); -let send; - -exports.getVersion = sendCached("GET_VERSION"); - -exports.getTypesInfo = sendCached("GET_TYPES_INFO"); - -exports.getVisitorKeys = sendCached("GET_VISITOR_KEYS"); - -exports.getTokLabels = sendCached("GET_TOKEN_LABELS"); - -exports.maybeParse = (code, options) => send("MAYBE_PARSE", { code, options }); - -function sendCached(action) { - let cache = null; - - return () => { - if (!cache) cache = send(action, undefined); - return cache; - }; +const ACTIONS = { + GET_VERSION: "GET_VERSION", + GET_TYPES_INFO: "GET_TYPES_INFO", + GET_VISITOR_KEYS: "GET_VISITOR_KEYS", + GET_TOKEN_LABELS: "GET_TOKEN_LABELS", + MAYBE_PARSE: "MAYBE_PARSE", + MAYBE_PARSE_SYNC: "MAYBE_PARSE_SYNC", +}; + +class Client { + #send; + + constructor(send) { + this.#send = send; + } + + #vCache; + getVersion() { + return (this.#vCache ??= this.#send(ACTIONS.GET_VERSION, undefined)); + } + + #tiCache; + getTypesInfo() { + return (this.#tiCache ??= this.#send(ACTIONS.GET_TYPES_INFO, undefined)); + } + + #vkCache; + getVisitorKeys() { + return (this.#vkCache ??= this.#send(ACTIONS.GET_VISITOR_KEYS, undefined)); + } + + #tlCache; + getTokLabels() { + return (this.#tlCache ??= this.#send(ACTIONS.GET_TOKEN_LABELS, undefined)); + } + + maybeParse(code, options) { + return this.#send(ACTIONS.MAYBE_PARSE, { code, options }); + } } -if (process.env.BABEL_8_BREAKING) { - const { - Worker, - receiveMessageOnPort, - MessageChannel, - SHARE_ENV, - } = require("worker_threads"); - - // We need to run Babel in a worker for two reasons: - // 1. ESLint workers must be CJS files, and this is a problem - // since Babel 8+ uses native ESM - // 2. ESLint parsers must run synchronously, but many steps - // of Babel's config loading (which is done for each file) - // can be asynchronous - // If ESLint starts supporting async parsers, we can move - // everything back to the main thread. - const worker = new Worker( +// We need to run Babel in a worker for two reasons: +// 1. ESLint workers must be CJS files, and this is a problem +// since Babel 8+ uses native ESM +// 2. ESLint parsers must run synchronously, but many steps +// of Babel's config loading (which is done for each file) +// can be asynchronous +// If ESLint starts supporting async parsers, we can move +// everything back to the main thread. +exports.WorkerClient = class WorkerClient extends Client { + static #worker_threads_cache; + static get #worker_threads() { + return (WorkerClient.#worker_threads_cache ??= require("worker_threads")); + } + + #worker = new WorkerClient.#worker_threads.Worker( path.resolve(__dirname, "../lib/worker/index.cjs"), - { env: SHARE_ENV }, + { env: WorkerClient.#worker_threads.SHARE_ENV }, ); - // The worker will never exit by itself. Prevent it from keeping - // the main process alive. - worker.unref(); - - const signal = new Int32Array(new SharedArrayBuffer(4)); - - send = (action, payload) => { - signal[0] = 0; - const subChannel = new MessageChannel(); - - worker.postMessage({ signal, port: subChannel.port1, action, payload }, [ - subChannel.port1, - ]); - - Atomics.wait(signal, 0, 0); - const { message } = receiveMessageOnPort(subChannel.port2); - - if (message.error) throw Object.assign(message.error, message.errorData); - else return message.result; + #signal = new Int32Array(new SharedArrayBuffer(4)); + + constructor() { + super((action, payload) => { + this.#signal[0] = 0; + const subChannel = new WorkerClient.#worker_threads.MessageChannel(); + + this.#worker.postMessage( + { signal: this.#signal, port: subChannel.port1, action, payload }, + [subChannel.port1], + ); + + Atomics.wait(this.#signal, 0, 0); + const { message } = WorkerClient.#worker_threads.receiveMessageOnPort( + subChannel.port2, + ); + + if (message.error) throw Object.assign(message.error, message.errorData); + else return message.result; + }); + + // The worker will never exit by itself. Prevent it from keeping + // the main process alive. + this.#worker.unref(); + } +}; + +if (!process.env.BABEL_8_BREAKING) { + exports.LocalClient = class LocalClient extends Client { + static #handleMessage; + + constructor() { + LocalClient.#handleMessage ??= require("./worker/handle-message.cjs"); + + super((action, payload) => { + return LocalClient.#handleMessage( + action === ACTIONS.MAYBE_PARSE ? ACTIONS.MAYBE_PARSE_SYNC : action, + payload, + ); + }); + } }; -} else { - send = require("./worker/index.cjs"); } diff --git a/eslint/babel-eslint-parser/src/experimental-worker.cjs b/eslint/babel-eslint-parser/src/experimental-worker.cjs new file mode 100644 index 000000000000..efd1036bed62 --- /dev/null +++ b/eslint/babel-eslint-parser/src/experimental-worker.cjs @@ -0,0 +1,22 @@ +const [major, minor] = process.versions.node.split(".").map(Number); + +if (major < 12 || (major === 12 && minor < 3)) { + throw new Error( + "@babel/eslint-parser/experimental-worker requires Node.js >= 12.3.0", + ); +} + +const { normalizeESLintConfig } = require("./configuration.cjs"); +const analyzeScope = require("./analyze-scope.cjs"); +const baseParse = require("./parse.cjs"); + +const { WorkerClient } = require("./client.cjs"); +const client = new WorkerClient(); + +exports.parseForESLint = function (code, options = {}) { + const normalizedOptions = normalizeESLintConfig(options); + const ast = baseParse(code, normalizedOptions, client); + const scopeManager = analyzeScope(ast, normalizedOptions, client); + + return { ast, scopeManager, visitorKeys: client.getVisitorKeys() }; +}; diff --git a/eslint/babel-eslint-parser/src/index.cjs b/eslint/babel-eslint-parser/src/index.cjs index eef046316976..f713b839f20e 100644 --- a/eslint/babel-eslint-parser/src/index.cjs +++ b/eslint/babel-eslint-parser/src/index.cjs @@ -1,63 +1,20 @@ -const semver = require("semver"); const { normalizeESLintConfig } = require("./configuration.cjs"); const analyzeScope = require("./analyze-scope.cjs"); -const { - getVersion, - getVisitorKeys, - getTokLabels, - maybeParse, -} = require("./client.cjs"); -const convert = require("./convert/index.cjs"); +const baseParse = require("./parse.cjs"); -const babelParser = require(require.resolve("@babel/parser", { - paths: [require.resolve("@babel/core/package.json")], -})); - -let isRunningMinSupportedCoreVersion = null; - -function baseParse(code, options) { - // Ensure we're using a version of `@babel/core` that includes `parse()` and `tokTypes`. - const minSupportedCoreVersion = ">=7.2.0"; - - if (typeof isRunningMinSupportedCoreVersion !== "boolean") { - isRunningMinSupportedCoreVersion = semver.satisfies( - getVersion(), - minSupportedCoreVersion, - ); - } - - if (!isRunningMinSupportedCoreVersion) { - throw new Error( - `@babel/eslint-parser@${ - PACKAGE_JSON.version - } does not support @babel/core@${getVersion()}. Please upgrade to @babel/core@${minSupportedCoreVersion}.`, - ); - } - - const { ast, parserOptions } = maybeParse(code, options); - - if (ast) return ast; - - try { - return convert.ast( - babelParser.parse(code, parserOptions), - code, - getTokLabels(), - getVisitorKeys(), - ); - } catch (err) { - throw convert.error(err); - } -} +const { LocalClient, WorkerClient } = require("./client.cjs"); +const client = new ( + process.env.BABEL_8_BREAKING ? WorkerClient : LocalClient +)(); exports.parse = function (code, options = {}) { - return baseParse(code, normalizeESLintConfig(options)); + return baseParse(code, normalizeESLintConfig(options), client); }; exports.parseForESLint = function (code, options = {}) { const normalizedOptions = normalizeESLintConfig(options); - const ast = baseParse(code, normalizedOptions); - const scopeManager = analyzeScope(ast, normalizedOptions); + const ast = baseParse(code, normalizedOptions, client); + const scopeManager = analyzeScope(ast, normalizedOptions, client); - return { ast, scopeManager, visitorKeys: getVisitorKeys() }; + return { ast, scopeManager, visitorKeys: client.getVisitorKeys() }; }; diff --git a/eslint/babel-eslint-parser/src/parse.cjs b/eslint/babel-eslint-parser/src/parse.cjs new file mode 100644 index 000000000000..e71a2a7e56e8 --- /dev/null +++ b/eslint/babel-eslint-parser/src/parse.cjs @@ -0,0 +1,45 @@ +"use strict"; + +const semver = require("semver"); +const convert = require("./convert/index.cjs"); + +const babelParser = require(require.resolve("@babel/parser", { + paths: [require.resolve("@babel/core/package.json")], +})); + +let isRunningMinSupportedCoreVersion = null; + +module.exports = function parse(code, options, client) { + // Ensure we're using a version of `@babel/core` that includes `parse()` and `tokTypes`. + const minSupportedCoreVersion = ">=7.2.0"; + + if (typeof isRunningMinSupportedCoreVersion !== "boolean") { + isRunningMinSupportedCoreVersion = semver.satisfies( + client.getVersion(), + minSupportedCoreVersion, + ); + } + + if (!isRunningMinSupportedCoreVersion) { + throw new Error( + `@babel/eslint-parser@${ + PACKAGE_JSON.version + } does not support @babel/core@${client.getVersion()}. Please upgrade to @babel/core@${minSupportedCoreVersion}.`, + ); + } + + const { ast, parserOptions } = client.maybeParse(code, options); + + if (ast) return ast; + + try { + return convert.ast( + babelParser.parse(code, parserOptions), + code, + client.getTokLabels(), + client.getVisitorKeys(), + ); + } catch (err) { + throw convert.error(err); + } +}; diff --git a/eslint/babel-eslint-parser/src/worker/configuration.cjs b/eslint/babel-eslint-parser/src/worker/configuration.cjs index 5864863b37ac..c34bfb8a6546 100644 --- a/eslint/babel-eslint-parser/src/worker/configuration.cjs +++ b/eslint/babel-eslint-parser/src/worker/configuration.cjs @@ -41,7 +41,7 @@ function normalizeParserOptions(options) { }; } -function validateResolvedConfig(config, options) { +function validateResolvedConfig(config, options, parseOptions) { if (config !== null) { if (options.requireConfigFile !== false) { if (!config.hasFilesystemConfig()) { @@ -54,8 +54,10 @@ function validateResolvedConfig(config, options) { throw new Error(error); } } - return config.options; + if (config.options) return config.options; } + + return getDefaultParserOptions(parseOptions); } function getDefaultParserOptions(options) { @@ -70,25 +72,14 @@ function getDefaultParserOptions(options) { }; } -module.exports = function normalizeBabelParseConfig(options) { +exports.normalizeBabelParseConfig = async function (options) { const parseOptions = normalizeParserOptions(options); + const config = await babel.loadPartialConfigAsync(parseOptions); + return validateResolvedConfig(config, options, parseOptions); +}; - if (process.env.BABEL_8_BREAKING) { - return babel - .loadPartialConfigAsync(parseOptions) - .then(config => validateConfigWithFallback(config)); - } else { - const config = babel.loadPartialConfigSync(parseOptions); - return validateConfigWithFallback(config); - } - - function validateConfigWithFallback(inputConfig) { - const result = validateResolvedConfig(inputConfig, options); - if (result) { - return result; - } else { - // Fallback when `loadPartialConfig` returns `null` (e.g.: when the file is ignored) - return getDefaultParserOptions(parseOptions); - } - } +exports.normalizeBabelParseConfigSync = function (options) { + const parseOptions = normalizeParserOptions(options); + const config = babel.loadPartialConfigSync(parseOptions); + return validateResolvedConfig(config, options, parseOptions); }; diff --git a/eslint/babel-eslint-parser/src/worker/handle-message.cjs b/eslint/babel-eslint-parser/src/worker/handle-message.cjs new file mode 100644 index 000000000000..7a198a847ff8 --- /dev/null +++ b/eslint/babel-eslint-parser/src/worker/handle-message.cjs @@ -0,0 +1,36 @@ +const babel = require("./babel-core.cjs"); +const maybeParse = require("./maybeParse.cjs"); +const { getVisitorKeys, getTokLabels } = require("./ast-info.cjs"); +const { + normalizeBabelParseConfig, + normalizeBabelParseConfigSync, +} = require("./configuration.cjs"); + +module.exports = function handleMessage(action, payload) { + switch (action) { + case "GET_VERSION": + return babel.version; + case "GET_TYPES_INFO": + return { + FLOW_FLIPPED_ALIAS_KEYS: babel.types.FLIPPED_ALIAS_KEYS.Flow, + VISITOR_KEYS: babel.types.VISITOR_KEYS, + }; + case "GET_TOKEN_LABELS": + return getTokLabels(); + case "GET_VISITOR_KEYS": + return getVisitorKeys(); + case "MAYBE_PARSE": + return normalizeBabelParseConfig(payload.options).then(options => + maybeParse(payload.code, options), + ); + case "MAYBE_PARSE_SYNC": + if (!process.env.BABEL_8_BREAKING) { + return maybeParse( + payload.code, + normalizeBabelParseConfigSync(payload.options), + ); + } + } + + throw new Error(`Unknown internal parser worker action: ${action}`); +}; diff --git a/eslint/babel-eslint-parser/src/worker/index.cjs b/eslint/babel-eslint-parser/src/worker/index.cjs index c212274cc7c2..9f3293cb4177 100644 --- a/eslint/babel-eslint-parser/src/worker/index.cjs +++ b/eslint/babel-eslint-parser/src/worker/index.cjs @@ -1,66 +1,28 @@ const babel = require("./babel-core.cjs"); -const maybeParse = require("./maybeParse.cjs"); -const { getVisitorKeys, getTokLabels } = require("./ast-info.cjs"); -const normalizeBabelParseConfig = require("./configuration.cjs"); +const handleMessage = require("./handle-message.cjs"); -function handleMessage(action, payload) { - switch (action) { - case "GET_VERSION": - return babel.version; - case "GET_TYPES_INFO": - return { - FLOW_FLIPPED_ALIAS_KEYS: babel.types.FLIPPED_ALIAS_KEYS.Flow, - VISITOR_KEYS: babel.types.VISITOR_KEYS, - }; - case "GET_TOKEN_LABELS": - return getTokLabels(); - case "GET_VISITOR_KEYS": - return getVisitorKeys(); - case "MAYBE_PARSE": - if (process.env.BABEL_8_BREAKING) { - return normalizeBabelParseConfig(payload.options).then(options => - maybeParse(payload.code, options), - ); - } else { - return maybeParse( - payload.code, - normalizeBabelParseConfig(payload.options), - ); - } - } - - throw new Error(`Unknown internal parser worker action: ${action}`); -} - -if (process.env.BABEL_8_BREAKING) { - const { parentPort } = require("worker_threads"); +const { parentPort } = require("worker_threads"); - parentPort.addListener( - "message", - async ({ signal, port, action, payload }) => { - let response; +parentPort.addListener("message", async ({ signal, port, action, payload }) => { + let response; - try { - if (babel.init) await babel.init; + try { + if (babel.init) await babel.init; - response = { result: await handleMessage(action, payload) }; - } catch (error) { - response = { error, errorData: { ...error } }; - } + response = { result: await handleMessage(action, payload) }; + } catch (error) { + response = { error, errorData: { ...error } }; + } - try { - port.postMessage(response); - } catch { - port.postMessage({ - error: new Error("Cannot serialize worker response"), - }); - } finally { - port.close(); - Atomics.store(signal, 0, 1); - Atomics.notify(signal, 0); - } - }, - ); -} else { - module.exports = handleMessage; -} + try { + port.postMessage(response); + } catch { + port.postMessage({ + error: new Error("Cannot serialize worker response"), + }); + } finally { + port.close(); + Atomics.store(signal, 0, 1); + Atomics.notify(signal, 0); + } +}); diff --git a/eslint/babel-eslint-tests/test/fixtures/mjs-config-file-babel-7/.eslintrc.js b/eslint/babel-eslint-tests/test/fixtures/mjs-config-file-babel-7/.eslintrc.js new file mode 100644 index 000000000000..d56bf00a27cc --- /dev/null +++ b/eslint/babel-eslint-tests/test/fixtures/mjs-config-file-babel-7/.eslintrc.js @@ -0,0 +1,13 @@ +module.exports = { + root: true, + parser: "@babel/eslint-parser/experimental-worker", + parserOptions: { + babelOptions: { + configFile: __dirname + "/babel.config.mjs", + sourceType: "module", + }, + }, + rules: { + "template-curly-spacing": "error", + }, +}; diff --git a/eslint/babel-eslint-tests/test/fixtures/mjs-config-file-babel-7/a.js b/eslint/babel-eslint-tests/test/fixtures/mjs-config-file-babel-7/a.js new file mode 100644 index 000000000000..60668017bf2c --- /dev/null +++ b/eslint/babel-eslint-tests/test/fixtures/mjs-config-file-babel-7/a.js @@ -0,0 +1 @@ +export default () =>
; diff --git a/eslint/babel-eslint-tests/test/fixtures/mjs-config-file-babel-7/babel.config.mjs b/eslint/babel-eslint-tests/test/fixtures/mjs-config-file-babel-7/babel.config.mjs new file mode 100644 index 000000000000..3d56fe842f6d --- /dev/null +++ b/eslint/babel-eslint-tests/test/fixtures/mjs-config-file-babel-7/babel.config.mjs @@ -0,0 +1,3 @@ +export default { + presets: ["@babel/preset-react"], +}; diff --git a/eslint/babel-eslint-tests/test/fixtures/mjs-config-file/.eslintrc.js b/eslint/babel-eslint-tests/test/fixtures/mjs-config-file/.eslintrc.js index 486757528be0..d56bf00a27cc 100644 --- a/eslint/babel-eslint-tests/test/fixtures/mjs-config-file/.eslintrc.js +++ b/eslint/babel-eslint-tests/test/fixtures/mjs-config-file/.eslintrc.js @@ -1,6 +1,6 @@ module.exports = { root: true, - parser: "@babel/eslint-parser", + parser: "@babel/eslint-parser/experimental-worker", parserOptions: { babelOptions: { configFile: __dirname + "/babel.config.mjs", diff --git a/eslint/babel-eslint-tests/test/integration/config-files.js b/eslint/babel-eslint-tests/test/integration/config-files.js index d99f38df986d..3ed1a87d257f 100644 --- a/eslint/babel-eslint-tests/test/integration/config-files.js +++ b/eslint/babel-eslint-tests/test/integration/config-files.js @@ -16,4 +16,21 @@ describe("Babel config files", () => { ]), ).toMatchObject({ errorCount: 0 }); }); + + const babel7node12 = + process.env.BABEL_8_BREAKING || parseInt(process.versions.node) < 12 + ? it.skip + : it; + + babel7node12("experimental worker works with babel.config.mjs", () => { + const engine = new eslint.CLIEngine({ ignore: false }); + expect( + engine.executeOnFiles([ + path.resolve( + path.dirname(fileURLToPath(import.meta.url)), + `../fixtures/mjs-config-file-babel-7/a.js`, + ), + ]), + ).toMatchObject({ errorCount: 0 }); + }); }); diff --git a/jest.config.js b/jest.config.js index 534db4892f48..2a03ce4e4202 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,3 +1,5 @@ +const supportsESM = parseInt(process.versions.node) >= 12; + module.exports = { collectCoverageFrom: [ "packages/*/src/**/*.{js,mjs,ts}", @@ -40,6 +42,7 @@ module.exports = { "/test/__data__/", "/build/", ], + resolver: supportsESM ? "./test/jestExportsMapResolver.cjs" : null, // We don't need module name mappers here as depedencies of workspace // package should be declared explicitly in the package.json // Yarn will generate correct file links so that Jest can resolve correctly diff --git a/package.json b/package.json index e271d693f6a3..1e7e89dd876c 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "babel-plugin-transform-charcodes": "^0.2.0", "chalk": "^2.4.2", "charcodes": "^0.2.0", + "enhanced-resolve": "^5.8.2", "eslint": "^7.27.0", "eslint-import-resolver-node": "^0.3.4", "eslint-plugin-flowtype": "^5.7.2", diff --git a/packages/babel-plugin-transform-runtime/scripts/build-dist.js b/packages/babel-plugin-transform-runtime/scripts/build-dist.js index db052f50012d..df6c0c96c1a1 100644 --- a/packages/babel-plugin-transform-runtime/scripts/build-dist.js +++ b/packages/babel-plugin-transform-runtime/scripts/build-dist.js @@ -127,7 +127,7 @@ function writeHelperFile( buildHelper(runtimeName, pkgDirname, fullPath, helperName, { esm, corejs }) ); - return `./${filePath}`; + return esm ? `./helpers/esm/${fileName}` : `./helpers/${fileName}`; } function writeHelpers(runtimeName, { corejs } = {}) { @@ -164,12 +164,13 @@ function writeHelpers(runtimeName, { corejs } = {}) { // - Node.js <13.2.0 will fail resolving the first array entry, and will // fallback to the second entry (the CJS file) // In Babel 8 we can simplify this. - helperSubExports[`./${helperPath}`] = [ + helperSubExports[`./${path.posix.join("helpers", helperName)}`] = [ { node: cjs, import: esm, default: cjs }, cjs, ]; // For backward compatibility. We can remove this in Babel 8. - helperSubExports[`./${path.join("helpers", "esm", helperName)}`] = esm; + helperSubExports[`./${path.posix.join("helpers", "esm", helperName)}`] = + esm; } writeHelperExports(runtimeName, helperSubExports); diff --git a/test/jestExportsMapResolver.cjs b/test/jestExportsMapResolver.cjs new file mode 100644 index 000000000000..194b9bad1975 --- /dev/null +++ b/test/jestExportsMapResolver.cjs @@ -0,0 +1,11 @@ +// Temporary workaround for https://github.com/facebook/jest/issues/9771 +// Source: https://github.com/facebook/jest/issues/9771#issuecomment-841624042 + +const resolver = require("enhanced-resolve").create.sync({ + conditionNames: ["node", "require", "default"], + extensions: [".js", ".json", ".node", ".ts"], +}); + +module.exports = function (request, options) { + return resolver(options.basedir, request); +}; diff --git a/yarn.lock b/yarn.lock index 2bbca57d0593..2f7d35e8b3f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5749,6 +5749,7 @@ __metadata: babel-plugin-transform-charcodes: ^0.2.0 chalk: ^2.4.2 charcodes: ^0.2.0 + enhanced-resolve: ^5.8.2 eslint: ^7.27.0 eslint-import-resolver-node: ^0.3.4 eslint-plugin-flowtype: ^5.7.2 @@ -7445,13 +7446,13 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.7.0": - version: 5.7.0 - resolution: "enhanced-resolve@npm:5.7.0" +"enhanced-resolve@npm:^5.7.0, enhanced-resolve@npm:^5.8.2": + version: 5.8.2 + resolution: "enhanced-resolve@npm:5.8.2" dependencies: graceful-fs: ^4.2.4 tapable: ^2.2.0 - checksum: 545cfa659e9cdccf1240bccbbd1791db7ec589979d71b35df5aeaf872dd8d13fab379ad73fa960f4cb32963b85492792c0fb0866f484043740014824ae6088b9 + checksum: 1af3f6bcb92e849f6c18d44c427cbdaecac4be61023f2008d2ef0f8a48c909bf13afa9a5c04f9d030f27d9a7e27e40c367caa22cd63d2a7eb5fdbab7579d1538 languageName: node linkType: hard