Add hermes parser (#17520)

This commit is contained in:
fisker Cheung authored and GitHub committed 2025-05-29 15:30:45 +08:00
1 parent f037a2674c
commit 4df0a871ca
85 files changed
+1231 -108

No files matched your search

+1 -1
View File
@@ -48,7 +48,7 @@ function runFormatTest(
Parameters: 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. - **`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. - **`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). The implementation of `runFormatTest` can be found in [`tests/config/run-format-test.js`](tests/config/run-format-test.js).
+2 -1
View File
@@ -9,6 +9,7 @@ export default {
"src/cli/index.js", "src/cli/index.js",
"src/experimental-cli/index.js", "src/experimental-cli/index.js",
"packages/plugin-oxc/index.js", "packages/plugin-oxc/index.js",
"packages/plugin-hermes/index.js",
], ],
project: ["src/**", "scripts/**"], project: ["src/**", "scripts/**"],
ignore: [ ignore: [
@@ -17,7 +18,7 @@ export default {
"scripts/tools/**", "scripts/tools/**",
"src/experimental-cli/**", "src/experimental-cli/**",
], ],
ignoreDependencies: ["eslint-formatter-friendly", "ts-expect"], ignoreDependencies: ["eslint-formatter-friendly", "ts-expect", "buffer"],
ignoreBinaries: [ ignoreBinaries: [
"test-coverage", "test-coverage",
"renovate-config-validator", "renovate-config-validator",
+4 -3
View File
@@ -121,6 +121,7 @@
"@typescript-eslint/parser": "8.33.0", "@typescript-eslint/parser": "8.33.0",
"browserslist": "4.24.5", "browserslist": "4.24.5",
"browserslist-to-esbuild": "2.1.1", "browserslist-to-esbuild": "2.1.1",
"buffer": "6.0.3",
"c8": "10.1.3", "c8": "10.1.3",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"cspell": "9.0.0", "cspell": "9.0.0",
@@ -189,9 +190,9 @@
"build": "node ./scripts/build/build.js", "build": "node ./scripts/build/build.js",
"build:website": "node ./scripts/build-website.js", "build:website": "node ./scripts/build-website.js",
"gen:changelog": "node ./scripts/generate-changelog.js", "gen:changelog": "node ./scripts/generate-changelog.js",
"debug": "node 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", "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" "debug:inspect": "node --inspect-brk bin/prettier.js --ignore-path=.prettierignore --plugin=./packages/plugin-oxc/index.js --plugin=./packages/plugin-hermes/index.js"
}, },
"c8": { "c8": {
"reporter": [ "reporter": [
+27
View File
@@ -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"
}
}
]
}
```
+1
View File
@@ -0,0 +1 @@
export * as parsers from "../../src/language-js/parse/hermes.js";
+22
View File
@@ -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 <lionkay@gmail.com>",
"license": "MIT"
}
+1 -5
View File
@@ -1,6 +1,6 @@
# @prettier/plugin-oxc # @prettier/plugin-oxc
> Prettier Oxc plugin. > Prettier [Oxc](https://oxc.rs/) plugin.
## Install ## 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
+19 -5
View File
@@ -43,7 +43,7 @@ async function buildPrettier() {
}); });
try { try {
await runYarn("build", ["--package=prettier", "--clean", "--playground"], { await runYarn("build", ["--clean", "--playground"], {
cwd: PROJECT_ROOT, cwd: PROJECT_ROOT,
}); });
} finally { } finally {
@@ -55,16 +55,30 @@ async function buildPrettier() {
async function buildPlaygroundFiles() { async function buildPlaygroundFiles() {
const patterns = ["standalone.mjs", "plugins/*.mjs"]; const patterns = ["standalone.mjs", "plugins/*.mjs"];
const files = await fastGlob(patterns, { let files = await fastGlob(patterns, {
cwd: PRETTIER_DIR, 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 = { const packageManifest = {
builtinPlugins: [], builtinPlugins: [],
}; };
for (const fileName of files) { for (const { fileName, file, dist } of files) {
const file = path.join(PRETTIER_DIR, fileName);
const dist = path.join(PLAYGROUND_PRETTIER_DIR, fileName);
await copyFile(file, dist); await copyFile(file, dist);
if (fileName === "standalone.mjs") { if (fileName === "standalone.mjs") {
+1 -3
View File
@@ -135,9 +135,7 @@ async function buildDependenciesLicense({
} }
const shouldBuildLicense = const shouldBuildLicense =
!cliOptions.playground && !cliOptions.files && typeof cliOptions.minify !== "boolean";
!cliOptions.files &&
typeof cliOptions.minify !== "boolean";
if (!shouldBuildLicense) { if (!shouldBuildLicense) {
return { skipped: true }; return { skipped: true };
+1 -1
View File
@@ -224,7 +224,7 @@ function getEsbuildOptions({ packageConfig, file, cliOptions }) {
bundle: true, bundle: true,
metafile: true, metafile: true,
plugins: [ plugins: [
esbuildPluginPrimitiveDefine(define), esbuildPluginPrimitiveDefine({ ...define, ...buildOptions.define }),
esbuildPluginEvaluate(), esbuildPluginEvaluate(),
esbuildPluginStripNodeProtocol(), esbuildPluginStripNodeProtocol(),
esbuildPluginReplaceModule({ esbuildPluginReplaceModule({
+33 -1
View File
@@ -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) { function pick(object, keys) {
keys = new Set(keys); keys = new Set(keys);
return Object.fromEntries( return Object.fromEntries(
@@ -148,4 +176,8 @@ function pick(object, keys) {
); );
} }
export { buildPluginOxcPackageJson, buildPrettierPackageJson }; export {
buildPluginHermesPackageJson,
buildPluginOxcPackageJson,
buildPrettierPackageJson,
};
+1 -4
View File
@@ -60,10 +60,7 @@ async function buildFile({ packageConfig, file, cliOptions, results }) {
if ( if (
(cliOptions.files && !cliOptions.files.has(file.output.file)) || (cliOptions.files && !cliOptions.files.has(file.output.file)) ||
(cliOptions.playground && (cliOptions.playground && !file.playground)
(file.output.format !== "esm" ||
file.platform !== "universal" ||
file.output.file === "doc.mjs"))
) { ) {
console.log(status.SKIPPED); console.log(status.SKIPPED);
return; return;
+97
View File
@@ -7,6 +7,7 @@ import { copyFile, DIST_DIR, PROJECT_ROOT } from "../utils/index.js";
import buildDependenciesLicense from "./build-dependencies-license.js"; import buildDependenciesLicense from "./build-dependencies-license.js";
import buildJavascriptModule from "./build-javascript-module.js"; import buildJavascriptModule from "./build-javascript-module.js";
import { import {
buildPluginHermesPackageJson,
buildPluginOxcPackageJson, buildPluginOxcPackageJson,
buildPrettierPackageJson, buildPrettierPackageJson,
} from "./build-package-json.js"; } from "./build-package-json.js";
@@ -738,6 +739,7 @@ const universalFiles = [...nonPluginUniversalFiles, ...pluginFiles].flatMap(
isPlugin, isPlugin,
build: buildJavascriptModule, build: buildJavascriptModule,
kind: "javascript", kind: "javascript",
playground: output.format === "esm" && outputBaseName !== "doc",
})), })),
getTypesFileConfig({ input, outputBaseName, isPlugin }), 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",
})),
],
},
]; ];
+2 -1
View File
@@ -44,6 +44,7 @@ function getCommentChildNodes(node, options) {
if ( if (
(options.parser === "typescript" || (options.parser === "typescript" ||
options.parser === "flow" || options.parser === "flow" ||
options.parser === "hermes" ||
options.parser === "acorn" || options.parser === "acorn" ||
options.parser === "oxc" || options.parser === "oxc" ||
options.parser === "oxc-ts" || options.parser === "oxc-ts" ||
@@ -81,7 +82,7 @@ function willPrintOwnComments(path) {
} }
function isGap(text, { parser }) { function isGap(text, { parser }) {
if (parser === "flow" || parser === "babel-flow") { if (parser === "flow" || parser === "hermes" || parser === "babel-flow") {
// Example: (a /* b */ /* : c */) // Example: (a /* b */ /* : c */)
// gap ^^^^ // gap ^^^^
text = text.replaceAll(/[\s(]/gu, ""); text = text.replaceAll(/[\s(]/gu, "");
+8 -4
View File
@@ -27,10 +27,14 @@ const parseOptions = {
}; };
function createParseError(error) { function createParseError(error) {
const { const { message, loc } = error;
message,
loc: { start, end }, /* c8 ignore next 3 */
} = error; if (!loc) {
return error;
}
const { start, end } = loc;
return createError(message, { return createError(message, {
loc: { loc: {
+51
View File
@@ -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);
+5
View File
@@ -8,6 +8,11 @@ import jsxRegexp from "./utils/jsx-regexp.evaluate.js";
import { getSourceType } from "./utils/source-types.js"; import { getSourceType } from "./utils/source-types.js";
function createParseError(error, { text }) { function createParseError(error, { text }) {
/* c8 ignore next 3 */
if (!error?.labels?.[0]) {
return error;
}
const { const {
message, message,
labels: [{ start: startIndex, end: endIndex }], labels: [{ start: startIndex, end: endIndex }],
+9 -1
View File
@@ -134,10 +134,11 @@ function postprocess(ast, options) {
break; break;
case "TemplateElement": 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 // https://github.com/eslint/js/blob/5826877f7b33548e5ba984878dd4a8eac8448f87/packages/espree/lib/espree.js#L213
if ( if (
parser === "flow" || parser === "flow" ||
parser === "hermes" ||
parser === "espree" || parser === "espree" ||
parser === "typescript" || parser === "typescript" ||
(parser === "oxc" && options.oxcAstType === "ts") (parser === "oxc" && options.oxcAstType === "ts")
@@ -215,6 +216,13 @@ function postprocess(ast, options) {
delete node.members; delete node.members;
} }
break; 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 */ /* c8 ignore next 3 */
+4 -5
View File
@@ -30,15 +30,14 @@ const baseParseOptions = {
}; };
function createParseError(error) { function createParseError(error) {
const { message, location } = error;
/* c8 ignore next 3 -- not a parse error */ /* c8 ignore next 3 -- not a parse error */
if (!error?.location) { if (!location) {
return error; return error;
} }
const { const { start, end } = location;
message,
location: { start, end },
} = error;
return createError(message, { return createError(message, {
loc: { loc: {
@@ -1,13 +1,16 @@
import createError from "../../../common/parser-create-error.js"; import createError from "../../../common/parser-create-error.js";
function createBabelParseError(error) { 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 // babel error prints (line:column) with cols that are zero indexed
// so we need our custom error // so we need our custom error
let { const { line, column } = loc;
message,
loc: { line, column },
reasonCode,
} = error;
let cause = error; let cause = error;
if (reasonCode === "MissingPlugin" || reasonCode === "MissingOneOfPlugins") { if (reasonCode === "MissingPlugin" || reasonCode === "MissingOneOfPlugins") {
+1
View File
@@ -170,6 +170,7 @@ function isSourceElement(opts, node, parentNode) {
} }
switch (opts.parser) { switch (opts.parser) {
case "flow": case "flow":
case "hermes":
case "babel": case "babel":
case "babel-flow": case "babel-flow":
case "babel-ts": case "babel-ts":
+43 -9
View File
@@ -103,6 +103,23 @@ const oxcTsDisabledTests = new Set(
"typescript/decorators/abstract-method.ts", "typescript/decorators/abstract-method.ts",
].map((file) => path.join(__dirname, "../format", file)), ].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 isUnstable = (filename, options) => {
const testFunction = unstableTests.get(filename); const testFunction = unstableTests.get(filename);
@@ -274,6 +291,14 @@ function runFormatTest(fixtures, parsers, options) {
allParsers.push("babel-flow"); 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")) { if (parsers.includes("babel") && !parsers.includes("__babel_estree")) {
allParsers.push("__babel_estree"); allParsers.push("__babel_estree");
} }
@@ -314,6 +339,7 @@ function runFormatTest(fixtures, parsers, options) {
(currentParser === "meriyah" && meriyahDisabledTests.has(filename)) || (currentParser === "meriyah" && meriyahDisabledTests.has(filename)) ||
(currentParser === "oxc" && oxcDisabledTests.has(filename)) || (currentParser === "oxc" && oxcDisabledTests.has(filename)) ||
(currentParser === "oxc-ts" && oxcTsDisabledTests.has(filename)) || (currentParser === "oxc-ts" && oxcTsDisabledTests.has(filename)) ||
(currentParser === "hermes" && hermesDisabledTests.has(filename)) ||
(currentParser === "babel-ts" && babelTsDisabledTests.has(filename)) (currentParser === "babel-ts" && babelTsDisabledTests.has(filename))
) { ) {
continue; continue;
@@ -487,9 +513,11 @@ function shouldSkipEolTest(code, options) {
async function parse(source, options) { async function parse(source, options) {
const prettier = await getPrettier(); const prettier = await getPrettier();
const { ast } = await prettier.__debug.parse(source, options, { const { ast } = await ensurePromise(
massage: true, prettier.__debug.parse(source, await loadPlugins(options), {
}); massage: true,
}),
);
return ast; return ast;
} }
@@ -534,16 +562,15 @@ const insertCursor = (text, cursorOffset) =>
text.slice(cursorOffset) text.slice(cursorOffset)
: text; : text;
async function format(originalText, originalOptions) { async function format(originalText, originalOptions) {
let { text: input, options } = replacePlaceholders( const { text: input, options } = replacePlaceholders(
originalText, originalText,
originalOptions, originalOptions,
); );
options = await loadPlugins(options);
const inputWithCursor = insertCursor(input, options.cursorOffset); const inputWithCursor = insertCursor(input, options.cursorOffset);
const prettier = await getPrettier(); const prettier = await getPrettier();
const { formatted: output, cursorOffset } = await ensurePromise( const { formatted: output, cursorOffset } = await ensurePromise(
prettier.formatWithCursor(input, options), prettier.formatWithCursor(input, await loadPlugins(options)),
); );
const outputWithCursor = insertCursor(output, cursorOffset); const outputWithCursor = insertCursor(output, cursorOffset);
const eolVisualizedOutput = visualizeEndOfLine(outputWithCursor); 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) { 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 plugins = options.plugins ?? [];
const pluginName = externalPlugins.get(parser);
const url = new URL( const url = new URL(
isProduction isProduction
? "../../dist/plugin-oxc/index.mjs" ? `../../dist/${pluginName}/index.mjs`
: "../../packages/plugin-oxc/index.js", : `../../packages/${pluginName}/index.js`,
import.meta.url, import.meta.url,
); );
plugins.push(TEST_STANDALONE ? await import(url) : url); plugins.push(TEST_STANDALONE ? await import(url) : url);
@@ -1,5 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // 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`] = ` exports[`const.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["flow"] 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`] = ` exports[`rebinding.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["flow"] 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`] = ` exports[`scope.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["flow"] parsers: ["flow"]
@@ -1 +1,3 @@
runFormatTest(import.meta, ["flow"]); runFormatTest(import.meta, ["flow"], {
errors: { hermes: ["const.js", "rebinding.js", "scope.js"] },
});
@@ -1,5 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // 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`] = ` exports[`test.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["flow"] parsers: ["flow"]
@@ -1 +1,5 @@
runFormatTest(import.meta, ["flow"]); runFormatTest(import.meta, ["flow"], {
errors: {
hermes:["test.js"],
},
});
@@ -1,5 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // 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`] = ` exports[`test.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["flow"] parsers: ["flow"]
@@ -1 +1,2 @@
runFormatTest(import.meta, ["flow"]); runFormatTest(import.meta, ["flow"], {errors: { hermes: ["test.js"] }
});
@@ -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`] = ` exports[`test.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["flow"] parsers: ["flow"]
@@ -1 +1 @@
runFormatTest(import.meta, ["flow"]); runFormatTest(import.meta, ["flow"], { errors: { hermes: ["test.js"] } });
@@ -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`] = ` exports[`bad_shadowing.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["flow"] 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`] = ` exports[`good_shadowing.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["flow"] parsers: ["flow"]
@@ -1 +1,5 @@
runFormatTest(import.meta, ["flow"]); runFormatTest(import.meta, ["flow"], {
errors: {
hermes: ["bad_shadowing.js", "good_shadowing.js"],
},
});
@@ -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`] = ` exports[`update.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["flow"] parsers: ["flow"]
+5 -1
View File
@@ -1 +1,5 @@
runFormatTest(import.meta, ["flow"]); runFormatTest(import.meta, ["flow"], {
errors: {
hermes: ["update.js"],
},
});
@@ -428,6 +428,20 @@ exports[`satisfies.js [babel-flow] format 1`] = `
Cause: Unexpected token, expected "type" (32:7)" 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`] = ` exports[`satisfies.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["flow"] parsers: ["flow"]
@@ -532,6 +546,19 @@ exports[`ternary.js [babel-flow] format 1`] = `
Cause: Unexpected token, expected "," (28:31)" 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`] = ` exports[`ternary.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["flow"] parsers: ["flow"]
@@ -1 +1,6 @@
runFormatTest(import.meta, ["flow"], { errors: { "babel-flow": true } }); runFormatTest(import.meta, ["flow"], {
errors: {
"babel-flow": true,
hermes: ["satisfies.js", "ternary.js"],
},
});
@@ -92,10 +92,10 @@ printWidth: 80
const map: Map<Function, Map<string | void, { value: UnloadedDescriptor }>> = const map: Map<Function, Map<string | void, { value: UnloadedDescriptor }>> =
new Map(); new Map();
const map: Map<Function, FunctionFunctionFunctionFunctionffFunction> = const ma2: Map<Function, FunctionFunctionFunctionFunctionffFunction> =
new Map(); new Map();
const map: Map<Function, Foo<S>> = new Map(); const ma3: Map<Function, Foo<S>> = new Map();
=====================================output===================================== =====================================output=====================================
const map: Map< const map: Map<
@@ -103,10 +103,10 @@ const map: Map<
Map<string | void, { value: UnloadedDescriptor }>, Map<string | void, { value: UnloadedDescriptor }>,
> = new Map(); > = new Map();
const map: Map<Function, FunctionFunctionFunctionFunctionffFunction> = const ma2: Map<Function, FunctionFunctionFunctionFunctionffFunction> =
new Map(); new Map();
const map: Map<Function, Foo<S>> = new Map(); const ma3: Map<Function, Foo<S>> = new Map();
================================================================================ ================================================================================
`; `;
+2 -2
View File
@@ -1,7 +1,7 @@
const map: Map<Function, Map<string | void, { value: UnloadedDescriptor }>> = const map: Map<Function, Map<string | void, { value: UnloadedDescriptor }>> =
new Map(); new Map();
const map: Map<Function, FunctionFunctionFunctionFunctionffFunction> = const ma2: Map<Function, FunctionFunctionFunctionFunctionffFunction> =
new Map(); new Map();
const map: Map<Function, Foo<S>> = new Map(); const ma3: Map<Function, Foo<S>> = new Map();
@@ -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)" 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`] = ` exports[`await-keywords.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["flow"] parsers: ["flow"]
+4 -1
View File
@@ -1,3 +1,6 @@
runFormatTest(import.meta, ["flow"], { runFormatTest(import.meta, ["flow"], {
errors: { "babel-flow": ["await-keywords.js"] }, errors: {
"babel-flow": ["await-keywords.js"],
hermes: ["await-keywords.js"],
},
}); });
@@ -7,17 +7,17 @@ printWidth: 80
| printWidth | printWidth
=====================================input====================================== =====================================input======================================
class A implements B {} class A implements B {}
class A implements B, C {} class B implements B, C {}
declare class A implements B {} declare class C implements B {}
declare class A mixins B implements C {} declare class D mixins B implements C {}
declare class A implements B, C {} declare class E implements B, C {}
=====================================output===================================== =====================================output=====================================
class A implements B {} class A implements B {}
class A implements B, C {} class B implements B, C {}
declare class A implements B {} declare class C implements B {}
declare class A mixins B implements C {} declare class D mixins B implements C {}
declare class A implements B, C {} declare class E implements B, C {}
================================================================================ ================================================================================
`; `;
+4 -4
View File
@@ -1,5 +1,5 @@
class A implements B {} class A implements B {}
class A implements B, C {} class B implements B, C {}
declare class A implements B {} declare class C implements B {}
declare class A mixins B implements C {} declare class D mixins B implements C {}
declare class A implements B, C {} declare class E implements B, C {}
@@ -14,7 +14,7 @@ import { Foo, type Baz } from "../module";
import type {} from 'foo'; import type {} from 'foo';
import type {somethingSuperLongsomethingSuperLong} from 'somethingSuperLongsomethingSuperLongsomethingSuperLong' import type {somethingSuperLongsomethingSuperLong} from 'somethingSuperLongsomethingSuperLongsomethingSuperLong'
import type {a, somethingSuperLongsomethingSuperLong} from 'somethingSuperLongsomethingSuperLongsomethingSuperLong' import type {a, somethingSuperLongsomethingSuperLon2} from 'somethingSuperLongsomethingSuperLongsomethingSuperLong'
import transformRouterContext, { type TransformedContextRouter } from '../../helpers/transformRouterContext'; import transformRouterContext, { type TransformedContextRouter } from '../../helpers/transformRouterContext';
@@ -29,7 +29,7 @@ import type {} from "foo";
import type { somethingSuperLongsomethingSuperLong } from "somethingSuperLongsomethingSuperLongsomethingSuperLong"; import type { somethingSuperLongsomethingSuperLong } from "somethingSuperLongsomethingSuperLongsomethingSuperLong";
import type { import type {
a, a,
somethingSuperLongsomethingSuperLong, somethingSuperLongsomethingSuperLon2,
} from "somethingSuperLongsomethingSuperLongsomethingSuperLong"; } from "somethingSuperLongsomethingSuperLongsomethingSuperLong";
import transformRouterContext, { import transformRouterContext, {
@@ -6,6 +6,6 @@ import { Foo, type Baz } from "../module";
import type {} from 'foo'; import type {} from 'foo';
import type {somethingSuperLongsomethingSuperLong} from 'somethingSuperLongsomethingSuperLongsomethingSuperLong' import type {somethingSuperLongsomethingSuperLong} from 'somethingSuperLongsomethingSuperLongsomethingSuperLong'
import type {a, somethingSuperLongsomethingSuperLong} from 'somethingSuperLongsomethingSuperLongsomethingSuperLong' import type {a, somethingSuperLongsomethingSuperLon2} from 'somethingSuperLongsomethingSuperLongsomethingSuperLong'
import transformRouterContext, { type TransformedContextRouter } from '../../helpers/transformRouterContext'; import transformRouterContext, { type TransformedContextRouter } from '../../helpers/transformRouterContext';
@@ -8,18 +8,32 @@ printWidth: 80
=====================================input====================================== =====================================input======================================
// @flow // @flow
import { foo as as } from "foo"; import { foo as as } from "foo";
import { as as as } from "foo";
import { as as foo } from "foo"; import { as as foo } from "foo";
=====================================output===================================== =====================================output=====================================
// @flow // @flow
import { foo as as } from "foo"; import { foo as as } from "foo";
import { as as as } from "foo";
import { as as foo } 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`] = ` exports[`type-import-as-as.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["flow"] parsers: ["flow"]
-1
View File
@@ -1,4 +1,3 @@
// @flow // @flow
import { foo as as } from "foo"; import { foo as as } from "foo";
import { as as as } from "foo";
import { as as foo } from "foo"; import { as as foo } from "foo";
@@ -0,0 +1,2 @@
// @flow
import { as as as } from "foo";
@@ -58,3 +58,51 @@ exports[`arrows.js [flow] format 1`] = `
8 | 8 |
9 | (a ? (b = c) : d => e : f); // a ? ((b = c): d => e) : f" 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)
================================================================================
`;
@@ -51,7 +51,7 @@ class C<const T>{}
type T<const +X> = X; type T<const +X> = X;
function f<const +T>(): void {} function f<const +T>(): void {}
<const +T>(x: T) => {} <const +T>(x: T) => {}
class C<const +T>{} class D<const +T>{}
=====================================output===================================== =====================================output=====================================
// Simple // Simple
@@ -64,7 +64,7 @@ class C<const T> {}
type T<const +X> = X; type T<const +X> = X;
function f<const +T>(): void {} function f<const +T>(): void {}
<const +T>(x: T) => {}; <const +T>(x: T) => {};
class C<const +T> {} class D<const +T> {}
================================================================================ ================================================================================
`; `;
@@ -8,4 +8,4 @@ class C<const T>{}
type T<const +X> = X; type T<const +X> = X;
function f<const +T>(): void {} function f<const +T>(): void {}
<const +T>(x: T) => {} <const +T>(x: T) => {}
class C<const +T>{} class D<const +T>{}
@@ -1,5 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // 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`] = ` exports[`binaryish.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "flow", "typescript"] parsers: ["babel", "flow", "typescript"]
+5 -1
View File
@@ -1 +1,5 @@
runFormatTest(import.meta, ["babel", "flow", "typescript"]); runFormatTest(import.meta, ["babel", "flow", "typescript"], {
errors: {
hermes: ["binaryish.js"],
},
});
@@ -26,6 +26,17 @@ exports[`arguments.js [flow] format 1`] = `
3 |" 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`] = ` exports[`arguments.js - {"semi":false} [acorn] format 1`] = `
"Unexpected character '@' (1:13) "Unexpected character '@' (1:13)
> 1 | console.log(@deco class Foo {}) > 1 | console.log(@deco class Foo {})
@@ -52,6 +63,17 @@ exports[`arguments.js - {"semi":false} [flow] format 1`] = `
3 |" 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`] = ` exports[`arguments.js - {"semi":false} format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "flow", "typescript"] parsers: ["babel", "flow", "typescript"]
@@ -126,6 +148,18 @@ exports[`class-expression.js [flow] format 1`] = `
4 | (@deco class Foo {});" 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`] = ` exports[`class-expression.js - {"semi":false} [acorn] format 1`] = `
"Unexpected character '@' (1:13) "Unexpected character '@' (1:13)
> 1 | const a1 = (@deco class Foo {}); > 1 | const a1 = (@deco class Foo {});
@@ -155,6 +189,18 @@ exports[`class-expression.js - {"semi":false} [flow] format 1`] = `
4 | (@deco class Foo {});" 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`] = ` exports[`class-expression.js - {"semi":false} format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "flow", "typescript"] parsers: ["babel", "flow", "typescript"]
@@ -296,6 +342,17 @@ exports[`member-expression.js [flow] format 1`] = `
3 |" 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`] = ` exports[`member-expression.js - {"semi":false} [acorn] format 1`] = `
"Unexpected character '@' (1:2) "Unexpected character '@' (1:2)
> 1 | (@deco class Foo {}).name; > 1 | (@deco class Foo {}).name;
@@ -322,6 +379,17 @@ exports[`member-expression.js - {"semi":false} [flow] format 1`] = `
3 |" 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`] = ` exports[`member-expression.js - {"semi":false} format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "flow", "typescript"] parsers: ["babel", "flow", "typescript"]
@@ -396,6 +464,18 @@ exports[`super-class.js [flow] format 1`] = `
4 |" 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`] = ` exports[`super-class.js - {"semi":false} [acorn] format 1`] = `
"Unexpected character '@' (1:20) "Unexpected character '@' (1:20)
> 1 | class Foo extends (@deco class Foo {}){} > 1 | class Foo extends (@deco class Foo {}){}
@@ -425,6 +505,18 @@ exports[`super-class.js - {"semi":false} [flow] format 1`] = `
4 |" 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`] = ` exports[`super-class.js - {"semi":false} format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "flow", "typescript"] parsers: ["babel", "flow", "typescript"]
@@ -1,5 +1,6 @@
const errors = { const errors = {
flow: true, flow: true,
hermes: true,
acorn: true, acorn: true,
espree: true, espree: true,
}; };
@@ -1,5 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // 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`] = ` exports[`destructuring.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "flow", "typescript"] parsers: ["babel", "flow", "typescript"]
+5 -1
View File
@@ -1 +1,5 @@
runFormatTest(import.meta, ["babel", "flow", "typescript"]); runFormatTest(import.meta, ["babel", "flow", "typescript"], {
errors: {
hermes: ["destructuring.js"],
},
});
@@ -50,6 +50,21 @@ exports[`import-phase.js [flow] format 1`] = `
4 |" 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`] = ` exports[`import-phase.js [meriyah] format 1`] = `
"The only valid meta property for import is 'import.meta' (1:8) "The only valid meta property for import is 'import.meta' (1:8)
> 1 | import.source(\`data:text/javascript, > 1 | import.source(\`data:text/javascript,
@@ -95,6 +110,18 @@ exports[`template-literal.js [flow] format 1`] = `
4 |" 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`] = ` exports[`template-literal.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "flow", "typescript"] parsers: ["babel", "flow", "typescript"]
@@ -1,6 +1,7 @@
runFormatTest(import.meta, ["babel", "flow", "typescript"], { runFormatTest(import.meta, ["babel", "flow", "typescript"], {
errors: { errors: {
flow: ["assertions.js", "template-literal.js", "import-phase.js"], flow: ["assertions.js", "template-literal.js", "import-phase.js"],
hermes: ["template-literal.js", "import-phase.js"],
acorn: ["import-phase.js"], acorn: ["import-phase.js"],
espree: ["import-phase.js"], espree: ["import-phase.js"],
meriyah: ["import-phase.js"], meriyah: ["import-phase.js"],
@@ -23,6 +23,16 @@ exports[`for-await-using-of-comments.js [flow] format 1`] = `
2 |" 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`] = ` exports[`for-await-using-of-comments.js [meriyah] format 1`] = `
"for await (... of ...) is only valid in async functions and async generators (1:51) "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*/; > 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();" 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`] = ` exports[`invalid-duplicate-using-bindings.js [meriyah] format 1`] = `
"Unexpected token: 'identifier' (2:9) "Unexpected token: 'identifier' (2:9)
1 | { 1 | {
@@ -138,6 +161,16 @@ exports[`invalid-script-top-level-using-binding.js [flow] format 1`] = `
2 |" 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`] = ` exports[`invalid-script-top-level-using-binding.js [meriyah] format 1`] = `
"Unexpected token: 'identifier' (1:7) "Unexpected token: 'identifier' (1:7)
> 1 | using x = bar(); > 1 | using x = bar();
@@ -192,6 +225,19 @@ exports[`using-declarations.js [flow] format 1`] = `
5 | for(using /* 1 */ a = foo(), /* 2 */ b = foo();;);" 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`] = ` exports[`using-declarations.js [meriyah] format 1`] = `
"Unexpected token: 'identifier' (2:17) "Unexpected token: 'identifier' (2:17)
1 | { 1 | {
@@ -347,6 +393,18 @@ exports[`valid-await-using-binding-basic.js [flow] format 1`] = `
4 |" 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`] = ` exports[`valid-await-using-binding-basic.js [meriyah] format 1`] = `
"Unexpected token: 'identifier' (2:15) "Unexpected token: 'identifier' (2:15)
1 | async function f() { 1 | async function f() {
@@ -404,6 +462,18 @@ exports[`valid-await-using-binding-escaped.js [flow] format 1`] = `
4 |" 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`] = ` exports[`valid-await-using-binding-escaped.js [meriyah] format 1`] = `
"Unexpected token: 'identifier' (2:15) "Unexpected token: 'identifier' (2:15)
1 | async function f() { 1 | async function f() {
@@ -461,6 +531,17 @@ exports[`valid-await-using-binding-non-bmp.js [flow] format 1`] = `
4 |" 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`] = ` exports[`valid-await-using-binding-non-bmp.js [meriyah] format 1`] = `
"Unexpected token: 'identifier' (2:15) "Unexpected token: 'identifier' (2:15)
1 | async function f() { 1 | async function f() {
@@ -521,6 +602,19 @@ exports[`valid-await-using-binding-using.js [flow] format 1`] = `
5 |" 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`] = ` exports[`valid-await-using-binding-using.js [meriyah] format 1`] = `
"Unexpected token: 'identifier' (2:15) "Unexpected token: 'identifier' (2:15)
1 | async function f() { 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*/;" 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`] = ` exports[`valid-await-using-comments.js [meriyah] format 1`] = `
"Unexpected token: 'identifier' (3:28) "Unexpected token: 'identifier' (3:28)
1 | async function f() { 1 | async function f() {
@@ -720,6 +828,19 @@ exports[`valid-for-using-binding-of-of.js [flow] format 1`] = `
5 |" 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`] = ` exports[`valid-for-using-binding-of-of.js [meriyah] format 1`] = `
"Invalid left-hand side in for-of (2:20) "Invalid left-hand side in for-of (2:20)
1 | async function f() { 1 | async function f() {
@@ -780,6 +901,18 @@ exports[`valid-for-using-declaration.js [flow] format 1`] = `
4 |" 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`] = ` exports[`valid-for-using-declaration.js [meriyah] format 1`] = `
"Expected ';' (2:20) "Expected ';' (2:20)
1 | async function f() { 1 | async function f() {
@@ -847,6 +980,18 @@ exports[`valid-module-block-top-level-await-using-binding.js [flow] format 1`] =
4 |" 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`] = ` exports[`valid-module-block-top-level-await-using-binding.js [meriyah] format 1`] = `
"Unexpected token: '{' (1:18) "Unexpected token: '{' (1:18)
> 1 | const m = module { > 1 | const m = module {
@@ -932,6 +1077,18 @@ exports[`valid-module-block-top-level-using-binding.js [flow] format 1`] = `
4 |" 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`] = ` exports[`valid-module-block-top-level-using-binding.js [meriyah] format 1`] = `
"Unexpected token: '{' (1:8) "Unexpected token: '{' (1:8)
> 1 | module { > 1 | module {
@@ -1027,6 +1184,16 @@ exports[`valid-using-as-identifier-for-await-of.js [flow] format 1`] = `
2 |" 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`] = ` exports[`valid-using-as-identifier-for-await-of.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "flow", "typescript"] parsers: ["babel", "flow", "typescript"]
@@ -1140,6 +1307,18 @@ exports[`valid-using-binding-basic.js [flow] format 1`] = `
4 |" 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`] = ` exports[`valid-using-binding-basic.js [meriyah] format 1`] = `
"Unexpected token: 'identifier' (2:9) "Unexpected token: 'identifier' (2:9)
1 | { 1 | {
@@ -1191,6 +1370,16 @@ exports[`valid-using-binding-escaped.js [flow] format 1`] = `
2 |" 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`] = ` exports[`valid-using-binding-escaped.js [meriyah] format 1`] = `
"Unexpected token: 'identifier' (1:9) "Unexpected token: 'identifier' (1:9)
> 1 | { using \\u0061b = c; } > 1 | { using \\u0061b = c; }
@@ -1238,6 +1427,15 @@ exports[`valid-using-binding-non-bmp.js [flow] format 1`] = `
2 |" 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`] = ` exports[`valid-using-binding-non-bmp.js [meriyah] format 1`] = `
"Unexpected token: 'identifier' (1:9) "Unexpected token: 'identifier' (1:9)
> 1 | { using 𠮷 = foo(); } > 1 | { using 𠮷 = foo(); }
@@ -1294,6 +1492,19 @@ exports[`valid-using-binding-using.js [flow] format 1`] = `
5 |" 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`] = ` exports[`valid-using-binding-using.js [meriyah] format 1`] = `
"Unexpected token: 'identifier' (2:9) "Unexpected token: 'identifier' (2:9)
1 | { 1 | {
@@ -24,6 +24,30 @@ runFormatTest(import.meta, ["babel", "flow", "typescript"], {
"valid-for-using-declaration.js", "valid-for-using-declaration.js",
"valid-module-block-top-level-await-using-binding.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: [ typescript: [
// https://github.com/typescript-eslint/typescript-eslint/blob/4f34d0ba34474926ba1eed623704b583a037f886/packages/typescript-estree/src/convert.ts#L1035-L1050 // https://github.com/typescript-eslint/typescript-eslint/blob/4f34d0ba34474926ba1eed623704b583a037f886/packages/typescript-estree/src/convert.ts#L1035-L1050
"valid-for-using-declaration.js", "valid-for-using-declaration.js",
@@ -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`] = ` exports[`default-escaped.js [meriyah] format 1`] = `
"Unexpected token: 'identifier' (2:8) "Unexpected token: 'identifier' (2:8)
1 | // export asyn\\u{63} from "async"; 1 | // export asyn\\u{63} from "async";
@@ -4,6 +4,7 @@ runFormatTest(import.meta, ["babel", "flow"], {
espree: true, espree: true,
meriyah: true, meriyah: true,
flow: true, flow: true,
hermes: true,
oxc: true, oxc: true,
"oxc-ts": true, "oxc-ts": true,
}, },
@@ -71,6 +71,16 @@ exports[`export-star-as-string.js [flow] format 1`] = `
2 |" 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`] = ` exports[`export-star-as-string.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "flow", "typescript"] parsers: ["babel", "flow", "typescript"]
@@ -92,6 +102,16 @@ exports[`export-star-as-string2.js [flow] format 1`] = `
2 |" 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`] = ` exports[`export-star-as-string2.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "flow", "typescript"] parsers: ["babel", "flow", "typescript"]
@@ -1,5 +1,6 @@
runFormatTest(import.meta, ["babel", "flow", "typescript"], { runFormatTest(import.meta, ["babel", "flow", "typescript"], {
errors: { errors: {
flow: ["export-star-as-string.js", "export-star-as-string2.js"], flow: ["export-star-as-string.js", "export-star-as-string2.js"],
hermes: ["export-star-as-string.js", "export-star-as-string2.js"],
}, },
}); });
@@ -35,6 +35,20 @@ exports[`class-expression-decorator.js [flow] format 1`] = `
6 |" 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`] = ` exports[`class-expression-decorator.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "flow", "typescript"] parsers: ["babel", "flow", "typescript"]
@@ -77,6 +91,17 @@ exports[`decorator.js [espree] format 1`] = `
Cause: Unexpected character '@'" 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`] = ` exports[`decorator.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "flow", "typescript"] parsers: ["babel", "flow", "typescript"]
+1
View File
@@ -3,5 +3,6 @@ runFormatTest(import.meta, ["babel", "flow", "typescript"], {
acorn: ["decorator.js", "class-expression-decorator.js"], acorn: ["decorator.js", "class-expression-decorator.js"],
espree: ["decorator.js", "class-expression-decorator.js"], espree: ["decorator.js", "class-expression-decorator.js"],
flow: ["class-expression-decorator.js"], flow: ["class-expression-decorator.js"],
hermes: ["decorator.js", "class-expression-decorator.js"],
}, },
}); });
@@ -33,6 +33,20 @@ exports[`text.js [flow] format 1`] = `
4 | foo = markdown\`\\u{prettier}\\u{0065}\`;" 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`] = ` exports[`text.js [meriyah] format 1`] = `
"Invalid hexadecimal escape sequence (6:17) "Invalid hexadecimal escape sequence (6:17)
4 | foo = markdown\`\\u{prettier}\\u{0065}\`; 4 | foo = markdown\`\\u{prettier}\\u{0065}\`;
@@ -3,6 +3,7 @@ runFormatTest(import.meta, ["babel", "flow", "typescript"], {
acorn: true, acorn: true,
espree: true, espree: true,
flow: true, flow: true,
hermes: true,
typescript: true, typescript: true,
meriyah: true, meriyah: true,
oxc: true, oxc: true,
@@ -23,6 +23,16 @@ exports[`outside-functions.js [flow] format 1`] = `
2 |" 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`] = ` exports[`outside-functions.js [meriyah] format 1`] = `
"new.target only allowed within functions or static blocks (1:15) "new.target only allowed within functions or static blocks (1:15)
> 1 | const x = new.target; > 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`] = ` exports[`range.js [meriyah] format 1`] = `
"new.target only allowed within functions or static blocks (2:5) "new.target only allowed within functions or static blocks (2:5)
1 | const x = 1 | const x =
@@ -4,5 +4,6 @@ runFormatTest(import.meta, ["babel", "flow", "typescript"], {
espree: true, espree: true,
meriyah: true, meriyah: true,
flow: true, flow: true,
hermes: true,
}, },
}); });
@@ -1,5 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // 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`] = ` exports[`bigint-key.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "typescript", "flow"] parsers: ["babel", "typescript", "flow"]
@@ -105,6 +117,20 @@ exports[`expression.js [flow] format 1`] = `
8 | ({} = 0);" 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`] = ` exports[`expression.js [meriyah] format 1`] = `
"Expected ')' (5:4) "Expected ')' (5:4)
3 | a = () => ({}).x; 3 | a = () => ({}).x;
+1
View File
@@ -7,5 +7,6 @@ runFormatTest(import.meta, ["babel", "typescript", "flow"], {
oxc: ["expression.js"], oxc: ["expression.js"],
"oxc-ts": ["expression.js"], "oxc-ts": ["expression.js"],
flow: ["expression.js"], flow: ["expression.js"],
hermes: ["expression.js", "bigint-key.js"],
}, },
}); });
@@ -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`] = ` exports[`eval-arguments.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "flow", "typescript"] parsers: ["babel", "flow", "typescript"]
@@ -96,6 +109,16 @@ exports[`function-declaration-in-while.js [flow] format 1`] = `
2 |" 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`] = ` 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) "In strict mode code, functions can only be declared at top level or inside a block (1:15)
> 1 | while (false) function foo(){} > 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`] = ` exports[`labeled-function-declaration.js format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["babel", "flow", "typescript"] parsers: ["babel", "flow", "typescript"]
@@ -1,6 +1,11 @@
runFormatTest(import.meta, ["babel", "flow", "typescript"], { runFormatTest(import.meta, ["babel", "flow", "typescript"], {
errors: { errors: {
flow: ["function-declaration-in-while.js"], 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"], acorn: ["function-declaration-in-while.js"],
espree: ["function-declaration-in-while.js"], espree: ["function-declaration-in-while.js"],
meriyah: ["function-declaration-in-while.js"], meriyah: ["function-declaration-in-while.js"],
@@ -97,26 +97,26 @@ parsers: ["typescript", "flow"]
printWidth: 80 printWidth: 80
| printWidth | printWidth
=====================================input====================================== =====================================input======================================
class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong { class looooooooooooooooooong1 extends looooooooooooooooooong implements loooooooooooooooooooong {
// leading comment // leading comment
property: string; property: string;
} }
class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong { class looooooooooooooooooong2 extends looooooooooooooooooong implements loooooooooooooooooooong {
property: string; property: string;
} }
class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong { class looooooooooooooooooong3 extends looooooooooooooooooong implements loooooooooooooooooooong {
property: string; property: string;
} }
class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong, loooooooooooooooooooong, loooooooooooooooooooong { class looooooooooooooooooong4 extends looooooooooooooooooong implements loooooooooooooooooooong, loooooooooooooooooooong, loooooooooooooooooooong {
property: string; property: string;
} }
=====================================output===================================== =====================================output=====================================
class loooooooooooooooooooong class looooooooooooooooooong1
extends looooooooooooooooooong extends looooooooooooooooooong
implements loooooooooooooooooooong implements loooooooooooooooooooong
{ {
@@ -124,21 +124,21 @@ class loooooooooooooooooooong
property: string; property: string;
} }
class loooooooooooooooooooong class looooooooooooooooooong2
extends looooooooooooooooooong extends looooooooooooooooooong
implements loooooooooooooooooooong implements loooooooooooooooooooong
{ {
property: string; property: string;
} }
class loooooooooooooooooooong class looooooooooooooooooong3
extends looooooooooooooooooong extends looooooooooooooooooong
implements loooooooooooooooooooong implements loooooooooooooooooooong
{ {
property: string; property: string;
} }
class loooooooooooooooooooong class looooooooooooooooooong4
extends looooooooooooooooooong extends looooooooooooooooooong
implements implements
loooooooooooooooooooong, loooooooooooooooooooong,
@@ -1,17 +1,17 @@
class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong { class looooooooooooooooooong1 extends looooooooooooooooooong implements loooooooooooooooooooong {
// leading comment // leading comment
property: string; property: string;
} }
class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong { class looooooooooooooooooong2 extends looooooooooooooooooong implements loooooooooooooooooooong {
property: string; property: string;
} }
class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong { class looooooooooooooooooong3 extends looooooooooooooooooong implements loooooooooooooooooooong {
property: string; property: string;
} }
class loooooooooooooooooooong extends looooooooooooooooooong implements loooooooooooooooooooong, loooooooooooooooooooong, loooooooooooooooooooong { class looooooooooooooooooong4 extends looooooooooooooooooong implements loooooooooooooooooooong, loooooooooooooooooooong, loooooooooooooooooooong {
property: string; property: string;
} }
@@ -99,6 +99,16 @@ exports[`template-literal-types.ts [flow] format 1`] = `
2 |" 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`] = ` exports[`template-literal-types.ts format 1`] = `
====================================options===================================== ====================================options=====================================
parsers: ["typescript", "flow"] parsers: ["typescript", "flow"]
@@ -1,6 +1,7 @@
runFormatTest(import.meta, ["typescript", "flow"], { runFormatTest(import.meta, ["typescript", "flow"], {
errors: { errors: {
flow: ["template-literal-types.ts"], flow: ["template-literal-types.ts"],
hermes: ["template-literal-types.ts"],
"babel-flow": ["template-literal-types.ts"], "babel-flow": ["template-literal-types.ts"],
}, },
}); });
@@ -8,26 +8,26 @@ printWidth: 80
trailingComma: "all" trailingComma: "all"
| printWidth | printWidth
=====================================input====================================== =====================================input======================================
const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx<> = const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1: xxxxxxxxxxxxxxxxxxxxxx<> =
arg => null; arg => null;
const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx</* comment */> = const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2: xxxxxxxxxxxxxxxxxxxxxx</* comment */> =
arg => null; arg => null;
const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx< const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3: xxxxxxxxxxxxxxxxxxxxxx<
// comment // comment
> = > =
arg => null; arg => null;
=====================================output===================================== =====================================output=====================================
const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx<> = const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1: xxxxxxxxxxxxxxxxxxxxxx<> =
arg => null; arg => null;
const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx</* comment */> = const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2: xxxxxxxxxxxxxxxxxxxxxx</* comment */> =
arg => null; arg => null;
const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx< const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3: xxxxxxxxxxxxxxxxxxxxxx<
// comment // comment
> = arg => null; > = arg => null;
@@ -1,11 +1,11 @@
const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx<> = const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1: xxxxxxxxxxxxxxxxxxxxxx<> =
arg => null; arg => null;
const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx</* comment */> = const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2: xxxxxxxxxxxxxxxxxxxxxx</* comment */> =
arg => null; arg => null;
const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxx< const xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3: xxxxxxxxxxxxxxxxxxxxxx<
// comment // comment
> = > =
arg => null; arg => null;
+1
View File
@@ -28,6 +28,7 @@ export default function getCodeSamples(parser) {
"}", "}",
].join("\n"); ].join("\n");
case "flow": case "flow":
case "hermes":
case "babel-flow": case "babel-flow":
return [ return [
"declare export function graphql<Props, Variables, Component: React$ComponentType<Props>>", "declare export function graphql<Props, Variables, Component: React$ComponentType<Props>>",
+1
View File
@@ -41,6 +41,7 @@ function getMarkdownSyntax(options) {
case "babel": case "babel":
case "babel-flow": case "babel-flow":
case "flow": case "flow":
case "hermes":
case "acorn": case "acorn":
case "espree": case "espree":
case "meriyah": case "meriyah":
+1
View File
@@ -65,6 +65,7 @@ const astAutoFold = {
export function getAstAutoFold(parser) { export function getAstAutoFold(parser) {
switch (parser) { switch (parser) {
case "flow": case "flow":
case "hermes":
case "babel": case "babel":
case "babel-flow": case "babel-flow":
case "babel-ts": case "babel-ts":
+7
View File
@@ -62,6 +62,13 @@ const plugins = [
createPlugin(plugin), createPlugin(plugin),
), ),
docExplorerPlugin, docExplorerPlugin,
prettierPackageManifest.builtinPlugins.some((plugin) =>
plugin.parsers?.includes("hermes"),
)
? {
languages: [{ name: "hermes", parsers: ["hermes"] }],
}
: {},
]; ];
self.onmessage = async function (event) { self.onmessage = async function (event) {
+2 -1
View File
@@ -2902,7 +2902,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"buffer@npm:^6.0.3": "buffer@npm:6.0.3, buffer@npm:^6.0.3":
version: 6.0.3 version: 6.0.3
resolution: "buffer@npm:6.0.3" resolution: "buffer@npm:6.0.3"
dependencies: dependencies:
@@ -7233,6 +7233,7 @@ __metadata:
angular-html-parser: "npm:8.1.0" angular-html-parser: "npm:8.1.0"
browserslist: "npm:4.24.5" browserslist: "npm:4.24.5"
browserslist-to-esbuild: "npm:2.1.1" browserslist-to-esbuild: "npm:2.1.1"
buffer: "npm:6.0.3"
c8: "npm:10.1.3" c8: "npm:10.1.3"
camelcase: "npm:8.0.0" camelcase: "npm:8.0.0"
ci-info: "npm:4.2.0" ci-info: "npm:4.2.0"