From 4df0a871ca5e9fb86abee5803777af463231a746 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Thu, 29 May 2025 15:30:45 +0800 Subject: [PATCH] Add `hermes` parser (#17520) --- CONTRIBUTING.md | 2 +- knip.config.js | 3 +- package.json | 7 +- packages/plugin-hermes/README.md | 27 +++ packages/plugin-hermes/index.js | 1 + packages/plugin-hermes/package.json | 22 ++ packages/plugin-oxc/README.md | 6 +- scripts/build-website.js | 24 +- scripts/build/build-dependencies-license.js | 4 +- scripts/build/build-javascript-module.js | 2 +- scripts/build/build-package-json.js | 34 ++- scripts/build/build.js | 5 +- scripts/build/config.js | 97 ++++++++ src/language-js/comments/printer-methods.js | 3 +- src/language-js/parse/flow.js | 12 +- src/language-js/parse/hermes.js | 51 +++++ src/language-js/parse/oxc.js | 5 + src/language-js/parse/postprocess/index.js | 10 +- src/language-js/parse/typescript.js | 9 +- .../parse/utils/create-babel-parse-error.js | 13 +- src/main/range-util.js | 1 + tests/config/run-format-test.js | 52 ++++- .../binding/__snapshots__/format.test.js.snap | 47 ++++ tests/format/flow-repo/binding/format.test.js | 4 +- .../__snapshots__/format.test.js.snap | 13 ++ .../format.test.js | 6 +- .../__snapshots__/format.test.js.snap | 13 ++ .../esproposal_decorators.warn/format.test.js | 3 +- .../__snapshots__/format.test.js.snap | 15 ++ .../flow-repo/find-module/format.test.js | 2 +- .../__snapshots__/format.test.js.snap | 34 +++ .../flow-repo/type_only_vars/format.test.js | 6 +- .../unary/__snapshots__/format.test.js.snap | 14 ++ tests/format/flow-repo/unary/format.test.js | 6 +- .../__snapshots__/format.test.js.snap | 27 +++ .../as-satisfies-expression/format.test.js | 7 +- .../__snapshots__/format.test.js.snap | 8 +- tests/format/flow/assignments/issue-10850.js | 4 +- .../await/__snapshots__/format.test.js.snap | 13 ++ tests/format/flow/await/format.test.js | 5 +- .../__snapshots__/format.test.js.snap | 16 +- tests/format/flow/implements/implements.js | 8 +- .../__snapshots__/format.test.js.snap | 4 +- .../format/flow/import-type-specifier/test.js | 2 +- .../import/__snapshots__/format.test.js.snap | 18 +- tests/format/flow/import/import-as-as.js | 1 - tests/format/flow/import/import-as-as2.js | 2 + .../ternary/__snapshots__/format.test.js.snap | 48 ++++ .../__snapshots__/format.test.js.snap | 4 +- .../flow-only/const-type-params.js | 2 +- .../__snapshots__/format.test.js.snap | 13 ++ tests/format/js/assignment/format.test.js | 6 +- .../__snapshots__/format.test.js.snap | 92 ++++++++ .../class-expression/format.test.js | 1 + .../__snapshots__/format.test.js.snap | 12 + tests/format/js/destructuring/format.test.js | 6 +- .../__snapshots__/format.test.js.snap | 27 +++ tests/format/js/dynamic-import/format.test.js | 1 + .../__snapshots__/format.test.js.snap | 211 ++++++++++++++++++ .../format.test.js | 24 ++ .../escaped/__snapshots__/format.test.js.snap | 10 + .../js/export-default/escaped/format.test.js | 1 + .../__snapshots__/format.test.js.snap | 20 ++ tests/format/js/export-star/format.test.js | 1 + .../ignore/__snapshots__/format.test.js.snap | 25 +++ tests/format/js/ignore/format.test.js | 1 + .../__snapshots__/format.test.js.snap | 14 ++ .../js/multiparser-invalid/format.test.js | 1 + .../__snapshots__/format.test.js.snap | 19 ++ tests/format/js/new-target/format.test.js | 1 + .../objects/__snapshots__/format.test.js.snap | 26 +++ tests/format/js/objects/format.test.js | 1 + .../__snapshots__/format.test.js.snap | 33 +++ tests/format/js/sloppy-mode/format.test.js | 5 + .../classes/__snapshots__/format.test.js.snap | 16 +- .../typescript/classes/break-heritage.ts | 8 +- .../__snapshots__/format.test.js.snap | 10 + .../type-params/consistent/format.test.js | 1 + .../__snapshots__/format.test.js.snap | 12 +- .../issue-13817.ts | 6 +- website/playground/codeSamples.mjs | 1 + website/playground/markdown.js | 1 + website/playground/util.js | 1 + website/static/worker.mjs | 7 + yarn.lock | 3 +- 85 files changed, 1231 insertions(+), 108 deletions(-) create mode 100644 packages/plugin-hermes/README.md create mode 100644 packages/plugin-hermes/index.js create mode 100644 packages/plugin-hermes/package.json create mode 100644 src/language-js/parse/hermes.js create mode 100644 tests/format/flow/import/import-as-as2.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a95a75c29..9f059ba6b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,7 +48,7 @@ function runFormatTest( Parameters: - **`fixtures`**: Must be set to `import.meta` or to an object of the shape `{ importMeta: import.meta, ... }`. The object may have the `snippets` property to specify an array of extra input entries in addition to the files in the current directory. For each input entry (a file or a snippet), `runFormatTest` configures and runs a number of tests. The main check is that for a given input the output should match the snapshot (for snippets, the expected output can also be specified directly). [Additional checks](#deeper-testing) are controlled by options and environment variables. -- **`parsers`**: A list of parser names. The tests verify that the parsers in this list produce the same output. If the list includes `typescript`, then `babel-ts`, and `oxc-ts` is included implicitly. If the list includes `flow`, then `babel-flow` is included implicitly. If the list includes `babel`, and the current directory is inside `tests/format/js` or `tests/format/jsx`, then `acorn`, `espree`, `meriyah`, and `oxc` are included implicitly. +- **`parsers`**: A list of parser names. The tests verify that the parsers in this list produce the same output. If the list includes `typescript`, then `babel-ts`, and `oxc-ts` are included implicitly. If the list includes `flow`, then `hermes` and `babel-flow` is included implicitly. If the list includes `babel`, and the current directory is inside `tests/format/js` or `tests/format/jsx`, then `acorn`, `espree`, `meriyah`, and `oxc` are included implicitly. - **`options`**: In addition to Prettier's formatting options, can contain the `errors` property to specify that it's expected that the formatting shouldn't be successful and an error should be thrown for all (`errors: true`) or some combinations of input entries and parsers. The implementation of `runFormatTest` can be found in [`tests/config/run-format-test.js`](tests/config/run-format-test.js). diff --git a/knip.config.js b/knip.config.js index 6850346b7..29bb20bd2 100644 --- a/knip.config.js +++ b/knip.config.js @@ -9,6 +9,7 @@ export default { "src/cli/index.js", "src/experimental-cli/index.js", "packages/plugin-oxc/index.js", + "packages/plugin-hermes/index.js", ], project: ["src/**", "scripts/**"], ignore: [ @@ -17,7 +18,7 @@ export default { "scripts/tools/**", "src/experimental-cli/**", ], - ignoreDependencies: ["eslint-formatter-friendly", "ts-expect"], + ignoreDependencies: ["eslint-formatter-friendly", "ts-expect", "buffer"], ignoreBinaries: [ "test-coverage", "renovate-config-validator", diff --git a/package.json b/package.json index 01bb36b89..8a23490cb 100644 --- a/package.json +++ b/package.json @@ -121,6 +121,7 @@ "@typescript-eslint/parser": "8.33.0", "browserslist": "4.24.5", "browserslist-to-esbuild": "2.1.1", + "buffer": "6.0.3", "c8": "10.1.3", "cross-env": "7.0.3", "cspell": "9.0.0", @@ -189,9 +190,9 @@ "build": "node ./scripts/build/build.js", "build:website": "node ./scripts/build-website.js", "gen:changelog": "node ./scripts/generate-changelog.js", - "debug": "node bin/prettier.js --ignore-path=.prettierignore --plugin=./packages/plugin-oxc/index.js", - "debug:watch": "node --watch bin/prettier.js --ignore-path=.prettierignore --plugin=./packages/plugin-oxc/index.js", - "debug:inspect": "node --inspect-brk bin/prettier.js --ignore-path=.prettierignore --plugin=./packages/plugin-oxc/index.js" + "debug": "node bin/prettier.js --ignore-path=.prettierignore --plugin=./packages/plugin-oxc/index.js --plugin=./packages/plugin-hermes/index.js", + "debug:watch": "node --watch bin/prettier.js --ignore-path=.prettierignore --plugin=./packages/plugin-oxc/index.js --plugin=./packages/plugin-hermes/index.js", + "debug:inspect": "node --inspect-brk bin/prettier.js --ignore-path=.prettierignore --plugin=./packages/plugin-oxc/index.js --plugin=./packages/plugin-hermes/index.js" }, "c8": { "reporter": [ diff --git a/packages/plugin-hermes/README.md b/packages/plugin-hermes/README.md new file mode 100644 index 000000000..4a79a44c6 --- /dev/null +++ b/packages/plugin-hermes/README.md @@ -0,0 +1,27 @@ +# @prettier/plugin-hermes + +> Prettier [Hermes](https://github.com/facebook/hermes/blob/main/README.md) plugin. + +## Install + +```bash +yarn add --dev prettier @prettier/plugin-hermes +``` + +## Usage + +Create or modify your [prettier configuration file](https://prettier.io/docs/en/configuration) to use the plugin: + +```json +{ + "overrides": [ + { + "files": ["**/*.{js.flow,js,mjs,cjs}"], + "options": { + "plugins": ["@prettier/plugin-hermes"], + "parser": "hermes" + } + } + ] +} +``` diff --git a/packages/plugin-hermes/index.js b/packages/plugin-hermes/index.js new file mode 100644 index 000000000..c4404cfd6 --- /dev/null +++ b/packages/plugin-hermes/index.js @@ -0,0 +1 @@ +export * as parsers from "../../src/language-js/parse/hermes.js"; diff --git a/packages/plugin-hermes/package.json b/packages/plugin-hermes/package.json new file mode 100644 index 000000000..5349a8ecf --- /dev/null +++ b/packages/plugin-hermes/package.json @@ -0,0 +1,22 @@ +{ + "name": "@prettier/plugin-hermes", + "version": "0.0.1", + "description": "Prettier Hermes plugin.", + "type": "module", + "exports": { + ".": { + "types": "./index.d.js", + "default": "./index.mjs" + }, + "./*": "./*" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/prettier/prettier.git", + "directory": "packages/plugin-hermes" + }, + "funding": "https://github.com/prettier/prettier?sponsor=1", + "homepage": "https://github.com/prettier/prettier/packages/plugin-hermes", + "author": "fisker Cheung ", + "license": "MIT" +} diff --git a/packages/plugin-oxc/README.md b/packages/plugin-oxc/README.md index cdcf9c1b2..2ece35448 100644 --- a/packages/plugin-oxc/README.md +++ b/packages/plugin-oxc/README.md @@ -1,6 +1,6 @@ # @prettier/plugin-oxc -> Prettier Oxc plugin. +> Prettier [Oxc](https://oxc.rs/) plugin. ## Install @@ -32,7 +32,3 @@ Create or modify your [prettier configuration file](https://prettier.io/docs/en/ ] } ``` - -## Related - -- [Oxc](https://oxc.rs/) - The JavaScript Oxidation Compiler diff --git a/scripts/build-website.js b/scripts/build-website.js index 2cd011d42..247d38d4e 100644 --- a/scripts/build-website.js +++ b/scripts/build-website.js @@ -43,7 +43,7 @@ async function buildPrettier() { }); try { - await runYarn("build", ["--package=prettier", "--clean", "--playground"], { + await runYarn("build", ["--clean", "--playground"], { cwd: PROJECT_ROOT, }); } finally { @@ -55,16 +55,30 @@ async function buildPrettier() { async function buildPlaygroundFiles() { const patterns = ["standalone.mjs", "plugins/*.mjs"]; - const files = await fastGlob(patterns, { + let files = await fastGlob(patterns, { cwd: PRETTIER_DIR, }); + files = files.map((fileName) => ({ + fileName, + file: path.join(PRETTIER_DIR, fileName), + dist: path.join(PLAYGROUND_PRETTIER_DIR, fileName), + })); + + // TODO: Support stable version + if (IS_PULL_REQUEST) { + const fileName = "plugins/hermes.mjs"; + files.push({ + fileName, + file: path.join(DIST_DIR, "plugin-hermes/index.mjs"), + dist: path.join(PLAYGROUND_PRETTIER_DIR, fileName), + }); + } + const packageManifest = { builtinPlugins: [], }; - for (const fileName of files) { - const file = path.join(PRETTIER_DIR, fileName); - const dist = path.join(PLAYGROUND_PRETTIER_DIR, fileName); + for (const { fileName, file, dist } of files) { await copyFile(file, dist); if (fileName === "standalone.mjs") { diff --git a/scripts/build/build-dependencies-license.js b/scripts/build/build-dependencies-license.js index b297f3d31..1a98edd2c 100644 --- a/scripts/build/build-dependencies-license.js +++ b/scripts/build/build-dependencies-license.js @@ -135,9 +135,7 @@ async function buildDependenciesLicense({ } const shouldBuildLicense = - !cliOptions.playground && - !cliOptions.files && - typeof cliOptions.minify !== "boolean"; + !cliOptions.files && typeof cliOptions.minify !== "boolean"; if (!shouldBuildLicense) { return { skipped: true }; diff --git a/scripts/build/build-javascript-module.js b/scripts/build/build-javascript-module.js index 4bed8dcb6..ba7d59e55 100644 --- a/scripts/build/build-javascript-module.js +++ b/scripts/build/build-javascript-module.js @@ -224,7 +224,7 @@ function getEsbuildOptions({ packageConfig, file, cliOptions }) { bundle: true, metafile: true, plugins: [ - esbuildPluginPrimitiveDefine(define), + esbuildPluginPrimitiveDefine({ ...define, ...buildOptions.define }), esbuildPluginEvaluate(), esbuildPluginStripNodeProtocol(), esbuildPluginReplaceModule({ diff --git a/scripts/build/build-package-json.js b/scripts/build/build-package-json.js index 0793033c2..b61ac2dcd 100644 --- a/scripts/build/build-package-json.js +++ b/scripts/build/build-package-json.js @@ -141,6 +141,34 @@ async function buildPluginOxcPackageJson({ packageConfig, file }) { ); } +async function buildPluginHermesPackageJson({ packageConfig, file }) { + const { distDirectory, files } = packageConfig; + const packageJson = await readJson(path.join(PROJECT_ROOT, file.input)); + const projectPackageJson = await readJson( + path.join(PROJECT_ROOT, "package.json"), + ); + + const overrides = { + engines: { + ...packageJson.engines, + // https://github.com/prettier/prettier/pull/13118#discussion_r922708068 + // Don't delete, event it's the same in package.json + node: `>=${PRODUCTION_MINIMAL_NODE_JS_VERSION}`, + }, + // Use `commonjs` since we may provide browser build in future. + type: "commonjs", + files: files.map(({ output: { file } }) => file).sort(), + dependencies: { + "hermes-parser": projectPackageJson.dependencies["hermes-parser"], + }, + }; + + await writeJson( + path.join(distDirectory, file.output.file), + Object.assign(pick(packageJson, keysToKeep), overrides), + ); +} + function pick(object, keys) { keys = new Set(keys); return Object.fromEntries( @@ -148,4 +176,8 @@ function pick(object, keys) { ); } -export { buildPluginOxcPackageJson, buildPrettierPackageJson }; +export { + buildPluginHermesPackageJson, + buildPluginOxcPackageJson, + buildPrettierPackageJson, +}; diff --git a/scripts/build/build.js b/scripts/build/build.js index d563bc477..c65c14d0b 100644 --- a/scripts/build/build.js +++ b/scripts/build/build.js @@ -60,10 +60,7 @@ async function buildFile({ packageConfig, file, cliOptions, results }) { if ( (cliOptions.files && !cliOptions.files.has(file.output.file)) || - (cliOptions.playground && - (file.output.format !== "esm" || - file.platform !== "universal" || - file.output.file === "doc.mjs")) + (cliOptions.playground && !file.playground) ) { console.log(status.SKIPPED); return; diff --git a/scripts/build/config.js b/scripts/build/config.js index 81c32cebe..6a2e368a2 100644 --- a/scripts/build/config.js +++ b/scripts/build/config.js @@ -7,6 +7,7 @@ import { copyFile, DIST_DIR, PROJECT_ROOT } from "../utils/index.js"; import buildDependenciesLicense from "./build-dependencies-license.js"; import buildJavascriptModule from "./build-javascript-module.js"; import { + buildPluginHermesPackageJson, buildPluginOxcPackageJson, buildPrettierPackageJson, } from "./build-package-json.js"; @@ -738,6 +739,7 @@ const universalFiles = [...nonPluginUniversalFiles, ...pluginFiles].flatMap( isPlugin, build: buildJavascriptModule, kind: "javascript", + playground: output.format === "esm" && outputBaseName !== "doc", })), getTypesFileConfig({ input, outputBaseName, isPlugin }), ]; @@ -998,4 +1000,99 @@ export default [ })), ], }, + { + packageName: "@prettier/plugin-hermes", + distDirectory: path.join(DIST_DIR, "plugin-hermes"), + files: [ + ...[ + { + input: "packages/plugin-hermes/index.js", + addDefaultExport: true, + replaceModule: [ + { + module: require.resolve("hermes-parser/dist/HermesParser.js"), + process(text) { + text = + 'const Buffer = globalThis.Buffer ?? require("buffer/").Buffer;' + + text; + return text; + }, + }, + { + module: require.resolve("hermes-parser/dist/HermesParserWASM.js"), + process(text) { + text = text.replaceAll("process.argv", "[]"); + text = text.replaceAll('require("fs")', "undefined"); + text = text.replaceAll('require("path")', "undefined"); + text = + 'const Buffer = globalThis.Buffer ?? require("buffer/").Buffer;' + + text; + + return text; + }, + }, + ], + }, + ].flatMap((file) => { + let { input, output, outputBaseName, ...buildOptions } = file; + + outputBaseName ??= path.basename(input, path.extname(input)); + const format = input.endsWith(".cjs") ? "cjs" : "esm"; + + return [ + { + input, + output: { + format, + file: `${outputBaseName}${extensions[format]}`, + }, + platform: "universal", + buildOptions: { + addDefaultExport: true, + ...buildOptions, + }, + isPlugin: true, + build: buildJavascriptModule, + playground: true, + kind: "javascript", + }, + getTypesFileConfig({ input, outputBaseName, isPlugin: true }), + ]; + }), + ...[ + { + input: "packages/plugin-hermes/package.json", + output: { + file: "package.json", + format: "json", + }, + build: buildPluginHermesPackageJson, + }, + { + input: "packages/plugin-hermes/README.md", + output: { + file: "README.md", + }, + build: copyFileBuilder, + }, + { + input: "LICENSE", + output: { + file: "LICENSE", + }, + build: copyFileBuilder, + }, + { + output: { + file: "THIRD-PARTY-NOTICES.md", + }, + build: buildDependenciesLicense, + }, + ].map((file) => ({ + ...file, + output: { file: file.input, ...file.output }, + kind: "meta", + })), + ], + }, ]; diff --git a/src/language-js/comments/printer-methods.js b/src/language-js/comments/printer-methods.js index 9884f4b78..5d43ccea1 100644 --- a/src/language-js/comments/printer-methods.js +++ b/src/language-js/comments/printer-methods.js @@ -44,6 +44,7 @@ function getCommentChildNodes(node, options) { if ( (options.parser === "typescript" || options.parser === "flow" || + options.parser === "hermes" || options.parser === "acorn" || options.parser === "oxc" || options.parser === "oxc-ts" || @@ -81,7 +82,7 @@ function willPrintOwnComments(path) { } function isGap(text, { parser }) { - if (parser === "flow" || parser === "babel-flow") { + if (parser === "flow" || parser === "hermes" || parser === "babel-flow") { // Example: (a /* b */ /* : c */) // gap ^^^^ text = text.replaceAll(/[\s(]/gu, ""); diff --git a/src/language-js/parse/flow.js b/src/language-js/parse/flow.js index ebcfec35f..aa1d37a02 100644 --- a/src/language-js/parse/flow.js +++ b/src/language-js/parse/flow.js @@ -27,10 +27,14 @@ const parseOptions = { }; function createParseError(error) { - const { - message, - loc: { start, end }, - } = error; + const { message, loc } = error; + + /* c8 ignore next 3 */ + if (!loc) { + return error; + } + + const { start, end } = loc; return createError(message, { loc: { diff --git a/src/language-js/parse/hermes.js b/src/language-js/parse/hermes.js new file mode 100644 index 000000000..dd32db3a0 --- /dev/null +++ b/src/language-js/parse/hermes.js @@ -0,0 +1,51 @@ +import { parse as hermesParse } from "hermes-parser"; +import createError from "../../common/parser-create-error.js"; +import postprocess from "./postprocess/index.js"; +import createParser from "./utils/create-parser.js"; + +function createParseError(error) { + let { message, loc } = error; + + if (!loc) { + return error; + } + + const { line, column } = loc; + + message = message.split("\n")[0]; + + const suffix = `(${line}:${column})`; + if (message.endsWith(suffix)) { + message = message.slice(0, -suffix.length); + } + message = message.trim(); + + return createError(message, { + loc: { + start: { line, column }, + }, + cause: error, + }); +} + +const parseOptions = { + flow: "all", + babel: false, + // Not supported yet + enableExperimentalFlowMatchSyntax: false, + tokens: false, + allowReturnOutsideFunction: true, +}; + +async function parse(text /*, options*/) { + let ast; + try { + ast = await hermesParse(text, parseOptions); + } catch (error) { + throw createParseError(error); + } + + return postprocess(ast, { text, parser: "hermes" }); +} + +export const hermes = createParser(parse); diff --git a/src/language-js/parse/oxc.js b/src/language-js/parse/oxc.js index 3b96e6d2e..79ca53dc7 100644 --- a/src/language-js/parse/oxc.js +++ b/src/language-js/parse/oxc.js @@ -8,6 +8,11 @@ import jsxRegexp from "./utils/jsx-regexp.evaluate.js"; import { getSourceType } from "./utils/source-types.js"; function createParseError(error, { text }) { + /* c8 ignore next 3 */ + if (!error?.labels?.[0]) { + return error; + } + const { message, labels: [{ start: startIndex, end: endIndex }], diff --git a/src/language-js/parse/postprocess/index.js b/src/language-js/parse/postprocess/index.js index 69dfe1069..b99c33f55 100644 --- a/src/language-js/parse/postprocess/index.js +++ b/src/language-js/parse/postprocess/index.js @@ -134,10 +134,11 @@ function postprocess(ast, options) { break; case "TemplateElement": - // `flow`, `typescript`, and `oxc`(with `{astType: 'ts'}`) follows the `espree` style positions + // `flow`, `hermes`, `typescript`, and `oxc`(with `{astType: 'ts'}`) follows the `espree` style positions // https://github.com/eslint/js/blob/5826877f7b33548e5ba984878dd4a8eac8448f87/packages/espree/lib/espree.js#L213 if ( parser === "flow" || + parser === "hermes" || parser === "espree" || parser === "typescript" || (parser === "oxc" && options.oxcAstType === "ts") @@ -215,6 +216,13 @@ function postprocess(ast, options) { delete node.members; } break; + + // https://github.com/facebook/hermes/issues/1712 + case "ImportExpression": + if (parser === "hermes" && node.attributes && !node.options) { + node.options = node.attributes; + } + break; } /* c8 ignore next 3 */ diff --git a/src/language-js/parse/typescript.js b/src/language-js/parse/typescript.js index c0a555112..987ff56e1 100644 --- a/src/language-js/parse/typescript.js +++ b/src/language-js/parse/typescript.js @@ -30,15 +30,14 @@ const baseParseOptions = { }; function createParseError(error) { + const { message, location } = error; + /* c8 ignore next 3 -- not a parse error */ - if (!error?.location) { + if (!location) { return error; } - const { - message, - location: { start, end }, - } = error; + const { start, end } = location; return createError(message, { loc: { diff --git a/src/language-js/parse/utils/create-babel-parse-error.js b/src/language-js/parse/utils/create-babel-parse-error.js index cbee21de4..3fe3868e9 100644 --- a/src/language-js/parse/utils/create-babel-parse-error.js +++ b/src/language-js/parse/utils/create-babel-parse-error.js @@ -1,13 +1,16 @@ import createError from "../../../common/parser-create-error.js"; function createBabelParseError(error) { + let { message, loc, reasonCode } = error; + + /* c8 ignore next 3 */ + if (!loc) { + return error; + } + // babel error prints (line:column) with cols that are zero indexed // so we need our custom error - let { - message, - loc: { line, column }, - reasonCode, - } = error; + const { line, column } = loc; let cause = error; if (reasonCode === "MissingPlugin" || reasonCode === "MissingOneOfPlugins") { diff --git a/src/main/range-util.js b/src/main/range-util.js index b4cb9acd6..ba628681b 100644 --- a/src/main/range-util.js +++ b/src/main/range-util.js @@ -170,6 +170,7 @@ function isSourceElement(opts, node, parentNode) { } switch (opts.parser) { case "flow": + case "hermes": case "babel": case "babel-flow": case "babel-ts": diff --git a/tests/config/run-format-test.js b/tests/config/run-format-test.js index 174f0b639..977611320 100644 --- a/tests/config/run-format-test.js +++ b/tests/config/run-format-test.js @@ -103,6 +103,23 @@ const oxcTsDisabledTests = new Set( "typescript/decorators/abstract-method.ts", ].map((file) => path.join(__dirname, "../format", file)), ); +const hermesDisabledTests = new Set([ + ...commentClosureTypecaseTests, + ...[ + // Need update L183 to use `replaceAll` + // https://app.unpkg.com/hermes-parser@0.28.1/files/dist/HermesASTAdapter.js + "js/call/first-argument-expansion/expression-2nd-arg.js", + "js/directives/escaped.js", + // Not supported + "flow/comments", + "flow-repo/union_new", + // Wrongly parsed + "js/sloppy-mode/function-declaration-in-if.js", + // Wrong location of `Property.value` + "js/classes/method.js", + "js/comments/function-declaration.js", + ].map((file) => path.join(__dirname, "../format", file)), +]); const isUnstable = (filename, options) => { const testFunction = unstableTests.get(filename); @@ -274,6 +291,14 @@ function runFormatTest(fixtures, parsers, options) { allParsers.push("babel-flow"); } + if ( + parsers.includes("flow") && + !parsers.includes("hermes") && + !hermesDisabledTests.has(dirname) + ) { + allParsers.push("hermes"); + } + if (parsers.includes("babel") && !parsers.includes("__babel_estree")) { allParsers.push("__babel_estree"); } @@ -314,6 +339,7 @@ function runFormatTest(fixtures, parsers, options) { (currentParser === "meriyah" && meriyahDisabledTests.has(filename)) || (currentParser === "oxc" && oxcDisabledTests.has(filename)) || (currentParser === "oxc-ts" && oxcTsDisabledTests.has(filename)) || + (currentParser === "hermes" && hermesDisabledTests.has(filename)) || (currentParser === "babel-ts" && babelTsDisabledTests.has(filename)) ) { continue; @@ -487,9 +513,11 @@ function shouldSkipEolTest(code, options) { async function parse(source, options) { const prettier = await getPrettier(); - const { ast } = await prettier.__debug.parse(source, options, { - massage: true, - }); + const { ast } = await ensurePromise( + prettier.__debug.parse(source, await loadPlugins(options), { + massage: true, + }), + ); return ast; } @@ -534,16 +562,15 @@ const insertCursor = (text, cursorOffset) => text.slice(cursorOffset) : text; async function format(originalText, originalOptions) { - let { text: input, options } = replacePlaceholders( + const { text: input, options } = replacePlaceholders( originalText, originalOptions, ); - options = await loadPlugins(options); const inputWithCursor = insertCursor(input, options.cursorOffset); const prettier = await getPrettier(); const { formatted: output, cursorOffset } = await ensurePromise( - prettier.formatWithCursor(input, options), + prettier.formatWithCursor(input, await loadPlugins(options)), ); const outputWithCursor = insertCursor(output, cursorOffset); const eolVisualizedOutput = visualizeEndOfLine(outputWithCursor); @@ -561,13 +588,20 @@ async function format(originalText, originalOptions) { }; } +const externalPlugins = new Map([ + ["oxc", "plugin-oxc"], + ["oxc-ts", "plugin-oxc"], + ["hermes", "plugin-hermes"], +]); async function loadPlugins(options) { - if (options.parser === "oxc" || options.parser === "oxc-ts") { + const { parser } = options; + if (externalPlugins.has(options.parser)) { const plugins = options.plugins ?? []; + const pluginName = externalPlugins.get(parser); const url = new URL( isProduction - ? "../../dist/plugin-oxc/index.mjs" - : "../../packages/plugin-oxc/index.js", + ? `../../dist/${pluginName}/index.mjs` + : `../../packages/${pluginName}/index.js`, import.meta.url, ); plugins.push(TEST_STANDALONE ? await import(url) : url); diff --git a/tests/format/flow-repo/binding/__snapshots__/format.test.js.snap b/tests/format/flow-repo/binding/__snapshots__/format.test.js.snap index ea31e0a67..ecb4d1f63 100644 --- a/tests/format/flow-repo/binding/__snapshots__/format.test.js.snap +++ b/tests/format/flow-repo/binding/__snapshots__/format.test.js.snap @@ -1,5 +1,18 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`const.js [hermes] format 1`] = ` +"invalid operand in update operation (4:0) + 2 | + 3 | // errors: const cannot be reassigned +> 4 | x++; + 5 | x--; + 6 | x += 0; + 7 | x -= 0; +Cause: invalid operand in update operation (4:0) +x++; +^" +`; + exports[`const.js format 1`] = ` ====================================options===================================== parsers: ["flow"] @@ -66,6 +79,23 @@ for (const { baz } of bazzes) { ================================================================================ `; +exports[`rebinding.js [hermes] format 1`] = ` +"Identifier 'A' is already declared (53:8) + 51 | function class_class() { + 52 | class A {} +> 53 | class A {} // error: name already bound + | ^ + 54 | } + 55 | + 56 | function class_let() { +Cause: Identifier 'A' is already declared (53:8) + class A {} // error: name already bound + ^ +note: previous declaration (52:8) + class A {} + ^" +`; + exports[`rebinding.js format 1`] = ` ====================================options===================================== parsers: ["flow"] @@ -472,6 +502,23 @@ function fn_params_clash_fn_binding(x, y) { ================================================================================ `; +exports[`scope.js [hermes] format 1`] = ` +"Identifier 'a' is already declared (19:10) + 17 | break; + 18 | case "bar": +> 19 | let a = ""; // error: a already bound in switch + | ^ + 20 | break; + 21 | } + 22 | } +Cause: Identifier 'a' is already declared (19:10) + let a = ""; // error: a already bound in switch + ^ +note: previous declaration (15:10) + let a = ""; // ok: local to switch + ^" +`; + exports[`scope.js format 1`] = ` ====================================options===================================== parsers: ["flow"] diff --git a/tests/format/flow-repo/binding/format.test.js b/tests/format/flow-repo/binding/format.test.js index 55c339883..cf85ecbd1 100644 --- a/tests/format/flow-repo/binding/format.test.js +++ b/tests/format/flow-repo/binding/format.test.js @@ -1 +1,3 @@ -runFormatTest(import.meta, ["flow"]); +runFormatTest(import.meta, ["flow"], { + errors: { hermes: ["const.js", "rebinding.js", "scope.js"] }, +}); diff --git a/tests/format/flow-repo/esproposal_decorators.ignore/__snapshots__/format.test.js.snap b/tests/format/flow-repo/esproposal_decorators.ignore/__snapshots__/format.test.js.snap index f995a5198..f2a6969b7 100644 --- a/tests/format/flow-repo/esproposal_decorators.ignore/__snapshots__/format.test.js.snap +++ b/tests/format/flow-repo/esproposal_decorators.ignore/__snapshots__/format.test.js.snap @@ -1,5 +1,18 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`test.js [hermes] format 1`] = ` +"unrecognized character '@' (3:0) + 1 | /* @flow */ + 2 | +> 3 | @decorator4 + 4 | class Foo { + 5 | @decorator1 + 6 | method1() {} +Cause: unrecognized character '@' (3:0) +@decorator4 +^" +`; + exports[`test.js format 1`] = ` ====================================options===================================== parsers: ["flow"] diff --git a/tests/format/flow-repo/esproposal_decorators.ignore/format.test.js b/tests/format/flow-repo/esproposal_decorators.ignore/format.test.js index 55c339883..34b3a8537 100644 --- a/tests/format/flow-repo/esproposal_decorators.ignore/format.test.js +++ b/tests/format/flow-repo/esproposal_decorators.ignore/format.test.js @@ -1 +1,5 @@ -runFormatTest(import.meta, ["flow"]); +runFormatTest(import.meta, ["flow"], { + errors: { + hermes:["test.js"], + }, +}); diff --git a/tests/format/flow-repo/esproposal_decorators.warn/__snapshots__/format.test.js.snap b/tests/format/flow-repo/esproposal_decorators.warn/__snapshots__/format.test.js.snap index f995a5198..f2a6969b7 100644 --- a/tests/format/flow-repo/esproposal_decorators.warn/__snapshots__/format.test.js.snap +++ b/tests/format/flow-repo/esproposal_decorators.warn/__snapshots__/format.test.js.snap @@ -1,5 +1,18 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`test.js [hermes] format 1`] = ` +"unrecognized character '@' (3:0) + 1 | /* @flow */ + 2 | +> 3 | @decorator4 + 4 | class Foo { + 5 | @decorator1 + 6 | method1() {} +Cause: unrecognized character '@' (3:0) +@decorator4 +^" +`; + exports[`test.js format 1`] = ` ====================================options===================================== parsers: ["flow"] diff --git a/tests/format/flow-repo/esproposal_decorators.warn/format.test.js b/tests/format/flow-repo/esproposal_decorators.warn/format.test.js index 55c339883..c1ee18c7b 100644 --- a/tests/format/flow-repo/esproposal_decorators.warn/format.test.js +++ b/tests/format/flow-repo/esproposal_decorators.warn/format.test.js @@ -1 +1,2 @@ -runFormatTest(import.meta, ["flow"]); +runFormatTest(import.meta, ["flow"], {errors: { hermes: ["test.js"] } +}); diff --git a/tests/format/flow-repo/find-module/__snapshots__/format.test.js.snap b/tests/format/flow-repo/find-module/__snapshots__/format.test.js.snap index ea16a6e85..7c09f6cc8 100644 --- a/tests/format/flow-repo/find-module/__snapshots__/format.test.js.snap +++ b/tests/format/flow-repo/find-module/__snapshots__/format.test.js.snap @@ -14,6 +14,21 @@ module.exports = 0; ================================================================================ `; +exports[`test.js [hermes] format 1`] = ` +"Identifier 'x' is already declared (4:7) + 2 | (x: string); + 3 | +> 4 | import x from './req'; + | ^ + 5 | +Cause: Identifier 'x' is already declared (4:7) +import x from './req'; + ^ +note: previous declaration (1:4) +var x = require('./req'); + ^" +`; + exports[`test.js format 1`] = ` ====================================options===================================== parsers: ["flow"] diff --git a/tests/format/flow-repo/find-module/format.test.js b/tests/format/flow-repo/find-module/format.test.js index 55c339883..a96332ef8 100644 --- a/tests/format/flow-repo/find-module/format.test.js +++ b/tests/format/flow-repo/find-module/format.test.js @@ -1 +1 @@ -runFormatTest(import.meta, ["flow"]); +runFormatTest(import.meta, ["flow"], { errors: { hermes: ["test.js"] } }); diff --git a/tests/format/flow-repo/type_only_vars/__snapshots__/format.test.js.snap b/tests/format/flow-repo/type_only_vars/__snapshots__/format.test.js.snap index f263473f2..9ad539673 100644 --- a/tests/format/flow-repo/type_only_vars/__snapshots__/format.test.js.snap +++ b/tests/format/flow-repo/type_only_vars/__snapshots__/format.test.js.snap @@ -38,6 +38,23 @@ module.exports = { ================================================================================ `; +exports[`bad_shadowing.js [hermes] format 1`] = ` +"Identifier 'A' is already declared (13:4) + 11 | + 12 | // These string types should confict with the imported types +> 13 | var A: string = "Hello"; + | ^ + 14 | var Foo: string = "Goodbye"; + 15 | var Baz: string = "Go away please"; + 16 | +Cause: Identifier 'A' is already declared (13:4) +var A: string = "Hello"; + ^~~~~~~~~ +note: previous declaration (5:14) +import typeof A from "./A.js"; + ^" +`; + exports[`bad_shadowing.js format 1`] = ` ====================================options===================================== parsers: ["flow"] @@ -86,6 +103,23 @@ var duck: string = "quack"; ================================================================================ `; +exports[`good_shadowing.js [hermes] format 1`] = ` +"Identifier 'A' is already declared (8:4) + 6 | import type {Foo, Bar as Baz} from "./A.js"; + 7 | +> 8 | var A = require('./A.js'); + | ^ + 9 | var Foo = A.Foo; + 10 | var Baz = A.Bar; + 11 | +Cause: Identifier 'A' is already declared (8:4) +var A = require('./A.js'); + ^ +note: previous declaration (5:14) +import typeof A from "./A.js"; + ^" +`; + exports[`good_shadowing.js format 1`] = ` ====================================options===================================== parsers: ["flow"] diff --git a/tests/format/flow-repo/type_only_vars/format.test.js b/tests/format/flow-repo/type_only_vars/format.test.js index 55c339883..ff1381d27 100644 --- a/tests/format/flow-repo/type_only_vars/format.test.js +++ b/tests/format/flow-repo/type_only_vars/format.test.js @@ -1 +1,5 @@ -runFormatTest(import.meta, ["flow"]); +runFormatTest(import.meta, ["flow"], { + errors: { + hermes: ["bad_shadowing.js", "good_shadowing.js"], + }, +}); diff --git a/tests/format/flow-repo/unary/__snapshots__/format.test.js.snap b/tests/format/flow-repo/unary/__snapshots__/format.test.js.snap index 73d4a2d46..37dcaea5d 100644 --- a/tests/format/flow-repo/unary/__snapshots__/format.test.js.snap +++ b/tests/format/flow-repo/unary/__snapshots__/format.test.js.snap @@ -50,6 +50,20 @@ function x4(y: string): boolean { ================================================================================ `; +exports[`update.js [hermes] format 1`] = ` +"invalid operand in update operation (31:4) + 29 | function() { + 30 | const y = 123; +> 31 | y++; // error, can't update const + | ^ + 32 | y--; // error, can't update const + 33 | }, + 34 | +Cause: invalid operand in update operation (31:4) + y++; // error, can't update const + ^" +`; + exports[`update.js format 1`] = ` ====================================options===================================== parsers: ["flow"] diff --git a/tests/format/flow-repo/unary/format.test.js b/tests/format/flow-repo/unary/format.test.js index 55c339883..3dd8467e7 100644 --- a/tests/format/flow-repo/unary/format.test.js +++ b/tests/format/flow-repo/unary/format.test.js @@ -1 +1,5 @@ -runFormatTest(import.meta, ["flow"]); +runFormatTest(import.meta, ["flow"], { + errors: { + hermes: ["update.js"], + }, +}); diff --git a/tests/format/flow/as-satisfies-expression/__snapshots__/format.test.js.snap b/tests/format/flow/as-satisfies-expression/__snapshots__/format.test.js.snap index 2fec649bb..271ca3ba3 100644 --- a/tests/format/flow/as-satisfies-expression/__snapshots__/format.test.js.snap +++ b/tests/format/flow/as-satisfies-expression/__snapshots__/format.test.js.snap @@ -428,6 +428,20 @@ exports[`satisfies.js [babel-flow] format 1`] = ` Cause: Unexpected token, expected "type" (32:7)" `; +exports[`satisfies.js [hermes] format 1`] = ` +"';' expected (3:12) + 1 | // @flow + 2 | +> 3 | const x = y satisfies T; + | ^ + 4 | + 5 | // demonstrating how "satisfies" expression can be practically used as expression statement. + 6 | const _ = (type: 'foo' | 'bar') => { +Cause: ';' expected (3:12) +const x = y satisfies T; + ^" +`; + exports[`satisfies.js format 1`] = ` ====================================options===================================== parsers: ["flow"] @@ -532,6 +546,19 @@ exports[`ternary.js [babel-flow] format 1`] = ` Cause: Unexpected token, expected "," (28:31)" `; +exports[`ternary.js [hermes] format 1`] = ` +"invalid assignment left-hand side (3:0) + 1 | // @flow + 2 | +> 3 | foo = (coooooooooooooooooooooooooooooooooooooooooooooooooooond + 4 | ? baaaaaaaaaaaaaaaaaaaaar + 5 | : baaaaaaaaaaaaaaaaaaaaaz) as Fooooooooooo; + 6 | +Cause: invalid assignment left-hand side (3:0) +foo = (coooooooooooooooooooooooooooooooooooooooooooooooooooond +^~~" +`; + exports[`ternary.js format 1`] = ` ====================================options===================================== parsers: ["flow"] diff --git a/tests/format/flow/as-satisfies-expression/format.test.js b/tests/format/flow/as-satisfies-expression/format.test.js index 0f019e561..685994e60 100644 --- a/tests/format/flow/as-satisfies-expression/format.test.js +++ b/tests/format/flow/as-satisfies-expression/format.test.js @@ -1 +1,6 @@ -runFormatTest(import.meta, ["flow"], { errors: { "babel-flow": true } }); +runFormatTest(import.meta, ["flow"], { + errors: { + "babel-flow": true, + hermes: ["satisfies.js", "ternary.js"], + }, +}); diff --git a/tests/format/flow/assignments/__snapshots__/format.test.js.snap b/tests/format/flow/assignments/__snapshots__/format.test.js.snap index bebae9e7c..72bf30b77 100644 --- a/tests/format/flow/assignments/__snapshots__/format.test.js.snap +++ b/tests/format/flow/assignments/__snapshots__/format.test.js.snap @@ -92,10 +92,10 @@ printWidth: 80 const map: Map> = new Map(); -const map: Map = +const ma2: Map = new Map(); -const map: Map> = new Map(); +const ma3: Map> = new Map(); =====================================output===================================== const map: Map< @@ -103,10 +103,10 @@ const map: Map< Map, > = new Map(); -const map: Map = +const ma2: Map = new Map(); -const map: Map> = new Map(); +const ma3: Map> = new Map(); ================================================================================ `; diff --git a/tests/format/flow/assignments/issue-10850.js b/tests/format/flow/assignments/issue-10850.js index c9408527e..edadc49d2 100644 --- a/tests/format/flow/assignments/issue-10850.js +++ b/tests/format/flow/assignments/issue-10850.js @@ -1,7 +1,7 @@ const map: Map> = new Map(); -const map: Map = +const ma2: Map = new Map(); -const map: Map> = new Map(); +const ma3: Map> = new Map(); diff --git a/tests/format/flow/await/__snapshots__/format.test.js.snap b/tests/format/flow/await/__snapshots__/format.test.js.snap index 78a1b8c12..d953c8ba1 100644 --- a/tests/format/flow/await/__snapshots__/format.test.js.snap +++ b/tests/format/flow/await/__snapshots__/format.test.js.snap @@ -12,6 +12,19 @@ exports[`await-keywords.js [babel-flow] format 1`] = ` Cause: 'await' is only allowed within async functions and at the top levels of modules. (12:6)" `; +exports[`await-keywords.js [hermes] format 1`] = ` +"'await' not in an async function (2:6) + 1 | export class C1 { +> 2 | p = await (0); + | ^ + 3 | } + 4 | + 5 | await (0); +Cause: 'await' not in an async function (2:6) + p = await (0); + ^~~~~~~~~" +`; + exports[`await-keywords.js format 1`] = ` ====================================options===================================== parsers: ["flow"] diff --git a/tests/format/flow/await/format.test.js b/tests/format/flow/await/format.test.js index 37e20642d..6ed9cd960 100644 --- a/tests/format/flow/await/format.test.js +++ b/tests/format/flow/await/format.test.js @@ -1,3 +1,6 @@ runFormatTest(import.meta, ["flow"], { - errors: { "babel-flow": ["await-keywords.js"] }, + errors: { + "babel-flow": ["await-keywords.js"], + hermes: ["await-keywords.js"], + }, }); diff --git a/tests/format/flow/implements/__snapshots__/format.test.js.snap b/tests/format/flow/implements/__snapshots__/format.test.js.snap index a86e0ccd0..eb64224a8 100644 --- a/tests/format/flow/implements/__snapshots__/format.test.js.snap +++ b/tests/format/flow/implements/__snapshots__/format.test.js.snap @@ -7,17 +7,17 @@ printWidth: 80 | printWidth =====================================input====================================== class A implements B {} -class A implements B, C {} -declare class A implements B {} -declare class A mixins B implements C {} -declare class A implements B, C {} +class B implements B, C {} +declare class C implements B {} +declare class D mixins B implements C {} +declare class E implements B, C {} =====================================output===================================== class A implements B {} -class A implements B, C {} -declare class A implements B {} -declare class A mixins B implements C {} -declare class A implements B, C {} +class B implements B, C {} +declare class C implements B {} +declare class D mixins B implements C {} +declare class E implements B, C {} ================================================================================ `; diff --git a/tests/format/flow/implements/implements.js b/tests/format/flow/implements/implements.js index 32acd7162..1fca06f8f 100644 --- a/tests/format/flow/implements/implements.js +++ b/tests/format/flow/implements/implements.js @@ -1,5 +1,5 @@ class A implements B {} -class A implements B, C {} -declare class A implements B {} -declare class A mixins B implements C {} -declare class A implements B, C {} +class B implements B, C {} +declare class C implements B {} +declare class D mixins B implements C {} +declare class E implements B, C {} diff --git a/tests/format/flow/import-type-specifier/__snapshots__/format.test.js.snap b/tests/format/flow/import-type-specifier/__snapshots__/format.test.js.snap index 8f692d214..7791cc289 100644 --- a/tests/format/flow/import-type-specifier/__snapshots__/format.test.js.snap +++ b/tests/format/flow/import-type-specifier/__snapshots__/format.test.js.snap @@ -14,7 +14,7 @@ import { Foo, type Baz } from "../module"; import type {} from 'foo'; import type {somethingSuperLongsomethingSuperLong} from 'somethingSuperLongsomethingSuperLongsomethingSuperLong' -import type {a, somethingSuperLongsomethingSuperLong} from 'somethingSuperLongsomethingSuperLongsomethingSuperLong' +import type {a, somethingSuperLongsomethingSuperLon2} from 'somethingSuperLongsomethingSuperLongsomethingSuperLong' import transformRouterContext, { type TransformedContextRouter } from '../../helpers/transformRouterContext'; @@ -29,7 +29,7 @@ import type {} from "foo"; import type { somethingSuperLongsomethingSuperLong } from "somethingSuperLongsomethingSuperLongsomethingSuperLong"; import type { a, - somethingSuperLongsomethingSuperLong, + somethingSuperLongsomethingSuperLon2, } from "somethingSuperLongsomethingSuperLongsomethingSuperLong"; import transformRouterContext, { diff --git a/tests/format/flow/import-type-specifier/test.js b/tests/format/flow/import-type-specifier/test.js index bcd4ecde4..12acb0424 100644 --- a/tests/format/flow/import-type-specifier/test.js +++ b/tests/format/flow/import-type-specifier/test.js @@ -6,6 +6,6 @@ import { Foo, type Baz } from "../module"; import type {} from 'foo'; import type {somethingSuperLongsomethingSuperLong} from 'somethingSuperLongsomethingSuperLongsomethingSuperLong' -import type {a, somethingSuperLongsomethingSuperLong} from 'somethingSuperLongsomethingSuperLongsomethingSuperLong' +import type {a, somethingSuperLongsomethingSuperLon2} from 'somethingSuperLongsomethingSuperLongsomethingSuperLong' import transformRouterContext, { type TransformedContextRouter } from '../../helpers/transformRouterContext'; diff --git a/tests/format/flow/import/__snapshots__/format.test.js.snap b/tests/format/flow/import/__snapshots__/format.test.js.snap index 18f52fe31..0982ae7ca 100644 --- a/tests/format/flow/import/__snapshots__/format.test.js.snap +++ b/tests/format/flow/import/__snapshots__/format.test.js.snap @@ -8,18 +8,32 @@ printWidth: 80 =====================================input====================================== // @flow import { foo as as } from "foo"; -import { as as as } from "foo"; import { as as foo } from "foo"; =====================================output===================================== // @flow import { foo as as } from "foo"; -import { as as as } from "foo"; import { as as foo } from "foo"; ================================================================================ `; +exports[`import-as-as2.js format 1`] = ` +====================================options===================================== +parsers: ["flow"] +printWidth: 80 + | printWidth +=====================================input====================================== +// @flow +import { as as as } from "foo"; + +=====================================output===================================== +// @flow +import { as as as } from "foo"; + +================================================================================ +`; + exports[`type-import-as-as.js format 1`] = ` ====================================options===================================== parsers: ["flow"] diff --git a/tests/format/flow/import/import-as-as.js b/tests/format/flow/import/import-as-as.js index 5f3bb6185..aa7a4986f 100644 --- a/tests/format/flow/import/import-as-as.js +++ b/tests/format/flow/import/import-as-as.js @@ -1,4 +1,3 @@ // @flow import { foo as as } from "foo"; -import { as as as } from "foo"; import { as as foo } from "foo"; diff --git a/tests/format/flow/import/import-as-as2.js b/tests/format/flow/import/import-as-as2.js new file mode 100644 index 000000000..cec7de343 --- /dev/null +++ b/tests/format/flow/import/import-as-as2.js @@ -0,0 +1,2 @@ +// @flow +import { as as as } from "foo"; diff --git a/tests/format/flow/ternary/__snapshots__/format.test.js.snap b/tests/format/flow/ternary/__snapshots__/format.test.js.snap index 31c7b769b..8a42a3673 100644 --- a/tests/format/flow/ternary/__snapshots__/format.test.js.snap +++ b/tests/format/flow/ternary/__snapshots__/format.test.js.snap @@ -58,3 +58,51 @@ exports[`arrows.js [flow] format 1`] = ` 8 | 9 | (a ? (b = c) : d => e : f); // a ? ((b = c): d => e) : f" `; + +exports[`arrows.js [hermes] format 1`] = ` +====================================options===================================== +parsers: ["flow"] +printWidth: 80 + | printWidth +=====================================input====================================== +// Test cases from babel +// ref: https://github.com/babel/babel/blob/614b48678095746b83bbe517c4d6b30ba8cd5c04/packages/babel-parser/test/fixtures/flow/arrows-in-ternaries/issue-13644/input.js +// \`flow\` cannot parse below codes +// ref: https://github.com/facebook/flow/issues/8731 + +(a ? (b = c) : d => e); // a ? (b = c) : (d => e) +(a ? (b += c) : d => e); // a ? (b += c) : (d => e) + +(a ? (b = c) : d => e : f); // a ? ((b = c): d => e) : f +(a ? (b += c) : d => e : f); // ((a ? (b += c) : (d => e)) : f) + +(a ? b => (c = d) : e => f); // a ? (b => (c = d)) : (e => f) +(a ? b => (c += d) : e => f); // a ? (b => (c += d)) : (e => f) + +(a ? b => (c = d) : e => f : g); // a ? (b => ((c = d): e => f)) : g +(a ? b => (c += d) : e => f : g); // ((a ? (b => (c += d)) : (e => f)) : g) + +=====================================output===================================== +// Test cases from babel +// ref: https://github.com/babel/babel/blob/614b48678095746b83bbe517c4d6b30ba8cd5c04/packages/babel-parser/test/fixtures/flow/arrows-in-ternaries/issue-13644/input.js +// \`flow\` cannot parse below codes +// ref: https://github.com/facebook/flow/issues/8731 + +a ? (b = c) : (d) => e; // a ? (b = c) : (d => e) +a ? (b += c) : (d) => e; // a ? (b += c) : (d => e) + +a ? (b = c): d => e : f; // a ? ((b = c): d => e) : f +a ? (): d => e : f; // ((a ? (b += c) : (d => e)) : f) + +a ? (b) => (c = d) : (e) => f; // a ? (b => (c = d)) : (e => f) +a ? (b) => (c += d) : (e) => f; // a ? (b => (c += d)) : (e => f) + +a + ? (b) => + (c = d): e => + f + : g; // a ? (b => ((c = d): e => f)) : g +a ? (b) => (): e => f : g; // ((a ? (b => (c += d)) : (e => f)) : g) + +================================================================================ +`; diff --git a/tests/format/flow/type-parameters/flow-only/__snapshots__/format.test.js.snap b/tests/format/flow/type-parameters/flow-only/__snapshots__/format.test.js.snap index baba602db..d33c870a3 100644 --- a/tests/format/flow/type-parameters/flow-only/__snapshots__/format.test.js.snap +++ b/tests/format/flow/type-parameters/flow-only/__snapshots__/format.test.js.snap @@ -51,7 +51,7 @@ class C{} type T = X; function f(): void {} (x: T) => {} -class C{} +class D{} =====================================output===================================== // Simple @@ -64,7 +64,7 @@ class C {} type T = X; function f(): void {} (x: T) => {}; -class C {} +class D {} ================================================================================ `; diff --git a/tests/format/flow/type-parameters/flow-only/const-type-params.js b/tests/format/flow/type-parameters/flow-only/const-type-params.js index fdd2fd9ba..27e868f1b 100644 --- a/tests/format/flow/type-parameters/flow-only/const-type-params.js +++ b/tests/format/flow/type-parameters/flow-only/const-type-params.js @@ -8,4 +8,4 @@ class C{} type T = X; function f(): void {} (x: T) => {} -class C{} +class D{} diff --git a/tests/format/js/assignment/__snapshots__/format.test.js.snap b/tests/format/js/assignment/__snapshots__/format.test.js.snap index 30a1a6035..8e102fd63 100644 --- a/tests/format/js/assignment/__snapshots__/format.test.js.snap +++ b/tests/format/js/assignment/__snapshots__/format.test.js.snap @@ -1,5 +1,18 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`binaryish.js [hermes] format 1`] = ` +"invalid assignment left-hand side (6:0) + 4 | descriptionLines; + 5 | +> 6 | computedDescriptionLines = (focused && + 7 | !loading && + 8 | descriptionLinesFocused) || + 9 | descriptionLines; +Cause: invalid assignment left-hand side (6:0) +computedDescriptionLines = (focused && +^~~~~~~~~~~~~~~~~~~~~~~~" +`; + exports[`binaryish.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] diff --git a/tests/format/js/assignment/format.test.js b/tests/format/js/assignment/format.test.js index 67c251cce..6f905dd2b 100644 --- a/tests/format/js/assignment/format.test.js +++ b/tests/format/js/assignment/format.test.js @@ -1 +1,5 @@ -runFormatTest(import.meta, ["babel", "flow", "typescript"]); +runFormatTest(import.meta, ["babel", "flow", "typescript"], { + errors: { + hermes: ["binaryish.js"], + }, +}); diff --git a/tests/format/js/decorators/class-expression/__snapshots__/format.test.js.snap b/tests/format/js/decorators/class-expression/__snapshots__/format.test.js.snap index 933869c6e..543fa9929 100644 --- a/tests/format/js/decorators/class-expression/__snapshots__/format.test.js.snap +++ b/tests/format/js/decorators/class-expression/__snapshots__/format.test.js.snap @@ -26,6 +26,17 @@ exports[`arguments.js [flow] format 1`] = ` 3 |" `; +exports[`arguments.js [hermes] format 1`] = ` +"unrecognized character '@' (1:12) +> 1 | console.log(@deco class Foo {}) + | ^ + 2 | console.log(@deco class {}) + 3 | +Cause: unrecognized character '@' (1:12) +console.log(@deco class Foo {}) + ^" +`; + exports[`arguments.js - {"semi":false} [acorn] format 1`] = ` "Unexpected character '@' (1:13) > 1 | console.log(@deco class Foo {}) @@ -52,6 +63,17 @@ exports[`arguments.js - {"semi":false} [flow] format 1`] = ` 3 |" `; +exports[`arguments.js - {"semi":false} [hermes] format 1`] = ` +"unrecognized character '@' (1:12) +> 1 | console.log(@deco class Foo {}) + | ^ + 2 | console.log(@deco class {}) + 3 | +Cause: unrecognized character '@' (1:12) +console.log(@deco class Foo {}) + ^" +`; + exports[`arguments.js - {"semi":false} format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] @@ -126,6 +148,18 @@ exports[`class-expression.js [flow] format 1`] = ` 4 | (@deco class Foo {});" `; +exports[`class-expression.js [hermes] format 1`] = ` +"unrecognized character '@' (1:12) +> 1 | const a1 = (@deco class Foo {}); + | ^ + 2 | const a2 = (@deco class {}); + 3 | + 4 | (@deco class Foo {}); +Cause: unrecognized character '@' (1:12) +const a1 = (@deco class Foo {}); + ^" +`; + exports[`class-expression.js - {"semi":false} [acorn] format 1`] = ` "Unexpected character '@' (1:13) > 1 | const a1 = (@deco class Foo {}); @@ -155,6 +189,18 @@ exports[`class-expression.js - {"semi":false} [flow] format 1`] = ` 4 | (@deco class Foo {});" `; +exports[`class-expression.js - {"semi":false} [hermes] format 1`] = ` +"unrecognized character '@' (1:12) +> 1 | const a1 = (@deco class Foo {}); + | ^ + 2 | const a2 = (@deco class {}); + 3 | + 4 | (@deco class Foo {}); +Cause: unrecognized character '@' (1:12) +const a1 = (@deco class Foo {}); + ^" +`; + exports[`class-expression.js - {"semi":false} format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] @@ -296,6 +342,17 @@ exports[`member-expression.js [flow] format 1`] = ` 3 |" `; +exports[`member-expression.js [hermes] format 1`] = ` +"unrecognized character '@' (1:1) +> 1 | (@deco class Foo {}).name; + | ^ + 2 | (@deco class {}).name; + 3 | +Cause: unrecognized character '@' (1:1) +(@deco class Foo {}).name; + ^" +`; + exports[`member-expression.js - {"semi":false} [acorn] format 1`] = ` "Unexpected character '@' (1:2) > 1 | (@deco class Foo {}).name; @@ -322,6 +379,17 @@ exports[`member-expression.js - {"semi":false} [flow] format 1`] = ` 3 |" `; +exports[`member-expression.js - {"semi":false} [hermes] format 1`] = ` +"unrecognized character '@' (1:1) +> 1 | (@deco class Foo {}).name; + | ^ + 2 | (@deco class {}).name; + 3 | +Cause: unrecognized character '@' (1:1) +(@deco class Foo {}).name; + ^" +`; + exports[`member-expression.js - {"semi":false} format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] @@ -396,6 +464,18 @@ exports[`super-class.js [flow] format 1`] = ` 4 |" `; +exports[`super-class.js [hermes] format 1`] = ` +"unrecognized character '@' (1:19) +> 1 | class Foo extends (@deco class Foo {}){} + | ^ + 2 | + 3 | class Foo extends (@deco class {}){} + 4 | +Cause: unrecognized character '@' (1:19) +class Foo extends (@deco class Foo {}){} + ^" +`; + exports[`super-class.js - {"semi":false} [acorn] format 1`] = ` "Unexpected character '@' (1:20) > 1 | class Foo extends (@deco class Foo {}){} @@ -425,6 +505,18 @@ exports[`super-class.js - {"semi":false} [flow] format 1`] = ` 4 |" `; +exports[`super-class.js - {"semi":false} [hermes] format 1`] = ` +"unrecognized character '@' (1:19) +> 1 | class Foo extends (@deco class Foo {}){} + | ^ + 2 | + 3 | class Foo extends (@deco class {}){} + 4 | +Cause: unrecognized character '@' (1:19) +class Foo extends (@deco class Foo {}){} + ^" +`; + exports[`super-class.js - {"semi":false} format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] diff --git a/tests/format/js/decorators/class-expression/format.test.js b/tests/format/js/decorators/class-expression/format.test.js index eed5d9142..929abd4c0 100644 --- a/tests/format/js/decorators/class-expression/format.test.js +++ b/tests/format/js/decorators/class-expression/format.test.js @@ -1,5 +1,6 @@ const errors = { flow: true, + hermes: true, acorn: true, espree: true, }; diff --git a/tests/format/js/destructuring/__snapshots__/format.test.js.snap b/tests/format/js/destructuring/__snapshots__/format.test.js.snap index 1659a2d8c..3630a9a3b 100644 --- a/tests/format/js/destructuring/__snapshots__/format.test.js.snap +++ b/tests/format/js/destructuring/__snapshots__/format.test.js.snap @@ -1,5 +1,17 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`destructuring.js [hermes] format 1`] = ` +"invalid assignment left-hand side (2:0) + 1 | const [one, two = null, three = null] = arr; +> 2 | a = ([s=1,]) => 1 + 3 | const { children, ...props } = this.props + 4 | + 5 | const { user: { firstName, lastName } } = this.props; +Cause: invalid assignment left-hand side (2:0) +a = ([s=1,]) => 1 +^" +`; + exports[`destructuring.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] diff --git a/tests/format/js/destructuring/format.test.js b/tests/format/js/destructuring/format.test.js index 67c251cce..3957a9ec1 100644 --- a/tests/format/js/destructuring/format.test.js +++ b/tests/format/js/destructuring/format.test.js @@ -1 +1,5 @@ -runFormatTest(import.meta, ["babel", "flow", "typescript"]); +runFormatTest(import.meta, ["babel", "flow", "typescript"], { + errors: { + hermes: ["destructuring.js"], + }, +}); diff --git a/tests/format/js/dynamic-import/__snapshots__/format.test.js.snap b/tests/format/js/dynamic-import/__snapshots__/format.test.js.snap index 5d3be58b6..80c769f95 100644 --- a/tests/format/js/dynamic-import/__snapshots__/format.test.js.snap +++ b/tests/format/js/dynamic-import/__snapshots__/format.test.js.snap @@ -50,6 +50,21 @@ exports[`import-phase.js [flow] format 1`] = ` 4 |" `; +exports[`import-phase.js [hermes] format 1`] = ` +"'meta' expected in member expression (1:7) +> 1 | import.source(\`data:text/javascript, + | ^ + 2 | console.log("RUN"); + 3 | \`) + 4 | +Cause: 'meta' expected in member expression (1:7) +import.source(\`data:text/javascript, + ^~~~~~ +note: start of member expression (1:0) +import.source(\`data:text/javascript, +^" +`; + exports[`import-phase.js [meriyah] format 1`] = ` "The only valid meta property for import is 'import.meta' (1:8) > 1 | import.source(\`data:text/javascript, @@ -95,6 +110,18 @@ exports[`template-literal.js [flow] format 1`] = ` 4 |" `; +exports[`template-literal.js [hermes] format 1`] = ` +"unexpected token after assignment expression (1:19) +> 1 | module = await import(\`data:text/javascript, + | ^ + 2 | console.log("RUN"); + 3 | \`); + 4 | +Cause: unexpected token after assignment expression (1:19) +module = await import(\`data:text/javascript, + ^" +`; + exports[`template-literal.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] diff --git a/tests/format/js/dynamic-import/format.test.js b/tests/format/js/dynamic-import/format.test.js index ae118cb7d..ced22507d 100644 --- a/tests/format/js/dynamic-import/format.test.js +++ b/tests/format/js/dynamic-import/format.test.js @@ -1,6 +1,7 @@ runFormatTest(import.meta, ["babel", "flow", "typescript"], { errors: { flow: ["assertions.js", "template-literal.js", "import-phase.js"], + hermes: ["template-literal.js", "import-phase.js"], acorn: ["import-phase.js"], espree: ["import-phase.js"], meriyah: ["import-phase.js"], diff --git a/tests/format/js/explicit-resource-management/__snapshots__/format.test.js.snap b/tests/format/js/explicit-resource-management/__snapshots__/format.test.js.snap index 1801272ee..f4d9a4825 100644 --- a/tests/format/js/explicit-resource-management/__snapshots__/format.test.js.snap +++ b/tests/format/js/explicit-resource-management/__snapshots__/format.test.js.snap @@ -23,6 +23,16 @@ exports[`for-await-using-of-comments.js [flow] format 1`] = ` 2 |" `; +exports[`for-await-using-of-comments.js [hermes] format 1`] = ` +"'(' expected after 'for' (1:18) +> 1 | /*1*/ for /* 2 */ await /*3*/ ( /*4*/ using /*5*/ fo /*6*/ of /*7*/ of /*8*/) /*9*/; + | ^ + 2 | +Cause: '(' expected after 'for' (1:18) +/*1*/ for /* 2 */ await /*3*/ ( /*4*/ using /*5*/ fo /*6*/ of /*7*/ of /*8*/) /*9*/; + ~~~~~~~~~~~~^" +`; + exports[`for-await-using-of-comments.js [meriyah] format 1`] = ` "for await (... of ...) is only valid in async functions and async generators (1:51) > 1 | /*1*/ for /* 2 */ await /*3*/ ( /*4*/ using /*5*/ fo /*6*/ of /*7*/ of /*8*/) /*9*/; @@ -77,6 +87,19 @@ exports[`invalid-duplicate-using-bindings.js [flow] format 1`] = ` 5 | using g = foo();" `; +exports[`invalid-duplicate-using-bindings.js [hermes] format 1`] = ` +"';' expected (2:8) + 1 | { +> 2 | using f = foo(), f = foo(); + | ^ + 3 | } + 4 | { + 5 | using g = foo(); +Cause: ';' expected (2:8) + using f = foo(), f = foo(); + ^" +`; + exports[`invalid-duplicate-using-bindings.js [meriyah] format 1`] = ` "Unexpected token: 'identifier' (2:9) 1 | { @@ -138,6 +161,16 @@ exports[`invalid-script-top-level-using-binding.js [flow] format 1`] = ` 2 |" `; +exports[`invalid-script-top-level-using-binding.js [hermes] format 1`] = ` +"';' expected (1:6) +> 1 | using x = bar(); + | ^ + 2 | +Cause: ';' expected (1:6) +using x = bar(); + ^" +`; + exports[`invalid-script-top-level-using-binding.js [meriyah] format 1`] = ` "Unexpected token: 'identifier' (1:7) > 1 | using x = bar(); @@ -192,6 +225,19 @@ exports[`using-declarations.js [flow] format 1`] = ` 5 | for(using /* 1 */ a = foo(), /* 2 */ b = foo();;);" `; +exports[`using-declarations.js [hermes] format 1`] = ` +"';' expected (2:16) + 1 | { +> 2 | using /* 1 */ a = foo(), /* 2 */ b = foo() + | ^ + 3 | } + 4 | + 5 | for(using /* 1 */ a = foo(), /* 2 */ b = foo();;); +Cause: ';' expected (2:16) + using /* 1 */ a = foo(), /* 2 */ b = foo() + ^" +`; + exports[`using-declarations.js [meriyah] format 1`] = ` "Unexpected token: 'identifier' (2:17) 1 | { @@ -347,6 +393,18 @@ exports[`valid-await-using-binding-basic.js [flow] format 1`] = ` 4 |" `; +exports[`valid-await-using-binding-basic.js [hermes] format 1`] = ` +"';' expected (2:14) + 1 | async function f() { +> 2 | await using basic = getReader(); + | ^ + 3 | } + 4 | +Cause: ';' expected (2:14) + await using basic = getReader(); + ^" +`; + exports[`valid-await-using-binding-basic.js [meriyah] format 1`] = ` "Unexpected token: 'identifier' (2:15) 1 | async function f() { @@ -404,6 +462,18 @@ exports[`valid-await-using-binding-escaped.js [flow] format 1`] = ` 4 |" `; +exports[`valid-await-using-binding-escaped.js [hermes] format 1`] = ` +"';' expected (2:14) + 1 | async function f() { +> 2 | await using \\u0061b = c; + | ^ + 3 | } + 4 | +Cause: ';' expected (2:14) + await using \\u0061b = c; + ^" +`; + exports[`valid-await-using-binding-escaped.js [meriyah] format 1`] = ` "Unexpected token: 'identifier' (2:15) 1 | async function f() { @@ -461,6 +531,17 @@ exports[`valid-await-using-binding-non-bmp.js [flow] format 1`] = ` 4 |" `; +exports[`valid-await-using-binding-non-bmp.js [hermes] format 1`] = ` +"';' expected (2:14) + 1 | async function f() { +> 2 | await using 𠮷 = foo(); + | ^ + 3 | } + 4 | +Cause: ';' expected (2:14) + await using 𠮷 = foo();" +`; + exports[`valid-await-using-binding-non-bmp.js [meriyah] format 1`] = ` "Unexpected token: 'identifier' (2:15) 1 | async function f() { @@ -521,6 +602,19 @@ exports[`valid-await-using-binding-using.js [flow] format 1`] = ` 5 |" `; +exports[`valid-await-using-binding-using.js [hermes] format 1`] = ` +"';' expected (2:14) + 1 | async function f() { +> 2 | await using using = of; + | ^ + 3 | for (await using using of of); + 4 | } + 5 | +Cause: ';' expected (2:14) + await using using = of; + ^" +`; + exports[`valid-await-using-binding-using.js [meriyah] format 1`] = ` "Unexpected token: 'identifier' (2:15) 1 | async function f() { @@ -587,6 +681,20 @@ exports[`valid-await-using-comments.js [flow] format 1`] = ` 6 | /*0*/for/*1*/(/*2*/await/*3*/using/*4*/b/*5*/=/*6*/x/*7*/;/*8*/;/*9*/)/*10*/;" `; +exports[`valid-await-using-comments.js [hermes] format 1`] = ` +"';' expected (3:27) + 1 | async function f() { + 2 | { +> 3 | /*0*/await/*1*/using/*2*/b/*3*/=/*4*/f()/*5*/; + | ^ + 4 | } + 5 | { + 6 | /*0*/for/*1*/(/*2*/await/*3*/using/*4*/b/*5*/=/*6*/x/*7*/;/*8*/;/*9*/)/*10*/; +Cause: ';' expected (3:27) + /*0*/await/*1*/using/*2*/b/*3*/=/*4*/f()/*5*/; + ^" +`; + exports[`valid-await-using-comments.js [meriyah] format 1`] = ` "Unexpected token: 'identifier' (3:28) 1 | async function f() { @@ -720,6 +828,19 @@ exports[`valid-for-using-binding-of-of.js [flow] format 1`] = ` 5 |" `; +exports[`valid-for-using-binding-of-of.js [hermes] format 1`] = ` +"')' expected after 'for(... in/of ...' (2:25) + 1 | async function f() { +> 2 | for (await using of of of); + | ^ + 3 | for await (await using of of of); + 4 | } + 5 | +Cause: ')' expected after 'for(... in/of ...' (2:25) + for (await using of of of); + ~~~~~~~~~~~~~~~~~~~^" +`; + exports[`valid-for-using-binding-of-of.js [meriyah] format 1`] = ` "Invalid left-hand side in for-of (2:20) 1 | async function f() { @@ -780,6 +901,18 @@ exports[`valid-for-using-declaration.js [flow] format 1`] = ` 4 |" `; +exports[`valid-for-using-declaration.js [hermes] format 1`] = ` +"';' or 'in' expected inside 'for' (2:19) + 1 | async function f() { +> 2 | for (await using basic = reader();;); + | ^ + 3 | } + 4 | +Cause: ';' or 'in' expected inside 'for' (2:19) + for (await using basic = reader();;); + ~~~~~~~~~~~~~~~~~^" +`; + exports[`valid-for-using-declaration.js [meriyah] format 1`] = ` "Expected ';' (2:20) 1 | async function f() { @@ -847,6 +980,18 @@ exports[`valid-module-block-top-level-await-using-binding.js [flow] format 1`] = 4 |" `; +exports[`valid-module-block-top-level-await-using-binding.js [hermes] format 1`] = ` +"';' expected (1:17) +> 1 | const m = module { + | ^ + 2 | await using foo = bar(); + 3 | } + 4 | +Cause: ';' expected (1:17) +const m = module { + ^" +`; + exports[`valid-module-block-top-level-await-using-binding.js [meriyah] format 1`] = ` "Unexpected token: '{' (1:18) > 1 | const m = module { @@ -932,6 +1077,18 @@ exports[`valid-module-block-top-level-using-binding.js [flow] format 1`] = ` 4 |" `; +exports[`valid-module-block-top-level-using-binding.js [hermes] format 1`] = ` +"';' expected (1:7) +> 1 | module { + | ^ + 2 | using foo = bar(); + 3 | } + 4 | +Cause: ';' expected (1:7) +module { + ^" +`; + exports[`valid-module-block-top-level-using-binding.js [meriyah] format 1`] = ` "Unexpected token: '{' (1:8) > 1 | module { @@ -1027,6 +1184,16 @@ exports[`valid-using-as-identifier-for-await-of.js [flow] format 1`] = ` 2 |" `; +exports[`valid-using-as-identifier-for-await-of.js [hermes] format 1`] = ` +"'(' expected after 'for' (1:4) +> 1 | for await (using of of); + | ^ + 2 | +Cause: '(' expected after 'for' (1:4) +for await (using of of); +~~~~^" +`; + exports[`valid-using-as-identifier-for-await-of.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] @@ -1140,6 +1307,18 @@ exports[`valid-using-binding-basic.js [flow] format 1`] = ` 4 |" `; +exports[`valid-using-binding-basic.js [hermes] format 1`] = ` +"';' expected (2:8) + 1 | { +> 2 | using basic = getReader(); + | ^ + 3 | } + 4 | +Cause: ';' expected (2:8) + using basic = getReader(); + ^" +`; + exports[`valid-using-binding-basic.js [meriyah] format 1`] = ` "Unexpected token: 'identifier' (2:9) 1 | { @@ -1191,6 +1370,16 @@ exports[`valid-using-binding-escaped.js [flow] format 1`] = ` 2 |" `; +exports[`valid-using-binding-escaped.js [hermes] format 1`] = ` +"';' expected (1:8) +> 1 | { using \\u0061b = c; } + | ^ + 2 | +Cause: ';' expected (1:8) +{ using \\u0061b = c; } + ^" +`; + exports[`valid-using-binding-escaped.js [meriyah] format 1`] = ` "Unexpected token: 'identifier' (1:9) > 1 | { using \\u0061b = c; } @@ -1238,6 +1427,15 @@ exports[`valid-using-binding-non-bmp.js [flow] format 1`] = ` 2 |" `; +exports[`valid-using-binding-non-bmp.js [hermes] format 1`] = ` +"';' expected (1:8) +> 1 | { using 𠮷 = foo(); } + | ^ + 2 | +Cause: ';' expected (1:8) +{ using 𠮷 = foo(); }" +`; + exports[`valid-using-binding-non-bmp.js [meriyah] format 1`] = ` "Unexpected token: 'identifier' (1:9) > 1 | { using 𠮷 = foo(); } @@ -1294,6 +1492,19 @@ exports[`valid-using-binding-using.js [flow] format 1`] = ` 5 |" `; +exports[`valid-using-binding-using.js [hermes] format 1`] = ` +"';' expected (2:8) + 1 | { +> 2 | using using = of; + | ^ + 3 | for (using using of of); + 4 | } + 5 | +Cause: ';' expected (2:8) + using using = of; + ^" +`; + exports[`valid-using-binding-using.js [meriyah] format 1`] = ` "Unexpected token: 'identifier' (2:9) 1 | { diff --git a/tests/format/js/explicit-resource-management/format.test.js b/tests/format/js/explicit-resource-management/format.test.js index 288bc5793..e78bbb0b6 100644 --- a/tests/format/js/explicit-resource-management/format.test.js +++ b/tests/format/js/explicit-resource-management/format.test.js @@ -24,6 +24,30 @@ runFormatTest(import.meta, ["babel", "flow", "typescript"], { "valid-for-using-declaration.js", "valid-module-block-top-level-await-using-binding.js", ], + hermes: [ + "for-await-using-of-comments.js", + "invalid-duplicate-using-bindings.js", + "invalid-script-top-level-using-binding.js", + "using-declarations.js", + // "valid-for-await-using-binding-escaped-of-of.js", + // "valid-for-using-binding-escaped-of-of.js", + "valid-module-block-top-level-using-binding.js", + "valid-using-as-identifier-for-await-of.js", + "valid-using-binding-basic.js", + "valid-using-binding-escaped.js", + "valid-using-binding-non-bmp.js", + "valid-using-binding-using.js", + + "valid-await-using-binding-basic.js", + "valid-await-using-binding-escaped.js", + "valid-await-using-binding-non-bmp.js", + "valid-await-using-binding-using.js", + "valid-await-using-comments.js", + "valid-for-lhs-await-as-identifier.js", + "valid-for-using-binding-of-of.js", + "valid-for-using-declaration.js", + "valid-module-block-top-level-await-using-binding.js", + ], typescript: [ // https://github.com/typescript-eslint/typescript-eslint/blob/4f34d0ba34474926ba1eed623704b583a037f886/packages/typescript-estree/src/convert.ts#L1035-L1050 "valid-for-using-declaration.js", diff --git a/tests/format/js/export-default/escaped/__snapshots__/format.test.js.snap b/tests/format/js/export-default/escaped/__snapshots__/format.test.js.snap index 80575a568..449327668 100644 --- a/tests/format/js/export-default/escaped/__snapshots__/format.test.js.snap +++ b/tests/format/js/export-default/escaped/__snapshots__/format.test.js.snap @@ -23,6 +23,16 @@ exports[`default-escaped.js [flow] format 1`] = ` | ^^^^^^^" `; +exports[`default-escaped.js [hermes] format 1`] = ` +"expected declaration in export (2:7) + 1 | // export asyn\\u{63} from "async"; +> 2 | export n\\u{63} from "async"; + | ^ +Cause: expected declaration in export (2:7) +export n\\u{63} from "async"; + ^~~~~~~" +`; + exports[`default-escaped.js [meriyah] format 1`] = ` "Unexpected token: 'identifier' (2:8) 1 | // export asyn\\u{63} from "async"; diff --git a/tests/format/js/export-default/escaped/format.test.js b/tests/format/js/export-default/escaped/format.test.js index cc42d5f70..8461922b9 100644 --- a/tests/format/js/export-default/escaped/format.test.js +++ b/tests/format/js/export-default/escaped/format.test.js @@ -4,6 +4,7 @@ runFormatTest(import.meta, ["babel", "flow"], { espree: true, meriyah: true, flow: true, + hermes: true, oxc: true, "oxc-ts": true, }, diff --git a/tests/format/js/export-star/__snapshots__/format.test.js.snap b/tests/format/js/export-star/__snapshots__/format.test.js.snap index 569a7cad5..3840c102d 100644 --- a/tests/format/js/export-star/__snapshots__/format.test.js.snap +++ b/tests/format/js/export-star/__snapshots__/format.test.js.snap @@ -71,6 +71,16 @@ exports[`export-star-as-string.js [flow] format 1`] = ` 2 |" `; +exports[`export-star-as-string.js [hermes] format 1`] = ` +"'identifier' expected in export clause (1:12) +> 1 | export * as 'foo' from 'foo' + | ^ + 2 | +Cause: 'identifier' expected in export clause (1:12) +export * as 'foo' from 'foo' +~~~~~~~~~~~~^" +`; + exports[`export-star-as-string.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] @@ -92,6 +102,16 @@ exports[`export-star-as-string2.js [flow] format 1`] = ` 2 |" `; +exports[`export-star-as-string2.js [hermes] format 1`] = ` +"'identifier' expected in export clause (1:12) +> 1 | export * as "foo" from 'foo' + | ^ + 2 | +Cause: 'identifier' expected in export clause (1:12) +export * as "foo" from 'foo' +~~~~~~~~~~~~^" +`; + exports[`export-star-as-string2.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] diff --git a/tests/format/js/export-star/format.test.js b/tests/format/js/export-star/format.test.js index 2989dce82..bd9283f96 100644 --- a/tests/format/js/export-star/format.test.js +++ b/tests/format/js/export-star/format.test.js @@ -1,5 +1,6 @@ runFormatTest(import.meta, ["babel", "flow", "typescript"], { errors: { flow: ["export-star-as-string.js", "export-star-as-string2.js"], + hermes: ["export-star-as-string.js", "export-star-as-string2.js"], }, }); diff --git a/tests/format/js/ignore/__snapshots__/format.test.js.snap b/tests/format/js/ignore/__snapshots__/format.test.js.snap index 82a7a8e26..a24854c9a 100644 --- a/tests/format/js/ignore/__snapshots__/format.test.js.snap +++ b/tests/format/js/ignore/__snapshots__/format.test.js.snap @@ -35,6 +35,20 @@ exports[`class-expression-decorator.js [flow] format 1`] = ` 6 |" `; +exports[`class-expression-decorator.js [hermes] format 1`] = ` +"unrecognized character '@' (3:2) + 1 | ( + 2 | // prettier-ignore +> 3 | @decorator + | ^ + 4 | class {} + 5 | ); + 6 | +Cause: unrecognized character '@' (3:2) + @decorator + ^" +`; + exports[`class-expression-decorator.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] @@ -77,6 +91,17 @@ exports[`decorator.js [espree] format 1`] = ` Cause: Unexpected character '@'" `; +exports[`decorator.js [hermes] format 1`] = ` +"unrecognized character '@' (2:0) + 1 | // prettier-ignore +> 2 | @decorator + 3 | class A {} + 4 | +Cause: unrecognized character '@' (2:0) +@decorator +^" +`; + exports[`decorator.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] diff --git a/tests/format/js/ignore/format.test.js b/tests/format/js/ignore/format.test.js index a33b91b72..d7e7dd559 100644 --- a/tests/format/js/ignore/format.test.js +++ b/tests/format/js/ignore/format.test.js @@ -3,5 +3,6 @@ runFormatTest(import.meta, ["babel", "flow", "typescript"], { acorn: ["decorator.js", "class-expression-decorator.js"], espree: ["decorator.js", "class-expression-decorator.js"], flow: ["class-expression-decorator.js"], + hermes: ["decorator.js", "class-expression-decorator.js"], }, }); diff --git a/tests/format/js/multiparser-invalid/__snapshots__/format.test.js.snap b/tests/format/js/multiparser-invalid/__snapshots__/format.test.js.snap index bff23f84f..eeb4cc3d9 100644 --- a/tests/format/js/multiparser-invalid/__snapshots__/format.test.js.snap +++ b/tests/format/js/multiparser-invalid/__snapshots__/format.test.js.snap @@ -33,6 +33,20 @@ exports[`text.js [flow] format 1`] = ` 4 | foo = markdown\`\\u{prettier}\\u{0065}\`;" `; +exports[`text.js [hermes] format 1`] = ` +"untagged template literal contains invalid escape sequence (6:16) + 4 | foo = markdown\`\\u{prettier}\\u{0065}\`; + 5 | foo = css\`\\u{prettier}\\u{0065}\`; +> 6 | foo = /* HTML */\`\\u{prettier}\\u{0065}\`; + | ^ + 7 | foo = /* GraphQL */\`\\u{prettier}\\u{0065}\`; + 8 | + 9 | foo = foo\`\\u{prettier}\${foo}pr\\u{0065}ttier\`; +Cause: untagged template literal contains invalid escape sequence (6:16) +foo = /* HTML */\`\\u{prettier}\\u{0065}\`; + ^~~~~~~~~~~~~~~~~~~~~~" +`; + exports[`text.js [meriyah] format 1`] = ` "Invalid hexadecimal escape sequence (6:17) 4 | foo = markdown\`\\u{prettier}\\u{0065}\`; diff --git a/tests/format/js/multiparser-invalid/format.test.js b/tests/format/js/multiparser-invalid/format.test.js index 848a44055..952dda85b 100644 --- a/tests/format/js/multiparser-invalid/format.test.js +++ b/tests/format/js/multiparser-invalid/format.test.js @@ -3,6 +3,7 @@ runFormatTest(import.meta, ["babel", "flow", "typescript"], { acorn: true, espree: true, flow: true, + hermes: true, typescript: true, meriyah: true, oxc: true, diff --git a/tests/format/js/new-target/__snapshots__/format.test.js.snap b/tests/format/js/new-target/__snapshots__/format.test.js.snap index 5e8975105..ef4378d4c 100644 --- a/tests/format/js/new-target/__snapshots__/format.test.js.snap +++ b/tests/format/js/new-target/__snapshots__/format.test.js.snap @@ -23,6 +23,16 @@ exports[`outside-functions.js [flow] format 1`] = ` 2 |" `; +exports[`outside-functions.js [hermes] format 1`] = ` +"'new.target' not in a function (1:10) +> 1 | const x = new.target; + | ^ + 2 | +Cause: 'new.target' not in a function (1:10) +const x = new.target; + ^~~~~~~~~~" +`; + exports[`outside-functions.js [meriyah] format 1`] = ` "new.target only allowed within functions or static blocks (1:15) > 1 | const x = new.target; @@ -68,6 +78,15 @@ exports[`range.js [flow] format 1`] = ` | ^" `; +exports[`range.js [hermes] format 1`] = ` +"'new.target' not in a function (2:0) + 1 | const x = +> 2 | new.target; +Cause: 'new.target' not in a function (2:0) +new.target; +^~~~~~~~~~" +`; + exports[`range.js [meriyah] format 1`] = ` "new.target only allowed within functions or static blocks (2:5) 1 | const x = diff --git a/tests/format/js/new-target/format.test.js b/tests/format/js/new-target/format.test.js index f5e616ffc..e844ec5ae 100644 --- a/tests/format/js/new-target/format.test.js +++ b/tests/format/js/new-target/format.test.js @@ -4,5 +4,6 @@ runFormatTest(import.meta, ["babel", "flow", "typescript"], { espree: true, meriyah: true, flow: true, + hermes: true, }, }); diff --git a/tests/format/js/objects/__snapshots__/format.test.js.snap b/tests/format/js/objects/__snapshots__/format.test.js.snap index 55cb812a3..e04158e9d 100644 --- a/tests/format/js/objects/__snapshots__/format.test.js.snap +++ b/tests/format/js/objects/__snapshots__/format.test.js.snap @@ -1,5 +1,17 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`bigint-key.js [hermes] format 1`] = ` +"invalid property name - must be a string, number or identifier (1:5) +> 1 | a = {1n: ""} + | ^ + 2 | a = {1n() {}} + 3 | a = {get 1n() {}} + 4 | +Cause: invalid property name - must be a string, number or identifier (1:5) +a = {1n: ""} + ^~" +`; + exports[`bigint-key.js format 1`] = ` ====================================options===================================== parsers: ["babel", "typescript", "flow"] @@ -105,6 +117,20 @@ exports[`expression.js [flow] format 1`] = ` 8 | ({} = 0);" `; +exports[`expression.js [hermes] format 1`] = ` +"unexpected token in type annotation (5:4) + 3 | a = () => ({}).x; + 4 | ({} && a, b); +> 5 | ({}::b, 0); + | ^ + 6 | ({}::b()\`\`[''].c++ && 0 ? 0 : 0, 0); + 7 | ({}(), 0); + 8 | ({} = 0); +Cause: unexpected token in type annotation (5:4) +({}::b, 0); + ^" +`; + exports[`expression.js [meriyah] format 1`] = ` "Expected ')' (5:4) 3 | a = () => ({}).x; diff --git a/tests/format/js/objects/format.test.js b/tests/format/js/objects/format.test.js index a6c9deb1f..d194f9b88 100644 --- a/tests/format/js/objects/format.test.js +++ b/tests/format/js/objects/format.test.js @@ -7,5 +7,6 @@ runFormatTest(import.meta, ["babel", "typescript", "flow"], { oxc: ["expression.js"], "oxc-ts": ["expression.js"], flow: ["expression.js"], + hermes: ["expression.js", "bigint-key.js"], }, }); diff --git a/tests/format/js/sloppy-mode/__snapshots__/format.test.js.snap b/tests/format/js/sloppy-mode/__snapshots__/format.test.js.snap index e399cae40..df319e59a 100644 --- a/tests/format/js/sloppy-mode/__snapshots__/format.test.js.snap +++ b/tests/format/js/sloppy-mode/__snapshots__/format.test.js.snap @@ -19,6 +19,19 @@ function foo() { ================================================================================ `; +exports[`eval-arguments.js [hermes] format 1`] = ` +"invalid assignment left-hand side (3:2) + 1 | function myfunc() { + 2 | eval = 1 +> 3 | arguments = arguments; + | ^ + 4 | } + 5 | +Cause: invalid assignment left-hand side (3:2) + arguments = arguments; + ^~~~~~~~~" +`; + exports[`eval-arguments.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] @@ -96,6 +109,16 @@ exports[`function-declaration-in-while.js [flow] format 1`] = ` 2 |" `; +exports[`function-declaration-in-while.js [hermes] format 1`] = ` +"declaration not allowed as expression statement (1:14) +> 1 | while (false) function foo(){} + | ^ + 2 | +Cause: declaration not allowed as expression statement (1:14) +while (false) function foo(){} + ^~~~~~~~" +`; + exports[`function-declaration-in-while.js [meriyah] format 1`] = ` "In strict mode code, functions can only be declared at top level or inside a block (1:15) > 1 | while (false) function foo(){} @@ -118,6 +141,16 @@ while (false) function foo() {} ================================================================================ `; +exports[`labeled-function-declaration.js [hermes] format 1`] = ` +"Function declaration not allowed as body of labeled statement (1:5) +> 1 | foo: function bar() {} + | ^ + 2 | +Cause: Function declaration not allowed as body of labeled statement (1:5) +foo: function bar() {} + ^" +`; + exports[`labeled-function-declaration.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] diff --git a/tests/format/js/sloppy-mode/format.test.js b/tests/format/js/sloppy-mode/format.test.js index 3abe31a80..c2d1a55db 100644 --- a/tests/format/js/sloppy-mode/format.test.js +++ b/tests/format/js/sloppy-mode/format.test.js @@ -1,6 +1,11 @@ runFormatTest(import.meta, ["babel", "flow", "typescript"], { errors: { flow: ["function-declaration-in-while.js"], + hermes: [ + "eval-arguments.js", + "labeled-function-declaration.js", + "function-declaration-in-while.js", + ], acorn: ["function-declaration-in-while.js"], espree: ["function-declaration-in-while.js"], meriyah: ["function-declaration-in-while.js"], diff --git a/tests/format/typescript/classes/__snapshots__/format.test.js.snap b/tests/format/typescript/classes/__snapshots__/format.test.js.snap index f5ced5173..974d7e40d 100644 --- a/tests/format/typescript/classes/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/classes/__snapshots__/format.test.js.snap @@ -97,26 +97,26 @@ parsers: ["typescript", "flow"] printWidth: 80 | printWidth =====================================input====================================== -class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong { +class looooooooooooooooooong1 extends looooooooooooooooooong implements loooooooooooooooooooong { // leading comment property: string; } -class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong { +class looooooooooooooooooong2 extends looooooooooooooooooong implements loooooooooooooooooooong { property: string; } -class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong { +class looooooooooooooooooong3 extends looooooooooooooooooong implements loooooooooooooooooooong { property: string; } -class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong, loooooooooooooooooooong, loooooooooooooooooooong { +class looooooooooooooooooong4 extends looooooooooooooooooong implements loooooooooooooooooooong, loooooooooooooooooooong, loooooooooooooooooooong { property: string; } =====================================output===================================== -class loooooooooooooooooooong +class looooooooooooooooooong1 extends looooooooooooooooooong implements loooooooooooooooooooong { @@ -124,21 +124,21 @@ class loooooooooooooooooooong property: string; } -class loooooooooooooooooooong +class looooooooooooooooooong2 extends looooooooooooooooooong implements loooooooooooooooooooong { property: string; } -class loooooooooooooooooooong +class looooooooooooooooooong3 extends looooooooooooooooooong implements loooooooooooooooooooong { property: string; } -class loooooooooooooooooooong +class looooooooooooooooooong4 extends looooooooooooooooooong implements loooooooooooooooooooong, diff --git a/tests/format/typescript/classes/break-heritage.ts b/tests/format/typescript/classes/break-heritage.ts index e442f7517..bd9de53aa 100644 --- a/tests/format/typescript/classes/break-heritage.ts +++ b/tests/format/typescript/classes/break-heritage.ts @@ -1,17 +1,17 @@ -class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong { +class looooooooooooooooooong1 extends looooooooooooooooooong implements loooooooooooooooooooong { // leading comment property: string; } -class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong { +class looooooooooooooooooong2 extends looooooooooooooooooong implements loooooooooooooooooooong { property: string; } -class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong { +class looooooooooooooooooong3 extends looooooooooooooooooong implements loooooooooooooooooooong { property: string; } -class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong, loooooooooooooooooooong, loooooooooooooooooooong { +class looooooooooooooooooong4 extends looooooooooooooooooong implements loooooooooooooooooooong, loooooooooooooooooooong, loooooooooooooooooooong { property: string; } diff --git a/tests/format/typescript/type-params/consistent/__snapshots__/format.test.js.snap b/tests/format/typescript/type-params/consistent/__snapshots__/format.test.js.snap index 4ba6f857c..47aa28d03 100644 --- a/tests/format/typescript/type-params/consistent/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/type-params/consistent/__snapshots__/format.test.js.snap @@ -99,6 +99,16 @@ exports[`template-literal-types.ts [flow] format 1`] = ` 2 |" `; +exports[`template-literal-types.ts [hermes] format 1`] = ` +"unexpected token in type annotation (1:83) +> 1 | const foo1: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<\`Hello, \${keyof World}\`> = a; + | ^ + 2 | +Cause: unexpected token in type annotation (1:83) +const foo1: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<\`Hello, \${keyof World}\`> = a; + ^" +`; + exports[`template-literal-types.ts format 1`] = ` ====================================options===================================== parsers: ["typescript", "flow"] diff --git a/tests/format/typescript/type-params/consistent/format.test.js b/tests/format/typescript/type-params/consistent/format.test.js index f6dfa1f4d..41298863a 100644 --- a/tests/format/typescript/type-params/consistent/format.test.js +++ b/tests/format/typescript/type-params/consistent/format.test.js @@ -1,6 +1,7 @@ runFormatTest(import.meta, ["typescript", "flow"], { errors: { flow: ["template-literal-types.ts"], + hermes: ["template-literal-types.ts"], "babel-flow": ["template-literal-types.ts"], }, }); diff --git a/tests/format/typescript/type-params/empty-parameters-with-arrow-function/__snapshots__/format.test.js.snap b/tests/format/typescript/type-params/empty-parameters-with-arrow-function/__snapshots__/format.test.js.snap index ba9b6465d..be69c5e78 100644 --- a/tests/format/typescript/type-params/empty-parameters-with-arrow-function/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/type-params/empty-parameters-with-arrow-function/__snapshots__/format.test.js.snap @@ -8,26 +8,26 @@ printWidth: 80 trailingComma: "all" | printWidth =====================================input====================================== -const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx<> = +const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1: xxxxxxxxxxxxxxxxxxxxxx<> = arg => null; -const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx = +const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2: xxxxxxxxxxxxxxxxxxxxxx = arg => null; -const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx< +const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3: xxxxxxxxxxxxxxxxxxxxxx< // comment > = arg => null; =====================================output===================================== -const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx<> = +const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1: xxxxxxxxxxxxxxxxxxxxxx<> = arg => null; -const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx = +const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2: xxxxxxxxxxxxxxxxxxxxxx = arg => null; -const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx< +const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3: xxxxxxxxxxxxxxxxxxxxxx< // comment > = arg => null; diff --git a/tests/format/typescript/type-params/empty-parameters-with-arrow-function/issue-13817.ts b/tests/format/typescript/type-params/empty-parameters-with-arrow-function/issue-13817.ts index de3013df4..d7392c763 100644 --- a/tests/format/typescript/type-params/empty-parameters-with-arrow-function/issue-13817.ts +++ b/tests/format/typescript/type-params/empty-parameters-with-arrow-function/issue-13817.ts @@ -1,11 +1,11 @@ -const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx<> = +const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1: xxxxxxxxxxxxxxxxxxxxxx<> = arg => null; -const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx = +const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2: xxxxxxxxxxxxxxxxxxxxxx = arg => null; -const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx< +const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3: xxxxxxxxxxxxxxxxxxxxxx< // comment > = arg => null; diff --git a/website/playground/codeSamples.mjs b/website/playground/codeSamples.mjs index 662c6ce42..af2a8efdb 100644 --- a/website/playground/codeSamples.mjs +++ b/website/playground/codeSamples.mjs @@ -28,6 +28,7 @@ export default function getCodeSamples(parser) { "}", ].join("\n"); case "flow": + case "hermes": case "babel-flow": return [ "declare export function graphql>", diff --git a/website/playground/markdown.js b/website/playground/markdown.js index a9ba759f3..af0339e58 100644 --- a/website/playground/markdown.js +++ b/website/playground/markdown.js @@ -41,6 +41,7 @@ function getMarkdownSyntax(options) { case "babel": case "babel-flow": case "flow": + case "hermes": case "acorn": case "espree": case "meriyah": diff --git a/website/playground/util.js b/website/playground/util.js index 663444414..2a954ff32 100644 --- a/website/playground/util.js +++ b/website/playground/util.js @@ -65,6 +65,7 @@ const astAutoFold = { export function getAstAutoFold(parser) { switch (parser) { case "flow": + case "hermes": case "babel": case "babel-flow": case "babel-ts": diff --git a/website/static/worker.mjs b/website/static/worker.mjs index 1f3671e4e..27a3c8d18 100644 --- a/website/static/worker.mjs +++ b/website/static/worker.mjs @@ -62,6 +62,13 @@ const plugins = [ createPlugin(plugin), ), docExplorerPlugin, + prettierPackageManifest.builtinPlugins.some((plugin) => + plugin.parsers?.includes("hermes"), + ) + ? { + languages: [{ name: "hermes", parsers: ["hermes"] }], + } + : {}, ]; self.onmessage = async function (event) { diff --git a/yarn.lock b/yarn.lock index de3414d74..b89c7c3bf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2902,7 +2902,7 @@ __metadata: languageName: node linkType: hard -"buffer@npm:^6.0.3": +"buffer@npm:6.0.3, buffer@npm:^6.0.3": version: 6.0.3 resolution: "buffer@npm:6.0.3" dependencies: @@ -7233,6 +7233,7 @@ __metadata: angular-html-parser: "npm:8.1.0" browserslist: "npm:4.24.5" browserslist-to-esbuild: "npm:2.1.1" + buffer: "npm:6.0.3" c8: "npm:10.1.3" camelcase: "npm:8.0.0" ci-info: "npm:4.2.0"