This file contains code for "lowering" syntax, which means converting it to older JavaScript. For example, "a ** b" becomes a call to "Math.pow(a, b)" when lowered. Which syntax is lowered is determined by the language target.

package js_parser

import (
	

	
	
	
	
	
)

func ( *parser) ( compat.JSFeature,  logger.Range) ( bool) {
	 = true

	if !.options.unsupportedJSFeatures.Has() {
		if  == compat.TopLevelAwait {
			if .options.mode == config.ModeBundle {
				.log.AddRangeError(&.source, , "Top-level await is currently not supported when bundling")
				return
			}
			if .options.mode == config.ModeConvertFormat && !.options.outputFormat.KeepES6ImportExportSyntax() {
				.log.AddRangeError(&.source, , fmt.Sprintf(
					"Top-level await is currently not supported with the %q output format", .options.outputFormat.String()))
				return
			}
		}

		 = false
		return
	}

	var  string
	 := "the configured target environment"

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

	case compat.RestArgument:
		 = "rest arguments"

	case compat.ArraySpread:
		 = "array spread"

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

	case compat.ObjectAccessors:
		 = "object accessors"

	case compat.ObjectExtensions:
		 = "object literal extensions"

	case compat.TemplateLiteral:
		 = "tagged template literals"

	case compat.Destructuring:
		 = "destructuring"

	case compat.NewTarget:
		 = "new.target"

	case compat.Const:
		 = "const"

	case compat.Let:
		 = "let"

	case compat.Class:
		 = "class syntax"

	case compat.Generator:
		 = "generator functions"

	case compat.AsyncAwait:
		 = "async functions"

	case compat.AsyncGenerator:
		 = "async generator functions"

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

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

	case compat.TopLevelAwait:
		.log.AddRangeError(&.source, ,
			fmt.Sprintf("Top-level await is not available in %s", ))
		return

Transforming these will never be supported
		.log.AddRangeError(&.source, ,
			fmt.Sprintf("Big integer literals are not available in %s", ))
		return

This can't be polyfilled
		.log.AddRangeWarning(&.source, ,
			fmt.Sprintf("\"import.meta\" is not available in %s and will be empty", ))
		return

	default:
		.log.AddRangeError(&.source, ,
			fmt.Sprintf("This feature is not available in %s", ))
		return
	}

	.log.AddRangeError(&.source, ,
		fmt.Sprintf("Transforming %s to %s is not supported yet", , ))
	return
}

func ( *parser) () bool {
	return .currentScope.StrictMode != js_ast.SloppyMode
}

func ( *parser) () bool {
	return .options.outputFormat == config.FormatESModule
}

type strictModeFeature uint8

const (
	withStatement strictModeFeature = iota
	deleteBareName
	forInVarInit
	evalOrArguments
	reservedWord
	legacyOctalLiteral
	legacyOctalEscape
	ifElseFunctionStmt
)

func ( *parser) ( strictModeFeature,  logger.Range,  string) {
	var  string
	 := false
	switch  {
	case withStatement:
		 = "With statements"
	case deleteBareName:
		 = "Delete of a bare identifier"
	case forInVarInit:
		 = "Variable initializers inside for-in loops"
		 = true
	case evalOrArguments:
		 = fmt.Sprintf("Declarations with the name %q", )
	case reservedWord:
		 = fmt.Sprintf("%q is a reserved word and", )
	case legacyOctalLiteral:
		 = "Legacy octal literals"
	case legacyOctalEscape:
		 = "Legacy octal escape sequences"
	case ifElseFunctionStmt:
		 = "Function declarations inside if statements"
	default:
		 = "This feature"
	}
	if .isStrictMode() {
		var  string
		var  []logger.MsgData
		var  logger.Range
		switch .currentScope.StrictMode {
		case js_ast.ImplicitStrictModeImport:
			 = "This file is implicitly in strict mode because of the \"import\" keyword"
			 = .es6ImportKeyword
		case js_ast.ImplicitStrictModeExport:
			 = "This file is implicitly in strict mode because of the \"export\" keyword"
			 = .es6ExportKeyword
		case js_ast.ImplicitStrictModeTopLevelAwait:
			 = "This file is implicitly in strict mode because of the top-level \"await\" keyword"
			 = .topLevelAwaitKeyword
		case js_ast.ImplicitStrictModeClass:
			 = "All code inside a class is implicitly in strict mode"
			 = .enclosingClassKeyword
		}
		if  != "" {
			 = []logger.MsgData{logger.RangeData(&.source, , )}
		}
		.log.AddRangeErrorWithNotes(&.source, ,
			fmt.Sprintf("%s cannot be used in strict mode", ), )
	} else if ! && .isStrictModeOutputFormat() {
		.log.AddRangeError(&.source, ,
			fmt.Sprintf("%s cannot be used with the \"esm\" output format due to strict mode", ))
	}
}
Mark the feature if "loweredFeature" is unsupported. This is used when one feature is implemented in terms of another feature.
func ( *parser) ( compat.JSFeature,  logger.Range,  compat.JSFeature) {
	if .options.unsupportedJSFeatures.Has() {
		.markSyntaxFeature(, )
	}
}

func ( *parser) ( *js_ast.EPrivateIdentifier) bool {
	return .options.unsupportedJSFeatures.Has(.symbols[.Ref.InnerIndex].Kind.Feature())
}

func ( *parser) () js_ast.Ref {
	if .fnOnlyDataVisit.thisCaptureRef == nil {
		 := .newSymbol(js_ast.SymbolHoisted, "_this")
		.fnOnlyDataVisit.thisCaptureRef = &
	}
	return *.fnOnlyDataVisit.thisCaptureRef
}

func ( *parser) () js_ast.Ref {
	if .fnOnlyDataVisit.argumentsCaptureRef == nil {
		 := .newSymbol(js_ast.SymbolHoisted, "_arguments")
		.fnOnlyDataVisit.argumentsCaptureRef = &
	}
	return *.fnOnlyDataVisit.argumentsCaptureRef
}

func ( *parser) (
	 *bool,
	 *[]js_ast.Arg,
	 logger.Loc,
	 *[]js_ast.Stmt,
	 *bool,
	 *bool,
	 bool,
Lower object rest binding patterns in function arguments
Lower each argument individually instead of lowering all arguments together. There is a correctness tradeoff here around default values for function arguments, with no right answer. Lowering all arguments together will preserve the order of side effects for default values, but will mess up their scope: // Side effect order: a(), b(), c() function foo([{[a()]: w, ...x}, y = b()], z = c()) {} // Side effect order is correct but scope is wrong function foo(_a, _b) { var [[{[a()]: w, ...x}, y = b()], z = c()] = [_a, _b] } Lowering each argument individually will preserve the scope for default values that don't contain object rest binding patterns, but will mess up the side effect order: // Side effect order: a(), b(), c() function foo([{[a()]: w, ...x}, y = b()], z = c()) {} // Side effect order is wrong but scope for c() is correct function foo(_a, z = c()) { var [{[a()]: w, ...x}, y = b()] = _a } This transform chooses to lower each argument individually with the thinking that perhaps scope matters more in real-world code than side effect order.
		for ,  := range * {
			if bindingHasObjectRest(.Binding) {
				 := .generateTempRef(tempRefNoDeclare, "")
				 := .convertBindingToExpr(.Binding, nil)
				 := js_ast.Expr{Loc: .Binding.Loc, Data: &js_ast.EIdentifier{Ref: }}
				.recordUsage()

Replace the binding but leave the default value intact
					(*)[].Binding.Data = &js_ast.BIdentifier{Ref: }
Append a variable declaration to the function body
					 = append(, js_ast.Stmt{Loc: .Binding.Loc,
						Data: &js_ast.SLocal{Kind: js_ast.LocalVar, Decls: }})
				}
			}
		}

		if len() > 0 {
			* = append(, *...)
		}
	}
Lower async functions
Use the shortened form if we're an arrow function
		if  != nil {
			* = true
		}
Determine the value for "this"
		,  := .valueForThis()
		if ! {
			 = js_ast.Expr{Loc: , Data: &js_ast.EThis{}}
		}
Move the code into a nested generator function
		 := js_ast.Fn{
			IsGenerator: true,
			Body:        js_ast.FnBody{Loc: , Stmts: *},
		}
		* = nil
Errors thrown during argument evaluation must reject the resulting promise, which needs more complex code to handle
		 := false
		for ,  := range * {
			if ,  := .Binding.Data.(*js_ast.BIdentifier); ! || (.Default != nil && couldPotentiallyThrow(.Default.Data)) {
				 = true
				break
			}
		}
Forward the arguments to the wrapper function
		 := ! && .fnOnlyDataVisit.argumentsRef != nil && .symbolUses[*.fnOnlyDataVisit.argumentsRef].CountEstimate > 0
		var  js_ast.Expr
Simple case: the arguments can stay on the outer function. It's worth separating out the simple case because it's the common case and it generates smaller code.
			 = js_ast.Expr{Loc: , Data: &js_ast.ENull{}}
If code uses "arguments" then we must move the arguments to the inner function. This is because you can modify arguments by assigning to elements in the "arguments" object: async function foo(x) { arguments[0] = 1; // "x" must be 1 here }
Complex case: the arguments must be moved to the inner function
			.Args = *
			.HasRestArg = *
			* = nil
			* = false
Make sure to not change the value of the "length" property. This is done by generating dummy arguments for the outer function equal to the expected length of the function: async function foo(a, b, c = d, ...e) { } This turns into: function foo(_0, _1) { return __async(this, arguments, function* (a, b, c = d, ...e) { }); } The "_0" and "_1" are dummy variables to ensure "foo.length" is 2.
			for ,  := range .Args {
Arguments from here on don't add to the "length"
					break
				}
Generate a dummy variable
Forward all arguments from the outer function to the inner function
Normal functions can just use "arguments" to forward everything
				 = js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: *.fnOnlyDataVisit.argumentsRef}}
Arrow functions can't use "arguments", so we need to forward the arguments manually. Note that if the arrow function references "arguments" in its body (even if it's inside another nested arrow function), that reference to "arguments" will have to be subsituted with a captured variable. This is because we're changing the arrow function into a generator function, which introduces a variable named "arguments". This is handled separately during symbol resolution instead of being handled here so we don't need to re-traverse the arrow function body.
If we need to forward more than the current number of arguments, add a rest argument to the set of forwarding variables. This is the case if the arrow function has rest or default arguments.
				if len(*) < len(.Args) {
					 := .newSymbol(js_ast.SymbolOther, fmt.Sprintf("_%d", len(*)))
					.currentScope.Generated = append(.currentScope.Generated, )
					* = append(*, js_ast.Arg{Binding: js_ast.Binding{Loc: , Data: &js_ast.BIdentifier{Ref: }}})
					* = true
				}
Forward all of the arguments
				 := make([]js_ast.Expr, 0, len(*))
				for ,  := range * {
					 := .Binding.Data.(*js_ast.BIdentifier)
					 := js_ast.Expr{Loc: .Binding.Loc, Data: &js_ast.EIdentifier{Ref: .Ref}}
					if * && +1 == len(*) {
						.Data = &js_ast.ESpread{Value: }
					}
					 = append(, )
				}
				 = js_ast.Expr{Loc: , Data: &js_ast.EArray{Items: , IsSingleLine: true}}
			}
		}
"async function foo(a, b) { stmts }" => "function foo(a, b) { return __async(this, null, function* () { stmts }) }"
		* = false
		 := .callRuntime(, "__async", []js_ast.Expr{
			,
			,
			{Loc: , Data: &js_ast.EFunction{Fn: }},
		})
		 := js_ast.Stmt{Loc: , Data: &js_ast.SReturn{Value: &}}
Prepend the "super" index function if necessary
		if .fnOrArrowDataVisit.superIndexRef != nil {
			 := .newSymbol(js_ast.SymbolOther, "key")
			.currentScope.Generated = append(.currentScope.Generated, *.fnOrArrowDataVisit.superIndexRef, )
			 := js_ast.Stmt{Loc: , Data: &js_ast.SLocal{
				Decls: []js_ast.Decl{{
					Binding: js_ast.Binding{Loc: , Data: &js_ast.BIdentifier{Ref: *.fnOrArrowDataVisit.superIndexRef}},
					Value: &js_ast.Expr{Loc: , Data: &js_ast.EArrow{
						Args: []js_ast.Arg{{
							Binding: js_ast.Binding{Loc: , Data: &js_ast.BIdentifier{Ref: }},
						}},
						Body: js_ast.FnBody{
							Loc: ,
							Stmts: []js_ast.Stmt{{Loc: , Data: &js_ast.SReturn{
								Value: &js_ast.Expr{Loc: , Data: &js_ast.EIndex{
									Target: js_ast.Expr{Loc: , Data: &js_ast.ESuper{}},
									Index:  js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }},
								}},
							}}},
						},
						PreferExpr: true,
					}},
				}},
			}}
			.recordUsage()
			* = []js_ast.Stmt{, }
		} else {
			* = []js_ast.Stmt{}
		}
	}
}

func ( *parser) ( js_ast.Expr,  exprIn,  exprOut) (js_ast.Expr, exprOut) {
	 := js_ast.Expr{Loc: .Loc, Data: &js_ast.EUndefined{}}
	 := false
	 := false
	 := false
	 := 
	 := []js_ast.Expr{}
	 := .Loc
Step 1: Get an array of all expressions in the chain. We're traversing the chain from the outside in, so the array will be filled in "backwards".
:
	for {
		 = append(, )

		switch e := .Data.(type) {
		case *js_ast.EDot:
			 = .Target
			if len() == 1 {
				 = true
			}
			if .OptionalChain == js_ast.OptionalChainStart {
				break 
			}

		case *js_ast.EIndex:
			 = .Target
			if len() == 1 {
				 = true
			}
If this is a private name that needs to be lowered, the entire chain itself will have to be lowered even if the language target supports optional chaining. This is because there's no way to use our shim function for private names with optional chaining syntax.
			if ,  := .Index.Data.(*js_ast.EPrivateIdentifier);  && .isPrivateUnsupported() {
				 = true
			}

			if .OptionalChain == js_ast.OptionalChainStart {
				break 
			}

		case *js_ast.ECall:
			 = .Target
			if .OptionalChain == js_ast.OptionalChainStart {
				 = true
				break 
			}

		case *js_ast.EUnary: // UnOpDelete
			 = js_ast.Expr{Loc: , Data: &js_ast.EBoolean{Value: true}}
			 = .Value

		default:
			panic("Internal error")
		}
	}
Stop now if we can strip the whole chain as dead code. Since the chain is lazily evaluated, it's safe to just drop the code entirely.
	switch .Data.(type) {
	case *js_ast.ENull, *js_ast.EUndefined:
		return , exprOut{}
	}
We need to lower this if this is an optional call off of a private name such as "foo.#bar?.()" because the value of "this" must be captured.
	if , ,  := .extractPrivateIndex();  != nil {
		 = true
	}
Don't lower this if we don't need to. This check must be done here instead of earlier so we can do the dead code elimination above when the target is null or undefined.
	if !.options.unsupportedJSFeatures.Has(compat.OptionalChain) && ! {
		return , exprOut{}
	}
Step 2: Figure out if we need to capture the value for "this" for the initial ECall. This will be passed to ".call(this, ...args)" later.
	var  js_ast.Expr
	var  func(js_ast.Expr) js_ast.Expr
	if  {
The initial value is a nested optional chain that ended in a property access. The nested chain was processed first and has saved the appropriate value for "this". The callback here will return a reference to that saved location.
			 = .thisArgFunc()
The initial value is a normal expression. If it's a property access, strip the property off and save the target of the property access to be used as the value for "this".
			switch e := .Data.(type) {
			case *js_ast.EDot:
Lower "super.prop" if necessary
Special-case "super.foo?.()" to avoid a syntax error. Without this, we would generate: (_b = (_a = super).foo) == null ? void 0 : _b.call(_a) which is a syntax error. Now we generate this instead: (_a = super.foo) == null ? void 0 : _a.call(this)
					 = js_ast.Expr{Loc: , Data: &js_ast.EThis{}}
				} else {
					,  := .captureValueWithPossibleSideEffects(, 2, .Target)
					 = js_ast.Expr{Loc: , Data: &js_ast.EDot{
						Target:  (),
						Name:    .Name,
						NameLoc: .NameLoc,
					}}
					 = ()
					 = 
				}

			case *js_ast.EIndex:
Lower "super[prop]" if necessary
See the comment above about a similar special case for EDot
					 = js_ast.Expr{Loc: , Data: &js_ast.EThis{}}
				} else {
					,  := .captureValueWithPossibleSideEffects(, 2, .Target)
					 = 
Capture the value of "this" if the target of the starting call expression is a private property access
"foo().#bar?.()" must capture "foo()" for "this"
						 = .lowerPrivateGet((), .Index.Loc, )
						 = ()
						break
					}

					 = js_ast.Expr{Loc: , Data: &js_ast.EIndex{
						Target: (),
						Index:  .Index,
					}}
					 = ()
				}
			}
		}
	}
Step 3: Figure out if we need to capture the starting value. We don't need to capture it if it doesn't have any side effects (e.g. it's just a bare identifier). Skipping the capture reduces code size and matches the output of the TypeScript compiler.
	,  := .captureValueWithPossibleSideEffects(, 2, )
	 = ()
	 := ()
Step 4: Wrap the starting value by each expression in the chain. We traverse the chain in reverse because we want to go from the inside out and the chain was built from the outside in.
	var  func() js_ast.Expr
	var  func(js_ast.Expr) js_ast.Expr
	var  func() js_ast.Expr
	var  func(js_ast.Expr) js_ast.Expr
Save a reference to the value of "this" for our parent ECall
		if  == 0 && .storeThisArgForParentOptionalChain &&  {
			,  = .captureValueWithPossibleSideEffects(.Loc, 2, )
			 = ()
		}

		switch e := [].Data.(type) {
		case *js_ast.EDot:
			 = js_ast.Expr{Loc: , Data: &js_ast.EDot{
				Target:  ,
				Name:    .Name,
				NameLoc: .NameLoc,
			}}

		case *js_ast.EIndex:
If this is private name property access inside a call expression and the call expression is part of this chain, then the call expression is going to need a copy of the property access target as the value for "this" for the call. Example for this case: "foo.#bar?.()"
				if  > 0 {
					if ,  := [-1].Data.(*js_ast.ECall);  {
						,  = .captureValueWithPossibleSideEffects(, 2, )
						 = ()
					}
				}

				 = .lowerPrivateGet(, .Index.Loc, )
				continue
			}

			 = js_ast.Expr{Loc: , Data: &js_ast.EIndex{
				Target: ,
				Index:  .Index,
			}}

If this is the initial ECall in the chain and it's being called off of a property access, invoke the function using ".call(this, ...args)" to explicitly provide the value for "this".
			if  == len()-1 && .Data != nil {
				 = js_ast.Expr{Loc: , Data: &js_ast.ECall{
					Target: js_ast.Expr{Loc: , Data: &js_ast.EDot{
						Target:  ,
						Name:    "call",
						NameLoc: ,
					}},
					Args:                   append([]js_ast.Expr{}, .Args...),
					CanBeUnwrappedIfUnused: .CanBeUnwrappedIfUnused,
				}}
				break
			}
If the target of this call expression is a private name property access that's also part of this chain, then we must use the copy of the property access target that was stashed away earlier as the value for "this" for the call. Example for this case: "foo.#bar?.()"
			if  != nil {
				 = (js_ast.Expr{Loc: , Data: &js_ast.ECall{
					Target: js_ast.Expr{Loc: , Data: &js_ast.EDot{
						Target:  ,
						Name:    "call",
						NameLoc: ,
					}},
					Args:                   append([]js_ast.Expr{()}, .Args...),
					CanBeUnwrappedIfUnused: .CanBeUnwrappedIfUnused,
				}})
				 = nil
				break
			}

			 = js_ast.Expr{Loc: , Data: &js_ast.ECall{
				Target:                 ,
				Args:                   .Args,
				IsDirectEval:           .IsDirectEval,
				CanBeUnwrappedIfUnused: .CanBeUnwrappedIfUnused,
			}}

		case *js_ast.EUnary:
			 = js_ast.Expr{Loc: , Data: &js_ast.EUnary{
				Op:    js_ast.UnOpDelete,
				Value: ,
			}}

		default:
			panic("Internal error")
		}
	}
Step 5: Wrap it all in a conditional that returns the chain or the default value if the initial value is null/undefined. The default value is usually "undefined" but is "true" if the chain ends in a "delete" operator. "x?.y" => "x == null ? void 0 : x.y" "x()?.y()" => "(_a = x()) == null ? void 0 : _a.y()"
	 = js_ast.Expr{Loc: , Data: &js_ast.EIf{
		Test: js_ast.Expr{Loc: , Data: &js_ast.EBinary{
			Op:    js_ast.BinOpLooseEq,
			Left:  ,
			Right: js_ast.Expr{Loc: , Data: &js_ast.ENull{}},
		}},
		Yes: ,
		No:  ,
	}}
	if  != nil {
		 = ()
	}
	if  != nil {
		 = ()
	}
	if .thisArgWrapFunc != nil {
		 = .thisArgWrapFunc()
	}
	return , exprOut{
		thisArgFunc:     ,
		thisArgWrapFunc: ,
	}
}

func ( *parser) ( js_ast.Expr,  func(js_ast.Expr, js_ast.Expr) js_ast.Expr) js_ast.Expr {
	switch left := .Data.(type) {
	case *js_ast.EDot:
		if .OptionalChain == js_ast.OptionalChainNone {
			,  := .captureValueWithPossibleSideEffects(.Loc, 2, .Target)
			return ((
				js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
					Target:  (),
					Name:    .Name,
					NameLoc: .NameLoc,
				}},
				js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
					Target:  (),
					Name:    .Name,
					NameLoc: .NameLoc,
				}},
			))
		}

	case *js_ast.EIndex:
		if .OptionalChain == js_ast.OptionalChainNone {
			,  := .captureValueWithPossibleSideEffects(.Loc, 2, .Target)
			,  := .captureValueWithPossibleSideEffects(.Loc, 2, .Index)
			return (((
				js_ast.Expr{Loc: .Loc, Data: &js_ast.EIndex{
					Target: (),
					Index:  (),
				}},
				js_ast.Expr{Loc: .Loc, Data: &js_ast.EIndex{
					Target: (),
					Index:  (),
				}},
			)))
		}

	case *js_ast.EIdentifier:
		return (
			js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .Ref}},
			,
		)
	}
We shouldn't get here with valid syntax? Just let this through for now since there's currently no assignment target validation. Garbage in, garbage out.
"a.#b **= c" => "__privateSet(a, #b, __pow(__privateGet(a, #b), c))"
		,  := .captureValueWithPossibleSideEffects(, 2, )
		return (.lowerPrivateSet((), , ,
			.callRuntime(, "__pow", []js_ast.Expr{
				.lowerPrivateGet((), , ),
				.Right,
			})))
	}

"a **= b" => "a = __pow(a, b)"
		return js_ast.Assign(, .callRuntime(, "__pow", []js_ast.Expr{, .Right}))
	})
}

func ( *parser) ( logger.Loc,  *js_ast.EBinary) js_ast.Expr {
	if , ,  := .extractPrivateIndex(.Left);  != nil {
"a.#b ??= c" => "(_a = __privateGet(a, #b)) != null ? _a : __privateSet(a, #b, c)"
			,  := .captureValueWithPossibleSideEffects(, 2, )
			 := .lowerPrivateGet((), , )
			 := .lowerPrivateSet((), , , .Right)
			return (.lowerNullishCoalescing(, , ))
		}
"a.#b ??= c" => "__privateGet(a, #b) ?? __privateSet(a, #b, c)"
		,  := .captureValueWithPossibleSideEffects(, 2, )
		return (js_ast.Expr{Loc: , Data: &js_ast.EBinary{
			Op:    js_ast.BinOpNullishCoalescing,
			Left:  .lowerPrivateGet((), , ),
			Right: .lowerPrivateSet((), , , .Right),
		}})
	}

	return .lowerAssignmentOperator(.Left, func( js_ast.Expr,  js_ast.Expr) js_ast.Expr {
"a ??= b" => "(_a = a) != null ? _a : a = b"
			return .lowerNullishCoalescing(, , js_ast.Assign(, .Right))
		}
"a ??= b" => "a ?? (a = b)"
"a.#b &&= c" => "__privateGet(a, #b) && __privateSet(a, #b, c)" "a.#b ||= c" => "__privateGet(a, #b) || __privateSet(a, #b, c)"
		,  := .captureValueWithPossibleSideEffects(, 2, )
		return (js_ast.Expr{Loc: , Data: &js_ast.EBinary{
			Op:    ,
			Left:  .lowerPrivateGet((), , ),
			Right: .lowerPrivateSet((), , , .Right),
		}})
	}

"a &&= b" => "a && (a = b)" "a ||= b" => "a || (a = b)"
		return js_ast.Expr{Loc: , Data: &js_ast.EBinary{
			Op:    ,
			Left:  ,
			Right: js_ast.Assign(, .Right),
		}}
	})
}

"x ?? y" => "x != null ? x : y" "x() ?? y()" => "_a = x(), _a != null ? _a : y"
	,  := .captureValueWithPossibleSideEffects(, 2, )
	return (js_ast.Expr{Loc: , Data: &js_ast.EIf{
		Test: js_ast.Expr{Loc: , Data: &js_ast.EBinary{
			Op:    js_ast.BinOpLooseNe,
			Left:  (),
			Right: js_ast.Expr{Loc: , Data: &js_ast.ENull{}},
		}},
		Yes: (),
		No:  ,
	}})
}
Lower object spread for environments that don't support them. Non-spread properties are grouped into object literals and then passed to __assign() like this (__assign() is an alias for Object.assign()): "{a, b, ...c, d, e}" => "__assign(__assign(__assign({a, b}, c), {d, e})" If the object literal starts with a spread, then we pass an empty object literal to __assign() to make sure we clone the object: "{...a, b}" => "__assign(__assign({}, a), {b})" It's not immediately obvious why we don't compile everything to a single call to __assign(). After all, Object.assign() can take any number of arguments. The reason is to preserve the order of side effects. Consider this code: let a = {get x() { b = {y: 2}; return 1 }} let b = {} let c = {...a, ...b} Converting the above code to "let c = __assign({}, a, b)" means "c" becomes "{x: 1}" which is incorrect. Converting the above code instead to "let c = __assign(__assign({}, a), b)" means "c" becomes "{x: 1, y: 2}" which is correct.
func ( *parser) ( logger.Loc,  *js_ast.EObject) js_ast.Expr {
	 := false

	if .options.unsupportedJSFeatures.Has(compat.ObjectRestSpread) {
		for ,  := range .Properties {
			if .Kind == js_ast.PropertySpread {
				 = true
				break
			}
		}
	}

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

	var  js_ast.Expr
	 := []js_ast.Property{}

	for ,  := range .Properties {
		if .Kind != js_ast.PropertySpread {
			 = append(, )
			continue
		}

		if len() > 0 || .Data == nil {
"{a, ...b}" => "__assign({a}, b)"
				 = js_ast.Expr{Loc: , Data: &js_ast.EObject{
					Properties:   ,
					IsSingleLine: .IsSingleLine,
				}}
"{...a, b, ...c}" => "__assign(__assign(__assign({}, a), {b}), c)"
				 = .callRuntime(, "__assign",
					[]js_ast.Expr{, {Loc: , Data: &js_ast.EObject{
						Properties:   ,
						IsSingleLine: .IsSingleLine,
					}}})
			}
			 = []js_ast.Property{}
		}
"{a, ...b}" => "__assign({a}, b)"
		 = .callRuntime(, "__assign", []js_ast.Expr{, *.Value})
	}

"{...a, b}" => "__assign(__assign({}, a), {b})"
		 = .callRuntime(, "__assign", []js_ast.Expr{, {Loc: , Data: &js_ast.EObject{
			Properties:   ,
			IsSingleLine: .IsSingleLine,
		}}})
	}

	return 
}

func ( *parser) ( js_ast.Expr,  logger.Loc,  *js_ast.EPrivateIdentifier) js_ast.Expr {
	switch .symbols[.Ref.InnerIndex].Kind {
"this.#method" => "__privateMethod(this, #method, method_fn)"
		 := .privateGetters[.Ref]
		.recordUsage()
		return .callRuntime(.Loc, "__privateMethod", []js_ast.Expr{
			,
			{Loc: , Data: &js_ast.EIdentifier{Ref: .Ref}},
			{Loc: , Data: &js_ast.EIdentifier{Ref: }},
		})

	case js_ast.SymbolPrivateGet, js_ast.SymbolPrivateStaticGet,
"this.#getter" => "__privateGet(this, #getter, getter_get)"
		 := .privateGetters[.Ref]
		.recordUsage()
		return .callRuntime(.Loc, "__privateGet", []js_ast.Expr{
			,
			{Loc: , Data: &js_ast.EIdentifier{Ref: .Ref}},
			{Loc: , Data: &js_ast.EIdentifier{Ref: }},
		})

"this.#field" => "__privateGet(this, #field)"
		return .callRuntime(.Loc, "__privateGet", []js_ast.Expr{
			,
			{Loc: , Data: &js_ast.EIdentifier{Ref: .Ref}},
		})
	}
}

func ( *parser) (
	 js_ast.Expr,
	 logger.Loc,
	 *js_ast.EPrivateIdentifier,
	 js_ast.Expr,
) js_ast.Expr {
	switch .symbols[.Ref.InnerIndex].Kind {
	case js_ast.SymbolPrivateSet, js_ast.SymbolPrivateStaticSet,
"this.#setter = 123" => "__privateSet(this, #setter, 123, setter_set)"
		 := .privateSetters[.Ref]
		.recordUsage()
		return .callRuntime(.Loc, "__privateSet", []js_ast.Expr{
			,
			{Loc: , Data: &js_ast.EIdentifier{Ref: .Ref}},
			,
			{Loc: , Data: &js_ast.EIdentifier{Ref: }},
		})

"this.#field = 123" => "__privateSet(this, #field, 123)"
		return .callRuntime(.Loc, "__privateSet", []js_ast.Expr{
			,
			{Loc: , Data: &js_ast.EIdentifier{Ref: .Ref}},
			,
		})
	}
}

func ( *parser) ( js_ast.Expr,  logger.Loc,  *js_ast.EPrivateIdentifier,  js_ast.OpCode,  bool) js_ast.Expr {
	,  := .captureValueWithPossibleSideEffects(.Loc, 2, )
	 = ()
Load the private field and then use the unary "+" operator to force it to be a number. Otherwise the binary "+" operator may cause string concatenation instead of addition if one of the operands is not a number.
	 := js_ast.Expr{Loc: .Loc, Data: &js_ast.EUnary{
		Op:    js_ast.UnOpPos,
		Value: .lowerPrivateGet((), , ),
	}}

"target.#private++" => "__privateSet(target, #private, _a = +__privateGet(target, #private) + 1), _a"
		,  := .captureValueWithPossibleSideEffects(.Loc, 2, )
		 := ((.lowerPrivateSet(, , , js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{
			Op:    ,
			Left:  (),
			Right: js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: 1}},
		}})))
		return js_ast.JoinWithComma(, ())
	}
"++target.#private" => "__privateSet(target, #private, +__privateGet(target, #private) + 1)"
	return (.lowerPrivateSet(, , , js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{
		Op:    ,
		Left:  ,
		Right: js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: 1}},
	}}))
}

"target.#private += 123" => "__privateSet(target, #private, __privateGet(target, #private) + 123)"
	,  := .captureValueWithPossibleSideEffects(.Loc, 2, )
	return (.lowerPrivateSet((), , , js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{
		Op:    ,
		Left:  .lowerPrivateGet((), , ),
		Right: ,
	}}))
}
Returns valid data if target is an expression of the form "foo.#bar" and if the language target is such that private members must be lowered
func ( *parser) ( js_ast.Expr) (js_ast.Expr, logger.Loc, *js_ast.EPrivateIdentifier) {
	if ,  := .Data.(*js_ast.EIndex);  {
		if ,  := .Index.Data.(*js_ast.EPrivateIdentifier);  && .isPrivateUnsupported() {
			return .Target, .Index.Loc, 
		}
	}
	return js_ast.Expr{}, logger.Loc{}, nil
}

func ( js_ast.Binding) bool {
	switch b := .Data.(type) {
	case *js_ast.BArray:
		for ,  := range .Items {
			if (.Binding) {
				return true
			}
		}
	case *js_ast.BObject:
		for ,  := range .Properties {
			if .IsSpread || (.Value) {
				return true
			}
		}
	}
	return false
}

func ( js_ast.Expr) bool {
	switch e := .Data.(type) {
	case *js_ast.EBinary:
		if .Op == js_ast.BinOpAssign && (.Left) {
			return true
		}
	case *js_ast.EArray:
		for ,  := range .Items {
			if () {
				return true
			}
		}
	case *js_ast.EObject:
		for ,  := range .Properties {
			if .Kind == js_ast.PropertySpread || (*.Value) {
				return true
			}
		}
	}
	return false
}

func ( *parser) ( []js_ast.Decl) []js_ast.Decl {
	if !.options.unsupportedJSFeatures.Has(compat.ObjectRestSpread) {
		return 
	}
Don't do any allocations if there are no object rest patterns. We want as little overhead as possible in the common case.
	for ,  := range  {
		if .Value != nil && bindingHasObjectRest(.Binding) {
			 := append([]js_ast.Decl{}, [:]...)
			for ,  := range [:] {
				if .Value != nil {
					 := .convertBindingToExpr(.Binding, nil)
					if ,  := .lowerObjectRestToDecls(, *.Value, );  {
						 = 
						continue
					}
				}
				 = append(, )
			}

			return 
		}
	}

	return 
}

func ( *parser) ( js_ast.Stmt,  *js_ast.Stmt) {
	if !.options.unsupportedJSFeatures.Has(compat.ObjectRestSpread) {
		return
	}

	var  js_ast.Stmt

	switch s := .Data.(type) {
"for ({...x} in y) {}" "for ({...x} of y) {}"
		if exprHasObjectRest(.Value) {
			 := .generateTempRef(tempRefNeedsDeclare, "")
			if ,  := .lowerObjectRestInAssign(.Value, js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: }});  {
				.Value.Data = &js_ast.EIdentifier{Ref: }
				 = js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: }}
			}
		}

"for (let {...x} in y) {}" "for (let {...x} of y) {}"
		if len(.Decls) == 1 && bindingHasObjectRest(.Decls[0].Binding) {
			 := .generateTempRef(tempRefNoDeclare, "")
			 := js_ast.Decl{Binding: .Decls[0].Binding, Value: &js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: }}}
			.recordUsage()
			 := .lowerObjectRestInDecls([]js_ast.Decl{})
			.Decls[0].Binding.Data = &js_ast.BIdentifier{Ref: }
			 = js_ast.Stmt{Loc: .Loc, Data: &js_ast.SLocal{Kind: .Kind, Decls: }}
		}
	}

	if .Data != nil {
If there's already a block, insert at the front
			 := make([]js_ast.Stmt, 0, 1+len(.Stmts))
			.Stmts = append(append(, ), .Stmts...)
Otherwise, make a block and insert at the front
			.Data = &js_ast.SBlock{Stmts: []js_ast.Stmt{, *}}
		}
	}
}

func ( *parser) ( *js_ast.Catch) {
	if !.options.unsupportedJSFeatures.Has(compat.ObjectRestSpread) {
		return
	}

	if .Binding != nil && bindingHasObjectRest(*.Binding) {
		 := .generateTempRef(tempRefNoDeclare, "")
		 := js_ast.Decl{Binding: *.Binding, Value: &js_ast.Expr{Loc: .Binding.Loc, Data: &js_ast.EIdentifier{Ref: }}}
		.recordUsage()
		 := .lowerObjectRestInDecls([]js_ast.Decl{})
		.Binding.Data = &js_ast.BIdentifier{Ref: }
		 := make([]js_ast.Stmt, 0, 1+len(.Body))
		 = append(, js_ast.Stmt{Loc: .Binding.Loc, Data: &js_ast.SLocal{Kind: js_ast.LocalLet, Decls: }})
		.Body = append(, .Body...)
	}
}

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

	 := func( js_ast.Expr,  js_ast.Expr) {
		 = maybeJoinWithComma(, js_ast.Assign(, ))
	}

	if .lowerObjectRestHelper(, , , tempRefNeedsDeclare) {
		return , true
	}

	return js_ast.Expr{}, false
}

func ( *parser) ( js_ast.Expr,  js_ast.Expr,  []js_ast.Decl) ([]js_ast.Decl, bool) {
	 := func( js_ast.Expr,  js_ast.Expr) {
		,  := .convertExprToBinding(, nil)
		if len() > 0 {
			panic("Internal error")
		}
		 = append(, js_ast.Decl{Binding: , Value: &})
	}

	if .lowerObjectRestHelper(, , , tempRefNoDeclare) {
		return , true
	}

	return nil, false
}

func ( *parser) (
	 js_ast.Expr,
	 js_ast.Expr,
	 func(js_ast.Expr, js_ast.Expr),
	 generateTempRefArg,
) bool {
	if !.options.unsupportedJSFeatures.Has(compat.ObjectRestSpread) {
		return false
	}
Check if this could possibly contain an object rest binding
	switch .Data.(type) {
	case *js_ast.EArray, *js_ast.EObject:
	default:
		return false
	}
Scan for object rest bindings and initalize rest binding containment
	 := make(map[js_ast.E]bool)
	var  func(js_ast.Expr) bool
	 = func( js_ast.Expr) bool {
		 := false
		switch e := .Data.(type) {
		case *js_ast.EBinary:
			if .Op == js_ast.BinOpAssign && (.Left) {
				 = true
			}
		case *js_ast.EArray:
			for ,  := range .Items {
				if () {
					 = true
				}
			}
		case *js_ast.EObject:
			for ,  := range .Properties {
				if .Kind == js_ast.PropertySpread || (*.Value) {
					 = true
				}
			}
		}
		if  {
			[.Data] = true
		}
		return 
	}
	()
	if len() == 0 {
		return false
	}
If there is at least one rest binding, lower the whole expression
	var  func(js_ast.Expr, js_ast.Expr, []func() js_ast.Expr)

	 := func( js_ast.Expr) js_ast.Ref {
		if ,  := .Data.(*js_ast.EIdentifier);  {
			return .Ref
		}
If the initializer isn't already a bare identifier that we can reference, store the initializer first so we can reference it later. The initializer may have side effects so we must evaluate it once.
		 := .generateTempRef(, "")
		(js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: }}, )
		.recordUsage()
		return 
	}

	 := func(
		 []js_ast.Property,
		 js_ast.Expr,
		 js_ast.Expr,
		 []func() js_ast.Expr,
		 bool,
If there are properties before this one, store the initializer in a temporary so we can reference it multiple times, then create a new destructuring assignment for these properties
"let {a, ...b} = c"
			 := ()
			(js_ast.Expr{Loc: [0].Key.Loc, Data: &js_ast.EObject{Properties: , IsSingleLine: }},
				js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: }})
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: }}
			.recordUsage()
			.recordUsage()
		}
Call "__rest" to clone the initializer without the keys for previous properties, then assign the result to the binding for the rest pattern
		 := make([]js_ast.Expr, len())
		for ,  := range  {
			[] = ()
		}
		(, .callRuntime(.Loc, "__rest", []js_ast.Expr{,
			{Loc: .Loc, Data: &js_ast.EArray{Items: , IsSingleLine: }}}))
	}

	 := func(
		 []js_ast.Expr,
		 js_ast.Expr,
		 []js_ast.Expr,
		 js_ast.Expr,
		 bool,
If this has a default value, skip the value to target the binding
		 := &
		if ,  := .Data.(*js_ast.EBinary);  && .Op == js_ast.BinOpAssign {
			 = &.Left
		}
Swap the binding with a temporary
		 := .generateTempRef(, "")
		 := *
		.Data = &js_ast.EIdentifier{Ref: }
		 := append(, )
If there are any items left over, defer them until later too
		var  js_ast.Expr
		var  js_ast.Expr
		if len() > 0 {
			 := .generateTempRef(, "")
			 := [0].Loc
			 = js_ast.Expr{Loc: , Data: &js_ast.EArray{Items: , IsSingleLine: }}
			 = js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}
			 = append(, js_ast.Expr{Loc: , Data: &js_ast.ESpread{Value: js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}}})
			.recordUsage()
			.recordUsage()
		}
The original destructuring assignment must come first
		(js_ast.Expr{Loc: .Loc, Data: &js_ast.EArray{Items: , IsSingleLine: }}, )
Then the deferred split is evaluated
		(, js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: }}, nil)
		.recordUsage()
Then anything after the split
		if len() > 0 {
			(, , nil)
		}
	}

	 := func(
		 []js_ast.Property,
		 []js_ast.Property,
		 js_ast.Expr,
		 []func() js_ast.Expr,
		 bool,
If there are properties after the split, store the initializer in a temporary so we can reference it multiple times
		var  js_ast.Expr
		if len() > 0 {
			 := ()
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: }}
			 = js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: }}
		}

		 := &[len()-1]
		 := .Value
Swap the binding with a temporary
		 := .generateTempRef(, "")
		 := *
		.Data = &js_ast.EIdentifier{Ref: }
		.recordUsage()
Use a destructuring assignment to unpack everything up to and including the split point
		(js_ast.Expr{Loc: .Loc, Data: &js_ast.EObject{Properties: , IsSingleLine: }}, )
Handle any nested rest binding patterns inside the split point
		(, js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: }}, nil)
		.recordUsage()
Then continue on to any properties after the split
		if len() > 0 {
			(js_ast.Expr{Loc: .Loc, Data: &js_ast.EObject{
				Properties:   ,
				IsSingleLine: ,
			}}, , )
		}
	}
This takes an expression representing a binding pattern as input and returns that binding pattern with any object rest patterns stripped out. The object rest patterns are lowered and appended to "exprChain" along with any child binding patterns that came after the binding pattern containing the object rest pattern. This transform must be very careful to preserve the exact evaluation order of all assignments, default values, and computed property keys. Unlike the Babel and TypeScript compilers, this transform does not lower binding patterns other than object rest patterns. For example, array spread patterns are preserved. Certain patterns such as "{a: {...a}, b: {...b}, ...c}" may need to be split multiple times. In this case the "capturedKeys" argument allows the visitor to pass on captured keys to the tail-recursive call that handles the properties after the split.
	 = func( js_ast.Expr,  js_ast.Expr,  []func() js_ast.Expr) {
		switch e := .Data.(type) {
Split on the first binding with a nested rest binding pattern
"let [a, {...b}, c] = d"
				if [.Data] {
					(.Items[:], , append([]js_ast.Expr{}, .Items[+1:]...), , .IsSingleLine)
					return
				}
			}

		case *js_ast.EObject:
			 := len(.Properties) - 1
			 :=  >= 0 && .Properties[].Kind == js_ast.PropertySpread
Split on the first binding with a nested rest binding pattern
			for  := range .Properties {
				 := &.Properties[]
"let {a, ...b} = c"
				if .Kind == js_ast.PropertySpread {
					(.Properties[:], *.Value, , , .IsSingleLine)
					return
				}
Save a copy of this key so the rest binding can exclude it
				if  {
					,  := .captureKeyForObjectRest(.Key)
					.Key = 
					 = append(, )
				}
"let {a: {...b}, c} = d"
				if [.Value.Data] {
					(.Properties[:+1], .Properties[+1:], , , .IsSingleLine)
					return
				}
			}
		}

		(, )
	}

	(, , nil)
	return true
}
Save a copy of the key for the call to "__rest" later on. Certain expressions can be converted to keys more efficiently than others.
func ( *parser) ( js_ast.Expr) ( js_ast.Expr,  func() js_ast.Expr) {
	 := .Loc
	 = 

	switch k := .Data.(type) {
	case *js_ast.EString:
		 = func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.EString{Value: .Value}} }

Emit it as the number plus a string (i.e. call toString() on it). It's important to do it this way instead of trying to print the float as a string because Go's floating-point printer doesn't behave exactly the same as JavaScript and if they are different, the generated code will be wrong.
		 = func() js_ast.Expr {
			return js_ast.Expr{Loc: , Data: &js_ast.EBinary{
				Op:    js_ast.BinOpAdd,
				Left:  js_ast.Expr{Loc: , Data: &js_ast.ENumber{Value: .Value}},
				Right: js_ast.Expr{Loc: , Data: &js_ast.EString{}},
			}}
		}

	case *js_ast.EIdentifier:
		 = func() js_ast.Expr {
			.recordUsage(.Ref)
			return .callRuntime(, "__restKey", []js_ast.Expr{{Loc: , Data: &js_ast.EIdentifier{Ref: .Ref}}})
		}

If it's an arbitrary expression, it probably has a side effect. Stash it in a temporary reference so we don't evaluate it twice.
		 := .generateTempRef(tempRefNeedsDeclare, "")
		 = js_ast.Assign(js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}, )
		 = func() js_ast.Expr {
			.recordUsage()
			return .callRuntime(, "__restKey", []js_ast.Expr{{Loc: , Data: &js_ast.EIdentifier{Ref: }}})
		}
	}

	return
}
Lower class fields for environments that don't support them. This either takes a statement or an expression.
func ( *parser) ( js_ast.Stmt,  js_ast.Expr,  js_ast.Ref) ([]js_ast.Stmt, js_ast.Expr) {
	type  uint8
	const (
		  = iota
		
		
		
	)
Unpack the class from the statement or expression
	var  
	var  *js_ast.Class
	var  logger.Loc
	var  js_ast.LocRef
	var  string
	if .Data == nil {
		,  := .Data.(*js_ast.EClass)
		 = &.Class
		 = 
		if .Name != nil {
			 := &.symbols[.Name.Ref.InnerIndex]
			 = .OriginalName
The shadowing name inside the class expression should be the same as the class expression name itself
			if  != js_ast.InvalidRef {
				.mergeSymbols(, .Name.Ref)
			}
Remove unused class names when minifying. Check this after we merge in the shadowing name above since that will adjust the use count.
			if .options.mangleSyntax && .UseCountEstimate == 0 {
				.Name = nil
			}
		}
	} else if ,  := .Data.(*js_ast.SClass);  {
		 = &.Class
		if .IsExport {
			 = 
		} else {
			 = 
		}
		 = .symbols[.Name.Ref.InnerIndex].OriginalName
	} else {
		,  := .Data.(*js_ast.SExportDefault)
		,  := .Value.Stmt.Data.(*js_ast.SClass)
		 = &.Class
		 = .DefaultName
		 = 
		if .Name != nil {
			 = .symbols[.Name.Ref.InnerIndex].OriginalName
		} else {
			 = "default"
		}
	}
	if .Data == nil {
		 = .Loc
	} else {
		 = .Loc
	}

	var  *js_ast.EFunction
	var  []js_ast.Stmt
	var  []js_ast.Stmt
	var  []js_ast.Stmt
	 := 0
These expressions are generated after the class body, in this order
	var  js_ast.Expr
	var  []js_ast.Expr
	var  []js_ast.Expr
	var  []js_ast.Expr
	var  []js_ast.Expr
	var  []js_ast.Expr
These are only for class expressions that need to be captured
	var  func() js_ast.Expr
	var  func(js_ast.Expr) js_ast.Expr
	 := false
Class statements can be missing a name if they are in an "export default" statement: export default class { static foo = 123 }
	 = func() js_ast.Expr {
If this is a class expression, capture and store it. We have to do this even if it has a name since the name isn't exposed outside the class body.
			 := &js_ast.EClass{Class: *}
			 = &.Class
			,  = .captureValueWithPossibleSideEffects(, 2, js_ast.Expr{Loc: , Data: })
			 = ()
			 = true
			 := ()
If we're storing the class expression in a variable, remove the class name and rewrite all references to the class name with references to the temporary variable holding the class expression. This ensures that references to the class expression by name in any expressions that end up being pulled outside of the class body still work. For example: let Bar = class Foo { static foo = 123 static bar = Foo.foo } This might be converted into the following: var _a; let Bar = (_a = class { }, _a.foo = 123, _a.bar = _a.foo, _a);
			if .Name != nil {
				.mergeSymbols(.Name.Ref, .Data.(*js_ast.EIdentifier).Ref)
				.Name = nil
			}

			return 
		} else {
			if .Name == nil {
				if  ==  {
					.Name = &
				} else {
					.Name = &js_ast.LocRef{Loc: , Ref: .generateTempRef(tempRefNoDeclare, "zomzomz")}
				}
			}
			.recordUsage(.Name.Ref)
			return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: .Name.Ref}}
		}
	}
Safari workaround: Automatically avoid TDZ issues when bundling
	 := .options.mode == config.ModeBundle && .currentScope.Parent == nil

Merge parameter decorators with method decorators
		if .options.ts.Parse && .IsMethod {
			if ,  := .Value.Data.(*js_ast.EFunction);  {
				 := false
				if ,  := .Key.Data.(*js_ast.EString);  {
					 = js_lexer.UTF16EqualsString(.Value, "constructor")
				}
				for ,  := range .Fn.Args {
Generate a call to "__param()" for this parameter decorator
						var  *[]js_ast.Expr = &.TSDecorators
						if  {
							 = &.TSDecorators
						}
						* = append(*,
							.callRuntime(.Loc, "__param", []js_ast.Expr{
								{Loc: .Loc, Data: &js_ast.ENumber{Value: float64()}},
								,
							}),
						)
					}
				}
			}
		}
The TypeScript class field transform requires removing fields without initializers. If the field is removed, then we only need the key for its side effects and we don't need a temporary reference for the key. However, the TypeScript compiler doesn't remove the field when doing strict class field initialization, so we shouldn't either.
		,  := .Key.Data.(*js_ast.EPrivateIdentifier)
		 :=  != nil && .isPrivateUnsupported()
		 := .options.ts.Parse && !.IsMethod && .Initializer == nil &&
			!.options.useDefineForClassFields && !
Class fields must be lowered if the environment doesn't support them
Be conservative and always lower static fields when we're doing TDZ- avoidance and the shadowing name for the class was captured somewhere.
		if !.IsMethod && .IsStatic &&  &&  != js_ast.InvalidRef {
			 = true
		}
Make sure the order of computed property keys doesn't change. These expressions have side effects and must be evaluated in order.
		 := .Key
		if .IsComputed && (.options.ts.Parse || len(.TSDecorators) > 0 ||
			 || .Data != nil) {
			 := true
			if len(.TSDecorators) == 0 && (.IsMethod || ) {
				 = false
			}

Just evaluate the key for its side effects
				 = maybeJoinWithComma(, .Key)
Store the key in a temporary so we can assign to it later
				 := .generateTempRef(tempRefNeedsDeclare, "")
				 = maybeJoinWithComma(,
					js_ast.Assign(js_ast.Expr{Loc: .Key.Loc, Data: &js_ast.EIdentifier{Ref: }}, .Key))
				.Key = js_ast.Expr{Loc: .Key.Loc, Data: &js_ast.EIdentifier{Ref: }}
				 = .Key
			}
If this is a computed method, the property value will be used immediately. In this case we inline all computed properties so far to make sure all computed properties before this one are evaluated first.
			if .IsMethod {
				.Key = 
				 = js_ast.Expr{}
			}
		}
Handle decorators
Generate a single call to "__decorate()" for this property
			if len(.TSDecorators) > 0 {
				 := .Key.Loc
Clone the key for the property descriptor
				var  js_ast.Expr
				switch k := .Data.(type) {
				case *js_ast.ENumber:
					 = js_ast.Expr{Loc: , Data: &js_ast.ENumber{Value: .Value}}
				case *js_ast.EString:
					 = js_ast.Expr{Loc: , Data: &js_ast.EString{Value: .Value}}
				case *js_ast.EIdentifier:
					 = js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: .Ref}}
				default:
					panic("Internal error")
				}
This code tells "__decorate()" if the descriptor should be undefined
				 := float64(1)
				if !.IsMethod {
					 = 2
				}
Instance properties use the prototype, static properties use the class
				var  js_ast.Expr
				if .IsStatic {
					 = ()
				} else {
					 = js_ast.Expr{Loc: , Data: &js_ast.EDot{Target: (), Name: "prototype", NameLoc: }}
				}

				 := .callRuntime(, "__decorate", []js_ast.Expr{
					{Loc: , Data: &js_ast.EArray{Items: .TSDecorators}},
					,
					,
					{Loc: , Data: &js_ast.ENumber{Value: }},
				})
Static decorators are grouped after instance decorators
				if .IsStatic {
					 = append(, )
				} else {
					 = append(, )
				}
			}
		}
Instance and static fields are a JavaScript feature, not just a TypeScript feature. Move their initializers from the class body to either the constructor (instance fields) or after the class (static fields).
The TypeScript compiler doesn't follow the JavaScript spec for uninitialized fields. They are supposed to be set to undefined but the TypeScript compiler just omits them entirely.
			if ! {
				 := .Key.Loc
Determine where to store the field
				var  js_ast.Expr
				if .IsStatic {
					 = ()
				} else {
					 = js_ast.Expr{Loc: , Data: &js_ast.EThis{}}
				}
Generate the assignment initializer
				var  js_ast.Expr
				if .Initializer != nil {
					 = *.Initializer
				} else {
					 = js_ast.Expr{Loc: , Data: &js_ast.EUndefined{}}
				}
Generate the assignment target
				var  js_ast.Expr
Generate a new symbol for this private field
Initialize the private field to a new WeakMap
Add every newly-constructed instance into this map
					 = js_ast.Expr{Loc: , Data: &js_ast.ECall{
						Target: js_ast.Expr{Loc: , Data: &js_ast.EDot{
							Target:  js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }},
							Name:    "set",
							NameLoc: ,
						}},
						Args: []js_ast.Expr{
							,
							,
						},
					}}
					.recordUsage()
				} else if  == nil && .options.useDefineForClassFields {
					if ,  := .Data.(*js_ast.EUndefined);  {
						 = .callRuntime(, "__publicField", []js_ast.Expr{, .Key})
					} else {
						 = .callRuntime(, "__publicField", []js_ast.Expr{, .Key, })
					}
				} else {
					if ,  := .Key.Data.(*js_ast.EString);  && !.IsComputed {
						 = js_ast.Expr{Loc: , Data: &js_ast.EDot{
							Target:  ,
							Name:    js_lexer.UTF16ToString(.Value),
							NameLoc: ,
						}}
					} else {
						 = js_ast.Expr{Loc: , Data: &js_ast.EIndex{
							Target: ,
							Index:  .Key,
						}}
					}

					 = js_ast.Assign(, )
				}

Move this property to an assignment after the class ends
					 = append(, )
Move this property to an assignment inside the class constructor
					 = append(, js_ast.Stmt{Loc: , Data: &js_ast.SExpr{Value: }})
				}
			}

Remove the field from the class body
				continue
			}
Keep the private field but remove the initializer
			.Initializer = nil
		}
Remember where the constructor is for later
		if .IsMethod {
			if  {
				 := .Key.Loc
Don't generate a symbol for a getter/setter pair twice
Generate a new symbol for this private method
Initialize the private method to a new WeakSet
Determine where to store the private method
					var  js_ast.Expr
					if .IsStatic {
						 = ()
					} else {
						 = js_ast.Expr{Loc: , Data: &js_ast.EThis{}}
					}
Add every newly-constructed instance into this map
					 := js_ast.Expr{Loc: , Data: &js_ast.ECall{
						Target: js_ast.Expr{Loc: , Data: &js_ast.EDot{
							Target:  js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }},
							Name:    "add",
							NameLoc: ,
						}},
						Args: []js_ast.Expr{
							,
						},
					}}
					.recordUsage()
Make sure that adding to the map happens before any field initializers to handle cases like this: class A { pub = this.#priv; #priv() {} }
Move this property to an assignment after the class ends
						 = append(, )
Move this property to an assignment inside the class constructor
						 = append(, js_ast.Stmt{Loc: , Data: &js_ast.SExpr{Value: }})
					}
				}
Move the method definition outside the class body
				 := .generateTempRef(tempRefNeedsDeclare, "_")
				if .Kind == js_ast.PropertySet {
					.symbols[.InnerIndex].Link = .privateSetters[.Ref]
				} else {
					.symbols[.InnerIndex].Link = .privateGetters[.Ref]
				}
				 = append(, js_ast.Assign(
					js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }},
					*.Value,
				))
				continue
			} else if ,  := .Key.Data.(*js_ast.EString);  && js_lexer.UTF16EqualsString(.Value, "constructor") {
				if ,  := .Value.Data.(*js_ast.EFunction);  {
					 = 
Initialize TypeScript constructor parameter fields
					if .options.ts.Parse {
						for ,  := range .Fn.Args {
							if .IsTypeScriptCtorField {
								if ,  := .Binding.Data.(*js_ast.BIdentifier);  {
									 = append(, js_ast.AssignStmt(
										js_ast.Expr{Loc: .Binding.Loc, Data: &js_ast.EDot{
											Target:  js_ast.Expr{Loc: .Binding.Loc, Data: &js_ast.EThis{}},
											Name:    .symbols[.Ref.InnerIndex].OriginalName,
											NameLoc: .Binding.Loc,
										}},
										js_ast.Expr{Loc: .Binding.Loc, Data: &js_ast.EIdentifier{Ref: .Ref}},
									))
								}
							}
						}
					}
				}
			}
		}
Keep this property
		.Properties[] = 
		++
	}
Finish the filtering operation
	.Properties = .Properties[:]
Insert instance field initializers into the constructor
Create a constructor if one doesn't already exist
		if  == nil {
			 = &js_ast.EFunction{}
Append it to the list to reuse existing allocation space
			.Properties = append(.Properties, js_ast.Property{
				IsMethod: true,
				Key:      js_ast.Expr{Loc: , Data: &js_ast.EString{Value: js_lexer.StringToUTF16("constructor")}},
				Value:    &js_ast.Expr{Loc: , Data: },
			})
Make sure the constructor has a super() call if needed
			if .Extends != nil {
				 := .newSymbol(js_ast.SymbolUnbound, "arguments")
				.currentScope.Generated = append(.currentScope.Generated, )
				.Fn.Body.Stmts = append(.Fn.Body.Stmts, js_ast.Stmt{Loc: , Data: &js_ast.SExpr{Value: js_ast.Expr{Loc: , Data: &js_ast.ECall{
					Target: js_ast.Expr{Loc: , Data: &js_ast.ESuper{}},
					Args:   []js_ast.Expr{{Loc: , Data: &js_ast.ESpread{Value: js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}}}},
				}}}})
			}
		}
Insert the instance field initializers after the super call if there is one
		 := .Fn.Body.Stmts
		 := []js_ast.Stmt{}
		for ,  := range  {
			if js_ast.IsSuperCall() {
				 = append(, [0:+1]...)
				 = [+1:]
				break
			}
		}
		 = append(, ...)
		 = append(, ...)
		 = append(, ...)
		.Fn.Body.Stmts = append(, ...)
Sort the constructor first to match the TypeScript compiler's output
		for  := 0;  < len(.Properties); ++ {
			if .Properties[].Value != nil && .Properties[].Value.Data ==  {
				 := .Properties[]
				for  := ;  > 0; -- {
					.Properties[] = .Properties[-1]
				}
				.Properties[0] = 
				break
			}
		}
	}
Pack the class back into an expression. We don't need to handle TypeScript decorators for class expressions because TypeScript doesn't support them.
Calling "nameFunc" will replace "expr", so make sure to do that first before joining "expr" with any other expressions
		var  js_ast.Expr
		if  || .Data != nil ||
			len() > 0 || len() > 0 || len() > 0 {
			 = ()
		}
Then join "expr" with any other expressions that apply
		if .Data != nil {
			 = js_ast.JoinWithComma(, )
		}
		for ,  := range  {
			 = js_ast.JoinWithComma(, )
		}
		for ,  := range  {
			 = js_ast.JoinWithComma(, )
		}
		for ,  := range  {
			 = js_ast.JoinWithComma(, )
		}
Finally join "expr" with the variable that holds the class object
		if .Data != nil {
			 = js_ast.JoinWithComma(, )
		}
		if  != nil {
			 = ()
		}
Optionally preserve the name
		if .options.keepNames &&  != "" {
			 = .keepExprSymbolName(, )
		}
		return nil, 
	}
If this is true, we have removed some code from the class body that could potentially contain an expression that captures the shadowing class name. This could lead to incorrect behavior if the class is later re-assigned, since the removed code would no longer be in the shadowing scope.
	 :=  != js_ast.InvalidRef &&
		(.Data != nil ||
			len() > 0 ||
			len() > 0 ||
			len() > 0 ||
			len() > 0 ||
			len() > 0 ||
			len(.TSDecorators) > 0)
Optionally preserve the name
	var  js_ast.Stmt
	if .options.keepNames &&  != "" {
		 := ()
		 = .keepStmtSymbolName(.Loc, .Data.(*js_ast.EIdentifier).Ref, )
	}
Pack the class back into a statement, with potentially some extra statements afterwards
	var  []js_ast.Stmt
	var  js_ast.LocRef
	 := false
	if len(.TSDecorators) > 0 ||  ||  {
		 = true
		 := ()
		 := .Data.(*js_ast.EIdentifier).Ref
		 = js_ast.LocRef{Loc: .Loc, Ref: }
		 := js_ast.EClass{Class: *}
		 = &.Class
		 := &js_ast.Expr{Loc: , Data: &}

If something captures the shadowing name and escapes the class body, make a new constant to store the class and forward that value to a mutable alias. That way if the alias is mutated, everything bound to the original constant doesn't change. class Foo { static foo() { return this.#foo() } static #foo() { return Foo } } Foo = class Bar {} becomes: var _foo, foo_fn; const Foo2 = class { static foo() { return __privateMethod(this, _foo, foo_fn).call(this); } }; let Foo = Foo2; _foo = new WeakSet(); foo_fn = function() { return Foo2; }; _foo.add(Foo); Foo = class Bar { }; Generate a new symbol instead of using the shadowing name directly because the shadowing name isn't a top-level symbol and we are now making a top-level symbol. This symbol must be minified along with other top-level symbols to avoid name collisions.
			 := .newSymbol(js_ast.SymbolOther, .symbols[.InnerIndex].OriginalName)
			.currentScope.Generated = append(.currentScope.Generated, )
			.recordDeclaredSymbol()
			.mergeSymbols(, )
			 = append(, js_ast.Stmt{Loc: , Data: &js_ast.SLocal{
				Kind: .selectLocalKind(js_ast.LocalConst),
				Decls: []js_ast.Decl{{
					Binding: js_ast.Binding{Loc: .Loc, Data: &js_ast.BIdentifier{Ref: }},
					Value:   ,
				}},
			}})
			 = &js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}
			.recordUsage()
If there are class decorators, then we actually need to mutate the immutable "const" binding that shadows everything in the class body. The official TypeScript compiler does this by rewriting all class name references in the class body to another temporary variable. This is basically what we're doing here.
			if  != js_ast.InvalidRef {
				.mergeSymbols(, )
			}
		}
Generate the variable statement that will represent the class statement
		 = append(, js_ast.Stmt{Loc: , Data: &js_ast.SLocal{
			Kind:     .selectLocalKind(js_ast.LocalLet),
			IsExport:  == ,
			Decls: []js_ast.Decl{{
				Binding: js_ast.Binding{Loc: .Loc, Data: &js_ast.BIdentifier{Ref: }},
				Value:   ,
			}},
		}})
	} else {
		switch  {
		case :
			 = append(, js_ast.Stmt{Loc: , Data: &js_ast.SClass{Class: *}})
		case :
			 = append(, js_ast.Stmt{Loc: , Data: &js_ast.SClass{Class: *, IsExport: true}})
		case :
			 = append(, js_ast.Stmt{Loc: , Data: &js_ast.SExportDefault{
				DefaultName: ,
				Value:       js_ast.ExprOrStmt{Stmt: &js_ast.Stmt{Loc: , Data: &js_ast.SClass{Class: *}}},
			}})
		}
The shadowing name inside the class statement should be the same as the class statement name itself
		if .Name != nil &&  != js_ast.InvalidRef {
			.mergeSymbols(, .Name.Ref)
		}
	}
The official TypeScript compiler adds generated code after the class body in this exact order. Matching this order is important for correctness.
	if .Data != nil {
		 = append(, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: }})
	}
	for ,  := range  {
		 = append(, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: }})
	}
	for ,  := range  {
		 = append(, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: }})
	}
	for ,  := range  {
		 = append(, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: }})
	}
	for ,  := range  {
		 = append(, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: }})
	}
	for ,  := range  {
		 = append(, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: }})
	}
	if len(.TSDecorators) > 0 {
		 = append(, js_ast.AssignStmt(
			js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .Ref}},
			.callRuntime(, "__decorate", []js_ast.Expr{
				{Loc: , Data: &js_ast.EArray{Items: .TSDecorators}},
				{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .Ref}},
			}),
		))
		.recordUsage(.Ref)
		.recordUsage(.Ref)
	}
	if  {
Generate a new default name symbol since the current one is being used by the class. If this SExportDefault turns into a variable declaration, we don't want it to accidentally use the same variable as the class and cause a name collision.
			 := .generateTempRef(tempRefNoDeclare, .source.IdentifierName+"_default")
			.recordDeclaredSymbol()

			 := ()
			 = append(, js_ast.Stmt{Loc: , Data: &js_ast.SExportDefault{
				DefaultName: js_ast.LocRef{Loc: .Loc, Ref: },
				Value:       js_ast.ExprOrStmt{Expr: &},
			}})
		}
Calling "nameFunc" will set the class name, but we don't want it to have one. If the class name was necessary, we would have already split it off into a "const" symbol above. Reset it back to empty here now that we know we won't call "nameFunc" after this point.
		.Name = nil
	}
	if .Data != nil {
		 = append(, )
	}
	return , js_ast.Expr{}
}

func ( *parser) ( js_ast.Expr) bool {
	if .fnOrArrowDataVisit.isAsync && .options.unsupportedJSFeatures.Has(compat.AsyncAwait) {
		,  := .Data.(*js_ast.ESuper)
		return 
	}
	return false
}

func ( *parser) ( logger.Loc,  js_ast.Expr) js_ast.Expr {
	if .fnOrArrowDataVisit.superIndexRef == nil {
		 := .newSymbol(js_ast.SymbolOther, "__super")
		.fnOrArrowDataVisit.superIndexRef = &
	}
	.recordUsage(*.fnOrArrowDataVisit.superIndexRef)
	return js_ast.Expr{Loc: , Data: &js_ast.ECall{
		Target: js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: *.fnOrArrowDataVisit.superIndexRef}},
		Args:   []js_ast.Expr{},
	}}
}

func ( *parser) ( *js_ast.ECall) {
	var  js_ast.Expr

	switch e := .Target.Data.(type) {
Lower "super.prop" if necessary
Lower "super[prop]" if necessary
		if !.shouldLowerSuperPropertyAccess(.Target) {
			return
		}
		 = .Index

	default:
		return
	}
"super.foo(a, b)" => "__superIndex('foo').call(this, a, b)"
	.Target.Data = &js_ast.EDot{
		Target:  .lowerSuperPropertyAccess(.Target.Loc, ),
		NameLoc: .Loc,
		Name:    "call",
	}
	 := js_ast.Expr{Loc: .Target.Loc, Data: &js_ast.EThis{}}
	.Args = append([]js_ast.Expr{}, .Args...)
}

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