package js_parser

import (
	
	
	
	
	
	

	
	
	
	
	
	
	
	
)
This parser does two passes: 1. Parse the source into an AST, create the scope tree, and declare symbols. 2. Visit each node in the AST, bind identifiers to declared symbols, do constant folding, substitute compile-time variable definitions, and lower certain syntactic constructs as appropriate given the language target. So many things have been put in so few passes because we want to minimize the number of full-tree passes to improve performance. However, we need to have at least two separate passes to handle variable hoisting. See the comment about scopesInOrder below for more information.
For strict mode handling
This is the reference to the generated function argument for the namespace, which is different than the reference to the namespace itself: namespace ns { } The code above is transformed into something like this: var ns1; (function(ns2) { })(ns1 || (ns1 = {})); This variable is "ns2" not "ns1". It is only used during the second "visit" pass.
Imports (both ES6 and CommonJS) are tracked at the top level
The parser does two passes and we need to pass the scope tree information from the first pass to the second pass. That's done by tracking the calls to pushScopeForParsePass() and popScope() during the first pass in scopesInOrder. Then, when the second pass calls pushScopeForVisitPass() and popScope(), we consume entries from scopesInOrder and make sure they are in the same order. This way the second pass can efficiently use the same scope tree as the first pass without having to attach the scope tree to the AST. We need to split this into two passes because the pass that declares the symbols must be separate from the pass that binds identifiers to declared symbols to handle declaring a hoisted "var" symbol in a nested scope and binding a name to it in a parent or sibling scope.
These properties are for the visit pass, which runs after the parse pass. The visit pass binds identifiers to declared symbols, does constant folding, substitutes compile-time variable definitions, and lowers certain syntactic constructs as appropriate.
These are for recognizing "typeof require == 'function' && require". This is a workaround for code that browserify generates that looks like this: (function e(t, n, r) { function s(o2, u) { if (!n[o2]) { if (!t[o2]) { var a = typeof require == "function" && require; if (!u && a) return a(o2, true); if (i) return i(o2, true); throw new Error("Cannot find module '" + o2 + "'"); } var f = n[o2] = {exports: {}}; t[o2][0].call(f.exports, function(e2) { var n2 = t[o2][1][e2]; return s(n2 ? n2 : e2); }, f, f.exports, e, t, n, r); } return n[o2].exports; } var i = typeof require == "function" && require; for (var o = 0; o < r.length; o++) s(r[o]); return s; }); It's checking to see if the environment it's running in has a "require" function before calling it. However, esbuild's bundling environment has a bundle-time require function because it's a bundler. So in this case "typeof require == 'function'" is true and the "&&" expression just becomes a single "require" identifier, which will then crash at run time. The workaround is to explicitly pattern-match for the exact expression "typeof require == 'function' && require" and replace it with "false" if we're targeting the browser. Note that we can't just leave "typeof require == 'function'" alone because there is other code in the wild that legitimately does need it to become "true" when bundling. Specifically, the package "@dagrejs/graphlib" has code that looks like this: if (typeof require === "function") { try { lodash = { clone: require("lodash/clone"), constant: require("lodash/constant"), each: require("lodash/each"), // ... more calls to require() here ... }; } catch (e) { // continue regardless of error } } That library will crash later on during startup if that branch isn't taken because "typeof require === 'function'" is false at run time.
This helps recognize the "await import()" pattern. When this is present, warnings about non-string import paths will be omitted inside try blocks.
This helps recognize the "import().catch()" pattern. We also try to avoid warning about this just like the "try { await import() }" pattern.
This helps recognize the "require.someProperty" pattern. If this pattern is present and the output format is CommonJS, we avoid generating a warning about an unbundled use of "require".
This helps recognize calls to "require.resolve()" which may become ERequireResolve expressions.
Temporary variables used for lowering
When bundling, hoisted top-level local variables declared with "var" in nested scopes are moved up to be declared in the top-level scope instead. The old "var" statements are turned into regular assignments instead. This makes it easier to quickly scan the top-level statements for "var" locals with the guarantee that all will be found.
ArrowFunction is a special case in the grammar. Although it appears to be a PrimaryExpression, it's actually an AssigmentExpression. This means if a AssigmentExpression ends up producing an ArrowFunction then nothing can come after it other than the comma operator, since the comma operator is the only thing above AssignmentExpression under the Expression rule: AssignmentExpression: ArrowFunction ConditionalExpression LeftHandSideExpression = AssignmentExpression LeftHandSideExpression AssignmentOperator AssignmentExpression Expression: AssignmentExpression Expression , AssignmentExpression
This is used as part of an incremental build cache key. Some of these values can potentially change between builds if they are derived from nearby "package.json" or "tsconfig.json" files that were changed since the last build.
This pointer will always be different for each build but the contents shouldn't ever behave different semantically. We ignore this field for the equality comparison.
This is an embedded struct. Always access these directly instead of off the name "optionsThatSupportStructuralEquality". This is only grouped like this to make the equality comparison easier and safer (and hopefully faster).
Compare "optionsThatSupportStructuralEquality"
Compare "InjectedFiles"
	if len(.injectedFiles) != len(.injectedFiles) {
		return false
	}
	for ,  := range .injectedFiles {
		 := .injectedFiles[]
		if .SourceIndex != .SourceIndex || .Path != .Path || !stringArraysEqual(.Exports, .Exports) {
			return false
		}
	}
Compare "JSX"
Do a cheap assert that the defines object hasn't changed
	if (.defines != nil || .defines != nil) && (.defines == nil || .defines == nil ||
		len(.defines.IdentifierDefines) != len(.defines.IdentifierDefines) ||
		len(.defines.DotDefines) != len(.defines.DotDefines)) {
		panic("Internal error")
	}

	return true
}

func ( []string,  []string) bool {
	if len() != len() {
		return false
	}
	for ,  := range  {
		if  != [] {
			return false
		}
	}
	return true
}

type tempRef struct {
	ref   js_ast.Ref
	value *js_ast.Expr
}

const (
	locModuleScope = -1
)

type scopeOrder struct {
	loc   logger.Loc
	scope *js_ast.Scope
}
This is function-specific information used during parsing. It is saved and restored on the call stack around code that parses nested functions and arrow expressions.
In TypeScript, forward declarations of functions have no bodies
Allow TypeScript decorators in function arguments
This is function-specific information used during visiting. It is saved and restored on the call stack around code that parses nested functions and arrow expressions.
This is used to silence references to "require" inside a try/catch statement. The assumption is that the try/catch statement is there to handle the case where the reference to "require" crashes. Specifically, the workaround handles the "moment" library which contains code that looks like this: try { oldLocale = globalLocale._abbr; var aliasedRequire = require; aliasedRequire('./locale/' + name); getSetGlobalLocale(oldLocale); } catch (e) {}
This is function-specific information used during visiting. It is saved and restored on the call stack around code that parses nested functions (but not nested arrow functions).
This is a reference to the magic "arguments" variable that exists inside functions in JavaScript. It will be non-nil inside functions and nil otherwise.
Arrow functions don't capture the value of "this" and "arguments". Instead, the values are inherited from the surrounding context. If arrow functions are turned into regular functions due to lowering, we will need to generate local variables to capture these values so they are preserved correctly.
Inside a static class property initializer, "this" expressions should be replaced with the class name.
If we're inside an async arrow function and async functions are not supported, then we will have to convert that arrow function to a generator function. That means references to "arguments" inside the arrow function will have to reference a captured variable instead of the real variable.
If false, the value for "this" is the top-level module scope "this" value. That means it's "undefined" for ECMAScript modules and "exports" for CommonJS modules. We track this information so that we can substitute the correct value for these top-level "this" references at compile time instead of passing the "this" expression through to the output and leaving the interpretation up to the run-time behavior of the generated code. If true, the value for "this" is nested inside something (either a function or a class declaration). That means the top-level module scope "this" value has been shadowed and is now inaccessible.
Preserve capacity
	.cases = .cases[:0]
This should be optimized by the compiler. See this for more information: https://github.com/golang/go/issues/5373
	 := .bloomFilter
	for  := range  {
		[] = 0
	}
}

func ( *duplicateCaseChecker) ( *parser,  js_ast.Expr) {
	if .options.suppressWarningsAboutWeirdCode {
		return
	}

	if ,  := duplicateCaseHash();  {
		 :=  % bloomFilterSize
		 := &.bloomFilter[/8]
		 := byte(1) << ( % 8)
Check for collisions
		if (* & ) != 0 {
			for ,  := range .cases {
				if .hash ==  {
					if ,  := duplicateCaseEquals(.value, );  {
						 := .source.RangeOfOperatorBefore(.Loc, "case")
						if  {
							.log.AddRangeWarning(&.source, ,
								"This case clause may never be evaluated because it likely duplicates an earlier case clause")
						} else {
							.log.AddRangeWarning(&.source, ,
								"This case clause will never be evaluated because it duplicates an earlier case clause")
						}
					}
					return
				}
			}
		}

		* |= 
		.cases = append(.cases, duplicateCaseValue{hash: , value: })
	}
}

func ( uint32,  uint32) uint32 {
	return  ^ ( + 0x9e3779b9 + ( << 6) + ( >> 2))
}

func ( js_ast.Expr) (uint32, bool) {
	switch e := .Data.(type) {
	case *js_ast.ENull:
		return 0, true

	case *js_ast.EUndefined:
		return 1, true

	case *js_ast.EBoolean:
		if .Value {
			return hashCombine(2, 1), true
		}
		return hashCombine(2, 0), true

	case *js_ast.ENumber:
		 := math.Float64bits(.Value)
		return hashCombine(hashCombine(3, uint32()), uint32(>>32)), true

	case *js_ast.EString:
		 := uint32(4)
		for ,  := range .Value {
			 = hashCombine(, uint32())
		}
		return , true

	case *js_ast.EBigInt:
		 := uint32(5)
		for ,  := range .Value {
			 = hashCombine(, uint32())
		}
		return , true

	case *js_ast.EIdentifier:
		return hashCombine(6, .Ref.InnerIndex), true

	case *js_ast.EDot:
		if ,  := (.Target);  {
			 := hashCombine(7, )
			for ,  := range .Name {
				 = hashCombine(, uint32())
			}
			return , true
		}

	case *js_ast.EIndex:
		if ,  := (.Target);  {
			if ,  := (.Index);  {
				return hashCombine(hashCombine(8, ), ), true
			}
		}
	}

	return 0, false
}

func ( js_ast.Expr,  js_ast.Expr) ( bool,  bool) {
	switch a := .Data.(type) {
	case *js_ast.ENull:
		,  := .Data.(*js_ast.ENull)
		return , false

	case *js_ast.EUndefined:
		,  := .Data.(*js_ast.EUndefined)
		return , false

	case *js_ast.EBoolean:
		,  := .Data.(*js_ast.EBoolean)
		return  && .Value == .Value, false

	case *js_ast.ENumber:
		,  := .Data.(*js_ast.ENumber)
		return  && .Value == .Value, false

	case *js_ast.EString:
		,  := .Data.(*js_ast.EString)
		return  && js_lexer.UTF16EqualsUTF16(.Value, .Value), false

	case *js_ast.EBigInt:
		,  := .Data.(*js_ast.EBigInt)
		return  && .Value == .Value, false

	case *js_ast.EIdentifier:
		,  := .Data.(*js_ast.EIdentifier)
		return  && .Ref == .Ref, false

	case *js_ast.EDot:
		if ,  := .Data.(*js_ast.EDot);  && .OptionalChain == .OptionalChain && .Name == .Name {
			,  := (.Target, .Target)
			return , true
		}

	case *js_ast.EIndex:
		if ,  := .Data.(*js_ast.EIndex);  && .OptionalChain == .OptionalChain {
			if ,  := (.Index, .Index);  {
				,  := (.Target, .Target)
				return , true
			}
		}
	}

	return false, false
}

func ( js_ast.S) bool {
	switch .(type) {
	case *js_ast.SBreak, *js_ast.SContinue, *js_ast.SReturn, *js_ast.SThrow:
		return true
	}

	return false
}

func ( js_ast.E) bool {
	switch .(type) {
	case *js_ast.ENull, *js_ast.EUndefined, *js_ast.EString, *js_ast.EBoolean, *js_ast.ENumber, *js_ast.EBigInt:
		return true
	}
	return false
}

type sideEffects uint8

const (
	couldHaveSideEffects sideEffects = iota
	noSideEffects
)

func ( js_ast.E) ( bool,  sideEffects,  bool) {
Never null or undefined
Always null or undefined
	case *js_ast.ENull, *js_ast.EUndefined:
		return true, noSideEffects, true

	case *js_ast.EUnary:
		switch .Op {
Always number or bigint
Always undefined
		case js_ast.UnOpVoid:
			return true, couldHaveSideEffects, true
		}

	case *js_ast.EBinary:
		switch .Op {
Always string or number or bigint
Always boolean
			js_ast.BinOpLt, js_ast.BinOpLe, js_ast.BinOpGt, js_ast.BinOpGe, js_ast.BinOpIn, js_ast.BinOpInstanceof,
			js_ast.BinOpLooseEq, js_ast.BinOpLooseNe, js_ast.BinOpStrictEq, js_ast.BinOpStrictNe:
			return false, couldHaveSideEffects, true

		case js_ast.BinOpComma:
			if , ,  := (.Right.Data);  {
				return , couldHaveSideEffects, true
			}
		}
	}

	return false, noSideEffects, false
}

func ( js_ast.E) ( bool,  sideEffects,  bool) {
	switch e := .(type) {
	case *js_ast.ENull, *js_ast.EUndefined:
		return false, noSideEffects, true

	case *js_ast.EBoolean:
		return .Value, noSideEffects, true

	case *js_ast.ENumber:
		return .Value != 0 && !math.IsNaN(.Value), noSideEffects, true

	case *js_ast.EBigInt:
		return .Value != "0", noSideEffects, true

	case *js_ast.EString:
		return len(.Value) > 0, noSideEffects, true

	case *js_ast.EFunction, *js_ast.EArrow, *js_ast.ERegExp:
		return true, noSideEffects, true

	case *js_ast.EObject, *js_ast.EArray, *js_ast.EClass:
		return true, couldHaveSideEffects, true

	case *js_ast.EUnary:
		switch .Op {
		case js_ast.UnOpVoid:
			return false, couldHaveSideEffects, true

Never an empty string
			return true, couldHaveSideEffects, true

		case js_ast.UnOpNot:
			if , ,  := (.Value.Data);  {
				return !, , true
			}
		}

	case *js_ast.EBinary:
		switch .Op {
"anything || truthy" is truthy
			if , ,  := (.Right.Data);  &&  {
				return true, couldHaveSideEffects, true
			}

"anything && falsy" is falsy
			if , ,  := (.Right.Data);  && ! {
				return false, couldHaveSideEffects, true
			}

"anything, truthy/falsy" is truthy/falsy
			if , ,  := (.Right.Data);  {
				return , couldHaveSideEffects, true
			}
		}
	}

	return false, couldHaveSideEffects, false
}

func ( js_ast.E) (float64, bool) {
	switch e := .(type) {
	case *js_ast.ENull:
		return 0, true

	case *js_ast.EUndefined:
		return math.NaN(), true

	case *js_ast.EBoolean:
		if .Value {
			return 1, true
		} else {
			return 0, true
		}

	case *js_ast.ENumber:
		return .Value, true
	}

	return 0, false
}
Returns true if the result of the "typeof" operator on this expression is statically determined and this expression has no side effects (i.e. can be removed without consequence).
func ( js_ast.E) (string, bool) {
	switch .(type) {
	case *js_ast.ENull:
		return "object", true

	case *js_ast.EUndefined:
		return "undefined", true

	case *js_ast.EBoolean:
		return "boolean", true

	case *js_ast.ENumber:
		return "number", true

	case *js_ast.EBigInt:
		return "bigint", true

	case *js_ast.EString:
		return "string", true

	case *js_ast.EFunction, *js_ast.EArrow:
		return "function", true
	}

	return "", false
}
Returns true if this expression is known to result in a primitive value (i.e. null, undefined, boolean, number, bigint, or string), even if the expression cannot be removed due to side effects.
func ( js_ast.E) bool {
	switch e := .(type) {
	case *js_ast.ENull, *js_ast.EUndefined, *js_ast.EBoolean, *js_ast.ENumber, *js_ast.EBigInt, *js_ast.EString:
		return true

	case *js_ast.EUnary:
		switch .Op {
Number or bigint
Boolean
Undefined
String
			js_ast.UnOpTypeof:
			return true
		}

	case *js_ast.EBinary:
		switch .Op {
String, number, or bigint
These always return one of the arguments unmodified
		case js_ast.BinOpLogicalAnd, js_ast.BinOpLogicalOr, js_ast.BinOpNullishCoalescing,
			js_ast.BinOpLogicalAndAssign, js_ast.BinOpLogicalOrAssign, js_ast.BinOpNullishCoalescingAssign:
			return (.Left.Data) && (.Right.Data)

		case js_ast.BinOpComma:
			return (.Right.Data)
		}

	case *js_ast.EIf:
		return (.Yes.Data) && (.No.Data)
	}

	return false
}
Returns "equal, ok". If "ok" is false, then nothing is known about the two values. If "ok" is true, the equality or inequality of the two values is stored in "equal".
func ( js_ast.E,  js_ast.E) (bool, bool) {
	switch l := .(type) {
	case *js_ast.ENull:
		,  := .(*js_ast.ENull)
		return , 

	case *js_ast.EUndefined:
		,  := .(*js_ast.EUndefined)
		return , 

	case *js_ast.EBoolean:
		,  := .(*js_ast.EBoolean)
		return  && .Value == .Value, 

	case *js_ast.ENumber:
		,  := .(*js_ast.ENumber)
		return  && .Value == .Value, 

	case *js_ast.EBigInt:
		,  := .(*js_ast.EBigInt)
		return  && .Value == .Value, 

	case *js_ast.EString:
		,  := .(*js_ast.EString)
		return  && js_lexer.UTF16EqualsUTF16(.Value, .Value), 
	}

	return false, false
}

func ( js_ast.E,  js_ast.E) bool {
	switch a := .(type) {
	case *js_ast.EIdentifier:
		if ,  := .(*js_ast.EIdentifier);  && .Ref == .Ref {
			return true
		}

	case *js_ast.EDot:
		if ,  := .(*js_ast.EDot);  && .HasSameFlagsAs() &&
			.Name == .Name && (.Target.Data, .Target.Data) {
			return true
		}

	case *js_ast.EIndex:
		if ,  := .(*js_ast.EIndex);  && .HasSameFlagsAs() &&
			(.Target.Data, .Target.Data) && (.Index.Data, .Index.Data) {
			return true
		}

	case *js_ast.EIf:
		if ,  := .(*js_ast.EIf);  && (.Test.Data, .Test.Data) &&
			(.Yes.Data, .Yes.Data) && (.No.Data, .No.Data) {
			return true
		}

	case *js_ast.EUnary:
		if ,  := .(*js_ast.EUnary);  && .Op == .Op && (.Value.Data, .Value.Data) {
			return true
		}

	case *js_ast.EBinary:
		if ,  := .(*js_ast.EBinary);  && .Op == .Op && (.Left.Data, .Left.Data) &&
			(.Right.Data, .Right.Data) {
			return true
		}

	case *js_ast.ECall:
		if ,  := .(*js_ast.ECall);  && .HasSameFlagsAs() &&
			len(.Args) == len(.Args) && (.Target.Data, .Target.Data) {
			for  := range .Args {
				if !(.Args[].Data, .Args[].Data) {
					return false
				}
			}
			return true
		}
	}

	,  := checkEqualityIfNoSideEffects(, )
	return  && 
}

func ( js_ast.S,  js_ast.S) bool {
	switch a := .(type) {
	case *js_ast.SBreak:
		,  := .(*js_ast.SBreak)
		return  && (.Label == nil) == (.Label == nil) && (.Label == nil || .Label.Ref == .Label.Ref)

	case *js_ast.SContinue:
		,  := .(*js_ast.SContinue)
		return  && (.Label == nil) == (.Label == nil) && (.Label == nil || .Label.Ref == .Label.Ref)

	case *js_ast.SReturn:
		,  := .(*js_ast.SReturn)
		return  && (.Value == nil) == (.Value == nil) && (.Value == nil || valuesLookTheSame(.Value.Data, .Value.Data))

	case *js_ast.SThrow:
		,  := .(*js_ast.SThrow)
		return  && valuesLookTheSame(.Value.Data, .Value.Data)
	}

	return false
}

func ( js_ast.Expr) bool {
	switch .Data.(type) {
	case *js_ast.EDot, *js_ast.EIndex:
		return true

	default:
		return false
	}
}

Safari workaround: Automatically avoid TDZ issues when bundling
Optimization: use "let" instead of "const" because it's shorter. This is only done when bundling because assigning to "const" is only an error when bundling.
	if .options.mode == config.ModeBundle &&  == js_ast.LocalConst && .options.mangleSyntax {
		return js_ast.LocalLet
	}

	return 
}

func ( *parser) ( js_ast.ScopeKind,  logger.Loc) int {
	 := .currentScope
	 := &js_ast.Scope{
		Kind:     ,
		Parent:   ,
		Members:  make(map[string]js_ast.ScopeMember),
		LabelRef: js_ast.InvalidRef,
	}
	if  != nil {
		.Children = append(.Children, )
		.StrictMode = .StrictMode
	}
	.currentScope = 
Enforce that scope locations are strictly increasing to help catch bugs where the pushed scopes are mistmatched between the first and second passes
	if len(.scopesInOrder) > 0 {
		 := .scopesInOrder[len(.scopesInOrder)-1].loc.Start
		if  >= .Start {
			panic(fmt.Sprintf("Scope location %d must be greater than %d", .Start, ))
		}
	}
Copy down function arguments into the function body scope. That way we get errors if a statement in the function body tries to re-declare any of the arguments.
	if  == js_ast.ScopeFunctionBody {
		if .Parent.Kind != js_ast.ScopeFunctionArgs {
			panic("Internal error")
		}
Don't copy down the optional function expression name. Re-declaring the name of a function expression is allowed.
			 := .symbols[.Ref.InnerIndex].Kind
			if  != js_ast.SymbolHoistedFunction {
				.Members[] = 
			}
		}
	}
Remember the length in case we call popAndDiscardScope() later
	 := len(.scopesInOrder)
	.scopesInOrder = append(.scopesInOrder, scopeOrder{, })
	return 
}

We cannot rename anything inside a scope containing a direct eval() call
Using direct eval when bundling is not a good idea in general because esbuild must assume that it can potentially reach anything in any of the containing scopes. We try to make it work but this isn't possible in some cases. For example, symbols imported using an ESM import are a live binding to the underlying symbol in another file. This is emulated during scope hoisting by erasing the ESM import and just referencing the underlying symbol in the flattened bundle directly. However, that symbol may have a different name which could break uses of direct eval: // Before bundling import { foo as bar } from './foo.js' console.log(eval('bar')) // After bundling let foo = 123 // The contents of "foo.js" console.log(eval('bar')) There really isn't any way to fix this. You can't just rename "foo" to "bar" in the example above because there may be a third bundled file that also contains direct eval and imports the same symbol with a different conflicting import alias. And there is no way to store a live binding to the underlying symbol in a variable with the import's name so that direct eval can access it: // After bundling let foo = 123 // The contents of "foo.js" const bar = cannot express a live binding to "foo" here console.log(eval('bar')) Technically a "with" statement could potentially make this work (with a big hit to performance), but they are deprecated and are unavailable in strict mode. This is a non-starter since all ESM code is strict mode. So while we still try to obey the requirement that all symbol names are pinned when direct eval is present, we make an exception for imported symbols. There is no guarantee that "eval" will be able to reach these symbols and they are free to be renamed or removed by tree shaking.
Move up to the parent scope
	 := .currentScope
	 := .Parent
	.currentScope = 
Truncate the scope order where we started to pretend we never saw this scope
	.scopesInOrder = .scopesInOrder[:]
Remove the last child from the parent scope
	 := len(.Children) - 1
	if .Children[] !=  {
		panic("Internal error")
	}
	.Children = .Children[:]
}

Move up to the parent scope
	 := .currentScope
	 := .Parent
	.currentScope = 
Erase this scope from the order. This will shift over the indices of all the scopes that were created after us. However, we shouldn't have to worry about other code with outstanding scope indices for these scopes. These scopes were all created in between this scope's push and pop operations, so they should all be child scopes and should all be popped by the time we get here.
	copy(.scopesInOrder[:], .scopesInOrder[+1:])
	.scopesInOrder = .scopesInOrder[:len(.scopesInOrder)-1]
Remove the last child from the parent scope
	 := len(.Children) - 1
	if .Children[] !=  {
		panic("Internal error")
	}
	.Children = .Children[:]
Reparent our child scopes into our parent
	for ,  := range .Children {
		.Parent = 
		.Children = append(.Children, )
	}
}
Undo all scopes pushed and popped after this scope index. This assumes that the scope stack is at the same level now as it was at the given scope index.
Remove any direct children from their parent
	 := .currentScope.Children
	for ,  := range .scopesInOrder[:] {
		if .scope.Parent == .currentScope {
			for  := len() - 1;  >= 0; -- {
				if [] == .scope {
					 = append([:], [+1:]...)
					break
				}
			}
		}
	}
	.currentScope.Children = 
Truncate the scope order where we started to pretend we never saw this scope
This is similar to "js_ast.MergeSymbols" but it works with this parser's one-level symbol map instead of the linker's two-level symbol map. It also doesn't handle cycles since they shouldn't come up due to the way this function is used.
In TypeScript, imports are allowed to silently collide with symbols within the module. Presumably this is because the imports may be type-only: import {Foo} from 'bar' class Foo {}
	if .options.ts.Parse &&  == js_ast.SymbolImport {
		return mergeReplaceWithNew
	}
"enum Foo {} enum Foo {}" "namespace Foo { ... } enum Foo {}"
	if  == js_ast.SymbolTSEnum && ( == js_ast.SymbolTSEnum ||  == js_ast.SymbolTSNamespace) {
		return mergeReplaceWithNew
	}
"namespace Foo { ... } namespace Foo { ... }" "function Foo() {} namespace Foo { ... }" "enum Foo {} namespace Foo { ... }"
"var foo; var foo;" "var foo; function foo() {}" "function foo() {} var foo;" "function *foo() {} function *foo() {}" but not "{ function *foo() {} function *foo() {} }"
	if .IsHoistedOrFunction() && .IsHoistedOrFunction() &&
		(.Kind == js_ast.ScopeEntry || .Kind == js_ast.ScopeFunctionBody ||
			(.IsHoisted() && .IsHoisted())) {
		return mergeKeepExisting
	}
"get #foo() {} set #foo() {}" "set #foo() {} get #foo() {}"
"try {} catch (e) { var e }"
"function() { var arguments }"
	if  == js_ast.SymbolArguments &&  == js_ast.SymbolHoisted {
		return mergeKeepExisting
	}
"function() { let arguments }"
Forbid declaring a symbol with a reserved word in strict mode
Allocate a new symbol
	 := .newSymbol(, )
Check for a collision in the declaring scope
	if ,  := .currentScope.Members[];  {
		 := &.symbols[.Ref.InnerIndex]

		switch .canMergeSymbols(.currentScope, .Kind, ) {
		case mergeForbidden:
			 := js_lexer.RangeOfIdentifier(.source, )
			.log.AddRangeErrorWithNotes(&.source, , fmt.Sprintf("%q has already been declared", ),
				[]logger.MsgData{logger.RangeData(&.source, js_lexer.RangeOfIdentifier(.source, .Loc),
					fmt.Sprintf("%q was originally declared here", ))})
			return .Ref

		case mergeKeepExisting:
			 = .Ref

		case mergeReplaceWithNew:
			.Link = 

		case mergeBecomePrivateGetSetPair:
			 = .Ref
			.Kind = js_ast.SymbolPrivateGetSetPair

		case mergeBecomePrivateStaticGetSetPair:
			 = .Ref
			.Kind = js_ast.SymbolPrivateStaticGetSetPair

		case mergeOverwriteWithNew:
		}
	}
Overwrite this name in the declaring scope
	.currentScope.Members[] = js_ast.ScopeMember{Ref: , Loc: }
	return 
}

func ( *parser) ( *js_ast.Scope) {
	if !.Kind.StopsHoisting() {
	:
		for ,  := range .Members {
			 := &.symbols[.Ref.InnerIndex]

			if !.Kind.IsHoisted() {
				continue
			}
Implement "Block-Level Function Declarations Web Legacy Compatibility Semantics" from Annex B of the ECMAScript standard version 6+
			 := false
			 := .Ref
Block-level function declarations behave like "let" in strict mode
				if .StrictMode != js_ast.SloppyMode {
					continue
				}
In sloppy mode, block level functions behave like "let" except with an assignment to "var", sort of. This code: if (x) { f(); function f() {} } f(); behaves like this code: if (x) { let f2 = function() {} var f = f2; f2(); } f();
				 := .newSymbol(js_ast.SymbolHoisted, .OriginalName)
				.Generated = append(.Generated, )
				if .hoistedRefForSloppyModeBlockFn == nil {
					.hoistedRefForSloppyModeBlockFn = make(map[js_ast.Ref]js_ast.Ref)
				}
				.hoistedRefForSloppyModeBlockFn[.Ref] = 
				 = &.symbols[.InnerIndex]
				.Ref = 
				 = true
			}
Check for collisions that would prevent to hoisting "var" symbols up to the enclosing function scope
			 := .Parent
Variable declarations hoisted past a "with" statement may actually end up overwriting a property on the target of the "with" statement instead of initializing the variable. We must not rename them or we risk causing a behavior change. var obj = { foo: 1 } with (obj) { var foo = 2 } assert(foo === undefined) assert(obj.foo === 2)
				if .Kind == js_ast.ScopeWith {
					.MustNotBeRenamed = true
				}

				if ,  := .Members[.OriginalName];  {
					 := &.symbols[.Ref.InnerIndex]
We can hoist the symbol from the child scope into the symbol in this scope if: - The symbol is unbound (i.e. a global variable access) - The symbol is also another hoisted variable - The symbol is a function of any kind and we're in a function or module scope Is this unbound (i.e. a global access) or also hoisted?
					if .Kind == js_ast.SymbolUnbound || .Kind == js_ast.SymbolHoisted ||
Silently merge this symbol into the existing symbol
						.Link = .Ref
						.Members[.OriginalName] = 
						continue 
					}
Otherwise if this isn't a catch identifier, it's a collision
An identifier binding from a catch statement and a function declaration can both silently shadow another hoisted symbol
						if .Kind != js_ast.SymbolCatchIdentifier && .Kind != js_ast.SymbolHoistedFunction {
							if ! {
								 := js_lexer.RangeOfIdentifier(.source, .Loc)
								.log.AddRangeErrorWithNotes(&.source, , fmt.Sprintf("%q has already been declared", .OriginalName),
									[]logger.MsgData{logger.RangeData(&.source, js_lexer.RangeOfIdentifier(.source, .Loc),
										fmt.Sprintf("%q was originally declared here", .OriginalName))})
Never mind about this, turns out it's not needed after all
								delete(.hoistedRefForSloppyModeBlockFn, )
							}
						}
						continue 
					}
If this is a catch identifier, silently merge the existing symbol into this symbol but continue hoisting past this catch scope
					.Link = .Ref
					.Members[.OriginalName] = 
				}

Declare the member in the scope that stopped the hoisting
					.Members[.OriginalName] = 
					break
				}
				 = .Parent
			}
		}
	}

	for ,  := range .Children {
		.()
	}
}

func ( *parser) ( js_ast.SymbolKind,  js_ast.Binding,  parseStmtOpts) {
	switch b := .Data.(type) {
	case *js_ast.BMissing:

	case *js_ast.BIdentifier:
		 := .loadNameFromRef(.Ref)
		if !.isTypeScriptDeclare || (.isNamespaceScope && .isExport) {
			.Ref = .declareSymbol(, .Loc, )
		}

	case *js_ast.BArray:
		for ,  := range .Items {
			.(, .Binding, )
		}

	case *js_ast.BObject:
		for ,  := range .Properties {
			.(, .Value, )
		}

	default:
		panic("Internal error")
	}
}

The use count stored in the symbol is used for generating symbol names during minification. These counts shouldn't include references inside dead code regions since those will be culled.
	if !.isControlFlowDead {
		.symbols[.InnerIndex].UseCountEstimate++
		 := .symbolUses[]
		.CountEstimate++
		.symbolUses[] = 
	}
The correctness of TypeScript-to-JavaScript conversion relies on accurate symbol use counts for the whole file, including dead code regions. This is tracked separately in a parser-only data structure.
	if .options.ts.Parse {
		.tsUseCounts[.InnerIndex]++
	}
}

Roll back the use count increment in recordUsage()
	if !.isControlFlowDead {
		.symbols[.InnerIndex].UseCountEstimate--
		 := .symbolUses[]
		.CountEstimate--
		if .CountEstimate == 0 {
			delete(.symbolUses, )
		} else {
			.symbolUses[] = 
		}
	}
Don't roll back the "tsUseCounts" increment. This must be counted even if the value is ignored because that's what the TypeScript compiler does.
}

func ( *parser) ( logger.Loc,  string,  []js_ast.Expr) js_ast.Expr {
	,  := .runtimeImports[]
	if ! {
		 = .newSymbol(js_ast.SymbolOther, )
		.moduleScope.Generated = append(.moduleScope.Generated, )
		.runtimeImports[] = 
	}
	.recordUsage()
	return js_ast.Expr{Loc: , Data: &js_ast.ECall{
		Target: js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }},
		Args:   ,
	}}
}

func ( *parser) () js_ast.Ref {
	if .promiseRef == js_ast.InvalidRef {
		.promiseRef = .newSymbol(js_ast.SymbolUnbound, "Promise")
	}
	return .promiseRef
}
The name is temporarily stored in the ref until the scope traversal pass happens, at which point a symbol will be generated and the ref will point to the symbol instead. The scope traversal pass will reconstruct the name using one of two methods. In the common case, the name is a slice of the file itself. In that case we can just store the slice and not need to allocate any extra memory. In the rare case, the name is an externally-allocated string. In that case we store an index to the string and use that index during the scope traversal pass.
Is the data in "name" a subset of the data in "p.source.Contents"?
The name is a slice of the file contents, so we can just reference it by length and don't have to allocate anything. This is the common case. It's stored as a negative value so we'll crash if we try to use it. That way we'll catch cases where we've forgetten to call loadNameFromRef(). The length is the negative part because we know it's non-zero.
The name is some memory allocated elsewhere. This is either an inline string constant in the parser or an identifier with escape sequences in the source code, which is very unusual. Stash it away for later. This uses allocations but it should hopefully be very uncommon.
		 := js_ast.Ref{OuterIndex: 0x80000000, InnerIndex: uint32(len(.allocatedNames))}
		.allocatedNames = append(.allocatedNames, )
		return 
	}
}
This is the inverse of storeNameInRef() above
func ( *parser) ( js_ast.Ref) string {
	if .OuterIndex == 0x80000000 {
		return .allocatedNames[.InnerIndex]
	} else {
		if (.OuterIndex & 0x80000000) == 0 {
			panic("Internal error: invalid symbol reference")
		}
		return .source.Contents[.InnerIndex : int32(.InnerIndex)-int32(.OuterIndex)]
	}
}
Due to ES6 destructuring patterns, there are many cases where it's impossible to distinguish between an array or object literal and a destructuring assignment until we hit the "=" operator later on. This object defers errors about being in one state or the other until we discover which state we're in.
The "await" and "yield" expressions are never allowed in argument lists but may or may not be allowed otherwise depending on the details of the enclosing function or module. This needs to be handled when parsing an arrow function argument list because we don't know if these expressions are not allowed until we reach the "=>" token (or discover the absence of one). Specifically, for await: // This is ok async function foo() { (x = await y) } // This is an error async function foo() { (x = await y) => {} } And for yield: // This is ok function* foo() { (x = yield y) } // This is an error function* foo() { (x = yield y) => {} }
type deferredArrowArgErrors struct {
	invalidExprAwait logger.Range
	invalidExprYield logger.Range
}

func ( *parser) ( *deferredArrowArgErrors) {
	if .invalidExprAwait.Len > 0 {
		 := .invalidExprAwait
		.log.AddRangeError(&.source, , "Cannot use an \"await\" expression here")
	}

	if .invalidExprYield.Len > 0 {
		 := .invalidExprYield
		.log.AddRangeError(&.source, , "Cannot use a \"yield\" expression here")
	}
}

func ( *parser) ( js_ast.Expr) string {
	switch k := .Data.(type) {
	case *js_ast.EString:
		return fmt.Sprintf("%q", js_lexer.UTF16ToString(.Value))
	case *js_ast.EPrivateIdentifier:
		return fmt.Sprintf("%q", .loadNameFromRef(.Ref))
	}
	return "property"
}

func ( *parser) ( js_ast.E) {
	if .lexer.IsLegacyOctalLiteral {
		if .legacyOctalLiterals == nil {
			.legacyOctalLiterals = make(map[js_ast.E]logger.Range)
		}
		.legacyOctalLiterals[] = .lexer.Range()
	}
}
This assumes the caller has already checked for TStringLiteral or TNoSubstitutionTemplateLiteral
func ( *parser) () js_ast.Expr {
	var  logger.Loc
	 := .lexer.Loc()
	if .lexer.LegacyOctalLoc.Start > .Start {
		 = .lexer.LegacyOctalLoc
	}
	 := js_ast.Expr{Loc: , Data: &js_ast.EString{
		Value:          .lexer.StringLiteral,
		LegacyOctalLoc: ,
		PreferTemplate: .lexer.Token == js_lexer.TNoSubstitutionTemplateLiteral,
	}}
	.lexer.Next()
	return 
}

type propertyOpts struct {
	asyncRange  logger.Range
	isAsync     bool
	isGenerator bool
Handle index signatures
		if .options.ts.Parse && .lexer.Token == js_lexer.TColon &&  && .isClass {
Skip this property entirely
				return js_ast.Property{}, false
			}
		}

		.lexer.Expect(js_lexer.TCloseBracket)
		 = 

	case js_lexer.TAsterisk:
		if  != js_ast.PropertyNormal || .isGenerator {
			.lexer.Unexpected()
		}
		.lexer.Next()
		.isGenerator = true
		return .(js_ast.PropertyNormal, , )

	default:
		 := .lexer.Identifier
		 := .lexer.Raw()
		 := .lexer.Range()
		if !.lexer.IsIdentifierOrKeyword() {
			.lexer.Expect(js_lexer.TIdentifier)
		}
		.lexer.Next()
Support contextual keywords
Does the following token look like a key?
			 := .lexer.IsIdentifierOrKeyword()
			if ! {
				switch .lexer.Token {
				case js_lexer.TOpenBracket, js_lexer.TNumericLiteral, js_lexer.TStringLiteral,
					js_lexer.TAsterisk, js_lexer.TPrivateIdentifier:
					 = true
				}
			}
If so, check for a modifier keyword
			if  {
				switch  {
				case "get":
					if !.isAsync &&  ==  {
						.markSyntaxFeature(compat.ObjectAccessors, )
						return .(js_ast.PropertyGet, , nil)
					}

				case "set":
					if !.isAsync &&  ==  {
						.markSyntaxFeature(compat.ObjectAccessors, )
						return .(js_ast.PropertySet, , nil)
					}

				case "async":
					if !.isAsync &&  ==  && !.lexer.HasNewlineBefore {
						.isAsync = true
						.asyncRange = 
						.markLoweredSyntaxFeature(compat.AsyncAwait, , compat.Generator)
						return .(, , nil)
					}

				case "static":
					if !.isStatic && !.isAsync && .isClass &&  ==  {
						.isStatic = true
						return .(, , nil)
					}

Skip over TypeScript keywords
					if .isClass && .options.ts.Parse &&  ==  {
						return .(, , nil)
					}
				}
			}
		}

		 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EString{Value: js_lexer.StringToUTF16()}}
Parse a shorthand property
		if !.isClass &&  == js_ast.PropertyNormal && .lexer.Token != js_lexer.TColon &&
			.lexer.Token != js_lexer.TOpenParen && .lexer.Token != js_lexer.TLessThan && !.isGenerator &&
			js_lexer.Keywords[] == js_lexer.T(0) {
			if (.fnOrArrowDataParse.allowAwait &&  == "await") || (.fnOrArrowDataParse.allowYield &&  == "yield") {
				.log.AddRangeError(&.source, , fmt.Sprintf("Cannot use %q as an identifier here", ))
			}
			 := .storeNameInRef()
			 := js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: }}
Destructuring patterns have an optional default value
			var  *js_ast.Expr = nil
			if  != nil && .lexer.Token == js_lexer.TEquals {
				.invalidExprDefaultValue = .lexer.Range()
				.lexer.Next()
				 := .parseExpr(js_ast.LComma)
				 = &
			}

			return js_ast.Property{
				Kind:         ,
				Key:          ,
				Value:        &,
				Initializer:  ,
				WasShorthand: true,
			}, true
		}
	}

"class X { foo?: number }" "class X { foo!: number }"
"class X { foo?<T>(): T }" "const x = { foo<T>(): T {} }"
Parse a class field with an optional initial value
	if .isClass &&  == js_ast.PropertyNormal && !.isAsync &&
		!.isGenerator && .lexer.Token != js_lexer.TOpenParen {
		var  *js_ast.Expr
Forbid the names "constructor" and "prototype" in some cases
		if ! {
			if ,  := .Data.(*js_ast.EString);  && (js_lexer.UTF16EqualsString(.Value, "constructor") ||
				(.isStatic && js_lexer.UTF16EqualsString(.Value, "prototype"))) {
				.log.AddRangeError(&.source, , fmt.Sprintf("Invalid field name %q", js_lexer.UTF16ToString(.Value)))
			}
		}
Skip over types
		if .options.ts.Parse && .lexer.Token == js_lexer.TColon {
			.lexer.Next()
			.skipTypeScriptType(js_ast.LLowest)
		}

		if .lexer.Token == js_lexer.TEquals {
			.lexer.Next()
			 := .parseExpr(js_ast.LComma)
			 = &
		}
Special-case private identifiers
		if ,  := .Data.(*js_ast.EPrivateIdentifier);  {
			 := .loadNameFromRef(.Ref)
			if  == "#constructor" {
				.log.AddRangeError(&.source, , fmt.Sprintf("Invalid field name %q", ))
			}
			var  js_ast.SymbolKind
			if .isStatic {
				 = js_ast.SymbolPrivateStaticField
			} else {
				 = js_ast.SymbolPrivateField
			}
			.Ref = .declareSymbol(, .Loc, )
		}

		.lexer.ExpectOrInsertSemicolon()
		return js_ast.Property{
			TSDecorators: .tsDecorators,
			Kind:         ,
			IsComputed:   ,
			IsStatic:     .isStatic,
			Key:          ,
			Initializer:  ,
		}, true
	}
Parse a method expression
	if .lexer.Token == js_lexer.TOpenParen ||  != js_ast.PropertyNormal ||
		.isClass || .isAsync || .isGenerator {
		if .lexer.Token == js_lexer.TOpenParen &&  != js_ast.PropertyGet &&  != js_ast.PropertySet {
			.markSyntaxFeature(compat.ObjectExtensions, .lexer.Range())
		}
		 := .lexer.Loc()
		 := .pushScopeForParsePass(js_ast.ScopeFunctionArgs, )
		 := false
Forbid the names "constructor" and "prototype" in some cases
		if .isClass && ! {
			if ,  := .Data.(*js_ast.EString);  {
				if !.isStatic && js_lexer.UTF16EqualsString(.Value, "constructor") {
					switch {
					case  == js_ast.PropertyGet:
						.log.AddRangeError(&.source, , "Class constructor cannot be a getter")
					case  == js_ast.PropertySet:
						.log.AddRangeError(&.source, , "Class constructor cannot be a setter")
					case .isAsync:
						.log.AddRangeError(&.source, , "Class constructor cannot be an async function")
					case .isGenerator:
						.log.AddRangeError(&.source, , "Class constructor cannot be a generator")
					default:
						 = true
					}
				} else if .isStatic && js_lexer.UTF16EqualsString(.Value, "prototype") {
					.log.AddRangeError(&.source, , "Invalid static method name \"prototype\"")
				}
			}
		}

		,  := .parseFn(nil, fnOrArrowDataParse{
			asyncRange:        .asyncRange,
			allowAwait:        .isAsync,
			allowYield:        .isGenerator,
			allowSuperCall:    .classHasExtends && ,
			allowTSDecorators: .allowTSDecorators,
			isConstructor:     ,
Only allow omitting the body if we're parsing TypeScript class
"class Foo { foo(): void; foo(): void {} }"
Skip this property entirely
			.popAndDiscardScope()
			return js_ast.Property{}, false
		}

		.popScope()
		.IsUniqueFormalParameters = true
		 := js_ast.Expr{Loc: , Data: &js_ast.EFunction{Fn: }}
Enforce argument rules for accessors
		switch  {
		case js_ast.PropertyGet:
			if len(.Args) > 0 {
				 := js_lexer.RangeOfIdentifier(.source, .Args[0].Binding.Loc)
				.log.AddRangeError(&.source, , fmt.Sprintf("Getter %s must have zero arguments", .keyNameForError()))
			}

		case js_ast.PropertySet:
			if len(.Args) != 1 {
				 := js_lexer.RangeOfIdentifier(.source, .Loc)
				if len(.Args) > 1 {
					 = js_lexer.RangeOfIdentifier(.source, .Args[1].Binding.Loc)
				}
				.log.AddRangeError(&.source, , fmt.Sprintf("Setter %s must have exactly one argument", .keyNameForError()))
			}
		}
Special-case private identifiers
		if ,  := .Data.(*js_ast.EPrivateIdentifier);  {
			var  js_ast.SymbolKind
			var  string
			switch  {
			case js_ast.PropertyGet:
				if .isStatic {
					 = js_ast.SymbolPrivateStaticGet
				} else {
					 = js_ast.SymbolPrivateGet
				}
				 = "_get"
			case js_ast.PropertySet:
				if .isStatic {
					 = js_ast.SymbolPrivateStaticSet
				} else {
					 = js_ast.SymbolPrivateSet
				}
				 = "_set"
			default:
				if .isStatic {
					 = js_ast.SymbolPrivateStaticMethod
				} else {
					 = js_ast.SymbolPrivateMethod
				}
				 = "_fn"
			}
			 := .loadNameFromRef(.Ref)
			if  == "#constructor" {
				.log.AddRangeError(&.source, , fmt.Sprintf("Invalid method name %q", ))
			}
			.Ref = .declareSymbol(, .Loc, )
			if .options.unsupportedJSFeatures.Has(.Feature()) {
				 := .newSymbol(js_ast.SymbolOther, [1:]+)
				if  == js_ast.PropertySet {
					.privateSetters[.Ref] = 
				} else {
					.privateGetters[.Ref] = 
				}
			}
		}

		return js_ast.Property{
			TSDecorators: .tsDecorators,
			Kind:         ,
			IsComputed:   ,
			IsMethod:     true,
			IsStatic:     .isStatic,
			Key:          ,
			Value:        &,
		}, true
	}
Parse an object key/value pair
	.lexer.Expect(js_lexer.TColon)
	 := .parseExprOrBindings(js_ast.LComma, )
	return js_ast.Property{
		Kind:       ,
		IsComputed: ,
		Key:        ,
		Value:      &,
	}, true
}

func ( *parser) () js_ast.PropertyBinding {
	var  js_ast.Expr
	 := false

	switch .lexer.Token {
	case js_lexer.TDotDotDot:
		.lexer.Next()
		 := js_ast.Binding{Loc: .lexer.Loc(), Data: &js_ast.BIdentifier{Ref: .storeNameInRef(.lexer.Identifier)}}
		.lexer.Expect(js_lexer.TIdentifier)
		return js_ast.PropertyBinding{
			IsSpread: true,
			Value:    ,
		}

	case js_lexer.TNumericLiteral:
		 = js_ast.Expr{Loc: .lexer.Loc(), Data: &js_ast.ENumber{Value: .lexer.Number}}
		.checkForLegacyOctalLiteral(.Data)
		.lexer.Next()

	case js_lexer.TStringLiteral:
		 = .parseStringLiteral()

	case js_lexer.TBigIntegerLiteral:
		 = js_ast.Expr{Loc: .lexer.Loc(), Data: &js_ast.EBigInt{Value: .lexer.Identifier}}
		.markSyntaxFeature(compat.BigInt, .lexer.Range())
		.lexer.Next()

	case js_lexer.TOpenBracket:
		 = true
		.lexer.Next()
		 = .parseExpr(js_ast.LComma)
		.lexer.Expect(js_lexer.TCloseBracket)

	default:
		 := .lexer.Identifier
		 := .lexer.Loc()
		if !.lexer.IsIdentifierOrKeyword() {
			.lexer.Expect(js_lexer.TIdentifier)
		}
		.lexer.Next()
		 = js_ast.Expr{Loc: , Data: &js_ast.EString{Value: js_lexer.StringToUTF16()}}

		if .lexer.Token != js_lexer.TColon && .lexer.Token != js_lexer.TOpenParen {
			 := .storeNameInRef()
			 := js_ast.Binding{Loc: , Data: &js_ast.BIdentifier{Ref: }}

			var  *js_ast.Expr
			if .lexer.Token == js_lexer.TEquals {
				.lexer.Next()
				 := .parseExpr(js_ast.LComma)
				 = &
			}

			return js_ast.PropertyBinding{
				Key:          ,
				Value:        ,
				DefaultValue: ,
			}
		}
	}

	.lexer.Expect(js_lexer.TColon)
	 := .parseBinding()

	var  *js_ast.Expr
	if .lexer.Token == js_lexer.TEquals {
		.lexer.Next()
		 := .parseExpr(js_ast.LComma)
		 = &
	}

	return js_ast.PropertyBinding{
		IsComputed:   ,
		Key:          ,
		Value:        ,
		DefaultValue: ,
	}
}

func ( *parser) ( []js_ast.Arg,  fnOrArrowDataParse) *js_ast.EArrow {
	 := .lexer.Loc()
Newlines are not allowed before "=>"
	if .lexer.HasNewlineBefore {
		.log.AddRangeError(&.source, .lexer.Range(), "Unexpected newline before \"=>\"")
		panic(js_lexer.LexerPanic{})
	}

	.lexer.Expect(js_lexer.TEqualsGreaterThan)

	for ,  := range  {
		.declareBinding(js_ast.SymbolHoisted, .Binding, parseStmtOpts{})
	}
The ability to call "super()" is inherited by arrow functions
	.allowSuperCall = .fnOrArrowDataParse.allowSuperCall

	if .lexer.Token == js_lexer.TOpenBrace {
		 := .parseFnBody()
		.afterArrowBodyLoc = .lexer.Loc()
		return &js_ast.EArrow{Args: , Body: }
	}

	.pushScopeForParsePass(js_ast.ScopeFunctionBody, )
	defer .popScope()

	 := .fnOrArrowDataParse
	.fnOrArrowDataParse = 
	 := .parseExpr(js_ast.LComma)
	.fnOrArrowDataParse = 
	return &js_ast.EArrow{
		Args:       ,
		PreferExpr: true,
		Body:       js_ast.FnBody{Loc: , Stmts: []js_ast.Stmt{{Loc: .Loc, Data: &js_ast.SReturn{Value: &}}}},
	}
}
This parses an expression. This assumes we've already parsed the "async" keyword and are currently looking at the following token.
"async function() {}"
	if !.lexer.HasNewlineBefore && .lexer.Token == js_lexer.TFunction {
		return .parseFnExpr(.Loc, true /* isAsync */, )
	}
Check the precedence level to avoid parsing an arrow function in "new async () => {}". This also avoids parsing "new async()" as "new (async())()" instead.
	if !.lexer.HasNewlineBefore &&  < js_ast.LMember {
"async => {}"
"async()" "async () => {}"
		case js_lexer.TOpenParen:
			.lexer.Next()
			return .parseParenExpr(.Loc, parenExprOpts{isAsync: true, asyncRange: })
"async<T>()" "async <T>() => {}"
"async" "async + 1"
	return js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .storeNameInRef("async")}}
}

func ( *parser) ( logger.Loc,  bool,  logger.Range) js_ast.Expr {
	.lexer.Next()
	 := .lexer.Token == js_lexer.TAsterisk
	if  {
		.markSyntaxFeature(compat.Generator, .lexer.Range())
		.lexer.Next()
	} else if  {
		.markLoweredSyntaxFeature(compat.AsyncAwait, , compat.Generator)
	}
	var  *js_ast.LocRef

	.pushScopeForParsePass(js_ast.ScopeFunctionArgs, )
	defer .popScope()
The name is optional
Don't declare the name "arguments" since it's shadowed and inaccessible
		 = &js_ast.LocRef{Loc: .lexer.Loc()}
		if  := .lexer.Identifier;  != "arguments" {
			.Ref = .declareSymbol(js_ast.SymbolHoistedFunction, .Loc, )
		} else {
			.Ref = .newSymbol(js_ast.SymbolHoistedFunction, )
		}
		.lexer.Next()
	}
Even anonymous functions can have TypeScript type parameters
	if .options.ts.Parse {
		.skipTypeScriptTypeParameters()
	}

	,  := .parseFn(, fnOrArrowDataParse{
		asyncRange: ,
		allowAwait: ,
		allowYield: ,
	})
	return js_ast.Expr{Loc: , Data: &js_ast.EFunction{Fn: }}
}

type parenExprOpts struct {
	asyncRange   logger.Range
	isAsync      bool
	forceArrowFn bool
}
This assumes that the open parenthesis has already been parsed by the caller
func ( *parser) ( logger.Loc,  parenExprOpts) js_ast.Expr {
	 := []js_ast.Expr{}
	 := deferredErrors{}
	 := deferredArrowArgErrors{}
	 := logger.Range{}
	 := logger.Range{}
	 := logger.Loc{}
Push a scope assuming this is an arrow function. It may not be, in which case we'll need to roll this change back. This has to be done ahead of parsing the arguments instead of later on when we hit the "=>" token and we know it's an arrow function because the arguments may have default values that introduce new scopes and declare new symbols. If this is an arrow function, then those new scopes will need to be parented under the scope of the arrow function itself.
Allow "in" inside parentheses
	 := .allowIn
	.allowIn = true
Forbid "await" and "yield", but only for arrow functions
	 := .fnOrArrowDataParse
	.fnOrArrowDataParse.arrowArgErrors = &
Scan over the comma-separated arguments or expressions
	for .lexer.Token != js_lexer.TCloseParen {
		 := .lexer.Loc()
		 := .lexer.Token == js_lexer.TDotDotDot

		if  {
			 = .lexer.Range()
			.markSyntaxFeature(compat.RestArgument, )
			.lexer.Next()
		}
We don't know yet whether these are arguments or expressions, so parse a superset of the expression syntax. Errors about things that are valid in one but not in the other are deferred.
		.latestArrowArgLoc = .lexer.Loc()
		 := .parseExprOrBindings(js_ast.LComma, &)

		if  {
			 = js_ast.Expr{Loc: , Data: &js_ast.ESpread{Value: }}
		}
Skip over types
		if .options.ts.Parse && .lexer.Token == js_lexer.TColon {
			 = .lexer.Range()
			.lexer.Next()
			.skipTypeScriptType(js_ast.LLowest)
		}
There may be a "=" after the type (but not after an "as" cast)
		if .options.ts.Parse && .lexer.Token == js_lexer.TEquals && .lexer.Loc() != .forbidSuffixAfterAsLoc {
			.lexer.Next()
			 = js_ast.Assign(, .parseExpr(js_ast.LComma))
		}

		 = append(, )
		if .lexer.Token != js_lexer.TComma {
			break
		}
Spread arguments must come last. If there's a spread argument followed by a comma, throw an error if we use these expressions as bindings.
		if  {
			 = .lexer.Loc()
		}
Eat the comma token
		.lexer.Next()
	}
The parenthetical construct must end with a close parenthesis
Restore "in" operator status before we parse the arrow function body
	.allowIn = 
Also restore "await" and "yield" expression errors
	.fnOrArrowDataParse = 
Are these arguments to an arrow function?
First, try converting the expressions to bindings
		for ,  := range  {
			 := false
			if ,  := .Data.(*js_ast.ESpread);  {
				 = .Value
				 = true
			}
			, ,  := .convertExprToBindingAndInitializer(, , )
			 = 
			 = append(, js_ast.Arg{Binding: , Default: })
		}
Avoid parsing TypeScript code like "a ? (1 + 2) : (3 + 4)" as an arrow function. The ":" after the ")" may be a return type annotation, so we attempt to convert the expressions to bindings first before deciding whether this is an arrow function, and only pick an arrow function if there were no conversion errors.
		if .lexer.Token == js_lexer.TEqualsGreaterThan || (len() == 0 &&
			.trySkipTypeScriptArrowReturnTypeWithBacktracking()) || .forceArrowFn {
			if .Start != 0 {
				.log.AddRangeError(&.source, logger.Range{Loc: , Len: 1}, "Unexpected \",\" after rest pattern")
			}
			.logArrowArgErrors(&)
Now that we've decided we're an arrow function, report binding pattern conversion errors
			if len() > 0 {
				for ,  := range  {
					.log.AddError(&.source, , "Invalid binding pattern")
				}
				panic(js_lexer.LexerPanic{})
			}

			 := .parseArrowBody(, fnOrArrowDataParse{allowAwait: .isAsync})
			.IsAsync = .isAsync
			.HasRestArg = .Len > 0
			.popScope()
			return js_ast.Expr{Loc: , Data: }
		}
	}
If we get here, it's not an arrow function so undo the pushing of the scope we did earlier. This needs to flatten any child scopes into the parent scope as if the scope was never pushed in the first place.
	.popAndFlattenScope()
If this isn't an arrow function, then types aren't allowed
	if .Len > 0 {
		.log.AddRangeError(&.source, , "Unexpected \":\"")
		panic(js_lexer.LexerPanic{})
	}
Are these arguments for a call to a function named "async"?
	if .isAsync {
		.logExprErrors(&)
		 := js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: .storeNameInRef("async")}}
		return js_ast.Expr{Loc: , Data: &js_ast.ECall{
			Target: ,
			Args:   ,
		}}
	}
Is this a chain of expressions and comma operators?
	if len() > 0 {
		.logExprErrors(&)
		if .Len > 0 {
			.log.AddRangeError(&.source, , "Unexpected \"...\"")
			panic(js_lexer.LexerPanic{})
		}
		 := js_ast.JoinAllWithComma()
		.markExprAsParenthesized()
		return 
	}
Indicate that we expected an arrow function
	.lexer.Expected(js_lexer.TEqualsGreaterThan)
	return js_ast.Expr{}
}

func ( *parser) ( js_ast.Expr,  []logger.Loc,  bool) (js_ast.Binding, *js_ast.Expr, []logger.Loc) {
	var  *js_ast.Expr
	if ,  := .Data.(*js_ast.EBinary);  && .Op == js_ast.BinOpAssign {
		 = &.Right
		 = .Left
	}
	,  := .convertExprToBinding(, )
	if  != nil {
		 := .source.RangeOfOperatorBefore(.Loc, "=")
		if  {
			.log.AddRangeError(&.source, , "A rest argument cannot have a default initializer")
		} else {
			.markSyntaxFeature(compat.DefaultArgument, )
		}
	}
	return , , 
}
Note: do not write to "p.log" in this function. Any errors due to conversion from expression to binding should be written to "invalidLog" instead. That way we can potentially keep this as an expression if it turns out it's not needed as a binding after all.
func ( *parser) ( js_ast.Expr,  []logger.Loc) (js_ast.Binding, []logger.Loc) {
	switch e := .Data.(type) {
	case *js_ast.EMissing:
		return js_ast.Binding{Loc: .Loc, Data: &js_ast.BMissing{}}, 

	case *js_ast.EIdentifier:
		return js_ast.Binding{Loc: .Loc, Data: &js_ast.BIdentifier{Ref: .Ref}}, 

	case *js_ast.EArray:
		if .CommaAfterSpread.Start != 0 {
			 = append(, .CommaAfterSpread)
		}
		if .IsParenthesized {
			 = append(, .source.RangeOfOperatorBefore(.Loc, "(").Loc)
		}
		.markSyntaxFeature(compat.Destructuring, .source.RangeOfOperatorAfter(.Loc, "["))
		 := []js_ast.ArrayBinding{}
		 := false
		for ,  := range .Items {
			if ,  := .Data.(*js_ast.ESpread);  {
				 = true
				 = .Value
				if ,  := .Data.(*js_ast.EIdentifier); ! {
					.markSyntaxFeature(compat.NestedRestBinding, .source.RangeOfOperatorAfter(.Loc, "["))
				}
			}
			, ,  := .convertExprToBindingAndInitializer(, , )
			 = 
			 = append(, js_ast.ArrayBinding{Binding: , DefaultValue: })
		}
		return js_ast.Binding{Loc: .Loc, Data: &js_ast.BArray{
			Items:        ,
			HasSpread:    ,
			IsSingleLine: .IsSingleLine,
		}}, 

	case *js_ast.EObject:
		if .CommaAfterSpread.Start != 0 {
			 = append(, .CommaAfterSpread)
		}
		if .IsParenthesized {
			 = append(, .source.RangeOfOperatorBefore(.Loc, "(").Loc)
		}
		.markSyntaxFeature(compat.Destructuring, .source.RangeOfOperatorAfter(.Loc, "{"))
		 := []js_ast.PropertyBinding{}
		for ,  := range .Properties {
			if .IsMethod || .Kind == js_ast.PropertyGet || .Kind == js_ast.PropertySet {
				 = append(, .Key.Loc)
				continue
			}
			, ,  := .convertExprToBindingAndInitializer(*.Value, , false)
			 = 
			if  == nil {
				 = .Initializer
			}
			 = append(, js_ast.PropertyBinding{
				IsSpread:     .Kind == js_ast.PropertySpread,
				IsComputed:   .IsComputed,
				Key:          .Key,
				Value:        ,
				DefaultValue: ,
			})
		}
		return js_ast.Binding{Loc: .Loc, Data: &js_ast.BObject{
			Properties:   ,
			IsSingleLine: .IsSingleLine,
		}}, 

	default:
		 = append(, .Loc)
		return js_ast.Binding{}, 
	}
}

func ( *parser) ( js_ast.Binding,  func(logger.Loc, js_ast.Ref) js_ast.Expr) js_ast.Expr {
	 := .Loc

	switch b := .Data.(type) {
	case *js_ast.BMissing:
		return js_ast.Expr{Loc: , Data: &js_ast.EMissing{}}

	case *js_ast.BIdentifier:
		if  != nil {
			return (, .Ref)
		}
		return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: .Ref}}

	case *js_ast.BArray:
		 := make([]js_ast.Expr, len(.Items))
		for ,  := range .Items {
			 := .(.Binding, )
			if .HasSpread && +1 == len(.Items) {
				 = js_ast.Expr{Loc: .Loc, Data: &js_ast.ESpread{Value: }}
			} else if .DefaultValue != nil {
				 = js_ast.Assign(, *.DefaultValue)
			}
			[] = 
		}
		return js_ast.Expr{Loc: , Data: &js_ast.EArray{
			Items:        ,
			IsSingleLine: .IsSingleLine,
		}}

	case *js_ast.BObject:
		 := make([]js_ast.Property, len(.Properties))
		for ,  := range .Properties {
			 := .(.Value, )
			 := js_ast.PropertyNormal
			if .IsSpread {
				 = js_ast.PropertySpread
			}
			[] = js_ast.Property{
				Kind:        ,
				IsComputed:  .IsComputed,
				Key:         .Key,
				Value:       &,
				Initializer: .DefaultValue,
			}
		}
		return js_ast.Expr{Loc: , Data: &js_ast.EObject{
			Properties:   ,
			IsSingleLine: .IsSingleLine,
		}}

	default:
		panic("Internal error")
	}
}

type exprFlag uint8

const (
	exprFlagTSDecorator exprFlag = 1 << iota
)

func ( *parser) ( js_ast.L,  *deferredErrors,  exprFlag) js_ast.Expr {
	 := .lexer.Loc()

	switch .lexer.Token {
	case js_lexer.TSuper:
		 := .lexer.Range()
		.lexer.Next()

		switch .lexer.Token {
		case js_lexer.TOpenParen:
			if  < js_ast.LCall && .fnOrArrowDataParse.allowSuperCall {
				return js_ast.Expr{Loc: , Data: &js_ast.ESuper{}}
			}

		case js_lexer.TDot, js_lexer.TOpenBracket:
			return js_ast.Expr{Loc: , Data: &js_ast.ESuper{}}
		}

		.log.AddRangeError(&.source, , "Unexpected \"super\"")
		return js_ast.Expr{Loc: , Data: &js_ast.ESuper{}}

	case js_lexer.TOpenParen:
		.lexer.Next()
Arrow functions aren't allowed in the middle of expressions
Allow "in" inside parentheses
			 := .allowIn
			.allowIn = true

			 := .parseExpr(js_ast.LLowest)
			.markExprAsParenthesized()
			.lexer.Expect(js_lexer.TCloseParen)

			.allowIn = 
			return 
		}

		 := .parseParenExpr(, parenExprOpts{})
		return 

	case js_lexer.TFalse:
		.lexer.Next()
		return js_ast.Expr{Loc: , Data: &js_ast.EBoolean{Value: false}}

	case js_lexer.TTrue:
		.lexer.Next()
		return js_ast.Expr{Loc: , Data: &js_ast.EBoolean{Value: true}}

	case js_lexer.TNull:
		.lexer.Next()
		return js_ast.Expr{Loc: , Data: &js_ast.ENull{}}

	case js_lexer.TThis:
		.lexer.Next()
		return js_ast.Expr{Loc: , Data: &js_ast.EThis{}}

	case js_lexer.TIdentifier:
		 := .lexer.Identifier
		 := .lexer.Range()
		 := .lexer.Raw()
		.lexer.Next()
Handle async and await expressions
		switch  {
		case "async":
			if  == "async" {
				return .parseAsyncPrefixExpr(, )
			}

		case "await":
			if .fnOrArrowDataParse.allowAwait {
				if  != "await" {
					.log.AddRangeError(&.source, , "The keyword \"await\" cannot be escaped")
				} else {
					if .fnOrArrowDataParse.isTopLevel {
						.topLevelAwaitKeyword = 
						.markSyntaxFeature(compat.TopLevelAwait, )
					}
					if .fnOrArrowDataParse.arrowArgErrors != nil {
						.fnOrArrowDataParse.arrowArgErrors.invalidExprAwait = 
					}
					 := .parseExpr(js_ast.LPrefix)
					if .lexer.Token == js_lexer.TAsteriskAsterisk {
						.lexer.Unexpected()
					}
					return js_ast.Expr{Loc: , Data: &js_ast.EAwait{Value: }}
				}
			}

		case "yield":
			if .fnOrArrowDataParse.allowYield {
				if  != "yield" {
					.log.AddRangeError(&.source, , "The keyword \"yield\" cannot be escaped")
				} else {
					if  > js_ast.LAssign {
						.log.AddRangeError(&.source, , "Cannot use a \"yield\" expression here without parentheses")
					}
					if .fnOrArrowDataParse.arrowArgErrors != nil {
						.fnOrArrowDataParse.arrowArgErrors.invalidExprYield = 
					}
					return .parseYieldExpr()
				}
Try to gracefully recover if "yield" is used in the wrong place
				switch .lexer.Token {
				case js_lexer.TNull, js_lexer.TIdentifier, js_lexer.TFalse, js_lexer.TTrue,
					js_lexer.TNumericLiteral, js_lexer.TBigIntegerLiteral, js_lexer.TStringLiteral:
					.log.AddRangeError(&.source, , "Cannot use \"yield\" outside a generator function")
					return .parseYieldExpr()
				}
			}
		}
Handle the start of an arrow expression
		if .lexer.Token == js_lexer.TEqualsGreaterThan {
			 := .storeNameInRef()
			 := js_ast.Arg{Binding: js_ast.Binding{Loc: , Data: &js_ast.BIdentifier{Ref: }}}

			.pushScopeForParsePass(js_ast.ScopeFunctionArgs, )
			defer .popScope()

			return js_ast.Expr{Loc: , Data: .parseArrowBody([]js_ast.Arg{}, fnOrArrowDataParse{})}
		}

		 := .storeNameInRef()
		return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}

	case js_lexer.TStringLiteral, js_lexer.TNoSubstitutionTemplateLiteral:
		return .parseStringLiteral()

	case js_lexer.TTemplateHead:
		var  logger.Loc
		 := .lexer.StringLiteral
		if .lexer.LegacyOctalLoc.Start > .Start {
			 = .lexer.LegacyOctalLoc
		}
		,  := .parseTemplateParts(false /* includeRaw */)
		if .Start > 0 {
			 = 
		}
		if .options.unsupportedJSFeatures.Has(compat.TemplateLiteral) {
			var  js_ast.Expr
"`${x}y`" => "x + 'y'"
				 := [0]
				 = js_ast.Expr{Loc: , Data: &js_ast.EBinary{
					Op:   js_ast.BinOpAdd,
					Left: .Value,
					Right: js_ast.Expr{Loc: .TailLoc, Data: &js_ast.EString{
						Value:          .Tail,
						LegacyOctalLoc: ,
					}},
				}}
				 = [1:]
"`x${y}`" => "'x' + y"
				 = js_ast.Expr{Loc: , Data: &js_ast.EString{
					Value:          ,
					LegacyOctalLoc: ,
				}}
			}
			for ,  := range  {
				 = js_ast.Expr{Loc: , Data: &js_ast.EBinary{
					Op:    js_ast.BinOpAdd,
					Left:  ,
					Right: .Value,
				}}
				if len(.Tail) > 0 {
					 = js_ast.Expr{Loc: , Data: &js_ast.EBinary{
						Op:    js_ast.BinOpAdd,
						Left:  ,
						Right: js_ast.Expr{Loc: .TailLoc, Data: &js_ast.EString{Value: .Tail}},
					}}
				}
			}
			return 
		}
		return js_ast.Expr{Loc: , Data: &js_ast.ETemplate{
			Head:           ,
			Parts:          ,
			LegacyOctalLoc: ,
		}}

	case js_lexer.TNumericLiteral:
		 := js_ast.Expr{Loc: , Data: &js_ast.ENumber{Value: .lexer.Number}}
		.checkForLegacyOctalLiteral(.Data)
		.lexer.Next()
		return 

	case js_lexer.TBigIntegerLiteral:
		 := .lexer.Identifier
		.markSyntaxFeature(compat.BigInt, .lexer.Range())
		.lexer.Next()
		return js_ast.Expr{Loc: , Data: &js_ast.EBigInt{Value: }}

	case js_lexer.TSlash, js_lexer.TSlashEquals:
		.lexer.ScanRegExp()
		 := .lexer.Raw()
		.lexer.Next()
		return js_ast.Expr{Loc: , Data: &js_ast.ERegExp{Value: }}

	case js_lexer.TVoid:
		.lexer.Next()
		 := .parseExpr(js_ast.LPrefix)
		if .lexer.Token == js_lexer.TAsteriskAsterisk {
			.lexer.Unexpected()
		}
		return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpVoid, Value: }}

	case js_lexer.TTypeof:
		.lexer.Next()
		 := .parseExpr(js_ast.LPrefix)
		if .lexer.Token == js_lexer.TAsteriskAsterisk {
			.lexer.Unexpected()
		}
		return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpTypeof, Value: }}

	case js_lexer.TDelete:
		.lexer.Next()
		 := .parseExpr(js_ast.LPrefix)
		if .lexer.Token == js_lexer.TAsteriskAsterisk {
			.lexer.Unexpected()
		}
		if ,  := .Data.(*js_ast.EIndex);  {
			if ,  := .Index.Data.(*js_ast.EPrivateIdentifier);  {
				 := .loadNameFromRef(.Ref)
				 := logger.Range{Loc: .Index.Loc, Len: int32(len())}
				.log.AddRangeError(&.source, , fmt.Sprintf("Deleting the private name %q is forbidden", ))
			}
		}
		return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpDelete, Value: }}

	case js_lexer.TPlus:
		.lexer.Next()
		 := .parseExpr(js_ast.LPrefix)
		if .lexer.Token == js_lexer.TAsteriskAsterisk {
			.lexer.Unexpected()
		}
		return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpPos, Value: }}

	case js_lexer.TMinus:
		.lexer.Next()
		 := .parseExpr(js_ast.LPrefix)
		if .lexer.Token == js_lexer.TAsteriskAsterisk {
			.lexer.Unexpected()
		}
		return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpNeg, Value: }}

	case js_lexer.TTilde:
		.lexer.Next()
		 := .parseExpr(js_ast.LPrefix)
		if .lexer.Token == js_lexer.TAsteriskAsterisk {
			.lexer.Unexpected()
		}
		return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpCpl, Value: }}

	case js_lexer.TExclamation:
		.lexer.Next()
		 := .parseExpr(js_ast.LPrefix)
		if .lexer.Token == js_lexer.TAsteriskAsterisk {
			.lexer.Unexpected()
		}
		return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpNot, Value: }}

	case js_lexer.TMinusMinus:
		.lexer.Next()
		return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpPreDec, Value: .parseExpr(js_ast.LPrefix)}}

	case js_lexer.TPlusPlus:
		.lexer.Next()
		return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpPreInc, Value: .parseExpr(js_ast.LPrefix)}}

	case js_lexer.TFunction:
		return .parseFnExpr(, false /* isAsync */, logger.Range{})

	case js_lexer.TClass:
		 := .lexer.Range()
		.markSyntaxFeature(compat.Class, )
		.lexer.Next()
		var  *js_ast.LocRef

		.pushScopeForParsePass(js_ast.ScopeClassName, )
Even anonymous classes can have TypeScript type parameters
		if .options.ts.Parse {
			.skipTypeScriptTypeParameters()
		}

		 := .parseClass(, , parseClassOpts{})

		.popScope()
		return js_ast.Expr{Loc: , Data: &js_ast.EClass{Class: }}

	case js_lexer.TNew:
		.lexer.Next()
Special-case the weird "new.target" expression here
		if .lexer.Token == js_lexer.TDot {
			.lexer.Next()
			if .lexer.Token != js_lexer.TIdentifier || .lexer.Identifier != "target" {
				.lexer.Unexpected()
			}
			 := logger.Range{Loc: , Len: .lexer.Range().End() - .Start}
			.markSyntaxFeature(compat.NewTarget, )
			.lexer.Next()
			return js_ast.Expr{Loc: , Data: &js_ast.ENewTarget{}}
		}

		 := .parseExprWithFlags(js_ast.LMember, )
		 := []js_ast.Expr{}

Skip over TypeScript non-null assertions
Skip over TypeScript type arguments here if there are any
			if .lexer.Token == js_lexer.TLessThan {
				.trySkipTypeScriptTypeArgumentsWithBacktracking()
			}
		}

		if .lexer.Token == js_lexer.TOpenParen {
			 = .parseCallArgs()
		}

		return js_ast.Expr{Loc: , Data: &js_ast.ENew{Target: , Args: }}

	case js_lexer.TOpenBracket:
		.lexer.Next()
		 := !.lexer.HasNewlineBefore
		 := []js_ast.Expr{}
		 := deferredErrors{}
		 := logger.Loc{}
Allow "in" inside arrays
		 := .allowIn
		.allowIn = true

		for .lexer.Token != js_lexer.TCloseBracket {
			switch .lexer.Token {
			case js_lexer.TComma:
				 = append(, js_ast.Expr{Loc: .lexer.Loc(), Data: &js_ast.EMissing{}})

			case js_lexer.TDotDotDot:
				if  != nil {
					.arraySpreadFeature = .lexer.Range()
				} else {
					.markSyntaxFeature(compat.ArraySpread, .lexer.Range())
				}
				 := .lexer.Loc()
				.lexer.Next()
				 := .parseExprOrBindings(js_ast.LComma, &)
				 = append(, js_ast.Expr{Loc: , Data: &js_ast.ESpread{Value: }})
Commas are not allowed here when destructuring
				if .lexer.Token == js_lexer.TComma {
					 = .lexer.Loc()
				}

			default:
				 := .parseExprOrBindings(js_ast.LComma, &)
				 = append(, )
			}

			if .lexer.Token != js_lexer.TComma {
				break
			}
			if .lexer.HasNewlineBefore {
				 = false
			}
			.lexer.Next()
			if .lexer.HasNewlineBefore {
				 = false
			}
		}

		if .lexer.HasNewlineBefore {
			 = false
		}
		.lexer.Expect(js_lexer.TCloseBracket)
		.allowIn = 

Is this a binding pattern?
Is this an expression?
			.logExprErrors(&)
In this case, we can't distinguish between the two yet
			.mergeInto()
		}

		return js_ast.Expr{Loc: , Data: &js_ast.EArray{
			Items:            ,
			CommaAfterSpread: ,
			IsSingleLine:     ,
		}}

	case js_lexer.TOpenBrace:
		.lexer.Next()
		 := !.lexer.HasNewlineBefore
		 := []js_ast.Property{}
		 := deferredErrors{}
		 := logger.Loc{}
Allow "in" inside object literals
		 := .allowIn
		.allowIn = true

		for .lexer.Token != js_lexer.TCloseBrace {
			if .lexer.Token == js_lexer.TDotDotDot {
				.lexer.Next()
				 := .parseExpr(js_ast.LComma)
				 = append(, js_ast.Property{
					Kind:  js_ast.PropertySpread,
					Value: &,
				})
Commas are not allowed here when destructuring
				if .lexer.Token == js_lexer.TComma {
					 = .lexer.Loc()
				}
This property may turn out to be a type in TypeScript, which should be ignored
				if ,  := .parseProperty(js_ast.PropertyNormal, propertyOpts{}, &);  {
					 = append(, )
				}
			}

			if .lexer.Token != js_lexer.TComma {
				break
			}
			if .lexer.HasNewlineBefore {
				 = false
			}
			.lexer.Next()
			if .lexer.HasNewlineBefore {
				 = false
			}
		}

		if .lexer.HasNewlineBefore {
			 = false
		}
		.lexer.Expect(js_lexer.TCloseBrace)
		.allowIn = 

Is this a binding pattern?
Is this an expression?
			.logExprErrors(&)
In this case, we can't distinguish between the two yet
			.mergeInto()
		}

		return js_ast.Expr{Loc: , Data: &js_ast.EObject{
			Properties:       ,
			CommaAfterSpread: ,
			IsSingleLine:     ,
		}}

This is a very complicated and highly ambiguous area of TypeScript syntax. Many similar-looking things are overloaded. TS: A type cast: <A>(x) <[]>(x) <A[]>(x) An arrow function with type parameters: <A>(x) => {} <A, B>(x) => {} <A = B>(x) => {} <A extends B>(x) => {} TSX: A JSX element: <A>(x) => {}</A> <A extends>(x) => {}</A> <A extends={false}>(x) => {}</A> An arrow function with type parameters: <A, B>(x) => {} <A extends B>(x) => {} A syntax error: <[]>(x) <A[]>(x) <A>(x) => {} <A = B>(x) => {}

		if .options.ts.Parse && .options.jsx.Parse {
			 := .lexer
			.lexer.Next()
Look ahead to see if this should be an arrow function instead
			 := false
			if .lexer.Token == js_lexer.TIdentifier {
				.lexer.Next()
				if .lexer.Token == js_lexer.TComma {
					 = true
				} else if .lexer.Token == js_lexer.TExtends {
					.lexer.Next()
					 = .lexer.Token != js_lexer.TEquals && .lexer.Token != js_lexer.TGreaterThan
				}
			}
Restore the lexer
Use NextInsideJSXElement() instead of Next() so we parse "<<" as "<"
The call to parseJSXElement() above doesn't consume the last TGreaterThan because the caller knows what Next() function to call. Use Next() instead of NextInsideJSXElement() here since the next token is an expression.
			.lexer.Next()
			return 
		}

This is either an old-style type cast or a generic lambda function
"<T>x"
			.lexer.Next()
			.skipTypeScriptType(js_ast.LLowest)
			.lexer.ExpectGreaterThan(false /* isInsideJSXElement */)
			 := .(, , )
			return 
		}

		.lexer.Unexpected()
		return js_ast.Expr{}

	case js_lexer.TImport:
		.lexer.Next()
		return .parseImportExpr(, )

	default:
		.lexer.Unexpected()
		return js_ast.Expr{}
	}
}

Parse a yield-from expression, which yields from an iterator
	 := .lexer.Token == js_lexer.TAsterisk
	if  {
		if .lexer.HasNewlineBefore {
			.lexer.Unexpected()
		}
		.lexer.Next()
	}

	var  *js_ast.Expr
The yield expression only has a value in certain cases
	switch .lexer.Token {
	case js_lexer.TCloseBrace, js_lexer.TCloseBracket, js_lexer.TCloseParen,
		js_lexer.TColon, js_lexer.TComma, js_lexer.TSemicolon:

	default:
		if  || !.lexer.HasNewlineBefore {
			 := .parseExpr(js_ast.LYield)
			 = &
		}
	}

	return js_ast.Expr{Loc: , Data: &js_ast.EYield{Value: , IsStar: }}
}

func ( *parser) () bool {
	switch .lexer.Token {
"[a] = b;"
		return true

"for ([a] in b) {}"
		return !.allowIn

"for ([a] of b) {}"
		return !.allowIn && .lexer.IsContextualKeyword("of")

	default:
		return false
	}
}
Note: The caller has already parsed the "import" keyword
Parse an "import.meta" expression
	if .lexer.Token == js_lexer.TDot {
		.es6ImportKeyword = js_lexer.RangeOfIdentifier(.source, )
		.lexer.Next()
		if .lexer.IsContextualKeyword("meta") {
			 := .lexer.Range()
			.lexer.Next()
			.hasImportMeta = true
			if .options.unsupportedJSFeatures.Has(compat.ImportMeta) {
				 = logger.Range{Loc: , Len: .End() - .Start}
				.markSyntaxFeature(compat.ImportMeta, )
			}
			return js_ast.Expr{Loc: , Data: &js_ast.EImportMeta{}}
		} else {
			.lexer.ExpectedString("\"meta\"")
		}
	}

	if  > js_ast.LCall {
		 := js_lexer.RangeOfIdentifier(.source, )
		.log.AddRangeError(&.source, , "Cannot use an \"import\" expression here without parentheses")
	}
Allow "in" inside call arguments
	 := .allowIn
	.allowIn = true

	.lexer.PreserveAllCommentsBefore = true
	.lexer.Expect(js_lexer.TOpenParen)
	 := .lexer.CommentsToPreserveBefore
	.lexer.PreserveAllCommentsBefore = false

	 := .parseExpr(js_ast.LComma)
	.lexer.Expect(js_lexer.TCloseParen)

	.allowIn = 
	return js_ast.Expr{Loc: , Data: &js_ast.EImport{Expr: , LeadingInteriorComments: }}
}

func ( *parser) ( js_ast.L,  *deferredErrors) js_ast.Expr {
	return .parseExprCommon(, , 0)
}

func ( *parser) ( js_ast.L) js_ast.Expr {
	return .parseExprCommon(, nil, 0)
}

func ( *parser) ( js_ast.L,  exprFlag) js_ast.Expr {
	return .parseExprCommon(, nil, )
}

func ( *parser) ( js_ast.L,  *deferredErrors,  exprFlag) js_ast.Expr {
	 := .lexer.HasPureCommentBefore && !.options.ignoreDCEAnnotations
	 := .parsePrefix(, , )
There is no formal spec for "__PURE__" comments but from reverse- engineering, it looks like they apply to the next CallExpression or NewExpression. So in " @__PURE__ a().b() + c()" the comment applies to the expression "a().b()".
	if  &&  < js_ast.LCall {
		 = .parseSuffix(, js_ast.LCall-1, , )
		switch e := .Data.(type) {
		case *js_ast.ECall:
			.CanBeUnwrappedIfUnused = true
		case *js_ast.ENew:
			.CanBeUnwrappedIfUnused = true
		}
	}

	return .parseSuffix(, , , )
}

func ( *parser) ( js_ast.Expr,  js_ast.L,  *deferredErrors,  exprFlag) js_ast.Expr {
	 := js_ast.OptionalChainNone

	for {
		if .lexer.Loc() == .afterArrowBodyLoc {
			for {
				switch .lexer.Token {
				case js_lexer.TComma:
					if  >= js_ast.LComma {
						return 
					}
					.lexer.Next()
					 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpComma, Left: , Right: .parseExpr(js_ast.LComma)}}

				default:
					return 
				}
			}
		}
Stop now if this token is forbidden to follow a TypeScript "as" cast
		if .lexer.Loc() == .forbidSuffixAfterAsLoc {
			return 
		}
Reset the optional chain flag by default. That way we won't accidentally treat "c.d" as OptionalChainContinue in "a?.b + c.d".
		 := 
		 = js_ast.OptionalChainNone

		switch .lexer.Token {
		case js_lexer.TDot:
			.lexer.Next()

"a.#b" "a?.b.#c"
				if ,  := .Data.(*js_ast.ESuper);  {
					.lexer.Expected(js_lexer.TIdentifier)
				}
				 := .lexer.Identifier
				 := .lexer.Loc()
				.lexer.Next()
				 := .storeNameInRef()
				 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EIndex{
					Target:        ,
					Index:         js_ast.Expr{Loc: , Data: &js_ast.EPrivateIdentifier{Ref: }},
					OptionalChain: ,
				}}
"a.b" "a?.b.c"
				if !.lexer.IsIdentifierOrKeyword() {
					.lexer.Expect(js_lexer.TIdentifier)
				}
				 := .lexer.Identifier
				 := .lexer.Loc()
				.lexer.Next()
				 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
					Target:        ,
					Name:          ,
					NameLoc:       ,
					OptionalChain: ,
				}}
			}

			 = 

		case js_lexer.TQuestionDot:
			.lexer.Next()

			switch .lexer.Token {
"a?.[b]"
				.lexer.Next()
Allow "in" inside the brackets
				 := .allowIn
				.allowIn = true

				 := .parseExpr(js_ast.LLowest)

				.allowIn = 

				.lexer.Expect(js_lexer.TCloseBracket)
				 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EIndex{
					Target:        ,
					Index:         ,
					OptionalChain: js_ast.OptionalChainStart,
				}}

"a?.()"
				if  >= js_ast.LCall {
					return 
				}
				 = js_ast.Expr{Loc: .Loc, Data: &js_ast.ECall{
					Target:        ,
					Args:          .parseCallArgs(),
					OptionalChain: js_ast.OptionalChainStart,
				}}

"a?.<T>()"
				if !.options.ts.Parse {
					.lexer.Expected(js_lexer.TIdentifier)
				}
				.skipTypeScriptTypeArguments(false /* isInsideJSXElement */)
				if .lexer.Token != js_lexer.TOpenParen {
					.lexer.Expected(js_lexer.TOpenParen)
				}
				if  >= js_ast.LCall {
					return 
				}
				 = js_ast.Expr{Loc: .Loc, Data: &js_ast.ECall{
					Target:        ,
					Args:          .parseCallArgs(),
					OptionalChain: js_ast.OptionalChainStart,
				}}

			default:
"a?.#b"
					 := .lexer.Identifier
					 := .lexer.Loc()
					.lexer.Next()
					 := .storeNameInRef()
					 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EIndex{
						Target:        ,
						Index:         js_ast.Expr{Loc: , Data: &js_ast.EPrivateIdentifier{Ref: }},
						OptionalChain: js_ast.OptionalChainStart,
					}}
"a?.b"
					if !.lexer.IsIdentifierOrKeyword() {
						.lexer.Expect(js_lexer.TIdentifier)
					}
					 := .lexer.Identifier
					 := .lexer.Loc()
					.lexer.Next()
					 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
						Target:        ,
						Name:          ,
						NameLoc:       ,
						OptionalChain: js_ast.OptionalChainStart,
					}}
				}
			}

			 = js_ast.OptionalChainContinue

		case js_lexer.TNoSubstitutionTemplateLiteral:
			if  != js_ast.OptionalChainNone {
				.log.AddRangeError(&.source, .lexer.Range(), "Template literals cannot have an optional chain as a tag")
			}
			.markSyntaxFeature(compat.TemplateLiteral, .lexer.Range())
			 := .lexer.StringLiteral
			 := .lexer.RawTemplateContents()
			.lexer.Next()
			 := 
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.ETemplate{Tag: &, Head: , HeadRaw: }}

		case js_lexer.TTemplateHead:
			if  != js_ast.OptionalChainNone {
				.log.AddRangeError(&.source, .lexer.Range(), "Template literals cannot have an optional chain as a tag")
			}
			.markSyntaxFeature(compat.TemplateLiteral, .lexer.Range())
			 := .lexer.StringLiteral
			 := .lexer.RawTemplateContents()
			,  := .parseTemplateParts(true /* includeRaw */)
			 := 
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.ETemplate{Tag: &, Head: , HeadRaw: , Parts: }}

When parsing a decorator, ignore EIndex expressions since they may be part of a computed property: class Foo { @foo ['computed']() {} } This matches the behavior of the TypeScript compiler.
			if ( & exprFlagTSDecorator) != 0 {
				return 
			}

			.lexer.Next()
Allow "in" inside the brackets
			 := .allowIn
			.allowIn = true

			 := .parseExpr(js_ast.LLowest)

			.allowIn = 

			.lexer.Expect(js_lexer.TCloseBracket)
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EIndex{
				Target:        ,
				Index:         ,
				OptionalChain: ,
			}}
			 = 

		case js_lexer.TOpenParen:
			if  >= js_ast.LCall {
				return 
			}
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.ECall{
				Target:        ,
				Args:          .parseCallArgs(),
				OptionalChain: ,
			}}
			 = 

		case js_lexer.TQuestion:
			if  >= js_ast.LConditional {
				return 
			}
			.lexer.Next()
Stop now if we're parsing one of these: "(a?) => {}" "(a?: b) => {}" "(a?, b?) => {}"
			if .options.ts.Parse && .Loc == .latestArrowArgLoc && (.lexer.Token == js_lexer.TColon ||
				.lexer.Token == js_lexer.TCloseParen || .lexer.Token == js_lexer.TComma) {
				if  == nil {
					.lexer.Unexpected()
				}
				.invalidExprAfterQuestion = .lexer.Range()
				return 
			}
Allow "in" in between "?" and ":"
			 := .allowIn
			.allowIn = true

			 := .parseExpr(js_ast.LComma)

			.allowIn = 

			.lexer.Expect(js_lexer.TColon)
			 := .parseExpr(js_ast.LComma)
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EIf{Test: , Yes: , No: }}

Skip over TypeScript non-null assertions
			if .lexer.HasNewlineBefore {
				return 
			}
			if !.options.ts.Parse {
				.lexer.Unexpected()
			}
			if  >= js_ast.LPostfix {
				return 
			}
			.lexer.Next()
			 = 

		case js_lexer.TMinusMinus:
			if .lexer.HasNewlineBefore ||  >= js_ast.LPostfix {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EUnary{Op: js_ast.UnOpPostDec, Value: }}

		case js_lexer.TPlusPlus:
			if .lexer.HasNewlineBefore ||  >= js_ast.LPostfix {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EUnary{Op: js_ast.UnOpPostInc, Value: }}

		case js_lexer.TComma:
			if  >= js_ast.LComma {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpComma, Left: , Right: .parseExpr(js_ast.LComma)}}

		case js_lexer.TPlus:
			if  >= js_ast.LAdd {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpAdd, Left: , Right: .parseExpr(js_ast.LAdd)}}

		case js_lexer.TPlusEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpAddAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TMinus:
			if  >= js_ast.LAdd {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpSub, Left: , Right: .parseExpr(js_ast.LAdd)}}

		case js_lexer.TMinusEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpSubAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TAsterisk:
			if  >= js_ast.LMultiply {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpMul, Left: , Right: .parseExpr(js_ast.LMultiply)}}

		case js_lexer.TAsteriskAsterisk:
			if  >= js_ast.LExponentiation {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpPow, Left: , Right: .parseExpr(js_ast.LExponentiation - 1)}}

		case js_lexer.TAsteriskAsteriskEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpPowAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TAsteriskEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpMulAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TPercent:
			if  >= js_ast.LMultiply {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpRem, Left: , Right: .parseExpr(js_ast.LMultiply)}}

		case js_lexer.TPercentEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpRemAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TSlash:
			if  >= js_ast.LMultiply {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpDiv, Left: , Right: .parseExpr(js_ast.LMultiply)}}

		case js_lexer.TSlashEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpDivAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TEqualsEquals:
			if  >= js_ast.LEquals {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLooseEq, Left: , Right: .parseExpr(js_ast.LEquals)}}

		case js_lexer.TExclamationEquals:
			if  >= js_ast.LEquals {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLooseNe, Left: , Right: .parseExpr(js_ast.LEquals)}}

		case js_lexer.TEqualsEqualsEquals:
			if  >= js_ast.LEquals {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpStrictEq, Left: , Right: .parseExpr(js_ast.LEquals)}}

		case js_lexer.TExclamationEqualsEquals:
			if  >= js_ast.LEquals {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpStrictNe, Left: , Right: .parseExpr(js_ast.LEquals)}}

TypeScript allows type arguments to be specified with angle brackets inside an expression. Unlike in other languages, this unfortunately appears to require backtracking to parse.
			if .options.ts.Parse && .trySkipTypeScriptTypeArgumentsWithBacktracking() {
				 = 
				continue
			}

			if  >= js_ast.LCompare {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLt, Left: , Right: .parseExpr(js_ast.LCompare)}}

		case js_lexer.TLessThanEquals:
			if  >= js_ast.LCompare {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLe, Left: , Right: .parseExpr(js_ast.LCompare)}}

		case js_lexer.TGreaterThan:
			if  >= js_ast.LCompare {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpGt, Left: , Right: .parseExpr(js_ast.LCompare)}}

		case js_lexer.TGreaterThanEquals:
			if  >= js_ast.LCompare {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpGe, Left: , Right: .parseExpr(js_ast.LCompare)}}

		case js_lexer.TLessThanLessThan:
			if  >= js_ast.LShift {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpShl, Left: , Right: .parseExpr(js_ast.LShift)}}

		case js_lexer.TLessThanLessThanEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpShlAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TGreaterThanGreaterThan:
			if  >= js_ast.LShift {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpShr, Left: , Right: .parseExpr(js_ast.LShift)}}

		case js_lexer.TGreaterThanGreaterThanEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpShrAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TGreaterThanGreaterThanGreaterThan:
			if  >= js_ast.LShift {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpUShr, Left: , Right: .parseExpr(js_ast.LShift)}}

		case js_lexer.TGreaterThanGreaterThanGreaterThanEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpUShrAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TQuestionQuestion:
			if  >= js_ast.LNullishCoalescing {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpNullishCoalescing, Left: , Right: .parseExpr(js_ast.LNullishCoalescing)}}

		case js_lexer.TQuestionQuestionEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpNullishCoalescingAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TBarBar:
			if  >= js_ast.LLogicalOr {
				return 
			}
Prevent "||" inside "??" from the right
			if  == js_ast.LNullishCoalescing {
				.lexer.Unexpected()
			}

			.lexer.Next()
			 := .parseExpr(js_ast.LLogicalOr)
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLogicalOr, Left: , Right: }}
Prevent "||" inside "??" from the left
			if  < js_ast.LNullishCoalescing {
				 = .(, js_ast.LNullishCoalescing+1, nil, )
				if .lexer.Token == js_lexer.TQuestionQuestion {
					.lexer.Unexpected()
				}
			}

		case js_lexer.TBarBarEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLogicalOrAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TAmpersandAmpersand:
			if  >= js_ast.LLogicalAnd {
				return 
			}
Prevent "&&" inside "??" from the right
Prevent "&&" inside "??" from the left
			if  < js_ast.LNullishCoalescing {
				 = .(, js_ast.LNullishCoalescing+1, nil, )
				if .lexer.Token == js_lexer.TQuestionQuestion {
					.lexer.Unexpected()
				}
			}

		case js_lexer.TAmpersandAmpersandEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLogicalAndAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TBar:
			if  >= js_ast.LBitwiseOr {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpBitwiseOr, Left: , Right: .parseExpr(js_ast.LBitwiseOr)}}

		case js_lexer.TBarEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpBitwiseOrAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TAmpersand:
			if  >= js_ast.LBitwiseAnd {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpBitwiseAnd, Left: , Right: .parseExpr(js_ast.LBitwiseAnd)}}

		case js_lexer.TAmpersandEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpBitwiseAndAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TCaret:
			if  >= js_ast.LBitwiseXor {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpBitwiseXor, Left: , Right: .parseExpr(js_ast.LBitwiseXor)}}

		case js_lexer.TCaretEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpBitwiseXorAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}

		case js_lexer.TEquals:
			if  >= js_ast.LAssign {
				return 
			}
			.lexer.Next()
			 = js_ast.Assign(, .parseExpr(js_ast.LAssign-1))

		case js_lexer.TIn:
			if  >= js_ast.LCompare || !.allowIn {
				return 
			}
Warn about "!a in b" instead of "!(a in b)"
			if !.options.suppressWarningsAboutWeirdCode {
				if ,  := .Data.(*js_ast.EUnary);  && .Op == js_ast.UnOpNot {
					.log.AddWarning(&.source, .Loc,
						"Suspicious use of the \"!\" operator inside the \"in\" operator")
				}
			}

			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpIn, Left: , Right: .parseExpr(js_ast.LCompare)}}

		case js_lexer.TInstanceof:
			if  >= js_ast.LCompare {
				return 
			}
Warn about "!a instanceof b" instead of "!(a instanceof b)". Here's an example of code with this problem: https://github.com/mrdoob/three.js/pull/11182.
			if !.options.suppressWarningsAboutWeirdCode {
				if ,  := .Data.(*js_ast.EUnary);  && .Op == js_ast.UnOpNot {
					.log.AddWarning(&.source, .Loc,
						"Suspicious use of the \"!\" operator inside the \"instanceof\" operator")
				}
			}

			.lexer.Next()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpInstanceof, Left: , Right: .parseExpr(js_ast.LCompare)}}

Handle the TypeScript "as" operator
These tokens are not allowed to follow a cast expression. This isn't an outright error because it may be on a new line, in which case it's the start of a new expression when it's after a cast: x = y as z (something);
Allow "in" inside call arguments
	 := .allowIn
	.allowIn = true

	 := []js_ast.Expr{}
	.lexer.Expect(js_lexer.TOpenParen)

	for .lexer.Token != js_lexer.TCloseParen {
		 := .lexer.Loc()
		 := .lexer.Token == js_lexer.TDotDotDot
		if  {
			.markSyntaxFeature(compat.RestArgument, .lexer.Range())
			.lexer.Next()
		}
		 := .parseExpr(js_ast.LComma)
		if  {
			 = js_ast.Expr{Loc: , Data: &js_ast.ESpread{Value: }}
		}
		 = append(, )
		if .lexer.Token != js_lexer.TComma {
			break
		}
		.lexer.Next()
	}

	.lexer.Expect(js_lexer.TCloseParen)
	.allowIn = 
	return 
}

func ( *parser) () (logger.Range, string, *js_ast.Expr) {
	 := .lexer.Loc()
A missing tag is a fragment
	if .lexer.Token == js_lexer.TGreaterThan {
		return logger.Range{Loc: , Len: 0}, "", nil
	}
The tag is an identifier
Certain identifiers are strings
	if strings.ContainsAny(, "-:") || (.lexer.Token != js_lexer.TDot && [0] >= 'a' && [0] <= 'z') {
		return , , &js_ast.Expr{Loc: , Data: &js_ast.EString{Value: js_lexer.StringToUTF16()}}
	}
Otherwise, this is an identifier
	 := &js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: .storeNameInRef()}}
Parse a member expression chain
Dashes are not allowed in member expression chains
		 := strings.IndexByte(, '-')
		if  >= 0 {
			.log.AddError(&.source, logger.Loc{Start: .Loc.Start + int32()}, "Unexpected \"-\"")
			panic(js_lexer.LexerPanic{})
		}

		 += "." + 
		 = &js_ast.Expr{Loc: , Data: &js_ast.EDot{
			Target:  *,
			Name:    ,
			NameLoc: .Loc,
		}}
		.Len = .Loc.Start + .Len - .Loc.Start
	}

	return , , 
}

Parse the tag
	, ,  := .parseJSXTag()
The tag may have TypeScript type arguments: "<Foo<T>/>"
Pass a flag to the type argument skipper because we need to call js_lexer.NextInsideJSXElement() after we hit the closing ">". The next token after the ">" might be an attribute name with a dash in it like this: "<Foo<T> data-disabled/>"
		.skipTypeScriptTypeArguments(true /* isInsideJSXElement */)
	}
Parse attributes
	 := []js_ast.Property{}
	if  != nil {
	:
		for {
			switch .lexer.Token {
Parse the key
Parse the value
				var  js_ast.Expr
Implicitly true value
					 = js_ast.Expr{Loc: logger.Loc{Start: .Loc.Start + .Len}, Data: &js_ast.EBoolean{Value: true}}
Use NextInsideJSXElement() not Next() so we can parse a JSX-style string literal
Use Expect() not ExpectInsideJSXElement() so we can parse expression tokens
Add a property
				 = append(, js_ast.Property{
					Key:   ,
					Value: &,
				})

Use Next() not ExpectInsideJSXElement() so we can parse "..."
				.lexer.Next()
				.lexer.Expect(js_lexer.TDotDotDot)
				 := .parseExpr(js_ast.LComma)
				 = append(, js_ast.Property{
					Kind:  js_ast.PropertySpread,
					Value: &,
				})
Use NextInsideJSXElement() not Next() so we can parse ">>" as ">"
				.lexer.NextInsideJSXElement()

			default:
				break 
			}
		}
	}
A slash here is a self-closing element
Use NextInsideJSXElement() not Next() so we can parse ">>" as ">"
Use ExpectJSXElementChild() so we parse child strings
Parse the children of this element
	 := []js_ast.Expr{}
	for {
		switch .lexer.Token {
		case js_lexer.TStringLiteral:
			 = append(, js_ast.Expr{Loc: .lexer.Loc(), Data: &js_ast.EString{Value: .lexer.StringLiteral}})
			.lexer.NextJSXElementChild()

Use Next() instead of NextJSXElementChild() here since the next token is an expression
			.lexer.Next()
The "..." here is ignored (it's used to signal an array type in TypeScript)
The expression is optional, and may be absent
			if .lexer.Token != js_lexer.TCloseBrace {
				 = append(, .parseExpr(js_ast.LLowest))
			}
Use ExpectJSXElementChild() so we parse child strings
This is a child element
				 = append(, .())
The call to parseJSXElement() above doesn't consume the last TGreaterThan because the caller knows what Next() function to call. Use NextJSXElementChild() here since the next token is an element child.
				.lexer.NextJSXElementChild()
				continue
			}
This is the closing element
			.lexer.NextInsideJSXElement()
			, ,  := .parseJSXTag()
			if  !=  {
				.log.AddRangeErrorWithNotes(&.source, , fmt.Sprintf("Expected closing tag %q to match opening tag %q", , ),
					[]logger.MsgData{logger.RangeData(&.source, , fmt.Sprintf("The opening tag %q is here", ))})
			}
			if .lexer.Token != js_lexer.TGreaterThan {
				.lexer.Expected(js_lexer.TGreaterThan)
			}

			return js_ast.Expr{Loc: , Data: &js_ast.EJSXElement{Tag: , Properties: , Children: }}

		default:
			.lexer.Unexpected()
		}
	}
}

Allow "in" inside template literals
	 := .allowIn
	.allowIn = true

	for {
		.lexer.Next()
		 := .parseExpr(js_ast.LLowest)
		 := .lexer.Loc()
		.lexer.RescanCloseBraceAsTemplateToken()
		 := .lexer.StringLiteral
		 := ""
		if  {
			 = .lexer.RawTemplateContents()
		} else if .lexer.LegacyOctalLoc.Start > .Start {
			 = .lexer.LegacyOctalLoc
		}
		 = append(, js_ast.TemplatePart{Value: , TailLoc: , Tail: , TailRaw: })
		if .lexer.Token == js_lexer.TTemplateTail {
			.lexer.Next()
			break
		}
	}

	.allowIn = 

	return , 
}

func ( *parser) ( js_ast.SymbolKind,  parseStmtOpts) []js_ast.Decl {
	 := []js_ast.Decl{}

Forbid "let let" and "const let" but not "var let"
		if ( == js_ast.SymbolOther ||  == js_ast.SymbolConst) && .lexer.IsContextualKeyword("let") {
			.log.AddRangeError(&.source, .lexer.Range(), "Cannot use \"let\" as an identifier here")
		}

		var  *js_ast.Expr
		 := .parseBinding()
		.declareBinding(, , )
Skip over types
"let foo!"
			 := .lexer.Token == js_lexer.TExclamation
			if  {
				.lexer.Next()
			}
"let foo: number"
			if  || .lexer.Token == js_lexer.TColon {
				.lexer.Expect(js_lexer.TColon)
				.skipTypeScriptType(js_ast.LLowest)
			}
		}

		if .lexer.Token == js_lexer.TEquals {
			.lexer.Next()
			 := .parseExpr(js_ast.LComma)
			 = &
		}

		 = append(, js_ast.Decl{Binding: , Value: })

		if .lexer.Token != js_lexer.TComma {
			break
		}
		.lexer.Next()
	}

	return 
}

func ( *parser) ( []js_ast.Decl) {
	for ,  := range  {
		if .Value == nil {
			if ,  := .Binding.Data.(*js_ast.BIdentifier);  {
				 := js_lexer.RangeOfIdentifier(.source, .Binding.Loc)
				.log.AddRangeError(&.source, , fmt.Sprintf("The constant %q must be initialized",
					.symbols[.Ref.InnerIndex].OriginalName))
			} else {
				.log.AddError(&.source, .Binding.Loc, "This constant must be initialized")
			}
		}
	}
}

func ( *parser) ( []js_ast.Decl,  string,  bool) {
	if len() > 1 {
		.log.AddError(&.source, [0].Binding.Loc, fmt.Sprintf("for-%s loops must have a single declaration", ))
	} else if len() == 1 && [0].Value != nil {
		if  {
This is a weird special case. Initializers are allowed in "var" statements with identifier bindings.
				return
			}
		}
		.log.AddError(&.source, [0].Value.Loc, fmt.Sprintf("for-%s loop variables cannot have an initializer", ))
	}
}

func ( *parser) () ([]js_ast.ClauseItem, bool) {
	 := []js_ast.ClauseItem{}
	.lexer.Expect(js_lexer.TOpenBrace)
	 := !.lexer.HasNewlineBefore

	for .lexer.Token != js_lexer.TCloseBrace {
		 := .lexer.Identifier
		 := .lexer.Loc()
		 := js_ast.LocRef{Loc: , Ref: .storeNameInRef()}
		 := 
The alias may be a keyword
An import where the name is a keyword must have an alias
Reject forbidden names
		if isEvalOrArguments() {
			 := js_lexer.RangeOfIdentifier(.source, .Loc)
			.log.AddRangeError(&.source, , fmt.Sprintf("Cannot use %q as an identifier here", ))
		}

		 = append(, js_ast.ClauseItem{
			Alias:        ,
			AliasLoc:     ,
			Name:         ,
			OriginalName: ,
		})

		if .lexer.Token != js_lexer.TComma {
			break
		}
		if .lexer.HasNewlineBefore {
			 = false
		}
		.lexer.Next()
		if .lexer.HasNewlineBefore {
			 = false
		}
	}

	if .lexer.HasNewlineBefore {
		 = false
	}
	.lexer.Expect(js_lexer.TCloseBrace)
	return , 
}

func ( *parser) () ([]js_ast.ClauseItem, bool) {
	 := []js_ast.ClauseItem{}
	 := logger.Loc{}
	.lexer.Expect(js_lexer.TOpenBrace)
	 := !.lexer.HasNewlineBefore

	for .lexer.Token != js_lexer.TCloseBrace {
		 := .lexer.Identifier
		 := .lexer.Loc()
		 := js_ast.LocRef{Loc: , Ref: .storeNameInRef()}
		 := 
The name can actually be a keyword if we're really an "export from" statement. However, we won't know until later. Allow keywords as identifiers for now and throw an error later if there's no "from". // This is fine export { default } from 'path' // This is a syntax error export { default }
		if .lexer.Token != js_lexer.TIdentifier {
			if !.lexer.IsIdentifierOrKeyword() {
				.lexer.Expect(js_lexer.TIdentifier)
			}
			if .Start == 0 {
				 = .lexer.Loc()
			}
		}
		.checkForNonBMPCodePoint(, )
		.lexer.Next()

		if .lexer.IsContextualKeyword("as") {
			.lexer.Next()
			 = .lexer.Identifier
			 = .lexer.Loc()
The alias may be a keyword
			if !.lexer.IsIdentifierOrKeyword() {
				.lexer.Expect(js_lexer.TIdentifier)
			}
			.checkForNonBMPCodePoint(, )
			.lexer.Next()
		}

		 = append(, js_ast.ClauseItem{
			Alias:        ,
			AliasLoc:     ,
			Name:         ,
			OriginalName: ,
		})

		if .lexer.Token != js_lexer.TComma {
			break
		}
		if .lexer.HasNewlineBefore {
			 = false
		}
		.lexer.Next()
		if .lexer.HasNewlineBefore {
			 = false
		}
	}

	if .lexer.HasNewlineBefore {
		 = false
	}
	.lexer.Expect(js_lexer.TCloseBrace)
Throw an error here if we found a keyword earlier and this isn't an "export from" statement after all
	if .Start != 0 && !.lexer.IsContextualKeyword("from") {
		 := js_lexer.RangeOfIdentifier(.source, )
		.log.AddRangeError(&.source, , fmt.Sprintf("Expected identifier but found %q", .source.TextForRange()))
		panic(js_lexer.LexerPanic{})
	}

	return , 
}

func ( *parser) () js_ast.Binding {
	 := .lexer.Loc()

	switch .lexer.Token {
	case js_lexer.TIdentifier:
		 := .lexer.Identifier
		if (.fnOrArrowDataParse.allowAwait &&  == "await") || (.fnOrArrowDataParse.allowYield &&  == "yield") {
			.log.AddRangeError(&.source, .lexer.Range(), fmt.Sprintf("Cannot use %q as an identifier here", ))
		}
		 := .storeNameInRef()
		.lexer.Next()
		return js_ast.Binding{Loc: , Data: &js_ast.BIdentifier{Ref: }}

	case js_lexer.TOpenBracket:
		.markSyntaxFeature(compat.Destructuring, .lexer.Range())
		.lexer.Next()
		 := !.lexer.HasNewlineBefore
		 := []js_ast.ArrayBinding{}
		 := false
"in" expressions are allowed
		 := .allowIn
		.allowIn = true

		for .lexer.Token != js_lexer.TCloseBracket {
			if .lexer.Token == js_lexer.TComma {
				 := js_ast.Binding{Loc: .lexer.Loc(), Data: &js_ast.BMissing{}}
				 = append(, js_ast.ArrayBinding{Binding: })
			} else {
				if .lexer.Token == js_lexer.TDotDotDot {
					.lexer.Next()
					 = true
This was a bug in the ES2015 spec that was fixed in ES2016
					if .lexer.Token != js_lexer.TIdentifier {
						.markSyntaxFeature(compat.NestedRestBinding, .lexer.Range())
					}
				}

				 := .()

				var  *js_ast.Expr
				if ! && .lexer.Token == js_lexer.TEquals {
					.lexer.Next()
					 := .parseExpr(js_ast.LComma)
					 = &
				}

				 = append(, js_ast.ArrayBinding{Binding: , DefaultValue: })
Commas after spread elements are not allowed
				if  && .lexer.Token == js_lexer.TComma {
					.log.AddRangeError(&.source, .lexer.Range(), "Unexpected \",\" after rest pattern")
					panic(js_lexer.LexerPanic{})
				}
			}

			if .lexer.Token != js_lexer.TComma {
				break
			}
			if .lexer.HasNewlineBefore {
				 = false
			}
			.lexer.Next()
			if .lexer.HasNewlineBefore {
				 = false
			}
		}

		.allowIn = 

		if .lexer.HasNewlineBefore {
			 = false
		}
		.lexer.Expect(js_lexer.TCloseBracket)
		return js_ast.Binding{Loc: , Data: &js_ast.BArray{
			Items:        ,
			HasSpread:    ,
			IsSingleLine: ,
		}}

	case js_lexer.TOpenBrace:
		.markSyntaxFeature(compat.Destructuring, .lexer.Range())
		.lexer.Next()
		 := !.lexer.HasNewlineBefore
		 := []js_ast.PropertyBinding{}
"in" expressions are allowed
		 := .allowIn
		.allowIn = true

		for .lexer.Token != js_lexer.TCloseBrace {
			 := .parsePropertyBinding()
			 = append(, )
Commas after spread elements are not allowed
			if .IsSpread && .lexer.Token == js_lexer.TComma {
				.log.AddRangeError(&.source, .lexer.Range(), "Unexpected \",\" after rest pattern")
				panic(js_lexer.LexerPanic{})
			}

			if .lexer.Token != js_lexer.TComma {
				break
			}
			if .lexer.HasNewlineBefore {
				 = false
			}
			.lexer.Next()
			if .lexer.HasNewlineBefore {
				 = false
			}
		}

		.allowIn = 

		if .lexer.HasNewlineBefore {
			 = false
		}
		.lexer.Expect(js_lexer.TCloseBrace)
		return js_ast.Binding{Loc: , Data: &js_ast.BObject{
			Properties:   ,
			IsSingleLine: ,
		}}
	}

	.lexer.Expect(js_lexer.TIdentifier)
	return js_ast.Binding{}
}

func ( *parser) ( *js_ast.LocRef,  fnOrArrowDataParse) ( js_ast.Fn,  bool) {
	if .allowAwait && .allowYield {
		.markSyntaxFeature(compat.AsyncGenerator, .asyncRange)
	}

	.Name = 
	.HasRestArg = false
	.IsAsync = .allowAwait
	.IsGenerator = .allowYield
	.ArgumentsRef = js_ast.InvalidRef
	.OpenParenLoc = .lexer.Loc()
	.lexer.Expect(js_lexer.TOpenParen)
Await and yield are not allowed in function arguments
If "super()" is allowed in the body, it's allowed in the arguments
Skip over "this" type annotations
		if .options.ts.Parse && .lexer.Token == js_lexer.TThis {
			.lexer.Next()
			if .lexer.Token == js_lexer.TColon {
				.lexer.Next()
				.skipTypeScriptType(js_ast.LLowest)
			}
			if .lexer.Token != js_lexer.TComma {
				break
			}
			.lexer.Next()
			continue
		}

		var  []js_ast.Expr
		if .allowTSDecorators {
			 = .parseTypeScriptDecorators()
		}

		if !.HasRestArg && .lexer.Token == js_lexer.TDotDotDot {
			.markSyntaxFeature(compat.RestArgument, .lexer.Range())
			.lexer.Next()
			.HasRestArg = true
		}

		 := false
		 := .lexer.Token == js_lexer.TIdentifier
		 := .lexer.Identifier
		 := .parseBinding()

Skip over TypeScript accessibility modifiers, which turn this argument into a class field when used inside a class constructor. This is known as a "parameter property" in TypeScript.
			if  && .isConstructor {
				for .lexer.Token == js_lexer.TIdentifier || .lexer.Token == js_lexer.TOpenBrace || .lexer.Token == js_lexer.TOpenBracket {
					if  != "public" &&  != "private" &&  != "protected" &&  != "readonly" {
						break
					}
					 = true
TypeScript requires an identifier binding
Re-parse the binding (the current binding is the TypeScript keyword)
					 = .parseBinding()
				}
			}
"function foo(a?) {}"
"function foo(a: any) {}"
			if .lexer.Token == js_lexer.TColon {
				.lexer.Next()
				.skipTypeScriptType(js_ast.LLowest)
			}
		}

		.declareBinding(js_ast.SymbolHoisted, , parseStmtOpts{})

		var  *js_ast.Expr
		if !.HasRestArg && .lexer.Token == js_lexer.TEquals {
			.markSyntaxFeature(compat.DefaultArgument, .lexer.Range())
			.lexer.Next()
			 := .parseExpr(js_ast.LComma)
			 = &
		}

		.Args = append(.Args, js_ast.Arg{
			TSDecorators: ,
			Binding:      ,
			Default:      ,
We need to track this because it affects code generation
			IsTypeScriptCtorField: ,
		})

		if .lexer.Token != js_lexer.TComma {
			break
		}
JavaScript does not allow a comma after a rest argument
TypeScript does allow a comma after a rest argument in a "declare" context
				.lexer.Next()
			} else {
				.lexer.Expect(js_lexer.TCloseParen)
			}
			break
		}
		.lexer.Next()
	}
Reserve the special name "arguments" in this scope. This ensures that it shadows any variable called "arguments" in any parent scopes. But only do this if it wasn't already declared above because arguments are allowed to be called "arguments", in which case the real "arguments" is inaccessible.
"function foo(): any {}"
"function foo(): any;"
	if .allowMissingBodyForTypeScript && .lexer.Token != js_lexer.TOpenBrace {
		.lexer.ExpectOrInsertSemicolon()
		return
	}

	.Body = .parseFnBody()
	 = true
	return
}

func ( *parser) ( logger.Loc,  parseStmtOpts) js_ast.Stmt {
	var  *js_ast.LocRef
	 := .lexer.Range()
	if .lexer.Token == js_lexer.TClass {
		.markSyntaxFeature(compat.Class, )
		.lexer.Next()
	} else {
		.lexer.Expected(js_lexer.TClass)
	}

	 := .lexer.Token == js_lexer.TIdentifier
	 :=  && js_lexer.StrictModeReservedWords[.lexer.Identifier]
	if !.isNameOptional || ( && !) {
		 := .lexer.Loc()
		 := .lexer.Identifier
		if  {
			.lexer.Unexpected()
		}
		.lexer.Expect(js_lexer.TIdentifier)
		 = &js_ast.LocRef{Loc: , Ref: js_ast.InvalidRef}
		if !.isTypeScriptDeclare {
			.Ref = .declareSymbol(js_ast.SymbolClass, , )
		}
	}
Even anonymous classes can have TypeScript type parameters
	if .options.ts.Parse {
		.skipTypeScriptTypeParameters()
	}

	 := parseClassOpts{
		allowTSDecorators:   true,
		isTypeScriptDeclare: .isTypeScriptDeclare,
	}
	if .tsDecorators != nil {
		.tsDecorators = .tsDecorators.values
	}
	 := .pushScopeForParsePass(js_ast.ScopeClassName, )
	 := .parseClass(, , )
	if .isTypeScriptDeclare {
		.popAndDiscardScope()
	} else {
		.popScope()
	}
	return js_ast.Stmt{Loc: , Data: &js_ast.SClass{Class: , IsExport: .isExport}}
}

type parseClassOpts struct {
	tsDecorators        []js_ast.Expr
	allowTSDecorators   bool
	isTypeScriptDeclare bool
}
By the time we call this, the identifier and type parameters have already been parsed. We need to start parsing from the "extends" clause.
func ( *parser) ( logger.Range,  *js_ast.LocRef,  parseClassOpts) js_ast.Class {
	var  *js_ast.Expr

	if .lexer.Token == js_lexer.TExtends {
		.lexer.Next()
		 := .parseExpr(js_ast.LNew)
		 = &
TypeScript's type argument parser inside expressions backtracks if the first token after the end of the type parameter list is "{", so the parsed expression above will have backtracked if there are any type arguments. This means we have to re-parse for any type arguments here. This seems kind of wasteful to me but it's what the official compiler does and it probably doesn't have that high of a performance overhead because "extends" clauses aren't that frequent, so it should be ok.
		if .options.ts.Parse {
			.skipTypeScriptTypeArguments(false /* isInsideJSXElement */)
		}
	}

	if .options.ts.Parse && .lexer.IsContextualKeyword("implements") {
		.lexer.Next()
		for {
			.skipTypeScriptType(js_ast.LLowest)
			if .lexer.Token != js_lexer.TComma {
				break
			}
			.lexer.Next()
		}
	}

	 := .lexer.Loc()
	.lexer.Expect(js_lexer.TOpenBrace)
	 := []js_ast.Property{}
Allow "in" and private fields inside class bodies
	 := .allowIn
	 := .allowPrivateIdentifiers
	.allowIn = true
	.allowPrivateIdentifiers = true
A scope is needed for private identifiers
Parse decorators for this property
		 := .lexer.Loc()
		if .allowTSDecorators {
			.tsDecorators = .parseTypeScriptDecorators()
		} else {
			.tsDecorators = nil
		}
This property may turn out to be a type in TypeScript, which should be ignored
		if ,  := .parseProperty(js_ast.PropertyNormal, , nil);  {
			 = append(, )
Forbid decorators on class constructors
			if len(.tsDecorators) > 0 {
				if ,  := .Key.Data.(*js_ast.EString);  && js_lexer.UTF16EqualsString(.Value, "constructor") {
					.log.AddError(&.source, , "TypeScript does not allow decorators on class constructors")
				}
			}
		}
	}
Discard the private identifier scope inside a TypeScript "declare class"
	if .isTypeScriptDeclare {
		.popAndDiscardScope()
	} else {
		.popScope()
	}

	.allowIn = 
	.allowPrivateIdentifiers = 

	.lexer.Expect(js_lexer.TCloseBrace)
	return js_ast.Class{
		ClassKeyword: ,
		TSDecorators: .tsDecorators,
		Name:         ,
		Extends:      ,
		BodyLoc:      ,
		Properties:   ,
	}
}

func ( *parser) () *js_ast.LocRef {
	if .lexer.Token != js_lexer.TIdentifier || .lexer.HasNewlineBefore {
		return nil
	}

	 := js_ast.LocRef{Loc: .lexer.Loc(), Ref: .storeNameInRef(.lexer.Identifier)}
	.lexer.Next()
	return &
}

func ( *parser) () (logger.Loc, string) {
	 := .lexer.Loc()
	 := js_lexer.UTF16ToString(.lexer.StringLiteral)
	if .lexer.Token == js_lexer.TNoSubstitutionTemplateLiteral {
		.lexer.Next()
	} else {
		.lexer.Expect(js_lexer.TStringLiteral)
	}
	return , 
}
This assumes the "function" token has already been parsed
func ( *parser) ( logger.Loc,  parseStmtOpts,  bool,  logger.Range) js_ast.Stmt {
	 := .lexer.Token == js_lexer.TAsterisk
	if  {
		.markSyntaxFeature(compat.Generator, .lexer.Range())
		.lexer.Next()
	} else if  {
		.markLoweredSyntaxFeature(compat.AsyncAwait, , compat.Generator)
	}

	switch .lexicalDecl {
	case lexicalDeclForbid:
		.forbidLexicalDecl()
Allow certain function statements in certain single-statement contexts
	case lexicalDeclAllowFnInsideIf, lexicalDeclAllowFnInsideLabel:
		if .isTypeScriptDeclare ||  ||  {
			.forbidLexicalDecl()
		}
	}

	var  *js_ast.LocRef
	var  string
The name is optional for "export default function() {}" pseudo-statements
	if !.isNameOptional || .lexer.Token == js_lexer.TIdentifier {
		 := .lexer.Loc()
		 = .lexer.Identifier
		.lexer.Expect(js_lexer.TIdentifier)
		 = &js_ast.LocRef{Loc: , Ref: js_ast.InvalidRef}
	}
Even anonymous functions can have TypeScript type parameters
Introduce a fake block scope for function declarations inside if statements
	var  int
	 := .lexicalDecl == lexicalDeclAllowFnInsideIf
	if  {
		 = .pushScopeForParsePass(js_ast.ScopeBlock, )
	}

	 := .pushScopeForParsePass(js_ast.ScopeFunctionArgs, .lexer.Loc())

	,  := .parseFn(, fnOrArrowDataParse{
		asyncRange:          ,
		allowAwait:          ,
		allowYield:          ,
		isTypeScriptDeclare: .isTypeScriptDeclare,
Only allow omitting the body if we're parsing TypeScript
Don't output anything if it's just a forward declaration of a function
	if .isTypeScriptDeclare || ! {
		.popAndDiscardScope()
Balance the fake block scope introduced above
		if  {
			.popAndDiscardScope()
		}

		return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}
	}

	.popScope()
Only declare the function after we know if it had a body or not. Otherwise TypeScript code such as this will double-declare the symbol: function foo(): void; function foo(): void {}
	if  != nil {
		 := js_ast.SymbolHoistedFunction
		if  ||  {
			 = js_ast.SymbolGeneratorOrAsyncFunction
		}
		.Ref = .declareSymbol(, .Loc, )
	}
Balance the fake block scope introduced above
	if  {
		.popScope()
	}

	.HasIfScope = 
	return js_ast.Stmt{Loc: , Data: &js_ast.SFunction{Fn: , IsExport: .isExport}}
}

type deferredTSDecorators struct {
	values []js_ast.Expr
If this turns out to be a "declare class" statement, we need to undo the scopes that were potentially pushed while parsing the decorator arguments.
TypeScript decorators only work on class declarations "@decorator export class Foo {}" "@decorator export abstract class Foo {}" "@decorator export default class Foo {}" "@decorator export default abstract class Foo {}" "@decorator export declare class Foo {}" "@decorator export declare abstract class Foo {}"
		if .tsDecorators != nil && .lexer.Token != js_lexer.TClass && .lexer.Token != js_lexer.TDefault &&
			!.lexer.IsContextualKeyword("abstract") && !.lexer.IsContextualKeyword("declare") {
			.lexer.Expected(js_lexer.TClass)
		}

		switch .lexer.Token {
		case js_lexer.TClass, js_lexer.TConst, js_lexer.TFunction, js_lexer.TVar:
			.isExport = true
			return .()

"export import foo = bar"
			if .options.ts.Parse && (.isModuleScope || .isNamespaceScope) {
				.isExport = true
				return .()
			}

			.lexer.Unexpected()
			return js_ast.Stmt{}

		case js_lexer.TEnum:
			if !.options.ts.Parse {
				.lexer.Unexpected()
			}
			.isExport = true
			return .()

		case js_lexer.TIdentifier:
			if .lexer.IsContextualKeyword("let") {
				.isExport = true
				return .()
			}

"export as namespace ns;"
"export async function foo() {}"
				 := .lexer.Range()
				.lexer.Next()
				if .lexer.HasNewlineBefore {
					.log.AddError(&.source, logger.Loc{Start: .End()}, "Unexpected newline after \"async\"")
					panic(js_lexer.LexerPanic{})
				}
				.lexer.Expect(js_lexer.TFunction)
				.isExport = true
				return .parseFnStmt(, , true /* isAsync */, )
			}

			if .options.ts.Parse {
				switch .lexer.Identifier {
"export type foo = ..."
					 := .lexer.Range()
					.lexer.Next()
					if .lexer.HasNewlineBefore {
						.log.AddError(&.source, logger.Loc{Start: .End()}, "Unexpected newline after \"type\"")
						panic(js_lexer.LexerPanic{})
					}
					.skipTypeScriptTypeStmt(parseStmtOpts{isModuleScope: .isModuleScope, isExport: true})
					return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}

"export namespace Foo {}" "export abstract class Foo {}" "export module Foo {}" "export interface Foo {}"
					.isExport = true
					return .()

"export declare class Foo {}"
					.isExport = true
					.lexicalDecl = lexicalDeclAllowAll
					.isTypeScriptDeclare = true
					return .()
				}
			}

			.lexer.Unexpected()
			return js_ast.Stmt{}

		case js_lexer.TDefault:
			if !.isModuleScope && (!.isNamespaceScope || !.isTypeScriptDeclare) {
				.lexer.Unexpected()
			}

			 := .lexer.Loc()
			.lexer.Next()
The default name is lazily generated only if no other name is present
			 := func() js_ast.LocRef {
				 := js_ast.LocRef{Loc: , Ref: .newSymbol(js_ast.SymbolOther, .source.IdentifierName+"_default")}
				.currentScope.Generated = append(.currentScope.Generated, .Ref)
				return 
			}
TypeScript decorators only work on class declarations "@decorator export default class Foo {}" "@decorator export default abstract class Foo {}"
			if .tsDecorators != nil && .lexer.Token != js_lexer.TClass && !.lexer.IsContextualKeyword("abstract") {
				.lexer.Expected(js_lexer.TClass)
			}

			if .lexer.IsContextualKeyword("async") {
				 := .lexer.Range()
				.lexer.Next()

				if .lexer.Token == js_lexer.TFunction && !.lexer.HasNewlineBefore {
					.lexer.Next()
					 := .parseFnStmt(, parseStmtOpts{
						isNameOptional: true,
						lexicalDecl:    lexicalDeclAllowAll,
					}, true /* isAsync */, )
					if ,  := .Data.(*js_ast.STypeScript);  {
						return  // This was just a type annotation
					}
Use the statement name if present, since it's a better name
					var  js_ast.LocRef
					if ,  := .Data.(*js_ast.SFunction);  && .Fn.Name != nil {
						 = js_ast.LocRef{Loc: , Ref: .Fn.Name.Ref}
					} else {
						 = ()
					}

					return js_ast.Stmt{Loc: , Data: &js_ast.SExportDefault{DefaultName: , Value: js_ast.ExprOrStmt{Stmt: &}}}
				}

				 := ()
				 := .parseSuffix(.parseAsyncPrefixExpr(, js_ast.LComma), js_ast.LComma, nil, 0)
				.lexer.ExpectOrInsertSemicolon()
				return js_ast.Stmt{Loc: , Data: &js_ast.SExportDefault{DefaultName: , Value: js_ast.ExprOrStmt{Expr: &}}}
			}

			if .lexer.Token == js_lexer.TFunction || .lexer.Token == js_lexer.TClass || .lexer.IsContextualKeyword("interface") {
				 := .(parseStmtOpts{
					tsDecorators:   .tsDecorators,
					isNameOptional: true,
					lexicalDecl:    lexicalDeclAllowAll,
				})
				if ,  := .Data.(*js_ast.STypeScript);  {
					return  // This was just a type annotation
				}
Use the statement name if present, since it's a better name
				var  js_ast.LocRef
				switch s := .Data.(type) {
				case *js_ast.SFunction:
					if .Fn.Name != nil {
						 = js_ast.LocRef{Loc: , Ref: .Fn.Name.Ref}
					} else {
						 = ()
					}
				case *js_ast.SClass:
					if .Class.Name != nil {
						 = js_ast.LocRef{Loc: , Ref: .Class.Name.Ref}
					} else {
						 = ()
					}
				default:
					panic("Internal error")
				}

				return js_ast.Stmt{Loc: , Data: &js_ast.SExportDefault{DefaultName: , Value: js_ast.ExprOrStmt{Stmt: &}}}
			}

			 := .lexer.Token == js_lexer.TIdentifier
			 := .lexer.Identifier
			 := .parseExpr(js_ast.LComma)
Handle the default export of an abstract class in TypeScript
			if .options.ts.Parse &&  &&  == "abstract" {
				if ,  := .Data.(*js_ast.EIdentifier);  && (.lexer.Token == js_lexer.TClass || .tsDecorators != nil) {
					 := .parseClassStmt(, parseStmtOpts{
						tsDecorators:   .tsDecorators,
						isNameOptional: true,
					})
Use the statement name if present, since it's a better name
					var  js_ast.LocRef
					if ,  := .Data.(*js_ast.SClass);  && .Class.Name != nil {
						 = js_ast.LocRef{Loc: , Ref: .Class.Name.Ref}
					} else {
						 = ()
					}

					return js_ast.Stmt{Loc: , Data: &js_ast.SExportDefault{DefaultName: , Value: js_ast.ExprOrStmt{Stmt: &}}}
				}
			}

			.lexer.ExpectOrInsertSemicolon()
			 := ()
			return js_ast.Stmt{Loc: , Data: &js_ast.SExportDefault{DefaultName: , Value: js_ast.ExprOrStmt{Expr: &}}}

		case js_lexer.TAsterisk:
			if !.isModuleScope && (!.isNamespaceScope || !.isTypeScriptDeclare) {
				.lexer.Unexpected()
			}

			.lexer.Next()
			var  js_ast.Ref
			var  *js_ast.ExportStarAlias
			var  logger.Loc
			var  string

"export * as ns from 'path'"
				.lexer.Next()
				 := .lexer.Identifier
				 = .storeNameInRef()
				 = &js_ast.ExportStarAlias{Loc: .lexer.Loc(), OriginalName: }
				if !.lexer.IsIdentifierOrKeyword() {
					.lexer.Expect(js_lexer.TIdentifier)
				}
				.checkForNonBMPCodePoint(.Loc, )
				.lexer.Next()
				.lexer.ExpectContextualKeyword("from")
				,  = .parsePath()
"export * from 'path'"
				.lexer.ExpectContextualKeyword("from")
				,  = .parsePath()
				 := js_ast.GenerateNonUniqueNameFromPath() + "_star"
				 = .storeNameInRef()
			}
			 := .addImportRecord(ast.ImportStmt, , )

			.lexer.ExpectOrInsertSemicolon()
			return js_ast.Stmt{Loc: , Data: &js_ast.SExportStar{
				NamespaceRef:      ,
				Alias:             ,
				ImportRecordIndex: ,
			}}

		case js_lexer.TOpenBrace:
			if !.isModuleScope && (!.isNamespaceScope || !.isTypeScriptDeclare) {
				.lexer.Unexpected()
			}

			,  := .parseExportClause()
			if .lexer.IsContextualKeyword("from") {
				.lexer.Next()
				,  := .parsePath()
				 := .addImportRecord(ast.ImportStmt, , )
				 := "import_" + js_ast.GenerateNonUniqueNameFromPath()
				 := .storeNameInRef()
				.lexer.ExpectOrInsertSemicolon()
				return js_ast.Stmt{Loc: , Data: &js_ast.SExportFrom{
					Items:             ,
					NamespaceRef:      ,
					ImportRecordIndex: ,
					IsSingleLine:      ,
				}}
			}
			.lexer.ExpectOrInsertSemicolon()
			return js_ast.Stmt{Loc: , Data: &js_ast.SExportClause{Items: , IsSingleLine: }}

"export = value;"
			.es6ExportKeyword =  // This wasn't an ESM export statement after all
			if .options.ts.Parse {
				.lexer.Next()
				 := .parseExpr(js_ast.LLowest)
				.lexer.ExpectOrInsertSemicolon()
				return js_ast.Stmt{Loc: , Data: &js_ast.SExportEquals{Value: }}
			}
			.lexer.Unexpected()
			return js_ast.Stmt{}

		default:
			.lexer.Unexpected()
			return js_ast.Stmt{}
		}

	case js_lexer.TFunction:
		.lexer.Next()
		return .parseFnStmt(, , false /* isAsync */, logger.Range{})

	case js_lexer.TEnum:
		if !.options.ts.Parse {
			.lexer.Unexpected()
		}
		return .parseTypeScriptEnumStmt(, )

Parse decorators before class statements, which are potentially exported
		if .options.ts.Parse {
			 := len(.scopesInOrder)
			 := .parseTypeScriptDecorators()
If this turns out to be a "declare class" statement, we need to undo the scopes that were potentially pushed while parsing the decorator arguments. That can look like any one of the following: "@decorator declare class Foo {}" "@decorator declare abstract class Foo {}" "@decorator export declare class Foo {}" "@decorator export declare abstract class Foo {}"
			.tsDecorators = &deferredTSDecorators{
				values:     ,
				scopeIndex: ,
			}
"@decorator class Foo {}" "@decorator abstract class Foo {}" "@decorator declare class Foo {}" "@decorator declare abstract class Foo {}" "@decorator export class Foo {}" "@decorator export abstract class Foo {}" "@decorator export declare class Foo {}" "@decorator export declare abstract class Foo {}" "@decorator export default class Foo {}" "@decorator export default abstract class Foo {}"
			if .lexer.Token != js_lexer.TClass && .lexer.Token != js_lexer.TExport &&
				!.lexer.IsContextualKeyword("abstract") && !.lexer.IsContextualKeyword("declare") {
				.lexer.Expected(js_lexer.TClass)
			}

			return .()
		}

		.lexer.Unexpected()
		return js_ast.Stmt{}

	case js_lexer.TClass:
		if .lexicalDecl != lexicalDeclAllowAll {
			.forbidLexicalDecl()
		}
		return .parseClassStmt(, )

	case js_lexer.TVar:
		.lexer.Next()
		 := .parseAndDeclareDecls(js_ast.SymbolHoisted, )
		.lexer.ExpectOrInsertSemicolon()
		return js_ast.Stmt{Loc: , Data: &js_ast.SLocal{
			Kind:     js_ast.LocalVar,
			Decls:    ,
			IsExport: .isExport,
		}}

	case js_lexer.TConst:
		if .lexicalDecl != lexicalDeclAllowAll {
			.forbidLexicalDecl()
		}
		.markSyntaxFeature(compat.Const, .lexer.Range())
		.lexer.Next()

		if .options.ts.Parse && .lexer.Token == js_lexer.TEnum {
			return .parseTypeScriptEnumStmt(, )
		}

		 := .parseAndDeclareDecls(js_ast.SymbolConst, )
		.lexer.ExpectOrInsertSemicolon()
		if !.isTypeScriptDeclare {
			.requireInitializers()
		}
		return js_ast.Stmt{Loc: , Data: &js_ast.SLocal{
			Kind:     js_ast.LocalConst,
			Decls:    ,
			IsExport: .isExport,
		}}

	case js_lexer.TIf:
		.lexer.Next()
		.lexer.Expect(js_lexer.TOpenParen)
		 := .parseExpr(js_ast.LLowest)
		.lexer.Expect(js_lexer.TCloseParen)
		 := .(parseStmtOpts{lexicalDecl: lexicalDeclAllowFnInsideIf})
		var  *js_ast.Stmt = nil
		if .lexer.Token == js_lexer.TElse {
			.lexer.Next()
			 := .(parseStmtOpts{lexicalDecl: lexicalDeclAllowFnInsideIf})
			 = &
		}
		return js_ast.Stmt{Loc: , Data: &js_ast.SIf{Test: , Yes: , No: }}

	case js_lexer.TDo:
		.lexer.Next()
		 := .(parseStmtOpts{})
		.lexer.Expect(js_lexer.TWhile)
		.lexer.Expect(js_lexer.TOpenParen)
		 := .parseExpr(js_ast.LLowest)
		.lexer.Expect(js_lexer.TCloseParen)
This is a weird corner case where automatic semicolon insertion applies even without a newline present
Push a scope so we make sure to prevent any bare identifiers referenced within the body from being renamed. Renaming them might change the semantics of the code.
		.pushScopeForParsePass(js_ast.ScopeWith, )
		 := .(parseStmtOpts{})
		.popScope()

		return js_ast.Stmt{Loc: , Data: &js_ast.SWith{Value: , BodyLoc: , Body: }}

	case js_lexer.TSwitch:
		.lexer.Next()
		.lexer.Expect(js_lexer.TOpenParen)
		 := .parseExpr(js_ast.LLowest)
		.lexer.Expect(js_lexer.TCloseParen)

		 := .lexer.Loc()
		.pushScopeForParsePass(js_ast.ScopeBlock, )
		defer .popScope()

		.lexer.Expect(js_lexer.TOpenBrace)
		 := []js_ast.Case{}
		 := false

		for .lexer.Token != js_lexer.TCloseBrace {
			var  *js_ast.Expr = nil
			 := []js_ast.Stmt{}

			if .lexer.Token == js_lexer.TDefault {
				if  {
					.log.AddRangeError(&.source, .lexer.Range(), "Multiple default clauses are not allowed")
					panic(js_lexer.LexerPanic{})
				}
				 = true
				.lexer.Next()
				.lexer.Expect(js_lexer.TColon)
			} else {
				.lexer.Expect(js_lexer.TCase)
				 := .parseExpr(js_ast.LLowest)
				 = &
				.lexer.Expect(js_lexer.TColon)
			}

		:
			for {
				switch .lexer.Token {
				case js_lexer.TCloseBrace, js_lexer.TCase, js_lexer.TDefault:
					break 

				default:
					 = append(, .(parseStmtOpts{lexicalDecl: lexicalDeclAllowAll}))
				}
			}

			 = append(, js_ast.Case{Value: , Body: })
		}

		.lexer.Expect(js_lexer.TCloseBrace)
		return js_ast.Stmt{Loc: , Data: &js_ast.SSwitch{
			Test:    ,
			BodyLoc: ,
			Cases:   ,
		}}

	case js_lexer.TTry:
		.lexer.Next()
		 := .lexer.Loc()
		.lexer.Expect(js_lexer.TOpenBrace)
		.pushScopeForParsePass(js_ast.ScopeBlock, )
		 := .parseStmtsUpTo(js_lexer.TCloseBrace, parseStmtOpts{})
		.popScope()
		.lexer.Next()

		var  *js_ast.Catch = nil
		var  *js_ast.Finally = nil

		if .lexer.Token == js_lexer.TCatch {
			 := .lexer.Loc()
			.pushScopeForParsePass(js_ast.ScopeBlock, )
			.lexer.Next()
			var  *js_ast.Binding
The catch binding is optional, and can be omitted
Generate a new symbol for the catch binding for older browsers
Bare identifiers are a special case
				 := js_ast.SymbolOther
				if ,  := .Data.(*js_ast.BIdentifier);  {
					 = js_ast.SymbolCatchIdentifier
				}
				.declareBinding(, , parseStmtOpts{})
				 = &
			}

			.lexer.Expect(js_lexer.TOpenBrace)
			 := .parseStmtsUpTo(js_lexer.TCloseBrace, parseStmtOpts{})
			.lexer.Next()
			 = &js_ast.Catch{Loc: , Binding: , Body: }
			.popScope()
		}

		if .lexer.Token == js_lexer.TFinally ||  == nil {
			 := .lexer.Loc()
			.pushScopeForParsePass(js_ast.ScopeBlock, )
			.lexer.Expect(js_lexer.TFinally)
			.lexer.Expect(js_lexer.TOpenBrace)
			 := .parseStmtsUpTo(js_lexer.TCloseBrace, parseStmtOpts{})
			.lexer.Next()
			 = &js_ast.Finally{Loc: , Stmts: }
			.popScope()
		}

		return js_ast.Stmt{Loc: , Data: &js_ast.STry{
			BodyLoc: ,
			Body:    ,
			Catch:   ,
			Finally: ,
		}}

	case js_lexer.TFor:
		.pushScopeForParsePass(js_ast.ScopeBlock, )
		defer .popScope()

		.lexer.Next()
"for await (let x of y) {}"
		 := .lexer.IsContextualKeyword("await")
		if  {
			 := .lexer.Range()
			if !.fnOrArrowDataParse.allowAwait {
				.log.AddRangeError(&.source, , "Cannot use \"await\" outside an async function")
				 = false
			} else {
				 := .markSyntaxFeature(compat.ForAwait, )
				if .fnOrArrowDataParse.isTopLevel && ! {
					.topLevelAwaitKeyword = 
					.markSyntaxFeature(compat.TopLevelAwait, )
				}
			}
			.lexer.Next()
		}

		.lexer.Expect(js_lexer.TOpenParen)

		var  *js_ast.Stmt = nil
		var  *js_ast.Expr = nil
		var  *js_ast.Expr = nil
"in" expressions aren't allowed here
		.allowIn = false

		var  logger.Range
		if .lexer.IsContextualKeyword("let") {
			 = .lexer.Range()
		}
		 := []js_ast.Decl{}
		 := .lexer.Loc()
		 := false
		switch .lexer.Token {
		case js_lexer.TVar:
			 = true
			.lexer.Next()
			 = .parseAndDeclareDecls(js_ast.SymbolHoisted, parseStmtOpts{})
			 = &js_ast.Stmt{Loc: , Data: &js_ast.SLocal{Kind: js_ast.LocalVar, Decls: }}

		case js_lexer.TConst:
			.markSyntaxFeature(compat.Const, .lexer.Range())
			.lexer.Next()
			 = .parseAndDeclareDecls(js_ast.SymbolConst, parseStmtOpts{})
			 = &js_ast.Stmt{Loc: , Data: &js_ast.SLocal{Kind: js_ast.LocalConst, Decls: }}

		case js_lexer.TSemicolon:

		default:
			var  js_ast.Expr
			var  js_ast.Stmt
			, ,  = .parseExprOrLetStmt(parseStmtOpts{lexicalDecl: lexicalDeclAllowAll})
			if .Data != nil {
				 = logger.Range{}
				 = &
			} else {
				 = &js_ast.Stmt{Loc: , Data: &js_ast.SExpr{Value: }}
			}
		}
"in" expressions are allowed again
Detect for-of loops
		if .lexer.IsContextualKeyword("of") ||  {
			if .Len > 0 {
				.log.AddRangeError(&.source, , "\"let\" must be wrapped in parentheses to be used as an expression here")
			}
			if  && !.lexer.IsContextualKeyword("of") {
				if  != nil {
					.lexer.ExpectedString("\"of\"")
				} else {
					.lexer.Unexpected()
				}
			}
			.forbidInitializers(, "of", false)
			.markSyntaxFeature(compat.ForOf, .lexer.Range())
			.lexer.Next()
			 := .parseExpr(js_ast.LComma)
			.lexer.Expect(js_lexer.TCloseParen)
			 := .(parseStmtOpts{})
			return js_ast.Stmt{Loc: , Data: &js_ast.SForOf{IsAwait: , Init: *, Value: , Body: }}
		}
Detect for-in loops
		if .lexer.Token == js_lexer.TIn {
			.forbidInitializers(, "in", )
			.lexer.Next()
			 := .parseExpr(js_ast.LLowest)
			.lexer.Expect(js_lexer.TCloseParen)
			 := .(parseStmtOpts{})
			return js_ast.Stmt{Loc: , Data: &js_ast.SForIn{Init: *, Value: , Body: }}
		}
Only require "const" statement initializers when we know we're a normal for loop
		if  != nil {
			if ,  := .Data.(*js_ast.SLocal);  && .Kind == js_ast.LocalConst {
				.requireInitializers()
			}
		}

		.lexer.Expect(js_lexer.TSemicolon)

		if .lexer.Token != js_lexer.TSemicolon {
			 := .parseExpr(js_ast.LLowest)
			 = &
		}

		.lexer.Expect(js_lexer.TSemicolon)

		if .lexer.Token != js_lexer.TCloseParen {
			 := .parseExpr(js_ast.LLowest)
			 = &
		}

		.lexer.Expect(js_lexer.TCloseParen)
		 := .(parseStmtOpts{})
		return js_ast.Stmt{Loc: , Data: &js_ast.SFor{Init: , Test: , Update: , Body: }}

	case js_lexer.TImport:
		 := .es6ImportKeyword
		.es6ImportKeyword = .lexer.Range()
		.lexer.Next()
		 := js_ast.SImport{}
		 := false
"export import foo = bar" "import foo = bar" in a namespace
"import('path')" "import.meta"
			.es6ImportKeyword =  // This wasn't an ESM import statement after all
			 := .parseSuffix(.parseImportExpr(, js_ast.LLowest), js_ast.LLowest, nil, 0)
			.lexer.ExpectOrInsertSemicolon()
			return js_ast.Stmt{Loc: , Data: &js_ast.SExpr{Value: }}

"import 'path'"
			if !.isModuleScope && (!.isNamespaceScope || !.isTypeScriptDeclare) {
				.lexer.Unexpected()
				return js_ast.Stmt{}
			}

			 = true

"import * as ns from 'path'"
"import {item1, item2} from 'path'"
			if !.isModuleScope && (!.isNamespaceScope || !.isTypeScriptDeclare) {
				.lexer.Unexpected()
				return js_ast.Stmt{}
			}

			,  := .parseImportClause()
			.Items = &
			.IsSingleLine = 
			.lexer.ExpectContextualKeyword("from")

"import defaultItem from 'path'" "import foo = bar"
			if !.isModuleScope && !.isNamespaceScope {
				.lexer.Unexpected()
				return js_ast.Stmt{}
			}

			 := .lexer.Identifier
			.DefaultName = &js_ast.LocRef{Loc: .lexer.Loc(), Ref: .storeNameInRef()}
			.lexer.Next()

Skip over type-only imports
				if  == "type" {
					switch .lexer.Token {
					case js_lexer.TIdentifier:
"import type foo from 'bar';"
"import type {foo} from 'bar';"
Parse TypeScript import assignment statements
				if .lexer.Token == js_lexer.TEquals || .isExport || (.isNamespaceScope && !.isTypeScriptDeclare) {
					.es6ImportKeyword =  // This wasn't an ESM import statement after all
					return .parseTypeScriptImportEqualsStmt(, , .DefaultName.Loc, )
				}
			}

			if .lexer.Token == js_lexer.TComma {
				.lexer.Next()
				switch .lexer.Token {
"import defaultItem, * as ns from 'path'"
"import defaultItem, {item1, item2} from 'path'"
					,  := .parseImportClause()
					.Items = &
					.IsSingleLine = 

				default:
					.lexer.Unexpected()
				}
			}

			.lexer.ExpectContextualKeyword("from")

		default:
			.lexer.Unexpected()
			return js_ast.Stmt{}
		}

		,  := .parsePath()
		.ImportRecordIndex = .addImportRecord(ast.ImportStmt, , )
		.importRecords[.ImportRecordIndex].WasOriginallyBareImport = 
		.lexer.ExpectOrInsertSemicolon()

		if .StarNameLoc != nil {
			 := .loadNameFromRef(.NamespaceRef)
			.NamespaceRef = .declareSymbol(js_ast.SymbolImport, *.StarNameLoc, )
Generate a symbol for the namespace
Link the default item to the namespace
		if .DefaultName != nil {
			 := .loadNameFromRef(.DefaultName.Ref)
			 := .declareSymbol(js_ast.SymbolImport, .DefaultName.Loc, )
			.isImportItem[] = true
			.DefaultName.Ref = 
		}
Link each import item to the namespace
		if .Items != nil {
			for ,  := range *.Items {
				 := .loadNameFromRef(.Name.Ref)
				 := .declareSymbol(js_ast.SymbolImport, .Name.Loc, )
				.checkForNonBMPCodePoint(.AliasLoc, .Alias)
				.isImportItem[] = true
				(*.Items)[].Name.Ref = 
				[.Alias] = js_ast.LocRef{Loc: .Name.Loc, Ref: }
			}
		}
Track the items for this namespace
		.importItemsForNamespace[.NamespaceRef] = 

		return js_ast.Stmt{Loc: , Data: &}

	case js_lexer.TBreak:
		.lexer.Next()
		 := .parseLabelName()
		.lexer.ExpectOrInsertSemicolon()
		return js_ast.Stmt{Loc: , Data: &js_ast.SBreak{Label: }}

	case js_lexer.TContinue:
		.lexer.Next()
		 := .parseLabelName()
		.lexer.ExpectOrInsertSemicolon()
		return js_ast.Stmt{Loc: , Data: &js_ast.SContinue{Label: }}

	case js_lexer.TReturn:
		.lexer.Next()
		var  *js_ast.Expr
		if .lexer.Token != js_lexer.TSemicolon &&
			!.lexer.HasNewlineBefore &&
			.lexer.Token != js_lexer.TCloseBrace &&
			.lexer.Token != js_lexer.TEndOfFile {
			 := .parseExpr(js_ast.LLowest)
			 = &
		}
		.latestReturnHadSemicolon = .lexer.Token == js_lexer.TSemicolon
		.lexer.ExpectOrInsertSemicolon()
		if .fnOrArrowDataParse.isOutsideFn {
			.hasTopLevelReturn = true
		}
		return js_ast.Stmt{Loc: , Data: &js_ast.SReturn{Value: }}

	case js_lexer.TThrow:
		.lexer.Next()
		if .lexer.HasNewlineBefore {
			.log.AddError(&.source, logger.Loc{Start: .Start + 5}, "Unexpected newline after \"throw\"")
			panic(js_lexer.LexerPanic{})
		}
		 := .parseExpr(js_ast.LLowest)
		.lexer.ExpectOrInsertSemicolon()
		return js_ast.Stmt{Loc: , Data: &js_ast.SThrow{Value: }}

	case js_lexer.TDebugger:
		.lexer.Next()
		.lexer.ExpectOrInsertSemicolon()
		return js_ast.Stmt{Loc: , Data: &js_ast.SDebugger{}}

	case js_lexer.TOpenBrace:
		.pushScopeForParsePass(js_ast.ScopeBlock, )
		defer .popScope()

		.lexer.Next()
		 := .parseStmtsUpTo(js_lexer.TCloseBrace, parseStmtOpts{})
		.lexer.Next()
		return js_ast.Stmt{Loc: , Data: &js_ast.SBlock{Stmts: }}

	default:
		 := .lexer.Token == js_lexer.TIdentifier
		 := .lexer.Identifier
Parse either an async function, an async expression, or a normal expression
		var  js_ast.Expr
		if  && .lexer.Raw() == "async" {
			 := .lexer.Range()
			.lexer.Next()
			if .lexer.Token == js_lexer.TFunction && !.lexer.HasNewlineBefore {
				.lexer.Next()
				return .parseFnStmt(.Loc, , true /* isAsync */, )
			}
			 = .parseSuffix(.parseAsyncPrefixExpr(, js_ast.LLowest), js_ast.LLowest, nil, 0)
		} else {
			var  js_ast.Stmt
			, , _ = .parseExprOrLetStmt()
			if .Data != nil {
				.lexer.ExpectOrInsertSemicolon()
				return 
			}
		}

		if  {
			if ,  := .Data.(*js_ast.EIdentifier);  {
				if .lexer.Token == js_lexer.TColon && .tsDecorators == nil {
					.pushScopeForParsePass(js_ast.ScopeLabel, )
					defer .popScope()
Parse a labeled statement
					.lexer.Next()
					 := js_ast.LocRef{Loc: .Loc, Ref: .Ref}
					 := parseStmtOpts{}
					if .lexicalDecl == lexicalDeclAllowAll || .lexicalDecl == lexicalDeclAllowFnInsideLabel {
						.lexicalDecl = lexicalDeclAllowFnInsideLabel
					}
					 := .()
					return js_ast.Stmt{Loc: , Data: &js_ast.SLabel{Name: , Stmt: }}
				}

				if .options.ts.Parse {
					switch  {
					case "type":
"namespace Foo {}" "module Foo {}" "declare module 'fs' {}" "declare module 'fs';"
"interface Foo {}"
						.skipTypeScriptInterfaceStmt(parseStmtOpts{isModuleScope: .isModuleScope})
						return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}

					case "abstract":
						if .lexer.Token == js_lexer.TClass || .tsDecorators != nil {
							return .parseClassStmt(, )
						}

"declare module 'fs' { global { namespace NodeJS {} } }"
"@decorator declare class Foo {}" "@decorator declare abstract class Foo {}"
"declare global { ... }"
"declare const x: any"
						 := .()
						if .tsDecorators != nil {
							.discardScopesUpTo(.tsDecorators.scopeIndex)
						}
Unlike almost all uses of "declare", statements that use "export declare" with "var/let/const" inside a namespace affect code generation. They cause any declared bindings to be considered exports of the namespace. Identifier references to those names must be converted into property accesses off the namespace object: namespace ns { export declare const x export function y() { return x } } (ns as any).x = 1 console.log(ns.y()) In this example, "return x" must be replaced with "return ns.x". This is handled by replacing each "export declare" statement inside a namespace with an "export var" statement containing all of the declared bindings. That "export var" statement will later cause identifiers to be transformed into property accesses.
						if .isNamespaceScope && .isExport {
							var  []js_ast.Decl
							if ,  := .Data.(*js_ast.SLocal);  {
								for ,  := range .Decls {
									 = extractDeclsForBinding(.Binding, )
								}
							}
							if len() > 0 {
								return js_ast.Stmt{Loc: , Data: &js_ast.SLocal{
									Kind:     js_ast.LocalVar,
									IsExport: true,
									Decls:    ,
								}}
							}
						}

						return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}
					}
				}
			}
		}

		.lexer.ExpectOrInsertSemicolon()
		return js_ast.Stmt{Loc: , Data: &js_ast.SExpr{Value: }}
	}
}

func ( js_ast.Binding,  []js_ast.Decl) []js_ast.Decl {
	switch b := .Data.(type) {
	case *js_ast.BMissing:

	case *js_ast.BIdentifier:
		 = append(, js_ast.Decl{Binding: })

	case *js_ast.BArray:
		for ,  := range .Items {
			 = (.Binding, )
		}

	case *js_ast.BObject:
		for ,  := range .Properties {
			 = (.Value, )
		}

	default:
		panic("Internal error")
	}

	return 
}

func ( *parser) ( ast.ImportKind,  logger.Loc,  string) uint32 {
	 := uint32(len(.importRecords))
	.importRecords = append(.importRecords, ast.ImportRecord{
		Kind:  ,
		Range: .source.RangeOfString(),
		Path:  logger.Path{Text: },
	})
	return 
}

func ( *parser) ( fnOrArrowDataParse) js_ast.FnBody {
	 := .fnOrArrowDataParse
	 := .allowIn
	.fnOrArrowDataParse = 
	.allowIn = true

	 := .lexer.Loc()
	.pushScopeForParsePass(js_ast.ScopeFunctionBody, )
	defer .popScope()

	.lexer.Expect(js_lexer.TOpenBrace)
	 := .parseStmtsUpTo(js_lexer.TCloseBrace, parseStmtOpts{})
	.lexer.Next()

	.allowIn = 
	.fnOrArrowDataParse = 
	return js_ast.FnBody{Loc: , Stmts: }
}

func ( *parser) ( logger.Loc) {
	 := js_lexer.RangeOfIdentifier(.source, )
	.log.AddRangeError(&.source, , "Cannot use a declaration in a single-statement context")
}

func ( *parser) ( js_lexer.T,  parseStmtOpts) []js_ast.Stmt {
	 := []js_ast.Stmt{}
	 := int32(-1)
	.lexicalDecl = lexicalDeclAllowAll
	 := true

Preserve some statement-level comments
		 := .lexer.CommentsToPreserveBefore
		if len() > 0 {
			for ,  := range  {
				 = append(, js_ast.Stmt{
					Loc:  .Loc,
					Data: &js_ast.SComment{Text: .Text},
				})
			}
		}

		if .lexer.Token ==  {
			break
		}

		 := .parseStmt()
Skip TypeScript types entirely
		if .options.ts.Parse {
			if ,  := .Data.(*js_ast.STypeScript);  {
				continue
			}
		}
Parse one or more directives at the beginning
		if  {
			 = false
			if ,  := .Data.(*js_ast.SExpr);  {
				if ,  := .Value.Data.(*js_ast.EString);  && !.PreferTemplate {
					.Data = &js_ast.SDirective{Value: .Value, LegacyOctalLoc: .LegacyOctalLoc}
					 = true

Track "use strict" directives
Deliberately remove "use asm" directives. The asm.js subset of JavaScript has complicated validation rules that are triggered by this directive. This parser is not designed with asm.js in mind and round-tripping asm.js code through esbuild will very likely cause it to no longer validate as asm.js. When this happens, V8 prints a warning and people don't like seeing the warning. We deliberately do not attempt to preserve the validity of asm.js code because it's a complicated legacy format and it's obsolete now that WebAssembly exists. By removing this directive it will just become normal JavaScript, which will work fine and won't generate a warning (but will run slower). We don't generate a warning ourselves in this case because there isn't necessarily anything easy and actionable that the user can do to fix this.
						.Data = &js_ast.SEmpty{}
					}
				}
			}
		}

		 = append(, )
Warn about ASI and return statements. Here's an example of code with this problem: https://github.com/rollup/rollup/issues/3729
		if !.options.suppressWarningsAboutWeirdCode {
			if ,  := .Data.(*js_ast.SReturn);  && .Value == nil && !.latestReturnHadSemicolon {
				 = .Loc.Start
			} else {
				if  != -1 {
					if ,  := .Data.(*js_ast.SExpr);  {
						.log.AddWarning(&.source, logger.Loc{Start:  + 6},
							"The following expression is not returned because of an automatically-inserted semicolon")
					}
				}
				 = -1
			}
		}
	}

	return 
}

type generateTempRefArg uint8

const (
	tempRefNeedsDeclare generateTempRefArg = iota
	tempRefNoDeclare
)

func ( *parser) ( generateTempRefArg,  string) js_ast.Ref {
	 := .currentScope
	for !.Kind.StopsHoisting() {
		 = .Parent
	}
	if  == "" {
		 = "_" + js_ast.DefaultNameMinifier.NumberToMinifiedName(.tempRefCount)
		.tempRefCount++
	}
	 := .newSymbol(js_ast.SymbolOther, )
	if  == tempRefNeedsDeclare {
		.tempRefsToDeclare = append(.tempRefsToDeclare, tempRef{ref: })
	}
	.Generated = append(.Generated, )
	return 
}

func ( *parser) ( js_ast.ScopeKind,  logger.Loc) {
	 := .scopesInOrder[0]
Sanity-check that the scopes generated by the first and second passes match
	if .loc !=  || .scope.Kind !=  {
		panic(fmt.Sprintf("Expected scope (%d, %d) in %s, found scope (%d, %d)",
			, .Start,
			.source.PrettyPath,
			.scope.Kind, .loc.Start))
	}

	.scopesInOrder = .scopesInOrder[1:]
	.currentScope = .scope
	.scopesForCurrentPart = append(.scopesForCurrentPart, .scope)
}

type findSymbolResult struct {
	ref               js_ast.Ref
	declareLoc        logger.Loc
	isInsideWithScope bool
}

func ( *parser) ( logger.Loc,  string) findSymbolResult {
	var  js_ast.Ref
	var  logger.Loc
	 := false
	 := false
	 := .currentScope

Track if we're inside a "with" statement body
		if .Kind == js_ast.ScopeWith {
			 = true
		}
Forbid referencing "arguments" inside class bodies
		if .ForbidArguments &&  == "arguments" && ! {
			 := js_lexer.RangeOfIdentifier(.source, )
			.log.AddRangeError(&.source, , fmt.Sprintf("Cannot access %q here", ))
			 = true
		}
Is the symbol a member of this scope?
		if ,  := .Members[];  {
			 = .Ref
			 = .Loc
			break
		}

		 = .Parent
Allocate an "unbound" symbol
			.checkForNonBMPCodePoint(, )
			 = .newSymbol(js_ast.SymbolUnbound, )
			 = 
			.moduleScope.Members[] = js_ast.ScopeMember{Ref: , Loc: logger.Loc{Start: -1}}
			break
		}
	}
If we had to pass through a "with" statement body to get to the symbol declaration, then this reference could potentially also refer to a property on the target object of the "with" statement. We must not rename it or we risk changing the behavior of the code.
	if  {
		.symbols[.InnerIndex].MustNotBeRenamed = true
	}
Track how many times we've referenced this symbol
	.recordUsage()
	return findSymbolResult{, , }
}

func ( *parser) ( logger.Loc,  string) ( js_ast.Ref,  bool,  bool) {
	for  := .currentScope;  != nil && !.Kind.StopsHoisting();  = .Parent {
Track how many times we've referenced this symbol
			.recordUsage(.LabelRef)
			 = .LabelRef
			 = .LabelStmtIsLoop
			 = true
			return
		}
	}

	 := js_lexer.RangeOfIdentifier(.source, )
	.log.AddRangeError(&.source, , fmt.Sprintf("There is no containing label named %q", ))
Allocate an "unbound" symbol
	 = .newSymbol(js_ast.SymbolUnbound, )
Track how many times we've referenced this symbol
	.recordUsage()
	return
}

func ( js_ast.Binding,  []js_ast.Decl) []js_ast.Decl {
	switch b := .Data.(type) {
	case *js_ast.BIdentifier:
		 = append(, js_ast.Decl{Binding: })

	case *js_ast.BArray:
		for ,  := range .Items {
			 = (.Binding, )
		}

	case *js_ast.BObject:
		for ,  := range .Properties {
			 = (.Value, )
		}
	}

	return 
}
If this is in a dead branch, then we want to trim as much dead code as we can. Everything can be trimmed except for hoisted declarations ("var" and "function"), which affect the parent scope. For example: function foo() { if (false) { var x; } x = 1; } We can't trim the entire branch as dead or calling foo() will incorrectly assign to a global variable instead.
func ( js_ast.Stmt) bool {
	switch s := .Data.(type) {
	case *js_ast.SEmpty, *js_ast.SExpr, *js_ast.SThrow, *js_ast.SReturn,
Omit these statements entirely
		return false

	case *js_ast.SLocal:
Omit these statements entirely
			return false
		}
Omit everything except the identifiers
		 := []js_ast.Decl{}
		for ,  := range .Decls {
			 = findIdentifiers(.Binding, )
		}
		.Decls = 
		return true

	case *js_ast.SBlock:
		for ,  := range .Stmts {
			if () {
				return true
			}
		}
		return false

	case *js_ast.SIf:
		return (.Yes) || (.No != nil && (*.No))

	case *js_ast.SWhile:
		return (.Body)

	case *js_ast.SDoWhile:
		return (.Body)

	case *js_ast.SFor:
		return (.Init != nil && (*.Init)) || (.Body)

	case *js_ast.SForIn:
		return (.Init) || (.Body)

	case *js_ast.SForOf:
		return (.Init) || (.Body)

	case *js_ast.SLabel:
		return (.Stmt)

Everything else must be kept
		return true
	}
}

type prependTempRefsOpts struct {
	fnBodyLoc *logger.Loc
	kind      stmtsKind
}

func ( *parser) ( []js_ast.Stmt,  prependTempRefsOpts) []js_ast.Stmt {
	 := .tempRefsToDeclare
	 := .tempRefCount
	.tempRefsToDeclare = nil
	.tempRefCount = 0

	 = .visitStmts(, .kind)
Prepend values for "this" and "arguments"
Prepend the generated temporary variables to the beginning of the statement list
	if len(.tempRefsToDeclare) > 0 {
		 := []js_ast.Decl{}
		for ,  := range .tempRefsToDeclare {
			 = append(, js_ast.Decl{Binding: js_ast.Binding{Data: &js_ast.BIdentifier{Ref: .ref}}, Value: .value})
			.recordDeclaredSymbol(.ref)
		}
If the first statement is a super() call, make sure it stays that way
		 := js_ast.Stmt{Data: &js_ast.SLocal{Kind: js_ast.LocalVar, Decls: }}
		if len() > 0 && js_ast.IsSuperCall([0]) {
			 = append([]js_ast.Stmt{[0], }, [1:]...)
		} else {
			 = append([]js_ast.Stmt{}, ...)
		}
	}

	.tempRefsToDeclare = 
	.tempRefCount = 
	return 
}

type stmtsKind uint8

const (
	stmtsNormal stmtsKind = iota
	stmtsLoopBody
	stmtsFnBody
)

Save the current control-flow liveness. This represents if we are currently inside an "if (false) { ... }" block.
	 := .isControlFlowDead
Visit all statements first
	 := make([]js_ast.Stmt, 0, len())
	var  []js_ast.Stmt
	var  []js_ast.Stmt
	for ,  := range  {
		switch s := .Data.(type) {
TypeScript "export = value;" becomes "module.exports = value;". This must happen at the end after everything is parsed because TypeScript moves this statement to the end when it generates code.
			 = .visitAndAppendStmt(, )
			continue

Manually hoist block-level function declarations to preserve semantics. This is only done for function declarations that are not generators or async functions, since this is a backwards-compatibility hack from Annex B of the JavaScript standard.
			if !.currentScope.Kind.StopsHoisting() && .symbols[int(.Fn.Name.Ref.InnerIndex)].Kind == js_ast.SymbolHoistedFunction {
				 = .visitAndAppendStmt(, )
				continue
			}
		}
		 = .visitAndAppendStmt(, )
	}
Transform block-level function declarations into variable declarations
	if len() > 0 {
		var  []js_ast.Decl
		var  []js_ast.Decl
		var  []js_ast.Stmt
		 := make(map[js_ast.Ref]int)
		for ,  := range  {
			,  := .Data.(*js_ast.SFunction)
We may get non-function statements here in certain scenarious such as when "KeepNames" is enabled
				 = append(, )
				continue
			}
			,  := [.Fn.Name.Ref]
			if ! {
				 = len()
				[.Fn.Name.Ref] = 
				 = append(, js_ast.Decl{Binding: js_ast.Binding{
					Loc: .Fn.Name.Loc, Data: &js_ast.BIdentifier{Ref: .Fn.Name.Ref}}})
Also write the function to the hoisted sibling symbol if applicable
				if ,  := .hoistedRefForSloppyModeBlockFn[.Fn.Name.Ref];  {
					.recordUsage(.Fn.Name.Ref)
					 = append(, js_ast.Decl{
						Binding: js_ast.Binding{Loc: .Fn.Name.Loc, Data: &js_ast.BIdentifier{Ref: }},
						Value:   &js_ast.Expr{Loc: .Fn.Name.Loc, Data: &js_ast.EIdentifier{Ref: .Fn.Name.Ref}},
					})
				}
			}
The last function statement for a given symbol wins
			.Fn.Name = nil
			[].Value = &js_ast.Expr{Loc: .Loc, Data: &js_ast.EFunction{Fn: .Fn}}
		}
Reuse memory from "before"
		 := js_ast.LocalLet
		if .options.unsupportedJSFeatures.Has(compat.Let) {
			 = js_ast.LocalVar
		}
		 = append([:0], js_ast.Stmt{Loc: [0].Value.Loc, Data: &js_ast.SLocal{Kind: , Decls: }})
Potentially relocate "var" declarations to the top level
			if ,  := .maybeRelocateVarsToTopLevel(, relocateVarsNormal);  {
				if .Data != nil {
					 = append(, )
				}
			} else {
				 = append(, js_ast.Stmt{Loc: [0].Value.Loc, Data: &js_ast.SLocal{Kind: js_ast.LocalVar, Decls: }})
			}
		}
		 = append(, ...)
		 = append(, ...)
	}
Move TypeScript "export =" statements to the end
	 = append(, ...)
Restore the current control-flow liveness if it was changed inside the loop above. This is important because the caller will not restore it.
	.isControlFlowDead = 
Stop now if we're not mangling
	if !.options.mangleSyntax {
		return 
	}
If this is in a dead branch, trim as much dead code as we can
	if .isControlFlowDead {
		 := 0
		for ,  := range  {
			if !shouldKeepStmtInDeadControlFlow() {
				continue
			}
Merge adjacent var statements
			if ,  := .Data.(*js_ast.SLocal);  && .Kind == js_ast.LocalVar &&  > 0 {
				 := [-1]
				if ,  := .Data.(*js_ast.SLocal);  && .Kind == js_ast.LocalVar && .IsExport == .IsExport {
					.Decls = append(.Decls, .Decls...)
					continue
				}
			}

			[] = 
			++
		}
		return [:]
	}

	return .mangleStmts(, )
}

When minifying, strip all directives other than "use strict" since that should be the only one that is ever really used by engines in practice. We don't support "use asm" even though that's also technically used in practice because the rest of our minifier would likely cause asm.js code to fail validation anyway.
	return js_lexer.UTF16EqualsString(.Value, "use strict")
}

Merge adjacent statements during mangling
	 := make([]js_ast.Stmt, 0, len())
	 := false
	for ,  := range  {
Strip unnecessary statements if the control flow is dead here
			continue
		}
Inline single-use variable declarations where possible: // Before let x = fn(); return x.y(); // After return fn().y(); The declaration must not be exported. We can't just check for the "export" keyword because something might do "export {id};" later on. Instead we just ignore all top-level declarations for now. That means this optimization currently only applies in nested scopes. Ignore declarations if the scope is shadowed by a direct "eval" call. The eval'd code may indirectly reference this symbol and the actual use count may be greater than 1.
Keep inlining variables until a failure or until there are none left. That handles cases like this: // Before let x = fn(); let y = x.prop; return y; // After return fn().prop;
Ignore "var" declarations since those have function-level scope and we may not have visited all of their uses yet by this point. We should have visited all the uses of "let" and "const" declarations by now since they are scoped to this block which we just finished visiting.
The variable must be initialized, since we will be substituting the value into the usage.
The binding must be an identifier that is only used once. Ignore destructuring bindings since that's not the simple case. Destructuring bindings could potentially execute side-effecting code which would invalidate reordering.
Try to substitute the identifier with the initializer. This will fail if something with side effects is in between the declaration and the usage.
Remove the previous declaration, since the substitution was successful.
								if len(.Decls) == 1 {
									 = [:len()-1]
								} else {
									.Decls = .Decls[:len(.Decls)-1]
								}
Loop back to try again
								continue
							}
						}
					}
				}
Substitution failed so stop trying
				break
			}
		}

		switch s := .Data.(type) {
Strip empty statements
			continue

		case *js_ast.SDirective:
			if !isDirectiveSupported() {
				continue
			}

Merge adjacent local statements
			if len() > 0 {
				 := [len()-1]
				if ,  := .Data.(*js_ast.SLocal);  && .Kind == .Kind && .IsExport == .IsExport {
					.Decls = append(.Decls, .Decls...)
					continue
				}
			}

Merge adjacent expression statements
			if len() > 0 {
				 := [len()-1]
				if ,  := .Data.(*js_ast.SExpr);  && !js_ast.IsSuperCall() {
					.Value = js_ast.JoinWithComma(.Value, .Value)
					.DoesNotAffectTreeShaking = .DoesNotAffectTreeShaking && .DoesNotAffectTreeShaking
					continue
				}
			}

Absorb a previous expression statement
			if len() > 0 {
				 := [len()-1]
				if ,  := .Data.(*js_ast.SExpr);  && !js_ast.IsSuperCall() {
					.Test = js_ast.JoinWithComma(.Value, .Test)
					 = [:len()-1]
				}
			}

Absorb a previous expression statement
			if len() > 0 {
				 := [len()-1]
				if ,  := .Data.(*js_ast.SExpr);  && !js_ast.IsSuperCall() {
					.Test = js_ast.JoinWithComma(.Value, .Test)
					 = [:len()-1]
				}
			}

			if isJumpStatement(.Yes.Data) {
				 := false
Absorb a previous if statement
				if len() > 0 {
					 := [len()-1]
"if (a) break c; if (b) break c;" => "if (a || b) break c;" "if (a) continue c; if (b) continue c;" => "if (a || b) continue c;" "if (a) return c; if (b) return c;" => "if (a || b) return c;" "if (a) throw c; if (b) throw c;" => "if (a || b) throw c;"
						.Test = js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalOr, .Test, .Test)
						 = [:len()-1]
					}
				}
"while (x) { if (y) continue; z(); }" => "while (x) { if (!y) z(); }" "while (x) { if (y) continue; else z(); w(); }" => "while (x) { if (!y) { z(); w(); } }" => "for (; x;) !y && (z(), w());"
				if  == stmtsLoopBody {
					if ,  := .Yes.Data.(*js_ast.SContinue);  && .Label == nil {
						 = true
					}
				}
"let x = () => { if (y) return; z(); };" => "let x = () => { if (!y) z(); };" "let x = () => { if (y) return; else z(); w(); };" => "let x = () => { if (!y) { z(); w(); } };" => "let x = () => { !y && (z(), w()); };"
				if  == stmtsFnBody {
					if ,  := .Yes.Data.(*js_ast.SReturn);  && .Value == nil {
						 = true
					}
				}

				if  {
					var  []js_ast.Stmt
					if .No != nil {
						 = append(, *.No)
					}
					 = append(, [+1:]...)
Don't do this transformation if the branch condition could potentially access symbols declared later on on this scope below. If so, inverting the branch condition and nesting statements after this in a block would break that access which is a behavior change. // This transformation is incorrect if (a()) return; function a() {} if (!a()) { function a() {} } // This transformation is incorrect if (a(() => b)) return; let b; if (a(() => b)) { let b; }
					 := true
					for ,  := range  {
						if statementCaresAboutScope() {
							 = false
							break
						}
					}

					if  {
						 = .(, )
						 := .Yes.Loc
						if len() > 0 {
							 = [0].Loc
						}
						return .mangleIf(, .Loc, &js_ast.SIf{
							Test: js_ast.Not(.Test),
							Yes:  stmtsToSingleStmt(, ),
						})
					}
				}

"if (a) return b; else if (c) return d; else return e;" => "if (a) return b; if (c) return d; return e;"
					for {
						 = append(, )
						 = *.No
						.No = nil
						var  bool
						,  = .Data.(*js_ast.SIf)
						if ! || !isJumpStatement(.Yes.Data) || .No == nil {
							break
						}
					}
					 = appendIfBodyPreservingScope(, )
					if isJumpStatement(.Data) {
						 = true
					}
					continue
				}
			}

Merge return statements with the previous expression statement
			if len() > 0 && .Value != nil {
				 := [len()-1]
				if ,  := .Data.(*js_ast.SExpr);  {
					 := js_ast.JoinWithComma(.Value, *.Value)
					[len()-1] = js_ast.Stmt{Loc: .Loc, Data: &js_ast.SReturn{Value: &}}
					continue
				}
			}

			 = true

Merge throw statements with the previous expression statement
			if len() > 0 {
				 := [len()-1]
				if ,  := .Data.(*js_ast.SExpr);  {
					[len()-1] = js_ast.Stmt{Loc: .Loc, Data: &js_ast.SThrow{Value: js_ast.JoinWithComma(.Value, .Value)}}
					continue
				}
			}

			 = true

		case *js_ast.SBreak, *js_ast.SContinue:
			 = true

		case *js_ast.SFor:
			if len() > 0 {
				 := [len()-1]
Insert the previous expression into the for loop initializer
					if .Init == nil {
						[len()-1] = 
						.Init = &js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: .Value}}
						continue
					} else if ,  := .Init.Data.(*js_ast.SExpr);  {
						[len()-1] = 
						.Init = &js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: js_ast.JoinWithComma(.Value, .Value)}}
						continue
					}
Insert the previous variable declaration into the for loop initializer if it's a "var" declaration, since the scope doesn't matter due to scope hoisting
					if .Init == nil {
						if ,  := .Data.(*js_ast.SLocal);  && .Kind == js_ast.LocalVar && !.IsExport {
							[len()-1] = 
							.Init = &
							continue
						}
					} else {
						if ,  := .Data.(*js_ast.SLocal);  && .Kind == js_ast.LocalVar && !.IsExport {
							if ,  := .Init.Data.(*js_ast.SLocal);  && .Kind == js_ast.LocalVar {
								[len()-1] = 
								.Init.Data = &js_ast.SLocal{Kind: js_ast.LocalVar, Decls: append(.Decls, .Decls...)}
								continue
							}
						}
					}
				}
			}
		}

		 = append(, )
	}
Drop a trailing unconditional jump statement if applicable
	if len() > 0 {
		switch  {
"while (x) { y(); continue; }" => "while (x) { y(); }"
			if ,  := [len()-1].Data.(*js_ast.SContinue);  && .Label == nil {
				 = [:len()-1]
			}

"function f() { x(); return; }" => "function f() { x(); }"
			if ,  := [len()-1].Data.(*js_ast.SReturn);  && .Value == nil {
				 = [:len()-1]
			}
		}
	}
Merge certain statements in reverse order
	if len() >= 2 {
		 := [len()-1]

"if (a) return b; if (c) return d; return e;" => "return a ? b : c ? d : e;"
		:
			for len() >= 2 {
				 := len() - 2
				 := []

				switch prevS := .Data.(type) {
This return statement must have a value
					if .Value == nil {
						break 
					}
"a(); return b;" => "return a(), b;"
					 := js_ast.JoinWithComma(.Value, *.Value)
					 = &js_ast.SReturn{Value: &}
Merge the last two statements
					 = js_ast.Stmt{Loc: .Loc, Data: }
					[] = 
					 = [:len()-1]

The previous statement must be an if statement with no else clause
					if .No != nil {
						break 
					}
The then clause must be a return
					,  := .Yes.Data.(*js_ast.SReturn)
					if ! {
						break 
					}
Handle some or all of the values being undefined
					 := .Value
					 := .Value
"if (a) return; return b;" => "return a ? void 0 : b;"
						 = &js_ast.Expr{Loc: .Yes.Loc, Data: &js_ast.EUndefined{}}
					}
"if (a) return a; return;" => "return a ? b : void 0;"
						 = &js_ast.Expr{Loc: .Loc, Data: &js_ast.EUndefined{}}
					}
"if (!a) return b; return c;" => "return a ? c : b;"
					if ,  := .Test.Data.(*js_ast.EUnary);  && .Op == js_ast.UnOpNot {
						.Test = .Value
						,  = , 
					}
Handle the returned values being the same
"if (a) return b; return b;" => "return a, b;"
						 := js_ast.JoinWithComma(.Test, *)
						 = &js_ast.SReturn{Value: &}
					} else {
"if (a, b) return c; return d;" => "return a, b ? c : d;"
							 := js_ast.JoinWithComma(.Left, .mangleIfExpr(.Right.Loc, &js_ast.EIf{Test: .Right, Yes: *, No: *}))
							 = &js_ast.SReturn{Value: &}
"if (a) return b; return c;" => "return a ? b : c;"
							 := .mangleIfExpr(.Test.Loc, &js_ast.EIf{Test: .Test, Yes: *, No: *})
							 = &js_ast.SReturn{Value: &}
						}
					}
Merge the last two statements
					 = js_ast.Stmt{Loc: .Loc, Data: }
					[] = 
					 = [:len()-1]

				default:
					break 
				}
			}
"if (a) throw b; if (c) throw d; throw e;" => "throw a ? b : c ? d : e;"
		:
			for len() >= 2 {
				 := len() - 2
				 := []

				switch prevS := .Data.(type) {
"a(); throw b;" => "throw a(), b;"
					 = &js_ast.SThrow{Value: js_ast.JoinWithComma(.Value, .Value)}
Merge the last two statements
					 = js_ast.Stmt{Loc: .Loc, Data: }
					[] = 
					 = [:len()-1]

The previous statement must be an if statement with no else clause
					if .No != nil {
						break 
					}
The then clause must be a throw
					,  := .Yes.Data.(*js_ast.SThrow)
					if ! {
						break 
					}

					 := .Value
					 := .Value
"if (!a) throw b; throw c;" => "throw a ? c : b;"
					if ,  := .Test.Data.(*js_ast.EUnary);  && .Op == js_ast.UnOpNot {
						.Test = .Value
						,  = , 
					}
Merge the last two statements
"if (a, b) return c; return d;" => "return a, b ? c : d;"
						 = &js_ast.SThrow{Value: js_ast.JoinWithComma(.Left, .mangleIfExpr(.Right.Loc, &js_ast.EIf{Test: .Right, Yes: , No: }))}
"if (a) return b; return c;" => "return a ? b : c;"
						 = &js_ast.SThrow{Value: .mangleIfExpr(.Test.Loc, &js_ast.EIf{Test: .Test, Yes: , No: })}
					}
					 = js_ast.Stmt{Loc: .Loc, Data: }
					[] = 
					 = [:len()-1]

				default:
					break 
				}
			}
		}
	}

	return 
}

func ( *parser) ( js_ast.Stmt,  js_ast.Ref,  js_ast.Expr) bool {
	var  *js_ast.Expr

	switch s := .Data.(type) {
	case *js_ast.SExpr:
		 = &.Value
	case *js_ast.SThrow:
		 = &.Value
	case *js_ast.SReturn:
		 = .Value
	case *js_ast.SIf:
		 = &.Test
	case *js_ast.SSwitch:
		 = &.Test
Only try substituting into the initializer for the first declaration
Make sure there isn't destructuring, which could evaluate code
			if ,  := .Binding.Data.(*js_ast.BIdentifier);  {
				 = .Value
			}
		}
	}

Only continue trying to insert this replacement into sub-expressions after the first one if the replacement has no side effects: // Substitution is ok let replacement = 123; return x + replacement; // Substitution is not ok because "fn()" may change "x" let replacement = fn(); return x + replacement; // Substitution is not ok because "x == x" may change "x" due to "valueOf()" evaluation let replacement = [x]; return (x == x) + replacement;
		 := .exprCanBeRemovedIfUnused()

		if ,  := .substituteSingleUseSymbolInExpr(*, , , );  == substituteSuccess {
			* = 
			return true
		}
	}

	return false
}

type substituteStatus uint8

const (
	substituteContinue substituteStatus = iota
	substituteSuccess
	substituteFailure
)

func ( *parser) (
	 js_ast.Expr,
	 js_ast.Ref,
	 js_ast.Expr,
	 bool,
) (js_ast.Expr, substituteStatus) {
	switch e := .Data.(type) {
	case *js_ast.EIdentifier:
		if .Ref ==  {
			.ignoreUsage()
			return , substituteSuccess
		}

	case *js_ast.ESpread:
		if ,  := .(.Value, , , );  != substituteContinue {
			.Value = 
			return , 
		}

	case *js_ast.EAwait:
		if ,  := .(.Value, , , );  != substituteContinue {
			.Value = 
			return , 
		}

	case *js_ast.EYield:
		if .Value != nil {
			if ,  := .(*.Value, , , );  != substituteContinue {
				.Value = &
				return , 
			}
		}

	case *js_ast.EImport:
		if ,  := .(.Expr, , , );  != substituteContinue {
			.Expr = 
			return , 
		}
The "import()" expression has side effects but the side effects are always asynchronous so there is no way for the side effects to modify the replacement value. So it's ok to reorder the replacement value past the "import()" expression assuming everything else checks out.
		if  && .exprCanBeRemovedIfUnused(.Expr) {
			return , substituteContinue
		}

	case *js_ast.EUnary:
		switch .Op {
Do not substitute into an assignment position

		default:
			if ,  := .(.Value, , , );  != substituteContinue {
				.Value = 
				return , 
			}
		}

	case *js_ast.EDot:
		if ,  := .(.Target, , , );  != substituteContinue {
			.Target = 
			return , 
		}

Do not substitute into an assignment position
		if .Op.BinaryAssignTarget() == js_ast.AssignTargetNone {
			if ,  := .(.Left, , , );  != substituteContinue {
				.Left = 
				return , 
			}
Do not reorder past a side effect
			return , substituteFailure
		}
Do not substitute our unconditionally-executed value into a branching short-circuit operator unless the value itself has no side effects
		if  || !.Op.IsShortCircuit() {
			if ,  := .(.Right, , , );  != substituteContinue {
				.Right = 
				return , 
			}
		}

	case *js_ast.EIf:
		if ,  := .(.Test, , , );  != substituteContinue {
			.Test = 
			return , 
		}
Do not substitute our unconditionally-executed value into a branch unless the value itself has no side effects
Unlike other branches in this function such as "a && b" or "a?.[b]", the "a ? b : c" form has potential code evaluation along both control flow paths. Handle this by allowing substitution into either branch. Side effects in one branch should not prevent the substitution into the other branch.

			,  := .(.Yes, , , )
			if  == substituteSuccess {
				.Yes = 
				return , 
			}

			,  := .(.No, , , )
			if  == substituteSuccess {
				.No = 
				return , 
			}
Side effects in either branch should stop us from continuing to try to substitute the replacement after the control flow branches merge again.
			if  != substituteContinue ||  != substituteContinue {
				return , substituteFailure
			}
		}

	case *js_ast.EIndex:
		if ,  := .(.Target, , , );  != substituteContinue {
			.Target = 
			return , 
		}
Do not substitute our unconditionally-executed value into a branch unless the value itself has no side effects
		if  || .OptionalChain == js_ast.OptionalChainNone {
			if ,  := .(.Index, , , );  != substituteContinue {
				.Index = 
				return , 
			}
		}

	case *js_ast.ECall:
		if ,  := .(.Target, , , );  != substituteContinue {
			.Target = 
			return , 
		}
Do not substitute our unconditionally-executed value into a branch unless the value itself has no side effects
		if  || .OptionalChain == js_ast.OptionalChainNone {
			for ,  := range .Args {
				if ,  := .(, , , );  != substituteContinue {
					.Args[] = 
					return , 
				}
			}
		}

	case *js_ast.EArray:
		for ,  := range .Items {
			if ,  := .(, , , );  != substituteContinue {
				.Items[] = 
				return , 
			}
		}

	case *js_ast.EObject:
Check the key
			if .IsComputed {
				if ,  := .(.Key, , , );  != substituteContinue {
					.Properties[].Key = 
					return , 
				}
Stop now because both computed keys and property spread have side effects
				return , substituteFailure
			}
Check the value
			if .Value != nil {
				if ,  := .(*.Value, , , );  != substituteContinue {
					.Properties[].Value = &
					return , 
				}
			}
		}

	case *js_ast.ETemplate:
		if .Tag != nil {
			if ,  := .(*.Tag, , , );  != substituteContinue {
				.Tag = &
				return , 
			}
		}

		for ,  := range .Parts {
			if ,  := .(.Value, , , );  != substituteContinue {
				.Parts[].Value = 
If we substituted a string, merge the string into the template
				if ,  := .Data.(*js_ast.EString);  {
					 = .mangleTemplate(.Loc, )
				}
				return , 
			}
		}
	}
If both the replacement and this expression have no observable side effects, then we can reorder the replacement past this expression
	if  && .exprCanBeRemovedIfUnused() {
		return , substituteContinue
	}
Otherwise we should stop trying to substitute past this point
	return , substituteFailure
}

func ( *parser) ( js_ast.Stmt) js_ast.Stmt {
	 := .fnOrArrowDataVisit.isInsideLoop
	.fnOrArrowDataVisit.isInsideLoop = true
	.loopBody = .Data
	 = .visitSingleStmt(, stmtsLoopBody)
	.fnOrArrowDataVisit.isInsideLoop = 
	return 
}

Introduce a fake block scope for function declarations inside if statements
	,  := .Data.(*js_ast.SFunction)
	 :=  && .Fn.HasIfScope
	if  {
		.pushScopeForVisitPass(js_ast.ScopeBlock, .Loc)
		if .isStrictMode() {
			.markStrictModeFeature(ifElseFunctionStmt, js_lexer.RangeOfIdentifier(.source, .Loc), "")
		}
	}

	 := .visitStmts([]js_ast.Stmt{}, )
Balance the fake block scope introduced above
	if  {
		.popScope()
	}

	return stmtsToSingleStmt(.Loc, )
}
One statement could potentially expand to several statements
func ( logger.Loc,  []js_ast.Stmt) js_ast.Stmt {
	if len() == 0 {
		return js_ast.Stmt{Loc: , Data: &js_ast.SEmpty{}}
	}
"let" and "const" must be put in a block when in a single-statement context
		if ,  := [0].Data.(*js_ast.SLocal); ! || .Kind == js_ast.LocalVar {
			return [0]
		}
	}
	return js_ast.Stmt{Loc: , Data: &js_ast.SBlock{Stmts: }}
}

func ( *parser) ( js_ast.Stmt,  bool) js_ast.Stmt {
	switch s := .Data.(type) {
	case *js_ast.SExpr:
		 := js_ast.AssignTargetNone
		if  {
			 = js_ast.AssignTargetReplace
		}
		.Value, _ = .visitExprInOut(.Value, exprIn{assignTarget: })

	case *js_ast.SLocal:
		for ,  := range .Decls {
			.visitBinding(.Binding, bindingOpts{})
			if .Value != nil {
				*.Value = .visitExpr(*.Value)
			}
		}
		.Decls = .lowerObjectRestInDecls(.Decls)
		.Kind = .selectLocalKind(.Kind)

	default:
		panic("Internal error")
	}

	return 
}

func ( *parser) ( js_ast.Ref) {
	.declaredSymbols = append(.declaredSymbols, js_ast.DeclaredSymbol{
		Ref:        ,
		IsTopLevel: .currentScope == .moduleScope,
	})
}

type bindingOpts struct {
	duplicateArgCheck map[string]bool
}

func ( *parser) ( js_ast.Binding,  bindingOpts) {
	switch b := .Data.(type) {
	case *js_ast.BMissing:

	case *js_ast.BIdentifier:
		.recordDeclaredSymbol(.Ref)
		 := .symbols[.Ref.InnerIndex].OriginalName
		if isEvalOrArguments() {
			.markStrictModeFeature(evalOrArguments, js_lexer.RangeOfIdentifier(.source, .Loc), )
		}
		if .duplicateArgCheck != nil {
			if .duplicateArgCheck[] {
				.log.AddRangeError(&.source, js_lexer.RangeOfIdentifier(.source, .Loc),
					fmt.Sprintf("%q cannot be bound multiple times in the same parameter list", ))
			}
			.duplicateArgCheck[] = true
		}

	case *js_ast.BArray:
		for ,  := range .Items {
			.(.Binding, )
			if .DefaultValue != nil {
				 := .isAnonymousNamedExpr(*.DefaultValue)
				*.DefaultValue = .visitExpr(*.DefaultValue)
Optionally preserve the name
				if ,  := .Binding.Data.(*js_ast.BIdentifier);  {
					*.DefaultValue = .maybeKeepExprSymbolName(
						*.DefaultValue, .symbols[.Ref.InnerIndex].OriginalName, )
				}
			}
		}

	case *js_ast.BObject:
		for ,  := range .Properties {
			if !.IsSpread {
				.Key = .visitExpr(.Key)
			}
			.(.Value, )
			if .DefaultValue != nil {
				 := .isAnonymousNamedExpr(*.DefaultValue)
				*.DefaultValue = .visitExpr(*.DefaultValue)
Optionally preserve the name
				if ,  := .Value.Data.(*js_ast.BIdentifier);  {
					*.DefaultValue = .maybeKeepExprSymbolName(
						*.DefaultValue, .symbols[.Ref.InnerIndex].OriginalName, )
				}
			}
			.Properties[] = 
		}

	default:
		panic("Internal error")
	}
}

func ( js_ast.Stmt) bool {
	switch s := .Data.(type) {
	case *js_ast.SBlock, *js_ast.SEmpty, *js_ast.SDebugger, *js_ast.SExpr, *js_ast.SIf,
		*js_ast.SFor, *js_ast.SForIn, *js_ast.SForOf, *js_ast.SDoWhile, *js_ast.SWhile,
		*js_ast.SWith, *js_ast.STry, *js_ast.SSwitch, *js_ast.SReturn, *js_ast.SThrow,
		*js_ast.SBreak, *js_ast.SContinue, *js_ast.SDirective:
		return false

	case *js_ast.SLocal:
		return .Kind != js_ast.LocalVar

	default:
		return true
	}
}

func ( js_ast.Stmt,  *js_ast.Stmt) js_ast.Stmt {
	if ,  := .Data.(*js_ast.SBlock);  && len(.Stmts) > 0 {
		if  != nil {
			.Stmts[0] = *
		} else if len(.Stmts) == 2 && !statementCaresAboutScope(.Stmts[1]) {
			return .Stmts[1]
		} else {
			.Stmts = .Stmts[1:]
		}
		return 
	}
	if  != nil {
		return *
	}
	return js_ast.Stmt{Loc: .Loc, Data: &js_ast.SEmpty{}}
}

Get the first statement in the loop
	 := .Body
	if ,  := .Data.(*js_ast.SBlock);  && len(.Stmts) > 0 {
		 = .Stmts[0]
	}

"for (;;) if (x) break;" => "for (; !x;) ;" "for (; a;) if (x) break;" => "for (; a && !x;) ;" "for (;;) if (x) break; else y();" => "for (; !x;) y();" "for (; a;) if (x) break; else y();" => "for (; a && !x;) y();"
		if ,  := .Yes.Data.(*js_ast.SBreak);  && .Label == nil {
			var  js_ast.Expr
			if ,  := .Test.Data.(*js_ast.EUnary);  && .Op == js_ast.UnOpNot {
				 = .Value
			} else {
				 = js_ast.Not(.Test)
			}
			if .Test != nil {
				.Test = &js_ast.Expr{Loc: .Test.Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLogicalAnd, Left: *.Test, Right: }}
			} else {
				.Test = &
			}
			.Body = dropFirstStatement(.Body, .No)
			return
		}
"for (;;) if (x) y(); else break;" => "for (; x;) y();" "for (; a;) if (x) y(); else break;" => "for (; a && x;) y();"
		if .No != nil {
			if ,  := .No.Data.(*js_ast.SBreak);  && .Label == nil {
				if .Test != nil {
					.Test = &js_ast.Expr{Loc: .Test.Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLogicalAnd, Left: *.Test, Right: .Test}}
				} else {
					.Test = &.Test
				}
				.Body = dropFirstStatement(.Body, &.Yes)
				return
			}
		}
	}
}

func ( []js_ast.Stmt,  js_ast.Stmt) []js_ast.Stmt {
	if ,  := .Data.(*js_ast.SBlock);  {
		 := false
		for ,  := range .Stmts {
			if statementCaresAboutScope() {
				 = true
				break
			}
		}
		if ! {
			return append(, .Stmts...)
		}
	}

	if statementCaresAboutScope() {
		return append(, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SBlock{Stmts: []js_ast.Stmt{}}})
	}

	return append(, )
}

Constant folding using the test expression
	if , ,  := toBooleanWithSideEffects(.Test.Data);  {
The test is truthy
We can drop the "no" branch
Keep the condition if it could have side effects (but is still known to be truthy)
					if  := .simplifyUnusedExpr(.Test); .Data != nil {
						 = append(, js_ast.Stmt{Loc: .Test.Loc, Data: &js_ast.SExpr{Value: }})
					}
				}
				return appendIfBodyPreservingScope(, .Yes)
We have to keep the "no" branch
			}
The test is falsy
We can drop the "yes" branch
Keep the condition if it could have side effects (but is still known to be falsy)
					if  := .simplifyUnusedExpr(.Test); .Data != nil {
						 = append(, js_ast.Stmt{Loc: .Test.Loc, Data: &js_ast.SExpr{Value: }})
					}
				}
				if .No == nil {
					return 
				}
				return appendIfBodyPreservingScope(, *.No)
We have to keep the "yes" branch
			}
		}
	}

"yes" is an expression
		if .No == nil {
"if (!a) b();" => "a || b();"
"if (a) b();" => "a && b();"
"if (a) b(); else c();" => "a ? b() : c();"
			return append(, js_ast.Stmt{Loc: , Data: &js_ast.SExpr{Value: .mangleIfExpr(, &js_ast.EIf{
				Test: .Test,
				Yes:  .Value,
				No:   .Value,
			})}})
		}
"yes" is missing
"yes" and "no" are both missing
"if (1) {}" => ""
				return 
"if (a) {}" => "a;"
				return append(, js_ast.Stmt{Loc: , Data: &js_ast.SExpr{Value: .Test}})
			}
		} else if ,  := .No.Data.(*js_ast.SExpr);  {
"if (!a) {} else b();" => "a && b();"
"if (a) {} else b();" => "a || b();"
"yes" is missing and "no" is not missing (and is not an expression)
"if (!a) {} else throw b;" => "if (a) throw b;"
				.Test = .Value
				.Yes = *.No
				.No = nil
"if (a) {} else throw b;" => "if (!a) throw b;"
				.Test = js_ast.Not(.Test)
				.Yes = *.No
				.No = nil
			}
		}
"yes" is not missing (and is not an expression)
"yes" is not missing (and is not an expression) and "no" is not missing
"if (!a) return b; else return c;" => "if (a) return c; else return b;"
				.Test = .Value
				.Yes, *.No = *.No, .Yes
			}
"no" is missing
"if (a) if (b) return c;" => "if (a && b) return c;"
				.Test = js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalAnd, .Test, .Test)
				.Yes = .Yes
			}
		}
	}

	return append(, js_ast.Stmt{Loc: , Data: })
}

"(a, b) ? c : d" => "a, b ? c : d"
	if ,  := .Test.Data.(*js_ast.EBinary);  && .Op == js_ast.BinOpComma {
		return js_ast.JoinWithComma(.Left, .(.Right.Loc, &js_ast.EIf{
			Test: .Right,
			Yes:  .Yes,
			No:   .No,
		}))
	}
"!a ? b : c" => "a ? c : b"
	if ,  := .Test.Data.(*js_ast.EUnary);  && .Op == js_ast.UnOpNot {
		.Test = .Value
		.Yes, .No = .No, .Yes
	}

" @__PURE__ a() ? b : b" => "b"
		if .exprCanBeRemovedIfUnused(.Test) {
			return .Yes
		}
"a ? b : b" => "a, b"
		return js_ast.JoinWithComma(.Test, .Yes)
	}
"a ? true : false" => "!!a" "a ? false : true" => "!a"
	if ,  := .Yes.Data.(*js_ast.EBoolean);  {
		if ,  := .No.Data.(*js_ast.EBoolean);  {
			if .Value && !.Value {
				return js_ast.Not(js_ast.Not(.Test))
			}
			if !.Value && .Value {
				return js_ast.Not(.Test)
			}
		}
	}

"a ? a : b" => "a || b"
		if ,  := .Yes.Data.(*js_ast.EIdentifier);  && .Ref == .Ref {
			return js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalOr, .Test, .No)
		}
"a ? b : a" => "a && b"
		if ,  := .No.Data.(*js_ast.EIdentifier);  && .Ref == .Ref {
			return js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalAnd, .Test, .Yes)
		}
	}
"a ? b ? c : d : d" => "a && b ? c : d"
	if ,  := .Yes.Data.(*js_ast.EIf);  && valuesLookTheSame(.No.Data, .No.Data) {
		.Test = js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalAnd, .Test, .Test)
		.Yes = .Yes
		return js_ast.Expr{Loc: , Data: }
	}
"a ? b : c ? b : d" => "a || c ? b : d"
	if ,  := .No.Data.(*js_ast.EIf);  && valuesLookTheSame(.Yes.Data, .Yes.Data) {
		.Test = js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalOr, .Test, .Test)
		.No = .No
		return js_ast.Expr{Loc: , Data: }
	}
"a ? c : (b, c)" => "(a || b), c"
	if ,  := .No.Data.(*js_ast.EBinary);  && .Op == js_ast.BinOpComma && valuesLookTheSame(.Yes.Data, .Right.Data) {
		return js_ast.JoinWithComma(
			js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalOr, .Test, .Left),
			.Right,
		)
	}
"a ? (b, c) : c" => "(a && b), c"
	if ,  := .Yes.Data.(*js_ast.EBinary);  && .Op == js_ast.BinOpComma && valuesLookTheSame(.Right.Data, .No.Data) {
		return js_ast.JoinWithComma(
			js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalAnd, .Test, .Left),
			.Right,
		)
	}
"a ? b || c : c" => "(a && b) || c"
"a ? c : b && c" => "(a || b) && c"
"a ? b(c, d) : b(e, d)" => "b(a ? c : e, d)"
	if ,  := .Yes.Data.(*js_ast.ECall);  && len(.Args) > 0 {
		if ,  := .No.Data.(*js_ast.ECall);  && len(.Args) == len(.Args) &&
Only do this if the condition can be reordered past the call target without side effects. For example, if the test or the call target is an unbound identifier, reordering could potentially mean evaluating the code could throw a different ReferenceError.
			if .exprCanBeRemovedIfUnused(.Test) && .exprCanBeRemovedIfUnused(.Target) {
				 := true
				for ,  := 1, len(.Args);  < ; ++ {
					if !valuesLookTheSame(.Args[].Data, .Args[].Data) {
						 = false
						break
					}
				}
				if  {
					,  := .Args[0].Data.(*js_ast.ESpread)
					,  := .Args[0].Data.(*js_ast.ESpread)
"a ? b(...c) : b(...e)" => "b(...a ? c : e)"
					if  &&  {
						.Yes = .Value
						.No = .Value
						.Args[0] = js_ast.Expr{Loc: , Data: &js_ast.ESpread{Value: .(, )}}
						return js_ast.Expr{Loc: , Data: }
					}
"a ? b(c) : b(e)" => "b(a ? c : e)"
					if ! && ! {
						.Yes = .Args[0]
						.No = .Args[0]
						.Args[0] = .(, )
						return js_ast.Expr{Loc: , Data: }
					}
				}
			}
		}
	}
Try using the "??" operator, but only if it's supported
	if !.options.unsupportedJSFeatures.Has(compat.NullishCoalescing) {
		if ,  := .Test.Data.(*js_ast.EBinary);  {
			switch .Op {
"a == null ? b : a" => "a ?? b"
"null == a ? b : a" => "a ?? b"
"a != null ? a : b" => "a ?? b"
"null != a ? a : b" => "a ?? b"
				if ,  := .Left.Data.(*js_ast.ENull);  && .exprCanBeRemovedIfUnused(.Right) && valuesLookTheSame(.Right.Data, .Yes.Data) {
					return js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpNullishCoalescing, .Right, .No)
				}
			}
		}
	}

	return js_ast.Expr{Loc: , Data: }
}

func ( *parser) ( js_ast.Expr) bool {
	switch e := .Data.(type) {
	case *js_ast.EArrow:
		return true
	case *js_ast.EFunction:
		return .Fn.Name == nil
	case *js_ast.EClass:
		return .Class.Name == nil
	}
	return false
}

func ( *parser) ( js_ast.Expr,  string,  bool) js_ast.Expr {
	if .options.keepNames &&  {
		return .keepExprSymbolName(, )
	}
	return 
}

func ( *parser) ( js_ast.Expr,  string) js_ast.Expr {
	 = .callRuntime(.Loc, "__name", []js_ast.Expr{,
		{Loc: .Loc, Data: &js_ast.EString{Value: js_lexer.StringToUTF16()}},
	})
Make sure tree shaking removes this if the function is never used
	.Data.(*js_ast.ECall).CanBeUnwrappedIfUnused = true
	return 
}

func ( *parser) ( logger.Loc,  js_ast.Ref,  string) js_ast.Stmt {
	return js_ast.Stmt{Loc: , Data: &js_ast.SExpr{
		Value: .callRuntime(, "__name", []js_ast.Expr{
			{Loc: , Data: &js_ast.EIdentifier{Ref: }},
			{Loc: , Data: &js_ast.EString{Value: js_lexer.StringToUTF16()}},
		}),
Make sure tree shaking removes this if the function is never used
		DoesNotAffectTreeShaking: true,
	}}
}

func ( *parser) ( []js_ast.Stmt,  js_ast.Stmt) []js_ast.Stmt {
	switch s := .Data.(type) {
These don't contain anything to traverse

Erase TypeScript constructs from the output completely
"export {foo}"
		 := 0
		for ,  := range .Items {
			 := .loadNameFromRef(.Name.Ref)
			 := .findSymbol(.AliasLoc, ).ref

Silently strip exports of non-local symbols in TypeScript, since those likely correspond to type-only exports. But report exports of non-local symbols as errors in JavaScript.
				if !.options.ts.Parse {
					 := js_lexer.RangeOfIdentifier(.source, .Name.Loc)
					.log.AddRangeError(&.source, , fmt.Sprintf("%q is not declared in this file", ))
				}
				continue
			}

			.Name.Ref = 
			.Items[] = 
			++
		}
Note: do not remove empty export statements since TypeScript uses them as module markers
		.Items = .Items[:]

This is a re-export and the symbols created here are used to reference names in another file. This means the symbols are really aliases.
		for ,  := range .Items {
			 := .loadNameFromRef(.Name.Ref)
			 := .newSymbol(js_ast.SymbolOther, )
			.currentScope.Generated = append(.currentScope.Generated, )
			.recordDeclaredSymbol()
			.Items[].Name.Ref = 
		}

"export * from 'path'" "export * as ns from 'path'"
"export * as ns from 'path'"
Optionally preserve the name
			*.Value.Expr = .maybeKeepExprSymbolName(*.Value.Expr, "default", )
Discard type-only export default statements
			if .options.ts.Parse {
				if ,  := (*.Value.Expr).Data.(*js_ast.EIdentifier);  {
					 := .symbols[.Ref.InnerIndex]
					if .Kind == js_ast.SymbolUnbound && .localTypeNames[.OriginalName] {
						return 
					}
				}
			}

		case .Value.Stmt != nil:
			switch s2 := .Value.Stmt.Data.(type) {
If we need to preserve the name but there is no name, generate a name
				var  string
				if .options.keepNames {
					if .Fn.Name == nil {
						 := .DefaultName
						.Fn.Name = &
						 = "default"
					} else {
						 = .symbols[.Fn.Name.Ref.InnerIndex].OriginalName
					}
				}

				.visitFn(&.Fn, .Fn.OpenParenLoc)
				 = append(, )
Optionally preserve the name
				if .options.keepNames && .Fn.Name != nil {
					 = append(, .keepStmtSymbolName(.Fn.Name.Loc, .Fn.Name.Ref, ))
				}

				return 

			case *js_ast.SClass:
				 := .visitClass(.Value.Stmt.Loc, &.Class)
Lower class field syntax for browsers that don't support it
				,  := .lowerClass(, js_ast.Expr{}, )
				return append(, ...)

			default:
				panic("Internal error")
			}
		}

"module.exports = value"
		 = append(, js_ast.AssignStmt(
			js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
				Target:  js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .moduleRef}},
				Name:    "exports",
				NameLoc: .Loc,
			}},
			.visitExpr(.Value),
		))
		.recordUsage(.moduleRef)
		return 

	case *js_ast.SBreak:
		if .Label != nil {
			 := .loadNameFromRef(.Label.Ref)
			.Label.Ref, _, _ = .findLabelSymbol(.Label.Loc, )
		} else if !.fnOrArrowDataVisit.isInsideLoop && !.fnOrArrowDataVisit.isInsideSwitch {
			 := js_lexer.RangeOfIdentifier(.source, .Loc)
			.log.AddRangeError(&.source, , "Cannot use \"break\" here")
		}

	case *js_ast.SContinue:
		if .Label != nil {
			 := .loadNameFromRef(.Label.Ref)
			var ,  bool
			.Label.Ref, ,  = .findLabelSymbol(.Label.Loc, )
			if  && ! {
				 := js_lexer.RangeOfIdentifier(.source, .Label.Loc)
				.log.AddRangeError(&.source, , fmt.Sprintf("Cannot continue to label \"%s\"", ))
			}
		} else if !.fnOrArrowDataVisit.isInsideLoop {
			 := js_lexer.RangeOfIdentifier(.source, .Loc)
			.log.AddRangeError(&.source, , "Cannot use \"continue\" here")
		}

	case *js_ast.SLabel:
		.pushScopeForVisitPass(js_ast.ScopeLabel, .Loc)
		 := .loadNameFromRef(.Name.Ref)
		 := .newSymbol(js_ast.SymbolLabel, )
		.Name.Ref = 
		.currentScope.LabelRef = 
		switch .Stmt.Data.(type) {
		case *js_ast.SFor, *js_ast.SForIn, *js_ast.SForOf, *js_ast.SWhile, *js_ast.SDoWhile:
			.currentScope.LabelStmtIsLoop = true
		}
		.Stmt = .visitSingleStmt(.Stmt, stmtsNormal)
		.popScope()

	case *js_ast.SLocal:
		for ,  := range .Decls {
			.visitBinding(.Binding, bindingOpts{})
			if .Value != nil {
				 := .isAnonymousNamedExpr(*.Value)
				*.Value = .visitExpr(*.Value)
Optionally preserve the name
				if ,  := .Binding.Data.(*js_ast.BIdentifier);  {
					*.Value = .maybeKeepExprSymbolName(
						*.Value, .symbols[.Ref.InnerIndex].OriginalName, )
				}
Initializing to undefined is implicit, but be careful to not accidentally cause a syntax error or behavior change by removing the value Good: "let a = undefined;" => "let a;" Bad (a syntax error): "let {} = undefined;" => "let {};" Bad (a behavior change): "a = 123; var a = undefined;" => "a = 123; var a;"
				if .options.mangleSyntax && .Kind == js_ast.LocalLet {
					if ,  := .Binding.Data.(*js_ast.BIdentifier);  {
						if ,  := .Value.Data.(*js_ast.EUndefined);  {
							.Decls[].Value = nil
						}
					}
				}
			}
		}
Handle being exported inside a namespace
		if .IsExport && .enclosingNamespaceArgRef != nil {
			 := func( logger.Loc,  js_ast.Ref) js_ast.Expr {
				.recordUsage(*.enclosingNamespaceArgRef)
				return js_ast.Expr{Loc: , Data: &js_ast.EDot{
					Target:  js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: *.enclosingNamespaceArgRef}},
					Name:    .symbols[.InnerIndex].OriginalName,
					NameLoc: ,
				}}
			}
			for ,  := range .Decls {
				if .Value != nil {
					 := .convertBindingToExpr(.Binding, )
					if ,  := .lowerObjectRestInAssign(, *.Value);  {
						 = 
					} else {
						 = js_ast.Assign(, *.Value)
					}
					 = append(, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: }})
				}
			}
			return 
		}

		.Decls = .lowerObjectRestInDecls(.Decls)
		.Kind = .selectLocalKind(.Kind)
Potentially relocate "var" declarations to the top level
		if .Kind == js_ast.LocalVar {
			if ,  := .maybeRelocateVarsToTopLevel(.Decls, relocateVarsNormal);  {
				if .Data != nil {
					 = append(, )
				}
				return 
			}
		}

	case *js_ast.SExpr:
		.Value = .visitExpr(.Value)
Trim expressions without side effects
		if .options.mangleSyntax {
			.Value = .simplifyUnusedExpr(.Value)
			if .Value.Data == nil {
				 = js_ast.Stmt{Loc: .Loc, Data: &js_ast.SEmpty{}}
			}
		}

	case *js_ast.SThrow:
		.Value = .visitExpr(.Value)

	case *js_ast.SReturn:
		if .Value != nil {
			*.Value = .visitExpr(*.Value)
Returning undefined is implicit
			if .options.mangleSyntax {
				if ,  := .Value.Data.(*js_ast.EUndefined);  {
					.Value = nil
				}
			}
		}

	case *js_ast.SBlock:
		.pushScopeForVisitPass(js_ast.ScopeBlock, .Loc)
Pass the "is loop body" status on to the direct children of a block used as a loop body. This is used to enable optimizations specific to the topmost scope in a loop body block.
		if .loopBody ==  {
			.Stmts = .visitStmts(.Stmts, stmtsLoopBody)
		} else {
			.Stmts = .visitStmts(.Stmts, stmtsNormal)
		}

		.popScope()

		if .options.mangleSyntax {
Unwrap blocks containing a single statement
				 = .Stmts[0]
A true value is implied
			 := &.Test
			if , ,  := toBooleanWithSideEffects(.Test.Data);  &&  &&  == noSideEffects {
				 = nil
			}
"while (a) {}" => "for (;a;) {}"
			 := &js_ast.SFor{Test: , Body: .Body}
			mangleFor()
			 = js_ast.Stmt{Loc: .Loc, Data: }
		}

	case *js_ast.SDoWhile:
		.Body = .visitLoopBody(.Body)
		.Test = .visitExpr(.Test)

		if .options.mangleSyntax {
			.Test = .simplifyBooleanExpr(.Test)
		}

	case *js_ast.SIf:
		.Test = .visitExpr(.Test)

		if .options.mangleSyntax {
			.Test = .simplifyBooleanExpr(.Test)
		}
Fold constants
		, ,  := toBooleanWithSideEffects(.Test.Data)
Mark the control flow as dead if the branch is never taken
		if  && ! {
			 := .isControlFlowDead
			.isControlFlowDead = true
			.Yes = .visitSingleStmt(.Yes, stmtsNormal)
			.isControlFlowDead = 
		} else {
			.Yes = .visitSingleStmt(.Yes, stmtsNormal)
		}
The "else" clause is optional
Mark the control flow as dead if the branch is never taken
			if  &&  {
				 := .isControlFlowDead
				.isControlFlowDead = true
				*.No = .visitSingleStmt(*.No, stmtsNormal)
				.isControlFlowDead = 
			} else {
				*.No = .visitSingleStmt(*.No, stmtsNormal)
			}
Trim unnecessary "else" clauses
			if .options.mangleSyntax {
				if ,  := .No.Data.(*js_ast.SEmpty);  {
					.No = nil
				}
			}
		}

		if .options.mangleSyntax {
			return .mangleIf(, .Loc, )
		}

	case *js_ast.SFor:
		.pushScopeForVisitPass(js_ast.ScopeBlock, .Loc)
		if .Init != nil {
			.visitForLoopInit(*.Init, false)
		}

		if .Test != nil {
			*.Test = .visitExpr(*.Test)

			if .options.mangleSyntax {
				*.Test = .simplifyBooleanExpr(*.Test)
A true value is implied
				if , ,  := toBooleanWithSideEffects(.Test.Data);  &&  &&  == noSideEffects {
					.Test = nil
				}
			}
		}

		if .Update != nil {
			*.Update = .visitExpr(*.Update)
		}
		.Body = .visitLoopBody(.Body)
		.popScope()
Potentially relocate "var" declarations to the top level
		if .Init != nil {
			if ,  := .Init.Data.(*js_ast.SLocal);  && .Kind == js_ast.LocalVar {
				if ,  := .maybeRelocateVarsToTopLevel(.Decls, relocateVarsNormal);  {
					if .Data != nil {
						.Init = &
					} else {
						.Init = nil
					}
				}
			}
		}

		if .options.mangleSyntax {
			mangleFor()
		}

	case *js_ast.SForIn:
		.pushScopeForVisitPass(js_ast.ScopeBlock, .Loc)
		.visitForLoopInit(.Init, true)
		.Value = .visitExpr(.Value)
		.Body = .visitLoopBody(.Body)
		.popScope()
		.lowerObjectRestInForLoopInit(.Init, &.Body)
Check for a variable initializer
		if ,  := .Init.Data.(*js_ast.SLocal);  && .Kind == js_ast.LocalVar && len(.Decls) == 1 {
			 := &.Decls[0]
			if ,  := .Binding.Data.(*js_ast.BIdentifier);  && .Value != nil {
				.markStrictModeFeature(forInVarInit, .source.RangeOfOperatorBefore(.Value.Loc, "="), "")
Lower for-in variable initializers in case the output is used in strict mode
				 = append(, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: js_ast.Assign(
					js_ast.Expr{Loc: .Binding.Loc, Data: &js_ast.EIdentifier{Ref: .Ref}},
					*.Value,
				)}})
				.Value = nil
			}
		}
Potentially relocate "var" declarations to the top level
		if ,  := .Init.Data.(*js_ast.SLocal);  && .Kind == js_ast.LocalVar {
			if ,  := .maybeRelocateVarsToTopLevel(.Decls, relocateVarsForInOrForOf);  {
				.Init = 
			}
		}

	case *js_ast.SForOf:
		.pushScopeForVisitPass(js_ast.ScopeBlock, .Loc)
		.visitForLoopInit(.Init, true)
		.Value = .visitExpr(.Value)
		.Body = .visitLoopBody(.Body)
		.popScope()
Make sure the assignment to the body above is preserved
			.Cases[] = 
		}
		.fnOrArrowDataVisit.isInsideSwitch = 
		.popScope()
Check for duplicate case values
		.duplicateCaseChecker.reset()
		for ,  := range .Cases {
			if .Value != nil {
				.duplicateCaseChecker.check(, *.Value)
			}
		}

	case *js_ast.SFunction:
		.visitFn(&.Fn, .Fn.OpenParenLoc)
Handle exporting this function from a namespace
Optionally preserve the name
		if .options.keepNames {
			 = append(, .keepStmtSymbolName(.Fn.Name.Loc, .Fn.Name.Ref, .symbols[.Fn.Name.Ref.InnerIndex].OriginalName))
		}
		return 

	case *js_ast.SClass:
		 := .visitClass(.Loc, &.Class)
Remove the export flag inside a namespace
		 := .IsExport && .enclosingNamespaceArgRef != nil
		if  {
			.IsExport = false
		}
Lower class field syntax for browsers that don't support it
		,  := .lowerClass(, js_ast.Expr{}, )
		 = append(, ...)
Handle exporting this class from a namespace
Scan ahead for any variables inside this namespace. This must be done ahead of time before visiting any statements inside the namespace because we may end up visiting the uses before the declarations. We need to convert the uses into property accesses on the namespace.
		for ,  := range .Values {
			if .Ref != js_ast.InvalidRef {
				.isExportedInsideNamespace[.Ref] = .Arg
			}
		}
Values without initializers are initialized to one more than the previous value if the previous value is numeric. Otherwise values without initializers are initialized to undefined.
		 := float64(0)
		 := true
		 := []js_ast.Expr{}
Track values so they can be used by constant folding. We need to follow links here in case the enum was merged with a preceding namespace.
		 := make(map[string]float64)
		.knownEnumValues[.Name.Ref] = 
		.knownEnumValues[.Arg] = 
We normally don't fold numeric constants because they might increase code size, but it's important to fold numeric constants inside enums since that's what the TypeScript compiler does.
		 := .shouldFoldNumericConstants
		.shouldFoldNumericConstants = true
Create an assignment for each enum value
		for ,  := range .Values {
			 := js_lexer.UTF16ToString(.Name)
			var  js_ast.Expr
			 := false

			if .Value != nil {
				*.Value = .visitExpr(*.Value)
				 = false
				switch e := .Value.Data.(type) {
				case *js_ast.ENumber:
					[] = .Value
					 = true
					 = .Value + 1
				case *js_ast.EString:
					 = true
				}
			} else if  {
				[] = 
				.Value = &js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: }}
				++
			} else {
				.Value = &js_ast.Expr{Loc: .Loc, Data: &js_ast.EUndefined{}}
			}

"Enum.Name = value"
				 = js_ast.Assign(
					js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
						Target:  js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .Arg}},
						Name:    ,
						NameLoc: .Loc,
					}},
					*.Value,
				)
"Enum['Name'] = value"
				 = js_ast.Assign(
					js_ast.Expr{Loc: .Loc, Data: &js_ast.EIndex{
						Target: js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .Arg}},
						Index:  js_ast.Expr{Loc: .Loc, Data: &js_ast.EString{Value: .Name}},
					}},
					*.Value,
				)
			}
			.recordUsage(.Arg)
String-valued enums do not form a two-way map
			if  {
				 = append(, )
"Enum[assignTarget] = 'Name'"
				 = append(, js_ast.Assign(
					js_ast.Expr{Loc: .Loc, Data: &js_ast.EIndex{
						Target: js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .Arg}},
						Index:  ,
					}},
					js_ast.Expr{Loc: .Loc, Data: &js_ast.EString{Value: .Name}},
				))
			}
			.recordUsage(.Arg)
		}

		.shouldFoldNumericConstants = 
Generate statements from expressions
		 := []js_ast.Stmt{}
		if len() > 0 {
"a; b; c;" => "a, b, c;"
				 := js_ast.JoinAllWithComma()
				 = append(, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: }})
			} else {
				for ,  := range  {
					 = append(, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: }})
				}
			}
		}
Wrap this enum definition in a closure
		 = .generateClosureForTypeScriptNamespaceOrEnum(
			, .Loc, .IsExport, .Name.Loc, .Name.Ref, .Arg, )
		return 

	case *js_ast.SNamespace:
		.recordDeclaredSymbol(.Name.Ref)
Scan ahead for any variables inside this namespace. This must be done ahead of time before visiting any statements inside the namespace because we may end up visiting the uses before the declarations. We need to convert the uses into property accesses on the namespace.
		for ,  := range .Stmts {
			if ,  := .Data.(*js_ast.SLocal);  {
				if .IsExport {
					.markExportedDeclsInsideNamespace(.Arg, .Decls)
				}
			}
		}

		 := .enclosingNamespaceArgRef
		.enclosingNamespaceArgRef = &.Arg
		.pushScopeForVisitPass(js_ast.ScopeEntry, .Loc)
		.recordDeclaredSymbol(.Arg)
		 := .visitStmtsAndPrependTempRefs(.Stmts, prependTempRefsOpts{kind: stmtsFnBody})
		.popScope()
		.enclosingNamespaceArgRef = 
Generate a closure for this namespace
		 = .generateClosureForTypeScriptNamespaceOrEnum(
			, .Loc, .IsExport, .Name.Loc, .Name.Ref, .Arg, )
		return 

	default:
		panic("Internal error")
	}

	 = append(, )
	return 
}

type relocateVarsMode uint8

const (
	relocateVarsNormal relocateVarsMode = iota
	relocateVarsForInOrForOf
)
If we are currently in a hoisted child of the module scope, relocate these declarations to the top level and return an equivalent assignment statement. Make sure to check that the declaration kind is "var" before calling this. And make sure to check that the returned statement is not the zero value. This is done to make it easier to traverse top-level declarations in the linker during bundling. Now it is sufficient to just scan the top-level statements instead of having to traverse recursively into the statement tree.
Only do this when bundling, and not when the scope is already top-level
Only do this if we're not inside a function
	 := .currentScope
	for !.Kind.StopsHoisting() {
		 = .Parent
	}
	if  != .moduleScope {
		return js_ast.Stmt{}, false
	}
Convert the declarations to assignments
	 := func( logger.Loc,  js_ast.Ref) js_ast.Expr {
		.relocatedTopLevelVars = append(.relocatedTopLevelVars, js_ast.LocRef{Loc: , Ref: })
		.recordUsage()
		return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}
	}
	var  js_ast.Expr
	for ,  := range  {
		 := .convertBindingToExpr(.Binding, )
		if .Value != nil {
			 = maybeJoinWithComma(, js_ast.Assign(, *.Value))
		} else if  == relocateVarsForInOrForOf {
			 = maybeJoinWithComma(, )
		}
	}
If none of the variables had any initializers, just remove the declarations
		return js_ast.Stmt{}, true
	}
	return js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: }}, true
}

func ( *parser) ( js_ast.Expr) {
	switch e := .Data.(type) {
	case *js_ast.EArray:
		.IsParenthesized = true
	case *js_ast.EObject:
		.IsParenthesized = true
	}
}

func ( *parser) ( js_ast.Ref,  []js_ast.Decl) {
	for ,  := range  {
		.markExportedBindingInsideNamespace(, .Binding)
	}
}

func ( *parser) ( js_ast.Ref,  js_ast.Binding) {
	switch b := .Data.(type) {
	case *js_ast.BMissing:

	case *js_ast.BIdentifier:
		.isExportedInsideNamespace[.Ref] = 

	case *js_ast.BArray:
		for ,  := range .Items {
			.(, .Binding)
		}

	case *js_ast.BObject:
		for ,  := range .Properties {
			.(, .Value)
		}

	default:
		panic("Internal error")
	}
}

func ( *parser) ( js_ast.Expr,  func(js_ast.Expr) js_ast.Expr) js_ast.Expr {
	if ,  := .Data.(*js_ast.EIf);  {
		.Yes = .(.Yes, )
		.No = .(.No, )
		return 
	}
	return ()
}

func ( js_ast.Expr,  js_ast.Expr) js_ast.Expr {
	if .Data == nil {
		return 
	}
	if .Data == nil {
		return 
	}
	return js_ast.JoinWithComma(, )
}
This is a helper function to use when you need to capture a value that may have side effects so you can use it multiple times. It guarantees that the side effects take place exactly once. Example usage: // "value" => "value + value" // "value()" => "(_a = value(), _a + _a)" valueFunc, wrapFunc := p.captureValueWithPossibleSideEffects(loc, 2, value) return wrapFunc(js_ast.Expr{Loc: loc, Data: &js_ast.EBinary{ Op: js_ast.BinOpAdd, Left: valueFunc(), Right: valueFunc(), }}) This returns a function for generating references instead of a raw reference because AST nodes are supposed to be unique in memory, not aliases of other AST nodes. That way you can mutate one during lowering without having to worry about messing up other nodes.
func ( *parser) (
	 logger.Loc, // The location to use for the generated references
	 int, // The expected number of references to generate
	 js_ast.Expr, // The value that might have side effects
) (
	func() js_ast.Expr, // Generates reference expressions "_a"
	func(js_ast.Expr) js_ast.Expr, // Call this on the final expression
) {
Make sure side effects still happen if no expression was generated
		if .Data == nil {
			return 
		}
		return 
	}
Referencing certain expressions more than once has no side effects, so we can just create them inline without capturing them in a temporary variable
	var  func() js_ast.Expr
	switch e := .Data.(type) {
	case *js_ast.ENull:
		 = func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.ENull{}} }
	case *js_ast.EUndefined:
		 = func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.EUndefined{}} }
	case *js_ast.EThis:
		 = func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.EThis{}} }
	case *js_ast.EBoolean:
		 = func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.EBoolean{Value: .Value}} }
	case *js_ast.ENumber:
		 = func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.ENumber{Value: .Value}} }
	case *js_ast.EBigInt:
		 = func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.EBigInt{Value: .Value}} }
	case *js_ast.EString:
		 = func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.EString{Value: .Value}} }
	case *js_ast.EIdentifier:
Make sure we record this usage in the usage count so that duplicating a single-use reference means it's no longer considered a single-use reference. Otherwise the single-use reference inlining code may incorrectly inline the initializer into the first reference, leaving the second reference without a definition.
			.recordUsage(.Ref)
			return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: .Ref}}
		}
	}
	if  != nil {
		return , 
	}
We don't need to worry about side effects if the value won't be used multiple times. This special case lets us avoid generating a temporary reference.
	if  < 2 {
		return func() js_ast.Expr {
			return 
		}, 
	}
Otherwise, fall back to generating a temporary reference
	 := js_ast.InvalidRef
If we're in a function argument scope, then we won't be able to generate symbols in this scope to store stuff, since there's nowhere to put the variable declaration. We don't want to put the variable declaration outside the function since some code in the argument list may cause the function to be reentrant, and we can't put the variable declaration in the function body since that's not accessible by the argument list. Instead, we use an immediately-invoked arrow function to create a new symbol inline by introducing a new scope. Make sure to only use it for symbol declaration and still initialize the variable inline to preserve side effect order.
	if .currentScope.Kind == js_ast.ScopeFunctionArgs {
		return func() js_ast.Expr {
				if  == js_ast.InvalidRef {
					 = .generateTempRef(tempRefNoDeclare, "")
Assign inline so the order of side effects remains the same
					.recordUsage()
					return js_ast.Assign(js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}, )
				}
				.recordUsage()
				return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}
Make sure side effects still happen if no expression was generated
				if .Data == nil {
					return 
				}
Generate a new variable using an arrow function to avoid messing with "this"
				return js_ast.Expr{Loc: , Data: &js_ast.ECall{
					Target: js_ast.Expr{Loc: , Data: &js_ast.EArrow{
						Args:       []js_ast.Arg{{Binding: js_ast.Binding{Loc: , Data: &js_ast.BIdentifier{Ref: }}}},
						PreferExpr: true,
						Body:       js_ast.FnBody{Loc: , Stmts: []js_ast.Stmt{{Loc: , Data: &js_ast.SReturn{Value: &}}}},
					}},
					Args: []js_ast.Expr{},
				}}
			}
	}

	return func() js_ast.Expr {
		if  == js_ast.InvalidRef {
			 = .generateTempRef(tempRefNeedsDeclare, "")
			.recordUsage()
			return js_ast.Assign(js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}, )
		}
		.recordUsage()
		return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}
	}, 
}

func ( *parser) ( []js_ast.Expr) []js_ast.Expr {
	for ,  := range  {
		[] = .visitExpr()
	}
	return 
}

func ( *parser) ( logger.Loc,  *js_ast.Class) js_ast.Ref {
	.TSDecorators = .visitTSDecorators(.TSDecorators)

	if .Name != nil {
		.recordDeclaredSymbol(.Name.Ref)
	}
Replace "this" with a reference to the class inside static field initializers either if static fields are not supported or if we are converting this class to a "var" to avoid the temporal dead zone.
	 := .options.unsupportedJSFeatures.Has(compat.ClassStaticField) ||
		(.options.mode == config.ModeBundle && .currentScope.Parent == nil)

	.pushScopeForVisitPass(js_ast.ScopeClassName, )
	 := .enclosingClassKeyword
	.enclosingClassKeyword = .ClassKeyword
	.currentScope.RecursiveSetStrictMode(js_ast.ImplicitStrictModeClass)

	 := js_ast.InvalidRef
	if .Name != nil {
		 = .Name.Ref
Generate a name if one doesn't already exist. This is necessary for handling "this" in static class property initializers.
		 = .newSymbol(js_ast.SymbolOther, "this")
	}
Insert a shadowing name that spans the whole class, which matches JavaScript's semantics. The class body (and extends clause) "captures" the original value of the name. This matters for class statements because the symbol can be re-assigned to something else later. The captured values must be the original value of the name, not the re-assigned value.
	 := js_ast.InvalidRef
Use "const" for this symbol to match JavaScript run-time semantics. You are not allowed to assign to this symbol (it throws a TypeError).
		 := .symbols[.InnerIndex].OriginalName
		 = .newSymbol(js_ast.SymbolConst, "_"+)
		.recordDeclaredSymbol()
		if .Name != nil {
			.currentScope.Members[] = js_ast.ScopeMember{Loc: .Name.Loc, Ref: }
		}
	}

	if .Extends != nil {
		*.Extends = .visitExpr(*.Extends)
	}
A scope is needed for private identifiers
	.pushScopeForVisitPass(js_ast.ScopeClassBody, .BodyLoc)
	defer .popScope()

	for ,  := range .Properties {
		.TSDecorators = .visitTSDecorators(.TSDecorators)
		,  := .Key.Data.(*js_ast.EPrivateIdentifier)
Special-case EPrivateIdentifier to allow it here
		if  {
			.recordDeclaredSymbol(.Ref)
		} else {
			 := .visitExpr(.Key)
			.Properties[].Key = 
"class {['x'] = y}" => "class {x = y}"
			if .options.mangleSyntax && .IsComputed {
				if ,  := .Data.(*js_ast.EString);  && js_lexer.IsIdentifierUTF16(.Value) {
					.Properties[].IsComputed = false
				}
			}
		}
Make it an error to use "arguments" in a class body
The value of "this" is shadowed inside property values
We need to explicitly assign the name to the property initializer if it will be transformed such that it is no longer an inline initializer.
		 := ""
		if  && .isPrivateUnsupported() {
			 = .symbols[.Ref.InnerIndex].OriginalName
		} else if !.IsMethod && !.IsComputed &&
			((!.IsStatic && .options.unsupportedJSFeatures.Has(compat.ClassField)) ||
				(.IsStatic && .options.unsupportedJSFeatures.Has(compat.ClassStaticField))) {
			if ,  := .Key.Data.(*js_ast.EString);  {
				 = js_lexer.UTF16ToString(.Value)
			}
		}

		if .Value != nil {
			if  != "" {
				 := .isAnonymousNamedExpr(*.Value)
				*.Value = .maybeKeepExprSymbolName(.visitExpr(*.Value), , )
			} else {
				*.Value = .visitExpr(*.Value)
			}
		}

		if .Initializer != nil {
Replace "this" with the class name inside static property initializers
				.fnOnlyDataVisit.thisClassStaticRef = &
			}
			if  != "" {
				 := .isAnonymousNamedExpr(*.Initializer)
				*.Initializer = .maybeKeepExprSymbolName(.visitExpr(*.Initializer), , )
			} else {
				*.Initializer = .visitExpr(*.Initializer)
			}
		}
Restore "this" so it will take the inherited value in property keys
Restore the ability to use "arguments" in decorators and computed properties
		.currentScope.ForbidArguments = false
	}

	.enclosingClassKeyword = 
	.popScope()

	if  != js_ast.InvalidRef {
Don't generate a shadowing name if one isn't needed
			 = js_ast.InvalidRef
If there was originally no class name but something inside needed one (e.g. there was a static property initializer that referenced "this"), store our generated name so the class expression ends up with a name.
			.Name = &js_ast.LocRef{Loc: , Ref: }
			.currentScope.Generated = append(.currentScope.Generated, )
			.recordDeclaredSymbol()
		}
	}

	return 
}

func ( []js_ast.Arg,  bool) bool {
	if  {
		return false
	}
	for ,  := range  {
		if ,  := .Binding.Data.(*js_ast.BIdentifier); ! || .Default != nil {
			return false
		}
	}
	return true
}

func ( []js_ast.Stmt) (logger.Loc, bool) {
	for ,  := range  {
		switch s := .Data.(type) {
		case *js_ast.SComment:
			continue
		case *js_ast.SDirective:
			if js_lexer.UTF16EqualsString(.Value, "use strict") {
				return .Loc, true
			}
		default:
			return logger.Loc{}, false
		}
	}
	return logger.Loc{}, false
}

type visitArgsOpts struct {
	body       []js_ast.Stmt
	hasRestArg bool
This is true if the function is an arrow function or a method
	isUniqueFormalParameters bool
}

func ( *parser) ( []js_ast.Arg,  visitArgsOpts) {
	var  map[string]bool
	,  := fnBodyContainsUseStrict(.body)
	 := isSimpleParameterList(, .hasRestArg)
Section 15.2.1 Static Semantics: Early Errors: "It is a Syntax Error if FunctionBodyContainsUseStrict of FunctionBody is true and IsSimpleParameterList of FormalParameters is false."
	if  && ! {
		.log.AddRangeError(&.source, .source.RangeOfString(),
			"Cannot use a \"use strict\" directive in a function with a non-simple parameter list")
	}
Section 15.1.1 Static Semantics: Early Errors: "Multiple occurrences of the same BindingIdentifier in a FormalParameterList is only allowed for functions which have simple parameter lists and which are not defined in strict mode code."
	if .isUniqueFormalParameters ||  || ! || .isStrictMode() {
		 = make(map[string]bool)
	}

	for ,  := range  {
		.TSDecorators = .visitTSDecorators(.TSDecorators)
		.visitBinding(.Binding, bindingOpts{
			duplicateArgCheck: ,
		})
		if .Default != nil {
			*.Default = .visitExpr(*.Default)
		}
	}
}

func ( *parser) ( js_ast.Expr,  []string) bool {
	switch e := .Data.(type) {
	case *js_ast.EDot:
Intermediates must be dot expressions
			 := len() - 1
			return [] == .Name && .OptionalChain == js_ast.OptionalChainNone &&
				.(.Target, [:])
		}

Allow matching on "import.meta"
		return len() == 2 && [0] == "import" && [1] == "meta"

The last expression must be an identifier
The name must match
			 := .loadNameFromRef(.Ref)
			if  != [0] {
				return false
			}

			 := .findSymbol(.Loc, )
We must not be in a "with" statement scope
			if .isInsideWithScope {
				return false
			}
The last symbol must be unbound
			return .symbols[.ref.InnerIndex].Kind == js_ast.SymbolUnbound
		}
	}

	return false
}

Check both user-specified defines and known globals
	if ,  := .options.defines.DotDefines[[len()-1]];  {
	:
		for ,  := range  {
			if len(.Parts) == len() {
				for  := range  {
					if [] != .Parts[] {
						continue 
					}
				}
			}
Substitute user-specified defines
			if .Data.DefineFunc != nil {
				return .valueForDefine(, js_ast.AssignTargetNone, false, .Data.DefineFunc)
			}
		}
	}
Generate an identifier for the first part
	 := .findSymbol(, [0])
	 := .handleIdentifier(, &js_ast.EIdentifier{
		Ref:                   .ref,
		MustKeepDueToWithStmt: .isInsideWithScope,
Build up a chain of property access expressions for subsequent parts
	for  := 1;  < len(); ++ {
		if ,  := .maybeRewritePropertyAccess(, js_ast.AssignTargetNone, false, js_ast.OptionalChainNone, , [], , false);  {
			 = 
		} else {
			 = js_ast.Expr{Loc: , Data: &js_ast.EDot{
				Target:  ,
				Name:    [],
				NameLoc: ,
Enable tree shaking
				CanBeRemovedIfUnused: true,
			}}
		}
	}

	return 
}

func ( *parser) ( logger.Loc,  string) {
	if .options.asciiOnly && .options.unsupportedJSFeatures.Has(compat.UnicodeEscapes) &&
		js_lexer.ContainsNonBMPCodePoint() {
		if .nonBMPIdentifiers == nil {
			.nonBMPIdentifiers = make(map[string]bool)
		}
		if !.nonBMPIdentifiers[] {
			.nonBMPIdentifiers[] = true
			 := js_lexer.RangeOfIdentifier(.source, )
			.log.AddRangeError(&.source, , fmt.Sprintf("%q cannot be escaped in the target environment ("+
				"consider setting the charset to \"utf8\" or changing the target)", ))
		}
	}
}

func ( *parser) ( js_ast.Expr,  js_ast.Expr) {
	if ,  := .Data.(*js_ast.EUnary);  && .Op == js_ast.UnOpTypeof {
		if ,  := .Data.(*js_ast.EString);  {
			 := js_lexer.UTF16ToString(.Value)
			switch  {
			case "undefined", "object", "boolean", "number", "bigint", "string", "symbol", "function", "unknown":
Warn about typeof comparisons with values that will never be returned. Here's an example of code with this problem: https://github.com/olifolkerd/tabulator/issues/2962
				if !.options.suppressWarningsAboutWeirdCode {
					 := .source.RangeOfString(.Loc)
					.log.AddRangeWarning(&.source, , fmt.Sprintf("The \"typeof\" operator will never evaluate to %q", ))
				}
			}
		}
	}
}

func ( js_ast.Expr,  js_ast.Expr) bool {
	return (js_ast.IsBooleanValue() && js_ast.IsBooleanValue()) ||
		(js_ast.IsNumericValue() && js_ast.IsNumericValue()) ||
		(js_ast.IsStringValue() && js_ast.IsStringValue())
}

"!x === true" => "!x" "!x === false" => "!!x" "!x !== true" => "!!x" "!x !== false" => "!x"
	if ,  := .Right.Data.(*js_ast.EBoolean);  && js_ast.IsBooleanValue(.Left) {
		if .Value ==  {
			return js_ast.Not(.Left), true
		} else {
			return .Left, true
		}
	}

	return js_ast.Expr{}, false
}

func ( *parser) ( string,  js_ast.Expr,  logger.Loc) bool {
	if .options.suppressWarningsAboutWeirdCode {
		return false
	}

	switch e := .Data.(type) {
"0 === -0" is true in JavaScript. Here's an example of code with this problem: https://github.com/mrdoob/three.js/pull/11183
		if .Value == 0 && math.Signbit(.Value) {
			 := logger.Range{Loc: .Loc, Len: 0}
			if int(.Loc.Start) < len(.source.Contents) && .source.Contents[.Loc.Start] == '-' {
				 := .source.RangeOfNumber(logger.Loc{Start: .Loc.Start + 1})
				.Len = .Len + 1
			}
			 := fmt.Sprintf("Comparison with -0 using the %q operator will also match 0", )
			if  == "case" {
				 = "Comparison with -0 using a case clause will also match 0"
			}
			.log.AddRangeWarning(&.source, , )
			return true
		}
"NaN === NaN" is false in JavaScript
		if math.IsNaN(.Value) {
			 := fmt.Sprintf("Comparison with NaN using the %q operator here is always %v", , [0] == '!')
			if  == "case" {
				 = "This case clause will never be evaluated because equality with NaN is always false"
			}
			.log.AddRangeWarning(&.source, .source.RangeOfOperatorBefore(, ), )
			return true
		}

	case *js_ast.EArray, *js_ast.EArrow, *js_ast.EClass,
This warning only applies to strict equality because loose equality can cause string conversions. For example, "x == []" is true if x is the empty string. Here's an example of code with this problem: https://github.com/aws/aws-sdk-js/issues/3325
		if len() > 2 {
			 := fmt.Sprintf("Comparison using the %q operator here is always %v", , [0] == '!')
			if  == "case" {
				 = "This case clause will never be evaluated because the comparison is always false"
			}
			.log.AddRangeWarning(&.source, .source.RangeOfOperatorBefore(, ), )
			return true
		}
	}

	return false
}

func ( *parser) ( string,  logger.Range) {
	if .options.mode == config.ModeBundle && .options.platform == config.PlatformBrowser {
		if .lackOfDefineWarnings == nil {
			.lackOfDefineWarnings = make(map[string]bool)
		}
		if !.lackOfDefineWarnings[] {
			.lackOfDefineWarnings[] = true
			.log.AddRangeWarning(&.source, ,
				fmt.Sprintf("Define %q when bundling for the browser", ))
		}
	}
}
EDot nodes represent a property access. This function may return an expression to replace the property access with. It assumes that the target of the EDot expression has already been visited.
func ( *parser) (
	 logger.Loc,
	 js_ast.AssignTarget,
	 bool,
	 js_ast.OptionalChain,
	 js_ast.Expr,
	 string,
	 logger.Loc,
	 bool,
) (js_ast.Expr, bool) {
Rewrite property accesses on explicit namespace imports as an identifier. This lets us replace them easily in the printer to rebind them to something else without paying the cost of a whole-tree traversal during module linking just to rewrite these EDot expressions.
Cache translation so each property access resolves to the same import
				,  := []
Generate a new import item symbol in the module scope
Link the namespace import and the import item together
					[] = 
					.isImportItem[.Ref] = true

					 := &.symbols[.Ref.InnerIndex]
Make sure the printer prints this as a property access
Mark this as generated in case it's missing. We don't want to generate errors for missing import items that are automatically generated.
Undo the usage count for the namespace itself. This is used later to detect whether the namespace symbol has ever been "captured" or whether it has just been used to read properties off of. The benefit of doing this is that if both this module and the imported module end up in the same module group and the namespace symbol has never been captured, then we don't need to generate any code for the namespace at all.
Track how many times we've referenced this symbol
				.recordUsage(.Ref)
				return .handleIdentifier(, &js_ast.EIdentifier{Ref: .Ref}, identifierOpts{
					assignTarget:   ,
					isDeleteTarget: ,
If this expression is used as the target of a call expression, make sure the value of "this" is preserved.
Rewrite "module.require()" to "require()" for Webpack compatibility. See https://github.com/webpack/webpack/pull/7750 for more info.
			if  && .Ref == .moduleRef &&  == "require" {
				.ignoreUsage(.moduleRef)
				.recordUsage(.requireRef)
				return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: .requireRef}}, true
			}
		}
If this is a known enum value, inline the value of the enum
		if .options.ts.Parse &&  == js_ast.OptionalChainNone {
			if ,  := .knownEnumValues[.Ref];  {
				if ,  := [];  {
					return js_ast.Expr{Loc: , Data: &js_ast.ENumber{Value: }}, true
				}
			}
		}
	}

	return js_ast.Expr{}, false
}

func ( []uint16,  []uint16) []uint16 {
	 := make([]uint16, len()+len())
	copy([:len()], )
	copy([len():], )
	return 
}

func ( js_ast.Expr,  js_ast.Expr) *js_ast.Expr {
	switch l := .Data.(type) {
	case *js_ast.EString:
		switch r := .Data.(type) {
		case *js_ast.EString:
			return &js_ast.Expr{Loc: .Loc, Data: &js_ast.EString{
				Value:          joinStrings(.Value, .Value),
				PreferTemplate: .PreferTemplate || .PreferTemplate,
			}}

		case *js_ast.ETemplate:
			if .Tag == nil {
				return &js_ast.Expr{Loc: .Loc, Data: &js_ast.ETemplate{Head: joinStrings(.Value, .Head), Parts: .Parts}}
			}
		}

	case *js_ast.ETemplate:
		if .Tag == nil {
			switch r := .Data.(type) {
			case *js_ast.EString:
				 := len(.Parts)
				 := .Head
				 := make([]js_ast.TemplatePart, )
				if  == 0 {
					 = joinStrings(, .Value)
				} else {
					copy(, .Parts)
					[-1].Tail = joinStrings([-1].Tail, .Value)
				}
				return &js_ast.Expr{Loc: .Loc, Data: &js_ast.ETemplate{Head: , Parts: }}

			case *js_ast.ETemplate:
				if .Tag == nil {
					 := len(.Parts)
					 := .Head
					 := make([]js_ast.TemplatePart, +len(.Parts))
					copy([:], .Parts)
					if  == 0 {
						 = joinStrings(, .Head)
					} else {
						copy([:], .Parts)
						[-1].Tail = joinStrings([-1].Tail, .Head)
					}
					return &js_ast.Expr{Loc: .Loc, Data: &js_ast.ETemplate{Head: , Parts: }}
				}
			}
		}
	}

	return nil
}
Simplify syntax when we know it's used inside a boolean context
func ( *parser) ( js_ast.Expr) js_ast.Expr {
	switch e := .Data.(type) {
	case *js_ast.EUnary:
"!!a" => "a"
			if ,  := .Value.Data.(*js_ast.EUnary);  && .Op == js_ast.UnOpNot {
				return .(.Value)
			}

			.Value = .(.Value)
		}

	case *js_ast.EBinary:
		switch .Op {
		case js_ast.BinOpLogicalAnd:
			if , ,  := toBooleanWithSideEffects(.Right.Data);  {
"if (anything && falsyWithSideEffects)" => "if (anything, falsyWithSideEffects)"
"if (anything && truthyNoSideEffects)" => "if (anything)"
					return .Left
				}
			}

		case js_ast.BinOpLogicalOr:
			if , ,  := toBooleanWithSideEffects(.Right.Data);  {
"if (anything || truthyWithSideEffects)" => "if (anything, truthyWithSideEffects)"
"if (anything || falsyNoSideEffects)" => "if (anything)"
					return .Left
				}
			}
		}
	}

	return 
}

The easy way
	 := int32()
	if float64() ==  {
		return 
	}
The hard way
	 = int32(uint32(math.Mod(math.Abs(), 4294967296)))
	if math.Signbit() {
		return -
	}
	return 
}

func ( float64) uint32 {
	return uint32(toInt32())
}

This tells us if there are optional chain expressions (EDot, EIndex, or ECall) that are chained on to this expression. Because of the way the AST works, chaining expressions on to this expression means they are our parent expressions. Some examples: a?.b.c // EDot a?.b[c] // EIndex a?.b() // ECall Note that this is false if our parent is a node with a OptionalChain value of OptionalChainStart. That means it's the start of a new chain, so it's not considered part of this one. Some examples: a?.b?.c // EDot a?.b?.[c] // EIndex a?.b?.() // ECall Also note that this is false if our parent is a node with a OptionalChain value of OptionalChainNone. That means it's outside parentheses, which means it's no longer part of the chain. Some examples: (a?.b).c // EDot (a?.b)[c] // EIndex (a?.b)() // ECall
If our parent is an ECall node with an OptionalChain value of OptionalChainStart, then we will need to store the value for the "this" of that call somewhere if the current expression is an optional chain that ends in a property access. That's because the value for "this" will be used twice: once for the inner optional chain and once for the outer optional chain. Example: // Original a?.b?.(); // Lowered var _a; (_a = a == null ? void 0 : a.b) == null ? void 0 : _a.call(a); In the example above we need to store "a" as the value for "this" so we can substitute it back in when we call "_a" if "_a" is indeed present. See also "thisArgFunc" and "thisArgWrapFunc" in "exprOut".
Certain substitutions of identifiers are disallowed for assignment targets. For example, we shouldn't transform "undefined = 1" into "void 0 = 1". This isn't something real-world code would do but it matters for conformance tests.
True if the child node is an optional chain node (EDot, EIndex, or ECall with an IsOptionalChain value of true)
If our parent is an ECall node with an OptionalChain value of OptionalChainContinue, then we may need to return the value for "this" from this node or one of this node's children so that the parent that is the end of the optional chain can use it. Example: // Original a?.b?.().c(); // Lowered var _a; (_a = a == null ? void 0 : a.b) == null ? void 0 : _a.call(a).c(); The value "_a" for "this" must be passed all the way up to the call to ".c()" which is where the optional chain is lowered. From there it must be substituted as the value for "this" in the call to ".b?.()". See also "storeThisArgForParentOptionalChain" in "exprIn".
	thisArgFunc     func() js_ast.Expr
	thisArgWrapFunc func(js_ast.Expr) js_ast.Expr
}

func ( *parser) ( js_ast.Expr) js_ast.Expr {
	, _ = .visitExprInOut(, exprIn{})
	return 
}

Substitute "this" if we're inside a static class property initializer
In an ES6 module, "this" is supposed to be undefined. Instead of doing this at runtime using "fn.call(undefined)", we do it at compile time using expression substitution here.
			return js_ast.Expr{Loc: , Data: &js_ast.EUndefined{}}, true
In a CommonJS module, "this" is supposed to be the same as "exports". Instead of doing this at runtime using "fn.call(module.exports)", we do it at compile time using expression substitution here.
			.recordUsage(.exportsRef)
			return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: .exportsRef}}, true
		}
	}

	return js_ast.Expr{}, false
}

func ( js_ast.Expr,  js_ast.Expr,  js_ast.OpCode) (js_ast.Expr, js_ast.Expr, bool) {
	if ,  := .Data.(*js_ast.EBinary);  && .Op ==  {
		if ,  := .Data.(*js_ast.EBinary);  && .Op ==  {
			if ,  := .Left.Data.(*js_ast.EIdentifier);  {
"a === null || a === void 0"
					if ,  := .Right.Data.(*js_ast.ENull);  {
						if ,  := .Right.Data.(*js_ast.EUndefined);  {
							return .Left, .Right, true
						}
					}
"a === void 0 || a === null"
					if ,  := .Right.Data.(*js_ast.EUndefined);  {
						if ,  := .Right.Data.(*js_ast.ENull);  {
							return .Left, .Right, true
						}
					}
				}
			}
		}
	}

	return js_ast.Expr{}, js_ast.Expr{}, false
}

func ( []js_ast.Expr) ( []js_ast.Expr) {
	for ,  := range  {
		if ,  := .Data.(*js_ast.ESpread);  {
			if ,  := .Value.Data.(*js_ast.EArray);  {
				for ,  := range .Items {
					if ,  := .Data.(*js_ast.EMissing);  {
						 = append(, js_ast.Expr{Loc: .Loc, Data: &js_ast.EUndefined{}})
					} else {
						 = append(, )
					}
				}
				continue
			}
		}
		 = append(, )
	}
	return
}

func ( *js_ast.EBinary) logger.Loc {
	if .Left.Loc.Start < .Right.Loc.Start {
		return .Right.Loc
Handle the case when we have transposed the operands
		return .Left.Loc
	}
}

func ( js_ast.Expr) bool {
	switch e := .Data.(type) {
	case *js_ast.EIdentifier, *js_ast.EDot, *js_ast.EIndex:
		return true
	case *js_ast.ENumber:
		return math.IsInf(.Value, 1) || math.IsNaN(.Value)
	}
	return false
}
This function exists to tie all of these checks together in one place
func ( string) bool {
	return  == "eval" ||  == "arguments"
}

func ( *parser) ( js_ast.Expr) bool {
	switch e := .Data.(type) {
	case *js_ast.EIdentifier:
		if .isStrictMode() {
			if  := .loadNameFromRef(.Ref); isEvalOrArguments() {
				return false
			}
		}
		return true
	case *js_ast.EDot:
		return .OptionalChain == js_ast.OptionalChainNone
	case *js_ast.EIndex:
		return .OptionalChain == js_ast.OptionalChainNone
Don't worry about recursive checking for objects and arrays. This will already be handled naturally by passing down the assign target flag.
	case *js_ast.EObject:
		return !.IsParenthesized
	case *js_ast.EArray:
		return !.IsParenthesized
	}
	return false
}
"`a${'b'}c`" => "`abc`"
Can't inline strings if there's a custom template tag
	if .Tag == nil {
		 := 0
		for ,  := range .Parts {
			if ,  := .Value.Data.(*js_ast.EString);  {
				if  == 0 {
					.Head = append(append(.Head, .Value...), .Tail...)
				} else {
					 := &.Parts[-1]
					.Tail = append(append(.Tail, .Value...), .Tail...)
				}
			} else {
				.Parts[] = 
				++
			}
		}
		.Parts = .Parts[:]
Become a plain string if there are no substitutions
		if len(.Parts) == 0 {
			return js_ast.Expr{Loc: , Data: &js_ast.EString{
				Value:          .Head,
				PreferTemplate: true,
			}}
		}
	}
	return js_ast.Expr{Loc: , Data: }
}
This function takes "exprIn" as input from the caller and produces "exprOut" for the caller to pass along extra data. This is mostly for optional chaining.
func ( *parser) ( js_ast.Expr,  exprIn) (js_ast.Expr, exprOut) {
	if .assignTarget != js_ast.AssignTargetNone && !.isValidAssignmentTarget() {
		.log.AddError(&.source, .Loc, "Invalid assignment target")
	}

	switch e := .Data.(type) {
	case *js_ast.ENull, *js_ast.ESuper,
		*js_ast.EBoolean, *js_ast.EBigInt,
		*js_ast.ERegExp, *js_ast.ENewTarget, *js_ast.EUndefined:

	case *js_ast.EString:
		if .LegacyOctalLoc.Start > 0 {
			if .PreferTemplate {
				.log.AddRangeError(&.source, .source.RangeOfLegacyOctalEscape(.LegacyOctalLoc),
					"Legacy octal escape sequences cannot be used in template literals")
			} else if .isStrictMode() {
				.markStrictModeFeature(legacyOctalEscape, .source.RangeOfLegacyOctalEscape(.LegacyOctalLoc), "")
			}
		}

	case *js_ast.ENumber:
		if .legacyOctalLiterals != nil && .isStrictMode() {
			if ,  := .legacyOctalLiterals[.Data];  {
				.markStrictModeFeature(legacyOctalLiteral, , "")
			}
		}

	case *js_ast.EThis:
		if ,  := .valueForThis(.Loc);  {
			return , exprOut{}
		}
Capture "this" inside arrow functions that will be lowered into normal function expressions for older language environments
Check both user-specified defines and known globals
		if ,  := .options.defines.DotDefines["meta"];  {
			for ,  := range  {
Substitute user-specified defines
					if .Data.DefineFunc != nil {
						return .valueForDefine(.Loc, .assignTarget, , .Data.DefineFunc), exprOut{}
					}
				}
			}
		}

Replace "import.meta" with a reference to the symbol
Handle assigning to a constant
		if .assignTarget != js_ast.AssignTargetNone && .symbols[.ref.InnerIndex].Kind == js_ast.SymbolConst {
			 := js_lexer.RangeOfIdentifier(.source, .Loc)
			 := []logger.MsgData{logger.RangeData(&.source, js_lexer.RangeOfIdentifier(.source, .declareLoc),
				fmt.Sprintf("%q was declared a constant here", ))}
Make this an error when bundling because we may need to convert this "const" into a "var" during bundling.
			if .options.mode == config.ModeBundle {
				.log.AddRangeErrorWithNotes(&.source, , fmt.Sprintf("Cannot assign to %q because it is a constant", ), )
			} else {
				.log.AddRangeWarningWithNotes(&.source, , fmt.Sprintf("This assignment will throw because %q is a constant", ), )
			}
		}
Substitute user-specified defines for unbound symbols
		if .symbols[.Ref.InnerIndex].Kind == js_ast.SymbolUnbound && !.isInsideWithScope &&  != .deleteTarget {
			if ,  := .options.defines.IdentifierDefines[];  {
				if .DefineFunc != nil {
					 := .valueForDefine(.Loc, .assignTarget, , .DefineFunc)
Don't substitute an identifier for a non-identifier if this is an assignment target, since it'll cause a syntax error
					if ,  := .Data.(*js_ast.EIdentifier); .assignTarget == js_ast.AssignTargetNone ||  {
						return , exprOut{}
					}
				}
Copy the side effect flags over in case this expression is unused
We should never get here
		panic("Internal error")

A missing tag is a fragment
		 := .Tag
		if  == nil {
			 := .jsxStringsToMemberExpression(.Loc, .options.jsx.Fragment)
			 = &
		} else {
			* = .visitExpr(*)
		}
Visit properties
		for ,  := range .Properties {
			if .Kind != js_ast.PropertySpread {
				.Key = .visitExpr(.Key)
			}
			if .Value != nil {
				*.Value = .visitExpr(*.Value)
			}
			if .Initializer != nil {
				*.Initializer = .visitExpr(*.Initializer)
			}
			.Properties[] = 
		}
Arguments to createElement()
		 := []js_ast.Expr{*}
		if len(.Properties) > 0 {
			 = append(, .lowerObjectSpread(.Loc, &js_ast.EObject{
				Properties: .Properties,
			}))
		} else {
			 = append(, js_ast.Expr{Loc: .Loc, Data: &js_ast.ENull{}})
		}
		if len(.Children) > 0 {
			for ,  := range .Children {
				 = append(, .visitExpr())
			}
		}
Call createElement()
Enable tree shaking
			CanBeUnwrappedIfUnused: !.options.ignoreDCEAnnotations,
		}}, exprOut{}

	case *js_ast.ETemplate:
		if .LegacyOctalLoc.Start > 0 {
			.log.AddRangeError(&.source, .source.RangeOfLegacyOctalEscape(.LegacyOctalLoc),
				"Legacy octal escape sequences cannot be used in template literals")
		}
		if .Tag != nil {
			*.Tag = .visitExpr(*.Tag)
		}
		for ,  := range .Parts {
			.Parts[].Value = .visitExpr(.Value)
		}

		if .options.mangleSyntax {
			return .mangleTemplate(.Loc, ), exprOut{}
		}

	case *js_ast.EBinary:
		 :=  == .callTarget
		 := .isAnonymousNamedExpr(.Right)
		.Left, _ = .(.Left, exprIn{assignTarget: .Op.BinaryAssignTarget()})
Pattern-match "typeof require == 'function' && ___" from browserify
Mark the control flow as dead if the branch is never taken
		switch .Op {
		case js_ast.BinOpLogicalOr:
"true || dead"
"false && dead"
"notNullOrUndefined ?? dead"
				 := .isControlFlowDead
				.isControlFlowDead = true
				.Right = .visitExpr(.Right)
				.isControlFlowDead = 
			} else {
				.Right = .visitExpr(.Right)
			}

		default:
			.Right = .visitExpr(.Right)
		}
Always put constants on the right for equality comparisons to help reduce the number of cases we have to check during pattern matching. We can only reorder expressions that do not have any side effects.
Post-process the binary expression
		switch .Op {
"(1, 2)" => "2" "(sideEffects(), 2)" => "(sideEffects(), 2)"
"(1, fn)()" => "fn()" "(1, this.fn)" => "this.fn" "(1, this.fn)()" => "(0, this.fn)()"
					if  && hasValueForThisInCall(.Right) {
						return js_ast.JoinWithComma(js_ast.Expr{Loc: .Left.Loc, Data: &js_ast.ENumber{}}, .Right), exprOut{}
					}
					return .Right, exprOut{}
				}
			}

		case js_ast.BinOpLooseEq:
			if ,  := checkEqualityIfNoSideEffects(.Left.Data, .Right.Data);  {
				 := &js_ast.EBoolean{Value: }
Pattern-match "typeof require == 'function'" from browserify. Also match "'function' == typeof require" because some minifiers such as terser transpose the left and right operands to "==" to form a different but equivalent expression.
				if  && (.Left.Data == .typeofRequire || .Right.Data == .typeofRequire) {
					.typeofRequireEqualsFn = 
				}

				return js_ast.Expr{Loc: .Loc, Data: }, exprOut{}
			}
			 := locAfterOp()
			if !.warnAboutEqualityCheck("==", .Left, ) {
				.warnAboutEqualityCheck("==", .Right, )
			}
			.warnAboutTypeofAndString(.Left, .Right)

"x == void 0" => "x == null"
				if ,  := .Right.Data.(*js_ast.EUndefined);  {
					.Right.Data = &js_ast.ENull{}
				}

				if ,  := maybeSimplifyEqualityComparison(, false /* isNotEqual */);  {
					return , exprOut{}
				}
			}

		case js_ast.BinOpStrictEq:
			if ,  := checkEqualityIfNoSideEffects(.Left.Data, .Right.Data);  {
				return js_ast.Expr{Loc: .Loc, Data: &js_ast.EBoolean{Value: }}, exprOut{}
			}
			 := locAfterOp()
			if !.warnAboutEqualityCheck("===", .Left, ) {
				.warnAboutEqualityCheck("===", .Right, )
			}
			.warnAboutTypeofAndString(.Left, .Right)

"typeof x === 'undefined'" => "typeof x == 'undefined'"
				if canChangeStrictToLoose(.Left, .Right) {
					.Op = js_ast.BinOpLooseEq
				}

				if ,  := maybeSimplifyEqualityComparison(, false /* isNotEqual */);  {
					return , exprOut{}
				}
			}

		case js_ast.BinOpLooseNe:
			if ,  := checkEqualityIfNoSideEffects(.Left.Data, .Right.Data);  {
				return js_ast.Expr{Loc: .Loc, Data: &js_ast.EBoolean{Value: !}}, exprOut{}
			}
			 := locAfterOp()
			if !.warnAboutEqualityCheck("!=", .Left, ) {
				.warnAboutEqualityCheck("!=", .Right, )
			}
			.warnAboutTypeofAndString(.Left, .Right)

"x != void 0" => "x != null"
				if ,  := .Right.Data.(*js_ast.EUndefined);  {
					.Right.Data = &js_ast.ENull{}
				}

				if ,  := maybeSimplifyEqualityComparison(, true /* isNotEqual */);  {
					return , exprOut{}
				}
			}

		case js_ast.BinOpStrictNe:
			if ,  := checkEqualityIfNoSideEffects(.Left.Data, .Right.Data);  {
				return js_ast.Expr{Loc: .Loc, Data: &js_ast.EBoolean{Value: !}}, exprOut{}
			}
			 := locAfterOp()
			if !.warnAboutEqualityCheck("!==", .Left, ) {
				.warnAboutEqualityCheck("!==", .Right, )
			}
			.warnAboutTypeofAndString(.Left, .Right)

"typeof x !== 'undefined'" => "typeof x != 'undefined'"
				if canChangeStrictToLoose(.Left, .Right) {
					.Op = js_ast.BinOpLooseNe
				}

				if ,  := maybeSimplifyEqualityComparison(, true /* isNotEqual */);  {
					return , exprOut{}
				}
			}

		case js_ast.BinOpNullishCoalescing:
			if , ,  := toNullOrUndefinedWithSideEffects(.Left.Data);  {
				if ! {
					return .Left, exprOut{}
"(null ?? fn)()" => "fn()" "(null ?? this.fn)" => "this.fn" "(null ?? this.fn)()" => "(0, this.fn)()"
					if  && hasValueForThisInCall(.Right) {
						return js_ast.JoinWithComma(js_ast.Expr{Loc: .Left.Loc, Data: &js_ast.ENumber{}}, .Right), exprOut{}
					}

					return .Right, exprOut{}
				}
			}

"a ?? (b ?? c)" => "a ?? b ?? c"
				if ,  := .Right.Data.(*js_ast.EBinary);  && .Op == js_ast.BinOpNullishCoalescing {
					.Left = js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpNullishCoalescing, .Left, .Left)
					.Right = .Right
				}
			}

			if .options.unsupportedJSFeatures.Has(compat.NullishCoalescing) {
				return .lowerNullishCoalescing(.Loc, .Left, .Right), exprOut{}
			}

		case js_ast.BinOpLogicalOr:
			if , ,  := toBooleanWithSideEffects(.Left.Data);  {
				if  {
					return .Left, exprOut{}
"(0 || fn)()" => "fn()" "(0 || this.fn)" => "this.fn" "(0 || this.fn)()" => "(0, this.fn)()"
					if  && hasValueForThisInCall(.Right) {
						return js_ast.JoinWithComma(js_ast.Expr{Loc: .Left.Loc, Data: &js_ast.ENumber{}}, .Right), exprOut{}
					}
					return .Right, exprOut{}
				}
			}

"a || (b || c)" => "a || b || c"
				if ,  := .Right.Data.(*js_ast.EBinary);  && .Op == js_ast.BinOpLogicalOr {
					.Left = js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalOr, .Left, .Left)
					.Right = .Right
				}
"a === null || a === undefined" => "a == null"
				if , ,  := isBinaryNullAndUndefined(.Left, .Right, js_ast.BinOpStrictEq);  {
					.Op = js_ast.BinOpLooseEq
					.Left = 
					.Right = 
				}
			}

		case js_ast.BinOpLogicalAnd:
			if , ,  := toBooleanWithSideEffects(.Left.Data);  {
				if ! {
					return .Left, exprOut{}
"(1 && fn)()" => "fn()" "(1 && this.fn)" => "this.fn" "(1 && this.fn)()" => "(0, this.fn)()"
					if  && hasValueForThisInCall(.Right) {
						return js_ast.JoinWithComma(js_ast.Expr{Loc: .Left.Loc, Data: &js_ast.ENumber{}}, .Right), exprOut{}
					}
					return .Right, exprOut{}
				}
			}

"a && (b && c)" => "a && b && c"
				if ,  := .Right.Data.(*js_ast.EBinary);  && .Op == js_ast.BinOpLogicalAnd {
					.Left = js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalAnd, .Left, .Left)
					.Right = .Right
				}
"a !== null && a !== undefined" => "a != null"
				if , ,  := isBinaryNullAndUndefined(.Left, .Right, js_ast.BinOpStrictNe);  {
					.Op = js_ast.BinOpLooseNe
					.Left = 
					.Right = 
				}
			}

		case js_ast.BinOpAdd:
			if .shouldFoldNumericConstants {
				if , ,  := extractNumericValues(.Left, .Right);  {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value:  + }}, exprOut{}
				}
			}
"'abc' + 'xyz'" => "'abcxyz'"
			if  := foldStringAddition(.Left, .Right);  != nil {
				return *, exprOut{}
			}

"x + 'abc' + 'xyz'" => "x + 'abcxyz'"
				if  := foldStringAddition(.Right, .Right);  != nil {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: .Op, Left: .Left, Right: *}}, exprOut{}
				}
			}

		case js_ast.BinOpSub:
			if .shouldFoldNumericConstants {
				if , ,  := extractNumericValues(.Left, .Right);  {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value:  - }}, exprOut{}
				}
			}

		case js_ast.BinOpMul:
			if .shouldFoldNumericConstants {
				if , ,  := extractNumericValues(.Left, .Right);  {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value:  * }}, exprOut{}
				}
			}

		case js_ast.BinOpDiv:
			if .shouldFoldNumericConstants {
				if , ,  := extractNumericValues(.Left, .Right);  {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value:  / }}, exprOut{}
				}
			}

		case js_ast.BinOpRem:
			if .shouldFoldNumericConstants {
				if , ,  := extractNumericValues(.Left, .Right);  {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: math.Mod(, )}}, exprOut{}
				}
			}

		case js_ast.BinOpPow:
			if .shouldFoldNumericConstants {
				if , ,  := extractNumericValues(.Left, .Right);  {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: math.Pow(, )}}, exprOut{}
				}
			}
Lower the exponentiation operator for browsers that don't support it
			if .options.unsupportedJSFeatures.Has(compat.ExponentOperator) {
				return .callRuntime(.Loc, "__pow", []js_ast.Expr{.Left, .Right}), exprOut{}
			}

		case js_ast.BinOpShl:
			if .shouldFoldNumericConstants {
				if , ,  := extractNumericValues(.Left, .Right);  {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: float64(toInt32() << (toUint32() & 31))}}, exprOut{}
				}
			}

		case js_ast.BinOpShr:
			if .shouldFoldNumericConstants {
				if , ,  := extractNumericValues(.Left, .Right);  {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: float64(toInt32() >> (toUint32() & 31))}}, exprOut{}
				}
			}

		case js_ast.BinOpUShr:
			if .shouldFoldNumericConstants {
				if , ,  := extractNumericValues(.Left, .Right);  {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: float64(toUint32() >> (toUint32() & 31))}}, exprOut{}
				}
			}

		case js_ast.BinOpBitwiseAnd:
			if .shouldFoldNumericConstants {
				if , ,  := extractNumericValues(.Left, .Right);  {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: float64(toInt32() & toInt32())}}, exprOut{}
				}
			}

		case js_ast.BinOpBitwiseOr:
			if .shouldFoldNumericConstants {
				if , ,  := extractNumericValues(.Left, .Right);  {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: float64(toInt32() | toInt32())}}, exprOut{}
				}
			}

		case js_ast.BinOpBitwiseXor:
			if .shouldFoldNumericConstants {
				if , ,  := extractNumericValues(.Left, .Right);  {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: float64(toInt32() ^ toInt32())}}, exprOut{}
				}
			}
////////////////////////////////////////////////////////////////////////////// All assignment operators below here

Optionally preserve the name
			if ,  := .Left.Data.(*js_ast.EIdentifier);  {
				.Right = .maybeKeepExprSymbolName(.Right, .symbols[.Ref.InnerIndex].OriginalName, )
			}

			if , ,  := .extractPrivateIndex(.Left);  != nil {
				return .lowerPrivateSet(, , , .Right), exprOut{}
			}
Lower object rest patterns for browsers that don't support them. Note that assignment expressions are used to represent initializers in binding patterns, so only do this if we're not ourselves the target of an assignment. Example: "[a = b] = c"
			if .assignTarget == js_ast.AssignTargetNone {
				if ,  := .lowerObjectRestInAssign(.Left, .Right);  {
					return , exprOut{}
				}
			}

		case js_ast.BinOpAddAssign:
			if , ,  := .extractPrivateIndex(.Left);  != nil {
				return .lowerPrivateSetBinOp(, , , js_ast.BinOpAdd, .Right), exprOut{}
			}

		case js_ast.BinOpSubAssign:
			if , ,  := .extractPrivateIndex(.Left);  != nil {
				return .lowerPrivateSetBinOp(, , , js_ast.BinOpSub, .Right), exprOut{}
			}

		case js_ast.BinOpMulAssign:
			if , ,  := .extractPrivateIndex(.Left);  != nil {
				return .lowerPrivateSetBinOp(, , , js_ast.BinOpMul, .Right), exprOut{}
			}

		case js_ast.BinOpDivAssign:
			if , ,  := .extractPrivateIndex(.Left);  != nil {
				return .lowerPrivateSetBinOp(, , , js_ast.BinOpDiv, .Right), exprOut{}
			}

		case js_ast.BinOpRemAssign:
			if , ,  := .extractPrivateIndex(.Left);  != nil {
				return .lowerPrivateSetBinOp(, , , js_ast.BinOpRem, .Right), exprOut{}
			}

Lower the exponentiation operator for browsers that don't support it
			if .options.unsupportedJSFeatures.Has(compat.ExponentOperator) {
				return .lowerExponentiationAssignmentOperator(.Loc, ), exprOut{}
			}

			if , ,  := .extractPrivateIndex(.Left);  != nil {
				return .lowerPrivateSetBinOp(, , , js_ast.BinOpPow, .Right), exprOut{}
			}

		case js_ast.BinOpShlAssign:
			if , ,  := .extractPrivateIndex(.Left);  != nil {
				return .lowerPrivateSetBinOp(, , , js_ast.BinOpShl, .Right), exprOut{}
			}

		case js_ast.BinOpShrAssign:
			if , ,  := .extractPrivateIndex(.Left);  != nil {
				return .lowerPrivateSetBinOp(, , , js_ast.BinOpShr, .Right), exprOut{}
			}

		case js_ast.BinOpUShrAssign:
			if , ,  := .extractPrivateIndex(.Left);  != nil {
				return .lowerPrivateSetBinOp(, , , js_ast.BinOpUShr, .Right), exprOut{}
			}

		case js_ast.BinOpBitwiseOrAssign:
			if , ,  := .extractPrivateIndex(.Left);  != nil {
				return .lowerPrivateSetBinOp(, , , js_ast.BinOpBitwiseOr, .Right), exprOut{}
			}

		case js_ast.BinOpBitwiseAndAssign:
			if , ,  := .extractPrivateIndex(.Left);  != nil {
				return .lowerPrivateSetBinOp(, , , js_ast.BinOpBitwiseAnd, .Right), exprOut{}
			}

		case js_ast.BinOpBitwiseXorAssign:
			if , ,  := .extractPrivateIndex(.Left);  != nil {
				return .lowerPrivateSetBinOp(, , , js_ast.BinOpBitwiseXor, .Right), exprOut{}
			}

		case js_ast.BinOpNullishCoalescingAssign:
			if .options.unsupportedJSFeatures.Has(compat.LogicalAssignment) {
				return .lowerNullishCoalescingAssignmentOperator(.Loc, ), exprOut{}
			}

		case js_ast.BinOpLogicalAndAssign:
			if .options.unsupportedJSFeatures.Has(compat.LogicalAssignment) {
				return .lowerLogicalAssignmentOperator(.Loc, , js_ast.BinOpLogicalAnd), exprOut{}
			}

		case js_ast.BinOpLogicalOrAssign:
			if .options.unsupportedJSFeatures.Has(compat.LogicalAssignment) {
				return .lowerLogicalAssignmentOperator(.Loc, , js_ast.BinOpLogicalOr), exprOut{}
			}
		}
"(a, b) + c" => "a, b + c"
		if .options.mangleSyntax && .Op != js_ast.BinOpComma {
			if ,  := .Left.Data.(*js_ast.EBinary);  && .Op == js_ast.BinOpComma {
				return js_ast.JoinWithComma(.Left, js_ast.Expr{
					Loc: .Right.Loc,
					Data: &js_ast.EBinary{
						Op:    .Op,
						Left:  .Right,
						Right: .Right,
					},
				}), exprOut{}
			}
		}

"a['b']" => "a.b"
		if .options.mangleSyntax {
			if ,  := .Index.Data.(*js_ast.EString);  && js_lexer.IsIdentifierUTF16(.Value) {
				return .(js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
					Target:        .Target,
					Name:          js_lexer.UTF16ToString(.Value),
					NameLoc:       .Index.Loc,
					OptionalChain: .OptionalChain,
				}}, )
			}
		}

		 :=  == .callTarget
		 :=  == .deleteTarget
		,  := .(.Target, exprIn{
			hasChainParent: .OptionalChain == js_ast.OptionalChainContinue,
		})
		.Target = 
Special-case EPrivateIdentifier to allow it here
		if ,  := .Index.Data.(*js_ast.EPrivateIdentifier);  {
			 := .loadNameFromRef(.Ref)
			 := .findSymbol(.Index.Loc, )
			.Ref = .ref
Unlike regular identifiers, there are no unbound private identifiers
			 := .symbols[.ref.InnerIndex].Kind
			if !.IsPrivate() {
				 := logger.Range{Loc: .Index.Loc, Len: int32(len())}
				.log.AddRangeError(&.source, , fmt.Sprintf("Private name %q must be declared in an enclosing class", ))
			} else if !.options.suppressWarningsAboutWeirdCode {
				if .assignTarget != js_ast.AssignTargetNone && ( == js_ast.SymbolPrivateGet ||  == js_ast.SymbolPrivateStaticGet) {
					 := logger.Range{Loc: .Index.Loc, Len: int32(len())}
					.log.AddRangeWarning(&.source, , fmt.Sprintf("Writing to getter-only property %q will throw", ))
				} else if .assignTarget != js_ast.AssignTargetReplace && ( == js_ast.SymbolPrivateSet ||  == js_ast.SymbolPrivateStaticSet) {
					 := logger.Range{Loc: .Index.Loc, Len: int32(len())}
					.log.AddRangeWarning(&.source, , fmt.Sprintf("Reading from setter-only property %q will throw", ))
				}
			}
Lower private member access only if we're sure the target isn't needed for the value of "this" for a call expression. All other cases will be taken care of by the enclosing call expression.
"foo.#bar" => "__privateGet(foo, #bar)"
				return .lowerPrivateGet(.Target, .Index.Loc, ), exprOut{}
			}
		} else {
			.Index = .visitExpr(.Index)
		}
Lower "super[prop]" if necessary
		if ! && .shouldLowerSuperPropertyAccess(.Target) {
			return .lowerSuperPropertyAccess(.Loc, .Index), exprOut{}
		}
Lower optional chaining if we're the top of the chain
		 := .OptionalChain != js_ast.OptionalChainNone
		if  && !.hasChainParent {
			return .lowerOptionalChain(, , )
		}
Potentially rewrite this property access
		 = exprOut{
			childContainsOptionalChain: ,
			thisArgFunc:                .thisArgFunc,
			thisArgWrapFunc:            .thisArgWrapFunc,
		}
		if !.hasChainParent {
			.thisArgFunc = nil
			.thisArgWrapFunc = nil
		}
		if ,  := .Index.Data.(*js_ast.EString);  {
			 := js_lexer.UTF16ToString(.Value)
			if ,  := .maybeRewritePropertyAccess(
				.Loc, .assignTarget, , .OptionalChain, .Target, , .Index.Loc, );  {
				return , 
			}
		}
Create an error for assigning to an import namespace when bundling. Even though this is a run-time error, we make it a compile-time error when bundling because scope hoisting means these will no longer be run-time errors.
		if .options.mode == config.ModeBundle && (.assignTarget != js_ast.AssignTargetNone || ) {
			if ,  := .Target.Data.(*js_ast.EIdentifier);  && .symbols[.Ref.InnerIndex].Kind == js_ast.SymbolImport {
				 := js_lexer.RangeOfIdentifier(.source, .Target.Loc)
				.log.AddRangeError(&.source, , fmt.Sprintf("Cannot assign to property on import %q", .symbols[.Ref.InnerIndex].OriginalName))
			}
		}

		return js_ast.Expr{Loc: .Loc, Data: }, 

	case *js_ast.EUnary:
		switch .Op {
		case js_ast.UnOpTypeof:
			.typeofTarget = .Value.Data

			,  := .Value.Data.(*js_ast.EIdentifier)
			.Value, _ = .(.Value, exprIn{assignTarget: .Op.UnaryAssignTarget()})
			,  := .Value.Data.(*js_ast.EIdentifier)
The expression "typeof (0, x)" must not become "typeof x" if "x" is unbound because that could suppress a ReferenceError from "x"
			if ! &&  && .symbols[.Ref.InnerIndex].Kind == js_ast.SymbolUnbound {
				.Value = js_ast.JoinWithComma(js_ast.Expr{Loc: .Value.Loc, Data: &js_ast.ENumber{}}, .Value)
			}
"typeof require" => "'function'"
			if .options.mode == config.ModeBundle {
				if ,  := .Value.Data.(*js_ast.EIdentifier);  && .Ref == .requireRef {
					.ignoreUsage(.requireRef)
					.typeofRequire = &js_ast.EString{Value: js_lexer.StringToUTF16("function")}
					return js_ast.Expr{Loc: .Loc, Data: .typeofRequire}, exprOut{}
				}
			}

			if ,  := typeofWithoutSideEffects(.Value.Data);  {
				return js_ast.Expr{Loc: .Loc, Data: &js_ast.EString{Value: js_lexer.StringToUTF16()}}, exprOut{}
			}

Warn about code that tries to do "delete super.foo"
			var  logger.Loc
			switch e2 := .Value.Data.(type) {
			case *js_ast.EDot:
				if ,  := .Target.Data.(*js_ast.ESuper);  {
					 = .Target.Loc
				}
			case *js_ast.EIndex:
				if ,  := .Target.Data.(*js_ast.ESuper);  {
					 = .Target.Loc
				}
			case *js_ast.EIdentifier:
				.markStrictModeFeature(deleteBareName, js_lexer.RangeOfIdentifier(.source, .Value.Loc), "")
			}
			if !.options.suppressWarningsAboutWeirdCode && .Start != 0 {
				 := js_lexer.RangeOfIdentifier(.source, )
				.log.AddRangeWarning(&.source, , "Attempting to delete a property of \"super\" will throw a ReferenceError")
			}

			.deleteTarget = .Value.Data
			 := canBeDeleted(.Value)
			,  := .(.Value, exprIn{hasChainParent: true})
			.Value = 
			 := canBeDeleted(.Value)
Lower optional chaining if present since we're guaranteed to be the end of the chain
			if .childContainsOptionalChain {
				return .lowerOptionalChain(, , )
			}
Make sure we don't accidentally change the return value Returns false: "var a; delete (a)" "var a = Object.freeze({b: 1}); delete (a.b)" "var a = Object.freeze({b: 1}); delete (a?.b)" "var a = Object.freeze({b: 1}); delete (a['b'])" "var a = Object.freeze({b: 1}); delete (a?.['b'])" Returns true: "var a; delete (0, a)" "var a = Object.freeze({b: 1}); delete (true && a.b)" "var a = Object.freeze({b: 1}); delete (false || a?.b)" "var a = Object.freeze({b: 1}); delete (null ?? a?.['b'])" "var a = Object.freeze({b: 1}); delete (true ? a['b'] : a['b'])"
			if  && ! {
				.Value = js_ast.JoinWithComma(js_ast.Expr{Loc: .Value.Loc, Data: &js_ast.ENumber{}}, .Value)
			}

		default:
			.Value, _ = .(.Value, exprIn{assignTarget: .Op.UnaryAssignTarget()})
Post-process the unary expression
			switch .Op {
			case js_ast.UnOpNot:
				if .options.mangleSyntax {
					.Value = .simplifyBooleanExpr(.Value)
				}

				if , ,  := toBooleanWithSideEffects(.Value.Data);  &&  == noSideEffects {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.EBoolean{Value: !}}, exprOut{}
				}

				if .options.mangleSyntax {
					if ,  := js_ast.MaybeSimplifyNot(.Value);  {
						return , exprOut{}
					}
				}

			case js_ast.UnOpVoid:
				if .exprCanBeRemovedIfUnused(.Value) {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.EUndefined{}}, exprOut{}
				}

			case js_ast.UnOpPos:
				if ,  := toNumberWithoutSideEffects(.Value.Data);  {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: }}, exprOut{}
				}

			case js_ast.UnOpNeg:
				if ,  := toNumberWithoutSideEffects(.Value.Data);  {
					return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: -}}, exprOut{}
				}
////////////////////////////////////////////////////////////////////////////// All assignment operators below here

			case js_ast.UnOpPreDec:
				if , ,  := .extractPrivateIndex(.Value);  != nil {
					return .lowerPrivateSetUnOp(, , , js_ast.BinOpSub, false), exprOut{}
				}

			case js_ast.UnOpPreInc:
				if , ,  := .extractPrivateIndex(.Value);  != nil {
					return .lowerPrivateSetUnOp(, , , js_ast.BinOpAdd, false), exprOut{}
				}

			case js_ast.UnOpPostDec:
				if , ,  := .extractPrivateIndex(.Value);  != nil {
					return .lowerPrivateSetUnOp(, , , js_ast.BinOpSub, true), exprOut{}
				}

			case js_ast.UnOpPostInc:
				if , ,  := .extractPrivateIndex(.Value);  != nil {
					return .lowerPrivateSetUnOp(, , , js_ast.BinOpAdd, true), exprOut{}
				}
			}
		}
"-(a, b)" => "a, -b"
		if .options.mangleSyntax && .Op != js_ast.UnOpDelete && .Op != js_ast.UnOpTypeof {
			if ,  := .Value.Data.(*js_ast.EBinary);  && .Op == js_ast.BinOpComma {
				return js_ast.JoinWithComma(.Left, js_ast.Expr{
					Loc: .Right.Loc,
					Data: &js_ast.EUnary{
						Op:    .Op,
						Value: .Right,
					},
				}), exprOut{}
			}
		}

	case *js_ast.EDot:
		 :=  == .deleteTarget
		 :=  == .callTarget
Check both user-specified defines and known globals
		if ,  := .options.defines.DotDefines[.Name];  {
			for ,  := range  {
Substitute user-specified defines
					if .Data.DefineFunc != nil {
						return .valueForDefine(.Loc, .assignTarget, , .Data.DefineFunc), exprOut{}
					}
Copy the side effect flags over in case this expression is unused
This helps us pattern-match "require.someProperty" when targeting CommonJS
Track ".then().catch()" chains
		if  && .thenCatchChain.nextTarget ==  {
			if .Name == "catch" {
				.thenCatchChain = thenCatchChain{
					nextTarget: .Target.Data,
					hasCatch:   true,
				}
			} else if .Name == "then" {
				.thenCatchChain = thenCatchChain{
					nextTarget: .Target.Data,
					hasCatch:   .thenCatchChain.hasCatch || .thenCatchChain.hasMultipleArgs,
				}
			}
		}

		,  := .(.Target, exprIn{
			hasChainParent: .OptionalChain == js_ast.OptionalChainContinue,
		})
		.Target = 
Lower "super.prop" if necessary
Lower optional chaining if we're the top of the chain
		 := .OptionalChain != js_ast.OptionalChainNone
		if  && !.hasChainParent {
			return .lowerOptionalChain(, , )
		}
Potentially rewrite this property access
		 = exprOut{
			childContainsOptionalChain: ,
			thisArgFunc:                .thisArgFunc,
			thisArgWrapFunc:            .thisArgWrapFunc,
		}
		if !.hasChainParent {
			.thisArgFunc = nil
			.thisArgWrapFunc = nil
		}
		if ,  := .maybeRewritePropertyAccess(.Loc, .assignTarget, , .OptionalChain, .Target, .Name, .NameLoc, );  {
			return , 
		}
		return js_ast.Expr{Loc: .Loc, Data: }, 

	case *js_ast.EIf:
		 :=  == .callTarget
		.Test = .visitExpr(.Test)

		if .options.mangleSyntax {
			.Test = .simplifyBooleanExpr(.Test)
		}
Fold constants
		if , ,  := toBooleanWithSideEffects(.Test.Data); ! {
			.Yes = .visitExpr(.Yes)
			.No = .visitExpr(.No)
Mark the control flow as dead if the branch is never taken
"true ? live : dead"
"(a, true) ? b : c" => "a, b"
					if  == couldHaveSideEffects {
						return maybeJoinWithComma(.simplifyUnusedExpr(.Test), .Yes), exprOut{}
					}
"(1 ? fn : 2)()" => "fn()" "(1 ? this.fn : 2)" => "this.fn" "(1 ? this.fn : 2)()" => "(0, this.fn)()"
					if  && hasValueForThisInCall(.Yes) {
						return js_ast.JoinWithComma(js_ast.Expr{Loc: .Test.Loc, Data: &js_ast.ENumber{}}, .Yes), exprOut{}
					}

					return .Yes, exprOut{}
				}
"false ? dead : live"
"(a, false) ? b : c" => "a, c"
					if  == couldHaveSideEffects {
						return maybeJoinWithComma(.simplifyUnusedExpr(.Test), .No), exprOut{}
					}
"(0 ? 1 : fn)()" => "fn()" "(0 ? 1 : this.fn)" => "this.fn" "(0 ? 1 : this.fn)()" => "(0, this.fn)()"
					if  && hasValueForThisInCall(.No) {
						return js_ast.JoinWithComma(js_ast.Expr{Loc: .Test.Loc, Data: &js_ast.ENumber{}}, .No), exprOut{}
					}

					return .No, exprOut{}
				}
			}
		}

		if .options.mangleSyntax {
			return .mangleIfExpr(.Loc, ), exprOut{}
		}

	case *js_ast.EAwait:
		.awaitTarget = .Value.Data
		.Value = .visitExpr(.Value)
"await" expressions turn into "yield" expressions when lowering
		if .options.unsupportedJSFeatures.Has(compat.AsyncAwait) {
			return js_ast.Expr{Loc: .Loc, Data: &js_ast.EYield{Value: &.Value}}, exprOut{}
		}

	case *js_ast.EYield:
		if .Value != nil {
			*.Value = .visitExpr(*.Value)
		}

	case *js_ast.EArray:
		if .assignTarget != js_ast.AssignTargetNone {
			if .CommaAfterSpread.Start != 0 {
				.log.AddRangeError(&.source, logger.Range{Loc: .CommaAfterSpread, Len: 1}, "Unexpected \",\" after rest pattern")
			}
			.markSyntaxFeature(compat.Destructuring, logger.Range{Loc: .Loc, Len: 1})
		}
		 := false
		for ,  := range .Items {
			switch e2 := .Data.(type) {
			case *js_ast.EMissing:
			case *js_ast.ESpread:
				.Value, _ = .(.Value, exprIn{assignTarget: .assignTarget})
				 = true
			case *js_ast.EBinary:
				if .assignTarget != js_ast.AssignTargetNone && .Op == js_ast.BinOpAssign {
					 := .isAnonymousNamedExpr(.Right)
					.Left, _ = .(.Left, exprIn{assignTarget: js_ast.AssignTargetReplace})
					.Right = .visitExpr(.Right)
Optionally preserve the name
					if ,  := .Left.Data.(*js_ast.EIdentifier);  {
						.Right = .maybeKeepExprSymbolName(
							.Right, .symbols[.Ref.InnerIndex].OriginalName, )
					}
				} else {
					, _ = .(, exprIn{assignTarget: .assignTarget})
				}
			default:
				, _ = .(, exprIn{assignTarget: .assignTarget})
			}
			.Items[] = 
		}
"[1, ...[2, 3], 4]" => "[1, 2, 3, 4]"
		if .options.mangleSyntax &&  && .assignTarget == js_ast.AssignTargetNone {
			.Items = inlineSpreadsOfArrayLiterals(.Items)
		}

	case *js_ast.EObject:
		if .assignTarget != js_ast.AssignTargetNone {
			if .CommaAfterSpread.Start != 0 {
				.log.AddRangeError(&.source, logger.Range{Loc: .CommaAfterSpread, Len: 1}, "Unexpected \",\" after rest pattern")
			}
			.markSyntaxFeature(compat.Destructuring, logger.Range{Loc: .Loc, Len: 1})
		}
		 := false
		 := false
		for  := range .Properties {
			 := &.Properties[]

			if .Kind != js_ast.PropertySpread {
				 := .visitExpr(.Key)
				.Properties[].Key = 
Forbid duplicate "__proto__" properties according to the specification
				if !.IsComputed && !.WasShorthand && !.IsMethod && .assignTarget == js_ast.AssignTargetNone {
					if ,  := .Data.(*js_ast.EString);  && js_lexer.UTF16EqualsString(.Value, "__proto__") {
						if  {
							 := js_lexer.RangeOfIdentifier(.source, .Loc)
							.log.AddRangeError(&.source, , "Cannot specify the \"__proto__\" property more than once per object")
						}
						 = true
					}
				}
"{['x']: y}" => "{x: y}"
				if .options.mangleSyntax && .IsComputed {
					if ,  := .Data.(*js_ast.EString);  && js_lexer.IsIdentifierUTF16(.Value) {
						.IsComputed = false
					}
				}
			} else {
				 = true
			}
Extract the initializer for expressions like "({ a: b = c } = d)"
			if .assignTarget != js_ast.AssignTargetNone && .Initializer == nil && .Value != nil {
				if ,  := .Value.Data.(*js_ast.EBinary);  && .Op == js_ast.BinOpAssign {
					.Initializer = &.Right
					.Value = &.Left
				}
			}

			if .Value != nil {
				*.Value, _ = .(*.Value, exprIn{assignTarget: .assignTarget})
			}
			if .Initializer != nil {
				 := .isAnonymousNamedExpr(*.Initializer)
				*.Initializer = .visitExpr(*.Initializer)
Optionally preserve the name
				if .Value != nil {
					if ,  := .Value.Data.(*js_ast.EIdentifier);  {
						*.Initializer = .maybeKeepExprSymbolName(
							*.Initializer, .symbols[.Ref.InnerIndex].OriginalName, )
					}
				}
			}
		}
Check for and warn about duplicate keys in object literals
		if len(.Properties) > 1 && !.options.suppressWarningsAboutWeirdCode {
			type  uint8
			type  struct {
				  logger.Loc
				 
			}
			const (
				  = iota
				
				
				
				
			)
			 := make(map[string])
			for ,  := range .Properties {
				if .Kind != js_ast.PropertySpread {
					if ,  := .Key.Data.(*js_ast.EString);  {
						 := js_lexer.UTF16ToString(.Value)
						 := []
						 := {: , : .Key.Loc}
						if .Kind == js_ast.PropertyGet {
							. = 
						} else if .Kind == js_ast.PropertySet {
							. = 
						}
						if . !=  &&  != "__proto__" {
							if (. ==  && . == ) || (. ==  && . == ) {
								. = 
							} else {
								 := js_lexer.RangeOfIdentifier(.source, .Key.Loc)
								.log.AddRangeWarningWithNotes(&.source, , fmt.Sprintf("Duplicate key %q in object literal", ),
									[]logger.MsgData{logger.RangeData(&.source, js_lexer.RangeOfIdentifier(.source, .),
										fmt.Sprintf("The original %q is here", ))})
							}
						}
						[] = 
					}
				}
			}
		}

"{a, ...{b, c}, d}" => "{a, b, c, d}"
			if .options.mangleSyntax &&  {
				var  []js_ast.Property
				for ,  := range .Properties {
					if .Kind == js_ast.PropertySpread {
						switch v := .Value.Data.(type) {
						case *js_ast.EBoolean, *js_ast.ENull, *js_ast.EUndefined, *js_ast.ENumber,
This value is ignored because it doesn't have any of its own properties
							continue

						case *js_ast.EObject:
Getters are evaluated at iteration time. The property descriptor is not inlined into the caller. Since we are not evaluating code at compile time, just bail if we hit one and preserve the spread with the remaining properties.
								if .Kind == js_ast.PropertyGet || .Kind == js_ast.PropertySet {
									.Properties = .Properties[:]
									 = append(, )
									break
								}
								 = append(, )
							}
							continue
						}
					}
					 = append(, )
				}
				.Properties = 
			}
Object expressions represent both object literals and binding patterns. Only lower object spread if we're an object literal, not a binding pattern.
			return .lowerObjectSpread(.Loc, ), exprOut{}
		}

	case *js_ast.EImport:
		 :=  == .awaitTarget
		 :=  == .thenCatchChain.nextTarget && .thenCatchChain.hasCatch
		.Expr = .visitExpr(.Expr)

The argument must be a string
Ignore calls to import() if the control flow is provably dead here. We don't want to spend time scanning the required files if they will never be used.
Heuristic: omit warnings when using "await import()" inside a try block because presumably the try block is there to handle the potential run-time error from the unbundled "await import()" call failing. Also support the "import().then(pass, fail)" pattern as well as the "import().catch(fail)" pattern.
				 := (.fnOrArrowDataVisit.tryBodyCount != 0 && ) || 

				if ! {
					 := "This dynamic import will not be bundled because the argument is not a string literal"
					if  {
						 += " (surround with a try/catch to silence this warning)"
					} else {
						 += " (use \"import().catch()\" to silence this warning)"
					}
					 := js_lexer.RangeOfIdentifier(.source, .Loc)
					.log.AddRangeWarning(&.source, , )
				}
			}
We need to convert this into a call to "require()" if ES6 syntax is not supported in the current output format. The full conversion: Before: import(foo) After: Promise.resolve().then(() => require(foo)) This is normally done by the printer since we don't know during the parsing stage whether this module is external or not. However, it's guaranteed to be external if the argument isn't a string. We handle this case here instead of in the printer because both the printer and the linker currently need an import record to handle this case correctly, and you need a string literal to get an import record.
			if !.options.outputFormat.KeepES6ImportExportSyntax() {
				var  js_ast.Expr
				 := .callRuntime(.Loc, "__toModule", []js_ast.Expr{{Loc: .Loc, Data: &js_ast.ECall{
					Target: js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .requireRef}},
					Args:   []js_ast.Expr{},
				}}})
				 := js_ast.FnBody{Loc: .Loc, Stmts: []js_ast.Stmt{{Loc: .Loc, Data: &js_ast.SReturn{Value: &}}}}
				if .options.unsupportedJSFeatures.Has(compat.Arrow) {
					 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EFunction{Fn: js_ast.Fn{Body: }}}
				} else {
					 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EArrow{Body: , PreferExpr: true}}
				}
				return 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.ECall{
							Target: js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
								Target:  js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .makePromiseRef()}},
								Name:    "resolve",
								NameLoc: .Loc,
							}},
						}},
						Name:    "then",
						NameLoc: .Loc,
					}},
					Args: []js_ast.Expr{},
				}}
			}

			return js_ast.Expr{Loc: .Loc, Data: &js_ast.EImport{
				Expr:                    ,
				LeadingInteriorComments: .LeadingInteriorComments,
			}}
		}), exprOut{}

	case *js_ast.ECall:
		.callTarget = .Target.Data
Prepare to recognize "require.resolve()" calls
		 := false
		if len(.Args) == 1 && .options.mode != config.ModePassThrough {
			if ,  := .Target.Data.(*js_ast.EDot);  && .OptionalChain == js_ast.OptionalChainNone && .Name == "resolve" {
				.resolveCallTarget = .Target.Data
				 = true
			}
		}

		,  := .Target.Data.(*js_ast.EIdentifier)
		,  := .(.Target, exprIn{
			hasChainParent: .OptionalChain == js_ast.OptionalChainContinue,
Signal to our child if this is an ECall at the start of an optional chain. If so, the child will need to stash the "this" context for us that we need for the ".call(this, ...args)".
			storeThisArgForParentOptionalChain: .OptionalChain == js_ast.OptionalChainStart,
		})
		.Target = 
		.warnAboutImportNamespaceCallOrConstruct(.Target, false /* isConstruct */)

		 := false
		for ,  := range .Args {
			 = .visitExpr()
			if ,  := .Data.(*js_ast.ESpread);  {
				 = true
			}
			.Args[] = 
		}
Recognize "require.resolve()" calls
		if  {
			if ,  := .Target.Data.(*js_ast.EDot);  {
				if ,  := .Target.Data.(*js_ast.EIdentifier);  && .Ref == .requireRef {
					return .maybeTransposeIfExprChain(.Args[0], func( js_ast.Expr) js_ast.Expr {
Ignore calls to require.resolve() if the control flow is provably dead here. We don't want to spend time scanning the required files if they will never be used.
Create a new expression to represent the operation
							.ignoreUsage(.requireRef)
							return js_ast.Expr{Loc: .Loc, Data: &js_ast.ERequireResolve{ImportRecordIndex: }}
						}
Otherwise just return a clone of the "require.resolve()" call
						return js_ast.Expr{Loc: .Loc, Data: &js_ast.ECall{
							Target: js_ast.Expr{Loc: .Target.Loc, Data: &js_ast.EDot{
								Target:  js_ast.Expr{Loc: .Target.Loc, Data: &js_ast.EIdentifier{Ref: .Ref}},
								Name:    .Name,
								NameLoc: .NameLoc,
							}},
							Args: []js_ast.Expr{},
						}}
					}), exprOut{}
				}
			}
		}
"foo(1, ...[2, 3], 4)" => "foo(1, 2, 3, 4)"
Detect if this is a direct eval. Note that "(1 ? eval : 0)(x)" will become "eval(x)" after we visit the target due to dead code elimination, but that doesn't mean it should become a direct eval.
		if  {
			if ,  := .Target.Data.(*js_ast.EIdentifier);  {
				if  := .symbols[.Ref.InnerIndex]; .OriginalName == "eval" {
					.IsDirectEval = true
Pessimistically assume that if this looks like a CommonJS module (no "import" or "export" keywords), a direct call to "eval" means that code could potentially access "module" or "exports".
Mark this scope and all parent scopes as containing a direct eval. This will prevent us from renaming any symbols.
					for  := .currentScope;  != nil;  = .Parent {
						.ContainsDirectEval = true
					}
Warn when direct eval is used in a file with ES6 import statements. There is no way we can guarantee that this will work correctly. Except don't warn when this code is in a 3rd-party library because there's nothing people will be able to do about the warning.
					if .options.mode == config.ModeBundle && .es6ImportKeyword.Len > 0 && !.options.suppressWarningsAboutWeirdCode {
						.log.AddRangeWarning(&.source, js_lexer.RangeOfIdentifier(.source, .Target.Loc),
							"Using direct eval with a bundler is not recommended and may cause problems (more info: https://esbuild.github.io/link/direct-eval)")
					}
				}
			}
		}
Copy the call side effect flag over if this is a known target
Lower optional chaining if we're the top of the chain
		 := .OptionalChain != js_ast.OptionalChainNone
		if  && !.hasChainParent {
			return .lowerOptionalChain(, , )
		}
If this is a plain call expression (instead of an optional chain), lower private member access in the call target now if there is one
		if ! {
"foo.#bar(123)" => "__privateGet(foo, #bar).call(foo, 123)"
				,  := .captureValueWithPossibleSideEffects(.Loc, 2, )
				return (js_ast.Expr{Loc: .Loc, Data: &js_ast.ECall{
					Target: js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
						Target:  .lowerPrivateGet((), , ),
						Name:    "call",
						NameLoc: .Loc,
					}},
					Args:                   append([]js_ast.Expr{()}, .Args...),
					CanBeUnwrappedIfUnused: .CanBeUnwrappedIfUnused,
				}}), exprOut{}
			}
			.maybeLowerSuperPropertyAccessInsideCall()
		}
Track calls to require() so we can use them while bundling
Heuristic: omit warnings inside try/catch blocks because presumably the try/catch statement is there to handle the potential run-time error from the unbundled require() call failing.
				 := .fnOrArrowDataVisit.tryBodyCount != 0

There must be one argument
					if len(.Args) == 1 {
The argument must be a string
Ignore calls to require() if the control flow is provably dead here. We don't want to spend time scanning the required files if they will never be used.
Create a new expression to represent the operation
								.ignoreUsage(.requireRef)
								return js_ast.Expr{Loc: .Loc, Data: &js_ast.ERequire{ImportRecordIndex: }}
							}

							if ! {
								 := js_lexer.RangeOfIdentifier(.source, .Target.Loc)
								.log.AddRangeWarning(&.source, ,
									"This call to \"require\" will not be bundled because the argument is not a string literal (surround with a try/catch to silence this warning)")
							}
Otherwise just return a clone of the "require()" call
							return js_ast.Expr{Loc: .Loc, Data: &js_ast.ECall{
								Target: js_ast.Expr{Loc: .Target.Loc, Data: &js_ast.EIdentifier{Ref: .Ref}},
								Args:   []js_ast.Expr{},
							}}
						}), exprOut{}
					} else if ! {
						 := js_lexer.RangeOfIdentifier(.source, .Target.Loc)
						.log.AddRangeWarning(&.source, , fmt.Sprintf(
							"This call to \"require\" will not be bundled because it has %d arguments (surround with a try/catch to silence this warning)", len(.Args)))
					}
				} else if .options.outputFormat == config.FormatESModule && ! {
					 := js_lexer.RangeOfIdentifier(.source, .Target.Loc)
					.log.AddRangeWarning(&.source, , "Converting \"require\" to \"esm\" is currently not supported")
				}
			}
		}

		 = exprOut{
			childContainsOptionalChain: ,
			thisArgFunc:                .thisArgFunc,
			thisArgWrapFunc:            .thisArgWrapFunc,
		}
		if !.hasChainParent {
			.thisArgFunc = nil
			.thisArgWrapFunc = nil
		}
		return , 

	case *js_ast.ENew:
		.Target = .visitExpr(.Target)
		.warnAboutImportNamespaceCallOrConstruct(.Target, true /* isConstruct */)

		for ,  := range .Args {
			.Args[] = .visitExpr()
		}

	case *js_ast.EArrow:
		 := .fnOrArrowDataVisit
		.fnOrArrowDataVisit = fnOrArrowDataVisit{
			isArrow: true,
			isAsync: .IsAsync,
		}
Mark if we're inside an async arrow function. This value should be true even if we're inside multiple arrow functions and the closest inclosing arrow function isn't async, as long as at least one enclosing arrow function within the current enclosing function is async.
"() => { return }" => "() => {}"
					.Body.Stmts = []js_ast.Stmt{}
"() => { return x }" => "() => x"
					.PreferExpr = true
				}
			}
		}

		.fnOnlyDataVisit.isInsideAsyncArrowFn = 
		.fnOrArrowDataVisit = 
Convert arrow functions to function expressions when lowering
Remove unused function names when minifying
		if .options.mangleSyntax &&  != nil && .symbols[.Ref.InnerIndex].UseCountEstimate == 0 {
			.Fn.Name = nil
		}
Optionally preserve the name
		if .options.keepNames &&  != nil {
			 = .keepExprSymbolName(, .symbols[.Ref.InnerIndex].OriginalName)
		}

	case *js_ast.EClass:
		 := .visitClass(.Loc, &.Class)
Lower class field syntax for browsers that don't support it
		_,  = .lowerClass(js_ast.Stmt{}, , )

	default:
		panic("Internal error")
	}

	return , exprOut{}
}

func ( *parser) ( js_ast.Expr,  bool) {
	if .options.outputFormat != config.FormatPreserve {
		if ,  := .Data.(*js_ast.EIdentifier);  && .importItemsForNamespace[.Ref] != nil {
			 := js_lexer.RangeOfIdentifier(.source, .Loc)
			 := ""
			if .options.ts.Parse {
				 = " (make sure to enable TypeScript's \"esModuleInterop\" setting)"
			}
			var  []logger.MsgData
			 := .symbols[.Ref.InnerIndex].OriginalName
			if ,  := .moduleScope.Members[];  && .Ref == .Ref {
				if  := .source.RangeOfOperatorBefore(.Loc, "*"); .Len > 0 {
					if  := .source.RangeOfOperatorBefore(.Loc, "as"); .Len > 0 && .Loc.Start > .Loc.Start {
						 := logger.RangeData(&.source,
							logger.Range{Loc: .Loc, Len: js_lexer.RangeOfIdentifier(.source, .Loc).End() - .Loc.Start},
							fmt.Sprintf("Consider changing %q to a default import instead", ))
						.Location.Suggestion = 
						 = []logger.MsgData{}
					}
				}
			}
			 := "Calling"
			 := "function"
			if  {
				 = "Constructing"
				 = "constructor"
			}
			.log.AddRangeWarningWithNotes(&.source, , fmt.Sprintf(
				"%s %q will crash at run-time because it's an import namespace object, not a %s%s",
				,
				.symbols[.Ref.InnerIndex].OriginalName,
				,
				),
				,
			)
		}
	}
}

func ( *parser) ( logger.Loc,  js_ast.AssignTarget,  bool,  config.DefineFunc) js_ast.Expr {
	 := js_ast.Expr{Loc: , Data: (config.DefineArgs{
		Loc:             ,
		FindSymbol:      .findSymbolHelper,
		SymbolForDefine: .symbolForDefineHelper,
	})}
	if ,  := .Data.(*js_ast.EIdentifier);  {
		return .handleIdentifier(, , identifierOpts{
			assignTarget:            ,
			isDeleteTarget:          ,
			wasOriginallyIdentifier: true,
		})
	}
	return 
}

type identifierOpts struct {
	assignTarget            js_ast.AssignTarget
	isDeleteTarget          bool
	wasOriginallyIdentifier bool
}

func ( *parser) ( logger.Loc,  *js_ast.EIdentifier,  identifierOpts) js_ast.Expr {
	 := .Ref
Capture the "arguments" variable if necessary
	if .fnOnlyDataVisit.argumentsRef != nil &&  == *.fnOnlyDataVisit.argumentsRef {
		 := .fnOrArrowDataVisit.isArrow && .options.unsupportedJSFeatures.Has(compat.Arrow)
		 := .fnOnlyDataVisit.isInsideAsyncArrowFn && .options.unsupportedJSFeatures.Has(compat.AsyncAwait)
		if  ||  {
			return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: .captureArguments()}}
		}
	}

	if .options.mode == config.ModeBundle && (.assignTarget != js_ast.AssignTargetNone || .isDeleteTarget) {
Create an error for assigning to an import namespace
			 := js_lexer.RangeOfIdentifier(.source, )
			.log.AddRangeError(&.source, , fmt.Sprintf("Cannot assign to import %q", .symbols[.InnerIndex].OriginalName))
Remember that this part assigns to this symbol for code splitting
			 := .symbolUses[]
			.IsAssigned = true
			.symbolUses[] = 
		}
	}
Substitute an EImportIdentifier now if this is an import item
Substitute a namespace export reference now if appropriate
	if .options.ts.Parse {
		if ,  := .isExportedInsideNamespace[];  {
			 := .symbols[.InnerIndex].OriginalName
If this is a known enum value, inline the value of the enum
			if ,  := .knownEnumValues[];  {
				if ,  := [];  {
					return js_ast.Expr{Loc: , Data: &js_ast.ENumber{Value: }}
				}
			}
Otherwise, create a property access on the namespace
			.recordUsage()
			return js_ast.Expr{Loc: , Data: &js_ast.EDot{
				Target:  js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }},
				Name:    ,
				NameLoc: ,
			}}
		}
	}
Warn about uses of "require" other than a direct "require()" call, a "typeof require" expression, or a "require.someProperty" access. But suppress warnings inside a try body block since presumably the try/catch is there to handle run-time failures due to indirect require calls.
"typeof require == 'function' && require"
Become "false" in the browser and "require" in node
			if .options.platform == config.PlatformBrowser {
				return js_ast.Expr{Loc: , Data: &js_ast.EBoolean{Value: false}}
			}
		} else if  != .resolveCallTarget {
			 := js_lexer.RangeOfIdentifier(.source, )
			.log.AddRangeWarning(&.source, ,
				"Indirect calls to \"require\" will not be bundled (surround with a try/catch to silence this warning)")
		}
	}

	return js_ast.Expr{Loc: , Data: }
}

func ( js_ast.Expr,  js_ast.Expr) (float64, float64, bool) {
	if ,  := .Data.(*js_ast.ENumber);  {
		if ,  := .Data.(*js_ast.ENumber);  {
			return .Value, .Value, true
		}
	}
	return 0, 0, false
}

func ( *parser) ( *js_ast.Fn,  logger.Loc) {
	 := .fnOrArrowDataVisit
	 := .fnOnlyDataVisit
	.fnOrArrowDataVisit = fnOrArrowDataVisit{
		isAsync: .IsAsync,
	}
	.fnOnlyDataVisit = fnOnlyDataVisit{
		isThisNested: true,
		argumentsRef: &.ArgumentsRef,
	}

	if .Name != nil {
		.recordDeclaredSymbol(.Name.Ref)
		if  := .symbols[.Name.Ref.InnerIndex].OriginalName; isEvalOrArguments() {
			.markStrictModeFeature(evalOrArguments, js_lexer.RangeOfIdentifier(.source, .Name.Loc), )
		}
	}

	.pushScopeForVisitPass(js_ast.ScopeFunctionArgs, )
	.visitArgs(.Args, visitArgsOpts{
		hasRestArg:               .HasRestArg,
		body:                     .Body.Stmts,
		isUniqueFormalParameters: .IsUniqueFormalParameters,
	})
	.pushScopeForVisitPass(js_ast.ScopeFunctionBody, .Body.Loc)
	.Body.Stmts = .visitStmtsAndPrependTempRefs(.Body.Stmts, prependTempRefsOpts{fnBodyLoc: &.Body.Loc, kind: stmtsFnBody})
	.popScope()
	.lowerFunction(&.IsAsync, &.Args, .Body.Loc, &.Body.Stmts, nil, &.HasRestArg, false /* isArrow */)
	.popScope()

	.fnOrArrowDataVisit = 
	.fnOnlyDataVisit = 
}

func ( *parser) ( logger.Loc,  string,  js_ast.Ref) {
Duplicate exports are an error
		.log.AddRangeErrorWithNotes(&.source, js_lexer.RangeOfIdentifier(.source, ),
			fmt.Sprintf("Multiple exports with the same name %q", ),
			[]logger.MsgData{logger.RangeData(&.source, js_lexer.RangeOfIdentifier(.source, .AliasLoc),
				fmt.Sprintf("%q was originally exported here", ))})
	} else {
		.namedExports[] = js_ast.NamedExport{AliasLoc: , Ref: }
	}
}

func ( *parser) ( js_ast.Binding) {
	switch b := .Data.(type) {
	case *js_ast.BMissing:

	case *js_ast.BIdentifier:
		.recordExport(.Loc, .symbols[.Ref.InnerIndex].OriginalName, .Ref)

	case *js_ast.BArray:
		for ,  := range .Items {
			.(.Binding)
		}

	case *js_ast.BObject:
		for ,  := range .Properties {
			.(.Value)
		}
	default:
		panic("Internal error")
	}
}

type scanForImportsAndExportsResult struct {
	stmts               []js_ast.Stmt
	keptImportEquals    bool
	removedImportEquals bool
}

func ( *parser) ( []js_ast.Stmt) ( scanForImportsAndExportsResult) {
	 := 0

	for ,  := range  {
		switch s := .Data.(type) {
		case *js_ast.SImport:
The official TypeScript compiler always removes unused imported symbols. However, we deliberately deviate from the official TypeScript compiler's behavior doing this in a specific scenario: we are not bundling, symbol renaming is off, and the tsconfig.json "importsNotUsedAsValues" setting is present and is not set to "remove". This exists to support the use case of compiling partial modules for compile-to-JavaScript languages such as Svelte. These languages try to reference imports in ways that are impossible for esbuild to know about when esbuild is only given a partial module to compile. Here is an example of some Svelte code that might use esbuild to convert TypeScript to JavaScript: <script lang="ts"> import Counter from './Counter.svelte'; export let name: string = 'world'; </script> <main> <h1>Hello {name}!</h1> <Counter /> </main> Tools that use esbuild to compile TypeScript code inside a Svelte file like this only give esbuild the contents of the <script> tag. These tools work around this missing import problem when using the official TypeScript compiler by hacking the TypeScript AST to remove the "unused import" flags. This isn't possible in esbuild because esbuild deliberately does not expose an AST manipulation API for performance reasons. We deviate from the TypeScript compiler's behavior in this specific case because doing so is useful for these compile-to-JavaScript languages and is benign in other cases. The rationale is as follows: * If "importsNotUsedAsValues" is absent or set to "remove", then we don't know if these imports are values or types. It's not safe to keep them because if they are types, the missing imports will cause run-time failures because there will be no matching exports. It's only safe keep imports if "importsNotUsedAsValues" is set to "preserve" or "error" because then we can assume that none of the imports are types (since the TypeScript compiler would generate an error in that case). * If we're bundling, then we know we aren't being used to compile a partial module. The parser is seeing the entire code for the module so it's safe to remove unused imports. And also we don't want the linker to generate errors about missing imports if the imported file is also in the bundle. * If identifier minification is enabled, then using esbuild as a partial-module transform library wouldn't work anyway because the names wouldn't match. And that means we're minifying so the user is expecting the output to be as small as possible. So we should omit unused imports.
TypeScript always trims unused imports. This is important for correctness since some imports might be fake (only in the type system and used for type-only imports).
			if (.options.mangleSyntax || .options.ts.Parse) && ! {
				 := false
				 := true
Remove the default name if it's unused
				if .DefaultName != nil {
					 = true
					 := .symbols[.DefaultName.Ref.InnerIndex]
TypeScript has a separate definition of unused
					if .options.ts.Parse && .tsUseCounts[.DefaultName.Ref.InnerIndex] != 0 {
						 = false
					}
Remove the symbol if it's never used outside a dead code region
					if .UseCountEstimate == 0 {
						.DefaultName = nil
					}
				}
Remove the star import if it's unused
				if .StarNameLoc != nil {
					 = true
					 := .symbols[.NamespaceRef.InnerIndex]
TypeScript has a separate definition of unused
					if .options.ts.Parse && .tsUseCounts[.NamespaceRef.InnerIndex] != 0 {
						 = false
					}
Remove the symbol if it's never used outside a dead code region
Make sure we don't remove this if it was used for a property access while bundling
						if ,  := .importItemsForNamespace[.NamespaceRef];  && len() == 0 {
							.StarNameLoc = nil
						}
					}
				}
Remove items if they are unused
				if .Items != nil {
					 = true
					 := 0

					for ,  := range *.Items {
						 := .symbols[.Name.Ref.InnerIndex]
TypeScript has a separate definition of unused
						if .options.ts.Parse && .tsUseCounts[.Name.Ref.InnerIndex] != 0 {
							 = false
						}
Remove the symbol if it's never used outside a dead code region
						if .UseCountEstimate != 0 {
							(*.Items)[] = 
							++
						}
					}
Filter the array by taking a slice
					if  == 0 {
						.Items = nil
					} else {
						*.Items = (*.Items)[:]
					}
				}
Omit this statement if we're parsing TypeScript and all imports are unused. Note that this is distinct from the case where there were no imports at all (e.g. "import 'foo'"). In that case we want to keep the statement because the user is clearly trying to import the module for side effects. This culling is important for correctness when parsing TypeScript because a) the TypeScript compiler does ths and we want to match it and b) this may be a fake module that only exists in the type system and doesn't actually exist in reality. We do not want to do this culling in JavaScript though because the module may have side effects even if all imports are unused.
Ignore import records with a pre-filled source index. These are for injected files and we definitely do not want to trim these.
					if  := &.importRecords[.ImportRecordIndex]; !.SourceIndex.IsValid() {
						.IsUnused = true
						continue
					}
				}
			}

			if .options.mode != config.ModePassThrough {
If we're bundling a star import and the namespace is only ever used for property accesses, then convert each unique property to a clause item in the import statement and remove the star import. That will cause the bundler to bundle them more efficiently when both this module and the imported module are in the same group. Before: import * as ns from 'foo' console.log(ns.a, ns.b) After: import {a, b} from 'foo' console.log(a, b) This is not done if the namespace itself is used, because in that case the code for the namespace will have to be generated. This is determined by the symbol count because the parser only counts the star import as used if it was used for something other than a property access: import * as ns from 'foo' console.log(ns, ns.a, ns.b)
					 := .symbols[.NamespaceRef.InnerIndex].UseCountEstimate == 0
					if  && ! {
						.StarNameLoc = nil
					}
"importItemsForNamespace" has property accesses off the namespace
Sort keys for determinism
						 := make([]string, 0, len())
						for  := range  {
							 = append(, )
						}
						sort.Strings()

Create an import clause for these items. Named imports will be automatically created later on since there is now a clause.
							 := make([]js_ast.ClauseItem, 0, len())
							for ,  := range  {
								 := []
								 := .symbols[.Ref.InnerIndex].OriginalName
								 = append(, js_ast.ClauseItem{
									Alias:        ,
									AliasLoc:     .Loc,
									Name:         ,
									OriginalName: ,
								})
								.declaredSymbols = append(.declaredSymbols, js_ast.DeclaredSymbol{
									Ref:        .Ref,
									IsTopLevel: true,
								})
							}
The syntax "import {x}, * as y from 'path'" isn't valid
								panic("Internal error")
							}
							.Items = &
If we aren't converting this star import to a clause, still create named imports for these property accesses. This will cause missing imports to generate useful warnings. It will also improve bundling efficiency for internal imports by still converting property accesses off the namespace into bare identifiers even if the namespace is still needed.
							for ,  := range  {
								 := []
								.namedImports[.Ref] = js_ast.NamedImport{
									Alias:             ,
									AliasLoc:          .Loc,
									NamespaceRef:      .NamespaceRef,
									ImportRecordIndex: .ImportRecordIndex,
								}
Remove unused import-equals statements, since those likely correspond to types instead of values
			if .WasTSImportEquals && !.IsExport {
				 := .Decls[0]
Skip to the underlying reference
				 := *.Decls[0].Value
				for {
					if ,  := .Data.(*js_ast.EDot);  {
						 = .Target
					} else {
						break
					}
				}
Is this an identifier reference and not a require() call?
Is this import statement unused?
Also don't count the referenced identifier
Import-equals statements can come in any order. Removing one could potentially cause another one to be removable too. Continue iterating until a fixed point has been reached to make sure we get them all.
Note that the imported alias is not item.Alias, which is the exported alias. This is somewhat confusing because each SExportFrom statement is basically SImport + SExportClause in one.
Filter out statements we skipped over
		[] = 
		++
	}

	.stmts = [:]
	return
}

func ( *parser) ( []js_ast.Part,  []js_ast.Stmt) []js_ast.Part {
	.symbolUses = make(map[js_ast.Ref]js_ast.SymbolUse)
	.declaredSymbols = nil
	.importRecordsForCurrentPart = nil
	.scopesForCurrentPart = nil
	 := js_ast.Part{
		Stmts:      .visitStmtsAndPrependTempRefs(, prependTempRefsOpts{}),
		SymbolUses: .symbolUses,
	}
Insert any relocated variable statements now
	if len(.relocatedTopLevelVars) > 0 {
		 := make(map[js_ast.Ref]bool)
Follow links because "var" declarations may be merged due to hoisting
			for {
				 := .symbols[.Ref.InnerIndex].Link
				if  == js_ast.InvalidRef {
					break
				}
				.Ref = 
			}
Only declare a given relocated variable once
			if ![.Ref] {
				[.Ref] = true
				.Stmts = append(.Stmts, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SLocal{
					Decls: []js_ast.Decl{{
						Binding: js_ast.Binding{Loc: .Loc, Data: &js_ast.BIdentifier{Ref: .Ref}},
					}},
				}})
			}
		}
		.relocatedTopLevelVars = nil
	}

	if len(.Stmts) > 0 {
		.CanBeRemovedIfUnused = .stmtsCanBeRemovedIfUnused(.Stmts)
		.DeclaredSymbols = .declaredSymbols
		.ImportRecordIndices = .importRecordsForCurrentPart
		.Scopes = .scopesForCurrentPart
		 = append(, )
	}
	return 
}

func ( *parser) ( []js_ast.Stmt) bool {
	for ,  := range  {
		switch s := .Data.(type) {
These never have side effects

Let these be removed if they are unused. Note that we also need to check if the imported file is marked as "sideEffects: false" before we can remove a SImport statement. Otherwise the import must be kept for its side effects.

		case *js_ast.SClass:
			if !.classCanBeRemovedIfUnused(.Class) {
				return false
			}

		case *js_ast.SExpr:
Expressions marked with this are automatically generated and have no side effects by construction.
				break
			}

			if !.exprCanBeRemovedIfUnused(.Value) {
				return false
			}

		case *js_ast.SLocal:
			for ,  := range .Decls {
				if !.bindingCanBeRemovedIfUnused(.Binding) {
					return false
				}
				if .Value != nil && !.exprCanBeRemovedIfUnused(*.Value) {
					return false
				}
			}

Exports are tracked separately, so this isn't necessary

		case *js_ast.SExportDefault:
			switch {
			case .Value.Expr != nil:
				if !.exprCanBeRemovedIfUnused(*.Value.Expr) {
					return false
				}

			case .Value.Stmt != nil:
				switch s2 := .Value.Stmt.Data.(type) {
These never have side effects

				case *js_ast.SClass:
					if !.classCanBeRemovedIfUnused(.Class) {
						return false
					}

				default:
					panic("Internal error")
				}
			}

Assume that all statements not explicitly special-cased here have side effects, and cannot be removed even if unused
			return false
		}
	}

	return true
}

func ( *parser) ( js_ast.Class) bool {
	if .Extends != nil && !.exprCanBeRemovedIfUnused(*.Extends) {
		return false
	}

	for ,  := range .Properties {
		if !.exprCanBeRemovedIfUnused(.Key) {
			return false
		}
		if .Value != nil && !.exprCanBeRemovedIfUnused(*.Value) {
			return false
		}
		if .Initializer != nil && !.exprCanBeRemovedIfUnused(*.Initializer) {
			return false
		}
	}

	return true
}

func ( *parser) ( js_ast.Binding) bool {
	switch b := .Data.(type) {
	case *js_ast.BArray:
		for ,  := range .Items {
			if !.(.Binding) {
				return false
			}
			if .DefaultValue != nil && !.exprCanBeRemovedIfUnused(*.DefaultValue) {
				return false
			}
		}

	case *js_ast.BObject:
		for ,  := range .Properties {
			if !.IsSpread && !.exprCanBeRemovedIfUnused(.Key) {
				return false
			}
			if !.(.Value) {
				return false
			}
			if .DefaultValue != nil && !.exprCanBeRemovedIfUnused(*.DefaultValue) {
				return false
			}
		}
	}

	return true
}

func ( *parser) ( js_ast.Expr) bool {
	switch e := .Data.(type) {
	case *js_ast.ENull, *js_ast.EUndefined, *js_ast.EMissing, *js_ast.EBoolean, *js_ast.ENumber, *js_ast.EBigInt,
		*js_ast.EString, *js_ast.EThis, *js_ast.ERegExp, *js_ast.EFunction, *js_ast.EArrow, *js_ast.EImportMeta:
		return true

	case *js_ast.EDot:
		return .CanBeRemovedIfUnused

	case *js_ast.EClass:
		return .classCanBeRemovedIfUnused(.Class)

	case *js_ast.EIdentifier:
		if .MustKeepDueToWithStmt {
			return false
		}
Unbound identifiers cannot be removed because they can have side effects. One possible side effect is throwing a ReferenceError if they don't exist. Another one is a getter with side effects on the global object: Object.defineProperty(globalThis, 'x', { get() { sideEffect(); }, }); Be very careful about this possibility. It's tempting to treat all identifier expressions as not having side effects but that's wrong. We must make sure they have been declared by the code we are currently compiling before we can tell that they have no side effects. Note that we currently ignore ReferenceErrors due to TDZ access. This is incorrect but proper TDZ analysis is very complicated and would have to be very conservative, which would inhibit a lot of optimizations of code inside closures. This may need to be revisited if it proves problematic.
References to an ES6 import item are always side-effect free in an ECMAScript environment. They could technically have side effects if the imported module is a CommonJS module and the import item was translated to a property access (which esbuild's bundler does) and the property has a getter with side effects. But this is very unlikely and respecting this edge case would mean disabling tree shaking of all code that references an export from a CommonJS module. It would also likely violate the expectations of some developers because the code *looks* like it should be able to be tree shaken. So we deliberately ignore this edge case and always treat import item references as being side-effect free.
		return true

	case *js_ast.EIf:
		return .(.Test) && .(.Yes) && .(.No)

	case *js_ast.EArray:
		for ,  := range .Items {
			if !.() {
				return false
			}
		}
		return true

	case *js_ast.EObject:
The key must still be evaluated if it's computed or a spread
			if .Kind == js_ast.PropertySpread || .IsComputed {
				return false
			}
			if .Value != nil && !.(*.Value) {
				return false
			}
		}
		return true

A call that has been marked "__PURE__" can be removed if all arguments can be removed. The annotation causes us to ignore the target.
		if .CanBeUnwrappedIfUnused {
			for ,  := range .Args {
				if !.() {
					return false
				}
			}
			return true
		}

A constructor call that has been marked "__PURE__" can be removed if all arguments can be removed. The annotation causes us to ignore the target.
		if .CanBeUnwrappedIfUnused {
			for ,  := range .Args {
				if !.() {
					return false
				}
			}
			return true
		}

	case *js_ast.EUnary:
These operators must not have any type conversions that can execute code such as "toString" or "valueOf". They must also never throw any exceptions.
		case js_ast.UnOpTypeof, js_ast.UnOpVoid, js_ast.UnOpNot:
			return .(.Value)
		}

	case *js_ast.EBinary:
These operators must not have any type conversions that can execute code such as "toString" or "valueOf". They must also never throw any exceptions.
		case js_ast.BinOpStrictEq, js_ast.BinOpStrictNe, js_ast.BinOpComma,
			js_ast.BinOpLogicalOr, js_ast.BinOpLogicalAnd, js_ast.BinOpNullishCoalescing:
			return .(.Left) && .(.Right)
		}
	}
Assume all other expression types have side effects and cannot be removed
	return false
}
This will return a nil expression if the expression can be totally removed
Make sure "ToString" is still evaluated on the value
				if .Data == nil {
					 = js_ast.Expr{Loc: .Value.Loc, Data: &js_ast.EString{}}
				}
				 = js_ast.Expr{Loc: .Value.Loc, Data: &js_ast.EBinary{
					Op:    js_ast.BinOpAdd,
					Left:  ,
					Right: .Value,
				}}
			}
			return 
		}

Arrays with "..." spread expressions can't be unwrapped because the "..." triggers code evaluation via iterators. In that case, just trim the other items instead and leave the array expression there.
		for ,  := range .Items {
			if ,  := .Data.(*js_ast.ESpread);  {
				 := 0
				for ,  := range .Items {
					 = .()
					if .Data != nil {
						.Items[] = 
						++
					}
				}
				.Items = .Items[:]
				return 
			}
		}
Otherwise, the array can be completely removed. We only need to keep any array items with side effects. Apply this simplification recursively.
		var  js_ast.Expr
		for ,  := range .Items {
			 = maybeJoinWithComma(, .())
		}
		return 

Objects with "..." spread expressions can't be unwrapped because the "..." triggers code evaluation via getters. In that case, just trim the other items instead and leave the object expression there.
		for ,  := range .Properties {
			if .Kind == js_ast.PropertySpread {
				 := 0
Spread properties must always be evaluated
					if .Kind != js_ast.PropertySpread {
						 := .(*.Value)
Keep the value
							*.Value = 
Skip this property if the key doesn't need to be computed
							continue
Replace values without side effects with "0" because it's short
							.Value.Data = &js_ast.ENumber{}
						}
					}
					.Properties[] = 
					++
				}
				.Properties = .Properties[:]
				return 
			}
		}
Otherwise, the object can be completely removed. We only need to keep any object properties with side effects. Apply this simplification recursively.
		var  js_ast.Expr
		for ,  := range .Properties {
Make sure "ToString" is still evaluated on the key
				 = maybeJoinWithComma(, js_ast.Expr{Loc: .Key.Loc, Data: &js_ast.EBinary{
					Op:    js_ast.BinOpAdd,
					Left:  .Key,
					Right: js_ast.Expr{Loc: .Key.Loc, Data: &js_ast.EString{}},
				}})
			}
			 = maybeJoinWithComma(, .(*.Value))
		}
		return 

	case *js_ast.EIf:
		.Yes = .(.Yes)
		.No = .(.No)
"foo() ? 1 : 2" => "foo()"
		if .Yes.Data == nil && .No.Data == nil {
			return .(.Test)
		}
"foo() ? 1 : bar()" => "foo() || bar()"
"foo() ? bar() : 2" => "foo() && bar()"
These operators must not have any type conversions that can execute code such as "toString" or "valueOf". They must also never throw any exceptions.
		case js_ast.UnOpVoid, js_ast.UnOpNot:
			return .(.Value)

		case js_ast.UnOpTypeof:
"typeof x" must not be transformed into if "x" since doing so could cause an exception to be thrown. Instead we can just remove it since "typeof x" is special-cased in the standard to never throw.
				return js_ast.Expr{}
			}
			return .(.Value)
		}

	case *js_ast.EBinary:
These operators must not have any type conversions that can execute code such as "toString" or "valueOf". They must also never throw any exceptions.
		case js_ast.BinOpStrictEq, js_ast.BinOpStrictNe, js_ast.BinOpComma:
			return maybeJoinWithComma(.(.Left), .(.Right))
We can simplify "==" and "!=" even though they can call "toString" and/or "valueOf" if we can statically determine that the types of both sides are primitives. In that case there won't be any chance for user-defined "toString" and/or "valueOf" to be called.
		case js_ast.BinOpLooseEq, js_ast.BinOpLooseNe:
			if isPrimitiveWithSideEffects(.Left.Data) && isPrimitiveWithSideEffects(.Right.Data) {
				return maybeJoinWithComma(.(.Left), .(.Right))
			}

Preserve short-circuit behavior: the left expression is only unused if the right expression can be completely removed. Otherwise, the left expression is important for the branch.
			.Right = .(.Right)
			if .Right.Data == nil {
				return .(.Left)
			}

		case js_ast.BinOpAdd:
			if ,  := simplifyUnusedStringAdditionChain();  {
				return 
			}
		}

A call that has been marked "__PURE__" can be removed if all arguments can be removed. The annotation causes us to ignore the target.
		if .CanBeUnwrappedIfUnused {
			 = js_ast.Expr{}
			for ,  := range .Args {
				 = maybeJoinWithComma(, .())
			}
		}

A constructor call that has been marked "__PURE__" can be removed if all arguments can be removed. The annotation causes us to ignore the target.
		if .CanBeUnwrappedIfUnused {
			 = js_ast.Expr{}
			for ,  := range .Args {
				 = maybeJoinWithComma(, .())
			}
		}
	}

	return 
}

func ( js_ast.Expr) (js_ast.Expr, bool) {
	switch e := .Data.(type) {
"'x' + y" => "'' + y"
		return js_ast.Expr{Loc: .Loc, Data: &js_ast.EString{}}, true

	case *js_ast.EBinary:
		if .Op == js_ast.BinOpAdd {
			,  := (.Left)
			.Left = 

"('' + x) + 'y'" => "'' + x"
				if  {
					return , true
				}
"x + 'y'" => "x + ''"
				if ! {
					.Right.Data = &js_ast.EString{}
					return , true
				}
			}

			return , 
		}
	}

	return , false
}

func ( logger.Log,  logger.Source,  js_lexer.Lexer,  *Options) *parser {
	if .defines == nil {
		 := config.ProcessDefines(nil)
		.defines = &
	}

	 := &parser{
		log:                ,
		source:             ,
		lexer:              ,
		allowIn:            true,
		options:            *,
		fnOrArrowDataParse: fnOrArrowDataParse{isOutsideFn: true},
		runtimeImports:     make(map[string]js_ast.Ref),
		promiseRef:         js_ast.InvalidRef,
		afterArrowBodyLoc:  logger.Loc{Start: -1},
These are for handling ES6 imports and exports
		importItemsForNamespace: make(map[js_ast.Ref]map[string]js_ast.LocRef),
		isImportItem:            make(map[js_ast.Ref]bool),
		namedImports:            make(map[js_ast.Ref]js_ast.NamedImport),
		namedExports:            make(map[string]js_ast.NamedExport),
	}

	.findSymbolHelper = func( logger.Loc,  string) js_ast.Ref {
		return .findSymbol(, ).ref
	}

	.symbolForDefineHelper = func( int) js_ast.Ref {
		 := .injectedDefineSymbols[]
		.recordUsage()
		return 
	}

	.pushScopeForParsePass(js_ast.ScopeEntry, logger.Loc{Start: locModuleScope})

	return 
}

var defaultJSXFactory = []string{"React", "createElement"}
var defaultJSXFragment = []string{"React", "Fragment"}

func ( logger.Log,  logger.Source,  Options) ( js_ast.AST,  bool) {
	 = true
	defer func() {
		 := recover()
		if ,  := .(js_lexer.LexerPanic);  {
			 = false
		} else if  != nil {
			panic()
		}
	}()
Default options for JSX elements
	if len(.jsx.Factory) == 0 {
		.jsx.Factory = defaultJSXFactory
	}
	if len(.jsx.Fragment) == 0 {
		.jsx.Fragment = defaultJSXFragment
	}
Non-TypeScript files get the real JavaScript class field behavior
	if !.ts.Parse {
		.useDefineForClassFields = true
	}

	 := newParser(, , js_lexer.NewLexer(, ), &)
Consume a leading hashbang comment
	 := ""
	if .lexer.Token == js_lexer.THashbang {
		 = .lexer.Identifier
		.lexer.Next()
	}
Parse the file in the first pass, but do not bind symbols
Strip off a leading "use strict" directive when not bundling
	 := ""
	if .options.mode != config.ModeBundle {
		for ,  := range  {
			switch s := .Data.(type) {
			case *js_ast.SComment:
				continue
			case *js_ast.SDirective:
				if !isDirectiveSupported() {
					continue
				}
				 = js_lexer.UTF16ToString(.Value)
Remove this directive from the statement list
				copy([1:], [:])
				 = [1:]
			}
			break
		}
	}
Insert a variable for "import.meta" at the top of the file if it was used. We don't need to worry about "use strict" directives because this only happens when bundling, in which case we are flatting the module scopes of all modules together anyway so such directives are meaningless.
	if .importMetaRef != js_ast.InvalidRef {
		 := js_ast.Stmt{Data: &js_ast.SLocal{
			Kind: .selectLocalKind(js_ast.LocalConst),
			Decls: []js_ast.Decl{{
				Binding: js_ast.Binding{Data: &js_ast.BIdentifier{Ref: .importMetaRef}},
				Value:   &js_ast.Expr{Data: &js_ast.EObject{}},
			}},
		}}
		 = append(append(make([]js_ast.Stmt, 0, len()+1), ), ...)
	}

	var  []js_ast.Part
	var  []js_ast.Part
	var  []js_ast.Part
Insert any injected import statements now that symbols have been declared
	for ,  := range .options.injectedFiles {
		 := make([]string, 0, len(.Exports))
		 := make(map[string]js_ast.Ref)
		if .IsDefine {
			 := .newSymbol(js_ast.SymbolOther, js_ast.GenerateNonUniqueNameFromPath(.Path))
			.moduleScope.Generated = append(.moduleScope.Generated, )
			["default"] = 
			 = append(, "default")
			.injectedDefineSymbols = append(.injectedDefineSymbols, )
		} else {
			for ,  := range .Exports {
				if ,  := .moduleScope.Members[]; ! {
					 := .newSymbol(js_ast.SymbolOther, )
					.moduleScope.Members[] = js_ast.ScopeMember{Ref: }
					[] = 
					 = append(, )
				}
			}
		}
		 = .generateImportStmt(.Path, , .SourceIndex, , )
	}
Bind symbols in a second pass over the AST. I started off doing this in a single pass, but it turns out it's pretty much impossible to do this correctly while handling arrow functions because of the grammar ambiguities.
When not bundling, everything comes in a single part
		 = .appendPart(, )
When bundling, each top-level statement is potentially a separate part
		for ,  := range  {
			switch s := .Data.(type) {
Split up top-level multi-declaration variable statements
				for ,  := range .Decls {
					 := *
					.Decls = []js_ast.Decl{}
					 = .appendPart(, []js_ast.Stmt{{Loc: .Loc, Data: &}})
				}

Move imports (and import-like exports) to the top of the file to ensure that if they are converted to a require() call, the effects will take place before any other statements are evaluated.
				 = .appendPart(, []js_ast.Stmt{})

TypeScript "export = value;" becomes "module.exports = value;". This must happen at the end after everything is parsed because TypeScript moves this statement to the end when it generates code.
				 = .appendPart(, []js_ast.Stmt{})

			default:
				 = .appendPart(, []js_ast.Stmt{})
			}
		}
	}
Pop the module scope to apply the "ContainsDirectEval" rules
	.popScope()

	 = append(append(, ...), ...)
	 = .toAST(, , , )
	.SourceMapComment = .lexer.SourceMappingURL
	return
}

Don't create a new lexer using js_lexer.NewLexer() here since that will actually attempt to parse the first token, which might cause a syntax error.
	 := newParser(, , js_lexer.Lexer{}, &)
	.prepareForVisitPass()
Optionally call a runtime API function to transform the expression
	if  != "" {
		.symbolUses = make(map[js_ast.Ref]js_ast.SymbolUse)
		 = .callRuntime(.Loc, , []js_ast.Expr{})
	}
Defer the actual code generation until linking
	 := js_ast.Part{
		Stmts:      []js_ast.Stmt{{Loc: .Loc, Data: &js_ast.SLazyExport{Value: }}},
		SymbolUses: .symbolUses,
	}
	.symbolUses = nil

	 := .toAST(, []js_ast.Part{}, "", "")
	.HasLazyExport = true
	return 
}

func ( *parser) ( js_ast.Span,  string) []string {
	if .Text == "" {
		return nil
	}
	 := strings.Split(.Text, ".")
	for ,  := range  {
		if !js_lexer.IsIdentifier() {
			.log.AddRangeWarning(&.source, .Range, fmt.Sprintf("Invalid JSX %s: %s", , .Text))
			return nil
		}
	}
	return 
}

func ( *parser) () {
	.pushScopeForVisitPass(js_ast.ScopeEntry, logger.Loc{Start: locModuleScope})
	.moduleScope = .currentScope
	.hasESModuleSyntax = .es6ImportKeyword.Len > 0 || .es6ExportKeyword.Len > 0 || .topLevelAwaitKeyword.Len > 0
ECMAScript modules are always interpreted as strict mode. This has to be done before "hoistSymbols" because strict mode can alter hoisting (!).
Convert "import.meta" to a variable if it's not supported in the output format
Handle "@jsx" and "@jsxFrag" pragmas now that lexing is done
	if .options.jsx.Parse {
		if  := .validateJSX(.lexer.JSXFactoryPragmaComment, "factory");  != nil {
			.options.jsx.Factory = 
		}
		if  := .validateJSX(.lexer.JSXFragmentPragmaComment, "fragment");  != nil {
			.options.jsx.Fragment = 
		}
	}
}

func ( *parser) ( js_ast.SymbolKind,  string) js_ast.Ref {
	,  := .moduleScope.Members[]
If the code declared this symbol using "var name", then this is actually not a collision. For example, node will let you do this: var exports; module.exports.foo = 123; console.log(exports.foo); This works because node's implementation of CommonJS wraps the entire source file like this: (function(require, exports, module, __filename, __dirname) { var exports; module.exports.foo = 123; console.log(exports.foo); }) Both the "exports" argument and "var exports" are hoisted variables, so they don't collide.
	if  && .symbols[.Ref.InnerIndex].Kind == js_ast.SymbolHoisted &&
		 == js_ast.SymbolHoisted && !.hasESModuleSyntax {
		return .Ref
	}
Create a new symbol if we didn't merge with an existing one above
	 := .newSymbol(, )
If the variable wasn't declared, declare it now. This means any references to this name will become bound to this symbol after this (since we haven't run the visit pass yet).
	if ! {
		.moduleScope.Members[] = js_ast.ScopeMember{Ref: , Loc: logger.Loc{Start: -1}}
		return 
	}
If the variable was declared, then it shadows this symbol. The code in this module will be unable to reference this symbol. However, we must still add the symbol to the scope so it gets minified (automatically- generated code may still reference the symbol).
	.moduleScope.Generated = append(.moduleScope.Generated, )
	return 
}
Compute a character frequency histogram for everything that's not a bound symbol. This is used to modify how minified names are generated for slightly better gzip compression. Even though it's a very small win, we still do it because it's simple to do and very cheap to compute.
Add everything in the file to the histogram
	 := &js_ast.CharFreq{}
	.Scan(.source.Contents, 1)
Subtract out all comments
	for ,  := range .lexer.AllOriginalComments {
		.Scan(.Text, -1)
	}
Subtract out all symbols that will be minified
	var  func(*js_ast.Scope)
	 = func( *js_ast.Scope) {
		for ,  := range .Members {
			 := &.symbols[.Ref.InnerIndex]
			if .SlotNamespace() != js_ast.SlotMustNotBeRenamed {
				.Scan(.OriginalName, -int32(.UseCountEstimate))
			}
		}
		if .LabelRef != js_ast.InvalidRef {
			 := &.symbols[.LabelRef.InnerIndex]
			if .SlotNamespace() != js_ast.SlotMustNotBeRenamed {
				.Scan(.OriginalName, -int32(.UseCountEstimate)-1)
			}
		}
		for ,  := range .Children {
			()
		}
	}
	(.moduleScope)

	return 
}

func ( *parser) (
	 string,
	 []string,
	 uint32,
	 []js_ast.Part,
	 map[string]js_ast.Ref,
) []js_ast.Part {
	 := .newSymbol(js_ast.SymbolOther, "import_"+js_ast.GenerateNonUniqueNameFromPath())
	.moduleScope.Generated = append(.moduleScope.Generated, )
	 := make([]js_ast.DeclaredSymbol, len())
	 := make([]js_ast.ClauseItem, len())
	 := .addImportRecord(ast.ImportStmt, logger.Loc{}, )
	.importRecords[].SourceIndex = ast.MakeIndex32()
Create per-import information
	for ,  := range  {
		 := []
		[] = js_ast.DeclaredSymbol{Ref: , IsTopLevel: true}
		[] = js_ast.ClauseItem{Alias: , Name: js_ast.LocRef{Ref: }}
		.isImportItem[] = true
		.namedImports[] = js_ast.NamedImport{
			Alias:             ,
			NamespaceRef:      ,
			ImportRecordIndex: ,
		}
	}
Append a single import to the end of the file (ES6 imports are hoisted so we don't need to worry about where the import statement goes)
	return append(, js_ast.Part{
		DeclaredSymbols:     ,
		ImportRecordIndices: []uint32{},
		Stmts: []js_ast.Stmt{{Data: &js_ast.SImport{
			NamespaceRef:      ,
			Items:             &,
			ImportRecordIndex: ,
		}}},
	})
}

Insert an import statement for any runtime imports we generated
Sort the imports for determinism
		 := make([]string, 0, len(.runtimeImports))
		for  := range .runtimeImports {
			 = append(, )
		}
		sort.Strings()
		 = .generateImportStmt("<runtime>", , runtime.SourceIndex, , .runtimeImports)
	}
Handle import paths after the whole file has been visited because we need symbol usage counts to be able to remove unused type-only imports in TypeScript code.
	for {
		 := false
		 := false
Potentially remove some statements, then filter out parts to remove any with no statements
		 := 0
		for ,  := range  {
			.importRecordsForCurrentPart = nil
			.declaredSymbols = nil

			 := .scanForImportsAndExports(.Stmts)
			.Stmts = .stmts
			 =  || .keptImportEquals
			 =  || .removedImportEquals

			.ImportRecordIndices = append(.ImportRecordIndices, .importRecordsForCurrentPart...)
			.DeclaredSymbols = append(.DeclaredSymbols, .declaredSymbols...)

			if len(.Stmts) > 0 {
If this file contains a direct call to "eval()", all parts that declare top-level symbols must be kept since the eval'd code may reference those symbols.
					.CanBeRemovedIfUnused = false
				}
				[] = 
				++
			}
		}
		 = [:]
We need to iterate multiple times if an import-equals statement was removed and there are more import-equals statements that may be removed
		if ! || ! {
			break
		}
	}
Do a second pass for exported items now that imported items are filled out
	for ,  := range  {
		for ,  := range .Stmts {
			if ,  := .Data.(*js_ast.SExportClause);  {
Mark re-exported imports as such
					if ,  := .namedImports[.Name.Ref];  {
						.IsExported = true
						.namedImports[.Name.Ref] = 
					}
				}
			}
		}
	}
Analyze cross-part dependencies for tree shaking and code splitting
Map locals to parts
		.topLevelSymbolToParts = make(map[js_ast.Ref][]uint32)
		for ,  := range  {
			for ,  := range .DeclaredSymbols {
				if .IsTopLevel {
					.topLevelSymbolToParts[.Ref] = append(
						.topLevelSymbolToParts[.Ref], uint32())
				}
			}
		}
Each part tracks the other parts it depends on within this file
		for ,  := range  {
			 := make(map[uint32]bool)
			for  := range .SymbolUses {
				for ,  := range .topLevelSymbolToParts[] {
					[] = true
				}
Also map from imports to parts that use them
				if ,  := .namedImports[];  {
					.LocalPartsWithUses = append(.LocalPartsWithUses, uint32())
					.namedImports[] = 
				}
			}
			[].LocalDependencies = 
		}
	}
Make a wrapper symbol in case we need to be wrapped in a closure
	 := .newSymbol(js_ast.SymbolOther, "require_"+.source.IdentifierName)
Assign slots to symbols in nested scopes. This is some precomputation for the symbol renaming pass that will happen later in the linker. It's done now in the parser because we want it to be done in parallel per file and we're already executing code in a dedicated goroutine for this file.