From 2bcc3c2a540c2f1db817c84f2e0eb363f9665ee5 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Thu, 27 Nov 2025 15:46:53 +0800 Subject: [PATCH] User `sourceType: 'commonjs'` where possible (#18333) --- src/language-js/parse/acorn.js | 14 ++++++++++++-- src/language-js/parse/babel.js | 11 +++++++++-- src/language-js/parse/espree.js | 1 - src/language-js/parse/meriyah.js | 7 +++---- src/language-js/parse/oxc.js | 18 ++++++++++++++++-- src/language-js/parse/utils/source-types.js | 13 +++++++------ types/espree/index.d.ts | 20 -------------------- 7 files changed, 47 insertions(+), 37 deletions(-) delete mode 100644 types/espree/index.d.ts diff --git a/src/language-js/parse/acorn.js b/src/language-js/parse/acorn.js index d93e2df4b..98cb314e5 100644 --- a/src/language-js/parse/acorn.js +++ b/src/language-js/parse/acorn.js @@ -7,10 +7,14 @@ import createParser from "./utils/create-parser.js"; import { getSourceType, SOURCE_TYPE_COMBINATIONS, + SOURCE_TYPE_COMMONJS, SOURCE_TYPE_MODULE, + SOURCE_TYPE_SCRIPT, } from "./utils/source-types.js"; -/** @import {Options} from "acorn" */ +/** +@import {Options} from "acorn"; +*/ /** @type {Options} */ const parseOptions = { @@ -55,6 +59,10 @@ const getParser = () => { return parser; }; +/** +@param {string} text +@param {SOURCE_TYPE_MODULE | SOURCE_TYPE_COMMONJS | undefined} sourceType +*/ function parseWithOptions(text, sourceType) { const parser = getParser(); @@ -62,7 +70,9 @@ function parseWithOptions(text, sourceType) { const ast = parser.parse(text, { ...parseOptions, - sourceType, + // https://github.com/acornjs/acorn/pull/1377 not released yet + sourceType: + sourceType === SOURCE_TYPE_COMMONJS ? SOURCE_TYPE_SCRIPT : sourceType, allowImportExportEverywhere: sourceType === SOURCE_TYPE_MODULE, onComment: comments, }); diff --git a/src/language-js/parse/babel.js b/src/language-js/parse/babel.js index 49007165d..f8957df1d 100644 --- a/src/language-js/parse/babel.js +++ b/src/language-js/parse/babel.js @@ -7,8 +7,8 @@ import createBabelParseError from "./utils/create-babel-parse-error.js"; import createParser from "./utils/create-parser.js"; import { getSourceType, + SOURCE_TYPE_COMMONJS, SOURCE_TYPE_MODULE, - SOURCE_TYPE_SCRIPT, } from "./utils/source-types.js"; import wrapBabelExpression from "./utils/wrap-babel-expression.js"; @@ -121,10 +121,17 @@ function createParse({ isExpression = false, optionsCombinations }) { let combinations = optionsCombinations; const sourceType = options.__babelSourceType ?? getSourceType(filepath); - if (sourceType === SOURCE_TYPE_SCRIPT) { + if (sourceType && sourceType !== SOURCE_TYPE_MODULE) { combinations = combinations.map((options) => ({ ...options, sourceType, + // `sourceType: "commonjs"` does not allow these two properties + ...(sourceType === SOURCE_TYPE_COMMONJS + ? { + allowReturnOutsideFunction: undefined, + allowNewTargetOutsideFunction: undefined, + } + : undefined), })); } diff --git a/src/language-js/parse/espree.js b/src/language-js/parse/espree.js index cf2790314..5369d111e 100644 --- a/src/language-js/parse/espree.js +++ b/src/language-js/parse/espree.js @@ -19,7 +19,6 @@ const parseOptions = { tokens: false, ecmaFeatures: { jsx: true, - globalReturn: true, impliedStrict: false, }, }; diff --git a/src/language-js/parse/meriyah.js b/src/language-js/parse/meriyah.js index 5af8ae0b9..d4c51853b 100644 --- a/src/language-js/parse/meriyah.js +++ b/src/language-js/parse/meriyah.js @@ -6,12 +6,11 @@ import createParser from "./utils/create-parser.js"; import { getSourceType, SOURCE_TYPE_COMBINATIONS, - SOURCE_TYPE_MODULE, } from "./utils/source-types.js"; /** @import {ESTree as MeriyahESTree} from "meriyah"; -@import {SOURCE_TYPE_SCRIPT} from "./utils/source-types.js"; +@import {SOURCE_TYPE_MODULE, SOURCE_TYPE_COMMONJS} from "./utils/source-types.js"; */ // https://github.com/meriyah/meriyah/blob/4676f60b6c149d7082bde2c9147f9ae2359c8075/src/parser.ts#L185 @@ -46,7 +45,7 @@ const parseOptions = { /** @param {string} text -@param {SOURCE_TYPE_MODULE | SOURCE_TYPE_SCRIPT} sourceType +@param {SOURCE_TYPE_MODULE | SOURCE_TYPE_COMMONJS} sourceType */ function parseWithOptions(text, sourceType) { /** @type {MeriyahESTree.Comment[]} */ @@ -54,7 +53,7 @@ function parseWithOptions(text, sourceType) { const ast = meriyahParse(text, { ...parseOptions, - sourceType: sourceType === SOURCE_TYPE_MODULE ? sourceType : "commonjs", + sourceType, onComment: comments, }); diff --git a/src/language-js/parse/oxc.js b/src/language-js/parse/oxc.js index b48a36782..1e7e5d735 100644 --- a/src/language-js/parse/oxc.js +++ b/src/language-js/parse/oxc.js @@ -5,10 +5,17 @@ import { tryCombinations } from "../../utils/try-combinations.js"; import postprocess from "./postprocess/index.js"; import createParser from "./utils/create-parser.js"; import jsxRegexp from "./utils/jsx-regexp.evaluate.js"; -import { getSourceType } from "./utils/source-types.js"; +import { + getSourceType, + SOURCE_TYPE_COMMONJS, + SOURCE_TYPE_SCRIPT, +} from "./utils/source-types.js"; /** @import {ParseResult, ParserOptions as ParserOptionsWithoutExperimentalRawTransfer} from "oxc-parser" */ -/** @typedef {ParserOptionsWithoutExperimentalRawTransfer & {experimentalRawTransfer?: boolean}} ParserOptions */ +/** @typedef {Omit & { + sourceType?: ParserOptionsWithoutExperimentalRawTransfer["sourceType"] | "commonjs", + experimentalRawTransfer?: boolean, +}} ParserOptions */ function createParseError(error, { text }) { /* c8 ignore next 3 */ @@ -41,10 +48,17 @@ function createParseError(error, { text }) { @returns {Promise} */ async function parseWithOptions(filepath, text, options) { + let { sourceType } = options; + // https://github.com/oxc-project/oxc/issues/16200 + if (sourceType === SOURCE_TYPE_COMMONJS) { + sourceType = SOURCE_TYPE_SCRIPT; + } + const result = await oxcParse(filepath, text, { preserveParens: true, showSemanticErrors: false, ...options, + sourceType, }); const { errors } = result; diff --git a/src/language-js/parse/utils/source-types.js b/src/language-js/parse/utils/source-types.js index e09a2d387..cdcec7f88 100644 --- a/src/language-js/parse/utils/source-types.js +++ b/src/language-js/parse/utils/source-types.js @@ -1,13 +1,14 @@ -export const SOURCE_TYPE_MODULE = "module"; -export const SOURCE_TYPE_SCRIPT = "script"; +export const SOURCE_TYPE_MODULE = /** @type {const} */ ("module"); +export const SOURCE_TYPE_SCRIPT = /** @type {const} */ ("script"); +export const SOURCE_TYPE_COMMONJS = /** @type {const} */ ("commonjs"); -/** @type {["module", "script"]} */ +/** @type {readonly [SOURCE_TYPE_MODULE, SOURCE_TYPE_COMMONJS]} */ export const SOURCE_TYPE_COMBINATIONS = [ SOURCE_TYPE_MODULE, - SOURCE_TYPE_SCRIPT, + SOURCE_TYPE_COMMONJS, ]; -/** @returns {"module" | "script" | undefined} */ +/** @returns {SOURCE_TYPE_MODULE | SOURCE_TYPE_COMMONJS | undefined} */ export function getSourceType(filepath) { if (typeof filepath !== "string") { return; @@ -20,6 +21,6 @@ export function getSourceType(filepath) { } if (/\.(?:cjs|cts)$/iu.test(filepath)) { - return SOURCE_TYPE_SCRIPT; + return SOURCE_TYPE_COMMONJS; } } diff --git a/types/espree/index.d.ts b/types/espree/index.d.ts deleted file mode 100644 index ba96d9bd1..000000000 --- a/types/espree/index.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -declare module "espree" { - // https://github.com/eslint/espree#options - export interface Options { - range?: boolean; - loc?: boolean; - comment?: boolean; - tokens?: boolean; - ecmaVersion?: "latest"; - sourceType?: "script" | "module"; - ecmaFeatures?: { - jsx?: boolean; - globalReturn?: boolean; - impliedStrict?: boolean; - }; - } - // https://github.com/eslint/espree#parse - export function parse(code: string, options?: Options): any; - // https://github.com/eslint/espree#tokenize - export function tokenize(code: string, options?: Options): any; -}