You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: js_parser_lower.go
    path of file: ./repos/esbuild/internal/js_parser
    
    the code of the file until where you have to start completion: // This file contains code for "lowering" syntax, which means converting it to
// older JavaScript. For example, "a ** b" becomes a call to "Math.pow(a, b)"
// when lowered. Which syntax is lowered is determined by the language target.

package js_parser

import (
	"fmt"

	"github.com/evanw/esbuild/internal/ast"
	"github.com/evanw/esbuild/internal/compat"
	"github.com/evanw/esbuild/internal/config"
	"github.com/evanw/esbuild/internal/helpers"
	"github.com/evanw/esbuild/internal/js_ast"
	"github.com/evanw/esbuild/internal/logger"
)

func (p *parser) markSyntaxFeature(feature compat.JSFeature, r logger.Range) (didGenerateError bool) {
	didGenerateError = true

	if !p.options.unsupportedJSFeatures.Has(feature) {
		if feature == compat.TopLevelAwait && !p.options.outputFormat.KeepESMImportExportSyntax() {
			p.log.AddError(&p.tracker, r, fmt.Sprintf(
				"Top-level await is currently not supported with the %q output format", p.options.outputFormat.String()))
			return
		}

		didGenerateError = false
		return
	}

	var name string
	where := config.PrettyPrintTargetEnvironment(p.options.originalTargetEnv, p.options.unsupportedJSFeatureOverridesMask)

	switch feature {
	case compat.DefaultArgument:
		name = "default arguments"

	case compat.RestArgument:
		name = "rest arguments"

	case compat.ArraySpread:
		name = "array spread"

	case compat.ForOf:
		name = "for-of loops"

	case compat.ObjectAccessors:
		name = "object accessors"

	case compat.ObjectExtensions:
		name = "object literal extensions"

	case compat.Destructuring:
		name = "destructuring"

	case compat.NewTarget:
		name = "new.target"

	case compat.ConstAndLet:
		name = p.source.TextForRange(r)

	case compat.Class:
		name = "class syntax"

	case compat.Generator:
		name = "generator functions"

	case compat.AsyncAwait:
		name = "async functions"

	case compat.AsyncGenerator:
		name = "async generator functions"

	case compat.ForAwait:
		name = "for-await loops"

	case compat.NestedRestBinding:
		name = "non-identifier array rest patterns"

	case compat.Decorators:
		name = "JavaScript decorators"

	case compat.ImportAttributes:
		p.log.AddError(&p.tracker, r, fmt.Sprintf(
			"Using an arbitrary value as the second argument to \"import()\" is not possible in %s", where))
		return

	case compat.TopLevelAwait:
		p.log.AddError(&p.tracker, r, fmt.Sprintf(
			"Top-level await is not available in %s", where))
		return

	case compat.ArbitraryModuleNamespaceNames:
		p.log.AddError(&p.tracker, r, fmt.Spri
    
func (p *parser) lowerForAwaitLoop(loc logger.Loc, loop *js_ast.SForOf, stmts []js_ast.Stmt) []js_ast.Stmt {
	// This code:
	//
	//   for await (let x of y) z()
	//
	// is transformed into the following code:
	//
	//   try {
	//     for (var iter = __forAwait(y), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
	//       let x = temp.value;
	//       z();
	//     }
	//   } catch (temp) {
	//     error = [temp]
	//   } finally {
	//     try {
	//       more && (temp = iter.return) && (await temp.call(iter))
	//     } finally {
	//       if (error) throw error[0]
	//     }
	//   }
	//
	// except that "yield" is used instead of "await" if await is unsupported.
	// This mostly follows TypeScript's implementation of the syntax transform.

	iterRef := p.generateTempRef(tempRefNoDeclare, "iter")
	moreRef := p.generateTempRef(tempRefNoDeclare, "more")
	tempRef := p.generateTempRef(tempRefNoDeclare, "temp")
	errorRef := p.generateTempRef(tempRefNoDeclare, "error")

	switch init := loop.Init.Data.(type) {
	case *js_ast.SLocal:
		if len(init.Decls) == 1 {
			init.Decls[0].ValueOrNil = js_ast.Expr{Loc: loc, Data: &js_ast.EDot{
				Target:  js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{Ref: tempRef}},
				NameLoc: loc,
				Name:    "value",
			}}
		}
	case *js_ast.SExpr:
		init.Value.Data = &js_ast.EBinary{
			Op:   js_ast.BinOpAssign,
			Left: init.Value,
			Right: js_ast.Expr{Loc: loc, Data: &js_ast.EDot{
				Target:  js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{Ref: tempRef}},
				NameLoc: loc,
				Name:    "value",
			}},
		}
	}

	var body []js_ast.Stmt
	var closeBraceLoc logger.Loc
	body = append(body, loop.Init)

	if block, ok := loop.Body.Data.(*js_ast.SBlock); ok {
		body = append(body, block.Stmts...)
		closeBraceLoc = block.CloseBraceLoc
	} else {
		body = append(body, loop.Body)
	}

	awaitIterNext := js_ast.Expr{Loc: loc, Data: &js_ast.ECall{
		Target: js_ast.Expr{Loc: loc, Data: &js_ast.EDot{
			Target:  js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{Ref: iterRef}},
			NameLoc: loc,
			Name:    "next",
		}},
		Kind: js_ast.TargetWasOriginallyPropertyAccess,
	}}
	awaitTempCallIter := js_ast.Expr{Loc: loc, Data: &js_ast.ECall{
		Target: js_ast.Expr{Loc: loc, Data: &js_ast.EDot{
			Target:  js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{Ref: tempRef}},
			NameLoc: loc,
			Name:    "call",
		}},
		Args: []js_ast.Expr{{Loc: loc, Data: &js_ast.EIdentifier{Ref: iterRef}}},
		Kind: js_ast.TargetWasOriginallyPropertyAccess,
	}}

	// "await" expressions turn into "yield" expressions when lowering
	awaitIterNext = p.maybeLowerAwait(awaitIterNext.Loc, &js_ast.EAwait{Value: awaitIterNext})
	awaitTempCallIter = p.maybeLowerAwait(awaitTempCallIter.Loc, &js_ast.EAwait{Value: awaitTempCallIter})

	return append(stmts, js_ast.Stmt{Loc: loc, Data: &js_ast.STry{
		BlockLoc: loc,
		Block: js_ast.SBlock{
			Stmts: []js_ast.Stmt{{Loc: loc, Data: &js_ast.SFor{
				InitOrNil: js_ast.Stmt{Loc: loc, Data: &js_ast.SLocal{Kind: js_ast.LocalVar, Decls: []js_ast.Decl{
					{Binding: js_ast.Binding{Loc: loc, Data: &js_ast.BIdentifier{Ref: iterRef}},
						ValueOrNil: p.callRuntime(loc, "__forAwait", []js_ast.Expr{loop.Value})},
					{Binding: js_ast.Binding{Loc: loc, Data: &js_ast.BIdentifier{Ref: moreRef}}},
					{Binding: js_ast.Binding{Loc: loc, Data: &js_ast.BIdentifier{Ref: tempRef}}},
					{Binding: js_ast.Binding{Loc: loc, Data: &js_ast.BIdentifier{Ref: errorRef}}},
				}}},
				TestOrNil: js_ast.Expr{Loc: loc, Data: &js_ast.EBinary{
					Op:   js_ast.BinOpAssign,
					Left: js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{Ref: moreRef}},
					Right: js_ast.Expr{Loc: loc, Data: &js_ast.EUnary{
						Op: js_ast.UnOpNot,
						Value: js_ast.Expr{Loc: loc, Data: &js_ast.EDot{
							Target: js_ast.Expr{Loc: loc, Data: &js_ast.EBinary{
								Op:    js_ast.BinOpAssign,
								Left:  js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{Ref: tempRef}},
								Right: awaitIterNext,
							}},
							NameLoc: loc,
							Name:    "done",
						}},
					}},
				}},
				UpdateOrNil: js_ast.Expr{Loc: loc, Data: &js_ast.EBinary{
					Op:    js_ast.BinOpAssign,
					Left:  js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{Ref: moreRef}},
					Right: js_ast.Expr{Loc: loc, Data: &js_ast.EBoolean{Value: false}},
				}},
				Body: js_ast.Stmt{Loc: loop.Body.Loc, Data: &js_ast.SBlock{
					Stmts:         body,
					CloseBraceLoc: closeBraceLoc,
				}},
			}}},
		},

		Catch: &js_ast.Catch{
			Loc: loc,
			BindingOrNil: js_ast.Binding{
				Loc:  loc,
				Data: &js_ast.BIdentifier{Ref: tempRef},
			},
			Block: js_ast.SBlock{
				Stmts: []js_ast.Stmt{{Loc: loc, Data: &js_ast.SExpr{Value: js_ast.Expr{Loc: loc, Data: &js_ast.EBinary{
					Op:   js_ast.BinOpAssign,
					Left: js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{Ref: errorRef}},
					Right: js_ast.Expr{Loc: loc, Data: &js_ast.EArray{
						Items:        []js_ast.Expr{{Loc: loc, Data: &js_ast.EIdentifier{Ref: tempRef}}},
						IsSingleLine: true,
					}},
				}}}}},
			},
		},

		Finally: &js_ast.Finally{
			Loc: loc,
			Block: js_ast.SBlock{
				Stmts: []js_ast.Stmt{{Loc: loc, Data: &js_ast.STry{
					BlockLoc: loc,
					Block: js_ast.SBlock{Stmts: []js_ast.Stmt{{Loc: loc, Data: &js_ast.SExpr{
						Value: js_ast.Expr{Loc: loc, Data: &js_ast.EBinary{
							Op: js_ast.BinOpLogicalAnd,
							Left: js_ast.Expr{Loc: loc, Data: &js_ast.EBinary{
								Op:   js_ast.BinOpLogicalAnd,
								Left: js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{Ref: moreRef}},
								Right: js_ast.Expr{Loc: loc, Data: &js_ast.EBinary{
									Op:   js_ast.BinOpAssign,
									Left: js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{Ref: tempRef}},
									Right: js_ast.Expr{Loc: loc, Data: &js_ast.EDot{
										Target:  js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{Ref: iterRef}},
										NameLoc: loc,
										Name:    "return",
									}},
								}},
							}},
							Right: awaitTempCallIter,
						}},
					}}}},
					Finally: &js_ast.Finally{
						Loc: loc,
						Block: js_ast.SBlock{Stmts: []js_ast.Stmt{{Loc: loc, Data: &js_ast.SIf{
							Test: js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{Ref: errorRef}},
							Yes: js_ast.Stmt{Loc: loc, Data: &js_ast.SThrow{Value: js_ast.Expr{Loc: loc, Data: &js_ast.EIndex{
								Target: js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{Ref: errorRef}},
								Index:  js_ast.Expr{Loc: loc, Data: &js_ast.ENumber{Value: 0}},
							}}}},
						}}}},
					},
				}}},
			},
		},
	}})
}