diff --git a/packages/babel-generator/src/generators/statements.ts b/packages/babel-generator/src/generators/statements.ts index da67affc209b..e010fa61c018 100644 --- a/packages/babel-generator/src/generators/statements.ts +++ b/packages/babel-generator/src/generators/statements.ts @@ -1,4 +1,5 @@ import type Printer from "../printer"; +import type { PrintJoinOptions } from "../printer"; import { isFor, isForStatement, @@ -102,6 +103,7 @@ function ForXStatement(this: Printer, node: t.ForXStatement) { this.word("await"); this.space(); } + this.printInnerComments(node, false); this.token("("); this.print(node.left, node); this.space(); @@ -259,7 +261,13 @@ export function VariableDeclaration( this.space(); } - this.word(node.kind); + const { kind } = node; + this.word(kind); + const { _noLineTerminator } = this; + if (kind === "using") { + // ensure no line break after `using` + this._noLineTerminator = true; + } this.space(); let hasInits = false; @@ -285,6 +293,16 @@ export function VariableDeclaration( // bar = "foo"; // + let iterator: PrintJoinOptions["iterator"] | undefined; + if (kind === "using") { + // Ensure no line break between `using` and the first declarator + iterator = (_, i: number) => { + if (i === 0) { + this._noLineTerminator = _noLineTerminator; + } + }; + } + this.printList(node.declarations, node, { separator: hasInits ? function (this: Printer) { @@ -292,6 +310,7 @@ export function VariableDeclaration( this.newline(); } : undefined, + iterator, indent: node.declarations.length > 1 ? true : false, }); diff --git a/packages/babel-generator/src/printer.ts b/packages/babel-generator/src/printer.ts index 7d39d5c7e7c3..424113047cdd 100644 --- a/packages/babel-generator/src/printer.ts +++ b/packages/babel-generator/src/printer.ts @@ -79,14 +79,12 @@ interface PrintSequenceOptions extends Partial { interface PrintListOptions { separator?: (this: Printer) => void; + iterator?: (node: t.Node, index: number) => void; statement?: boolean; indent?: boolean; } -type PrintJoinOptions = PrintListOptions & - PrintSequenceOptions & { - iterator?: (node: t.Node, index: number) => void; - }; +export type PrintJoinOptions = PrintListOptions & PrintSequenceOptions; class Printer { constructor(format: Format, map: SourceMap) { this.format = format; diff --git a/packages/babel-generator/test/fixtures/comments/for-await-using-of-comments/input.mjs b/packages/babel-generator/test/fixtures/comments/for-await-using-of-comments/input.mjs new file mode 100644 index 000000000000..97230845f53d --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/for-await-using-of-comments/input.mjs @@ -0,0 +1 @@ +/*1*/ for /* 2 */ await /*3*/ ( /*4*/ using /*5*/ fo /*6*/ of /*7*/ of /*8*/) /*9*/; diff --git a/packages/babel-generator/test/fixtures/comments/for-await-using-of-comments/options.json b/packages/babel-generator/test/fixtures/comments/for-await-using-of-comments/options.json new file mode 100644 index 000000000000..495a16f9a39a --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/for-await-using-of-comments/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["explicitResourceManagement"] +} diff --git a/packages/babel-generator/test/fixtures/comments/for-await-using-of-comments/output.js b/packages/babel-generator/test/fixtures/comments/for-await-using-of-comments/output.js new file mode 100644 index 000000000000..c79925d2a6bd --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/for-await-using-of-comments/output.js @@ -0,0 +1 @@ +/*1*/for await /* 2 */ /*3*/( /*4*/using /*5*/fo /*6*/ of /*7*/of /*8*/) /*9*/; \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/using-declarations/basic/input.js b/packages/babel-generator/test/fixtures/using-declarations/basic/input.js new file mode 100644 index 000000000000..4905c20bceea --- /dev/null +++ b/packages/babel-generator/test/fixtures/using-declarations/basic/input.js @@ -0,0 +1,3 @@ +{ + using /* 1 */ a = foo(), /* 2 */ b = foo() +} diff --git a/packages/babel-generator/test/fixtures/using-declarations/basic/output.js b/packages/babel-generator/test/fixtures/using-declarations/basic/output.js new file mode 100644 index 000000000000..25dac2b3df88 --- /dev/null +++ b/packages/babel-generator/test/fixtures/using-declarations/basic/output.js @@ -0,0 +1,4 @@ +{ + using /* 1 */a = foo(), + /* 2 */b = foo(); +} \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/using-declarations/for-using-init/input.js b/packages/babel-generator/test/fixtures/using-declarations/for-using-init/input.js new file mode 100644 index 000000000000..cc6511295e0c --- /dev/null +++ b/packages/babel-generator/test/fixtures/using-declarations/for-using-init/input.js @@ -0,0 +1 @@ +for(using /* 1 */ a = foo(), /* 2 */ b = foo();;); diff --git a/packages/babel-generator/test/fixtures/using-declarations/for-using-init/output.js b/packages/babel-generator/test/fixtures/using-declarations/for-using-init/output.js new file mode 100644 index 000000000000..6051b65d4fe1 --- /dev/null +++ b/packages/babel-generator/test/fixtures/using-declarations/for-using-init/output.js @@ -0,0 +1 @@ +for (using /* 1 */a = foo(), /* 2 */b = foo();;); \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/using-declarations/for-using-of/input.js b/packages/babel-generator/test/fixtures/using-declarations/for-using-of/input.js new file mode 100644 index 000000000000..3ba266853779 --- /dev/null +++ b/packages/babel-generator/test/fixtures/using-declarations/for-using-of/input.js @@ -0,0 +1 @@ +for(using /* 1 */ foo of bar()); diff --git a/packages/babel-generator/test/fixtures/using-declarations/for-using-of/output.js b/packages/babel-generator/test/fixtures/using-declarations/for-using-of/output.js new file mode 100644 index 000000000000..b99e8231f2a6 --- /dev/null +++ b/packages/babel-generator/test/fixtures/using-declarations/for-using-of/output.js @@ -0,0 +1 @@ +for (using /* 1 */foo of bar()); \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/using-declarations/options.json b/packages/babel-generator/test/fixtures/using-declarations/options.json new file mode 100644 index 000000000000..495a16f9a39a --- /dev/null +++ b/packages/babel-generator/test/fixtures/using-declarations/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["explicitResourceManagement"] +} diff --git a/packages/babel-parser/ast/spec.md b/packages/babel-parser/ast/spec.md index aabdc572c4d9..f233db2cd621 100644 --- a/packages/babel-parser/ast/spec.md +++ b/packages/babel-parser/ast/spec.md @@ -572,7 +572,7 @@ A function declaration. Note that unlike in the parent interface `Function`, the interface VariableDeclaration <: Declaration { type: "VariableDeclaration"; declarations: [ VariableDeclarator ]; - kind: "var" | "let" | "const"; + kind: "var" | "let" | "const" | "using"; } ``` @@ -1469,3 +1469,4 @@ interface PipelineBareConstructorBody <: NodeBase { type: "PipelineBareAwaitedFunctionBody"; callee: Expression; } +``` diff --git a/packages/babel-parser/data/schema.json b/packages/babel-parser/data/schema.json index 0fbcf6d9e2a3..9b90d00c89b1 100644 --- a/packages/babel-parser/data/schema.json +++ b/packages/babel-parser/data/schema.json @@ -131,9 +131,12 @@ "decimal", "decorators", "decorators-legacy", + "decoratorAutoAccessors", + "destructuringPrivate", "doExpressions", "dynamicImport", "estree", + "explicitResourceManagement", "exportDefaultFrom", "exportNamespaceFrom", "flow", @@ -144,6 +147,7 @@ "importMeta", "jsx", "logicalAssignment", + "moduleBlocks", "moduleStringNames", "nullishCoalescingOperator", "numericSeparator", @@ -154,6 +158,7 @@ "pipelineOperator", "placeholders", "privateIn", + "regexpUnicodeSets", "throwExpressions", "topLevelAwait", "typescript", diff --git a/packages/babel-parser/src/parse-error/standard-errors.ts b/packages/babel-parser/src/parse-error/standard-errors.ts index e50a5a33e007..97ac30be4a6a 100644 --- a/packages/babel-parser/src/parse-error/standard-errors.ts +++ b/packages/babel-parser/src/parse-error/standard-errors.ts @@ -90,6 +90,7 @@ export default { `'${ type === "ForInStatement" ? "for-in" : "for-of" }' loop variable declaration may not have an initializer.`, + ForInUsing: "For-in loop may not start with 'using' declaration.", ForOfAsync: "The left-hand side of a for-of loop may not be 'async'.", ForOfLet: "The left-hand side of a for-of loop may not start with 'let'.", @@ -263,6 +264,8 @@ export default { }`, UnexpectedTokenUnaryExponentiation: "Illegal expression. Wrap left hand side or entire exponentiation in parentheses.", + UnexpectedUsingDeclaration: + "Using declaration cannot appear in the top level when source type is `script`.", UnsupportedBind: "Binding should be performed on object property.", UnsupportedDecoratorExport: "A decorated export must export a class declaration.", @@ -288,6 +291,8 @@ export default { UnterminatedRegExp: "Unterminated regular expression.", UnterminatedString: "Unterminated string constant.", UnterminatedTemplate: "Unterminated template.", + UsingDeclarationHasBindingPattern: + "Using declaration cannot have destructuring patterns.", VarRedeclaration: ({ identifierName }: { identifierName: string }) => `Identifier '${identifierName}' has already been declared.`, YieldBindingIdentifier: diff --git a/packages/babel-parser/src/parser/statement.ts b/packages/babel-parser/src/parser/statement.ts index 56481df9aae0..b4fc104495cd 100644 --- a/packages/babel-parser/src/parser/statement.ts +++ b/packages/babel-parser/src/parser/statement.ts @@ -281,7 +281,7 @@ export default abstract class StatementParser extends ExpressionParser { if (!this.isContextual(tt._let)) { return false; } - return this.isLetKeyword(context); + return this.hasFollowingIdentifier(context); } /** @@ -293,7 +293,7 @@ export default abstract class StatementParser extends ExpressionParser { * @returns {boolean} * @memberof StatementParser */ - isLetKeyword(context?: string | null): boolean { + hasFollowingIdentifier(context?: string | null): boolean { const next = this.nextTokenStart(); const nextCh = this.codePointAtPos(next); // For ambiguous cases, determine if a LexicalDeclaration (or only a @@ -326,6 +326,17 @@ export default abstract class StatementParser extends ExpressionParser { return false; } + startsUsingForOf(): boolean { + const lookahead = this.lookahead(); + if (lookahead.type === tt._of && !lookahead.containsEsc) { + // `using of` must start a for-lhs-of statement + return false; + } else { + this.expectPlugin("explicitResourceManagement"); + return true; + } + } + // Parse a single statement. // // If expecting a statement and finding a slash operator, parse a @@ -351,14 +362,8 @@ export default abstract class StatementParser extends ExpressionParser { context?: string | null, topLevel?: boolean | null, ): N.Statement { - let starttype = this.state.type; + const starttype = this.state.type; const node = this.startNode(); - let kind; - - if (this.isLet(context)) { - starttype = tt._var; - kind = "let"; - } // Most types of statements are recognized by the keyword they // start with. Many are trivial to parse, some require a bit of @@ -405,9 +410,28 @@ export default abstract class StatementParser extends ExpressionParser { case tt._try: return this.parseTryStatement(node as Undone); + case tt._using: + // using [no LineTerminator here] BindingList[+Using] + if (this.hasFollowingLineBreak()) { + break; + } + // fall through + case tt._let: + if (this.state.containsEsc || !this.hasFollowingIdentifier(context)) { + break; + } + // fall through case tt._const: - case tt._var: - kind = kind || this.state.value; + case tt._var: { + const kind = this.state.value; + if (kind === "using") { + this.expectPlugin("explicitResourceManagement"); + if (!this.scope.inModule && this.scope.inTopLevel) { + this.raise(Errors.UnexpectedUsingDeclaration, { + at: this.state.startLoc, + }); + } + } if (context && kind !== "var") { this.raise(Errors.UnexpectedLexicalDeclaration, { at: this.state.startLoc, @@ -417,7 +441,7 @@ export default abstract class StatementParser extends ExpressionParser { node as Undone, kind, ); - + } case tt._while: return this.parseWhileStatement(node as Undone); case tt._with: @@ -762,16 +786,26 @@ export default abstract class StatementParser extends ExpressionParser { } const startsWithLet = this.isContextual(tt._let); - const isLet = startsWithLet && this.isLetKeyword(); - if (this.match(tt._var) || this.match(tt._const) || isLet) { + const startsWithUsing = + this.isContextual(tt._using) && !this.hasFollowingLineBreak(); + const isLetOrUsing = + (startsWithLet && this.hasFollowingIdentifier()) || + (startsWithUsing && + this.hasFollowingIdentifier() && + this.startsUsingForOf()); + if (this.match(tt._var) || this.match(tt._const) || isLetOrUsing) { const initNode = this.startNode(); - const kind = isLet ? "let" : this.state.value; + const kind = this.state.value; this.next(); this.parseVar(initNode, true, kind); const init = this.finishNode(initNode, "VariableDeclaration"); + const isForIn = this.match(tt._in); + if (isForIn && startsWithUsing) { + this.raise(Errors.ForInUsing, { at: init }); + } if ( - (this.match(tt._in) || this.isContextual(tt._of)) && + (isForIn || this.isContextual(tt._of)) && init.declarations.length === 1 ) { return this.parseForIn(node as Undone, init, awaitAt); @@ -989,7 +1023,7 @@ export default abstract class StatementParser extends ExpressionParser { parseVarStatement( this: Parser, node: Undone, - kind: "var" | "let" | "const", + kind: "var" | "let" | "const" | "using", allowMissingInitializer: boolean = false, ): N.VariableDeclaration { this.next(); @@ -1317,7 +1351,7 @@ export default abstract class StatementParser extends ExpressionParser { this: Parser, node: Undone, isFor: boolean, - kind: "var" | "let" | "const", + kind: "var" | "let" | "const" | "using", allowMissingInitializer: boolean = false, ): Undone { const declarations: N.VariableDeclarator[] = (node.declarations = []); @@ -1359,13 +1393,17 @@ export default abstract class StatementParser extends ExpressionParser { parseVarId( this: Parser, decl: Undone, - kind: "var" | "let" | "const", + kind: "var" | "let" | "const" | "using", ): void { - decl.id = this.parseBindingAtom(); - this.checkLVal(decl.id, { + const id = this.parseBindingAtom(); + if (kind === "using" && id.type !== "Identifier") { + this.raise(Errors.UsingDeclarationHasBindingPattern, { at: id }); + } + this.checkLVal(id, { in: { type: "VariableDeclarator" }, binding: kind === "var" ? BIND_VAR : BIND_LEXICAL, }); + decl.id = id; } // Parse a function declaration or literal (depending on the diff --git a/packages/babel-parser/src/plugins/placeholders.ts b/packages/babel-parser/src/plugins/placeholders.ts index a89b150f8c9b..1cc76f40b44d 100644 --- a/packages/babel-parser/src/plugins/placeholders.ts +++ b/packages/babel-parser/src/plugins/placeholders.ts @@ -152,16 +152,11 @@ export default (superClass: typeof Parser) => * parser/statement.js * * ============================================================ */ - isLet(context?: string | null): boolean { - if (super.isLet(context)) { + hasFollowingIdentifier(context?: string | null): boolean { + if (super.hasFollowingIdentifier(context)) { return true; } - // Replicate the original checks that lead to looking ahead for an - // identifier. - if (!this.isContextual(tt._let)) { - return false; - } if (context) return false; // Accept "let %%" as the start of "let %%placeholder%%", as though the diff --git a/packages/babel-parser/src/tokenizer/state.ts b/packages/babel-parser/src/tokenizer/state.ts index e5667faf2dfd..c39eb76c54a1 100644 --- a/packages/babel-parser/src/tokenizer/state.ts +++ b/packages/babel-parser/src/tokenizer/state.ts @@ -189,4 +189,7 @@ export type LookaheadState = { curPosition: () => Position; /* Used only in readToken_mult_modulo */ inType: boolean; + // These boolean properties are not initialized in createLookaheadState() + // instead they will only be set by the tokenizer + containsEsc?: boolean; }; diff --git a/packages/babel-parser/src/tokenizer/types.ts b/packages/babel-parser/src/tokenizer/types.ts index 0eb638d2693e..a35030e716f7 100644 --- a/packages/babel-parser/src/tokenizer/types.ts +++ b/packages/babel-parser/src/tokenizer/types.ts @@ -294,6 +294,7 @@ export const tt: InternalTokenTypes = { _sent: createKeywordLike("sent", { startsExpr }), _set: createKeywordLike("set", { startsExpr }), _static: createKeywordLike("static", { startsExpr }), + _using: createKeywordLike("using", { startsExpr }), _yield: createKeywordLike("yield", { startsExpr }), // Flow and TypeScript Keywordlike diff --git a/packages/babel-parser/src/types.d.ts b/packages/babel-parser/src/types.d.ts index a53d67316fba..c3063e1439d7 100644 --- a/packages/babel-parser/src/types.d.ts +++ b/packages/babel-parser/src/types.d.ts @@ -355,7 +355,7 @@ export interface FunctionDeclaration extends OptFunctionDeclaration { export interface VariableDeclaration extends DeclarationBase, HasDecorators { type: "VariableDeclaration"; declarations: VariableDeclarator[]; - kind: "var" | "let" | "const"; + kind: "var" | "let" | "const" | "using"; } export interface VariableDeclarator extends NodeBase { diff --git a/packages/babel-parser/src/typings.d.ts b/packages/babel-parser/src/typings.d.ts index 6cf279daa349..d04d9ff74425 100644 --- a/packages/babel-parser/src/typings.d.ts +++ b/packages/babel-parser/src/typings.d.ts @@ -12,6 +12,7 @@ export type Plugin = | "destructuringPrivate" | "doExpressions" | "dynamicImport" + | "explicitResourceManagement" | "exportDefaultFrom" | "exportNamespaceFrom" // deprecated | "flow" diff --git a/packages/babel-parser/src/util/scope.ts b/packages/babel-parser/src/util/scope.ts index 94277cbaf603..516130ab6ab7 100644 --- a/packages/babel-parser/src/util/scope.ts +++ b/packages/babel-parser/src/util/scope.ts @@ -48,6 +48,9 @@ export default class ScopeHandler { this.inModule = inModule; } + get inTopLevel() { + return (this.currentScope().flags & SCOPE_PROGRAM) > 0; + } get inFunction() { return (this.currentVarScopeFlags() & SCOPE_FUNCTION) > 0; } diff --git a/packages/babel-parser/test/fixtures/experimental/_no-plugin/explicit-resource-management-for-of/input.js b/packages/babel-parser/test/fixtures/experimental/_no-plugin/explicit-resource-management-for-of/input.js new file mode 100644 index 000000000000..00bcc4bbbc24 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/_no-plugin/explicit-resource-management-for-of/input.js @@ -0,0 +1 @@ +for (using reader of getReaders()); diff --git a/packages/babel-parser/test/fixtures/experimental/_no-plugin/explicit-resource-management-for-of/options.json b/packages/babel-parser/test/fixtures/experimental/_no-plugin/explicit-resource-management-for-of/options.json new file mode 100644 index 000000000000..335d92605b27 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/_no-plugin/explicit-resource-management-for-of/options.json @@ -0,0 +1,3 @@ +{ + "throws": "This experimental syntax requires enabling the parser plugin: \"explicitResourceManagement\". (1:5)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/_no-plugin/explicit-resource-management-variable-declaration/input.js b/packages/babel-parser/test/fixtures/experimental/_no-plugin/explicit-resource-management-variable-declaration/input.js new file mode 100644 index 000000000000..9f1dc211a81c --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/_no-plugin/explicit-resource-management-variable-declaration/input.js @@ -0,0 +1 @@ +using reader = getReader(); diff --git a/packages/babel-parser/test/fixtures/experimental/_no-plugin/explicit-resource-management-variable-declaration/options.json b/packages/babel-parser/test/fixtures/experimental/_no-plugin/explicit-resource-management-variable-declaration/options.json new file mode 100644 index 000000000000..a5fcb8118e1f --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/_no-plugin/explicit-resource-management-variable-declaration/options.json @@ -0,0 +1,3 @@ +{ + "throws": "This experimental syntax requires enabling the parser plugin: \"explicitResourceManagement\". (1:0)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-duplicate-using-bindings/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-duplicate-using-bindings/input.js new file mode 100644 index 000000000000..d04dedd0e6b6 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-duplicate-using-bindings/input.js @@ -0,0 +1,7 @@ +{ + using f, f = foo(); +} +{ + using g = foo(); + using g = foo(); +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-duplicate-using-bindings/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-duplicate-using-bindings/output.json new file mode 100644 index 000000000000..b2dd2ff6f5d0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-duplicate-using-bindings/output.json @@ -0,0 +1,119 @@ +{ + "type": "File", + "start":0,"end":67,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":7,"column":1,"index":67}}, + "errors": [ + "SyntaxError: Identifier 'f' has already been declared. (2:11)", + "SyntaxError: Identifier 'g' has already been declared. (6:8)" + ], + "program": { + "type": "Program", + "start":0,"end":67,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":7,"column":1,"index":67}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "BlockStatement", + "start":0,"end":25,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":25}}, + "body": [ + { + "type": "VariableDeclaration", + "start":4,"end":23,"loc":{"start":{"line":2,"column":2,"index":4},"end":{"line":2,"column":21,"index":23}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":10,"end":11,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":9,"index":11}}, + "id": { + "type": "Identifier", + "start":10,"end":11,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":9,"index":11},"identifierName":"f"}, + "name": "f" + }, + "init": null + }, + { + "type": "VariableDeclarator", + "start":13,"end":22,"loc":{"start":{"line":2,"column":11,"index":13},"end":{"line":2,"column":20,"index":22}}, + "id": { + "type": "Identifier", + "start":13,"end":14,"loc":{"start":{"line":2,"column":11,"index":13},"end":{"line":2,"column":12,"index":14},"identifierName":"f"}, + "name": "f" + }, + "init": { + "type": "CallExpression", + "start":17,"end":22,"loc":{"start":{"line":2,"column":15,"index":17},"end":{"line":2,"column":20,"index":22}}, + "callee": { + "type": "Identifier", + "start":17,"end":20,"loc":{"start":{"line":2,"column":15,"index":17},"end":{"line":2,"column":18,"index":20},"identifierName":"foo"}, + "name": "foo" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + }, + { + "type": "BlockStatement", + "start":26,"end":67,"loc":{"start":{"line":4,"column":0,"index":26},"end":{"line":7,"column":1,"index":67}}, + "body": [ + { + "type": "VariableDeclaration", + "start":30,"end":46,"loc":{"start":{"line":5,"column":2,"index":30},"end":{"line":5,"column":18,"index":46}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":36,"end":45,"loc":{"start":{"line":5,"column":8,"index":36},"end":{"line":5,"column":17,"index":45}}, + "id": { + "type": "Identifier", + "start":36,"end":37,"loc":{"start":{"line":5,"column":8,"index":36},"end":{"line":5,"column":9,"index":37},"identifierName":"g"}, + "name": "g" + }, + "init": { + "type": "CallExpression", + "start":40,"end":45,"loc":{"start":{"line":5,"column":12,"index":40},"end":{"line":5,"column":17,"index":45}}, + "callee": { + "type": "Identifier", + "start":40,"end":43,"loc":{"start":{"line":5,"column":12,"index":40},"end":{"line":5,"column":15,"index":43},"identifierName":"foo"}, + "name": "foo" + }, + "arguments": [] + } + } + ], + "kind": "using" + }, + { + "type": "VariableDeclaration", + "start":49,"end":65,"loc":{"start":{"line":6,"column":2,"index":49},"end":{"line":6,"column":18,"index":65}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":55,"end":64,"loc":{"start":{"line":6,"column":8,"index":55},"end":{"line":6,"column":17,"index":64}}, + "id": { + "type": "Identifier", + "start":55,"end":56,"loc":{"start":{"line":6,"column":8,"index":55},"end":{"line":6,"column":9,"index":56},"identifierName":"g"}, + "name": "g" + }, + "init": { + "type": "CallExpression", + "start":59,"end":64,"loc":{"start":{"line":6,"column":12,"index":59},"end":{"line":6,"column":17,"index":64}}, + "callee": { + "type": "Identifier", + "start":59,"end":62,"loc":{"start":{"line":6,"column":12,"index":59},"end":{"line":6,"column":15,"index":62},"identifierName":"foo"}, + "name": "foo" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-await-using-binding-of-of/input.mjs b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-await-using-binding-of-of/input.mjs new file mode 100644 index 000000000000..215d13819232 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-await-using-binding-of-of/input.mjs @@ -0,0 +1 @@ +for await (using of of of); diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-await-using-binding-of-of/options.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-await-using-binding-of-of/options.json new file mode 100644 index 000000000000..253b9d69fbce --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-await-using-binding-of-of/options.json @@ -0,0 +1,4 @@ +{ + "sourceType": "module", + "throws": "Unexpected token, expected \")\" (1:23)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-in/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-in/input.js new file mode 100644 index 000000000000..0676e7bf0436 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-in/input.js @@ -0,0 +1 @@ +for (using foo in {}); diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-in/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-in/output.json new file mode 100644 index 000000000000..33e3f36a15f8 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-in/output.json @@ -0,0 +1,46 @@ +{ + "type": "File", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":22,"index":22}}, + "errors": [ + "SyntaxError: For-in loop may not start with 'using' declaration. (1:5)" + ], + "program": { + "type": "Program", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":22,"index":22}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ForInStatement", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":22,"index":22}}, + "left": { + "type": "VariableDeclaration", + "start":5,"end":14,"loc":{"start":{"line":1,"column":5,"index":5},"end":{"line":1,"column":14,"index":14}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":11,"end":14,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":14,"index":14}}, + "id": { + "type": "Identifier", + "start":11,"end":14,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":14,"index":14},"identifierName":"foo"}, + "name": "foo" + }, + "init": null + } + ], + "kind": "using" + }, + "right": { + "type": "ObjectExpression", + "start":18,"end":20,"loc":{"start":{"line":1,"column":18,"index":18},"end":{"line":1,"column":20,"index":20}}, + "properties": [] + }, + "body": { + "type": "EmptyStatement", + "start":21,"end":22,"loc":{"start":{"line":1,"column":21,"index":21},"end":{"line":1,"column":22,"index":22}} + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-of-in/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-of-in/input.js new file mode 100644 index 000000000000..28f239c385de --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-of-in/input.js @@ -0,0 +1 @@ +for (using of in []); diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-of-in/options.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-of-in/options.json new file mode 100644 index 000000000000..d50e8469b860 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-of-in/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (1:14)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-of-of/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-of-of/input.js new file mode 100644 index 000000000000..4795b33654a1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-of-of/input.js @@ -0,0 +1 @@ +for (using of of of); diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-of-of/options.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-of-of/options.json new file mode 100644 index 000000000000..9432d2ede36d --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-for-using-binding-of-of/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token, expected \")\" (1:17)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-script-top-level-using-binding/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-script-top-level-using-binding/input.js new file mode 100644 index 000000000000..e33689ba7080 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-script-top-level-using-binding/input.js @@ -0,0 +1 @@ +using x = bar(); diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-script-top-level-using-binding/options.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-script-top-level-using-binding/options.json new file mode 100644 index 000000000000..b412ffe6712f --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-script-top-level-using-binding/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "script" +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-script-top-level-using-binding/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-script-top-level-using-binding/output.json new file mode 100644 index 000000000000..b4c4407a1b9b --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-script-top-level-using-binding/output.json @@ -0,0 +1,42 @@ +{ + "type": "File", + "start":0,"end":16,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":16,"index":16}}, + "errors": [ + "SyntaxError: Using declaration cannot appear in the top level when source type is `script`. (1:0)" + ], + "program": { + "type": "Program", + "start":0,"end":16,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":16,"index":16}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":0,"end":16,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":16,"index":16}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":6,"end":15,"loc":{"start":{"line":1,"column":6,"index":6},"end":{"line":1,"column":15,"index":15}}, + "id": { + "type": "Identifier", + "start":6,"end":7,"loc":{"start":{"line":1,"column":6,"index":6},"end":{"line":1,"column":7,"index":7},"identifierName":"x"}, + "name": "x" + }, + "init": { + "type": "CallExpression", + "start":10,"end":15,"loc":{"start":{"line":1,"column":10,"index":10},"end":{"line":1,"column":15,"index":15}}, + "callee": { + "type": "Identifier", + "start":10,"end":13,"loc":{"start":{"line":1,"column":10,"index":10},"end":{"line":1,"column":13,"index":13},"identifierName":"bar"}, + "name": "bar" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-let/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-let/input.js new file mode 100644 index 000000000000..c0d1a8f2d474 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-let/input.js @@ -0,0 +1,3 @@ +{ + using let = h(); +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-let/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-let/output.json new file mode 100644 index 000000000000..451251d317c5 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-let/output.json @@ -0,0 +1,49 @@ +{ + "type": "File", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":22}}, + "errors": [ + "SyntaxError: 'let' is not allowed to be used as a name in 'let' or 'const' declarations. (2:8)" + ], + "program": { + "type": "Program", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":22}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "BlockStatement", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":22}}, + "body": [ + { + "type": "VariableDeclaration", + "start":4,"end":20,"loc":{"start":{"line":2,"column":2,"index":4},"end":{"line":2,"column":18,"index":20}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":10,"end":19,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":17,"index":19}}, + "id": { + "type": "Identifier", + "start":10,"end":13,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":11,"index":13},"identifierName":"let"}, + "name": "let" + }, + "init": { + "type": "CallExpression", + "start":16,"end":19,"loc":{"start":{"line":2,"column":14,"index":16},"end":{"line":2,"column":17,"index":19}}, + "callee": { + "type": "Identifier", + "start":16,"end":17,"loc":{"start":{"line":2,"column":14,"index":16},"end":{"line":2,"column":15,"index":17},"identifierName":"h"}, + "name": "h" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-pattern/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-pattern/input.js new file mode 100644 index 000000000000..2a0678a9ce82 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-pattern/input.js @@ -0,0 +1,6 @@ +{ + using { foo } = f(); + using [ bar ] = g(); + for (using { qux } of h()); + for (using [ quux ] of i()); +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-pattern/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-pattern/output.json new file mode 100644 index 000000000000..7ddc83fa56b5 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-pattern/output.json @@ -0,0 +1,204 @@ +{ + "type": "File", + "start":0,"end":110,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":6,"column":1,"index":110}}, + "errors": [ + "SyntaxError: Using declaration cannot have destructuring patterns. (2:8)", + "SyntaxError: Using declaration cannot have destructuring patterns. (3:8)", + "SyntaxError: Using declaration cannot have destructuring patterns. (4:13)", + "SyntaxError: Using declaration cannot have destructuring patterns. (5:13)" + ], + "program": { + "type": "Program", + "start":0,"end":110,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":6,"column":1,"index":110}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "BlockStatement", + "start":0,"end":110,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":6,"column":1,"index":110}}, + "body": [ + { + "type": "VariableDeclaration", + "start":4,"end":24,"loc":{"start":{"line":2,"column":2,"index":4},"end":{"line":2,"column":22,"index":24}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":10,"end":23,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":21,"index":23}}, + "id": { + "type": "ObjectPattern", + "start":10,"end":17,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":15,"index":17}}, + "properties": [ + { + "type": "ObjectProperty", + "start":12,"end":15,"loc":{"start":{"line":2,"column":10,"index":12},"end":{"line":2,"column":13,"index":15}}, + "key": { + "type": "Identifier", + "start":12,"end":15,"loc":{"start":{"line":2,"column":10,"index":12},"end":{"line":2,"column":13,"index":15},"identifierName":"foo"}, + "name": "foo" + }, + "computed": false, + "method": false, + "shorthand": true, + "value": { + "type": "Identifier", + "start":12,"end":15,"loc":{"start":{"line":2,"column":10,"index":12},"end":{"line":2,"column":13,"index":15},"identifierName":"foo"}, + "name": "foo" + }, + "extra": { + "shorthand": true + } + } + ] + }, + "init": { + "type": "CallExpression", + "start":20,"end":23,"loc":{"start":{"line":2,"column":18,"index":20},"end":{"line":2,"column":21,"index":23}}, + "callee": { + "type": "Identifier", + "start":20,"end":21,"loc":{"start":{"line":2,"column":18,"index":20},"end":{"line":2,"column":19,"index":21},"identifierName":"f"}, + "name": "f" + }, + "arguments": [] + } + } + ], + "kind": "using" + }, + { + "type": "VariableDeclaration", + "start":27,"end":47,"loc":{"start":{"line":3,"column":2,"index":27},"end":{"line":3,"column":22,"index":47}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":33,"end":46,"loc":{"start":{"line":3,"column":8,"index":33},"end":{"line":3,"column":21,"index":46}}, + "id": { + "type": "ArrayPattern", + "start":33,"end":40,"loc":{"start":{"line":3,"column":8,"index":33},"end":{"line":3,"column":15,"index":40}}, + "elements": [ + { + "type": "Identifier", + "start":35,"end":38,"loc":{"start":{"line":3,"column":10,"index":35},"end":{"line":3,"column":13,"index":38},"identifierName":"bar"}, + "name": "bar" + } + ] + }, + "init": { + "type": "CallExpression", + "start":43,"end":46,"loc":{"start":{"line":3,"column":18,"index":43},"end":{"line":3,"column":21,"index":46}}, + "callee": { + "type": "Identifier", + "start":43,"end":44,"loc":{"start":{"line":3,"column":18,"index":43},"end":{"line":3,"column":19,"index":44},"identifierName":"g"}, + "name": "g" + }, + "arguments": [] + } + } + ], + "kind": "using" + }, + { + "type": "ForOfStatement", + "start":50,"end":77,"loc":{"start":{"line":4,"column":2,"index":50},"end":{"line":4,"column":29,"index":77}}, + "await": false, + "left": { + "type": "VariableDeclaration", + "start":55,"end":68,"loc":{"start":{"line":4,"column":7,"index":55},"end":{"line":4,"column":20,"index":68}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":61,"end":68,"loc":{"start":{"line":4,"column":13,"index":61},"end":{"line":4,"column":20,"index":68}}, + "id": { + "type": "ObjectPattern", + "start":61,"end":68,"loc":{"start":{"line":4,"column":13,"index":61},"end":{"line":4,"column":20,"index":68}}, + "properties": [ + { + "type": "ObjectProperty", + "start":63,"end":66,"loc":{"start":{"line":4,"column":15,"index":63},"end":{"line":4,"column":18,"index":66}}, + "key": { + "type": "Identifier", + "start":63,"end":66,"loc":{"start":{"line":4,"column":15,"index":63},"end":{"line":4,"column":18,"index":66},"identifierName":"qux"}, + "name": "qux" + }, + "computed": false, + "method": false, + "shorthand": true, + "value": { + "type": "Identifier", + "start":63,"end":66,"loc":{"start":{"line":4,"column":15,"index":63},"end":{"line":4,"column":18,"index":66},"identifierName":"qux"}, + "name": "qux" + }, + "extra": { + "shorthand": true + } + } + ] + }, + "init": null + } + ], + "kind": "using" + }, + "right": { + "type": "CallExpression", + "start":72,"end":75,"loc":{"start":{"line":4,"column":24,"index":72},"end":{"line":4,"column":27,"index":75}}, + "callee": { + "type": "Identifier", + "start":72,"end":73,"loc":{"start":{"line":4,"column":24,"index":72},"end":{"line":4,"column":25,"index":73},"identifierName":"h"}, + "name": "h" + }, + "arguments": [] + }, + "body": { + "type": "EmptyStatement", + "start":76,"end":77,"loc":{"start":{"line":4,"column":28,"index":76},"end":{"line":4,"column":29,"index":77}} + } + }, + { + "type": "ForOfStatement", + "start":80,"end":108,"loc":{"start":{"line":5,"column":2,"index":80},"end":{"line":5,"column":30,"index":108}}, + "await": false, + "left": { + "type": "VariableDeclaration", + "start":85,"end":99,"loc":{"start":{"line":5,"column":7,"index":85},"end":{"line":5,"column":21,"index":99}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":91,"end":99,"loc":{"start":{"line":5,"column":13,"index":91},"end":{"line":5,"column":21,"index":99}}, + "id": { + "type": "ArrayPattern", + "start":91,"end":99,"loc":{"start":{"line":5,"column":13,"index":91},"end":{"line":5,"column":21,"index":99}}, + "elements": [ + { + "type": "Identifier", + "start":93,"end":97,"loc":{"start":{"line":5,"column":15,"index":93},"end":{"line":5,"column":19,"index":97},"identifierName":"quux"}, + "name": "quux" + } + ] + }, + "init": null + } + ], + "kind": "using" + }, + "right": { + "type": "CallExpression", + "start":103,"end":106,"loc":{"start":{"line":5,"column":25,"index":103},"end":{"line":5,"column":28,"index":106}}, + "callee": { + "type": "Identifier", + "start":103,"end":104,"loc":{"start":{"line":5,"column":25,"index":103},"end":{"line":5,"column":26,"index":104},"identifierName":"i"}, + "name": "i" + }, + "arguments": [] + }, + "body": { + "type": "EmptyStatement", + "start":107,"end":108,"loc":{"start":{"line":5,"column":29,"index":107},"end":{"line":5,"column":30,"index":108}} + } + } + ], + "directives": [] + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/options.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/options.json new file mode 100644 index 000000000000..495a16f9a39a --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["explicitResourceManagement"] +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-await-using-binding-escaped-of-of/input.mjs b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-await-using-binding-escaped-of-of/input.mjs new file mode 100644 index 000000000000..510149a318e8 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-await-using-binding-escaped-of-of/input.mjs @@ -0,0 +1 @@ +for await (using \u006ff of of); diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-await-using-binding-escaped-of-of/options.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-await-using-binding-escaped-of-of/options.json new file mode 100644 index 000000000000..2104ca43283f --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-await-using-binding-escaped-of-of/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "module" +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-await-using-binding-escaped-of-of/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-await-using-binding-escaped-of-of/output.json new file mode 100644 index 000000000000..67467ec8b50a --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-await-using-binding-escaped-of-of/output.json @@ -0,0 +1,44 @@ +{ + "type": "File", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":32,"index":32}}, + "program": { + "type": "Program", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":32,"index":32}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ForOfStatement", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":32,"index":32}}, + "await": true, + "left": { + "type": "VariableDeclaration", + "start":11,"end":24,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":24,"index":24}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":17,"end":24,"loc":{"start":{"line":1,"column":17,"index":17},"end":{"line":1,"column":24,"index":24}}, + "id": { + "type": "Identifier", + "start":17,"end":24,"loc":{"start":{"line":1,"column":17,"index":17},"end":{"line":1,"column":24,"index":24},"identifierName":"of"}, + "name": "of" + }, + "init": null + } + ], + "kind": "using" + }, + "right": { + "type": "Identifier", + "start":28,"end":30,"loc":{"start":{"line":1,"column":28,"index":28},"end":{"line":1,"column":30,"index":30},"identifierName":"of"}, + "name": "of" + }, + "body": { + "type": "EmptyStatement", + "start":31,"end":32,"loc":{"start":{"line":1,"column":31,"index":31},"end":{"line":1,"column":32,"index":32}} + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-using-binding-escaped-of-of/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-using-binding-escaped-of-of/input.js new file mode 100644 index 000000000000..c879259290dd --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-using-binding-escaped-of-of/input.js @@ -0,0 +1 @@ +for (using o\u0066 of of); diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-using-binding-escaped-of-of/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-using-binding-escaped-of-of/output.json new file mode 100644 index 000000000000..a4be3572d81f --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-for-using-binding-escaped-of-of/output.json @@ -0,0 +1,44 @@ +{ + "type": "File", + "start":0,"end":26,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":26,"index":26}}, + "program": { + "type": "Program", + "start":0,"end":26,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":26,"index":26}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ForOfStatement", + "start":0,"end":26,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":26,"index":26}}, + "await": false, + "left": { + "type": "VariableDeclaration", + "start":5,"end":18,"loc":{"start":{"line":1,"column":5,"index":5},"end":{"line":1,"column":18,"index":18}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":11,"end":18,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":18,"index":18}}, + "id": { + "type": "Identifier", + "start":11,"end":18,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":18,"index":18},"identifierName":"of"}, + "name": "of" + }, + "init": null + } + ], + "kind": "using" + }, + "right": { + "type": "Identifier", + "start":22,"end":24,"loc":{"start":{"line":1,"column":22,"index":22},"end":{"line":1,"column":24,"index":24},"identifierName":"of"}, + "name": "of" + }, + "body": { + "type": "EmptyStatement", + "start":25,"end":26,"loc":{"start":{"line":1,"column":25,"index":25},"end":{"line":1,"column":26,"index":26}} + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-module-block-top-level-using-binding/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-module-block-top-level-using-binding/input.js new file mode 100644 index 000000000000..b9c213bf2e94 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-module-block-top-level-using-binding/input.js @@ -0,0 +1,3 @@ +module { + using foo = bar(); +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-module-block-top-level-using-binding/options.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-module-block-top-level-using-binding/options.json new file mode 100644 index 000000000000..aefaa1b232dd --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-module-block-top-level-using-binding/options.json @@ -0,0 +1,4 @@ +{ + "sourceType": "script", + "plugins": ["explicitResourceManagement", "moduleBlocks"] +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-module-block-top-level-using-binding/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-module-block-top-level-using-binding/output.json new file mode 100644 index 000000000000..9c7321cbaef8 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-module-block-top-level-using-binding/output.json @@ -0,0 +1,56 @@ +{ + "type": "File", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":31}}, + "program": { + "type": "Program", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":31}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":31}}, + "expression": { + "type": "ModuleExpression", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":31}}, + "body": { + "type": "Program", + "start":8,"end":30,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":3,"column":0,"index":30}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":11,"end":29,"loc":{"start":{"line":2,"column":2,"index":11},"end":{"line":2,"column":20,"index":29}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":17,"end":28,"loc":{"start":{"line":2,"column":8,"index":17},"end":{"line":2,"column":19,"index":28}}, + "id": { + "type": "Identifier", + "start":17,"end":20,"loc":{"start":{"line":2,"column":8,"index":17},"end":{"line":2,"column":11,"index":20},"identifierName":"foo"}, + "name": "foo" + }, + "init": { + "type": "CallExpression", + "start":23,"end":28,"loc":{"start":{"line":2,"column":14,"index":23},"end":{"line":2,"column":19,"index":28}}, + "callee": { + "type": "Identifier", + "start":23,"end":26,"loc":{"start":{"line":2,"column":14,"index":23},"end":{"line":2,"column":17,"index":26},"identifierName":"bar"}, + "name": "bar" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + } + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-expression-statement/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-expression-statement/input.js new file mode 100644 index 000000000000..8261b5a2e0b3 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-expression-statement/input.js @@ -0,0 +1,2 @@ +using +reader = getReader() diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-expression-statement/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-expression-statement/output.json new file mode 100644 index 000000000000..9ba4a8772a56 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-expression-statement/output.json @@ -0,0 +1,46 @@ +{ + "type": "File", + "start":0,"end":26,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":20,"index":26}}, + "program": { + "type": "Program", + "start":0,"end":26,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":20,"index":26}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":5,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":5,"index":5}}, + "expression": { + "type": "Identifier", + "start":0,"end":5,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":5,"index":5},"identifierName":"using"}, + "name": "using" + } + }, + { + "type": "ExpressionStatement", + "start":6,"end":26,"loc":{"start":{"line":2,"column":0,"index":6},"end":{"line":2,"column":20,"index":26}}, + "expression": { + "type": "AssignmentExpression", + "start":6,"end":26,"loc":{"start":{"line":2,"column":0,"index":6},"end":{"line":2,"column":20,"index":26}}, + "operator": "=", + "left": { + "type": "Identifier", + "start":6,"end":12,"loc":{"start":{"line":2,"column":0,"index":6},"end":{"line":2,"column":6,"index":12},"identifierName":"reader"}, + "name": "reader" + }, + "right": { + "type": "CallExpression", + "start":15,"end":26,"loc":{"start":{"line":2,"column":9,"index":15},"end":{"line":2,"column":20,"index":26}}, + "callee": { + "type": "Identifier", + "start":15,"end":24,"loc":{"start":{"line":2,"column":9,"index":15},"end":{"line":2,"column":18,"index":24},"identifierName":"getReader"}, + "name": "getReader" + }, + "arguments": [] + } + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-await-of/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-await-of/input.js new file mode 100644 index 000000000000..9c1ceb473d77 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-await-of/input.js @@ -0,0 +1 @@ +for await (using of of); diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-await-of/options.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-await-of/options.json new file mode 100644 index 000000000000..2104ca43283f --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-await-of/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "module" +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-await-of/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-await-of/output.json new file mode 100644 index 000000000000..b9cbc73cd352 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-await-of/output.json @@ -0,0 +1,32 @@ +{ + "type": "File", + "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":24,"index":24}}, + "program": { + "type": "Program", + "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":24,"index":24}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ForOfStatement", + "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":24,"index":24}}, + "await": true, + "left": { + "type": "Identifier", + "start":11,"end":16,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":16,"index":16},"identifierName":"using"}, + "name": "using" + }, + "right": { + "type": "Identifier", + "start":20,"end":22,"loc":{"start":{"line":1,"column":20,"index":20},"end":{"line":1,"column":22,"index":22},"identifierName":"of"}, + "name": "of" + }, + "body": { + "type": "EmptyStatement", + "start":23,"end":24,"loc":{"start":{"line":1,"column":23,"index":23},"end":{"line":1,"column":24,"index":24}} + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-in/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-in/input.js new file mode 100644 index 000000000000..fb5a69740d6b --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-in/input.js @@ -0,0 +1 @@ +for (using in []); diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-in/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-in/output.json new file mode 100644 index 000000000000..41f7971dacc5 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-in/output.json @@ -0,0 +1,31 @@ +{ + "type": "File", + "start":0,"end":18,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":18,"index":18}}, + "program": { + "type": "Program", + "start":0,"end":18,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":18,"index":18}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ForInStatement", + "start":0,"end":18,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":18,"index":18}}, + "left": { + "type": "Identifier", + "start":5,"end":10,"loc":{"start":{"line":1,"column":5,"index":5},"end":{"line":1,"column":10,"index":10},"identifierName":"using"}, + "name": "using" + }, + "right": { + "type": "ArrayExpression", + "start":14,"end":16,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":16,"index":16}}, + "elements": [] + }, + "body": { + "type": "EmptyStatement", + "start":17,"end":18,"loc":{"start":{"line":1,"column":17,"index":17},"end":{"line":1,"column":18,"index":18}} + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-init/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-init/input.js new file mode 100644 index 000000000000..e2115da2feae --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-init/input.js @@ -0,0 +1,3 @@ +for ( + using; + reader = getReader();); diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-init/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-init/output.json new file mode 100644 index 000000000000..49c2acaee451 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-init/output.json @@ -0,0 +1,47 @@ +{ + "type": "File", + "start":0,"end":40,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":25,"index":40}}, + "program": { + "type": "Program", + "start":0,"end":40,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":25,"index":40}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ForStatement", + "start":0,"end":40,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":25,"index":40}}, + "init": { + "type": "Identifier", + "start":8,"end":13,"loc":{"start":{"line":2,"column":2,"index":8},"end":{"line":2,"column":7,"index":13},"identifierName":"using"}, + "name": "using" + }, + "test": { + "type": "AssignmentExpression", + "start":17,"end":37,"loc":{"start":{"line":3,"column":2,"index":17},"end":{"line":3,"column":22,"index":37}}, + "operator": "=", + "left": { + "type": "Identifier", + "start":17,"end":23,"loc":{"start":{"line":3,"column":2,"index":17},"end":{"line":3,"column":8,"index":23},"identifierName":"reader"}, + "name": "reader" + }, + "right": { + "type": "CallExpression", + "start":26,"end":37,"loc":{"start":{"line":3,"column":11,"index":26},"end":{"line":3,"column":22,"index":37}}, + "callee": { + "type": "Identifier", + "start":26,"end":35,"loc":{"start":{"line":3,"column":11,"index":26},"end":{"line":3,"column":20,"index":35},"identifierName":"getReader"}, + "name": "getReader" + }, + "arguments": [] + } + }, + "update": null, + "body": { + "type": "EmptyStatement", + "start":39,"end":40,"loc":{"start":{"line":3,"column":24,"index":39},"end":{"line":3,"column":25,"index":40}} + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-of/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-of/input.js new file mode 100644 index 000000000000..71c7cc667fa1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-of/input.js @@ -0,0 +1 @@ +for (using of of); diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-of/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-of/output.json new file mode 100644 index 000000000000..ad0e3954d5fd --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-for-of/output.json @@ -0,0 +1,32 @@ +{ + "type": "File", + "start":0,"end":18,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":18,"index":18}}, + "program": { + "type": "Program", + "start":0,"end":18,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":18,"index":18}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ForOfStatement", + "start":0,"end":18,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":18,"index":18}}, + "await": false, + "left": { + "type": "Identifier", + "start":5,"end":10,"loc":{"start":{"line":1,"column":5,"index":5},"end":{"line":1,"column":10,"index":10},"identifierName":"using"}, + "name": "using" + }, + "right": { + "type": "Identifier", + "start":14,"end":16,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":16,"index":16},"identifierName":"of"}, + "name": "of" + }, + "body": { + "type": "EmptyStatement", + "start":17,"end":18,"loc":{"start":{"line":1,"column":17,"index":17},"end":{"line":1,"column":18,"index":18}} + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-in/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-in/input.js new file mode 100644 index 000000000000..b7574f490471 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-in/input.js @@ -0,0 +1 @@ +using in using instanceof using; diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-in/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-in/output.json new file mode 100644 index 000000000000..c3f8067a6a4e --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-as-identifier-in/output.json @@ -0,0 +1,42 @@ +{ + "type": "File", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":32,"index":32}}, + "program": { + "type": "Program", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":32,"index":32}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":32,"index":32}}, + "expression": { + "type": "BinaryExpression", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":31,"index":31}}, + "left": { + "type": "BinaryExpression", + "start":0,"end":14,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":14,"index":14}}, + "left": { + "type": "Identifier", + "start":0,"end":5,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":5,"index":5},"identifierName":"using"}, + "name": "using" + }, + "operator": "in", + "right": { + "type": "Identifier", + "start":9,"end":14,"loc":{"start":{"line":1,"column":9,"index":9},"end":{"line":1,"column":14,"index":14},"identifierName":"using"}, + "name": "using" + } + }, + "operator": "instanceof", + "right": { + "type": "Identifier", + "start":26,"end":31,"loc":{"start":{"line":1,"column":26,"index":26},"end":{"line":1,"column":31,"index":31},"identifierName":"using"}, + "name": "using" + } + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-basic/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-basic/input.js new file mode 100644 index 000000000000..9f8f2445bc6a --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-basic/input.js @@ -0,0 +1,3 @@ +{ + using basic = getReader(); +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-basic/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-basic/output.json new file mode 100644 index 000000000000..d0916e11a02c --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-basic/output.json @@ -0,0 +1,46 @@ +{ + "type": "File", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":32}}, + "program": { + "type": "Program", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":32}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "BlockStatement", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":32}}, + "body": [ + { + "type": "VariableDeclaration", + "start":4,"end":30,"loc":{"start":{"line":2,"column":2,"index":4},"end":{"line":2,"column":28,"index":30}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":10,"end":29,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":27,"index":29}}, + "id": { + "type": "Identifier", + "start":10,"end":15,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":13,"index":15},"identifierName":"basic"}, + "name": "basic" + }, + "init": { + "type": "CallExpression", + "start":18,"end":29,"loc":{"start":{"line":2,"column":16,"index":18},"end":{"line":2,"column":27,"index":29}}, + "callee": { + "type": "Identifier", + "start":18,"end":27,"loc":{"start":{"line":2,"column":16,"index":18},"end":{"line":2,"column":25,"index":27},"identifierName":"getReader"}, + "name": "getReader" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-escaped/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-escaped/input.js new file mode 100644 index 000000000000..475887f4dbdf --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-escaped/input.js @@ -0,0 +1 @@ +{ using \u0061b = c; } diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-escaped/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-escaped/output.json new file mode 100644 index 000000000000..73a2eb1e4d0b --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-escaped/output.json @@ -0,0 +1,41 @@ +{ + "type": "File", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":22,"index":22}}, + "program": { + "type": "Program", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":22,"index":22}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "BlockStatement", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":22,"index":22}}, + "body": [ + { + "type": "VariableDeclaration", + "start":2,"end":20,"loc":{"start":{"line":1,"column":2,"index":2},"end":{"line":1,"column":20,"index":20}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":8,"end":19,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":19,"index":19}}, + "id": { + "type": "Identifier", + "start":8,"end":15,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":15,"index":15},"identifierName":"ab"}, + "name": "ab" + }, + "init": { + "type": "Identifier", + "start":18,"end":19,"loc":{"start":{"line":1,"column":18,"index":18},"end":{"line":1,"column":19,"index":19},"identifierName":"c"}, + "name": "c" + } + } + ], + "kind": "using" + } + ], + "directives": [] + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-non-bmp/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-non-bmp/input.js new file mode 100644 index 000000000000..ff01e43dfd6f --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-non-bmp/input.js @@ -0,0 +1 @@ +{ using 𠮷 = foo(); } diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-non-bmp/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-non-bmp/output.json new file mode 100644 index 000000000000..87a71e6fefed --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-non-bmp/output.json @@ -0,0 +1,46 @@ +{ + "type": "File", + "start":0,"end":21,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":21,"index":21}}, + "program": { + "type": "Program", + "start":0,"end":21,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":21,"index":21}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "BlockStatement", + "start":0,"end":21,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":21,"index":21}}, + "body": [ + { + "type": "VariableDeclaration", + "start":2,"end":19,"loc":{"start":{"line":1,"column":2,"index":2},"end":{"line":1,"column":19,"index":19}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":8,"end":18,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":18,"index":18}}, + "id": { + "type": "Identifier", + "start":8,"end":10,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":10,"index":10},"identifierName":"𠮷"}, + "name": "𠮷" + }, + "init": { + "type": "CallExpression", + "start":13,"end":18,"loc":{"start":{"line":1,"column":13,"index":13},"end":{"line":1,"column":18,"index":18}}, + "callee": { + "type": "Identifier", + "start":13,"end":16,"loc":{"start":{"line":1,"column":13,"index":13},"end":{"line":1,"column":16,"index":16},"identifierName":"foo"}, + "name": "foo" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-using/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-using/input.js new file mode 100644 index 000000000000..62baf2a5e640 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-using/input.js @@ -0,0 +1,4 @@ +{ + using using = of; + for (using using of of); +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-using/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-using/output.json new file mode 100644 index 000000000000..5580855aa4a1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/valid-using-binding-using/output.json @@ -0,0 +1,72 @@ +{ + "type": "File", + "start":0,"end":50,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":4,"column":1,"index":50}}, + "program": { + "type": "Program", + "start":0,"end":50,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":4,"column":1,"index":50}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "BlockStatement", + "start":0,"end":50,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":4,"column":1,"index":50}}, + "body": [ + { + "type": "VariableDeclaration", + "start":4,"end":21,"loc":{"start":{"line":2,"column":2,"index":4},"end":{"line":2,"column":19,"index":21}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":10,"end":20,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":18,"index":20}}, + "id": { + "type": "Identifier", + "start":10,"end":15,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":13,"index":15},"identifierName":"using"}, + "name": "using" + }, + "init": { + "type": "Identifier", + "start":18,"end":20,"loc":{"start":{"line":2,"column":16,"index":18},"end":{"line":2,"column":18,"index":20},"identifierName":"of"}, + "name": "of" + } + } + ], + "kind": "using" + }, + { + "type": "ForOfStatement", + "start":24,"end":48,"loc":{"start":{"line":3,"column":2,"index":24},"end":{"line":3,"column":26,"index":48}}, + "await": false, + "left": { + "type": "VariableDeclaration", + "start":29,"end":40,"loc":{"start":{"line":3,"column":7,"index":29},"end":{"line":3,"column":18,"index":40}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":35,"end":40,"loc":{"start":{"line":3,"column":13,"index":35},"end":{"line":3,"column":18,"index":40}}, + "id": { + "type": "Identifier", + "start":35,"end":40,"loc":{"start":{"line":3,"column":13,"index":35},"end":{"line":3,"column":18,"index":40},"identifierName":"using"}, + "name": "using" + }, + "init": null + } + ], + "kind": "using" + }, + "right": { + "type": "Identifier", + "start":44,"end":46,"loc":{"start":{"line":3,"column":22,"index":44},"end":{"line":3,"column":24,"index":46},"identifierName":"of"}, + "name": "of" + }, + "body": { + "type": "EmptyStatement", + "start":47,"end":48,"loc":{"start":{"line":3,"column":25,"index":47},"end":{"line":3,"column":26,"index":48}} + } + } + ], + "directives": [] + } + ], + "directives": [] + } +} diff --git a/packages/babel-plugin-syntax-explicit-resource-management/README.md b/packages/babel-plugin-syntax-explicit-resource-management/README.md new file mode 100644 index 000000000000..cce231fe1ae8 --- /dev/null +++ b/packages/babel-plugin-syntax-explicit-resource-management/README.md @@ -0,0 +1,19 @@ +# @babel/plugin-syntax-explicit-resource-management + +> Allow parsing of the using declarations + +See our website [@babel/plugin-syntax-explicit-resource-management](https://babeljs.io/docs/en/babel-plugin-syntax-explicit-resource-management) for more information. + +## Install + +Using npm: + +```sh +npm install --save-dev @babel/plugin-syntax-explicit-resource-management +``` + +or using yarn: + +```sh +yarn add @babel/plugin-syntax-explicit-resource-management --dev +``` diff --git a/packages/babel-plugin-syntax-explicit-resource-management/package.json b/packages/babel-plugin-syntax-explicit-resource-management/package.json new file mode 100644 index 000000000000..14e52c5327bd --- /dev/null +++ b/packages/babel-plugin-syntax-explicit-resource-management/package.json @@ -0,0 +1,50 @@ +{ + "name": "@babel/plugin-syntax-explicit-resource-management", + "version": "7.18.6", + "description": "Allow parsing of the using declarations", + "repository": { + "type": "git", + "url": "https://github.com/babel/babel.git", + "directory": "packages/babel-plugin-syntax-explicit-resource-management" + }, + "license": "MIT", + "publishConfig": { + "access": "public" + }, + "main": "./lib/index.js", + "keywords": [ + "babel-plugin" + ], + "dependencies": { + "@babel/helper-plugin-utils": "workspace:^" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "devDependencies": { + "@babel/core": "workspace:^" + }, + "engines": { + "node": ">=6.9.0" + }, + "author": "The Babel Team (https://babel.dev/team)", + "conditions": { + "BABEL_8_BREAKING": [ + null, + { + "exports": null + } + ], + "USE_ESM": [ + { + "type": "module" + }, + null + ] + }, + "exports": { + ".": "./lib/index.js", + "./package.json": "./package.json" + }, + "type": "commonjs" +} diff --git a/packages/babel-plugin-syntax-explicit-resource-management/src/index.ts b/packages/babel-plugin-syntax-explicit-resource-management/src/index.ts new file mode 100644 index 000000000000..f5eed49556c9 --- /dev/null +++ b/packages/babel-plugin-syntax-explicit-resource-management/src/index.ts @@ -0,0 +1,13 @@ +import { declare } from "@babel/helper-plugin-utils"; + +export default declare(api => { + api.assertVersion(7); + + return { + name: "syntax-explicit-resource-management", + + manipulateOptions(opts, parserOpts) { + parserOpts.plugins.push("explicitResourceManagement"); + }, + }; +}); diff --git a/packages/babel-plugin-transform-block-scoping/src/index.ts b/packages/babel-plugin-transform-block-scoping/src/index.ts index 84bd0ce3ad89..b368a547daf9 100644 --- a/packages/babel-plugin-transform-block-scoping/src/index.ts +++ b/packages/babel-plugin-transform-block-scoping/src/index.ts @@ -132,7 +132,10 @@ function isBlockScoped(node: t.Node): node is t.VariableDeclaration { return true; } - if (node.kind !== "let" && node.kind !== "const") return false; + if (node.kind !== "let" && node.kind !== "const" && node.kind !== "using") { + return false; + } + return true; } diff --git a/packages/babel-plugin-transform-destructuring/src/util.ts b/packages/babel-plugin-transform-destructuring/src/util.ts index 166f7f830c70..c52cc6ffe54d 100644 --- a/packages/babel-plugin-transform-destructuring/src/util.ts +++ b/packages/babel-plugin-transform-destructuring/src/util.ts @@ -148,7 +148,7 @@ export class DestructuringTransformer { } else { let nodeInit: t.Expression; - if (this.kind === "const" && init === null) { + if ((this.kind === "const" || this.kind === "using") && init === null) { nodeInit = this.scope.buildUndefinedNode(); } else { nodeInit = t.cloneNode(init); @@ -231,7 +231,11 @@ export class DestructuringTransformer { let patternId; let node; - if (this.kind === "const" || this.kind === "let") { + if ( + this.kind === "const" || + this.kind === "let" || + this.kind === "using" + ) { patternId = this.scope.generateUidIdentifier(tempId.name); node = this.buildVariableDeclaration(patternId, tempConditional); } else { diff --git a/packages/babel-standalone/package.json b/packages/babel-standalone/package.json index 41f119faf666..5b977f1ac0e7 100644 --- a/packages/babel-standalone/package.json +++ b/packages/babel-standalone/package.json @@ -42,6 +42,7 @@ "@babel/plugin-syntax-decorators": "workspace:^", "@babel/plugin-syntax-destructuring-private": "workspace:^", "@babel/plugin-syntax-do-expressions": "workspace:^", + "@babel/plugin-syntax-explicit-resource-management": "workspace:^", "@babel/plugin-syntax-export-default-from": "workspace:^", "@babel/plugin-syntax-flow": "workspace:^", "@babel/plugin-syntax-function-bind": "workspace:^", diff --git a/packages/babel-standalone/scripts/pluginConfig.json b/packages/babel-standalone/scripts/pluginConfig.json index 8ea84da6e37d..69bd8216b3a8 100644 --- a/packages/babel-standalone/scripts/pluginConfig.json +++ b/packages/babel-standalone/scripts/pluginConfig.json @@ -24,6 +24,7 @@ "syntax-decorators", "syntax-destructuring-private", "syntax-do-expressions", + "syntax-explicit-resource-management", "syntax-export-default-from", "syntax-flow", "syntax-function-bind", diff --git a/packages/babel-standalone/src/generated/plugins.ts b/packages/babel-standalone/src/generated/plugins.ts index 977eee8a7892..8ee4964afd94 100644 --- a/packages/babel-standalone/src/generated/plugins.ts +++ b/packages/babel-standalone/src/generated/plugins.ts @@ -8,6 +8,7 @@ import syntaxDecimal from "@babel/plugin-syntax-decimal"; import syntaxDecorators from "@babel/plugin-syntax-decorators"; import syntaxDestructuringPrivate from "@babel/plugin-syntax-destructuring-private"; import syntaxDoExpressions from "@babel/plugin-syntax-do-expressions"; +import syntaxExplicitResourceManagement from "@babel/plugin-syntax-explicit-resource-management"; import syntaxExportDefaultFrom from "@babel/plugin-syntax-export-default-from"; import syntaxFlow from "@babel/plugin-syntax-flow"; import syntaxFunctionBind from "@babel/plugin-syntax-function-bind"; @@ -108,6 +109,7 @@ export { syntaxDecorators, syntaxDestructuringPrivate, syntaxDoExpressions, + syntaxExplicitResourceManagement, syntaxExportDefaultFrom, syntaxFlow, syntaxFunctionBind, @@ -209,6 +211,7 @@ export const all: { [k: string]: any } = { "syntax-decorators": syntaxDecorators, "syntax-destructuring-private": syntaxDestructuringPrivate, "syntax-do-expressions": syntaxDoExpressions, + "syntax-explicit-resource-management": syntaxExplicitResourceManagement, "syntax-export-default-from": syntaxExportDefaultFrom, "syntax-flow": syntaxFlow, "syntax-function-bind": syntaxFunctionBind, diff --git a/packages/babel-standalone/src/preset-stage-2.ts b/packages/babel-standalone/src/preset-stage-2.ts index c38a0d2f7991..9d7d7db89989 100644 --- a/packages/babel-standalone/src/preset-stage-2.ts +++ b/packages/babel-standalone/src/preset-stage-2.ts @@ -34,6 +34,7 @@ export default (_: any, opts: any = {}) => { babelPlugins.proposalRecordAndTuple, { syntaxType: recordAndTupleSyntax }, ], + babelPlugins.syntaxExplicitResourceManagement, babelPlugins.syntaxModuleBlocks, ], }; diff --git a/packages/babel-traverse/src/scope/binding.ts b/packages/babel-traverse/src/scope/binding.ts index 5813b6c58cb0..78b2b576f7ff 100644 --- a/packages/babel-traverse/src/scope/binding.ts +++ b/packages/babel-traverse/src/scope/binding.ts @@ -5,7 +5,7 @@ import type Scope from "./index"; export type BindingKind = | "var" /* var declarator */ | "let" /* let declarator, class declaration id, catch clause parameters */ - | "const" /* const declarator */ + | "const" /* const/using declarator */ | "module" /* import specifiers */ | "hoisted" /* function declaration id */ | "param" /* function declaration parameters */ diff --git a/packages/babel-traverse/src/scope/index.ts b/packages/babel-traverse/src/scope/index.ts index 9c1febb0de4e..b858d452462e 100644 --- a/packages/babel-traverse/src/scope/index.ts +++ b/packages/babel-traverse/src/scope/index.ts @@ -725,8 +725,9 @@ export default class Scope { this.registerBinding("hoisted", path.get("id"), path); } else if (path.isVariableDeclaration()) { const declarations = path.get("declarations"); + const { kind } = path.node; for (const declar of declarations) { - this.registerBinding(path.node.kind, declar); + this.registerBinding(kind === "using" ? "const" : kind, declar); } } else if (path.isClassDeclaration()) { if (path.node.declare) return; diff --git a/packages/babel-traverse/test/__snapshots__/scope.js.snap b/packages/babel-traverse/test/__snapshots__/scope.js.snap index 2009e74ea47d..3e2298bf4e24 100644 --- a/packages/babel-traverse/test/__snapshots__/scope.js.snap +++ b/packages/babel-traverse/test/__snapshots__/scope.js.snap @@ -4,6 +4,8 @@ exports[`scope duplicate bindings catch const 1`] = `"Duplicate declaration \\"e exports[`scope duplicate bindings catch let 1`] = `"Duplicate declaration \\"e\\""`; +exports[`scope duplicate bindings catch using 1`] = `"Duplicate declaration \\"e\\""`; + exports[`scope duplicate bindings global class/class should fail 1`] = `"Duplicate declaration \\"foo\\""`; exports[`scope duplicate bindings global class/const should fail 1`] = `"Duplicate declaration \\"foo\\""`; diff --git a/packages/babel-traverse/test/scope.js b/packages/babel-traverse/test/scope.js index 96900a1aca54..612e7046b3d4 100644 --- a/packages/babel-traverse/test/scope.js +++ b/packages/babel-traverse/test/scope.js @@ -662,6 +662,12 @@ describe("scope", () => { expect(() => getPath(ast)).toThrowErrorMatchingSnapshot(); }); + it("using", () => { + const ast = createTryCatch("using"); + + expect(() => getPath(ast)).toThrowErrorMatchingSnapshot(); + }); + it("var", () => { const ast = createTryCatch("var"); diff --git a/packages/babel-types/src/ast-types/generated/index.ts b/packages/babel-types/src/ast-types/generated/index.ts index 9975a9536fb9..58df226948fe 100644 --- a/packages/babel-types/src/ast-types/generated/index.ts +++ b/packages/babel-types/src/ast-types/generated/index.ts @@ -687,7 +687,7 @@ export interface UpdateExpression extends BaseNode { export interface VariableDeclaration extends BaseNode { type: "VariableDeclaration"; - kind: "var" | "let" | "const"; + kind: "var" | "let" | "const" | "using"; declarations: Array; declare?: boolean | null; } diff --git a/packages/babel-types/src/builders/generated/index.ts b/packages/babel-types/src/builders/generated/index.ts index acfef5336e0b..5a7dffdc69b5 100644 --- a/packages/babel-types/src/builders/generated/index.ts +++ b/packages/babel-types/src/builders/generated/index.ts @@ -508,7 +508,7 @@ export function updateExpression( }); } export function variableDeclaration( - kind: "var" | "let" | "const", + kind: "var" | "let" | "const" | "using", declarations: Array, ): t.VariableDeclaration { return validateNode({ diff --git a/packages/babel-types/src/definitions/core.ts b/packages/babel-types/src/definitions/core.ts index 2cc13e9ed197..67cd39ba666b 100644 --- a/packages/babel-types/src/definitions/core.ts +++ b/packages/babel-types/src/definitions/core.ts @@ -1150,7 +1150,13 @@ defineType("VariableDeclaration", { optional: true, }, kind: { - validate: assertOneOf("var", "let", "const"), + validate: assertOneOf( + "var", + "let", + "const", + // https://github.com/tc39/proposal-explicit-resource-management + "using", + ), }, declarations: { validate: chain( diff --git a/yarn.lock b/yarn.lock index 11591d64e309..76c6461c9b63 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1908,6 +1908,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-explicit-resource-management@workspace:^, @babel/plugin-syntax-explicit-resource-management@workspace:packages/babel-plugin-syntax-explicit-resource-management": + version: 0.0.0-use.local + resolution: "@babel/plugin-syntax-explicit-resource-management@workspace:packages/babel-plugin-syntax-explicit-resource-management" + dependencies: + "@babel/core": "workspace:^" + "@babel/helper-plugin-utils": "workspace:^" + peerDependencies: + "@babel/core": ^7.0.0-0 + languageName: unknown + linkType: soft + "@babel/plugin-syntax-export-default-from@workspace:^, @babel/plugin-syntax-export-default-from@workspace:packages/babel-plugin-syntax-export-default-from": version: 0.0.0-use.local resolution: "@babel/plugin-syntax-export-default-from@workspace:packages/babel-plugin-syntax-export-default-from" @@ -3647,6 +3658,7 @@ __metadata: "@babel/plugin-syntax-decorators": "workspace:^" "@babel/plugin-syntax-destructuring-private": "workspace:^" "@babel/plugin-syntax-do-expressions": "workspace:^" + "@babel/plugin-syntax-explicit-resource-management": "workspace:^" "@babel/plugin-syntax-export-default-from": "workspace:^" "@babel/plugin-syntax-flow": "workspace:^" "@babel/plugin-syntax-function-bind": "workspace:^"