1package js_ast
2
3import (
4	"math"
5	"sort"
6
7	"github.com/evanw/esbuild/internal/ast"
8	"github.com/evanw/esbuild/internal/compat"
9	"github.com/evanw/esbuild/internal/logger"
10)
11
12// Every module (i.e. file) is parsed into a separate AST data structure. For
13// efficiency, the parser also resolves all scopes and binds all symbols in the
14// tree.
15//
16// Identifiers in the tree are referenced by a Ref, which is a pointer into the
17// symbol table for the file. The symbol table is stored as a top-level field
18// in the AST so it can be accessed without traversing the tree. For example,
19// a renaming pass can iterate over the symbol table without touching the tree.
20//
21// Parse trees are intended to be immutable. That makes it easy to build an
22// incremental compiler with a "watch" mode that can avoid re-parsing files
23// that have already been parsed. Any passes that operate on an AST after it
24// has been parsed should create a copy of the mutated parts of the tree
25// instead of mutating the original tree.
26
27type L int
28
29// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
30const (
31	LLowest L = iota
32	LComma
33	LSpread
34	LYield
35	LAssign
36	LConditional
37	LNullishCoalescing
38	LLogicalOr
39	LLogicalAnd
40	LBitwiseOr
41	LBitwiseXor
42	LBitwiseAnd
43	LEquals
44	LCompare
45	LShift
46	LAdd
47	LMultiply
48	LExponentiation
49	LPrefix
50	LPostfix
51	LNew
52	LCall
53	LMember
54)
55
56type OpCode int
57
58func (op OpCode) IsPrefix() bool {
59	return op < UnOpPostDec
60}
61
62func (op OpCode) UnaryAssignTarget() AssignTarget {
63	if op >= UnOpPreDec && op <= UnOpPostInc {
64		return AssignTargetUpdate
65	}
66	return AssignTargetNone
67}
68
69func (op OpCode) IsLeftAssociative() bool {
70	return op >= BinOpAdd && op < BinOpComma && op != BinOpPow
71}
72
73func (op OpCode) IsRightAssociative() bool {
74	return op >= BinOpAssign || op == BinOpPow
75}
76
77func (op OpCode) BinaryAssignTarget() AssignTarget {
78	if op == BinOpAssign {
79		return AssignTargetReplace
80	}
81	if op > BinOpAssign {
82		return AssignTargetUpdate
83	}
84	return AssignTargetNone
85}
86
87func (op OpCode) IsShortCircuit() bool {
88	switch op {
89	case BinOpLogicalOr, BinOpLogicalOrAssign,
90		BinOpLogicalAnd, BinOpLogicalAndAssign,
91		BinOpNullishCoalescing, BinOpNullishCoalescingAssign:
92		return true
93	}
94	return false
95}
96
97type AssignTarget uint8
98
99const (
100	AssignTargetNone    AssignTarget = iota
101	AssignTargetReplace              // "a = b"
102	AssignTargetUpdate               // "a += b"
103)
104
105// If you add a new token, remember to add it to "OpTable" too
106const (
107	// Prefix
108	UnOpPos OpCode = iota
109	UnOpNeg
110	UnOpCpl
111	UnOpNot
112	UnOpVoid
113	UnOpTypeof
114	UnOpDelete
115
116	// Prefix update
117	UnOpPreDec
118	UnOpPreInc
119
120	// Postfix update
121	UnOpPostDec
122	UnOpPostInc
123
124	// Left-associative
125	BinOpAdd
126	BinOpSub
127	BinOpMul
128	BinOpDiv
129	BinOpRem
130	BinOpPow
131	BinOpLt
132	BinOpLe
133	BinOpGt
134	BinOpGe
135	BinOpIn
136	BinOpInstanceof
137	BinOpShl
138	BinOpShr
139	BinOpUShr
140	BinOpLooseEq
141	BinOpLooseNe
142	BinOpStrictEq
143	BinOpStrictNe
144	BinOpNullishCoalescing
145	BinOpLogicalOr
146	BinOpLogicalAnd
147	BinOpBitwiseOr
148	BinOpBitwiseAnd
149	BinOpBitwiseXor
150
151	// Non-associative
152	BinOpComma
153
154	// Right-associative
155	BinOpAssign
156	BinOpAddAssign
157	BinOpSubAssign
158	BinOpMulAssign
159	BinOpDivAssign
160	BinOpRemAssign
161	BinOpPowAssign
162	BinOpShlAssign
163	BinOpShrAssign
164	BinOpUShrAssign
165	BinOpBitwiseOrAssign
166	BinOpBitwiseAndAssign
167	BinOpBitwiseXorAssign
168	BinOpNullishCoalescingAssign
169	BinOpLogicalOrAssign
170	BinOpLogicalAndAssign
171)
172
173type opTableEntry struct {
174	Text      string
175	Level     L
176	IsKeyword bool
177}
178
179var OpTable = []opTableEntry{
180	// Prefix
181	{"+", LPrefix, false},
182	{"-", LPrefix, false},
183	{"~", LPrefix, false},
184	{"!", LPrefix, false},
185	{"void", LPrefix, true},
186	{"typeof", LPrefix, true},
187	{"delete", LPrefix, true},
188
189	// Prefix update
190	{"--", LPrefix, false},
191	{"++", LPrefix, false},
192
193	// Postfix update
194	{"--", LPostfix, false},
195	{"++", LPostfix, false},
196
197	// Left-associative
198	{"+", LAdd, false},
199	{"-", LAdd, false},
200	{"*", LMultiply, false},
201	{"/", LMultiply, false},
202	{"%", LMultiply, false},
203	{"**", LExponentiation, false}, // Right-associative
204	{"<", LCompare, false},
205	{"<=", LCompare, false},
206	{">", LCompare, false},
207	{">=", LCompare, false},
208	{"in", LCompare, true},
209	{"instanceof", LCompare, true},
210	{"<<", LShift, false},
211	{">>", LShift, false},
212	{">>>", LShift, false},
213	{"==", LEquals, false},
214	{"!=", LEquals, false},
215	{"===", LEquals, false},
216	{"!==", LEquals, false},
217	{"??", LNullishCoalescing, false},
218	{"||", LLogicalOr, false},
219	{"&&", LLogicalAnd, false},
220	{"|", LBitwiseOr, false},
221	{"&", LBitwiseAnd, false},
222	{"^", LBitwiseXor, false},
223
224	// Non-associative
225	{",", LComma, false},
226
227	// Right-associative
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	{"||=", LAssign, false},
243	{"&&=", LAssign, false},
244}
245
246type LocRef struct {
247	Loc logger.Loc
248	Ref Ref
249}
250
251type Comment struct {
252	Loc  logger.Loc
253	Text string
254}
255
256type PropertyKind int
257
258const (
259	PropertyNormal PropertyKind = iota
260	PropertyGet
261	PropertySet
262	PropertySpread
263	PropertyDeclare
264	PropertyClassStaticBlock
265)
266
267type ClassStaticBlock struct {
268	Loc   logger.Loc
269	Stmts []Stmt
270}
271
272type Property struct {
273	TSDecorators     []Expr
274	ClassStaticBlock *ClassStaticBlock
275
276	Key Expr
277
278	// This is omitted for class fields
279	ValueOrNil Expr
280
281	// This is used when parsing a pattern that uses default values:
282	//
283	//   [a = 1] = [];
284	//   ({a = 1} = {});
285	//
286	// It's also used for class fields:
287	//
288	//   class Foo { a = 1 }
289	//
290	InitializerOrNil Expr
291
292	Kind            PropertyKind
293	IsComputed      bool
294	IsMethod        bool
295	IsStatic        bool
296	WasShorthand    bool
297	PreferQuotedKey bool
298}
299
300type PropertyBinding struct {
301	Key               Expr
302	Value             Binding
303	DefaultValueOrNil Expr
304	IsComputed        bool
305	IsSpread          bool
306	PreferQuotedKey   bool
307}
308
309type Arg struct {
310	TSDecorators []Expr
311	Binding      Binding
312	DefaultOrNil Expr
313
314	// "constructor(public x: boolean) {}"
315	IsTypeScriptCtorField bool
316}
317
318type Fn struct {
319	Name         *LocRef
320	OpenParenLoc logger.Loc
321	Args         []Arg
322	Body         FnBody
323	ArgumentsRef Ref
324
325	IsAsync     bool
326	IsGenerator bool
327	HasRestArg  bool
328	HasIfScope  bool
329
330	// This is true if the function is a method
331	IsUniqueFormalParameters bool
332}
333
334type FnBody struct {
335	Loc   logger.Loc
336	Stmts []Stmt
337}
338
339type Class struct {
340	ClassKeyword logger.Range
341	TSDecorators []Expr
342	Name         *LocRef
343	ExtendsOrNil Expr
344	BodyLoc      logger.Loc
345	Properties   []Property
346}
347
348type ArrayBinding struct {
349	Binding           Binding
350	DefaultValueOrNil Expr
351}
352
353type Binding struct {
354	Loc  logger.Loc
355	Data B
356}
357
358// This interface is never called. Its purpose is to encode a variant type in
359// Go's type system.
360type B interface{ isBinding() }
361
362func (*BMissing) isBinding()    {}
363func (*BIdentifier) isBinding() {}
364func (*BArray) isBinding()      {}
365func (*BObject) isBinding()     {}
366
367type BMissing struct{}
368
369type BIdentifier struct{ Ref Ref }
370
371type BArray struct {
372	Items        []ArrayBinding
373	HasSpread    bool
374	IsSingleLine bool
375}
376
377type BObject struct {
378	Properties   []PropertyBinding
379	IsSingleLine bool
380}
381
382type Expr struct {
383	Loc  logger.Loc
384	Data E
385}
386
387// This interface is never called. Its purpose is to encode a variant type in
388// Go's type system.
389type E interface{ isExpr() }
390
391func (*EArray) isExpr()                {}
392func (*EUnary) isExpr()                {}
393func (*EBinary) isExpr()               {}
394func (*EBoolean) isExpr()              {}
395func (*ESuper) isExpr()                {}
396func (*ENull) isExpr()                 {}
397func (*EUndefined) isExpr()            {}
398func (*EThis) isExpr()                 {}
399func (*ENew) isExpr()                  {}
400func (*ENewTarget) isExpr()            {}
401func (*EImportMeta) isExpr()           {}
402func (*ECall) isExpr()                 {}
403func (*EDot) isExpr()                  {}
404func (*EIndex) isExpr()                {}
405func (*EArrow) isExpr()                {}
406func (*EFunction) isExpr()             {}
407func (*EClass) isExpr()                {}
408func (*EIdentifier) isExpr()           {}
409func (*EImportIdentifier) isExpr()     {}
410func (*EPrivateIdentifier) isExpr()    {}
411func (*EJSXElement) isExpr()           {}
412func (*EMissing) isExpr()              {}
413func (*ENumber) isExpr()               {}
414func (*EBigInt) isExpr()               {}
415func (*EObject) isExpr()               {}
416func (*ESpread) isExpr()               {}
417func (*EString) isExpr()               {}
418func (*ETemplate) isExpr()             {}
419func (*ERegExp) isExpr()               {}
420func (*EInlinedEnum) isExpr()          {}
421func (*EAwait) isExpr()                {}
422func (*EYield) isExpr()                {}
423func (*EIf) isExpr()                   {}
424func (*ERequireString) isExpr()        {}
425func (*ERequireResolveString) isExpr() {}
426func (*EImportString) isExpr()         {}
427func (*EImportCall) isExpr()           {}
428
429type EArray struct {
430	Items            []Expr
431	CommaAfterSpread logger.Loc
432	IsSingleLine     bool
433	IsParenthesized  bool
434}
435
436type EUnary struct {
437	Op    OpCode
438	Value Expr
439}
440
441type EBinary struct {
442	Left  Expr
443	Right Expr
444	Op    OpCode
445}
446
447type EBoolean struct{ Value bool }
448
449type EMissing struct{}
450
451type ESuper struct{}
452
453type ENull struct{}
454
455type EUndefined struct{}
456
457type EThis struct{}
458
459type ENewTarget struct {
460	Range logger.Range
461}
462
463type EImportMeta struct {
464	RangeLen int32
465}
466
467// These help reduce unnecessary memory allocations
468var BMissingShared = &BMissing{}
469var EMissingShared = &EMissing{}
470var ESuperShared = &ESuper{}
471var ENullShared = &ENull{}
472var EUndefinedShared = &EUndefined{}
473var EThisShared = &EThis{}
474
475type ENew struct {
476	Target Expr
477	Args   []Expr
478
479	// True if there is a comment containing "@__PURE__" or "#__PURE__" preceding
480	// this call expression. See the comment inside ECall for more details.
481	CanBeUnwrappedIfUnused bool
482}
483
484type OptionalChain uint8
485
486const (
487	// "a.b"
488	OptionalChainNone OptionalChain = iota
489
490	// "a?.b"
491	OptionalChainStart
492
493	// "a?.b.c" => ".c" is OptionalChainContinue
494	// "(a?.b).c" => ".c" is OptionalChainNone
495	OptionalChainContinue
496)
497
498type ECall struct {
499	Target        Expr
500	Args          []Expr
501	OptionalChain OptionalChain
502	IsDirectEval  bool
503
504	// True if there is a comment containing "@__PURE__" or "#__PURE__" preceding
505	// this call expression. This is an annotation used for tree shaking, and
506	// means that the call can be removed if it's unused. It does not mean the
507	// call is pure (e.g. it may still return something different if called twice).
508	//
509	// Note that the arguments are not considered to be part of the call. If the
510	// call itself is removed due to this annotation, the arguments must remain
511	// if they have side effects.
512	CanBeUnwrappedIfUnused bool
513}
514
515func (a *ECall) HasSameFlagsAs(b *ECall) bool {
516	return a.OptionalChain == b.OptionalChain &&
517		a.IsDirectEval == b.IsDirectEval &&
518		a.CanBeUnwrappedIfUnused == b.CanBeUnwrappedIfUnused
519}
520
521type EDot struct {
522	Target        Expr
523	Name          string
524	NameLoc       logger.Loc
525	OptionalChain OptionalChain
526
527	// If true, this property access is known to be free of side-effects. That
528	// means it can be removed if the resulting value isn't used.
529	CanBeRemovedIfUnused bool
530
531	// If true, this property access is a function that, when called, can be
532	// unwrapped if the resulting value is unused. Unwrapping means discarding
533	// the call target but keeping any arguments with side effects.
534	CallCanBeUnwrappedIfUnused bool
535}
536
537func (a *EDot) HasSameFlagsAs(b *EDot) bool {
538	return a.OptionalChain == b.OptionalChain &&
539		a.CanBeRemovedIfUnused == b.CanBeRemovedIfUnused &&
540		a.CallCanBeUnwrappedIfUnused == b.CallCanBeUnwrappedIfUnused
541}
542
543type EIndex struct {
544	Target        Expr
545	Index         Expr
546	OptionalChain OptionalChain
547}
548
549func (a *EIndex) HasSameFlagsAs(b *EIndex) bool {
550	return a.OptionalChain == b.OptionalChain
551}
552
553type EArrow struct {
554	Args []Arg
555	Body FnBody
556
557	IsAsync    bool
558	HasRestArg bool
559	PreferExpr bool // Use shorthand if true and "Body" is a single return statement
560}
561
562type EFunction struct{ Fn Fn }
563
564type EClass struct{ Class Class }
565
566type EIdentifier struct {
567	Ref Ref
568
569	// If we're inside a "with" statement, this identifier may be a property
570	// access. In that case it would be incorrect to remove this identifier since
571	// the property access may be a getter or setter with side effects.
572	MustKeepDueToWithStmt bool
573
574	// If true, this identifier is known to not have a side effect (i.e. to not
575	// throw an exception) when referenced. If false, this identifier may or may
576	// not have side effects when referenced. This is used to allow the removal
577	// of known globals such as "Object" if they aren't used.
578	CanBeRemovedIfUnused bool
579
580	// If true, this identifier represents a function that, when called, can be
581	// unwrapped if the resulting value is unused. Unwrapping means discarding
582	// the call target but keeping any arguments with side effects.
583	CallCanBeUnwrappedIfUnused bool
584}
585
586// This is similar to an EIdentifier but it represents a reference to an ES6
587// import item.
588//
589// Depending on how the code is linked, the file containing this EImportIdentifier
590// may or may not be in the same module group as the file it was imported from.
591//
592// If it's the same module group than we can just merge the import item symbol
593// with the corresponding symbol that was imported, effectively renaming them
594// to be the same thing and statically binding them together.
595//
596// But if it's a different module group, then the import must be dynamically
597// evaluated using a property access off the corresponding namespace symbol,
598// which represents the result of a require() call.
599//
600// It's stored as a separate type so it's not easy to confuse with a plain
601// identifier. For example, it'd be bad if code trying to convert "{x: x}" into
602// "{x}" shorthand syntax wasn't aware that the "x" in this case is actually
603// "{x: importedNamespace.x}". This separate type forces code to opt-in to
604// doing this instead of opt-out.
605type EImportIdentifier struct {
606	Ref             Ref
607	PreferQuotedKey bool
608
609	// If true, this was originally an identifier expression such as "foo". If
610	// false, this could potentially have been a member access expression such
611	// as "ns.foo" off of an imported namespace object.
612	WasOriginallyIdentifier bool
613}
614
615// This is similar to EIdentifier but it represents class-private fields and
616// methods. It can be used where computed properties can be used, such as
617// EIndex and Property.
618type EPrivateIdentifier struct {
619	Ref Ref
620}
621
622type EJSXElement struct {
623	TagOrNil   Expr
624	Properties []Property
625	Children   []Expr
626	CloseLoc   logger.Loc
627}
628
629type ENumber struct{ Value float64 }
630
631type EBigInt struct{ Value string }
632
633type EObject struct {
634	Properties       []Property
635	CommaAfterSpread logger.Loc
636	IsSingleLine     bool
637	IsParenthesized  bool
638}
639
640type ESpread struct{ Value Expr }
641
642// This is used for both strings and no-substitution template literals to reduce
643// the number of cases that need to be checked for string optimization code
644type EString struct {
645	Value          []uint16
646	LegacyOctalLoc logger.Loc
647	PreferTemplate bool
648}
649
650type TemplatePart struct {
651	Value      Expr
652	TailLoc    logger.Loc
653	TailCooked []uint16 // Only use when "TagOrNil" is nil
654	TailRaw    string   // Only use when "TagOrNil" is not nil
655}
656
657type ETemplate struct {
658	TagOrNil       Expr
659	HeadLoc        logger.Loc
660	HeadCooked     []uint16 // Only use when "TagOrNil" is nil
661	HeadRaw        string   // Only use when "TagOrNil" is not nil
662	Parts          []TemplatePart
663	LegacyOctalLoc logger.Loc
664}
665
666type ERegExp struct{ Value string }
667
668type EInlinedEnum struct {
669	Value   Expr
670	Comment string
671}
672
673type EAwait struct {
674	Value Expr
675}
676
677type EYield struct {
678	ValueOrNil Expr
679	IsStar     bool
680}
681
682type EIf struct {
683	Test Expr
684	Yes  Expr
685	No   Expr
686}
687
688type ERequireString struct {
689	ImportRecordIndex uint32
690}
691
692type ERequireResolveString struct {
693	ImportRecordIndex uint32
694}
695
696type EImportString struct {
697	ImportRecordIndex uint32
698
699	// Comments inside "import()" expressions have special meaning for Webpack.
700	// Preserving comments inside these expressions makes it possible to use
701	// esbuild as a TypeScript-to-JavaScript frontend for Webpack to improve
702	// performance. We intentionally do not interpret these comments in esbuild
703	// because esbuild is not Webpack. But we do preserve them since doing so is
704	// harmless, easy to maintain, and useful to people. See the Webpack docs for
705	// more info: https://webpack.js.org/api/module-methods/#magic-comments.
706	LeadingInteriorComments []Comment
707}
708
709type EImportCall struct {
710	Expr         Expr
711	OptionsOrNil Expr
712
713	// See the comment for this same field on "EImportCall" for more information
714	LeadingInteriorComments []Comment
715}
716
717func IsOptionalChain(value Expr) bool {
718	switch e := value.Data.(type) {
719	case *EDot:
720		return e.OptionalChain != OptionalChainNone
721	case *EIndex:
722		return e.OptionalChain != OptionalChainNone
723	case *ECall:
724		return e.OptionalChain != OptionalChainNone
725	}
726	return false
727}
728
729func Assign(a Expr, b Expr) Expr {
730	return Expr{Loc: a.Loc, Data: &EBinary{Op: BinOpAssign, Left: a, Right: b}}
731}
732
733func AssignStmt(a Expr, b Expr) Stmt {
734	return Stmt{Loc: a.Loc, Data: &SExpr{Value: Assign(a, b)}}
735}
736
737// Wraps the provided expression in the "!" prefix operator. The expression
738// will potentially be simplified to avoid generating unnecessary extra "!"
739// operators. For example, calling this with "!!x" will return "!x" instead
740// of returning "!!!x".
741func Not(expr Expr) Expr {
742	if result, ok := MaybeSimplifyNot(expr); ok {
743		return result
744	}
745	return Expr{Loc: expr.Loc, Data: &EUnary{Op: UnOpNot, Value: expr}}
746}
747
748// The given "expr" argument should be the operand of a "!" prefix operator
749// (i.e. the "x" in "!x"). This returns a simplified expression for the
750// whole operator (i.e. the "!x") if it can be simplified, or false if not.
751// It's separate from "Not()" above to avoid allocation on failure in case
752// that is undesired.
753func MaybeSimplifyNot(expr Expr) (Expr, bool) {
754	switch e := expr.Data.(type) {
755	case *EInlinedEnum:
756		if value, ok := MaybeSimplifyNot(e.Value); ok {
757			return value, true
758		}
759
760	case *ENull, *EUndefined:
761		return Expr{Loc: expr.Loc, Data: &EBoolean{Value: true}}, true
762
763	case *EBoolean:
764		return Expr{Loc: expr.Loc, Data: &EBoolean{Value: !e.Value}}, true
765
766	case *ENumber:
767		return Expr{Loc: expr.Loc, Data: &EBoolean{Value: e.Value == 0 || math.IsNaN(e.Value)}}, true
768
769	case *EBigInt:
770		return Expr{Loc: expr.Loc, Data: &EBoolean{Value: e.Value == "0"}}, true
771
772	case *EString:
773		return Expr{Loc: expr.Loc, Data: &EBoolean{Value: len(e.Value) == 0}}, true
774
775	case *EFunction, *EArrow, *ERegExp:
776		return Expr{Loc: expr.Loc, Data: &EBoolean{Value: false}}, true
777
778	case *EUnary:
779		// "!!!a" => "!a"
780		if e.Op == UnOpNot && KnownPrimitiveType(e.Value) == PrimitiveBoolean {
781			return e.Value, true
782		}
783
784	case *EBinary:
785		// Make sure that these transformations are all safe for special values.
786		// For example, "!(a < b)" is not the same as "a >= b" if a and/or b are
787		// NaN (or undefined, or null, or possibly other problem cases too).
788		switch e.Op {
789		case BinOpLooseEq:
790			// "!(a == b)" => "a != b"
791			e.Op = BinOpLooseNe
792			return expr, true
793
794		case BinOpLooseNe:
795			// "!(a != b)" => "a == b"
796			e.Op = BinOpLooseEq
797			return expr, true
798
799		case BinOpStrictEq:
800			// "!(a === b)" => "a !== b"
801			e.Op = BinOpStrictNe
802			return expr, true
803
804		case BinOpStrictNe:
805			// "!(a !== b)" => "a === b"
806			e.Op = BinOpStrictEq
807			return expr, true
808
809		case BinOpComma:
810			// "!(a, b)" => "a, !b"
811			e.Right = Not(e.Right)
812			return expr, true
813		}
814	}
815
816	return Expr{}, false
817}
818
819type PrimitiveType uint8
820
821const (
822	PrimitiveUnknown PrimitiveType = iota
823	PrimitiveMixed
824	PrimitiveNull
825	PrimitiveUndefined
826	PrimitiveBoolean
827	PrimitiveNumber
828	PrimitiveString
829	PrimitiveBigInt
830)
831
832// This can be used when the returned type is either one or the other
833func MergedKnownPrimitiveTypes(a Expr, b Expr) PrimitiveType {
834	x := KnownPrimitiveType(a)
835	y := KnownPrimitiveType(b)
836	if x == PrimitiveUnknown || y == PrimitiveUnknown {
837		return PrimitiveUnknown
838	}
839	if x == y {
840		return x
841	}
842	return PrimitiveMixed // Definitely some kind of primitive
843}
844
845func KnownPrimitiveType(a Expr) PrimitiveType {
846	switch e := a.Data.(type) {
847	case *EInlinedEnum:
848		return KnownPrimitiveType(e.Value)
849
850	case *ENull:
851		return PrimitiveNull
852
853	case *EUndefined:
854		return PrimitiveUndefined
855
856	case *EBoolean:
857		return PrimitiveBoolean
858
859	case *ENumber:
860		return PrimitiveNumber
861
862	case *EString:
863		return PrimitiveString
864
865	case *EBigInt:
866		return PrimitiveBigInt
867
868	case *ETemplate:
869		if e.TagOrNil.Data == nil {
870			return PrimitiveString
871		}
872
873	case *EIf:
874		return MergedKnownPrimitiveTypes(e.Yes, e.No)
875
876	case *EUnary:
877		switch e.Op {
878		case UnOpVoid:
879			return PrimitiveUndefined
880
881		case UnOpTypeof:
882			return PrimitiveString
883
884		case UnOpNot, UnOpDelete:
885			return PrimitiveBoolean
886
887		case UnOpPos:
888			return PrimitiveNumber // Cannot be bigint because that throws an exception
889
890		case UnOpNeg, UnOpCpl:
891			value := KnownPrimitiveType(e.Value)
892			if value == PrimitiveBigInt {
893				return PrimitiveBigInt
894			}
895			if value != PrimitiveUnknown && value != PrimitiveMixed {
896				return PrimitiveNumber
897			}
898			return PrimitiveMixed // Can be number or bigint
899
900		case UnOpPreDec, UnOpPreInc, UnOpPostDec, UnOpPostInc:
901			return PrimitiveMixed // Can be number or bigint
902		}
903
904	case *EBinary:
905		switch e.Op {
906		case BinOpStrictEq, BinOpStrictNe, BinOpLooseEq, BinOpLooseNe,
907			BinOpLt, BinOpGt, BinOpLe, BinOpGe,
908			BinOpInstanceof, BinOpIn:
909			return PrimitiveBoolean
910
911		case BinOpLogicalOr, BinOpLogicalAnd:
912			return MergedKnownPrimitiveTypes(e.Left, e.Right)
913
914		case BinOpNullishCoalescing:
915			left := KnownPrimitiveType(e.Left)
916			right := KnownPrimitiveType(e.Right)
917			if left == PrimitiveNull || left == PrimitiveUndefined {
918				return right
919			}
920			if left != PrimitiveUnknown {
921				if left != PrimitiveMixed {
922					return left // Definitely not null or undefined
923				}
924				if right != PrimitiveUnknown {
925					return PrimitiveMixed // Definitely some kind of primitive
926				}
927			}
928
929		case BinOpAdd:
930			left := KnownPrimitiveType(e.Left)
931			right := KnownPrimitiveType(e.Right)
932			if left == PrimitiveString || right == PrimitiveString {
933				return PrimitiveString
934			}
935			if left == PrimitiveBigInt && right == PrimitiveBigInt {
936				return PrimitiveBigInt
937			}
938			if left != PrimitiveUnknown && left != PrimitiveMixed && left != PrimitiveBigInt &&
939				right != PrimitiveUnknown && right != PrimitiveMixed && right != PrimitiveBigInt {
940				return PrimitiveNumber
941			}
942			return PrimitiveMixed // Can be number or bigint or string (or an exception)
943
944		case BinOpAddAssign:
945			right := KnownPrimitiveType(e.Right)
946			if right == PrimitiveString {
947				return PrimitiveString
948			}
949			return PrimitiveMixed // Can be number or bigint or string (or an exception)
950
951		case
952			BinOpSub, BinOpSubAssign,
953			BinOpMul, BinOpMulAssign,
954			BinOpDiv, BinOpDivAssign,
955			BinOpRem, BinOpRemAssign,
956			BinOpPow, BinOpPowAssign,
957			BinOpBitwiseAnd, BinOpBitwiseAndAssign,
958			BinOpBitwiseOr, BinOpBitwiseOrAssign,
959			BinOpBitwiseXor, BinOpBitwiseXorAssign,
960			BinOpShl, BinOpShlAssign,
961			BinOpShr, BinOpShrAssign,
962			BinOpUShr, BinOpUShrAssign:
963			return PrimitiveMixed // Can be number or bigint (or an exception)
964
965		case BinOpAssign, BinOpComma:
966			return KnownPrimitiveType(e.Right)
967		}
968	}
969
970	return PrimitiveUnknown
971}
972
973// The goal of this function is to "rotate" the AST if it's possible to use the
974// left-associative property of the operator to avoid unnecessary parentheses.
975//
976// When using this, make absolutely sure that the operator is actually
977// associative. For example, the "-" operator is not associative for
978// floating-point numbers.
979func JoinWithLeftAssociativeOp(op OpCode, a Expr, b Expr) Expr {
980	// "(a, b) op c" => "a, b op c"
981	if comma, ok := a.Data.(*EBinary); ok && comma.Op == BinOpComma {
982		comma.Right = JoinWithLeftAssociativeOp(op, comma.Right, b)
983		return a
984	}
985
986	// "a op (b op c)" => "(a op b) op c"
987	// "a op (b op (c op d))" => "((a op b) op c) op d"
988	if binary, ok := b.Data.(*EBinary); ok && binary.Op == op {
989		return JoinWithLeftAssociativeOp(
990			op,
991			JoinWithLeftAssociativeOp(op, a, binary.Left),
992			binary.Right,
993		)
994	}
995
996	// "a op b" => "a op b"
997	// "(a op b) op c" => "(a op b) op c"
998	return Expr{Loc: a.Loc, Data: &EBinary{Op: op, Left: a, Right: b}}
999}
1000
1001func JoinWithComma(a Expr, b Expr) Expr {
1002	if a.Data == nil {
1003		return b
1004	}
1005	if b.Data == nil {
1006		return a
1007	}
1008	return Expr{Loc: a.Loc, Data: &EBinary{Op: BinOpComma, Left: a, Right: b}}
1009}
1010
1011func JoinAllWithComma(all []Expr) (result Expr) {
1012	for _, value := range all {
1013		result = JoinWithComma(result, value)
1014	}
1015	return
1016}
1017
1018type Stmt struct {
1019	Loc  logger.Loc
1020	Data S
1021}
1022
1023// This interface is never called. Its purpose is to encode a variant type in
1024// Go's type system.
1025type S interface{ isStmt() }
1026
1027func (*SBlock) isStmt()         {}
1028func (*SComment) isStmt()       {}
1029func (*SDebugger) isStmt()      {}
1030func (*SDirective) isStmt()     {}
1031func (*SEmpty) isStmt()         {}
1032func (*STypeScript) isStmt()    {}
1033func (*SExportClause) isStmt()  {}
1034func (*SExportFrom) isStmt()    {}
1035func (*SExportDefault) isStmt() {}
1036func (*SExportStar) isStmt()    {}
1037func (*SExportEquals) isStmt()  {}
1038func (*SLazyExport) isStmt()    {}
1039func (*SExpr) isStmt()          {}
1040func (*SEnum) isStmt()          {}
1041func (*SNamespace) isStmt()     {}
1042func (*SFunction) isStmt()      {}
1043func (*SClass) isStmt()         {}
1044func (*SLabel) isStmt()         {}
1045func (*SIf) isStmt()            {}
1046func (*SFor) isStmt()           {}
1047func (*SForIn) isStmt()         {}
1048func (*SForOf) isStmt()         {}
1049func (*SDoWhile) isStmt()       {}
1050func (*SWhile) isStmt()         {}
1051func (*SWith) isStmt()          {}
1052func (*STry) isStmt()           {}
1053func (*SSwitch) isStmt()        {}
1054func (*SImport) isStmt()        {}
1055func (*SReturn) isStmt()        {}
1056func (*SThrow) isStmt()         {}
1057func (*SLocal) isStmt()         {}
1058func (*SBreak) isStmt()         {}
1059func (*SContinue) isStmt()      {}
1060
1061type SBlock struct {
1062	Stmts []Stmt
1063}
1064
1065type SEmpty struct{}
1066
1067// This is a stand-in for a TypeScript type declaration
1068type STypeScript struct{}
1069
1070type SComment struct {
1071	Text           string
1072	IsLegalComment bool
1073}
1074
1075type SDebugger struct{}
1076
1077type SDirective struct {
1078	Value          []uint16
1079	LegacyOctalLoc logger.Loc
1080}
1081
1082type SExportClause struct {
1083	Items        []ClauseItem
1084	IsSingleLine bool
1085}
1086
1087type SExportFrom struct {
1088	Items             []ClauseItem
1089	NamespaceRef      Ref
1090	ImportRecordIndex uint32
1091	IsSingleLine      bool
1092}
1093
1094type SExportDefault struct {
1095	DefaultName LocRef
1096	Value       Stmt // May be a SExpr or SFunction or SClass
1097}
1098
1099type ExportStarAlias struct {
1100	Loc logger.Loc
1101
1102	// Although this alias name starts off as being the same as the statement's
1103	// namespace symbol, it may diverge if the namespace symbol name is minified.
1104	// The original alias name is preserved here to avoid this scenario.
1105	OriginalName string
1106}
1107
1108type SExportStar struct {
1109	NamespaceRef      Ref
1110	Alias             *ExportStarAlias
1111	ImportRecordIndex uint32
1112}
1113
1114// This is an "export = value;" statement in TypeScript
1115type SExportEquals struct {
1116	Value Expr
1117}
1118
1119// The decision of whether to export an expression using "module.exports" or
1120// "export default" is deferred until linking using this statement kind
1121type SLazyExport struct {
1122	Value Expr
1123}
1124
1125type SExpr struct {
1126	Value Expr
1127
1128	// This is set to true for automatically-generated expressions that should
1129	// not affect tree shaking. For example, calling a function from the runtime
1130	// that doesn't have externally-visible side effects.
1131	DoesNotAffectTreeShaking bool
1132}
1133
1134type EnumValue struct {
1135	Name       []uint16
1136	ValueOrNil Expr
1137	Ref        Ref
1138	Loc        logger.Loc
1139}
1140
1141type SEnum struct {
1142	Name     LocRef
1143	Arg      Ref
1144	Values   []EnumValue
1145	IsExport bool
1146}
1147
1148type SNamespace struct {
1149	Name     LocRef
1150	Arg      Ref
1151	Stmts    []Stmt
1152	IsExport bool
1153}
1154
1155type SFunction struct {
1156	Fn       Fn
1157	IsExport bool
1158}
1159
1160type SClass struct {
1161	Class    Class
1162	IsExport bool
1163}
1164
1165type SLabel struct {
1166	Name LocRef
1167	Stmt Stmt
1168}
1169
1170type SIf struct {
1171	Test    Expr
1172	Yes     Stmt
1173	NoOrNil Stmt
1174}
1175
1176type SFor struct {
1177	InitOrNil   Stmt // May be a SConst, SLet, SVar, or SExpr
1178	TestOrNil   Expr
1179	UpdateOrNil Expr
1180	Body        Stmt
1181}
1182
1183type SForIn struct {
1184	Init  Stmt // May be a SConst, SLet, SVar, or SExpr
1185	Value Expr
1186	Body  Stmt
1187}
1188
1189type SForOf struct {
1190	IsAwait bool
1191	Init    Stmt // May be a SConst, SLet, SVar, or SExpr
1192	Value   Expr
1193	Body    Stmt
1194}
1195
1196type SDoWhile struct {
1197	Body Stmt
1198	Test Expr
1199}
1200
1201type SWhile struct {
1202	Test Expr
1203	Body Stmt
1204}
1205
1206type SWith struct {
1207	Value   Expr
1208	BodyLoc logger.Loc
1209	Body    Stmt
1210}
1211
1212type Catch struct {
1213	BindingOrNil Binding
1214	Body         []Stmt
1215	Loc          logger.Loc
1216	BodyLoc      logger.Loc
1217}
1218
1219type Finally struct {
1220	Loc   logger.Loc
1221	Stmts []Stmt
1222}
1223
1224type STry struct {
1225	BodyLoc logger.Loc
1226	Body    []Stmt
1227	Catch   *Catch
1228	Finally *Finally
1229}
1230
1231type Case struct {
1232	ValueOrNil Expr // If this is nil, this is "default" instead of "case"
1233	Body       []Stmt
1234}
1235
1236type SSwitch struct {
1237	Test    Expr
1238	BodyLoc logger.Loc
1239	Cases   []Case
1240}
1241
1242// This object represents all of these types of import statements:
1243//
1244//    import 'path'
1245//    import {item1, item2} from 'path'
1246//    import * as ns from 'path'
1247//    import defaultItem, {item1, item2} from 'path'
1248//    import defaultItem, * as ns from 'path'
1249//
1250// Many parts are optional and can be combined in different ways. The only
1251// restriction is that you cannot have both a clause and a star namespace.
1252type SImport struct {
1253	// If this is a star import: This is a Ref for the namespace symbol. The Loc
1254	// for the symbol is StarLoc.
1255	//
1256	// Otherwise: This is an auto-generated Ref for the namespace representing
1257	// the imported file. In this case StarLoc is nil. The NamespaceRef is used
1258	// when converting this module to a CommonJS module.
1259	NamespaceRef Ref
1260
1261	DefaultName       *LocRef
1262	Items             *[]ClauseItem
1263	StarNameLoc       *logger.Loc
1264	ImportRecordIndex uint32
1265	IsSingleLine      bool
1266}
1267
1268type SReturn struct {
1269	ValueOrNil Expr
1270}
1271
1272type SThrow struct {
1273	Value Expr
1274}
1275
1276type LocalKind uint8
1277
1278const (
1279	LocalVar LocalKind = iota
1280	LocalLet
1281	LocalConst
1282)
1283
1284type SLocal struct {
1285	Decls    []Decl
1286	Kind     LocalKind
1287	IsExport bool
1288
1289	// The TypeScript compiler doesn't generate code for "import foo = bar"
1290	// statements where the import is never used.
1291	WasTSImportEquals bool
1292}
1293
1294type SBreak struct {
1295	Label *LocRef
1296}
1297
1298type SContinue struct {
1299	Label *LocRef
1300}
1301
1302func IsSuperCall(stmt Stmt) bool {
1303	if expr, ok := stmt.Data.(*SExpr); ok {
1304		if call, ok := expr.Value.Data.(*ECall); ok {
1305			if _, ok := call.Target.Data.(*ESuper); ok {
1306				return true
1307			}
1308		}
1309	}
1310	return false
1311}
1312
1313type ClauseItem struct {
1314	Alias    string
1315	AliasLoc logger.Loc
1316	Name     LocRef
1317
1318	// This is the original name of the symbol stored in "Name". It's needed for
1319	// "SExportClause" statements such as this:
1320	//
1321	//   export {foo as bar} from 'path'
1322	//
1323	// In this case both "foo" and "bar" are aliases because it's a re-export.
1324	// We need to preserve both aliases in case the symbol is renamed. In this
1325	// example, "foo" is "OriginalName" and "bar" is "Alias".
1326	OriginalName string
1327}
1328
1329type Decl struct {
1330	Binding    Binding
1331	ValueOrNil Expr
1332}
1333
1334type SymbolKind uint8
1335
1336const (
1337	// An unbound symbol is one that isn't declared in the file it's referenced
1338	// in. For example, using "window" without declaring it will be unbound.
1339	SymbolUnbound SymbolKind = iota
1340
1341	// This has special merging behavior. You're allowed to re-declare these
1342	// symbols more than once in the same scope. These symbols are also hoisted
1343	// out of the scope they are declared in to the closest containing function
1344	// or module scope. These are the symbols with this kind:
1345	//
1346	// - Function arguments
1347	// - Function statements
1348	// - Variables declared using "var"
1349	//
1350	SymbolHoisted
1351	SymbolHoistedFunction
1352
1353	// There's a weird special case where catch variables declared using a simple
1354	// identifier (i.e. not a binding pattern) block hoisted variables instead of
1355	// becoming an error:
1356	//
1357	//   var e = 0;
1358	//   try { throw 1 } catch (e) {
1359	//     print(e) // 1
1360	//     var e = 2
1361	//     print(e) // 2
1362	//   }
1363	//   print(e) // 0 (since the hoisting stops at the catch block boundary)
1364	//
1365	// However, other forms are still a syntax error:
1366	//
1367	//   try {} catch (e) { let e }
1368	//   try {} catch ({e}) { var e }
1369	//
1370	// This symbol is for handling this weird special case.
1371	SymbolCatchIdentifier
1372
1373	// Generator and async functions are not hoisted, but still have special
1374	// properties such as being able to overwrite previous functions with the
1375	// same name
1376	SymbolGeneratorOrAsyncFunction
1377
1378	// This is the special "arguments" variable inside functions
1379	SymbolArguments
1380
1381	// Classes can merge with TypeScript namespaces.
1382	SymbolClass
1383
1384	// A class-private identifier (i.e. "#foo").
1385	SymbolPrivateField
1386	SymbolPrivateMethod
1387	SymbolPrivateGet
1388	SymbolPrivateSet
1389	SymbolPrivateGetSetPair
1390	SymbolPrivateStaticField
1391	SymbolPrivateStaticMethod
1392	SymbolPrivateStaticGet
1393	SymbolPrivateStaticSet
1394	SymbolPrivateStaticGetSetPair
1395
1396	// Labels are in their own namespace
1397	SymbolLabel
1398
1399	// TypeScript enums can merge with TypeScript namespaces and other TypeScript
1400	// enums.
1401	SymbolTSEnum
1402
1403	// TypeScript namespaces can merge with classes, functions, TypeScript enums,
1404	// and other TypeScript namespaces.
1405	SymbolTSNamespace
1406
1407	// In TypeScript, imports are allowed to silently collide with symbols within
1408	// the module. Presumably this is because the imports may be type-only.
1409	SymbolImport
1410
1411	// Assigning to a "const" symbol will throw a TypeError at runtime
1412	SymbolConst
1413
1414	// Injected symbols can be overridden by provided defines
1415	SymbolInjected
1416
1417	// This annotates all other symbols that don't have special behavior.
1418	SymbolOther
1419)
1420
1421func (kind SymbolKind) IsPrivate() bool {
1422	return kind >= SymbolPrivateField && kind <= SymbolPrivateStaticGetSetPair
1423}
1424
1425func (kind SymbolKind) Feature() compat.JSFeature {
1426	switch kind {
1427	case SymbolPrivateField:
1428		return compat.ClassPrivateField
1429	case SymbolPrivateMethod:
1430		return compat.ClassPrivateMethod
1431	case SymbolPrivateGet, SymbolPrivateSet, SymbolPrivateGetSetPair:
1432		return compat.ClassPrivateAccessor
1433	case SymbolPrivateStaticField:
1434		return compat.ClassPrivateStaticField
1435	case SymbolPrivateStaticMethod:
1436		return compat.ClassPrivateStaticMethod
1437	case SymbolPrivateStaticGet, SymbolPrivateStaticSet, SymbolPrivateStaticGetSetPair:
1438		return compat.ClassPrivateStaticAccessor
1439	default:
1440		return 0
1441	}
1442}
1443
1444func (kind SymbolKind) IsHoisted() bool {
1445	return kind == SymbolHoisted || kind == SymbolHoistedFunction
1446}
1447
1448func (kind SymbolKind) IsHoistedOrFunction() bool {
1449	return kind.IsHoisted() || kind == SymbolGeneratorOrAsyncFunction
1450}
1451
1452func (kind SymbolKind) IsFunction() bool {
1453	return kind == SymbolHoistedFunction || kind == SymbolGeneratorOrAsyncFunction
1454}
1455
1456func (kind SymbolKind) IsUnboundOrInjected() bool {
1457	return kind == SymbolUnbound || kind == SymbolInjected
1458}
1459
1460var InvalidRef Ref = Ref{^uint32(0), ^uint32(0)}
1461
1462// Files are parsed in parallel for speed. We want to allow each parser to
1463// generate symbol IDs that won't conflict with each other. We also want to be
1464// able to quickly merge symbol tables from all files into one giant symbol
1465// table.
1466//
1467// We can accomplish both goals by giving each symbol ID two parts: a source
1468// index that is unique to the parser goroutine, and an inner index that
1469// increments as the parser generates new symbol IDs. Then a symbol map can
1470// be an array of arrays indexed first by source index, then by inner index.
1471// The maps can be merged quickly by creating a single outer array containing
1472// all inner arrays from all parsed files.
1473type Ref struct {
1474	SourceIndex uint32
1475	InnerIndex  uint32
1476}
1477
1478type ImportItemStatus uint8
1479
1480const (
1481	ImportItemNone ImportItemStatus = iota
1482
1483	// The linker doesn't report import/export mismatch errors
1484	ImportItemGenerated
1485
1486	// The printer will replace this import with "undefined"
1487	ImportItemMissing
1488)
1489
1490type SymbolFlags uint8
1491
1492const (
1493	// Certain symbols must not be renamed or minified. For example, the
1494	// "arguments" variable is declared by the runtime for every function.
1495	// Renaming can also break any identifier used inside a "with" statement.
1496	MustNotBeRenamed SymbolFlags = 1 << iota
1497
1498	// In React's version of JSX, lower-case names are strings while upper-case
1499	// names are identifiers. If we are preserving JSX syntax (i.e. not
1500	// transforming it), then we need to be careful to name the identifiers
1501	// something with a capital letter so further JSX processing doesn't treat
1502	// them as strings instead.
1503	MustStartWithCapitalLetterForJSX
1504
1505	// If true, this symbol is the target of a "__name" helper function call.
1506	// This call is special because it deliberately doesn't count as a use
1507	// of the symbol (otherwise keeping names would disable tree shaking)
1508	// so "UseCountEstimate" is not incremented. This flag helps us know to
1509	// avoid optimizing this symbol when "UseCountEstimate" is 1 in this case.
1510	DidKeepName
1511
1512	// Sometimes we lower private symbols even if they are supported. For example,
1513	// consider the following TypeScript code:
1514	//
1515	//   class Foo {
1516	//     #foo = 123
1517	//     bar = this.#foo
1518	//   }
1519	//
1520	// If "useDefineForClassFields: false" is set in "tsconfig.json", then "bar"
1521	// must use assignment semantics instead of define semantics. We can compile
1522	// that to this code:
1523	//
1524	//   class Foo {
1525	//     constructor() {
1526	//       this.#foo = 123;
1527	//       this.bar = this.#foo;
1528	//     }
1529	//     #foo;
1530	//   }
1531	//
1532	// However, we can't do the same for static fields:
1533	//
1534	//   class Foo {
1535	//     static #foo = 123
1536	//     static bar = this.#foo
1537	//   }
1538	//
1539	// Compiling these static fields to something like this would be invalid:
1540	//
1541	//   class Foo {
1542	//     static #foo;
1543	//   }
1544	//   Foo.#foo = 123;
1545	//   Foo.bar = Foo.#foo;
1546	//
1547	// Thus "#foo" must be lowered even though it's supported. Another case is
1548	// when we're converting top-level class declarations to class expressions
1549	// to avoid the TDZ and the class shadowing symbol is referenced within the
1550	// class body:
1551	//
1552	//   class Foo {
1553	//     static #foo = Foo
1554	//   }
1555	//
1556	// This cannot be converted into something like this:
1557	//
1558	//   var Foo = class {
1559	//     static #foo;
1560	//   };
1561	//   Foo.#foo = Foo;
1562	//
1563	PrivateSymbolMustBeLowered
1564
1565	// This is used to remove the all but the last function re-declaration if a
1566	// function is re-declared multiple times like this:
1567	//
1568	//   function foo() { console.log(1) }
1569	//   function foo() { console.log(2) }
1570	//
1571	RemoveOverwrittenFunctionDeclaration
1572)
1573
1574func (flags SymbolFlags) Has(flag SymbolFlags) bool {
1575	return (flags & flag) != 0
1576}
1577
1578// Note: the order of values in this struct matters to reduce struct size.
1579type Symbol struct {
1580	// This is the name that came from the parser. Printed names may be renamed
1581	// during minification or to avoid name collisions. Do not use the original
1582	// name during printing.
1583	OriginalName string
1584
1585	// This is used for symbols that represent items in the import clause of an
1586	// ES6 import statement. These should always be referenced by EImportIdentifier
1587	// instead of an EIdentifier. When this is present, the expression should
1588	// be printed as a property access off the namespace instead of as a bare
1589	// identifier.
1590	//
1591	// For correctness, this must be stored on the symbol instead of indirectly
1592	// associated with the Ref for the symbol somehow. In ES6 "flat bundling"
1593	// mode, re-exported symbols are collapsed using MergeSymbols() and renamed
1594	// symbols from other files that end up at this symbol must be able to tell
1595	// if it has a namespace alias.
1596	NamespaceAlias *NamespaceAlias
1597
1598	// Used by the parser for single pass parsing. Symbols that have been merged
1599	// form a linked-list where the last link is the symbol to use. This link is
1600	// an invalid ref if it's the last link. If this isn't invalid, you need to
1601	// FollowSymbols to get the real one.
1602	Link Ref
1603
1604	// An estimate of the number of uses of this symbol. This is used to detect
1605	// whether a symbol is used or not. For example, TypeScript imports that are
1606	// unused must be removed because they are probably type-only imports. This
1607	// is an estimate and may not be completely accurate due to oversights in the
1608	// code. But it should always be non-zero when the symbol is used.
1609	UseCountEstimate uint32
1610
1611	// This is for generating cross-chunk imports and exports for code splitting.
1612	ChunkIndex ast.Index32
1613
1614	// This is used for minification. Symbols that are declared in sibling scopes
1615	// can share a name. A good heuristic (from Google Closure Compiler) is to
1616	// assign names to symbols from sibling scopes in declaration order. That way
1617	// local variable names are reused in each global function like this, which
1618	// improves gzip compression:
1619	//
1620	//   function x(a, b) { ... }
1621	//   function y(a, b, c) { ... }
1622	//
1623	// The parser fills this in for symbols inside nested scopes. There are three
1624	// slot namespaces: regular symbols, label symbols, and private symbols.
1625	NestedScopeSlot ast.Index32
1626
1627	Kind SymbolKind
1628
1629	// We automatically generate import items for property accesses off of
1630	// namespace imports. This lets us remove the expensive namespace imports
1631	// while bundling in many cases, replacing them with a cheap import item
1632	// instead:
1633	//
1634	//   import * as ns from 'path'
1635	//   ns.foo()
1636	//
1637	// That can often be replaced by this, which avoids needing the namespace:
1638	//
1639	//   import {foo} from 'path'
1640	//   foo()
1641	//
1642	// However, if the import is actually missing then we don't want to report a
1643	// compile-time error like we do for real import items. This status lets us
1644	// avoid this. We also need to be able to replace such import items with
1645	// undefined, which this status is also used for.
1646	ImportItemStatus ImportItemStatus
1647
1648	// Boolean values should all be flags instead to save space
1649	Flags SymbolFlags
1650}
1651
1652// You should call "MergeSymbols" instead of calling this directly
1653func (newSymbol *Symbol) MergeContentsWith(oldSymbol *Symbol) {
1654	newSymbol.UseCountEstimate += oldSymbol.UseCountEstimate
1655	if oldSymbol.Flags.Has(MustNotBeRenamed) {
1656		newSymbol.OriginalName = oldSymbol.OriginalName
1657		newSymbol.Flags |= MustNotBeRenamed
1658	}
1659	if oldSymbol.Flags.Has(MustStartWithCapitalLetterForJSX) {
1660		newSymbol.Flags |= MustStartWithCapitalLetterForJSX
1661	}
1662}
1663
1664type SlotNamespace uint8
1665
1666const (
1667	SlotDefault SlotNamespace = iota
1668	SlotLabel
1669	SlotPrivateName
1670	SlotMustNotBeRenamed
1671)
1672
1673func (s *Symbol) SlotNamespace() SlotNamespace {
1674	if s.Kind == SymbolUnbound || s.Flags.Has(MustNotBeRenamed) {
1675		return SlotMustNotBeRenamed
1676	}
1677	if s.Kind.IsPrivate() {
1678		return SlotPrivateName
1679	}
1680	if s.Kind == SymbolLabel {
1681		return SlotLabel
1682	}
1683	return SlotDefault
1684}
1685
1686type SlotCounts [3]uint32
1687
1688func (a *SlotCounts) UnionMax(b SlotCounts) {
1689	for i := range *a {
1690		ai := &(*a)[i]
1691		bi := b[i]
1692		if *ai < bi {
1693			*ai = bi
1694		}
1695	}
1696}
1697
1698type NamespaceAlias struct {
1699	NamespaceRef Ref
1700	Alias        string
1701}
1702
1703type ScopeKind int
1704
1705const (
1706	ScopeBlock ScopeKind = iota
1707	ScopeWith
1708	ScopeLabel
1709	ScopeClassName
1710	ScopeClassBody
1711	ScopeCatchBinding
1712
1713	// The scopes below stop hoisted variables from extending into parent scopes
1714	ScopeEntry // This is a module, TypeScript enum, or TypeScript namespace
1715	ScopeFunctionArgs
1716	ScopeFunctionBody
1717	ScopeClassStaticInit
1718)
1719
1720func (kind ScopeKind) StopsHoisting() bool {
1721	return kind >= ScopeEntry
1722}
1723
1724type ScopeMember struct {
1725	Ref Ref
1726	Loc logger.Loc
1727}
1728
1729type Scope struct {
1730	Kind      ScopeKind
1731	Parent    *Scope
1732	Children  []*Scope
1733	Members   map[string]ScopeMember
1734	Generated []Ref
1735
1736	// This will be non-nil if this is a TypeScript "namespace" or "enum"
1737	TSNamespace *TSNamespaceScope
1738
1739	// The location of the "use strict" directive for ExplicitStrictMode
1740	UseStrictLoc logger.Loc
1741
1742	// This is used to store the ref of the label symbol for ScopeLabel scopes.
1743	Label           LocRef
1744	LabelStmtIsLoop bool
1745
1746	// If a scope contains a direct eval() expression, then none of the symbols
1747	// inside that scope can be renamed. We conservatively assume that the
1748	// evaluated code might reference anything that it has access to.
1749	ContainsDirectEval bool
1750
1751	// This is to help forbid "arguments" inside class body scopes
1752	ForbidArguments bool
1753
1754	StrictMode StrictModeKind
1755}
1756
1757type StrictModeKind uint8
1758
1759const (
1760	SloppyMode StrictModeKind = iota
1761	ExplicitStrictMode
1762	ImplicitStrictModeImport
1763	ImplicitStrictModeExport
1764	ImplicitStrictModeTopLevelAwait
1765	ImplicitStrictModeClass
1766)
1767
1768func (s *Scope) RecursiveSetStrictMode(kind StrictModeKind) {
1769	if s.StrictMode == SloppyMode {
1770		s.StrictMode = kind
1771		for _, child := range s.Children {
1772			child.RecursiveSetStrictMode(kind)
1773		}
1774	}
1775}
1776
1777// This is for TypeScript "enum" and "namespace" blocks. Each block can
1778// potentially be instantiated multiple times. The exported members of each
1779// block are merged into a single namespace while the non-exported code is
1780// still scoped to just within that block:
1781//
1782//   let x = 1;
1783//   namespace Foo {
1784//     let x = 2;
1785//     export let y = 3;
1786//   }
1787//   namespace Foo {
1788//     console.log(x); // 1
1789//     console.log(y); // 3
1790//   }
1791//
1792// Doing this also works inside an enum:
1793//
1794//   enum Foo {
1795//     A = 3,
1796//     B = A + 1,
1797//   }
1798//   enum Foo {
1799//     C = A + 2,
1800//   }
1801//   console.log(Foo.B) // 4
1802//   console.log(Foo.C) // 5
1803//
1804// This is a form of identifier lookup that works differently than the
1805// hierarchical scope-based identifier lookup in JavaScript. Lookup now needs
1806// to search sibling scopes in addition to parent scopes. This is accomplished
1807// by sharing the map of exported members between all matching sibling scopes.
1808type TSNamespaceScope struct {
1809	// This is shared between all sibling namespace blocks
1810	ExportedMembers TSNamespaceMembers
1811
1812	// This is specific to this namespace block. It's the argument of the
1813	// immediately-invoked function expression that the namespace block is
1814	// compiled into:
1815	//
1816	//   var ns;
1817	//   (function (ns2) {
1818	//     ns2.x = 123;
1819	//   })(ns || (ns = {}));
1820	//
1821	// This variable is "ns2" in the above example. It's the symbol to use when
1822	// generating property accesses off of this namespace when it's in scope.
1823	ArgRef Ref
1824
1825	// This is a lazily-generated map of identifiers that actually represent
1826	// property accesses to this namespace's properties. For example:
1827	//
1828	//   namespace x {
1829	//     export let y = 123
1830	//   }
1831	//   namespace x {
1832	//     export let z = y
1833	//   }
1834	//
1835	// This should be compiled into the following code:
1836	//
1837	//   var x;
1838	//   (function(x2) {
1839	//     x2.y = 123;
1840	//   })(x || (x = {}));
1841	//   (function(x3) {
1842	//     x3.z = x3.y;
1843	//   })(x || (x = {}));
1844	//
1845	// When we try to find the symbol "y", we instead return one of these lazily
1846	// generated proxy symbols that represent the property access "x3.y". This
1847	// map is unique per namespace block because "x3" is the argument symbol that
1848	// is specific to that particular namespace block.
1849	LazilyGeneratedProperyAccesses map[string]Ref
1850
1851	// Even though enums are like namespaces and both enums and namespaces allow
1852	// implicit references to properties of sibling scopes, they behave like
1853	// separate, er, namespaces. Implicit references only work namespace-to-
1854	// namespace and enum-to-enum. They do not work enum-to-namespace. And I'm
1855	// not sure what's supposed to happen for the namespace-to-enum case because
1856	// the compiler crashes: https://github.com/microsoft/TypeScript/issues/46891.
1857	// So basically these both work:
1858	//
1859	//   enum a { b = 1 }
1860	//   enum a { c = b }
1861	//
1862	//   namespace x { export let y = 1 }
1863	//   namespace x { export let z = y }
1864	//
1865	// This doesn't work:
1866	//
1867	//   enum a { b = 1 }
1868	//   namespace a { export let c = b }
1869	//
1870	// And this crashes the TypeScript compiler:
1871	//
1872	//   namespace a { export let b = 1 }
1873	//   enum a { c = b }
1874	//
1875	// Therefore we only allow enum/enum and namespace/namespace interactions.
1876	IsEnumScope bool
1877}
1878
1879type TSNamespaceMembers map[string]TSNamespaceMember
1880
1881type TSNamespaceMember struct {
1882	Data        TSNamespaceMemberData
1883	Loc         logger.Loc
1884	IsEnumValue bool
1885}
1886
1887type TSNamespaceMemberData interface {
1888	isTSNamespaceMember()
1889}
1890
1891func (TSNamespaceMemberProperty) isTSNamespaceMember()   {}
1892func (TSNamespaceMemberNamespace) isTSNamespaceMember()  {}
1893func (TSNamespaceMemberEnumNumber) isTSNamespaceMember() {}
1894func (TSNamespaceMemberEnumString) isTSNamespaceMember() {}
1895
1896// "namespace ns { export let it }"
1897type TSNamespaceMemberProperty struct{}
1898
1899// "namespace ns { export namespace it {} }"
1900type TSNamespaceMemberNamespace struct {
1901	ExportedMembers TSNamespaceMembers
1902}
1903
1904// "enum ns { it }"
1905type TSNamespaceMemberEnumNumber struct {
1906	Value float64
1907}
1908
1909// "enum ns { it = 'it' }"
1910type TSNamespaceMemberEnumString struct {
1911	Value []uint16
1912}
1913
1914type SymbolMap struct {
1915	// This could be represented as a "map[Ref]Symbol" but a two-level array was
1916	// more efficient in profiles. This appears to be because it doesn't involve
1917	// a hash. This representation also makes it trivial to quickly merge symbol
1918	// maps from multiple files together. Each file only generates symbols in a
1919	// single inner array, so you can join the maps together by just make a
1920	// single outer array containing all of the inner arrays. See the comment on
1921	// "Ref" for more detail.
1922	SymbolsForSource [][]Symbol
1923}
1924
1925func NewSymbolMap(sourceCount int) SymbolMap {
1926	return SymbolMap{make([][]Symbol, sourceCount)}
1927}
1928
1929func (sm SymbolMap) Get(ref Ref) *Symbol {
1930	return &sm.SymbolsForSource[ref.SourceIndex][ref.InnerIndex]
1931}
1932
1933type ExportsKind uint8
1934
1935const (
1936	// This file doesn't have any kind of export, so it's impossible to say what
1937	// kind of file this is. An empty file is in this category, for example.
1938	ExportsNone ExportsKind = iota
1939
1940	// The exports are stored on "module" and/or "exports". Calling "require()"
1941	// on this module returns "module.exports". All imports to this module are
1942	// allowed but may return undefined.
1943	ExportsCommonJS
1944
1945	// All export names are known explicitly. Calling "require()" on this module
1946	// generates an exports object (stored in "exports") with getters for the
1947	// export names. Named imports to this module are only allowed if they are
1948	// in the set of export names.
1949	ExportsESM
1950
1951	// Some export names are known explicitly, but others fall back to a dynamic
1952	// run-time object. This is necessary when using the "export * from" syntax
1953	// with either a CommonJS module or an external module (i.e. a module whose
1954	// export names are not known at compile-time).
1955	//
1956	// Calling "require()" on this module generates an exports object (stored in
1957	// "exports") with getters for the export names. All named imports to this
1958	// module are allowed. Direct named imports reference the corresponding export
1959	// directly. Other imports go through property accesses on "exports".
1960	ExportsESMWithDynamicFallback
1961)
1962
1963func (kind ExportsKind) IsDynamic() bool {
1964	return kind == ExportsCommonJS || kind == ExportsESMWithDynamicFallback
1965}
1966
1967type ModuleType uint8
1968
1969const (
1970	ModuleUnknown ModuleType = iota
1971
1972	// ".cjs" or ".cts" or "type: commonjs" in package.json
1973	ModuleCommonJS
1974
1975	// ".mjs" or ".mts" or "type: module" in package.json
1976	ModuleESM
1977)
1978
1979// This is the index to the automatically-generated part containing code that
1980// calls "__export(exports, { ... getters ... })". This is used to generate
1981// getters on an exports object for ES6 export statements, and is both for
1982// ES6 star imports and CommonJS-style modules. All files have one of these,
1983// although it may contain no statements if there is nothing to export.
1984const NSExportPartIndex = uint32(0)
1985
1986type AST struct {
1987	ApproximateLineCount  int32
1988	NestedScopeSlotCounts SlotCounts
1989	HasLazyExport         bool
1990	ModuleType            ModuleType
1991
1992	// This is a list of CommonJS features. When a file uses CommonJS features,
1993	// it's not a candidate for "flat bundling" and must be wrapped in its own
1994	// closure. Note that this also includes top-level "return" but these aren't
1995	// here because only the parser checks those.
1996	UsesExportsRef bool
1997	UsesModuleRef  bool
1998	ExportsKind    ExportsKind
1999
2000	// This is a list of ES6 features. They are ranges instead of booleans so
2001	// that they can be used in log messages. Check to see if "Len > 0".
2002	ImportKeyword        logger.Range // Does not include TypeScript-specific syntax or "import()"
2003	ExportKeyword        logger.Range // Does not include TypeScript-specific syntax
2004	TopLevelAwaitKeyword logger.Range
2005
2006	Hashbang    string
2007	Directive   string
2008	URLForCSS   string
2009	Parts       []Part
2010	Symbols     []Symbol
2011	ModuleScope *Scope
2012	CharFreq    *CharFreq
2013	ExportsRef  Ref
2014	ModuleRef   Ref
2015	WrapperRef  Ref
2016
2017	// This contains all top-level exported TypeScript enum constants. It exists
2018	// to enable cross-module inlining of constant enums.
2019	TSEnums map[Ref]map[string]TSEnumValue
2020
2021	// These are stored at the AST level instead of on individual AST nodes so
2022	// they can be manipulated efficiently without a full AST traversal
2023	ImportRecords []ast.ImportRecord
2024
2025	// These are used when bundling. They are filled in during the parser pass
2026	// since we already have to traverse the AST then anyway and the parser pass
2027	// is conveniently fully parallelized.
2028	NamedImports            map[Ref]NamedImport
2029	NamedExports            map[string]NamedExport
2030	ExportStarImportRecords []uint32
2031
2032	// Note: If you're in the linker, do not use this map directly. This map is
2033	// filled in by the parser and is considered immutable. For performance reasons,
2034	// the linker doesn't mutate this map (cloning a map is slow in Go). Instead the
2035	// linker super-imposes relevant information on top in a method call. You should
2036	// call "TopLevelSymbolToParts" instead.
2037	TopLevelSymbolToPartsFromParser map[Ref][]uint32
2038
2039	SourceMapComment logger.Span
2040}
2041
2042type TSEnumValue struct {
2043	String []uint16 // Use this if it's not nil
2044	Number float64  // Use this if "String" is nil
2045}
2046
2047// This is a histogram of character frequencies for minification
2048type CharFreq [64]int32
2049
2050func (freq *CharFreq) Scan(text string, delta int32) {
2051	if delta == 0 {
2052		return
2053	}
2054
2055	// This matches the order in "DefaultNameMinifier"
2056	for i, n := 0, len(text); i < n; i++ {
2057		c := text[i]
2058		switch {
2059		case c >= 'a' && c <= 'z':
2060			(*freq)[c-'a'] += delta
2061		case c >= 'A' && c <= 'Z':
2062			(*freq)[c-('A'-26)] += delta
2063		case c >= '0' && c <= '9':
2064			(*freq)[c+(52-'0')] += delta
2065		case c == '_':
2066			(*freq)[62] += delta
2067		case c == '$':
2068			(*freq)[63] += delta
2069		}
2070	}
2071}
2072
2073func (freq *CharFreq) Include(other *CharFreq) {
2074	for i := 0; i < 64; i++ {
2075		(*freq)[i] += (*other)[i]
2076	}
2077}
2078
2079type NameMinifier struct {
2080	head string
2081	tail string
2082}
2083
2084var DefaultNameMinifier = NameMinifier{
2085	head: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$",
2086	tail: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$",
2087}
2088
2089type charAndCount struct {
2090	index byte
2091	count int32
2092	char  string
2093}
2094
2095// This type is just so we can use Go's native sort function
2096type charAndCountArray []charAndCount
2097
2098func (a charAndCountArray) Len() int          { return len(a) }
2099func (a charAndCountArray) Swap(i int, j int) { a[i], a[j] = a[j], a[i] }
2100
2101func (a charAndCountArray) Less(i int, j int) bool {
2102	ai := a[i]
2103	aj := a[j]
2104	return ai.count > aj.count || (ai.count == aj.count && ai.index < aj.index)
2105}
2106
2107func (freq *CharFreq) Compile() NameMinifier {
2108	// Sort the histogram in descending order by count
2109	array := make(charAndCountArray, 64)
2110	for i := 0; i < len(DefaultNameMinifier.tail); i++ {
2111		array[i] = charAndCount{
2112			char:  DefaultNameMinifier.tail[i : i+1],
2113			index: byte(i),
2114			count: freq[i],
2115		}
2116	}
2117	sort.Sort(array)
2118
2119	// Compute the identifier start and identifier continue sequences
2120	minifier := NameMinifier{}
2121	for _, item := range array {
2122		if item.char < "0" || item.char > "9" {
2123			minifier.head += item.char
2124		}
2125		minifier.tail += item.char
2126	}
2127	return minifier
2128}
2129
2130func (minifier *NameMinifier) NumberToMinifiedName(i int) string {
2131	j := i % 54
2132	name := minifier.head[j : j+1]
2133	i = i / 54
2134
2135	for i > 0 {
2136		i--
2137		j := i % 64
2138		name += minifier.tail[j : j+1]
2139		i = i / 64
2140	}
2141
2142	return name
2143}
2144
2145type NamedImport struct {
2146	// Parts within this file that use this import
2147	LocalPartsWithUses []uint32
2148
2149	Alias             string
2150	AliasLoc          logger.Loc
2151	NamespaceRef      Ref
2152	ImportRecordIndex uint32
2153
2154	// If true, the alias refers to the entire export namespace object of a
2155	// module. This is no longer represented as an alias called "*" because of
2156	// the upcoming "Arbitrary module namespace identifier names" feature:
2157	// https://github.com/tc39/ecma262/pull/2154
2158	AliasIsStar bool
2159
2160	// It's useful to flag exported imports because if they are in a TypeScript
2161	// file, we can't tell if they are a type or a value.
2162	IsExported bool
2163}
2164
2165type NamedExport struct {
2166	Ref      Ref
2167	AliasLoc logger.Loc
2168}
2169
2170// Each file is made up of multiple parts, and each part consists of one or
2171// more top-level statements. Parts are used for tree shaking and code
2172// splitting analysis. Individual parts of a file can be discarded by tree
2173// shaking and can be assigned to separate chunks (i.e. output files) by code
2174// splitting.
2175type Part struct {
2176	Stmts  []Stmt
2177	Scopes []*Scope
2178
2179	// Each is an index into the file-level import record list
2180	ImportRecordIndices []uint32
2181
2182	// All symbols that are declared in this part. Note that a given symbol may
2183	// have multiple declarations, and so may end up being declared in multiple
2184	// parts (e.g. multiple "var" declarations with the same name). Also note
2185	// that this list isn't deduplicated and may contain duplicates.
2186	DeclaredSymbols []DeclaredSymbol
2187
2188	// An estimate of the number of uses of all symbols used within this part.
2189	SymbolUses map[Ref]SymbolUse
2190
2191	// The indices of the other parts in this file that are needed if this part
2192	// is needed.
2193	Dependencies []Dependency
2194
2195	// If true, this part can be removed if none of the declared symbols are
2196	// used. If the file containing this part is imported, then all parts that
2197	// don't have this flag enabled must be included.
2198	CanBeRemovedIfUnused bool
2199
2200	// This is used for generated parts that we don't want to be present if they
2201	// aren't needed. This enables tree shaking for these parts even if global
2202	// tree shaking isn't enabled.
2203	ForceTreeShaking bool
2204
2205	// This is true if this file has been marked as live by the tree shaking
2206	// algorithm.
2207	IsLive bool
2208}
2209
2210type Dependency struct {
2211	SourceIndex uint32
2212	PartIndex   uint32
2213}
2214
2215type DeclaredSymbol struct {
2216	Ref        Ref
2217	IsTopLevel bool
2218}
2219
2220type SymbolUse struct {
2221	CountEstimate uint32
2222}
2223
2224// Returns the canonical ref that represents the ref for the provided symbol.
2225// This may not be the provided ref if the symbol has been merged with another
2226// symbol.
2227func FollowSymbols(symbols SymbolMap, ref Ref) Ref {
2228	symbol := symbols.Get(ref)
2229	if symbol.Link == InvalidRef {
2230		return ref
2231	}
2232
2233	link := FollowSymbols(symbols, symbol.Link)
2234
2235	// Only write if needed to avoid concurrent map update hazards
2236	if symbol.Link != link {
2237		symbol.Link = link
2238	}
2239
2240	return link
2241}
2242
2243// Use this before calling "FollowSymbols" from separate threads to avoid
2244// concurrent map update hazards. In Go, mutating a map is not threadsafe
2245// but reading from a map is. Calling "FollowAllSymbols" first ensures that
2246// all mutation is done up front.
2247func FollowAllSymbols(symbols SymbolMap) {
2248	for sourceIndex, inner := range symbols.SymbolsForSource {
2249		for symbolIndex := range inner {
2250			FollowSymbols(symbols, Ref{uint32(sourceIndex), uint32(symbolIndex)})
2251		}
2252	}
2253}
2254
2255// Makes "old" point to "new" by joining the linked lists for the two symbols
2256// together. That way "FollowSymbols" on both "old" and "new" will result in
2257// the same ref.
2258func MergeSymbols(symbols SymbolMap, old Ref, new Ref) Ref {
2259	if old == new {
2260		return new
2261	}
2262
2263	oldSymbol := symbols.Get(old)
2264	if oldSymbol.Link != InvalidRef {
2265		oldSymbol.Link = MergeSymbols(symbols, oldSymbol.Link, new)
2266		return oldSymbol.Link
2267	}
2268
2269	newSymbol := symbols.Get(new)
2270	if newSymbol.Link != InvalidRef {
2271		newSymbol.Link = MergeSymbols(symbols, old, newSymbol.Link)
2272		return newSymbol.Link
2273	}
2274
2275	oldSymbol.Link = new
2276	newSymbol.MergeContentsWith(oldSymbol)
2277	return new
2278}
2279
2280// For readability, the names of certain automatically-generated symbols are
2281// derived from the file name. For example, instead of the CommonJS wrapper for
2282// a file being called something like "require273" it can be called something
2283// like "require_react" instead. This function generates the part of these
2284// identifiers that's specific to the file path. It can take both an absolute
2285// path (OS-specific) and a path in the source code (OS-independent).
2286//
2287// Note that these generated names do not at all relate to the correctness of
2288// the code as far as avoiding symbol name collisions. These names still go
2289// through the renaming logic that all other symbols go through to avoid name
2290// collisions.
2291func GenerateNonUniqueNameFromPath(path string) string {
2292	// Get the file name without the extension
2293	dir, base, _ := logger.PlatformIndependentPathDirBaseExt(path)
2294
2295	// If the name is "index", use the directory name instead. This is because
2296	// many packages in npm use the file name "index.js" because it triggers
2297	// node's implicit module resolution rules that allows you to import it by
2298	// just naming the directory.
2299	if base == "index" {
2300		_, dirBase, _ := logger.PlatformIndependentPathDirBaseExt(dir)
2301		if dirBase != "" {
2302			base = dirBase
2303		}
2304	}
2305
2306	return EnsureValidIdentifier(base)
2307}
2308
2309func EnsureValidIdentifier(base string) string {
2310	// Convert it to an ASCII identifier. Note: If you change this to a non-ASCII
2311	// identifier, you're going to potentially cause trouble with non-BMP code
2312	// points in target environments that don't support bracketed Unicode escapes.
2313	bytes := []byte{}
2314	needsGap := false
2315	for _, c := range base {
2316		if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (len(bytes) > 0 && c >= '0' && c <= '9') {
2317			if needsGap {
2318				bytes = append(bytes, '_')
2319				needsGap = false
2320			}
2321			bytes = append(bytes, byte(c))
2322		} else if len(bytes) > 0 {
2323			needsGap = true
2324		}
2325	}
2326
2327	// Make sure the name isn't empty
2328	if len(bytes) == 0 {
2329		return "_"
2330	}
2331	return string(bytes)
2332}
2333
2334func ConvertBindingToExpr(binding Binding, wrapIdentifier func(logger.Loc, Ref) Expr) Expr {
2335	loc := binding.Loc
2336
2337	switch b := binding.Data.(type) {
2338	case *BMissing:
2339		return Expr{Loc: loc, Data: &EMissing{}}
2340
2341	case *BIdentifier:
2342		if wrapIdentifier != nil {
2343			return wrapIdentifier(loc, b.Ref)
2344		}
2345		return Expr{Loc: loc, Data: &EIdentifier{Ref: b.Ref}}
2346
2347	case *BArray:
2348		exprs := make([]Expr, len(b.Items))
2349		for i, item := range b.Items {
2350			expr := ConvertBindingToExpr(item.Binding, wrapIdentifier)
2351			if b.HasSpread && i+1 == len(b.Items) {
2352				expr = Expr{Loc: expr.Loc, Data: &ESpread{Value: expr}}
2353			} else if item.DefaultValueOrNil.Data != nil {
2354				expr = Assign(expr, item.DefaultValueOrNil)
2355			}
2356			exprs[i] = expr
2357		}
2358		return Expr{Loc: loc, Data: &EArray{
2359			Items:        exprs,
2360			IsSingleLine: b.IsSingleLine,
2361		}}
2362
2363	case *BObject:
2364		properties := make([]Property, len(b.Properties))
2365		for i, property := range b.Properties {
2366			value := ConvertBindingToExpr(property.Value, wrapIdentifier)
2367			kind := PropertyNormal
2368			if property.IsSpread {
2369				kind = PropertySpread
2370			}
2371			properties[i] = Property{
2372				Kind:             kind,
2373				IsComputed:       property.IsComputed,
2374				Key:              property.Key,
2375				ValueOrNil:       value,
2376				InitializerOrNil: property.DefaultValueOrNil,
2377			}
2378		}
2379		return Expr{Loc: loc, Data: &EObject{
2380			Properties:   properties,
2381			IsSingleLine: b.IsSingleLine,
2382		}}
2383
2384	default:
2385		panic("Internal error")
2386	}
2387}
2388