github.com/evanw/esbuild@v0.21.4/internal/js_ast/js_ast.go (about)

     1  package js_ast
     2  
     3  import (
     4  	"strconv"
     5  
     6  	"github.com/evanw/esbuild/internal/ast"
     7  	"github.com/evanw/esbuild/internal/logger"
     8  )
     9  
    10  // Every module (i.e. file) is parsed into a separate AST data structure. For
    11  // efficiency, the parser also resolves all scopes and binds all symbols in the
    12  // tree.
    13  //
    14  // Identifiers in the tree are referenced by a Ref, which is a pointer into the
    15  // symbol table for the file. The symbol table is stored as a top-level field
    16  // in the AST so it can be accessed without traversing the tree. For example,
    17  // a renaming pass can iterate over the symbol table without touching the tree.
    18  //
    19  // Parse trees are intended to be immutable. That makes it easy to build an
    20  // incremental compiler with a "watch" mode that can avoid re-parsing files
    21  // that have already been parsed. Any passes that operate on an AST after it
    22  // has been parsed should create a copy of the mutated parts of the tree
    23  // instead of mutating the original tree.
    24  
    25  type L uint8
    26  
    27  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
    28  const (
    29  	LLowest L = iota
    30  	LComma
    31  	LSpread
    32  	LYield
    33  	LAssign
    34  	LConditional
    35  	LNullishCoalescing
    36  	LLogicalOr
    37  	LLogicalAnd
    38  	LBitwiseOr
    39  	LBitwiseXor
    40  	LBitwiseAnd
    41  	LEquals
    42  	LCompare
    43  	LShift
    44  	LAdd
    45  	LMultiply
    46  	LExponentiation
    47  	LPrefix
    48  	LPostfix
    49  	LNew
    50  	LCall
    51  	LMember
    52  )
    53  
    54  type OpCode uint8
    55  
    56  func (op OpCode) IsPrefix() bool {
    57  	return op < UnOpPostDec
    58  }
    59  
    60  func (op OpCode) UnaryAssignTarget() AssignTarget {
    61  	if op >= UnOpPreDec && op <= UnOpPostInc {
    62  		return AssignTargetUpdate
    63  	}
    64  	return AssignTargetNone
    65  }
    66  
    67  func (op OpCode) IsLeftAssociative() bool {
    68  	return op >= BinOpAdd && op < BinOpComma && op != BinOpPow
    69  }
    70  
    71  func (op OpCode) IsRightAssociative() bool {
    72  	return op >= BinOpAssign || op == BinOpPow
    73  }
    74  
    75  func (op OpCode) BinaryAssignTarget() AssignTarget {
    76  	if op == BinOpAssign {
    77  		return AssignTargetReplace
    78  	}
    79  	if op > BinOpAssign {
    80  		return AssignTargetUpdate
    81  	}
    82  	return AssignTargetNone
    83  }
    84  
    85  func (op OpCode) IsShortCircuit() bool {
    86  	switch op {
    87  	case BinOpLogicalOr, BinOpLogicalOrAssign,
    88  		BinOpLogicalAnd, BinOpLogicalAndAssign,
    89  		BinOpNullishCoalescing, BinOpNullishCoalescingAssign:
    90  		return true
    91  	}
    92  	return false
    93  }
    94  
    95  type AssignTarget uint8
    96  
    97  const (
    98  	AssignTargetNone    AssignTarget = iota
    99  	AssignTargetReplace              // "a = b"
   100  	AssignTargetUpdate               // "a += b"
   101  )
   102  
   103  // If you add a new token, remember to add it to "OpTable" too
   104  const (
   105  	// Prefix
   106  	UnOpPos OpCode = iota
   107  	UnOpNeg
   108  	UnOpCpl
   109  	UnOpNot
   110  	UnOpVoid
   111  	UnOpTypeof
   112  	UnOpDelete
   113  
   114  	// Prefix update
   115  	UnOpPreDec
   116  	UnOpPreInc
   117  
   118  	// Postfix update
   119  	UnOpPostDec
   120  	UnOpPostInc
   121  
   122  	// Left-associative
   123  	BinOpAdd
   124  	BinOpSub
   125  	BinOpMul
   126  	BinOpDiv
   127  	BinOpRem
   128  	BinOpPow
   129  	BinOpLt
   130  	BinOpLe
   131  	BinOpGt
   132  	BinOpGe
   133  	BinOpIn
   134  	BinOpInstanceof
   135  	BinOpShl
   136  	BinOpShr
   137  	BinOpUShr
   138  	BinOpLooseEq
   139  	BinOpLooseNe
   140  	BinOpStrictEq
   141  	BinOpStrictNe
   142  	BinOpNullishCoalescing
   143  	BinOpLogicalOr
   144  	BinOpLogicalAnd
   145  	BinOpBitwiseOr
   146  	BinOpBitwiseAnd
   147  	BinOpBitwiseXor
   148  
   149  	// Non-associative
   150  	BinOpComma
   151  
   152  	// Right-associative
   153  	BinOpAssign
   154  	BinOpAddAssign
   155  	BinOpSubAssign
   156  	BinOpMulAssign
   157  	BinOpDivAssign
   158  	BinOpRemAssign
   159  	BinOpPowAssign
   160  	BinOpShlAssign
   161  	BinOpShrAssign
   162  	BinOpUShrAssign
   163  	BinOpBitwiseOrAssign
   164  	BinOpBitwiseAndAssign
   165  	BinOpBitwiseXorAssign
   166  	BinOpNullishCoalescingAssign
   167  	BinOpLogicalOrAssign
   168  	BinOpLogicalAndAssign
   169  )
   170  
   171  type OpTableEntry struct {
   172  	Text      string
   173  	Level     L
   174  	IsKeyword bool
   175  }
   176  
   177  var OpTable = []OpTableEntry{
   178  	// Prefix
   179  	{"+", LPrefix, false},
   180  	{"-", LPrefix, false},
   181  	{"~", LPrefix, false},
   182  	{"!", LPrefix, false},
   183  	{"void", LPrefix, true},
   184  	{"typeof", LPrefix, true},
   185  	{"delete", LPrefix, true},
   186  
   187  	// Prefix update
   188  	{"--", LPrefix, false},
   189  	{"++", LPrefix, false},
   190  
   191  	// Postfix update
   192  	{"--", LPostfix, false},
   193  	{"++", LPostfix, false},
   194  
   195  	// Left-associative
   196  	{"+", LAdd, false},
   197  	{"-", LAdd, false},
   198  	{"*", LMultiply, false},
   199  	{"/", LMultiply, false},
   200  	{"%", LMultiply, false},
   201  	{"**", LExponentiation, false}, // Right-associative
   202  	{"<", LCompare, false},
   203  	{"<=", LCompare, false},
   204  	{">", LCompare, false},
   205  	{">=", LCompare, false},
   206  	{"in", LCompare, true},
   207  	{"instanceof", LCompare, true},
   208  	{"<<", LShift, false},
   209  	{">>", LShift, false},
   210  	{">>>", LShift, false},
   211  	{"==", LEquals, false},
   212  	{"!=", LEquals, false},
   213  	{"===", LEquals, false},
   214  	{"!==", LEquals, false},
   215  	{"??", LNullishCoalescing, false},
   216  	{"||", LLogicalOr, false},
   217  	{"&&", LLogicalAnd, false},
   218  	{"|", LBitwiseOr, false},
   219  	{"&", LBitwiseAnd, false},
   220  	{"^", LBitwiseXor, false},
   221  
   222  	// Non-associative
   223  	{",", LComma, false},
   224  
   225  	// Right-associative
   226  	{"=", LAssign, false},
   227  	{"+=", LAssign, false},
   228  	{"-=", LAssign, false},
   229  	{"*=", LAssign, false},
   230  	{"/=", LAssign, false},
   231  	{"%=", LAssign, false},
   232  	{"**=", LAssign, false},
   233  	{"<<=", LAssign, false},
   234  	{">>=", LAssign, false},
   235  	{">>>=", LAssign, false},
   236  	{"|=", LAssign, false},
   237  	{"&=", LAssign, false},
   238  	{"^=", LAssign, false},
   239  	{"??=", LAssign, false},
   240  	{"||=", LAssign, false},
   241  	{"&&=", LAssign, false},
   242  }
   243  
   244  type Decorator struct {
   245  	Value            Expr
   246  	AtLoc            logger.Loc
   247  	OmitNewlineAfter bool
   248  }
   249  
   250  type PropertyKind uint8
   251  
   252  const (
   253  	PropertyField PropertyKind = iota
   254  	PropertyMethod
   255  	PropertyGetter
   256  	PropertySetter
   257  	PropertyAutoAccessor
   258  	PropertySpread
   259  	PropertyDeclareOrAbstract
   260  	PropertyClassStaticBlock
   261  )
   262  
   263  // This returns true if and only if this property matches the "MethodDefinition"
   264  // grammar from the specification. That means it's one of the following forms:
   265  //
   266  //	foo() {}
   267  //	*foo() {}
   268  //	async foo() {}
   269  //	async *foo() {}
   270  //	get foo() {}
   271  //	set foo(_) {}
   272  //
   273  // If this returns true, the "ValueOrNil" field of the property is always an
   274  // "EFunction" expression and it is always printed as a method.
   275  func (kind PropertyKind) IsMethodDefinition() bool {
   276  	return kind == PropertyMethod || kind == PropertyGetter || kind == PropertySetter
   277  }
   278  
   279  type ClassStaticBlock struct {
   280  	Block SBlock
   281  	Loc   logger.Loc
   282  }
   283  
   284  type PropertyFlags uint8
   285  
   286  const (
   287  	PropertyIsComputed PropertyFlags = 1 << iota
   288  	PropertyIsStatic
   289  	PropertyWasShorthand
   290  	PropertyPreferQuotedKey
   291  )
   292  
   293  func (flags PropertyFlags) Has(flag PropertyFlags) bool {
   294  	return (flags & flag) != 0
   295  }
   296  
   297  type Property struct {
   298  	ClassStaticBlock *ClassStaticBlock
   299  
   300  	Key Expr
   301  
   302  	// This is omitted for class fields
   303  	ValueOrNil Expr
   304  
   305  	// This is used when parsing a pattern that uses default values:
   306  	//
   307  	//   [a = 1] = [];
   308  	//   ({a = 1} = {});
   309  	//
   310  	// It's also used for class fields:
   311  	//
   312  	//   class Foo { a = 1 }
   313  	//
   314  	InitializerOrNil Expr
   315  
   316  	Decorators []Decorator
   317  
   318  	Loc             logger.Loc
   319  	CloseBracketLoc logger.Loc
   320  	Kind            PropertyKind
   321  	Flags           PropertyFlags
   322  }
   323  
   324  type PropertyBinding struct {
   325  	Key               Expr
   326  	Value             Binding
   327  	DefaultValueOrNil Expr
   328  	Loc               logger.Loc
   329  	CloseBracketLoc   logger.Loc
   330  	IsComputed        bool
   331  	IsSpread          bool
   332  	PreferQuotedKey   bool
   333  }
   334  
   335  type Arg struct {
   336  	Binding      Binding
   337  	DefaultOrNil Expr
   338  	Decorators   []Decorator
   339  
   340  	// "constructor(public x: boolean) {}"
   341  	IsTypeScriptCtorField bool
   342  }
   343  
   344  type Fn struct {
   345  	Name         *ast.LocRef
   346  	Args         []Arg
   347  	Body         FnBody
   348  	ArgumentsRef ast.Ref
   349  	OpenParenLoc logger.Loc
   350  
   351  	IsAsync     bool
   352  	IsGenerator bool
   353  	HasRestArg  bool
   354  	HasIfScope  bool
   355  
   356  	// See: https://github.com/rollup/rollup/pull/5024
   357  	HasNoSideEffectsComment bool
   358  
   359  	// This is true if the function is a method
   360  	IsUniqueFormalParameters bool
   361  }
   362  
   363  type FnBody struct {
   364  	Block SBlock
   365  	Loc   logger.Loc
   366  }
   367  
   368  type Class struct {
   369  	Decorators    []Decorator
   370  	Name          *ast.LocRef
   371  	ExtendsOrNil  Expr
   372  	Properties    []Property
   373  	ClassKeyword  logger.Range
   374  	BodyLoc       logger.Loc
   375  	CloseBraceLoc logger.Loc
   376  
   377  	// If true, property field initializers cannot be assumed to have no side
   378  	// effects. For example:
   379  	//
   380  	//   class Foo {
   381  	//     static set foo(x) { importantSideEffect(x) }
   382  	//   }
   383  	//   class Bar extends Foo {
   384  	//     foo = 1
   385  	//   }
   386  	//
   387  	// This happens in TypeScript when "useDefineForClassFields" is disabled
   388  	// because TypeScript (and esbuild) transforms the above class into this:
   389  	//
   390  	//   class Foo {
   391  	//     static set foo(x) { importantSideEffect(x); }
   392  	//   }
   393  	//   class Bar extends Foo {
   394  	//   }
   395  	//   Bar.foo = 1;
   396  	//
   397  	UseDefineForClassFields bool
   398  }
   399  
   400  type ArrayBinding struct {
   401  	Binding           Binding
   402  	DefaultValueOrNil Expr
   403  	Loc               logger.Loc
   404  }
   405  
   406  type Binding struct {
   407  	Data B
   408  	Loc  logger.Loc
   409  }
   410  
   411  // This interface is never called. Its purpose is to encode a variant type in
   412  // Go's type system.
   413  type B interface{ isBinding() }
   414  
   415  func (*BMissing) isBinding()    {}
   416  func (*BIdentifier) isBinding() {}
   417  func (*BArray) isBinding()      {}
   418  func (*BObject) isBinding()     {}
   419  
   420  type BMissing struct{}
   421  
   422  type BIdentifier struct{ Ref ast.Ref }
   423  
   424  type BArray struct {
   425  	Items           []ArrayBinding
   426  	CloseBracketLoc logger.Loc
   427  	HasSpread       bool
   428  	IsSingleLine    bool
   429  }
   430  
   431  type BObject struct {
   432  	Properties    []PropertyBinding
   433  	CloseBraceLoc logger.Loc
   434  	IsSingleLine  bool
   435  }
   436  
   437  type Expr struct {
   438  	Data E
   439  	Loc  logger.Loc
   440  }
   441  
   442  // This interface is never called. Its purpose is to encode a variant type in
   443  // Go's type system.
   444  type E interface{ isExpr() }
   445  
   446  func (*EArray) isExpr()                {}
   447  func (*EUnary) isExpr()                {}
   448  func (*EBinary) isExpr()               {}
   449  func (*EBoolean) isExpr()              {}
   450  func (*ESuper) isExpr()                {}
   451  func (*ENull) isExpr()                 {}
   452  func (*EUndefined) isExpr()            {}
   453  func (*EThis) isExpr()                 {}
   454  func (*ENew) isExpr()                  {}
   455  func (*ENewTarget) isExpr()            {}
   456  func (*EImportMeta) isExpr()           {}
   457  func (*ECall) isExpr()                 {}
   458  func (*EDot) isExpr()                  {}
   459  func (*EIndex) isExpr()                {}
   460  func (*EArrow) isExpr()                {}
   461  func (*EFunction) isExpr()             {}
   462  func (*EClass) isExpr()                {}
   463  func (*EIdentifier) isExpr()           {}
   464  func (*EImportIdentifier) isExpr()     {}
   465  func (*EPrivateIdentifier) isExpr()    {}
   466  func (*ENameOfSymbol) isExpr()         {}
   467  func (*EJSXElement) isExpr()           {}
   468  func (*EJSXText) isExpr()              {}
   469  func (*EMissing) isExpr()              {}
   470  func (*ENumber) isExpr()               {}
   471  func (*EBigInt) isExpr()               {}
   472  func (*EObject) isExpr()               {}
   473  func (*ESpread) isExpr()               {}
   474  func (*EString) isExpr()               {}
   475  func (*ETemplate) isExpr()             {}
   476  func (*ERegExp) isExpr()               {}
   477  func (*EInlinedEnum) isExpr()          {}
   478  func (*EAnnotation) isExpr()           {}
   479  func (*EAwait) isExpr()                {}
   480  func (*EYield) isExpr()                {}
   481  func (*EIf) isExpr()                   {}
   482  func (*ERequireString) isExpr()        {}
   483  func (*ERequireResolveString) isExpr() {}
   484  func (*EImportString) isExpr()         {}
   485  func (*EImportCall) isExpr()           {}
   486  
   487  type EArray struct {
   488  	Items            []Expr
   489  	CommaAfterSpread logger.Loc
   490  	CloseBracketLoc  logger.Loc
   491  	IsSingleLine     bool
   492  	IsParenthesized  bool
   493  }
   494  
   495  type EUnary struct {
   496  	Value Expr
   497  	Op    OpCode
   498  
   499  	// The expression "typeof (0, x)" must not become "typeof x" if "x"
   500  	// is unbound because that could suppress a ReferenceError from "x".
   501  	//
   502  	// Also if we know a typeof operator was originally an identifier, then
   503  	// we know that this typeof operator always has no side effects (even if
   504  	// we consider the identifier by itself to have a side effect).
   505  	//
   506  	// Note that there *is* actually a case where "typeof x" can throw an error:
   507  	// when "x" is being referenced inside of its TDZ (temporal dead zone). TDZ
   508  	// checks are not yet handled correctly by esbuild, so this possibility is
   509  	// currently ignored.
   510  	WasOriginallyTypeofIdentifier bool
   511  
   512  	// Similarly the expression "delete (0, x)" must not become "delete x"
   513  	// because that syntax is invalid in strict mode. We also need to make sure
   514  	// we don't accidentally change the return value:
   515  	//
   516  	//   Returns false:
   517  	//     "var a; delete (a)"
   518  	//     "var a = Object.freeze({b: 1}); delete (a.b)"
   519  	//     "var a = Object.freeze({b: 1}); delete (a?.b)"
   520  	//     "var a = Object.freeze({b: 1}); delete (a['b'])"
   521  	//     "var a = Object.freeze({b: 1}); delete (a?.['b'])"
   522  	//
   523  	//   Returns true:
   524  	//     "var a; delete (0, a)"
   525  	//     "var a = Object.freeze({b: 1}); delete (true && a.b)"
   526  	//     "var a = Object.freeze({b: 1}); delete (false || a?.b)"
   527  	//     "var a = Object.freeze({b: 1}); delete (null ?? a?.['b'])"
   528  	//     "var a = Object.freeze({b: 1}); delete (true ? a['b'] : a['b'])"
   529  	//
   530  	WasOriginallyDeleteOfIdentifierOrPropertyAccess bool
   531  }
   532  
   533  type EBinary struct {
   534  	Left  Expr
   535  	Right Expr
   536  	Op    OpCode
   537  }
   538  
   539  type EBoolean struct{ Value bool }
   540  
   541  type EMissing struct{}
   542  
   543  type ESuper struct{}
   544  
   545  type ENull struct{}
   546  
   547  type EUndefined struct{}
   548  
   549  type EThis struct{}
   550  
   551  type ENewTarget struct {
   552  	Range logger.Range
   553  }
   554  
   555  type EImportMeta struct {
   556  	RangeLen int32
   557  }
   558  
   559  // These help reduce unnecessary memory allocations
   560  var BMissingShared = &BMissing{}
   561  var EMissingShared = &EMissing{}
   562  var ENullShared = &ENull{}
   563  var ESuperShared = &ESuper{}
   564  var EThisShared = &EThis{}
   565  var EUndefinedShared = &EUndefined{}
   566  var SDebuggerShared = &SDebugger{}
   567  var SEmptyShared = &SEmpty{}
   568  var STypeScriptShared = &STypeScript{}
   569  var STypeScriptSharedWasDeclareClass = &STypeScript{WasDeclareClass: true}
   570  
   571  type ENew struct {
   572  	Target Expr
   573  	Args   []Expr
   574  
   575  	CloseParenLoc logger.Loc
   576  	IsMultiLine   bool
   577  
   578  	// True if there is a comment containing "@__PURE__" or "#__PURE__" preceding
   579  	// this call expression. See the comment inside ECall for more details.
   580  	CanBeUnwrappedIfUnused bool
   581  }
   582  
   583  type CallKind uint8
   584  
   585  const (
   586  	NormalCall CallKind = iota
   587  	DirectEval
   588  	TargetWasOriginallyPropertyAccess
   589  )
   590  
   591  type OptionalChain uint8
   592  
   593  const (
   594  	// "a.b"
   595  	OptionalChainNone OptionalChain = iota
   596  
   597  	// "a?.b"
   598  	OptionalChainStart
   599  
   600  	// "a?.b.c" => ".c" is OptionalChainContinue
   601  	// "(a?.b).c" => ".c" is OptionalChainNone
   602  	OptionalChainContinue
   603  )
   604  
   605  type ECall struct {
   606  	Target        Expr
   607  	Args          []Expr
   608  	CloseParenLoc logger.Loc
   609  	OptionalChain OptionalChain
   610  	Kind          CallKind
   611  	IsMultiLine   bool
   612  
   613  	// True if there is a comment containing "@__PURE__" or "#__PURE__" preceding
   614  	// this call expression. This is an annotation used for tree shaking, and
   615  	// means that the call can be removed if it's unused. It does not mean the
   616  	// call is pure (e.g. it may still return something different if called twice).
   617  	//
   618  	// Note that the arguments are not considered to be part of the call. If the
   619  	// call itself is removed due to this annotation, the arguments must remain
   620  	// if they have side effects.
   621  	CanBeUnwrappedIfUnused bool
   622  }
   623  
   624  func (a *ECall) HasSameFlagsAs(b *ECall) bool {
   625  	return a.OptionalChain == b.OptionalChain &&
   626  		a.Kind == b.Kind &&
   627  		a.CanBeUnwrappedIfUnused == b.CanBeUnwrappedIfUnused
   628  }
   629  
   630  type EDot struct {
   631  	Target        Expr
   632  	Name          string
   633  	NameLoc       logger.Loc
   634  	OptionalChain OptionalChain
   635  
   636  	// If true, this property access is known to be free of side-effects. That
   637  	// means it can be removed if the resulting value isn't used.
   638  	CanBeRemovedIfUnused bool
   639  
   640  	// If true, this property access is a function that, when called, can be
   641  	// unwrapped if the resulting value is unused. Unwrapping means discarding
   642  	// the call target but keeping any arguments with side effects.
   643  	CallCanBeUnwrappedIfUnused bool
   644  
   645  	// Symbol values are known to not have side effects when used as property
   646  	// names in class declarations and object literals.
   647  	IsSymbolInstance bool
   648  }
   649  
   650  func (a *EDot) HasSameFlagsAs(b *EDot) bool {
   651  	return a.OptionalChain == b.OptionalChain &&
   652  		a.CanBeRemovedIfUnused == b.CanBeRemovedIfUnused &&
   653  		a.CallCanBeUnwrappedIfUnused == b.CallCanBeUnwrappedIfUnused &&
   654  		a.IsSymbolInstance == b.IsSymbolInstance
   655  }
   656  
   657  type EIndex struct {
   658  	Target          Expr
   659  	Index           Expr
   660  	CloseBracketLoc logger.Loc
   661  	OptionalChain   OptionalChain
   662  
   663  	// If true, this property access is known to be free of side-effects. That
   664  	// means it can be removed if the resulting value isn't used.
   665  	CanBeRemovedIfUnused bool
   666  
   667  	// If true, this property access is a function that, when called, can be
   668  	// unwrapped if the resulting value is unused. Unwrapping means discarding
   669  	// the call target but keeping any arguments with side effects.
   670  	CallCanBeUnwrappedIfUnused bool
   671  
   672  	// Symbol values are known to not have side effects when used as property
   673  	// names in class declarations and object literals.
   674  	IsSymbolInstance bool
   675  }
   676  
   677  func (a *EIndex) HasSameFlagsAs(b *EIndex) bool {
   678  	return a.OptionalChain == b.OptionalChain &&
   679  		a.CanBeRemovedIfUnused == b.CanBeRemovedIfUnused &&
   680  		a.CallCanBeUnwrappedIfUnused == b.CallCanBeUnwrappedIfUnused &&
   681  		a.IsSymbolInstance == b.IsSymbolInstance
   682  }
   683  
   684  type EArrow struct {
   685  	Args []Arg
   686  	Body FnBody
   687  
   688  	IsAsync    bool
   689  	HasRestArg bool
   690  	PreferExpr bool // Use shorthand if true and "Body" is a single return statement
   691  
   692  	// See: https://github.com/rollup/rollup/pull/5024
   693  	HasNoSideEffectsComment bool
   694  }
   695  
   696  type EFunction struct{ Fn Fn }
   697  
   698  type EClass struct{ Class Class }
   699  
   700  type EIdentifier struct {
   701  	Ref ast.Ref
   702  
   703  	// If we're inside a "with" statement, this identifier may be a property
   704  	// access. In that case it would be incorrect to remove this identifier since
   705  	// the property access may be a getter or setter with side effects.
   706  	MustKeepDueToWithStmt bool
   707  
   708  	// If true, this identifier is known to not have a side effect (i.e. to not
   709  	// throw an exception) when referenced. If false, this identifier may or may
   710  	// not have side effects when referenced. This is used to allow the removal
   711  	// of known globals such as "Object" if they aren't used.
   712  	CanBeRemovedIfUnused bool
   713  
   714  	// If true, this identifier represents a function that, when called, can be
   715  	// unwrapped if the resulting value is unused. Unwrapping means discarding
   716  	// the call target but keeping any arguments with side effects.
   717  	CallCanBeUnwrappedIfUnused bool
   718  }
   719  
   720  // This is similar to an EIdentifier but it represents a reference to an ES6
   721  // import item.
   722  //
   723  // Depending on how the code is linked, the file containing this EImportIdentifier
   724  // may or may not be in the same module group as the file it was imported from.
   725  //
   726  // If it's the same module group than we can just merge the import item symbol
   727  // with the corresponding symbol that was imported, effectively renaming them
   728  // to be the same thing and statically binding them together.
   729  //
   730  // But if it's a different module group, then the import must be dynamically
   731  // evaluated using a property access off the corresponding namespace symbol,
   732  // which represents the result of a require() call.
   733  //
   734  // It's stored as a separate type so it's not easy to confuse with a plain
   735  // identifier. For example, it'd be bad if code trying to convert "{x: x}" into
   736  // "{x}" shorthand syntax wasn't aware that the "x" in this case is actually
   737  // "{x: importedNamespace.x}". This separate type forces code to opt-in to
   738  // doing this instead of opt-out.
   739  type EImportIdentifier struct {
   740  	Ref             ast.Ref
   741  	PreferQuotedKey bool
   742  
   743  	// If true, this was originally an identifier expression such as "foo". If
   744  	// false, this could potentially have been a member access expression such
   745  	// as "ns.foo" off of an imported namespace object.
   746  	WasOriginallyIdentifier bool
   747  }
   748  
   749  // This is similar to EIdentifier but it represents class-private fields and
   750  // methods. It can be used where computed properties can be used, such as
   751  // EIndex and Property.
   752  type EPrivateIdentifier struct {
   753  	Ref ast.Ref
   754  }
   755  
   756  // This represents an internal property name that can be mangled. The symbol
   757  // referenced by this expression should be a "SymbolMangledProp" symbol.
   758  type ENameOfSymbol struct {
   759  	Ref                   ast.Ref
   760  	HasPropertyKeyComment bool // If true, a preceding comment contains "@__KEY__"
   761  }
   762  
   763  type EJSXElement struct {
   764  	TagOrNil   Expr
   765  	Properties []Property
   766  
   767  	// Note: This array may contain nil entries. Be careful about nil entries
   768  	// when iterating over this array.
   769  	//
   770  	// Each nil entry corresponds to the "JSXChildExpression_opt" part of the
   771  	// grammar (https://facebook.github.io/jsx/#prod-JSXChild):
   772  	//
   773  	//   JSXChild :
   774  	//       JSXText
   775  	//       JSXElement
   776  	//       JSXFragment
   777  	//       { JSXChildExpression_opt }
   778  	//
   779  	// This is the "{}" part in "<a>{}</a>". We allow this because some people
   780  	// put comments there and then expect to be able to process them from
   781  	// esbuild's output. These absent AST nodes are completely omitted when
   782  	// JSX is transformed to JS. They are only present when JSX preservation is
   783  	// enabled.
   784  	NullableChildren []Expr
   785  
   786  	CloseLoc        logger.Loc
   787  	IsTagSingleLine bool
   788  }
   789  
   790  // The JSX specification doesn't say how JSX text is supposed to be interpreted
   791  // so our "preserve" JSX transform should reproduce the original source code
   792  // verbatim. One reason why this matters is because there is no canonical way
   793  // to interpret JSX text (Babel and TypeScript differ in what newlines mean).
   794  // Another reason is that some people want to do custom things such as this:
   795  // https://github.com/evanw/esbuild/issues/3605
   796  type EJSXText struct {
   797  	Raw string
   798  }
   799  
   800  type ENumber struct{ Value float64 }
   801  
   802  type EBigInt struct{ Value string }
   803  
   804  type EObject struct {
   805  	Properties       []Property
   806  	CommaAfterSpread logger.Loc
   807  	CloseBraceLoc    logger.Loc
   808  	IsSingleLine     bool
   809  	IsParenthesized  bool
   810  }
   811  
   812  type ESpread struct{ Value Expr }
   813  
   814  // This is used for both strings and no-substitution template literals to reduce
   815  // the number of cases that need to be checked for string optimization code
   816  type EString struct {
   817  	Value                 []uint16
   818  	LegacyOctalLoc        logger.Loc
   819  	PreferTemplate        bool
   820  	HasPropertyKeyComment bool // If true, a preceding comment contains "@__KEY__"
   821  	ContainsUniqueKey     bool // If true, this string must not be wrapped
   822  }
   823  
   824  type TemplatePart struct {
   825  	Value      Expr
   826  	TailRaw    string   // Only use when "TagOrNil" is not nil
   827  	TailCooked []uint16 // Only use when "TagOrNil" is nil
   828  	TailLoc    logger.Loc
   829  }
   830  
   831  type ETemplate struct {
   832  	TagOrNil       Expr
   833  	HeadRaw        string   // Only use when "TagOrNil" is not nil
   834  	HeadCooked     []uint16 // Only use when "TagOrNil" is nil
   835  	Parts          []TemplatePart
   836  	HeadLoc        logger.Loc
   837  	LegacyOctalLoc logger.Loc
   838  
   839  	// True if this is a tagged template literal with a comment that indicates
   840  	// this function call can be removed if the result is unused. Note that the
   841  	// arguments are not considered to be part of the call. If the call itself
   842  	// is removed due to this annotation, the arguments must remain if they have
   843  	// side effects (including the string conversions).
   844  	CanBeUnwrappedIfUnused bool
   845  
   846  	// If the tag is present, it is expected to be a function and is called. If
   847  	// the tag is a syntactic property access, then the value for "this" in the
   848  	// function call is the object whose property was accessed (e.g. in "a.b``"
   849  	// the value for "this" in "a.b" is "a"). We need to ensure that if "a``"
   850  	// ever becomes "b.c``" later on due to optimizations, it is written as
   851  	// "(0, b.c)``" to avoid a behavior change.
   852  	TagWasOriginallyPropertyAccess bool
   853  }
   854  
   855  type ERegExp struct{ Value string }
   856  
   857  type EInlinedEnum struct {
   858  	Value   Expr
   859  	Comment string
   860  }
   861  
   862  type AnnotationFlags uint8
   863  
   864  const (
   865  	// This is sort of like an IIFE with a "/* @__PURE__ */" comment except it's an
   866  	// inline annotation on an expression itself without the nested scope. Sometimes
   867  	// we can't easily introduce a new scope (e.g. if the expression uses "await").
   868  	CanBeRemovedIfUnusedFlag AnnotationFlags = 1 << iota
   869  )
   870  
   871  func (flags AnnotationFlags) Has(flag AnnotationFlags) bool {
   872  	return (flags & flag) != 0
   873  }
   874  
   875  type EAnnotation struct {
   876  	Value Expr
   877  	Flags AnnotationFlags
   878  }
   879  
   880  type EAwait struct {
   881  	Value Expr
   882  }
   883  
   884  type EYield struct {
   885  	ValueOrNil Expr
   886  	IsStar     bool
   887  }
   888  
   889  type EIf struct {
   890  	Test Expr
   891  	Yes  Expr
   892  	No   Expr
   893  }
   894  
   895  type ERequireString struct {
   896  	ImportRecordIndex uint32
   897  	CloseParenLoc     logger.Loc
   898  }
   899  
   900  type ERequireResolveString struct {
   901  	ImportRecordIndex uint32
   902  	CloseParenLoc     logger.Loc
   903  }
   904  
   905  type EImportString struct {
   906  	ImportRecordIndex uint32
   907  	CloseParenLoc     logger.Loc
   908  }
   909  
   910  type EImportCall struct {
   911  	Expr          Expr
   912  	OptionsOrNil  Expr
   913  	CloseParenLoc logger.Loc
   914  }
   915  
   916  type Stmt struct {
   917  	Data S
   918  	Loc  logger.Loc
   919  }
   920  
   921  // This interface is never called. Its purpose is to encode a variant type in
   922  // Go's type system.
   923  type S interface{ isStmt() }
   924  
   925  func (*SBlock) isStmt()         {}
   926  func (*SComment) isStmt()       {}
   927  func (*SDebugger) isStmt()      {}
   928  func (*SDirective) isStmt()     {}
   929  func (*SEmpty) isStmt()         {}
   930  func (*STypeScript) isStmt()    {}
   931  func (*SExportClause) isStmt()  {}
   932  func (*SExportFrom) isStmt()    {}
   933  func (*SExportDefault) isStmt() {}
   934  func (*SExportStar) isStmt()    {}
   935  func (*SExportEquals) isStmt()  {}
   936  func (*SLazyExport) isStmt()    {}
   937  func (*SExpr) isStmt()          {}
   938  func (*SEnum) isStmt()          {}
   939  func (*SNamespace) isStmt()     {}
   940  func (*SFunction) isStmt()      {}
   941  func (*SClass) isStmt()         {}
   942  func (*SLabel) isStmt()         {}
   943  func (*SIf) isStmt()            {}
   944  func (*SFor) isStmt()           {}
   945  func (*SForIn) isStmt()         {}
   946  func (*SForOf) isStmt()         {}
   947  func (*SDoWhile) isStmt()       {}
   948  func (*SWhile) isStmt()         {}
   949  func (*SWith) isStmt()          {}
   950  func (*STry) isStmt()           {}
   951  func (*SSwitch) isStmt()        {}
   952  func (*SImport) isStmt()        {}
   953  func (*SReturn) isStmt()        {}
   954  func (*SThrow) isStmt()         {}
   955  func (*SLocal) isStmt()         {}
   956  func (*SBreak) isStmt()         {}
   957  func (*SContinue) isStmt()      {}
   958  
   959  type SBlock struct {
   960  	Stmts         []Stmt
   961  	CloseBraceLoc logger.Loc
   962  }
   963  
   964  type SEmpty struct{}
   965  
   966  // This is a stand-in for a TypeScript type declaration
   967  type STypeScript struct {
   968  	WasDeclareClass bool
   969  }
   970  
   971  type SComment struct {
   972  	Text           string
   973  	IsLegalComment bool
   974  }
   975  
   976  type SDebugger struct{}
   977  
   978  type SDirective struct {
   979  	Value          []uint16
   980  	LegacyOctalLoc logger.Loc
   981  }
   982  
   983  type SExportClause struct {
   984  	Items        []ClauseItem
   985  	IsSingleLine bool
   986  }
   987  
   988  type SExportFrom struct {
   989  	Items             []ClauseItem
   990  	NamespaceRef      ast.Ref
   991  	ImportRecordIndex uint32
   992  	IsSingleLine      bool
   993  }
   994  
   995  type SExportDefault struct {
   996  	Value       Stmt // May be a SExpr or SFunction or SClass
   997  	DefaultName ast.LocRef
   998  }
   999  
  1000  type ExportStarAlias struct {
  1001  	// Although this alias name starts off as being the same as the statement's
  1002  	// namespace symbol, it may diverge if the namespace symbol name is minified.
  1003  	// The original alias name is preserved here to avoid this scenario.
  1004  	OriginalName string
  1005  
  1006  	Loc logger.Loc
  1007  }
  1008  
  1009  type SExportStar struct {
  1010  	Alias             *ExportStarAlias
  1011  	NamespaceRef      ast.Ref
  1012  	ImportRecordIndex uint32
  1013  }
  1014  
  1015  // This is an "export = value;" statement in TypeScript
  1016  type SExportEquals struct {
  1017  	Value Expr
  1018  }
  1019  
  1020  // The decision of whether to export an expression using "module.exports" or
  1021  // "export default" is deferred until linking using this statement kind
  1022  type SLazyExport struct {
  1023  	Value Expr
  1024  }
  1025  
  1026  type SExpr struct {
  1027  	Value Expr
  1028  
  1029  	// This is set to true for automatically-generated expressions that are part
  1030  	// of class syntax lowering. A single class declaration may end up with many
  1031  	// generated expressions after it (e.g. class field initializations, a call
  1032  	// to keep the original value of the "name" property). When this happens we
  1033  	// can't tell that the class is side-effect free anymore because all of these
  1034  	// methods mutate the class. We use this annotation for that instead.
  1035  	IsFromClassOrFnThatCanBeRemovedIfUnused bool
  1036  }
  1037  
  1038  type EnumValue struct {
  1039  	ValueOrNil Expr
  1040  	Name       []uint16
  1041  	Ref        ast.Ref
  1042  	Loc        logger.Loc
  1043  }
  1044  
  1045  type SEnum struct {
  1046  	Values   []EnumValue
  1047  	Name     ast.LocRef
  1048  	Arg      ast.Ref
  1049  	IsExport bool
  1050  }
  1051  
  1052  type SNamespace struct {
  1053  	Stmts    []Stmt
  1054  	Name     ast.LocRef
  1055  	Arg      ast.Ref
  1056  	IsExport bool
  1057  }
  1058  
  1059  type SFunction struct {
  1060  	Fn       Fn
  1061  	IsExport bool
  1062  }
  1063  
  1064  type SClass struct {
  1065  	Class    Class
  1066  	IsExport bool
  1067  }
  1068  
  1069  type SLabel struct {
  1070  	Stmt             Stmt
  1071  	Name             ast.LocRef
  1072  	IsSingleLineStmt bool
  1073  }
  1074  
  1075  type SIf struct {
  1076  	Test            Expr
  1077  	Yes             Stmt
  1078  	NoOrNil         Stmt
  1079  	IsSingleLineYes bool
  1080  	IsSingleLineNo  bool
  1081  }
  1082  
  1083  type SFor struct {
  1084  	InitOrNil        Stmt // May be a SConst, SLet, SVar, or SExpr
  1085  	TestOrNil        Expr
  1086  	UpdateOrNil      Expr
  1087  	Body             Stmt
  1088  	IsSingleLineBody bool
  1089  }
  1090  
  1091  type SForIn struct {
  1092  	Init             Stmt // May be a SConst, SLet, SVar, or SExpr
  1093  	Value            Expr
  1094  	Body             Stmt
  1095  	IsSingleLineBody bool
  1096  }
  1097  
  1098  type SForOf struct {
  1099  	Init             Stmt // May be a SConst, SLet, SVar, or SExpr
  1100  	Value            Expr
  1101  	Body             Stmt
  1102  	Await            logger.Range
  1103  	IsSingleLineBody bool
  1104  }
  1105  
  1106  type SDoWhile struct {
  1107  	Body Stmt
  1108  	Test Expr
  1109  }
  1110  
  1111  type SWhile struct {
  1112  	Test             Expr
  1113  	Body             Stmt
  1114  	IsSingleLineBody bool
  1115  }
  1116  
  1117  type SWith struct {
  1118  	Value            Expr
  1119  	Body             Stmt
  1120  	BodyLoc          logger.Loc
  1121  	IsSingleLineBody bool
  1122  }
  1123  
  1124  type Catch struct {
  1125  	BindingOrNil Binding
  1126  	Block        SBlock
  1127  	Loc          logger.Loc
  1128  	BlockLoc     logger.Loc
  1129  }
  1130  
  1131  type Finally struct {
  1132  	Block SBlock
  1133  	Loc   logger.Loc
  1134  }
  1135  
  1136  type STry struct {
  1137  	Catch    *Catch
  1138  	Finally  *Finally
  1139  	Block    SBlock
  1140  	BlockLoc logger.Loc
  1141  }
  1142  
  1143  type Case struct {
  1144  	ValueOrNil Expr // If this is nil, this is "default" instead of "case"
  1145  	Body       []Stmt
  1146  	Loc        logger.Loc
  1147  }
  1148  
  1149  type SSwitch struct {
  1150  	Test          Expr
  1151  	Cases         []Case
  1152  	BodyLoc       logger.Loc
  1153  	CloseBraceLoc logger.Loc
  1154  }
  1155  
  1156  // This object represents all of these types of import statements:
  1157  //
  1158  //	import 'path'
  1159  //	import {item1, item2} from 'path'
  1160  //	import * as ns from 'path'
  1161  //	import defaultItem, {item1, item2} from 'path'
  1162  //	import defaultItem, * as ns from 'path'
  1163  //
  1164  // Many parts are optional and can be combined in different ways. The only
  1165  // restriction is that you cannot have both a clause and a star namespace.
  1166  type SImport struct {
  1167  	DefaultName *ast.LocRef
  1168  	Items       *[]ClauseItem
  1169  	StarNameLoc *logger.Loc
  1170  
  1171  	// If this is a star import: This is a Ref for the namespace symbol. The Loc
  1172  	// for the symbol is StarLoc.
  1173  	//
  1174  	// Otherwise: This is an auto-generated Ref for the namespace representing
  1175  	// the imported file. In this case StarLoc is nil. The NamespaceRef is used
  1176  	// when converting this module to a CommonJS module.
  1177  	NamespaceRef ast.Ref
  1178  
  1179  	ImportRecordIndex uint32
  1180  	IsSingleLine      bool
  1181  }
  1182  
  1183  type SReturn struct {
  1184  	ValueOrNil Expr
  1185  }
  1186  
  1187  type SThrow struct {
  1188  	Value Expr
  1189  }
  1190  
  1191  type LocalKind uint8
  1192  
  1193  const (
  1194  	LocalVar LocalKind = iota
  1195  	LocalLet
  1196  	LocalConst
  1197  	LocalUsing
  1198  	LocalAwaitUsing
  1199  )
  1200  
  1201  func (kind LocalKind) IsUsing() bool {
  1202  	return kind >= LocalUsing
  1203  }
  1204  
  1205  type SLocal struct {
  1206  	Decls    []Decl
  1207  	Kind     LocalKind
  1208  	IsExport bool
  1209  
  1210  	// The TypeScript compiler doesn't generate code for "import foo = bar"
  1211  	// statements where the import is never used.
  1212  	WasTSImportEquals bool
  1213  }
  1214  
  1215  type SBreak struct {
  1216  	Label *ast.LocRef
  1217  }
  1218  
  1219  type SContinue struct {
  1220  	Label *ast.LocRef
  1221  }
  1222  
  1223  type ClauseItem struct {
  1224  	Alias string
  1225  
  1226  	// This is the original name of the symbol stored in "Name". It's needed for
  1227  	// "SExportClause" statements such as this:
  1228  	//
  1229  	//   export {foo as bar} from 'path'
  1230  	//
  1231  	// In this case both "foo" and "bar" are aliases because it's a re-export.
  1232  	// We need to preserve both aliases in case the symbol is renamed. In this
  1233  	// example, "foo" is "OriginalName" and "bar" is "Alias".
  1234  	OriginalName string
  1235  
  1236  	AliasLoc logger.Loc
  1237  	Name     ast.LocRef
  1238  }
  1239  
  1240  type Decl struct {
  1241  	Binding    Binding
  1242  	ValueOrNil Expr
  1243  }
  1244  
  1245  type ScopeKind uint8
  1246  
  1247  const (
  1248  	ScopeBlock ScopeKind = iota
  1249  	ScopeWith
  1250  	ScopeLabel
  1251  	ScopeClassName
  1252  	ScopeClassBody
  1253  	ScopeCatchBinding
  1254  
  1255  	// The scopes below stop hoisted variables from extending into parent scopes
  1256  	ScopeEntry // This is a module, TypeScript enum, or TypeScript namespace
  1257  	ScopeFunctionArgs
  1258  	ScopeFunctionBody
  1259  	ScopeClassStaticInit
  1260  )
  1261  
  1262  func (kind ScopeKind) StopsHoisting() bool {
  1263  	return kind >= ScopeEntry
  1264  }
  1265  
  1266  type ScopeMember struct {
  1267  	Ref ast.Ref
  1268  	Loc logger.Loc
  1269  }
  1270  
  1271  type Scope struct {
  1272  	// This will be non-nil if this is a TypeScript "namespace" or "enum"
  1273  	TSNamespace *TSNamespaceScope
  1274  
  1275  	Parent    *Scope
  1276  	Children  []*Scope
  1277  	Members   map[string]ScopeMember
  1278  	Replaced  []ScopeMember
  1279  	Generated []ast.Ref
  1280  
  1281  	// The location of the "use strict" directive for ExplicitStrictMode
  1282  	UseStrictLoc logger.Loc
  1283  
  1284  	// This is used to store the ref of the label symbol for ScopeLabel scopes.
  1285  	Label           ast.LocRef
  1286  	LabelStmtIsLoop bool
  1287  
  1288  	// If a scope contains a direct eval() expression, then none of the symbols
  1289  	// inside that scope can be renamed. We conservatively assume that the
  1290  	// evaluated code might reference anything that it has access to.
  1291  	ContainsDirectEval bool
  1292  
  1293  	// This is to help forbid "arguments" inside class body scopes
  1294  	ForbidArguments bool
  1295  
  1296  	// As a special case, we enable constant propagation for any chain of "const"
  1297  	// declarations at the start of a statement list. This special case doesn't
  1298  	// have any TDZ considerations because no other statements come before it.
  1299  	IsAfterConstLocalPrefix bool
  1300  
  1301  	StrictMode StrictModeKind
  1302  	Kind       ScopeKind
  1303  }
  1304  
  1305  type StrictModeKind uint8
  1306  
  1307  const (
  1308  	SloppyMode StrictModeKind = iota
  1309  	ExplicitStrictMode
  1310  	ImplicitStrictModeClass
  1311  	ImplicitStrictModeESM
  1312  	ImplicitStrictModeTSAlwaysStrict
  1313  	ImplicitStrictModeJSXAutomaticRuntime
  1314  )
  1315  
  1316  func (s *Scope) RecursiveSetStrictMode(kind StrictModeKind) {
  1317  	if s.StrictMode == SloppyMode {
  1318  		s.StrictMode = kind
  1319  		for _, child := range s.Children {
  1320  			child.RecursiveSetStrictMode(kind)
  1321  		}
  1322  	}
  1323  }
  1324  
  1325  // This is for TypeScript "enum" and "namespace" blocks. Each block can
  1326  // potentially be instantiated multiple times. The exported members of each
  1327  // block are merged into a single namespace while the non-exported code is
  1328  // still scoped to just within that block:
  1329  //
  1330  //	let x = 1;
  1331  //	namespace Foo {
  1332  //	  let x = 2;
  1333  //	  export let y = 3;
  1334  //	}
  1335  //	namespace Foo {
  1336  //	  console.log(x); // 1
  1337  //	  console.log(y); // 3
  1338  //	}
  1339  //
  1340  // Doing this also works inside an enum:
  1341  //
  1342  //	enum Foo {
  1343  //	  A = 3,
  1344  //	  B = A + 1,
  1345  //	}
  1346  //	enum Foo {
  1347  //	  C = A + 2,
  1348  //	}
  1349  //	console.log(Foo.B) // 4
  1350  //	console.log(Foo.C) // 5
  1351  //
  1352  // This is a form of identifier lookup that works differently than the
  1353  // hierarchical scope-based identifier lookup in JavaScript. Lookup now needs
  1354  // to search sibling scopes in addition to parent scopes. This is accomplished
  1355  // by sharing the map of exported members between all matching sibling scopes.
  1356  type TSNamespaceScope struct {
  1357  	// This is shared between all sibling namespace blocks
  1358  	ExportedMembers TSNamespaceMembers
  1359  
  1360  	// This is a lazily-generated map of identifiers that actually represent
  1361  	// property accesses to this namespace's properties. For example:
  1362  	//
  1363  	//   namespace x {
  1364  	//     export let y = 123
  1365  	//   }
  1366  	//   namespace x {
  1367  	//     export let z = y
  1368  	//   }
  1369  	//
  1370  	// This should be compiled into the following code:
  1371  	//
  1372  	//   var x;
  1373  	//   (function(x2) {
  1374  	//     x2.y = 123;
  1375  	//   })(x || (x = {}));
  1376  	//   (function(x3) {
  1377  	//     x3.z = x3.y;
  1378  	//   })(x || (x = {}));
  1379  	//
  1380  	// When we try to find the symbol "y", we instead return one of these lazily
  1381  	// generated proxy symbols that represent the property access "x3.y". This
  1382  	// map is unique per namespace block because "x3" is the argument symbol that
  1383  	// is specific to that particular namespace block.
  1384  	LazilyGeneratedProperyAccesses map[string]ast.Ref
  1385  
  1386  	// This is specific to this namespace block. It's the argument of the
  1387  	// immediately-invoked function expression that the namespace block is
  1388  	// compiled into:
  1389  	//
  1390  	//   var ns;
  1391  	//   (function (ns2) {
  1392  	//     ns2.x = 123;
  1393  	//   })(ns || (ns = {}));
  1394  	//
  1395  	// This variable is "ns2" in the above example. It's the symbol to use when
  1396  	// generating property accesses off of this namespace when it's in scope.
  1397  	ArgRef ast.Ref
  1398  
  1399  	// Even though enums are like namespaces and both enums and namespaces allow
  1400  	// implicit references to properties of sibling scopes, they behave like
  1401  	// separate, er, namespaces. Implicit references only work namespace-to-
  1402  	// namespace and enum-to-enum. They do not work enum-to-namespace. And I'm
  1403  	// not sure what's supposed to happen for the namespace-to-enum case because
  1404  	// the compiler crashes: https://github.com/microsoft/TypeScript/issues/46891.
  1405  	// So basically these both work:
  1406  	//
  1407  	//   enum a { b = 1 }
  1408  	//   enum a { c = b }
  1409  	//
  1410  	//   namespace x { export let y = 1 }
  1411  	//   namespace x { export let z = y }
  1412  	//
  1413  	// This doesn't work:
  1414  	//
  1415  	//   enum a { b = 1 }
  1416  	//   namespace a { export let c = b }
  1417  	//
  1418  	// And this crashes the TypeScript compiler:
  1419  	//
  1420  	//   namespace a { export let b = 1 }
  1421  	//   enum a { c = b }
  1422  	//
  1423  	// Therefore we only allow enum/enum and namespace/namespace interactions.
  1424  	IsEnumScope bool
  1425  }
  1426  
  1427  type TSNamespaceMembers map[string]TSNamespaceMember
  1428  
  1429  type TSNamespaceMember struct {
  1430  	Data        TSNamespaceMemberData
  1431  	Loc         logger.Loc
  1432  	IsEnumValue bool
  1433  }
  1434  
  1435  type TSNamespaceMemberData interface {
  1436  	isTSNamespaceMember()
  1437  }
  1438  
  1439  func (TSNamespaceMemberProperty) isTSNamespaceMember()   {}
  1440  func (TSNamespaceMemberNamespace) isTSNamespaceMember()  {}
  1441  func (TSNamespaceMemberEnumNumber) isTSNamespaceMember() {}
  1442  func (TSNamespaceMemberEnumString) isTSNamespaceMember() {}
  1443  
  1444  // "namespace ns { export let it }"
  1445  type TSNamespaceMemberProperty struct{}
  1446  
  1447  // "namespace ns { export namespace it {} }"
  1448  type TSNamespaceMemberNamespace struct {
  1449  	ExportedMembers TSNamespaceMembers
  1450  }
  1451  
  1452  // "enum ns { it }"
  1453  type TSNamespaceMemberEnumNumber struct {
  1454  	Value float64
  1455  }
  1456  
  1457  // "enum ns { it = 'it' }"
  1458  type TSNamespaceMemberEnumString struct {
  1459  	Value []uint16
  1460  }
  1461  
  1462  type ExportsKind uint8
  1463  
  1464  const (
  1465  	// This file doesn't have any kind of export, so it's impossible to say what
  1466  	// kind of file this is. An empty file is in this category, for example.
  1467  	ExportsNone ExportsKind = iota
  1468  
  1469  	// The exports are stored on "module" and/or "exports". Calling "require()"
  1470  	// on this module returns "module.exports". All imports to this module are
  1471  	// allowed but may return undefined.
  1472  	ExportsCommonJS
  1473  
  1474  	// All export names are known explicitly. Calling "require()" on this module
  1475  	// generates an exports object (stored in "exports") with getters for the
  1476  	// export names. Named imports to this module are only allowed if they are
  1477  	// in the set of export names.
  1478  	ExportsESM
  1479  
  1480  	// Some export names are known explicitly, but others fall back to a dynamic
  1481  	// run-time object. This is necessary when using the "export * from" syntax
  1482  	// with either a CommonJS module or an external module (i.e. a module whose
  1483  	// export names are not known at compile-time).
  1484  	//
  1485  	// Calling "require()" on this module generates an exports object (stored in
  1486  	// "exports") with getters for the export names. All named imports to this
  1487  	// module are allowed. Direct named imports reference the corresponding export
  1488  	// directly. Other imports go through property accesses on "exports".
  1489  	ExportsESMWithDynamicFallback
  1490  )
  1491  
  1492  func (kind ExportsKind) IsDynamic() bool {
  1493  	return kind == ExportsCommonJS || kind == ExportsESMWithDynamicFallback
  1494  }
  1495  
  1496  type ModuleType uint8
  1497  
  1498  const (
  1499  	ModuleUnknown ModuleType = iota
  1500  
  1501  	// ".cjs" or ".cts" or "type: commonjs" in package.json
  1502  	ModuleCommonJS_CJS
  1503  	ModuleCommonJS_CTS
  1504  	ModuleCommonJS_PackageJSON
  1505  
  1506  	// ".mjs" or ".mts" or "type: module" in package.json
  1507  	ModuleESM_MJS
  1508  	ModuleESM_MTS
  1509  	ModuleESM_PackageJSON
  1510  )
  1511  
  1512  func (mt ModuleType) IsCommonJS() bool {
  1513  	return mt >= ModuleCommonJS_CJS && mt <= ModuleCommonJS_PackageJSON
  1514  }
  1515  
  1516  func (mt ModuleType) IsESM() bool {
  1517  	return mt >= ModuleESM_MJS && mt <= ModuleESM_PackageJSON
  1518  }
  1519  
  1520  type ModuleTypeData struct {
  1521  	Source *logger.Source
  1522  	Range  logger.Range
  1523  	Type   ModuleType
  1524  }
  1525  
  1526  // This is the index to the automatically-generated part containing code that
  1527  // calls "__export(exports, { ... getters ... })". This is used to generate
  1528  // getters on an exports object for ES6 export statements, and is both for
  1529  // ES6 star imports and CommonJS-style modules. All files have one of these,
  1530  // although it may contain no statements if there is nothing to export.
  1531  const NSExportPartIndex = uint32(0)
  1532  
  1533  type AST struct {
  1534  	ModuleTypeData ModuleTypeData
  1535  	Parts          []Part
  1536  	Symbols        []ast.Symbol
  1537  	ExprComments   map[logger.Loc][]string
  1538  	ModuleScope    *Scope
  1539  	CharFreq       *ast.CharFreq
  1540  
  1541  	// This is internal-only data used for the implementation of Yarn PnP
  1542  	ManifestForYarnPnP Expr
  1543  
  1544  	Hashbang   string
  1545  	Directives []string
  1546  	URLForCSS  string
  1547  
  1548  	// Note: If you're in the linker, do not use this map directly. This map is
  1549  	// filled in by the parser and is considered immutable. For performance reasons,
  1550  	// the linker doesn't mutate this map (cloning a map is slow in Go). Instead the
  1551  	// linker super-imposes relevant information on top in a method call. You should
  1552  	// call "TopLevelSymbolToParts" instead.
  1553  	TopLevelSymbolToPartsFromParser map[ast.Ref][]uint32
  1554  
  1555  	// This contains all top-level exported TypeScript enum constants. It exists
  1556  	// to enable cross-module inlining of constant enums.
  1557  	TSEnums map[ast.Ref]map[string]TSEnumValue
  1558  
  1559  	// This contains the values of all detected inlinable constants. It exists
  1560  	// to enable cross-module inlining of these constants.
  1561  	ConstValues map[ast.Ref]ConstValue
  1562  
  1563  	// Properties in here are represented as symbols instead of strings, which
  1564  	// allows them to be renamed to smaller names.
  1565  	MangledProps map[string]ast.Ref
  1566  
  1567  	// Properties in here are existing non-mangled properties in the source code
  1568  	// and must not be used when generating mangled names to avoid a collision.
  1569  	ReservedProps map[string]bool
  1570  
  1571  	// These are stored at the AST level instead of on individual AST nodes so
  1572  	// they can be manipulated efficiently without a full AST traversal
  1573  	ImportRecords []ast.ImportRecord
  1574  
  1575  	// These are used when bundling. They are filled in during the parser pass
  1576  	// since we already have to traverse the AST then anyway and the parser pass
  1577  	// is conveniently fully parallelized.
  1578  	NamedImports            map[ast.Ref]NamedImport
  1579  	NamedExports            map[string]NamedExport
  1580  	ExportStarImportRecords []uint32
  1581  
  1582  	SourceMapComment logger.Span
  1583  
  1584  	// This is a list of ES6 features. They are ranges instead of booleans so
  1585  	// that they can be used in log messages. Check to see if "Len > 0".
  1586  	ExportKeyword            logger.Range // Does not include TypeScript-specific syntax
  1587  	TopLevelAwaitKeyword     logger.Range
  1588  	LiveTopLevelAwaitKeyword logger.Range // Excludes top-level await in dead branches
  1589  
  1590  	ExportsRef ast.Ref
  1591  	ModuleRef  ast.Ref
  1592  	WrapperRef ast.Ref
  1593  
  1594  	ApproximateLineCount  int32
  1595  	NestedScopeSlotCounts ast.SlotCounts
  1596  	HasLazyExport         bool
  1597  
  1598  	// This is a list of CommonJS features. When a file uses CommonJS features,
  1599  	// it's not a candidate for "flat bundling" and must be wrapped in its own
  1600  	// closure. Note that this also includes top-level "return" but these aren't
  1601  	// here because only the parser checks those.
  1602  	UsesExportsRef bool
  1603  	UsesModuleRef  bool
  1604  	ExportsKind    ExportsKind
  1605  }
  1606  
  1607  type TSEnumValue struct {
  1608  	String []uint16 // Use this if it's not nil
  1609  	Number float64  // Use this if "String" is nil
  1610  }
  1611  
  1612  type ConstValueKind uint8
  1613  
  1614  const (
  1615  	ConstValueNone ConstValueKind = iota
  1616  	ConstValueNull
  1617  	ConstValueUndefined
  1618  	ConstValueTrue
  1619  	ConstValueFalse
  1620  	ConstValueNumber
  1621  )
  1622  
  1623  type ConstValue struct {
  1624  	Number float64 // Use this for "ConstValueNumber"
  1625  	Kind   ConstValueKind
  1626  }
  1627  
  1628  func ExprToConstValue(expr Expr) ConstValue {
  1629  	switch v := expr.Data.(type) {
  1630  	case *ENull:
  1631  		return ConstValue{Kind: ConstValueNull}
  1632  
  1633  	case *EUndefined:
  1634  		return ConstValue{Kind: ConstValueUndefined}
  1635  
  1636  	case *EBoolean:
  1637  		if v.Value {
  1638  			return ConstValue{Kind: ConstValueTrue}
  1639  		} else {
  1640  			return ConstValue{Kind: ConstValueFalse}
  1641  		}
  1642  
  1643  	case *ENumber:
  1644  		// Inline integers and other small numbers. Don't inline large
  1645  		// real numbers because people may not want them to be inlined
  1646  		// as it will increase the minified code size by too much.
  1647  		if asInt := int64(v.Value); v.Value == float64(asInt) || len(strconv.FormatFloat(v.Value, 'g', -1, 64)) <= 8 {
  1648  			return ConstValue{Kind: ConstValueNumber, Number: v.Value}
  1649  		}
  1650  
  1651  	case *EString:
  1652  		// I'm deliberately not inlining strings here. It seems more likely that
  1653  		// people won't want them to be inlined since they can be arbitrarily long.
  1654  
  1655  	case *EBigInt:
  1656  		// I'm deliberately not inlining bigints here for the same reason (they can
  1657  		// be arbitrarily long).
  1658  	}
  1659  
  1660  	return ConstValue{}
  1661  }
  1662  
  1663  func ConstValueToExpr(loc logger.Loc, value ConstValue) Expr {
  1664  	switch value.Kind {
  1665  	case ConstValueNull:
  1666  		return Expr{Loc: loc, Data: ENullShared}
  1667  
  1668  	case ConstValueUndefined:
  1669  		return Expr{Loc: loc, Data: EUndefinedShared}
  1670  
  1671  	case ConstValueTrue:
  1672  		return Expr{Loc: loc, Data: &EBoolean{Value: true}}
  1673  
  1674  	case ConstValueFalse:
  1675  		return Expr{Loc: loc, Data: &EBoolean{Value: false}}
  1676  
  1677  	case ConstValueNumber:
  1678  		return Expr{Loc: loc, Data: &ENumber{Value: value.Number}}
  1679  	}
  1680  
  1681  	panic("Internal error: invalid constant value")
  1682  }
  1683  
  1684  type NamedImport struct {
  1685  	Alias string
  1686  
  1687  	// Parts within this file that use this import
  1688  	LocalPartsWithUses []uint32
  1689  
  1690  	AliasLoc          logger.Loc
  1691  	NamespaceRef      ast.Ref
  1692  	ImportRecordIndex uint32
  1693  
  1694  	// If true, the alias refers to the entire export namespace object of a
  1695  	// module. This is no longer represented as an alias called "*" because of
  1696  	// the upcoming "Arbitrary module namespace identifier names" feature:
  1697  	// https://github.com/tc39/ecma262/pull/2154
  1698  	AliasIsStar bool
  1699  
  1700  	// It's useful to flag exported imports because if they are in a TypeScript
  1701  	// file, we can't tell if they are a type or a value.
  1702  	IsExported bool
  1703  }
  1704  
  1705  type NamedExport struct {
  1706  	Ref      ast.Ref
  1707  	AliasLoc logger.Loc
  1708  }
  1709  
  1710  // Each file is made up of multiple parts, and each part consists of one or
  1711  // more top-level statements. Parts are used for tree shaking and code
  1712  // splitting analysis. Individual parts of a file can be discarded by tree
  1713  // shaking and can be assigned to separate chunks (i.e. output files) by code
  1714  // splitting.
  1715  type Part struct {
  1716  	Stmts  []Stmt
  1717  	Scopes []*Scope
  1718  
  1719  	// Each is an index into the file-level import record list
  1720  	ImportRecordIndices []uint32
  1721  
  1722  	// All symbols that are declared in this part. Note that a given symbol may
  1723  	// have multiple declarations, and so may end up being declared in multiple
  1724  	// parts (e.g. multiple "var" declarations with the same name). Also note
  1725  	// that this list isn't deduplicated and may contain duplicates.
  1726  	DeclaredSymbols []DeclaredSymbol
  1727  
  1728  	// An estimate of the number of uses of all symbols used within this part.
  1729  	SymbolUses map[ast.Ref]SymbolUse
  1730  
  1731  	// An estimate of the number of uses of all symbols used as the target of
  1732  	// function calls within this part.
  1733  	SymbolCallUses map[ast.Ref]SymbolCallUse
  1734  
  1735  	// This tracks property accesses off of imported symbols. We don't know
  1736  	// during parsing if an imported symbol is going to be an inlined enum
  1737  	// value or not. This is only known during linking. So we defer adding
  1738  	// a dependency on these imported symbols until we know whether the
  1739  	// property access is an inlined enum value or not.
  1740  	ImportSymbolPropertyUses map[ast.Ref]map[string]SymbolUse
  1741  
  1742  	// The indices of the other parts in this file that are needed if this part
  1743  	// is needed.
  1744  	Dependencies []Dependency
  1745  
  1746  	// If true, this part can be removed if none of the declared symbols are
  1747  	// used. If the file containing this part is imported, then all parts that
  1748  	// don't have this flag enabled must be included.
  1749  	CanBeRemovedIfUnused bool
  1750  
  1751  	// This is used for generated parts that we don't want to be present if they
  1752  	// aren't needed. This enables tree shaking for these parts even if global
  1753  	// tree shaking isn't enabled.
  1754  	ForceTreeShaking bool
  1755  
  1756  	// This is true if this file has been marked as live by the tree shaking
  1757  	// algorithm.
  1758  	IsLive bool
  1759  }
  1760  
  1761  type Dependency struct {
  1762  	SourceIndex uint32
  1763  	PartIndex   uint32
  1764  }
  1765  
  1766  type DeclaredSymbol struct {
  1767  	Ref        ast.Ref
  1768  	IsTopLevel bool
  1769  }
  1770  
  1771  type SymbolUse struct {
  1772  	CountEstimate uint32
  1773  }
  1774  
  1775  type SymbolCallUse struct {
  1776  	CallCountEstimate                   uint32
  1777  	SingleArgNonSpreadCallCountEstimate uint32
  1778  }
  1779  
  1780  // For readability, the names of certain automatically-generated symbols are
  1781  // derived from the file name. For example, instead of the CommonJS wrapper for
  1782  // a file being called something like "require273" it can be called something
  1783  // like "require_react" instead. This function generates the part of these
  1784  // identifiers that's specific to the file path. It can take both an absolute
  1785  // path (OS-specific) and a path in the source code (OS-independent).
  1786  //
  1787  // Note that these generated names do not at all relate to the correctness of
  1788  // the code as far as avoiding symbol name collisions. These names still go
  1789  // through the renaming logic that all other symbols go through to avoid name
  1790  // collisions.
  1791  func GenerateNonUniqueNameFromPath(path string) string {
  1792  	// Get the file name without the extension
  1793  	dir, base, _ := logger.PlatformIndependentPathDirBaseExt(path)
  1794  
  1795  	// If the name is "index", use the directory name instead. This is because
  1796  	// many packages in npm use the file name "index.js" because it triggers
  1797  	// node's implicit module resolution rules that allows you to import it by
  1798  	// just naming the directory.
  1799  	if base == "index" {
  1800  		_, dirBase, _ := logger.PlatformIndependentPathDirBaseExt(dir)
  1801  		if dirBase != "" {
  1802  			base = dirBase
  1803  		}
  1804  	}
  1805  
  1806  	return EnsureValidIdentifier(base)
  1807  }
  1808  
  1809  func EnsureValidIdentifier(base string) string {
  1810  	// Convert it to an ASCII identifier. Note: If you change this to a non-ASCII
  1811  	// identifier, you're going to potentially cause trouble with non-BMP code
  1812  	// points in target environments that don't support bracketed Unicode escapes.
  1813  	bytes := []byte{}
  1814  	needsGap := false
  1815  	for _, c := range base {
  1816  		if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (len(bytes) > 0 && c >= '0' && c <= '9') {
  1817  			if needsGap {
  1818  				bytes = append(bytes, '_')
  1819  				needsGap = false
  1820  			}
  1821  			bytes = append(bytes, byte(c))
  1822  		} else if len(bytes) > 0 {
  1823  			needsGap = true
  1824  		}
  1825  	}
  1826  
  1827  	// Make sure the name isn't empty
  1828  	if len(bytes) == 0 {
  1829  		return "_"
  1830  	}
  1831  	return string(bytes)
  1832  }