 src/common.ts                                      |   9 +-
 src/errors.ts                                      |  11 +
 src/estree.ts                                      |   2 +-
 src/parser.ts                                      | 475 ++++++++++++++++++++-
 src/token.ts                                       |   9 +-
 .../miscellaneous/__snapshots__/commonjs.ts.snap   |   4 +-
 6 files changed, 502 insertions(+), 8 deletions(-)
+    // UsingDeclaration
+    // using [no LineTerminator here] BindingList
+    case Token.UsingKeyword:
+      return parseUsingDeclarationOrExpressionStatement(parser, context, scope, privateScope, origin, labels);
+    // AwaitUsingDeclaration
+    // await [no LineTerminator here] using [no LineTerminator here] BindingList
+    case Token.AwaitKeyword:
+      if (parser.options.next) {
+        return parseAwaitUsingDeclarationOrExpressionStatement(parser, context, scope, privateScope, origin, labels);
+      }
+      return parseStatement(parser, context, scope, privateScope, origin, labels, 1);
+/**
+ * Parses either a `using` declaration statement or an expression statement
+ * (or labelled statement) starting with `using` as an identifier.
+ *
+ * Because we are not doing any backtracking - this parses `using` as an identifier
+ * first, and decides based on the token following it.
+ *
+ * @param parser  Parser object
+ * @param context Context masks
+ * @param scope Scope object
+ * @param origin Binding origin
+ * @param labels Labels object
+ */
+function parseUsingDeclarationOrExpressionStatement(
+  parser: Parser,
+  context: Context,
+  scope: Scope | undefined,
+  privateScope: PrivateScope | undefined,
+  origin: Origin,
+  labels: ESTree.Labels,
+): ESTree.VariableDeclaration | ESTree.LabeledStatement | ESTree.ExpressionStatement {
+  // UsingDeclaration ::
+  //   using [no LineTerminator here] [lookahead ∉ { await }] BindingList ;
+  const { tokenValue, tokenStart } = parser;
+  const token = parser.getToken();
+
+  let expr: ESTree.Identifier | ESTree.Expression = parseIdentifier(parser, context | Context.TaggedTemplate);
+
+  if (parser.options.next && (parser.flags & Flags.NewLine) === 0) {
+    const followingToken = parser.getToken();
+    const isDeclaration =
+      (followingToken & Token.IsIdentifier) === Token.IsIdentifier && followingToken !== Token.AwaitKeyword;
+    const isDestructuring = (followingToken & Token.IsPatternStart) === Token.IsPatternStart;
+
+    if (isDeclaration || isDestructuring) {
+      /* UsingDeclarations are not allowed at the top level of a Script */
+      if (origin & Origin.TopLevel && context & Context.InGlobal && (context & Context.Module) === 0) {
+        parser.report(Errors.UsingDeclarationInGlobalScope, 'using');
+      }
+
+      if (isDestructuring) parser.report(Errors.UsingDeclarationNoDestructuring, 'using');
+
+      const declarations = parseVariableDeclarationList(
+        parser,
+        context,
+        scope,
+        privateScope,
+        BindingKind.Using,
+        Origin.None,
