diff --git a/packages/babel-parser/src/parse-error/standard-errors.ts b/packages/babel-parser/src/parse-error/standard-errors.ts index 034db87f20ac..8221a6a53d4f 100644 --- a/packages/babel-parser/src/parse-error/standard-errors.ts +++ b/packages/babel-parser/src/parse-error/standard-errors.ts @@ -14,6 +14,7 @@ export type LValAncestor = | "ImportSpecifier" | "ImportNamespaceSpecifier" | "ImportDefaultSpecifier" + | "ParenthesizedExpression" | "ObjectPattern" | "RestElement" | "VariableDeclarator"; @@ -32,6 +33,8 @@ export default { "Can not use 'await' as identifier inside a static block.", AwaitExpressionFormalParameter: "'await' is not allowed in async function parameters.", + AwaitInUsingBinding: + "'await' is not allowed to be used as a name in 'using' declarations.", AwaitNotInAsyncContext: "'await' is only allowed within async functions and at the top levels of modules.", AwaitNotInAsyncFunction: "'await' is only allowed within async functions.", diff --git a/packages/babel-parser/src/parser/lval.ts b/packages/babel-parser/src/parser/lval.ts index 990eee1e0e05..d1df5f9daa88 100644 --- a/packages/babel-parser/src/parser/lval.ts +++ b/packages/babel-parser/src/parser/lval.ts @@ -29,7 +29,7 @@ import { NodeUtils, type Undone } from "./node"; import { type BindingTypes, BIND_NONE, - BIND_SCOPE_LEXICAL, + BIND_FLAGS_NO_LET_IN_LEXICAL, } from "../util/scopeflags"; import type { ExpressionErrors } from "./util"; import { Errors, type LValAncestor } from "../parse-error"; @@ -560,10 +560,6 @@ export default abstract class LValParser extends NodeUtils { * `checkLVal` will add checked identifier name to `checkClashes` It is * used in tracking duplicates in function parameter lists. If it is * false, `checkLVal` will skip duplicate checks - * @param options.allowingSloppyLetBinding - * Whether an identifier named "let" should be allowed in sloppy mode. - * Defaults to `true` unless lexical scope its being used. This property - * is only relevant if the parser's state is in sloppy mode. * @param options.strictModeChanged * Whether an identifier has been parsed in a sloppy context but should * be reinterpreted as strict-mode. e.g. `(arguments) => { "use strict "}` @@ -579,14 +575,12 @@ export default abstract class LValParser extends NodeUtils { binding = BIND_NONE, checkClashes = false, strictModeChanged = false, - allowingSloppyLetBinding = !(binding & BIND_SCOPE_LEXICAL), hasParenthesizedAncestor = false, }: { in: LValAncestor; binding?: BindingTypes; checkClashes?: Set | false; strictModeChanged?: boolean; - allowingSloppyLetBinding?: boolean; hasParenthesizedAncestor?: boolean; }, ): void { @@ -604,12 +598,11 @@ export default abstract class LValParser extends NodeUtils { return; } - if (expression.type === "Identifier") { + if (type === "Identifier") { this.checkIdentifier( expression as Identifier, binding, strictModeChanged, - allowingSloppyLetBinding, ); const { name } = expression as Identifier; @@ -626,7 +619,7 @@ export default abstract class LValParser extends NodeUtils { } const validity = this.isValidLVal( - expression.type, + type, !(hasParenthesizedAncestor || expression.extra?.parenthesized) && ancestor.type === "AssignmentExpression", binding, @@ -637,13 +630,7 @@ export default abstract class LValParser extends NodeUtils { const ParseErrorClass = binding === BIND_NONE ? Errors.InvalidLhs : Errors.InvalidLhsBinding; - this.raise(ParseErrorClass, { - at: expression, - ancestor: - ancestor.type === "UpdateExpression" - ? { type: "UpdateExpression", prefix: ancestor.prefix } - : { type: ancestor.type }, - }); + this.raise(ParseErrorClass, { at: expression, ancestor }); return; } @@ -651,21 +638,19 @@ export default abstract class LValParser extends NodeUtils { ? validity : [validity, type === "ParenthesizedExpression"]; const nextAncestor = - expression.type === "ArrayPattern" || - expression.type === "ObjectPattern" || - expression.type === "ParenthesizedExpression" - ? expression + type === "ArrayPattern" || + type === "ObjectPattern" || + type === "ParenthesizedExpression" + ? ({ type } as const) : ancestor; // @ts-expect-error key may not index expression. for (const child of [].concat(expression[key])) { if (child) { this.checkLVal(child, { - // @ts-expect-error: refine types in: nextAncestor, binding, checkClashes, - allowingSloppyLetBinding, strictModeChanged, hasParenthesizedAncestor: isParenthesizedExpression, }); @@ -677,7 +662,6 @@ export default abstract class LValParser extends NodeUtils { at: Identifier, bindingType: BindingTypes, strictModeChanged: boolean = false, - allowLetBinding: boolean = !(bindingType & BIND_SCOPE_LEXICAL), ) { if ( this.state.strict && @@ -695,7 +679,7 @@ export default abstract class LValParser extends NodeUtils { } } - if (!allowLetBinding && at.name === "let") { + if (bindingType & BIND_FLAGS_NO_LET_IN_LEXICAL && at.name === "let") { this.raise(Errors.LetInLexicalBinding, { at }); } diff --git a/packages/babel-parser/src/parser/statement.ts b/packages/babel-parser/src/parser/statement.ts index 8b95366f08a4..d70623b0a70b 100644 --- a/packages/babel-parser/src/parser/statement.ts +++ b/packages/babel-parser/src/parser/statement.ts @@ -29,6 +29,7 @@ import { CLASS_ELEMENT_STATIC_GETTER, CLASS_ELEMENT_STATIC_SETTER, type BindingTypes, + BIND_CATCH_PARAM, } from "../util/scopeflags"; import { ExpressionErrors } from "./util"; import { PARAM, functionFlags } from "../util/production-parameter"; @@ -470,7 +471,7 @@ export default abstract class StatementParser extends ExpressionParser { return this.parseTryStatement(node as Undone); case tt._using: - // using [no LineTerminator here] BindingList[+Using] + // using [no LineTerminator here][lookahead != `await`] BindingList[+Using] if ( this.hasFollowingLineBreak() || this.state.containsEsc || @@ -1076,8 +1077,7 @@ export default abstract class StatementParser extends ExpressionParser { this.scope.enter(simple ? SCOPE_SIMPLE_CATCH : 0); this.checkLVal(param, { in: { type: "CatchClause" }, - binding: BIND_LEXICAL, - allowingSloppyLetBinding: true, + binding: BIND_CATCH_PARAM, }); return param; @@ -1507,6 +1507,11 @@ export default abstract class StatementParser extends ExpressionParser { decl: Undone, kind: "var" | "let" | "const" | "using", ): void { + // Unlike "let" which must be handled in checkLVal, it suffices to check + // await here because `using` must not precede binding patterns. + if (kind === "using" && !this.inModule && this.match(tt._await)) { + this.raise(Errors.AwaitInUsingBinding, { at: this.state.startLoc }); + } const id = this.parseBindingAtom(); this.checkLVal(id, { in: { type: "VariableDeclarator" }, @@ -2958,8 +2963,7 @@ export default abstract class StatementParser extends ExpressionParser { | N.ImportNamespaceSpecifier, >(specifier: Undone, type: T["type"], bindingType = BIND_LEXICAL) { this.checkLVal(specifier.local, { - // @ts-expect-error refine types - in: specifier, + in: { type }, binding: bindingType, }); return this.finishNode(specifier, type); diff --git a/packages/babel-parser/src/util/scopeflags.ts b/packages/babel-parser/src/util/scopeflags.ts index be4ccdc84eb4..cd4b8f109c12 100644 --- a/packages/babel-parser/src/util/scopeflags.ts +++ b/packages/babel-parser/src/util/scopeflags.ts @@ -26,42 +26,45 @@ export type ScopeFlags = // These flags are meant to be _only_ used inside the Scope class (or subclasses). // prettier-ignore -export const BIND_KIND_VALUE = 0b000000_0000_01, - BIND_KIND_TYPE = 0b000000_0000_10, +export const BIND_KIND_VALUE = 0b0000000_0000_01, + BIND_KIND_TYPE = 0b0000000_0000_10, // Used in checkLVal and declareName to determine the type of a binding - BIND_SCOPE_VAR = 0b000000_0001_00, // Var-style binding - BIND_SCOPE_LEXICAL = 0b000000_0010_00, // Let- or const-style binding - BIND_SCOPE_FUNCTION = 0b000000_0100_00, // Function declaration - BIND_SCOPE_OUTSIDE = 0b000000_1000_00, // Special case for function names as + BIND_SCOPE_VAR = 0b0000000_0001_00, // Var-style binding + BIND_SCOPE_LEXICAL = 0b0000000_0010_00, // Let- or const-style binding + BIND_SCOPE_FUNCTION = 0b0000000_0100_00, // Function declaration + BIND_SCOPE_OUTSIDE = 0b0000000_1000_00, // Special case for function names as // bound inside the function // Misc flags - BIND_FLAGS_NONE = 0b0000001_0000_00, - BIND_FLAGS_CLASS = 0b0000010_0000_00, - BIND_FLAGS_TS_ENUM = 0b0000100_0000_00, - BIND_FLAGS_TS_CONST_ENUM = 0b0001000_0000_00, - BIND_FLAGS_TS_EXPORT_ONLY = 0b0010000_0000_00, - BIND_FLAGS_FLOW_DECLARE_FN = 0b0100000_0000_00, - BIND_FLAGS_TS_IMPORT = 0b1000000_0000_00; + BIND_FLAGS_NONE = 0b00000001_0000_00, + BIND_FLAGS_CLASS = 0b00000010_0000_00, + BIND_FLAGS_TS_ENUM = 0b00000100_0000_00, + BIND_FLAGS_TS_CONST_ENUM = 0b00001000_0000_00, + BIND_FLAGS_TS_EXPORT_ONLY = 0b00010000_0000_00, + BIND_FLAGS_FLOW_DECLARE_FN = 0b00100000_0000_00, + BIND_FLAGS_TS_IMPORT = 0b01000000_0000_00, + // Whether "let" should be allowed in bound names in sloppy mode + BIND_FLAGS_NO_LET_IN_LEXICAL = 0b10000000_0000_00; // These flags are meant to be _only_ used by Scope consumers // prettier-ignore /* = is value? | is type? | scope | misc flags */ -export const BIND_CLASS = BIND_KIND_VALUE | BIND_KIND_TYPE | BIND_SCOPE_LEXICAL | BIND_FLAGS_CLASS , - BIND_LEXICAL = BIND_KIND_VALUE | 0 | BIND_SCOPE_LEXICAL | 0 , +export const BIND_CLASS = BIND_KIND_VALUE | BIND_KIND_TYPE | BIND_SCOPE_LEXICAL | BIND_FLAGS_CLASS|BIND_FLAGS_NO_LET_IN_LEXICAL, + BIND_LEXICAL = BIND_KIND_VALUE | 0 | BIND_SCOPE_LEXICAL | BIND_FLAGS_NO_LET_IN_LEXICAL, + BIND_CATCH_PARAM = BIND_KIND_VALUE | 0 | BIND_SCOPE_LEXICAL | 0 , BIND_VAR = BIND_KIND_VALUE | 0 | BIND_SCOPE_VAR | 0 , BIND_FUNCTION = BIND_KIND_VALUE | 0 | BIND_SCOPE_FUNCTION | 0 , BIND_TS_INTERFACE = 0 | BIND_KIND_TYPE | 0 | BIND_FLAGS_CLASS , BIND_TS_TYPE = 0 | BIND_KIND_TYPE | 0 | 0 , - BIND_TS_ENUM = BIND_KIND_VALUE | BIND_KIND_TYPE | BIND_SCOPE_LEXICAL | BIND_FLAGS_TS_ENUM, + BIND_TS_ENUM = BIND_KIND_VALUE | BIND_KIND_TYPE | BIND_SCOPE_LEXICAL | BIND_FLAGS_TS_ENUM|BIND_FLAGS_NO_LET_IN_LEXICAL, BIND_TS_AMBIENT = 0 | 0 | 0 | BIND_FLAGS_TS_EXPORT_ONLY, // These bindings don't introduce anything in the scope. They are used for assignments and // function expressions IDs. - BIND_NONE = 0 | 0 | 0 | BIND_FLAGS_NONE , - BIND_OUTSIDE = BIND_KIND_VALUE | 0 | 0 | BIND_FLAGS_NONE , + BIND_NONE = 0 | 0 | 0 | BIND_FLAGS_NONE , + BIND_OUTSIDE = BIND_KIND_VALUE | 0 | 0 | BIND_FLAGS_NONE , - BIND_TS_CONST_ENUM = BIND_TS_ENUM | BIND_FLAGS_TS_CONST_ENUM , + BIND_TS_CONST_ENUM = BIND_TS_ENUM | BIND_FLAGS_TS_CONST_ENUM , BIND_TS_NAMESPACE = 0 | 0 | 0 | BIND_FLAGS_TS_EXPORT_ONLY, - BIND_TS_TYPE_IMPORT= 0 | BIND_KIND_TYPE | 0 | BIND_FLAGS_TS_IMPORT, + BIND_TS_TYPE_IMPORT= 0 | BIND_KIND_TYPE | 0 | BIND_FLAGS_TS_IMPORT , BIND_FLOW_DECLARE_FN = BIND_FLAGS_FLOW_DECLARE_FN; diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-module/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-module/input.js new file mode 100644 index 000000000000..9eb1bacb90b0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-module/input.js @@ -0,0 +1,12 @@ +{ + using await = h(); +} +{ + using \u0061wait = h(); +} +{ + using x, await = h(); +} +{ + for (using await of []); +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-module/options.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-module/options.json new file mode 100644 index 000000000000..2104ca43283f --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-module/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "module" +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-module/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-module/output.json new file mode 100644 index 000000000000..65286858f703 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-module/output.json @@ -0,0 +1,166 @@ +{ + "type": "File", + "start":0,"end":113,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":12,"column":1,"index":113}}, + "errors": [ + "SyntaxError: Can not use 'await' as identifier inside an async function. (2:8)", + "SyntaxError: Can not use 'await' as identifier inside an async function. (5:8)", + "SyntaxError: Can not use 'await' as identifier inside an async function. (8:11)", + "SyntaxError: Can not use 'await' as identifier inside an async function. (11:13)" + ], + "program": { + "type": "Program", + "start":0,"end":113,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":12,"column":1,"index":113}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "BlockStatement", + "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":24}}, + "body": [ + { + "type": "VariableDeclaration", + "start":4,"end":22,"loc":{"start":{"line":2,"column":2,"index":4},"end":{"line":2,"column":20,"index":22}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":10,"end":21,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":19,"index":21}}, + "id": { + "type": "Identifier", + "start":10,"end":15,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":13,"index":15},"identifierName":"await"}, + "name": "await" + }, + "init": { + "type": "CallExpression", + "start":18,"end":21,"loc":{"start":{"line":2,"column":16,"index":18},"end":{"line":2,"column":19,"index":21}}, + "callee": { + "type": "Identifier", + "start":18,"end":19,"loc":{"start":{"line":2,"column":16,"index":18},"end":{"line":2,"column":17,"index":19},"identifierName":"h"}, + "name": "h" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + }, + { + "type": "BlockStatement", + "start":25,"end":54,"loc":{"start":{"line":4,"column":0,"index":25},"end":{"line":6,"column":1,"index":54}}, + "body": [ + { + "type": "VariableDeclaration", + "start":29,"end":52,"loc":{"start":{"line":5,"column":2,"index":29},"end":{"line":5,"column":25,"index":52}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":35,"end":51,"loc":{"start":{"line":5,"column":8,"index":35},"end":{"line":5,"column":24,"index":51}}, + "id": { + "type": "Identifier", + "start":35,"end":45,"loc":{"start":{"line":5,"column":8,"index":35},"end":{"line":5,"column":18,"index":45},"identifierName":"await"}, + "name": "await" + }, + "init": { + "type": "CallExpression", + "start":48,"end":51,"loc":{"start":{"line":5,"column":21,"index":48},"end":{"line":5,"column":24,"index":51}}, + "callee": { + "type": "Identifier", + "start":48,"end":49,"loc":{"start":{"line":5,"column":21,"index":48},"end":{"line":5,"column":22,"index":49},"identifierName":"h"}, + "name": "h" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + }, + { + "type": "BlockStatement", + "start":55,"end":82,"loc":{"start":{"line":7,"column":0,"index":55},"end":{"line":9,"column":1,"index":82}}, + "body": [ + { + "type": "VariableDeclaration", + "start":59,"end":80,"loc":{"start":{"line":8,"column":2,"index":59},"end":{"line":8,"column":23,"index":80}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":65,"end":66,"loc":{"start":{"line":8,"column":8,"index":65},"end":{"line":8,"column":9,"index":66}}, + "id": { + "type": "Identifier", + "start":65,"end":66,"loc":{"start":{"line":8,"column":8,"index":65},"end":{"line":8,"column":9,"index":66},"identifierName":"x"}, + "name": "x" + }, + "init": null + }, + { + "type": "VariableDeclarator", + "start":68,"end":79,"loc":{"start":{"line":8,"column":11,"index":68},"end":{"line":8,"column":22,"index":79}}, + "id": { + "type": "Identifier", + "start":68,"end":73,"loc":{"start":{"line":8,"column":11,"index":68},"end":{"line":8,"column":16,"index":73},"identifierName":"await"}, + "name": "await" + }, + "init": { + "type": "CallExpression", + "start":76,"end":79,"loc":{"start":{"line":8,"column":19,"index":76},"end":{"line":8,"column":22,"index":79}}, + "callee": { + "type": "Identifier", + "start":76,"end":77,"loc":{"start":{"line":8,"column":19,"index":76},"end":{"line":8,"column":20,"index":77},"identifierName":"h"}, + "name": "h" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + }, + { + "type": "BlockStatement", + "start":83,"end":113,"loc":{"start":{"line":10,"column":0,"index":83},"end":{"line":12,"column":1,"index":113}}, + "body": [ + { + "type": "ForOfStatement", + "start":87,"end":111,"loc":{"start":{"line":11,"column":2,"index":87},"end":{"line":11,"column":26,"index":111}}, + "await": false, + "left": { + "type": "VariableDeclaration", + "start":92,"end":103,"loc":{"start":{"line":11,"column":7,"index":92},"end":{"line":11,"column":18,"index":103}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":98,"end":103,"loc":{"start":{"line":11,"column":13,"index":98},"end":{"line":11,"column":18,"index":103}}, + "id": { + "type": "Identifier", + "start":98,"end":103,"loc":{"start":{"line":11,"column":13,"index":98},"end":{"line":11,"column":18,"index":103},"identifierName":"await"}, + "name": "await" + }, + "init": null + } + ], + "kind": "using" + }, + "right": { + "type": "ArrayExpression", + "start":107,"end":109,"loc":{"start":{"line":11,"column":22,"index":107},"end":{"line":11,"column":24,"index":109}}, + "elements": [] + }, + "body": { + "type": "EmptyStatement", + "start":110,"end":111,"loc":{"start":{"line":11,"column":25,"index":110},"end":{"line":11,"column":26,"index":111}} + } + } + ], + "directives": [] + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-script/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-script/input.js new file mode 100644 index 000000000000..9eb1bacb90b0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-script/input.js @@ -0,0 +1,12 @@ +{ + using await = h(); +} +{ + using \u0061wait = h(); +} +{ + using x, await = h(); +} +{ + for (using await of []); +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-script/options.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-script/options.json new file mode 100644 index 000000000000..b412ffe6712f --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-script/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "script" +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-script/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-script/output.json new file mode 100644 index 000000000000..5f57e6c4814c --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await-script/output.json @@ -0,0 +1,166 @@ +{ + "type": "File", + "start":0,"end":113,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":12,"column":1,"index":113}}, + "errors": [ + "SyntaxError: 'await' is not allowed to be used as a name in 'using' declarations. (2:8)", + "SyntaxError: 'await' is not allowed to be used as a name in 'using' declarations. (5:8)", + "SyntaxError: 'await' is not allowed to be used as a name in 'using' declarations. (8:11)", + "SyntaxError: 'await' is not allowed to be used as a name in 'using' declarations. (11:13)" + ], + "program": { + "type": "Program", + "start":0,"end":113,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":12,"column":1,"index":113}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "BlockStatement", + "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":24}}, + "body": [ + { + "type": "VariableDeclaration", + "start":4,"end":22,"loc":{"start":{"line":2,"column":2,"index":4},"end":{"line":2,"column":20,"index":22}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":10,"end":21,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":19,"index":21}}, + "id": { + "type": "Identifier", + "start":10,"end":15,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":13,"index":15},"identifierName":"await"}, + "name": "await" + }, + "init": { + "type": "CallExpression", + "start":18,"end":21,"loc":{"start":{"line":2,"column":16,"index":18},"end":{"line":2,"column":19,"index":21}}, + "callee": { + "type": "Identifier", + "start":18,"end":19,"loc":{"start":{"line":2,"column":16,"index":18},"end":{"line":2,"column":17,"index":19},"identifierName":"h"}, + "name": "h" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + }, + { + "type": "BlockStatement", + "start":25,"end":54,"loc":{"start":{"line":4,"column":0,"index":25},"end":{"line":6,"column":1,"index":54}}, + "body": [ + { + "type": "VariableDeclaration", + "start":29,"end":52,"loc":{"start":{"line":5,"column":2,"index":29},"end":{"line":5,"column":25,"index":52}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":35,"end":51,"loc":{"start":{"line":5,"column":8,"index":35},"end":{"line":5,"column":24,"index":51}}, + "id": { + "type": "Identifier", + "start":35,"end":45,"loc":{"start":{"line":5,"column":8,"index":35},"end":{"line":5,"column":18,"index":45},"identifierName":"await"}, + "name": "await" + }, + "init": { + "type": "CallExpression", + "start":48,"end":51,"loc":{"start":{"line":5,"column":21,"index":48},"end":{"line":5,"column":24,"index":51}}, + "callee": { + "type": "Identifier", + "start":48,"end":49,"loc":{"start":{"line":5,"column":21,"index":48},"end":{"line":5,"column":22,"index":49},"identifierName":"h"}, + "name": "h" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + }, + { + "type": "BlockStatement", + "start":55,"end":82,"loc":{"start":{"line":7,"column":0,"index":55},"end":{"line":9,"column":1,"index":82}}, + "body": [ + { + "type": "VariableDeclaration", + "start":59,"end":80,"loc":{"start":{"line":8,"column":2,"index":59},"end":{"line":8,"column":23,"index":80}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":65,"end":66,"loc":{"start":{"line":8,"column":8,"index":65},"end":{"line":8,"column":9,"index":66}}, + "id": { + "type": "Identifier", + "start":65,"end":66,"loc":{"start":{"line":8,"column":8,"index":65},"end":{"line":8,"column":9,"index":66},"identifierName":"x"}, + "name": "x" + }, + "init": null + }, + { + "type": "VariableDeclarator", + "start":68,"end":79,"loc":{"start":{"line":8,"column":11,"index":68},"end":{"line":8,"column":22,"index":79}}, + "id": { + "type": "Identifier", + "start":68,"end":73,"loc":{"start":{"line":8,"column":11,"index":68},"end":{"line":8,"column":16,"index":73},"identifierName":"await"}, + "name": "await" + }, + "init": { + "type": "CallExpression", + "start":76,"end":79,"loc":{"start":{"line":8,"column":19,"index":76},"end":{"line":8,"column":22,"index":79}}, + "callee": { + "type": "Identifier", + "start":76,"end":77,"loc":{"start":{"line":8,"column":19,"index":76},"end":{"line":8,"column":20,"index":77},"identifierName":"h"}, + "name": "h" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + }, + { + "type": "BlockStatement", + "start":83,"end":113,"loc":{"start":{"line":10,"column":0,"index":83},"end":{"line":12,"column":1,"index":113}}, + "body": [ + { + "type": "ForOfStatement", + "start":87,"end":111,"loc":{"start":{"line":11,"column":2,"index":87},"end":{"line":11,"column":26,"index":111}}, + "await": false, + "left": { + "type": "VariableDeclaration", + "start":92,"end":103,"loc":{"start":{"line":11,"column":7,"index":92},"end":{"line":11,"column":18,"index":103}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":98,"end":103,"loc":{"start":{"line":11,"column":13,"index":98},"end":{"line":11,"column":18,"index":103}}, + "id": { + "type": "Identifier", + "start":98,"end":103,"loc":{"start":{"line":11,"column":13,"index":98},"end":{"line":11,"column":18,"index":103},"identifierName":"await"}, + "name": "await" + }, + "init": null + } + ], + "kind": "using" + }, + "right": { + "type": "ArrayExpression", + "start":107,"end":109,"loc":{"start":{"line":11,"column":22,"index":107},"end":{"line":11,"column":24,"index":109}}, + "elements": [] + }, + "body": { + "type": "EmptyStatement", + "start":110,"end":111,"loc":{"start":{"line":11,"column":25,"index":110},"end":{"line":11,"column":26,"index":111}} + } + } + ], + "directives": [] + } + ], + "directives": [] + } +}