diff --git a/changelog_unreleased/flow/18511.md b/changelog_unreleased/flow/18511.md new file mode 100644 index 000000000..77d6a62d1 --- /dev/null +++ b/changelog_unreleased/flow/18511.md @@ -0,0 +1,23 @@ +#### Add support for Flow match instance patterns and Flow records (#18511 by @gkz) + + +```jsx +// Input +record R { + num: number, +} + +const x = R {num: 1}; + +const label = match (x) { + R {num: 0} => "zero", + R {num: 1} => "one", + R {const num} => `${num} items`, +} + +// Prettier stable +// Unsupported + +// Prettier main +// Same as input +``` diff --git a/package.json b/package.json index aff64f9b1..f1cdba4e1 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "get-east-asian-width": "1.4.0", "get-stdin": "9.0.0", "graphql": "16.12.0", - "hermes-parser": "0.33.0", + "hermes-parser": "0.33.1", "html-element-attributes": "3.5.0", "html-ua-styles": "0.3.1", "ignore": "7.0.5", diff --git a/src/language-js/parse/flow.js b/src/language-js/parse/flow.js index 3f0b0ac43..527e16e40 100644 --- a/src/language-js/parse/flow.js +++ b/src/language-js/parse/flow.js @@ -20,6 +20,7 @@ const parseOptions = { esproposal_export_star_as: true, // Undocumented pattern_matching: true, + records: true, // `types` (boolean, default `true`) - enable parsing of Flow types // types: true, // `use_strict` (boolean, default `false`) - treat the file as strict, without needing a "use strict" directive diff --git a/src/language-js/print/class-body.js b/src/language-js/print/class-body.js index a063a1f5e..53c6b47e7 100644 --- a/src/language-js/print/class-body.js +++ b/src/language-js/print/class-body.js @@ -25,11 +25,13 @@ import { shouldHugTheOnlyParameter } from "./function-parameters.js"; - `TSInterfaceBody` (TypeScript) - `TSTypeLiteral` (TypeScript) - `ObjectTypeAnnotation` (Flow) +- `RecordDeclarationBody` (Flow) */ function printClassBody(path, options, print) { const { node } = path; const parts = []; const isFlowTypeAnnotation = node.type === "ObjectTypeAnnotation"; + const isFlowRecordDeclaration = node.type === "RecordDeclarationBody"; const isObjectType = !isClassBody(path); const separator = isObjectType ? line : hardline; const hasDanglingComments = hasComment(node, CommentCheckFlags.Dangling); @@ -42,7 +44,7 @@ function printClassBody(path, options, print) { firstMember ??= node; parts.push(print()); - if (isObjectType && isFlowTypeAnnotation) { + if (!isFlowRecordDeclaration && isObjectType && isFlowTypeAnnotation) { const { parent } = path; if (parent.inexact || !isLast) { @@ -52,7 +54,12 @@ function printClassBody(path, options, print) { } } + if (isFlowRecordDeclaration && node.type !== "MethodDefinition") { + parts.push(","); + } + if ( + !isFlowRecordDeclaration && !isObjectType && (shouldPrintSemicolonAfterClassProperty({ node, next }, options) || shouldPrintSemicolonAfterInterfaceProperty({ node, next }, options)) @@ -158,7 +165,11 @@ function isClassBody(path) { ); } - return node.type === "ClassBody" || node.type === "TSInterfaceBody"; + return ( + node.type === "ClassBody" || + node.type === "TSInterfaceBody" || + node.type === "RecordDeclarationBody" + ); } function iterateClassMembers(path, iteratee) { @@ -173,6 +184,11 @@ function iterateClassMembers(path, iteratee) { return; } + if (node.type === "RecordDeclarationBody") { + path.each(iteratee, "elements"); + return; + } + if (node.type === "ObjectTypeAnnotation") { // Unfortunately, things grouped together in the ast can be // interleaved in the source code. So we need to reorder them before diff --git a/src/language-js/print/class.js b/src/language-js/print/class.js index 774fa9f01..8f84e9bb0 100644 --- a/src/language-js/print/class.js +++ b/src/language-js/print/class.js @@ -53,18 +53,22 @@ const isInterface = createTypeCheckFunction([ - `DeclareInterface`(flow) - `InterfaceDeclaration`(flow) - `InterfaceTypeAnnotation`(flow) +- `RecordDeclaration`(flow) - `TSInterfaceDeclaration`(TypeScript) */ function printClass(path, options, print) { const { node } = path; const isPrintingInterface = isInterface(node); + const isPrintingRecord = node.type === "RecordDeclaration"; + + const keyword = isPrintingInterface + ? "interface" + : isPrintingRecord + ? "record" + : "class"; /** @type {Doc[]} */ - const parts = [ - printDeclareToken(path), - printAbstractToken(path), - isPrintingInterface ? "interface" : "class", - ]; + const parts = [printDeclareToken(path), printAbstractToken(path), keyword]; // Keep old behaviour of extends in same line // If there is only on extends and there are not comments @@ -146,7 +150,9 @@ function isNonEmptyClassBody(node) { ? ["properties", "indexers", "callProperties", "internalSlots"].some( (property) => isNonEmptyArray(node[property]), ) - : isNonEmptyArray(node.body); + : node.type === "RecordDeclarationBody" + ? isNonEmptyArray(node.elements) + : isNonEmptyArray(node.body); } function hasMultipleHeritage(node) { diff --git a/src/language-js/print/flow.js b/src/language-js/print/flow.js index 044756d68..c92bb8a69 100644 --- a/src/language-js/print/flow.js +++ b/src/language-js/print/flow.js @@ -39,6 +39,7 @@ import { printFlowMappedTypeProperty } from "./mapped-type.js"; import { printMatch, printMatchCase, printMatchPattern } from "./match.js"; import { printDeclareToken, printOptionalToken } from "./miscellaneous.js"; import { printExportDeclaration } from "./module.js"; +import { printObject } from "./object.js"; import { printOpaqueType } from "./opaque-type.js"; import { printPropertyKey } from "./property.js"; import { printSpreadElement } from "./rest-element.js"; @@ -191,12 +192,17 @@ function printFlow(path, options, print) { case "DeclareInterface": case "InterfaceDeclaration": case "InterfaceTypeAnnotation": + case "RecordDeclaration": return printClass(path, options, print); case "ObjectTypeAnnotation": + case "RecordDeclarationBody": return printClassBody(path, options, print); case "ClassImplements": case "InterfaceExtends": + // Use `typeArguments` once https://github.com/facebook/flow/issues/9343 get fixed return [print("id"), print("typeParameters")]; + case "RecordDeclarationImplements": + return [print("id"), print("typeArguments")]; case "NullableTypeAnnotation": return ["?", print("typeAnnotation")]; case "Variance": { @@ -328,6 +334,8 @@ function printFlow(path, options, print) { case "MatchLiteralPattern": case "MatchUnaryPattern": case "MatchIdentifierPattern": + case "MatchInstancePattern": + case "MatchInstanceObjectPattern": case "MatchMemberPattern": case "MatchBindingPattern": case "MatchObjectPattern": @@ -335,6 +343,27 @@ function printFlow(path, options, print) { case "MatchRestPattern": case "MatchArrayPattern": return printMatchPattern(path, options, print); + + case "RecordExpression": + return [ + print("recordConstructor"), + print("typeArguments"), + " ", + print("properties"), + ]; + case "RecordExpressionProperties": + return printObject(path, options, print); + case "RecordDeclarationProperty": + case "RecordDeclarationStaticProperty": { + const isStatic = node.type === "RecordDeclarationStaticProperty"; + const valueKey = isStatic ? "value" : "defaultValue"; + return [ + isStatic ? "static " : "", + printPropertyKey(path, options, print), + printTypeAnnotationProperty(path, print), + node[valueKey] ? [" = ", print(valueKey)] : "", + ]; + } } } diff --git a/src/language-js/print/match.js b/src/language-js/print/match.js index b97bbf443..2235779a3 100644 --- a/src/language-js/print/match.js +++ b/src/language-js/print/match.js @@ -112,19 +112,12 @@ export function printMatchPattern(path, options, print) { } case "MatchBindingPattern": return [node.kind, " ", print("id")]; - case "MatchObjectPattern": { - const properties = path.map(print, "properties"); - if (node.rest) { - properties.push(print("rest")); - } - return group([ - "{", - indent([softline, join([",", line], properties)]), - node.rest ? "" : ifBreak(","), - softline, - "}", - ]); - } + case "MatchObjectPattern": + case "MatchInstanceObjectPattern": + return printMatchObjectPattern(path, options, print); + case "MatchInstancePattern": + return group([print("targetConstructor"), " ", print("properties")]); + case "MatchArrayPattern": { const elements = path.map(print, "elements"); if (node.rest) { @@ -153,6 +146,21 @@ export function printMatchPattern(path, options, print) { } } +function printMatchObjectPattern(path, options, print) { + const { node } = path; + const properties = path.map(print, "properties"); + if (node.rest) { + properties.push(print("rest")); + } + return group([ + "{", + indent([softline, join([",", line], properties)]), + node.rest ? "" : ifBreak(","), + softline, + "}", + ]); +} + const isSimpleMatchPattern = createTypeCheckFunction([ "MatchWildcardPattern", "MatchLiteralPattern", diff --git a/src/language-js/traverse/visitor-keys.evaluate.js b/src/language-js/traverse/visitor-keys.evaluate.js index 047dfc041..9869179e9 100644 --- a/src/language-js/traverse/visitor-keys.evaluate.js +++ b/src/language-js/traverse/visitor-keys.evaluate.js @@ -48,23 +48,12 @@ const excludeNodeTypes = [ // Babel will remove in v8 // https://github.com/babel/babel/pull/17242 "TupleExpression", - "RecordExpression", // Babel, Won't exist since we use `createImportExpressions` when parsing with babel "Import", // https://github.com/typescript-eslint/typescript-eslint/blob/d2d7ace4e52bedf07482fd879d8e31a52b38fc26/packages/visitor-keys/tests/visitor-keys.test.ts#L14-L18 "ExperimentalRestProperty", "ExperimentalSpreadProperty", - - // Unsupported flow features - "MatchInstanceObjectPattern", - "MatchInstancePattern", - "RecordDeclaration", - "RecordDeclarationBody", - "RecordDeclarationImplements", - "RecordDeclarationProperty", - "RecordDeclarationStaticProperty", - "RecordExpressionProperties", ]; let visitorKeys = unionVisitorKeys( diff --git a/tests/format/flow/match/__snapshots__/format.test.js.snap b/tests/format/flow/match/__snapshots__/format.test.js.snap new file mode 100644 index 000000000..6b44b81d8 --- /dev/null +++ b/tests/format/flow/match/__snapshots__/format.test.js.snap @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`pattern-instance.js format 1`] = ` +====================================options===================================== +parsers: ["flow"] +printWidth: 80 + | printWidth +=====================================input====================================== +const e = match (x) { + Bort {foo: 1, bar: 2} => 1, + Burt {const x, ...} => x, + Burt {x: 1, ...const y} => y, + Foo.Bart {} => 0, + Foo["one-two"] {...} => 0, + Foo[0] {...const r} => r, +}; + +=====================================output===================================== +const e = match (x) { + Bort {foo: 1, bar: 2} => 1, + Burt {const x, ...} => x, + Burt {x: 1, ...const y} => y, + Foo.Bart {} => 0, + Foo["one-two"] {...} => 0, + Foo[0] {...const r} => r, +}; + +================================================================================ +`; diff --git a/tests/format/flow/match/format.test.js b/tests/format/flow/match/format.test.js new file mode 100644 index 000000000..55c339883 --- /dev/null +++ b/tests/format/flow/match/format.test.js @@ -0,0 +1 @@ +runFormatTest(import.meta, ["flow"]); diff --git a/tests/format/flow/match/pattern-instance.js b/tests/format/flow/match/pattern-instance.js new file mode 100644 index 000000000..f28da779d --- /dev/null +++ b/tests/format/flow/match/pattern-instance.js @@ -0,0 +1,8 @@ +const e = match (x) { + Bort {foo: 1, bar: 2} => 1, + Burt {const x, ...} => x, + Burt {x: 1, ...const y} => y, + Foo.Bart {} => 0, + Foo["one-two"] {...} => 0, + Foo[0] {...const r} => r, +}; diff --git a/tests/format/flow/records/__snapshots__/format.test.js.snap b/tests/format/flow/records/__snapshots__/format.test.js.snap new file mode 100644 index 000000000..78b6016b0 --- /dev/null +++ b/tests/format/flow/records/__snapshots__/format.test.js.snap @@ -0,0 +1,273 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`declaration.js format 1`] = ` +====================================options===================================== +parsers: ["flow"] +printWidth: 80 + | printWidth +=====================================input====================================== +record Empty {} + +record Basic { + foo: string, + default: boolean = false, + 42: number, + 'one-two': string, + 2n: bigint, +} + +record DefaultValueParens { + foo: number = (1, 2), +} + +/** + * It's a record. + */ +record Comments { + /** + * A string property. + */ + foo: string, + /** + * A boolean property. + */ + bar: boolean = false, +} + +record CommentsEmpty { + // Comment +} + +export default record ExportDefault { + a: number, +} + +export record ExportNamed { + a: number, +} + +record Targs { + foo: T, + bar: boolean = false, + class: string, +} + +record Implements implements Iface { + foo: string, +} + +record ImplementsMany implements Iface, OtherIface { + foo: T, +} + +record Methods { + foo: string, + + equals(other: string) { + return this.foo === other; + } + + f_tparams() {} + + static f_static(): void {} + + async f_async() {} + + *f_generator() {} + + async *f_async_generator() {} + + static *f_static_generator() {} + + static async f_static_async() {} + + static async *f_all() {} +} + +record Static { + static foo: string = "", + static bar: boolean = false, + static 42: number = 0, + static 'one-two': string = '', + static 2n: bigint = 0n, +} + +record Looooooooooooooooooooooooooooooong implements ILoooooooooooooooooooooooooooooooongA ,ILoooooooooooooooooooooooooooooooongB { + a: number, +} + +=====================================output===================================== +record Empty {} + +record Basic { + foo: string, + default: boolean = false, + 42: number, + "one-two": string, + 2n: bigint, +} + +record DefaultValueParens { + foo: number = (1, 2), +} + +/** + * It's a record. + */ +record Comments { + /** + * A string property. + */ + foo: string, + /** + * A boolean property. + */ + bar: boolean = false, +} + +record CommentsEmpty { + // Comment +} + +export default record ExportDefault { + a: number, +}; + +export record ExportNamed { + a: number, +} + +record Targs { + foo: T, + bar: boolean = false, + class: string, +} + +record Implements implements Iface { + foo: string, +} + +record ImplementsMany implements Iface, OtherIface { + foo: T, +} + +record Methods { + foo: string, + + equals(other: string) { + return this.foo === other; + } + + f_tparams() {} + + static f_static(): void {} + + async f_async() {} + + *f_generator() {} + + async *f_async_generator() {} + + static *f_static_generator() {} + + static async f_static_async() {} + + static async *f_all() {} +} + +record Static { + static foo: string = "", + static bar: boolean = false, + static 42: number = 0, + static "one-two": string = "", + static 2n: bigint = 0n, +} + +record Looooooooooooooooooooooooooooooong + implements + ILoooooooooooooooooooooooooooooooongA, + ILoooooooooooooooooooooooooooooooongB +{ + a: number, +} + +================================================================================ +`; + +exports[`expression.js format 1`] = ` +====================================options===================================== +parsers: ["flow"] +printWidth: 80 + | printWidth +=====================================input====================================== +const empty = R {}; + +const basic = R {a: 1, b: 2}; + +const keysString = R {"one-key": 1, "another-key": 2}; + +const keysNumber = R {1: "one", 2: "two", 3: "three"}; + +const shorthand = R {a, b, c: 3}; + +const spread = R {...x, b: 2}; + +const typeArgsEmpty = R<> {a: 1}; + +const typeArgs = R {a: 1}; + +function contextFunc() { + return R {a: 1, b: 2}; +} + +const contextCall = foo(R {c: 3}); + +const contextArr = [R {d: 4}, R {e: 5}]; + +const contextObj = {nested: R {f: 6}}; + +class C extends not_parsed_as_a_record_expression {} + +const memberIdent = Foo.Bart {a: 1}; + +const memberStr = Foo["one-two"] {a: 1}; + +const memberNum = Foo[0] {a: 1}; + +=====================================output===================================== +const empty = R {}; + +const basic = R { a: 1, b: 2 }; + +const keysString = R { "one-key": 1, "another-key": 2 }; + +const keysNumber = R { 1: "one", 2: "two", 3: "three" }; + +const shorthand = R { a, b, c: 3 }; + +const spread = R { ...x, b: 2 }; + +const typeArgsEmpty = R<> { a: 1 }; + +const typeArgs = R { a: 1 }; + +function contextFunc() { + return R { a: 1, b: 2 }; +} + +const contextCall = foo(R { c: 3 }); + +const contextArr = [R { d: 4 }, R { e: 5 }]; + +const contextObj = { nested: R { f: 6 } }; + +class C extends not_parsed_as_a_record_expression {} + +const memberIdent = Foo.Bart { a: 1 }; + +const memberStr = Foo["one-two"] { a: 1 }; + +const memberNum = Foo[0] { a: 1 }; + +================================================================================ +`; diff --git a/tests/format/flow/records/declaration.js b/tests/format/flow/records/declaration.js new file mode 100644 index 000000000..37f623432 --- /dev/null +++ b/tests/format/flow/records/declaration.js @@ -0,0 +1,89 @@ +record Empty {} + +record Basic { + foo: string, + default: boolean = false, + 42: number, + 'one-two': string, + 2n: bigint, +} + +record DefaultValueParens { + foo: number = (1, 2), +} + +/** + * It's a record. + */ +record Comments { + /** + * A string property. + */ + foo: string, + /** + * A boolean property. + */ + bar: boolean = false, +} + +record CommentsEmpty { + // Comment +} + +export default record ExportDefault { + a: number, +} + +export record ExportNamed { + a: number, +} + +record Targs { + foo: T, + bar: boolean = false, + class: string, +} + +record Implements implements Iface { + foo: string, +} + +record ImplementsMany implements Iface, OtherIface { + foo: T, +} + +record Methods { + foo: string, + + equals(other: string) { + return this.foo === other; + } + + f_tparams() {} + + static f_static(): void {} + + async f_async() {} + + *f_generator() {} + + async *f_async_generator() {} + + static *f_static_generator() {} + + static async f_static_async() {} + + static async *f_all() {} +} + +record Static { + static foo: string = "", + static bar: boolean = false, + static 42: number = 0, + static 'one-two': string = '', + static 2n: bigint = 0n, +} + +record Looooooooooooooooooooooooooooooong implements ILoooooooooooooooooooooooooooooooongA ,ILoooooooooooooooooooooooooooooooongB { + a: number, +} diff --git a/tests/format/flow/records/expression.js b/tests/format/flow/records/expression.js new file mode 100644 index 000000000..99375a2df --- /dev/null +++ b/tests/format/flow/records/expression.js @@ -0,0 +1,33 @@ +const empty = R {}; + +const basic = R {a: 1, b: 2}; + +const keysString = R {"one-key": 1, "another-key": 2}; + +const keysNumber = R {1: "one", 2: "two", 3: "three"}; + +const shorthand = R {a, b, c: 3}; + +const spread = R {...x, b: 2}; + +const typeArgsEmpty = R<> {a: 1}; + +const typeArgs = R {a: 1}; + +function contextFunc() { + return R {a: 1, b: 2}; +} + +const contextCall = foo(R {c: 3}); + +const contextArr = [R {d: 4}, R {e: 5}]; + +const contextObj = {nested: R {f: 6}}; + +class C extends not_parsed_as_a_record_expression {} + +const memberIdent = Foo.Bart {a: 1}; + +const memberStr = Foo["one-two"] {a: 1}; + +const memberNum = Foo[0] {a: 1}; diff --git a/tests/format/flow/records/format.test.js b/tests/format/flow/records/format.test.js new file mode 100644 index 000000000..55c339883 --- /dev/null +++ b/tests/format/flow/records/format.test.js @@ -0,0 +1 @@ +runFormatTest(import.meta, ["flow"]); 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 59562b9c7..850ff61ae 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 @@ -830,10 +830,10 @@ Cause: Unexpected token {" `; exports[`valid-module-block-top-level-await-using-binding.js [flow] format 1`] = ` -"Unexpected token \`{\`, expected the token \`;\` (1:18) -> 1 | const m = module { - | ^ - 2 | await using foo = bar(); +"Unexpected identifier, expected the token \`,\` (2:9) + 1 | const m = module { +> 2 | await using foo = bar(); + | ^^^^^ 3 | } 4 |" `; @@ -927,10 +927,10 @@ Cause: Unexpected token {" `; exports[`valid-module-block-top-level-using-binding.js [flow] format 1`] = ` -"Unexpected token \`{\`, expected the end of an expression statement (\`;\`) (1:8) -> 1 | module { - | ^ - 2 | using foo = bar(); +"Unexpected identifier, expected the token \`,\` (2:9) + 1 | module { +> 2 | using foo = bar(); + | ^^^ 3 | } 4 |" `; diff --git a/tests/format/misc/errors/js/explicit-resource-management/__snapshots__/format.test.js.snap b/tests/format/misc/errors/js/explicit-resource-management/__snapshots__/format.test.js.snap index e8bbd0df1..3681aca7f 100644 --- a/tests/format/misc/errors/js/explicit-resource-management/__snapshots__/format.test.js.snap +++ b/tests/format/misc/errors/js/explicit-resource-management/__snapshots__/format.test.js.snap @@ -92,10 +92,10 @@ Cause: Unexpected token, expected ")" (4:24)" `; exports[`invalid-using-binding-pattern.js [flow] format 1`] = ` -"Unexpected token \`{\`, expected the end of an expression statement (\`;\`) (2:9) +"Invalid left-hand side in assignment (2:3) 1 | { > 2 | using { foo } = f(); - | ^ + | ^^^^^^^^^^^^^ 3 | using [ bar ] = g(); 4 | for (using { qux } of h()); 5 | for (using [ quux ] of i());" diff --git a/tests/unit/__snapshots__/visitor-keys.js.snap b/tests/unit/__snapshots__/visitor-keys.js.snap index 3b1e7ab40..90d31eeec 100644 --- a/tests/unit/__snapshots__/visitor-keys.js.snap +++ b/tests/unit/__snapshots__/visitor-keys.js.snap @@ -539,6 +539,14 @@ exports[`visitor keys estree 1`] = ` "MatchIdentifierPattern": [ "id", ], + "MatchInstanceObjectPattern": [ + "properties", + "rest", + ], + "MatchInstancePattern": [ + "properties", + "targetConstructor", + ], "MatchLiteralPattern": [ "literal", ], @@ -749,6 +757,37 @@ exports[`visitor keys estree 1`] = ` "id", "qualification", ], + "RecordDeclaration": [ + "body", + "id", + "implements", + "typeParameters", + ], + "RecordDeclarationBody": [ + "elements", + ], + "RecordDeclarationImplements": [ + "id", + "typeArguments", + ], + "RecordDeclarationProperty": [ + "defaultValue", + "key", + "typeAnnotation", + ], + "RecordDeclarationStaticProperty": [ + "key", + "typeAnnotation", + "value", + ], + "RecordExpression": [ + "properties", + "recordConstructor", + "typeArguments", + ], + "RecordExpressionProperties": [ + "properties", + ], "RegExpLiteral": [], "RestElement": [ "argument", diff --git a/yarn.lock b/yarn.lock index 5965fd7ef..db6b3727a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5429,19 +5429,19 @@ __metadata: languageName: node linkType: hard -"hermes-estree@npm:0.33.0": - version: 0.33.0 - resolution: "hermes-estree@npm:0.33.0" - checksum: 10/dff69960345cc3cf034a5f1cb92c0c87a8d5cd9e136d0840e92cfff9fe7453088b792661cbcdf0b4a087de9b1e5d208db740b5505b1d4bef9f1e2133cdf3b4cf +"hermes-estree@npm:0.33.1": + version: 0.33.1 + resolution: "hermes-estree@npm:0.33.1" + checksum: 10/8da08418f10c70bd943db3acfd6be3bca28de6974ab85034f087513d771546b7410246c8c03d7781ce3b613d2f03769058caa7f82e21028df7545284ba485caa languageName: node linkType: hard -"hermes-parser@npm:0.33.0": - version: 0.33.0 - resolution: "hermes-parser@npm:0.33.0" +"hermes-parser@npm:0.33.1": + version: 0.33.1 + resolution: "hermes-parser@npm:0.33.1" dependencies: - hermes-estree: "npm:0.33.0" - checksum: 10/69da5c96459e9be53616045756be7a2b97ed40bdab66a0181fe783a68cba2fb21c2bd8e2177e8cb5369e7a120656d32d8d892b35438818b93e46dfcbfd99edee + hermes-estree: "npm:0.33.1" + checksum: 10/f7caeb5609b47b44fcc3fc0be5d171ec1c5747db854e43eded16c1ff4de1bda4c6e00c115361e3bd62cbaca4518683f8e2bcab94034d6d762a1c3b4ab0af2bd8 languageName: node linkType: hard @@ -8417,7 +8417,7 @@ __metadata: gfm-test-suite: "npm:0.0.2" globals: "npm:16.5.0" graphql: "npm:16.12.0" - hermes-parser: "npm:0.33.0" + hermes-parser: "npm:0.33.1" html-element-attributes: "npm:3.5.0" html-ua-styles: "npm:0.3.1" ignore: "npm:7.0.5"