diff --git a/packages/babel-core/src/parser/util/missing-plugin-helper.js b/packages/babel-core/src/parser/util/missing-plugin-helper.js index 2560f3ea94..4893173824 100644 --- a/packages/babel-core/src/parser/util/missing-plugin-helper.js +++ b/packages/babel-core/src/parser/util/missing-plugin-helper.js @@ -143,6 +143,12 @@ const pluginNameMap = { url: "https://git.io/vb4SU", }, }, + recordAndTuple: { + syntax: { + name: "@babel/plugin-syntax-record-and-tuple", + url: "https://git.io/JvKp3", + }, + }, throwExpressions: { syntax: { name: "@babel/plugin-syntax-throw-expressions", diff --git a/packages/babel-generator/src/generators/types.js b/packages/babel-generator/src/generators/types.js index 985daa477b..e0e70b8ad4 100644 --- a/packages/babel-generator/src/generators/types.js +++ b/packages/babel-generator/src/generators/types.js @@ -106,6 +106,69 @@ export function ArrayExpression(node: Object) { export { ArrayExpression as ArrayPattern }; +export function RecordExpression(node: Object) { + const props = node.properties; + + let startToken; + let endToken; + if (this.format.recordAndTupleSyntaxType === "bar") { + startToken = "{|"; + endToken = "|}"; + } else if (this.format.recordAndTupleSyntaxType === "hash") { + startToken = "#{"; + endToken = "}"; + } else { + throw new Error( + `The "recordAndTupleSyntaxType" generator option must be "bar" or "hash" (${JSON.stringify( + this.format.recordAndTupleSyntaxType, + )} received).`, + ); + } + + this.token(startToken); + this.printInnerComments(node); + + if (props.length) { + this.space(); + this.printList(props, node, { indent: true, statement: true }); + this.space(); + } + this.token(endToken); +} + +export function TupleExpression(node: Object) { + const elems = node.elements; + const len = elems.length; + + let startToken; + let endToken; + if (this.format.recordAndTupleSyntaxType === "bar") { + startToken = "[|"; + endToken = "|]"; + } else if (this.format.recordAndTupleSyntaxType === "hash") { + startToken = "#["; + endToken = "]"; + } else { + throw new Error( + `${this.format.recordAndTupleSyntaxType} is not a valid recordAndTuple syntax type`, + ); + } + + this.token(startToken); + this.printInnerComments(node); + + for (let i = 0; i < elems.length; i++) { + const elem = elems[i]; + if (elem) { + if (i > 0) this.space(); + this.print(elem, node); + if (i < len - 1) this.token(","); + } + } + + this.token(endToken); +} + export function RegExpLiteral(node: Object) { this.word(`/${node.pattern}/${node.flags}`); } diff --git a/packages/babel-generator/src/index.js b/packages/babel-generator/src/index.js index 9d288fb0f3..1f56bc2854 100644 --- a/packages/babel-generator/src/index.js +++ b/packages/babel-generator/src/index.js @@ -58,6 +58,7 @@ function normalizeOptions(code, opts): Format { wrap: true, ...opts.jsescOption, }, + recordAndTupleSyntaxType: opts.recordAndTupleSyntaxType, }; if (format.minified) { diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-record/input.js b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-record/input.js new file mode 100644 index 0000000000..93e090d7c9 --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-record/input.js @@ -0,0 +1 @@ +{| a: 1 |} diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-record/options.json b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-record/options.json new file mode 100644 index 0000000000..37424cd7c9 --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-record/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "bar" }]], + "recordAndTupleSyntaxType": "bar" +} diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-record/output.js b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-record/output.js new file mode 100644 index 0000000000..84df2a985c --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-record/output.js @@ -0,0 +1,3 @@ +{| + a: 1 +|}; \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-tuple/input.js b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-tuple/input.js new file mode 100644 index 0000000000..36a4579b06 --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-tuple/input.js @@ -0,0 +1 @@ +[| 1 |] diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-tuple/options.json b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-tuple/options.json new file mode 100644 index 0000000000..37424cd7c9 --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-tuple/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "bar" }]], + "recordAndTupleSyntaxType": "bar" +} diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-tuple/output.js b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-tuple/output.js new file mode 100644 index 0000000000..5ef84a9ba0 --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/bar-tuple/output.js @@ -0,0 +1 @@ +[|1|]; \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-record/input.js b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-record/input.js new file mode 100644 index 0000000000..6412030c42 --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-record/input.js @@ -0,0 +1 @@ +#{ a: 1 } diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-record/options.json b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-record/options.json new file mode 100644 index 0000000000..e55454c942 --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-record/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "hash" }]], + "recordAndTupleSyntaxType": "hash" +} diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-record/output.js b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-record/output.js new file mode 100644 index 0000000000..3db8963f54 --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-record/output.js @@ -0,0 +1,3 @@ +#{ + a: 1 +}; \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-tuple/input.js b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-tuple/input.js new file mode 100644 index 0000000000..53cbd2199d --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-tuple/input.js @@ -0,0 +1 @@ +#[ 1 ] diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-tuple/options.json b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-tuple/options.json new file mode 100644 index 0000000000..e55454c942 --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-tuple/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "hash" }]], + "recordAndTupleSyntaxType": "hash" +} diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-tuple/output.js b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-tuple/output.js new file mode 100644 index 0000000000..8922efd0eb --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/hash-tuple/output.js @@ -0,0 +1 @@ +#[1]; \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/invalid-option/input.js b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/invalid-option/input.js new file mode 100644 index 0000000000..6412030c42 --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/invalid-option/input.js @@ -0,0 +1 @@ +#{ a: 1 } diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/invalid-option/options.json b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/invalid-option/options.json new file mode 100644 index 0000000000..8c3f43216d --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/invalid-option/options.json @@ -0,0 +1,5 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "hash" }]], + "recordAndTupleSyntaxType": "invalid", + "throws": "The \"recordAndTupleSyntaxType\" generator option must be \"bar\" or \"hash\" (\"invalid\" received)" +} diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/missing-option/input.js b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/missing-option/input.js new file mode 100644 index 0000000000..6412030c42 --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/missing-option/input.js @@ -0,0 +1 @@ +#{ a: 1 } diff --git a/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/missing-option/options.json b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/missing-option/options.json new file mode 100644 index 0000000000..09a736a1a2 --- /dev/null +++ b/packages/babel-generator/test/fixtures/recordAndTupleSyntaxType/missing-option/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "hash" }]], + "throws": "The \"recordAndTupleSyntaxType\" generator option must be \"bar\" or \"hash\" (undefined received)" +} diff --git a/packages/babel-generator/test/index.js b/packages/babel-generator/test/index.js index f62ae453f5..bde9800295 100644 --- a/packages/babel-generator/test/index.js +++ b/packages/babel-generator/test/index.js @@ -534,22 +534,33 @@ suites.forEach(function(testSuite) { sourceMaps: task.sourceMap ? true : task.options.sourceMaps, }; - const result = generate(actualAst, options, actualCode); + const run = () => { + return generate(actualAst, options, actualCode); + }; - if (options.sourceMaps) { - expect(result.map).toEqual(task.sourceMap); - } - - if ( - !expected.code && - result.code && - fs.statSync(path.dirname(expected.loc)).isDirectory() && - !process.env.CI - ) { - console.log(`New test file created: ${expected.loc}`); - fs.writeFileSync(expected.loc, result.code); + const throwMsg = task.options.throws; + if (throwMsg) { + expect(() => run()).toThrow( + throwMsg === true ? undefined : throwMsg, + ); } else { - expect(result.code).toBe(expected.code); + const result = run(); + + if (options.sourceMaps) { + expect(result.map).toEqual(task.sourceMap); + } + + if ( + !expected.code && + result.code && + fs.statSync(path.dirname(expected.loc)).isDirectory() && + !process.env.CI + ) { + console.log(`New test file created: ${expected.loc}`); + fs.writeFileSync(expected.loc, result.code); + } else { + expect(result.code).toBe(expected.code); + } } } }, diff --git a/packages/babel-parser/ast/spec.md b/packages/babel-parser/ast/spec.md index 52272d2d0a..6805e3121b 100644 --- a/packages/babel-parser/ast/spec.md +++ b/packages/babel-parser/ast/spec.md @@ -58,6 +58,8 @@ These are the core @babel/parser (babylon) AST node types. - [ObjectMember](#objectmember) - [ObjectProperty](#objectproperty) - [ObjectMethod](#objectmethod) + - [RecordExpression](#recordexpression) + - [TupleExpression](#tupleexpression) - [FunctionExpression](#functionexpression) - [Unary operations](#unary-operations) - [UnaryExpression](#unaryexpression) @@ -719,6 +721,24 @@ interface ObjectMethod <: ObjectMember, Function { } ``` +## RecordExpression + +```js +interface RecordExpression <: Expression { + type: "RecordExpression"; + properties: [ ObjectProperty | ObjectMethod | SpreadElement ]; +} +``` + +## TupleExpression + +```js +interface TupleExpression <: Expression { + type: "TupleExpression"; + elements: [ Expression | SpreadElement | null ]; +} +``` + ## FunctionExpression ```js diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index 18cd921636..1d49fe0e4e 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -1026,6 +1026,25 @@ export default class ExpressionParser extends LValParser { case tt.parenL: return this.parseParenAndDistinguishExpression(canBeArrow); + case tt.bracketBarL: + case tt.bracketHashL: { + this.expectPlugin("recordAndTuple"); + const oldInFSharpPipelineDirectBody = this.state + .inFSharpPipelineDirectBody; + const close = + this.state.type === tt.bracketBarL ? tt.bracketBarR : tt.bracketR; + this.state.inFSharpPipelineDirectBody = false; + node = this.startNode(); + this.next(); + node.elements = this.parseExprList( + close, + true, + refExpressionErrors, + node, + ); + this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody; + return this.finishNode(node, "TupleExpression"); + } case tt.bracketL: { const oldInFSharpPipelineDirectBody = this.state .inFSharpPipelineDirectBody; @@ -1049,11 +1068,23 @@ export default class ExpressionParser extends LValParser { this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody; return this.finishNode(node, "ArrayExpression"); } + case tt.braceBarL: + case tt.braceHashL: { + this.expectPlugin("recordAndTuple"); + const oldInFSharpPipelineDirectBody = this.state + .inFSharpPipelineDirectBody; + const close = + this.state.type === tt.braceBarL ? tt.braceBarR : tt.braceR; + this.state.inFSharpPipelineDirectBody = false; + const ret = this.parseObj(close, false, true, refExpressionErrors); + this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody; + return ret; + } case tt.braceL: { const oldInFSharpPipelineDirectBody = this.state .inFSharpPipelineDirectBody; this.state.inFSharpPipelineDirectBody = false; - const ret = this.parseObj(false, refExpressionErrors); + const ret = this.parseObj(tt.braceR, false, false, refExpressionErrors); this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody; return ret; } @@ -1465,10 +1496,12 @@ export default class ExpressionParser extends LValParser { return this.finishNode(node, "TemplateLiteral"); } - // Parse an object literal or binding pattern. + // Parse an object literal, binding pattern, or record. parseObj( + close: TokenType, isPattern: boolean, + isRecord?: ?boolean, refExpressionErrors?: ?ExpressionErrors, ): T { const propHash: any = Object.create(null); @@ -1478,12 +1511,12 @@ export default class ExpressionParser extends LValParser { node.properties = []; this.next(); - while (!this.eat(tt.braceR)) { + while (!this.eat(close)) { if (first) { first = false; } else { this.expect(tt.comma); - if (this.match(tt.braceR)) { + if (this.match(close)) { this.addExtra(node, "trailingComma", this.state.lastTokStart); this.next(); break; @@ -1504,10 +1537,13 @@ export default class ExpressionParser extends LValParser { node.properties.push(prop); } - return this.finishNode( - node, - isPattern ? "ObjectPattern" : "ObjectExpression", - ); + let type = "ObjectExpression"; + if (isPattern) { + type = "ObjectPattern"; + } else if (isRecord) { + type = "RecordExpression"; + } + return this.finishNode(node, type); } isAsyncProp(prop: N.ObjectProperty): boolean { diff --git a/packages/babel-parser/src/parser/location.js b/packages/babel-parser/src/parser/location.js index fc548b0b72..0e8aaf9960 100644 --- a/packages/babel-parser/src/parser/location.js +++ b/packages/babel-parser/src/parser/location.js @@ -127,6 +127,12 @@ export const Errors = Object.freeze({ PrimaryTopicRequiresSmartPipeline: "Primary Topic Reference found but pipelineOperator not passed 'smart' for 'proposal' option.", PrivateNameRedeclaration: "Duplicate private name #%0", + RecordExpressionBarIncorrectEndSyntaxType: + "Record expressions ending with '|}' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'", + RecordExpressionBarIncorrectStartSyntaxType: + "Record expressions starting with '{|' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'", + RecordExpressionHashIncorrectStartSyntaxType: + "Record expressions starting with '#{' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'hash'", RestTrailingComma: "Unexpected trailing comma after rest element", SloppyFunction: "In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement", @@ -143,6 +149,12 @@ export const Errors = Object.freeze({ SuperPrivateField: "Private fields can't be accessed on super", //todo: rephrase this error message as it is too subjective TrailingDecorator: "You have trailing decorators with no method", + TupleExpressionBarIncorrectEndSyntaxType: + "Tuple expressions ending with '|]' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'", + TupleExpressionBarIncorrectStartSyntaxType: + "Tuple expressions starting with '[|' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'", + TupleExpressionHashIncorrectStartSyntaxType: + "Tuple expressions starting with '#[' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'hash'", UnexpectedArgumentPlaceholder: "Unexpected argument placeholder", UnexpectedAwaitAfterPipelineBody: 'Unexpected "await" after pipeline body; await must have parentheses in minimal proposal', diff --git a/packages/babel-parser/src/parser/lval.js b/packages/babel-parser/src/parser/lval.js index 79e192eb35..ca998f25d7 100644 --- a/packages/babel-parser/src/parser/lval.js +++ b/packages/babel-parser/src/parser/lval.js @@ -41,7 +41,9 @@ export default class LValParser extends NodeUtils { refNeedsArrowPos?: ?Pos, ) => Expression; +parseObj: ( + close: TokenType, isPattern: boolean, + isRecord?: ?boolean, refExpressionErrors?: ?ExpressionErrors, ) => T; */ @@ -253,7 +255,7 @@ export default class LValParser extends NodeUtils { } case tt.braceL: - return this.parseObj(true); + return this.parseObj(tt.braceR, true); } return this.parseIdentifier(); diff --git a/packages/babel-parser/src/plugin-utils.js b/packages/babel-parser/src/plugin-utils.js index 2cf5225321..021f98f1c0 100644 --- a/packages/babel-parser/src/plugin-utils.js +++ b/packages/babel-parser/src/plugin-utils.js @@ -39,6 +39,7 @@ export function getPluginOption( } const PIPELINE_PROPOSALS = ["minimal", "smart", "fsharp"]; +const RECORD_AND_TUPLE_SYNTAX_TYPES = ["hash", "bar"]; export function validatePlugins(plugins: PluginList) { if (hasPlugin(plugins, "decorators")) { @@ -84,6 +85,18 @@ export function validatePlugins(plugins: PluginList) { PIPELINE_PROPOSALS.map(p => `'${p}'`).join(", "), ); } + + if ( + hasPlugin(plugins, "recordAndTuple") && + !RECORD_AND_TUPLE_SYNTAX_TYPES.includes( + getPluginOption(plugins, "recordAndTuple", "syntaxType"), + ) + ) { + throw new Error( + "'recordAndTuple' requires 'syntaxType' option whose value should be one of: " + + RECORD_AND_TUPLE_SYNTAX_TYPES.map(p => `'${p}'`).join(", "), + ); + } } // These plugins are defined using a mixin which extends the parser class. diff --git a/packages/babel-parser/src/tokenizer/index.js b/packages/babel-parser/src/tokenizer/index.js index 9667faba1d..1eefa40ade 100644 --- a/packages/babel-parser/src/tokenizer/index.js +++ b/packages/babel-parser/src/tokenizer/index.js @@ -405,6 +405,28 @@ export default class Tokenizer extends LocationParser { } if ( + this.hasPlugin("recordAndTuple") && + (next === charCodes.leftCurlyBrace || + next === charCodes.leftSquareBracket) + ) { + if (this.getPluginOption("recordAndTuple", "syntaxType") !== "hash") { + throw this.raise( + this.state.pos, + next === charCodes.leftCurlyBrace + ? Errors.RecordExpressionHashIncorrectStartSyntaxType + : Errors.TupleExpressionHashIncorrectStartSyntaxType, + ); + } + + if (next === charCodes.leftCurlyBrace) { + // #{ + this.finishToken(tt.braceHashL); + } else { + // #[ + this.finishToken(tt.bracketHashL); + } + this.state.pos += 2; + } else if ( this.hasPlugin("classPrivateProperties") || this.hasPlugin("classPrivateMethods") || this.getPluginOption("pipelineOperator", "proposal") === "smart" @@ -453,12 +475,12 @@ export default class Tokenizer extends LocationParser { readToken_interpreter(): boolean { if (this.state.pos !== 0 || this.length < 2) return false; + let ch = this.input.charCodeAt(this.state.pos + 1); + if (ch !== charCodes.exclamationMark) return false; + const start = this.state.pos; this.state.pos += 1; - let ch = this.input.charCodeAt(this.state.pos); - if (ch !== charCodes.exclamationMark) return false; - while (!isNewLine(ch) && ++this.state.pos < this.length) { ch = this.input.charCodeAt(this.state.pos); } @@ -514,6 +536,37 @@ export default class Tokenizer extends LocationParser { this.finishOp(tt.pipeline, 2); return; } + // '|}' + if ( + this.hasPlugin("recordAndTuple") && + next === charCodes.rightCurlyBrace + ) { + if (this.getPluginOption("recordAndTuple", "syntaxType") !== "bar") { + throw this.raise( + this.state.pos, + Errors.RecordExpressionBarIncorrectEndSyntaxType, + ); + } + + this.finishOp(tt.braceBarR, 2); + return; + } + + // '|]' + if ( + this.hasPlugin("recordAndTuple") && + next === charCodes.rightSquareBracket + ) { + if (this.getPluginOption("recordAndTuple", "syntaxType") !== "bar") { + throw this.raise( + this.state.pos, + Errors.TupleExpressionBarIncorrectEndSyntaxType, + ); + } + + this.finishOp(tt.bracketBarR, 2); + return; + } } if (next === charCodes.equalsTo) { @@ -682,16 +735,48 @@ export default class Tokenizer extends LocationParser { this.finishToken(tt.comma); return; case charCodes.leftSquareBracket: - ++this.state.pos; - this.finishToken(tt.bracketL); + if ( + this.hasPlugin("recordAndTuple") && + this.input.charCodeAt(this.state.pos + 1) === charCodes.verticalBar + ) { + if (this.getPluginOption("recordAndTuple", "syntaxType") !== "bar") { + throw this.raise( + this.state.pos, + Errors.TupleExpressionBarIncorrectStartSyntaxType, + ); + } + + // [| + this.finishToken(tt.bracketBarL); + this.state.pos += 2; + } else { + ++this.state.pos; + this.finishToken(tt.bracketL); + } return; case charCodes.rightSquareBracket: ++this.state.pos; this.finishToken(tt.bracketR); return; case charCodes.leftCurlyBrace: - ++this.state.pos; - this.finishToken(tt.braceL); + if ( + this.hasPlugin("recordAndTuple") && + this.input.charCodeAt(this.state.pos + 1) === charCodes.verticalBar + ) { + if (this.getPluginOption("recordAndTuple", "syntaxType") !== "bar") { + throw this.raise( + this.state.pos, + Errors.RecordExpressionBarIncorrectStartSyntaxType, + ); + } + + // {| + this.finishToken(tt.braceBarL); + this.state.pos += 2; + } else { + ++this.state.pos; + this.finishToken(tt.braceL); + } return; case charCodes.rightCurlyBrace: ++this.state.pos; diff --git a/packages/babel-parser/src/tokenizer/types.js b/packages/babel-parser/src/tokenizer/types.js index 6e9b64defd..b7459e368b 100644 --- a/packages/babel-parser/src/tokenizer/types.js +++ b/packages/babel-parser/src/tokenizer/types.js @@ -93,9 +93,13 @@ export const types: { [name: string]: TokenType } = { // Punctuation token types. bracketL: new TokenType("[", { beforeExpr, startsExpr }), + bracketHashL: new TokenType("#[", { beforeExpr, startsExpr }), + bracketBarL: new TokenType("[|", { beforeExpr, startsExpr }), bracketR: new TokenType("]"), + bracketBarR: new TokenType("|]"), braceL: new TokenType("{", { beforeExpr, startsExpr }), braceBarL: new TokenType("{|", { beforeExpr, startsExpr }), + braceHashL: new TokenType("#{", { beforeExpr, startsExpr }), braceR: new TokenType("}"), braceBarR: new TokenType("|}"), parenL: new TokenType("(", { beforeExpr, startsExpr }), diff --git a/packages/babel-parser/src/types.js b/packages/babel-parser/src/types.js index 597b2f5d67..17f96dc493 100644 --- a/packages/babel-parser/src/types.js +++ b/packages/babel-parser/src/types.js @@ -389,11 +389,21 @@ export type ArrayExpression = NodeBase & { elements: $ReadOnlyArray, }; +export type TupleExpression = NodeBase & { + type: "TupleExpression", + elements: $ReadOnlyArray, +}; + export type ObjectExpression = NodeBase & { type: "ObjectExpression", properties: $ReadOnlyArray, }; +export type RecordExpression = NodeBase & { + type: "RecordExpression", + properties: $ReadOnlyArray, +}; + export type ObjectOrClassMember = ClassMethod | ClassProperty | ObjectMember; export type ObjectMember = ObjectProperty | ObjectMethod; diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar-flow/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar-flow/input.js new file mode 100644 index 0000000000..0562b27afb --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar-flow/input.js @@ -0,0 +1 @@ +var a: {| x: number |} = {| x: 2 |} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar-flow/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar-flow/options.json new file mode 100644 index 0000000000..001c7217b7 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar-flow/options.json @@ -0,0 +1,6 @@ +{ + "plugins": [ + ["recordAndTuple", { "syntaxType": "bar" }], + ["flow"] + ] +} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar-flow/output.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar-flow/output.json new file mode 100644 index 0000000000..dc325327e4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar-flow/output.json @@ -0,0 +1,247 @@ +{ + "type": "File", + "start": 0, + "end": 35, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 35 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 35, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 35 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start": 0, + "end": 35, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 35 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 4, + "end": 35, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 35 + } + }, + "id": { + "type": "Identifier", + "start": 4, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 22 + }, + "identifierName": "a" + }, + "name": "a", + "typeAnnotation": { + "type": "TypeAnnotation", + "start": 5, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 22 + } + }, + "typeAnnotation": { + "type": "ObjectTypeAnnotation", + "start": 7, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 22 + } + }, + "callProperties": [], + "properties": [ + { + "type": "ObjectTypeProperty", + "start": 10, + "end": 19, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 19 + } + }, + "key": { + "type": "Identifier", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "x" + }, + "name": "x" + }, + "static": false, + "proto": false, + "kind": "init", + "method": false, + "value": { + "type": "NumberTypeAnnotation", + "start": 13, + "end": 19, + "loc": { + "start": { + "line": 1, + "column": 13 + }, + "end": { + "line": 1, + "column": 19 + } + } + }, + "variance": null, + "optional": false + } + ], + "indexers": [], + "internalSlots": [], + "exact": true, + "inexact": false + } + } + }, + "init": { + "type": "RecordExpression", + "start": 25, + "end": 35, + "loc": { + "start": { + "line": 1, + "column": 25 + }, + "end": { + "line": 1, + "column": 35 + } + }, + "properties": [ + { + "type": "ObjectProperty", + "start": 28, + "end": 32, + "loc": { + "start": { + "line": 1, + "column": 28 + }, + "end": { + "line": 1, + "column": 32 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 28, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 28 + }, + "end": { + "line": 1, + "column": 29 + }, + "identifierName": "x" + }, + "name": "x" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "NumericLiteral", + "start": 31, + "end": 32, + "loc": { + "start": { + "line": 1, + "column": 31 + }, + "end": { + "line": 1, + "column": 32 + } + }, + "extra": { + "rawValue": 2, + "raw": "2" + }, + "value": 2 + } + } + ] + } + } + ], + "kind": "var" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar/input.js new file mode 100644 index 0000000000..685ddb9ec7 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar/input.js @@ -0,0 +1,16 @@ +{||}; + +{| a: 1, b: 2, c: 3 |}; + +{| + a: 1, + b: {| + c: 3, + |}, +|}; + +[||]; + +[|1, 2, 3|]; + +[|1, [|2, 3|], 4|]; diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar/options.json new file mode 100644 index 0000000000..bf5a72aaff --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar/options.json @@ -0,0 +1,3 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "bar" }]] +} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar/output.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar/output.json new file mode 100644 index 0000000000..db51a8cf70 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/bar/output.json @@ -0,0 +1,715 @@ +{ + "type": "File", + "start": 0, + "end": 112, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 16, + "column": 19 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 112, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 16, + "column": 19 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 5 + } + }, + "expression": { + "type": "RecordExpression", + "start": 0, + "end": 4, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 4 + } + }, + "properties": [] + } + }, + { + "type": "ExpressionStatement", + "start": 7, + "end": 30, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 23 + } + }, + "expression": { + "type": "RecordExpression", + "start": 7, + "end": 29, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 22 + } + }, + "properties": [ + { + "type": "ObjectProperty", + "start": 10, + "end": 14, + "loc": { + "start": { + "line": 3, + "column": 3 + }, + "end": { + "line": 3, + "column": 7 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 3, + "column": 3 + }, + "end": { + "line": 3, + "column": 4 + }, + "identifierName": "a" + }, + "name": "a" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "NumericLiteral", + "start": 13, + "end": 14, + "loc": { + "start": { + "line": 3, + "column": 6 + }, + "end": { + "line": 3, + "column": 7 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + } + }, + { + "type": "ObjectProperty", + "start": 16, + "end": 20, + "loc": { + "start": { + "line": 3, + "column": 9 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 16, + "end": 17, + "loc": { + "start": { + "line": 3, + "column": 9 + }, + "end": { + "line": 3, + "column": 10 + }, + "identifierName": "b" + }, + "name": "b" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "NumericLiteral", + "start": 19, + "end": 20, + "loc": { + "start": { + "line": 3, + "column": 12 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "extra": { + "rawValue": 2, + "raw": "2" + }, + "value": 2 + } + }, + { + "type": "ObjectProperty", + "start": 22, + "end": 26, + "loc": { + "start": { + "line": 3, + "column": 15 + }, + "end": { + "line": 3, + "column": 19 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 22, + "end": 23, + "loc": { + "start": { + "line": 3, + "column": 15 + }, + "end": { + "line": 3, + "column": 16 + }, + "identifierName": "c" + }, + "name": "c" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "NumericLiteral", + "start": 25, + "end": 26, + "loc": { + "start": { + "line": 3, + "column": 18 + }, + "end": { + "line": 3, + "column": 19 + } + }, + "extra": { + "rawValue": 3, + "raw": "3" + }, + "value": 3 + } + } + ] + } + }, + { + "type": "ExpressionStatement", + "start": 32, + "end": 70, + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 10, + "column": 3 + } + }, + "expression": { + "type": "RecordExpression", + "start": 32, + "end": 69, + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 10, + "column": 2 + } + }, + "properties": [ + { + "type": "ObjectProperty", + "start": 37, + "end": 41, + "loc": { + "start": { + "line": 6, + "column": 2 + }, + "end": { + "line": 6, + "column": 6 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 37, + "end": 38, + "loc": { + "start": { + "line": 6, + "column": 2 + }, + "end": { + "line": 6, + "column": 3 + }, + "identifierName": "a" + }, + "name": "a" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "NumericLiteral", + "start": 40, + "end": 41, + "loc": { + "start": { + "line": 6, + "column": 5 + }, + "end": { + "line": 6, + "column": 6 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + } + }, + { + "type": "ObjectProperty", + "start": 45, + "end": 65, + "loc": { + "start": { + "line": 7, + "column": 2 + }, + "end": { + "line": 9, + "column": 4 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 45, + "end": 46, + "loc": { + "start": { + "line": 7, + "column": 2 + }, + "end": { + "line": 7, + "column": 3 + }, + "identifierName": "b" + }, + "name": "b" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "RecordExpression", + "start": 48, + "end": 65, + "loc": { + "start": { + "line": 7, + "column": 5 + }, + "end": { + "line": 9, + "column": 4 + } + }, + "properties": [ + { + "type": "ObjectProperty", + "start": 55, + "end": 59, + "loc": { + "start": { + "line": 8, + "column": 4 + }, + "end": { + "line": 8, + "column": 8 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 55, + "end": 56, + "loc": { + "start": { + "line": 8, + "column": 4 + }, + "end": { + "line": 8, + "column": 5 + }, + "identifierName": "c" + }, + "name": "c" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "NumericLiteral", + "start": 58, + "end": 59, + "loc": { + "start": { + "line": 8, + "column": 7 + }, + "end": { + "line": 8, + "column": 8 + } + }, + "extra": { + "rawValue": 3, + "raw": "3" + }, + "value": 3 + } + } + ], + "extra": { + "trailingComma": 59 + } + } + } + ], + "extra": { + "trailingComma": 65 + } + } + }, + { + "type": "ExpressionStatement", + "start": 72, + "end": 77, + "loc": { + "start": { + "line": 12, + "column": 0 + }, + "end": { + "line": 12, + "column": 5 + } + }, + "expression": { + "type": "TupleExpression", + "start": 72, + "end": 76, + "loc": { + "start": { + "line": 12, + "column": 0 + }, + "end": { + "line": 12, + "column": 4 + } + }, + "elements": [] + } + }, + { + "type": "ExpressionStatement", + "start": 79, + "end": 91, + "loc": { + "start": { + "line": 14, + "column": 0 + }, + "end": { + "line": 14, + "column": 12 + } + }, + "expression": { + "type": "TupleExpression", + "start": 79, + "end": 90, + "loc": { + "start": { + "line": 14, + "column": 0 + }, + "end": { + "line": 14, + "column": 11 + } + }, + "elements": [ + { + "type": "NumericLiteral", + "start": 81, + "end": 82, + "loc": { + "start": { + "line": 14, + "column": 2 + }, + "end": { + "line": 14, + "column": 3 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + }, + { + "type": "NumericLiteral", + "start": 84, + "end": 85, + "loc": { + "start": { + "line": 14, + "column": 5 + }, + "end": { + "line": 14, + "column": 6 + } + }, + "extra": { + "rawValue": 2, + "raw": "2" + }, + "value": 2 + }, + { + "type": "NumericLiteral", + "start": 87, + "end": 88, + "loc": { + "start": { + "line": 14, + "column": 8 + }, + "end": { + "line": 14, + "column": 9 + } + }, + "extra": { + "rawValue": 3, + "raw": "3" + }, + "value": 3 + } + ] + } + }, + { + "type": "ExpressionStatement", + "start": 93, + "end": 112, + "loc": { + "start": { + "line": 16, + "column": 0 + }, + "end": { + "line": 16, + "column": 19 + } + }, + "expression": { + "type": "TupleExpression", + "start": 93, + "end": 111, + "loc": { + "start": { + "line": 16, + "column": 0 + }, + "end": { + "line": 16, + "column": 18 + } + }, + "elements": [ + { + "type": "NumericLiteral", + "start": 95, + "end": 96, + "loc": { + "start": { + "line": 16, + "column": 2 + }, + "end": { + "line": 16, + "column": 3 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + }, + { + "type": "TupleExpression", + "start": 98, + "end": 106, + "loc": { + "start": { + "line": 16, + "column": 5 + }, + "end": { + "line": 16, + "column": 13 + } + }, + "elements": [ + { + "type": "NumericLiteral", + "start": 100, + "end": 101, + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + }, + "extra": { + "rawValue": 2, + "raw": "2" + }, + "value": 2 + }, + { + "type": "NumericLiteral", + "start": 103, + "end": 104, + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 11 + } + }, + "extra": { + "rawValue": 3, + "raw": "3" + }, + "value": 3 + } + ] + }, + { + "type": "NumericLiteral", + "start": 108, + "end": 109, + "loc": { + "start": { + "line": 16, + "column": 15 + }, + "end": { + "line": 16, + "column": 16 + } + }, + "extra": { + "rawValue": 4, + "raw": "4" + }, + "value": 4 + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/hash/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/hash/input.js new file mode 100644 index 0000000000..9217cfe71b --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/hash/input.js @@ -0,0 +1,16 @@ +#{}; + +#{ a: 1, b: 2, c: 3 }; + +#{ + a: 1, + b: #{ + c: 3, + }, +}; + +#[]; + +#[1, 2, 3]; + +#[1, #[2, 3], 4]; diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/hash/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/hash/options.json new file mode 100644 index 0000000000..703c537be3 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/hash/options.json @@ -0,0 +1,3 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "hash" }]] +} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/hash/output.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/hash/output.json new file mode 100644 index 0000000000..c5d7401728 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/hash/output.json @@ -0,0 +1,715 @@ +{ + "type": "File", + "start": 0, + "end": 104, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 16, + "column": 17 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 104, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 16, + "column": 17 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 4, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 4 + } + }, + "expression": { + "type": "RecordExpression", + "start": 0, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 3 + } + }, + "properties": [] + } + }, + { + "type": "ExpressionStatement", + "start": 6, + "end": 28, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 22 + } + }, + "expression": { + "type": "RecordExpression", + "start": 6, + "end": 27, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 21 + } + }, + "properties": [ + { + "type": "ObjectProperty", + "start": 9, + "end": 13, + "loc": { + "start": { + "line": 3, + "column": 3 + }, + "end": { + "line": 3, + "column": 7 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 9, + "end": 10, + "loc": { + "start": { + "line": 3, + "column": 3 + }, + "end": { + "line": 3, + "column": 4 + }, + "identifierName": "a" + }, + "name": "a" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "NumericLiteral", + "start": 12, + "end": 13, + "loc": { + "start": { + "line": 3, + "column": 6 + }, + "end": { + "line": 3, + "column": 7 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + } + }, + { + "type": "ObjectProperty", + "start": 15, + "end": 19, + "loc": { + "start": { + "line": 3, + "column": 9 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 15, + "end": 16, + "loc": { + "start": { + "line": 3, + "column": 9 + }, + "end": { + "line": 3, + "column": 10 + }, + "identifierName": "b" + }, + "name": "b" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "NumericLiteral", + "start": 18, + "end": 19, + "loc": { + "start": { + "line": 3, + "column": 12 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "extra": { + "rawValue": 2, + "raw": "2" + }, + "value": 2 + } + }, + { + "type": "ObjectProperty", + "start": 21, + "end": 25, + "loc": { + "start": { + "line": 3, + "column": 15 + }, + "end": { + "line": 3, + "column": 19 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 21, + "end": 22, + "loc": { + "start": { + "line": 3, + "column": 15 + }, + "end": { + "line": 3, + "column": 16 + }, + "identifierName": "c" + }, + "name": "c" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "NumericLiteral", + "start": 24, + "end": 25, + "loc": { + "start": { + "line": 3, + "column": 18 + }, + "end": { + "line": 3, + "column": 19 + } + }, + "extra": { + "rawValue": 3, + "raw": "3" + }, + "value": 3 + } + } + ] + } + }, + { + "type": "ExpressionStatement", + "start": 30, + "end": 66, + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 10, + "column": 2 + } + }, + "expression": { + "type": "RecordExpression", + "start": 30, + "end": 65, + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 10, + "column": 1 + } + }, + "properties": [ + { + "type": "ObjectProperty", + "start": 35, + "end": 39, + "loc": { + "start": { + "line": 6, + "column": 2 + }, + "end": { + "line": 6, + "column": 6 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 35, + "end": 36, + "loc": { + "start": { + "line": 6, + "column": 2 + }, + "end": { + "line": 6, + "column": 3 + }, + "identifierName": "a" + }, + "name": "a" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "NumericLiteral", + "start": 38, + "end": 39, + "loc": { + "start": { + "line": 6, + "column": 5 + }, + "end": { + "line": 6, + "column": 6 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + } + }, + { + "type": "ObjectProperty", + "start": 43, + "end": 62, + "loc": { + "start": { + "line": 7, + "column": 2 + }, + "end": { + "line": 9, + "column": 3 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 43, + "end": 44, + "loc": { + "start": { + "line": 7, + "column": 2 + }, + "end": { + "line": 7, + "column": 3 + }, + "identifierName": "b" + }, + "name": "b" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "RecordExpression", + "start": 46, + "end": 62, + "loc": { + "start": { + "line": 7, + "column": 5 + }, + "end": { + "line": 9, + "column": 3 + } + }, + "properties": [ + { + "type": "ObjectProperty", + "start": 53, + "end": 57, + "loc": { + "start": { + "line": 8, + "column": 4 + }, + "end": { + "line": 8, + "column": 8 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 53, + "end": 54, + "loc": { + "start": { + "line": 8, + "column": 4 + }, + "end": { + "line": 8, + "column": 5 + }, + "identifierName": "c" + }, + "name": "c" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "NumericLiteral", + "start": 56, + "end": 57, + "loc": { + "start": { + "line": 8, + "column": 7 + }, + "end": { + "line": 8, + "column": 8 + } + }, + "extra": { + "rawValue": 3, + "raw": "3" + }, + "value": 3 + } + } + ], + "extra": { + "trailingComma": 57 + } + } + } + ], + "extra": { + "trailingComma": 62 + } + } + }, + { + "type": "ExpressionStatement", + "start": 68, + "end": 72, + "loc": { + "start": { + "line": 12, + "column": 0 + }, + "end": { + "line": 12, + "column": 4 + } + }, + "expression": { + "type": "TupleExpression", + "start": 68, + "end": 71, + "loc": { + "start": { + "line": 12, + "column": 0 + }, + "end": { + "line": 12, + "column": 3 + } + }, + "elements": [] + } + }, + { + "type": "ExpressionStatement", + "start": 74, + "end": 85, + "loc": { + "start": { + "line": 14, + "column": 0 + }, + "end": { + "line": 14, + "column": 11 + } + }, + "expression": { + "type": "TupleExpression", + "start": 74, + "end": 84, + "loc": { + "start": { + "line": 14, + "column": 0 + }, + "end": { + "line": 14, + "column": 10 + } + }, + "elements": [ + { + "type": "NumericLiteral", + "start": 76, + "end": 77, + "loc": { + "start": { + "line": 14, + "column": 2 + }, + "end": { + "line": 14, + "column": 3 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + }, + { + "type": "NumericLiteral", + "start": 79, + "end": 80, + "loc": { + "start": { + "line": 14, + "column": 5 + }, + "end": { + "line": 14, + "column": 6 + } + }, + "extra": { + "rawValue": 2, + "raw": "2" + }, + "value": 2 + }, + { + "type": "NumericLiteral", + "start": 82, + "end": 83, + "loc": { + "start": { + "line": 14, + "column": 8 + }, + "end": { + "line": 14, + "column": 9 + } + }, + "extra": { + "rawValue": 3, + "raw": "3" + }, + "value": 3 + } + ] + } + }, + { + "type": "ExpressionStatement", + "start": 87, + "end": 104, + "loc": { + "start": { + "line": 16, + "column": 0 + }, + "end": { + "line": 16, + "column": 17 + } + }, + "expression": { + "type": "TupleExpression", + "start": 87, + "end": 103, + "loc": { + "start": { + "line": 16, + "column": 0 + }, + "end": { + "line": 16, + "column": 16 + } + }, + "elements": [ + { + "type": "NumericLiteral", + "start": 89, + "end": 90, + "loc": { + "start": { + "line": 16, + "column": 2 + }, + "end": { + "line": 16, + "column": 3 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + }, + { + "type": "TupleExpression", + "start": 92, + "end": 99, + "loc": { + "start": { + "line": 16, + "column": 5 + }, + "end": { + "line": 16, + "column": 12 + } + }, + "elements": [ + { + "type": "NumericLiteral", + "start": 94, + "end": 95, + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + }, + "extra": { + "rawValue": 2, + "raw": "2" + }, + "value": 2 + }, + { + "type": "NumericLiteral", + "start": 97, + "end": 98, + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 11 + } + }, + "extra": { + "rawValue": 3, + "raw": "3" + }, + "value": 3 + } + ] + }, + { + "type": "NumericLiteral", + "start": 101, + "end": 102, + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 16, + "column": 15 + } + }, + "extra": { + "rawValue": 4, + "raw": "4" + }, + "value": 4 + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-end-bar/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-end-bar/input.js new file mode 100644 index 0000000000..b1bef5c7e1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-end-bar/input.js @@ -0,0 +1 @@ +|} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-end-bar/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-end-bar/options.json new file mode 100644 index 0000000000..de1fad0a73 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-end-bar/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "hash" }]], + "throws": "Record expressions ending with '|}' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar' (1:0)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-start-bar/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-start-bar/input.js new file mode 100644 index 0000000000..acc5a0adcb --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-start-bar/input.js @@ -0,0 +1 @@ +{| diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-start-bar/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-start-bar/options.json new file mode 100644 index 0000000000..ad916de061 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-start-bar/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "hash" }]], + "throws": "Record expressions starting with '{|' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar' (1:0)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-start-hash/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-start-hash/input.js new file mode 100644 index 0000000000..1dff7ae1c5 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-start-hash/input.js @@ -0,0 +1 @@ +#{ diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-start-hash/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-start-hash/options.json new file mode 100644 index 0000000000..9d23281e46 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-record-start-hash/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "bar" }]], + "throws": "Record expressions starting with '#{' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'hash' (1:0)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-end-bar/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-end-bar/input.js new file mode 100644 index 0000000000..9adcc6ff49 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-end-bar/input.js @@ -0,0 +1 @@ +|] diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-end-bar/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-end-bar/options.json new file mode 100644 index 0000000000..cacf8c4cad --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-end-bar/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "hash" }]], + "throws": "Tuple expressions ending with '|]' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar' (1:0)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-start-bar/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-start-bar/input.js new file mode 100644 index 0000000000..6eb879a13b --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-start-bar/input.js @@ -0,0 +1 @@ +[| diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-start-bar/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-start-bar/options.json new file mode 100644 index 0000000000..c7b3f7a090 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-start-bar/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "hash" }]], + "throws": "Tuple expressions starting with '[|' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar' (1:0)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-start-hash/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-start-hash/input.js new file mode 100644 index 0000000000..47ffe98649 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-start-hash/input.js @@ -0,0 +1 @@ +#[ diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-start-hash/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-start-hash/options.json new file mode 100644 index 0000000000..4a28c83772 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/incorrect-type-tuple-start-hash/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "bar" }]], + "throws": "Tuple expressions starting with '#[' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'hash' (1:0)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-bar-record/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-bar-record/input.js new file mode 100644 index 0000000000..58bca25f7e --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-bar-record/input.js @@ -0,0 +1 @@ +{||} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-bar-record/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-bar-record/options.json new file mode 100644 index 0000000000..f266a14d42 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-bar-record/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "invalid" }]], + "throws": "'recordAndTuple' requires 'syntaxType' option whose value should be one of: 'hash', 'bar'" +} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-bar-tuple/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-bar-tuple/input.js new file mode 100644 index 0000000000..38030aa27c --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-bar-tuple/input.js @@ -0,0 +1 @@ +[||] diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-bar-tuple/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-bar-tuple/options.json new file mode 100644 index 0000000000..f266a14d42 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-bar-tuple/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "invalid" }]], + "throws": "'recordAndTuple' requires 'syntaxType' option whose value should be one of: 'hash', 'bar'" +} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-hash-record/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-hash-record/input.js new file mode 100644 index 0000000000..feca1c1b89 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-hash-record/input.js @@ -0,0 +1 @@ +#{} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-hash-record/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-hash-record/options.json new file mode 100644 index 0000000000..f266a14d42 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-hash-record/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "invalid" }]], + "throws": "'recordAndTuple' requires 'syntaxType' option whose value should be one of: 'hash', 'bar'" +} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-hash-tuple/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-hash-tuple/input.js new file mode 100644 index 0000000000..0fbee2942b --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-hash-tuple/input.js @@ -0,0 +1 @@ +#[] diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-hash-tuple/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-hash-tuple/options.json new file mode 100644 index 0000000000..f266a14d42 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/invalid-type-hash-tuple/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["recordAndTuple", { "syntaxType": "invalid" }]], + "throws": "'recordAndTuple' requires 'syntaxType' option whose value should be one of: 'hash', 'bar'" +} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/not-enabled-bar/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/not-enabled-bar/input.js new file mode 100644 index 0000000000..58bca25f7e --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/not-enabled-bar/input.js @@ -0,0 +1 @@ +{||} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/not-enabled-bar/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/not-enabled-bar/options.json new file mode 100644 index 0000000000..3500bb1aae --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/not-enabled-bar/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [], + "throws": "Unexpected token (1:1)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/not-enabled-hash/input.js b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/not-enabled-hash/input.js new file mode 100644 index 0000000000..95bd07c248 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/not-enabled-hash/input.js @@ -0,0 +1 @@ +#{}; diff --git a/packages/babel-parser/test/fixtures/experimental/record-and-tuple/not-enabled-hash/options.json b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/not-enabled-hash/options.json new file mode 100644 index 0000000000..52f524480c --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/record-and-tuple/not-enabled-hash/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [], + "throws": "Unexpected character '#' (1:0)" +} diff --git a/packages/babel-plugin-syntax-record-and-tuple/.npmignore b/packages/babel-plugin-syntax-record-and-tuple/.npmignore new file mode 100644 index 0000000000..f980694583 --- /dev/null +++ b/packages/babel-plugin-syntax-record-and-tuple/.npmignore @@ -0,0 +1,3 @@ +src +test +*.log diff --git a/packages/babel-plugin-syntax-record-and-tuple/README.md b/packages/babel-plugin-syntax-record-and-tuple/README.md new file mode 100644 index 0000000000..8f91e3d16a --- /dev/null +++ b/packages/babel-plugin-syntax-record-and-tuple/README.md @@ -0,0 +1,19 @@ +# @babel/plugin-syntax-record-and-tuple + +> Allow parsing of records and tuples. + +See our website [@babel/plugin-syntax-record-and-tuple](https://babeljs.io/docs/en/next/babel-plugin-syntax-record-and-tuple.html) for more information. + +## Install + +Using npm: + +```sh +npm install --save-dev @babel/plugin-syntax-record-and-tuple +``` + +or using yarn: + +```sh +yarn add @babel/plugin-syntax-record-and-tuple --dev +``` diff --git a/packages/babel-plugin-syntax-record-and-tuple/package.json b/packages/babel-plugin-syntax-record-and-tuple/package.json new file mode 100644 index 0000000000..3d756cf8be --- /dev/null +++ b/packages/babel-plugin-syntax-record-and-tuple/package.json @@ -0,0 +1,23 @@ +{ + "name": "@babel/plugin-syntax-record-and-tuple", + "version": "7.7.4", + "description": "Allow parsing of records and tuples.", + "repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-syntax-record-and-tuple", + "license": "MIT", + "publishConfig": { + "access": "public" + }, + "main": "lib/index.js", + "keywords": [ + "babel-plugin" + ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + }, + "devDependencies": { + "@babel/core": "^7.0.0" + } +} diff --git a/packages/babel-plugin-syntax-record-and-tuple/src/index.js b/packages/babel-plugin-syntax-record-and-tuple/src/index.js new file mode 100644 index 0000000000..12f50f60c9 --- /dev/null +++ b/packages/babel-plugin-syntax-record-and-tuple/src/index.js @@ -0,0 +1,18 @@ +import { declare } from "@babel/helper-plugin-utils"; + +export default declare((api, options) => { + api.assertVersion(7); + + return { + name: "syntax-record-and-tuple", + + manipulateOptions(opts, parserOpts) { + opts.generatorOpts.recordAndTupleSyntaxType = options.syntaxType; + + parserOpts.plugins.push([ + "recordAndTuple", + { syntaxType: options.syntaxType }, + ]); + }, + }; +}); diff --git a/packages/babel-types/src/asserts/generated/index.js b/packages/babel-types/src/asserts/generated/index.js index b6bbfa0a1b..06464cd3a3 100644 --- a/packages/babel-types/src/asserts/generated/index.js +++ b/packages/babel-types/src/asserts/generated/index.js @@ -791,6 +791,12 @@ export function assertPrivateName(node: Object, opts?: Object = {}): void { export function assertBigIntLiteral(node: Object, opts?: Object = {}): void { assert("BigIntLiteral", node, opts); } +export function assertRecordExpression(node: Object, opts?: Object = {}): void { + assert("RecordExpression", node, opts); +} +export function assertTupleExpression(node: Object, opts?: Object = {}): void { + assert("TupleExpression", node, opts); +} export function assertTSParameterProperty( node: Object, opts?: Object = {}, diff --git a/packages/babel-types/src/builders/generated/index.js b/packages/babel-types/src/builders/generated/index.js index c80d440a6c..fc319d6ad1 100644 --- a/packages/babel-types/src/builders/generated/index.js +++ b/packages/babel-types/src/builders/generated/index.js @@ -716,6 +716,14 @@ export function BigIntLiteral(...args: Array): Object { return builder("BigIntLiteral", ...args); } export { BigIntLiteral as bigIntLiteral }; +export function RecordExpression(...args: Array): Object { + return builder("RecordExpression", ...args); +} +export { RecordExpression as recordExpression }; +export function TupleExpression(...args: Array): Object { + return builder("TupleExpression", ...args); +} +export { TupleExpression as tupleExpression }; export function TSParameterProperty(...args: Array): Object { return builder("TSParameterProperty", ...args); } diff --git a/packages/babel-types/src/definitions/experimental.js b/packages/babel-types/src/definitions/experimental.js index a77350105a..27d4ca71de 100644 --- a/packages/babel-types/src/definitions/experimental.js +++ b/packages/babel-types/src/definitions/experimental.js @@ -2,6 +2,7 @@ import defineType, { assertEach, assertNodeType, + assertNodeOrValueType, assertValueType, chain, } from "./utils"; @@ -276,3 +277,34 @@ defineType("BigIntLiteral", { }, aliases: ["Expression", "Pureish", "Literal", "Immutable"], }); + +defineType("RecordExpression", { + visitor: ["properties"], + aliases: ["Expression"], + fields: { + properties: { + validate: chain( + assertValueType("array"), + assertEach( + assertNodeType("ObjectProperty", "ObjectMethod", "SpreadElement"), + ), + ), + }, + }, +}); + +defineType("TupleExpression", { + fields: { + elements: { + validate: chain( + assertValueType("array"), + assertEach( + assertNodeOrValueType("null", "Expression", "SpreadElement"), + ), + ), + default: [], + }, + }, + visitor: ["elements"], + aliases: ["Expression"], +}); diff --git a/packages/babel-types/src/validators/generated/index.js b/packages/babel-types/src/validators/generated/index.js index 9eaf2d0f61..f78c4127ef 100644 --- a/packages/babel-types/src/validators/generated/index.js +++ b/packages/babel-types/src/validators/generated/index.js @@ -2531,6 +2531,34 @@ export function isBigIntLiteral(node: ?Object, opts?: Object): boolean { return false; } +export function isRecordExpression(node: ?Object, opts?: Object): boolean { + if (!node) return false; + + const nodeType = node.type; + if (nodeType === "RecordExpression") { + if (typeof opts === "undefined") { + return true; + } else { + return shallowEqual(node, opts); + } + } + + return false; +} +export function isTupleExpression(node: ?Object, opts?: Object): boolean { + if (!node) return false; + + const nodeType = node.type; + if (nodeType === "TupleExpression") { + if (typeof opts === "undefined") { + return true; + } else { + return shallowEqual(node, opts); + } + } + + return false; +} export function isTSParameterProperty(node: ?Object, opts?: Object): boolean { if (!node) return false; @@ -3460,6 +3488,8 @@ export function isExpression(node: ?Object, opts?: Object): boolean { "Import" === nodeType || "DoExpression" === nodeType || "BigIntLiteral" === nodeType || + "RecordExpression" === nodeType || + "TupleExpression" === nodeType || "TSAsExpression" === nodeType || "TSTypeAssertion" === nodeType || "TSNonNullExpression" === nodeType ||