Source File
js_parser.go
Belonging Package
github.com/evanw/esbuild/internal/js_parser
package js_parser
import (
)
type parser struct {
options Options
log logger.Log
source logger.Source
lexer js_lexer.Lexer
allowIn bool
allowPrivateIdentifiers bool
hasTopLevelReturn bool
latestReturnHadSemicolon bool
hasImportMeta bool
hasESModuleSyntax bool
topLevelAwaitKeyword logger.Range
fnOrArrowDataParse fnOrArrowDataParse
fnOrArrowDataVisit fnOrArrowDataVisit
fnOnlyDataVisit fnOnlyDataVisit
allocatedNames []string
latestArrowArgLoc logger.Loc
forbidSuffixAfterAsLoc logger.Loc
currentScope *js_ast.Scope
scopesForCurrentPart []*js_ast.Scope
symbols []js_ast.Symbol
tsUseCounts []uint32
exportsRef js_ast.Ref
requireRef js_ast.Ref
moduleRef js_ast.Ref
importMetaRef js_ast.Ref
promiseRef js_ast.Ref
findSymbolHelper func(loc logger.Loc, name string) js_ast.Ref
symbolForDefineHelper func(int) js_ast.Ref
injectedDefineSymbols []js_ast.Ref
symbolUses map[js_ast.Ref]js_ast.SymbolUse
declaredSymbols []js_ast.DeclaredSymbol
runtimeImports map[string]js_ast.Ref
duplicateCaseChecker duplicateCaseChecker
nonBMPIdentifiers map[string]bool
lackOfDefineWarnings map[string]bool
legacyOctalLiterals map[js_ast.E]logger.Range
es6ImportKeyword logger.Range
es6ExportKeyword logger.Range
enclosingClassKeyword logger.Range
importItemsForNamespace map[js_ast.Ref]map[string]js_ast.LocRef
isImportItem map[js_ast.Ref]bool
namedImports map[js_ast.Ref]js_ast.NamedImport
namedExports map[string]js_ast.NamedExport
topLevelSymbolToParts map[js_ast.Ref][]uint32
afterArrowBodyLoc logger.Loc
}
type thenCatchChain struct {
nextTarget js_ast.E
hasMultipleArgs bool
hasCatch bool
}
type Options struct {
injectedFiles []config.InjectedFile
jsx config.JSXOptions
ts config.TSOptions
mode config.Mode
platform config.Platform
outputFormat config.Format
asciiOnly bool
keepNames bool
mangleSyntax bool
minifyIdentifiers bool
omitRuntimeForTests bool
ignoreDCEAnnotations bool
preserveUnusedImportsTS bool
useDefineForClassFields bool
suppressWarningsAboutWeirdCode bool
}
func ( *config.Options) Options {
return Options{
injectedFiles: .InjectedFiles,
jsx: .JSX,
defines: .Defines,
optionsThatSupportStructuralEquality: optionsThatSupportStructuralEquality{
unsupportedJSFeatures: .UnsupportedJSFeatures,
ts: .TS,
mode: .Mode,
platform: .Platform,
outputFormat: .OutputFormat,
asciiOnly: .ASCIIOnly,
keepNames: .KeepNames,
mangleSyntax: .MangleSyntax,
minifyIdentifiers: .MinifyIdentifiers,
omitRuntimeForTests: .OmitRuntimeForTests,
ignoreDCEAnnotations: .IgnoreDCEAnnotations,
preserveUnusedImportsTS: .PreserveUnusedImportsTS,
useDefineForClassFields: .UseDefineForClassFields,
suppressWarningsAboutWeirdCode: .SuppressWarningsAboutWeirdCode,
},
}
}
if .optionsThatSupportStructuralEquality != .optionsThatSupportStructuralEquality {
return false
}
if len(.injectedFiles) != len(.injectedFiles) {
return false
}
for , := range .injectedFiles {
:= .injectedFiles[]
if .SourceIndex != .SourceIndex || .Path != .Path || !stringArraysEqual(.Exports, .Exports) {
return false
}
}
if (.defines != nil || .defines != nil) && (.defines == nil || .defines == nil ||
len(.defines.IdentifierDefines) != len(.defines.IdentifierDefines) ||
len(.defines.DotDefines) != len(.defines.DotDefines)) {
panic("Internal error")
}
return true
}
func ( []string, []string) bool {
if len() != len() {
return false
}
for , := range {
if != [] {
return false
}
}
return true
}
type tempRef struct {
ref js_ast.Ref
value *js_ast.Expr
}
const (
locModuleScope = -1
)
type scopeOrder struct {
loc logger.Loc
scope *js_ast.Scope
}
type fnOrArrowDataVisit struct {
superIndexRef *js_ast.Ref
isArrow bool
isAsync bool
isInsideLoop bool
isInsideSwitch bool
isThisNested bool
}
const bloomFilterSize = 251
type duplicateCaseValue struct {
hash uint32
value js_ast.Expr
}
type duplicateCaseChecker struct {
bloomFilter [(bloomFilterSize + 7) / 8]byte
cases []duplicateCaseValue
}
:= .bloomFilter
for := range {
[] = 0
}
}
func ( *duplicateCaseChecker) ( *parser, js_ast.Expr) {
if .options.suppressWarningsAboutWeirdCode {
return
}
if , := duplicateCaseHash(); {
:= % bloomFilterSize
:= &.bloomFilter[/8]
:= byte(1) << ( % 8)
if (* & ) != 0 {
for , := range .cases {
if .hash == {
if , := duplicateCaseEquals(.value, ); {
:= .source.RangeOfOperatorBefore(.Loc, "case")
if {
.log.AddRangeWarning(&.source, ,
"This case clause may never be evaluated because it likely duplicates an earlier case clause")
} else {
.log.AddRangeWarning(&.source, ,
"This case clause will never be evaluated because it duplicates an earlier case clause")
}
}
return
}
}
}
* |=
.cases = append(.cases, duplicateCaseValue{hash: , value: })
}
}
func ( uint32, uint32) uint32 {
return ^ ( + 0x9e3779b9 + ( << 6) + ( >> 2))
}
func ( js_ast.Expr) (uint32, bool) {
switch e := .Data.(type) {
case *js_ast.ENull:
return 0, true
case *js_ast.EUndefined:
return 1, true
case *js_ast.EBoolean:
if .Value {
return hashCombine(2, 1), true
}
return hashCombine(2, 0), true
case *js_ast.ENumber:
:= math.Float64bits(.Value)
return hashCombine(hashCombine(3, uint32()), uint32(>>32)), true
case *js_ast.EString:
:= uint32(4)
for , := range .Value {
= hashCombine(, uint32())
}
return , true
case *js_ast.EBigInt:
:= uint32(5)
for , := range .Value {
= hashCombine(, uint32())
}
return , true
case *js_ast.EIdentifier:
return hashCombine(6, .Ref.InnerIndex), true
case *js_ast.EDot:
if , := (.Target); {
:= hashCombine(7, )
for , := range .Name {
= hashCombine(, uint32())
}
return , true
}
case *js_ast.EIndex:
if , := (.Target); {
if , := (.Index); {
return hashCombine(hashCombine(8, ), ), true
}
}
}
return 0, false
}
func ( js_ast.Expr, js_ast.Expr) ( bool, bool) {
switch a := .Data.(type) {
case *js_ast.ENull:
, := .Data.(*js_ast.ENull)
return , false
case *js_ast.EUndefined:
, := .Data.(*js_ast.EUndefined)
return , false
case *js_ast.EBoolean:
, := .Data.(*js_ast.EBoolean)
return && .Value == .Value, false
case *js_ast.ENumber:
, := .Data.(*js_ast.ENumber)
return && .Value == .Value, false
case *js_ast.EString:
, := .Data.(*js_ast.EString)
return && js_lexer.UTF16EqualsUTF16(.Value, .Value), false
case *js_ast.EBigInt:
, := .Data.(*js_ast.EBigInt)
return && .Value == .Value, false
case *js_ast.EIdentifier:
, := .Data.(*js_ast.EIdentifier)
return && .Ref == .Ref, false
case *js_ast.EDot:
if , := .Data.(*js_ast.EDot); && .OptionalChain == .OptionalChain && .Name == .Name {
, := (.Target, .Target)
return , true
}
case *js_ast.EIndex:
if , := .Data.(*js_ast.EIndex); && .OptionalChain == .OptionalChain {
if , := (.Index, .Index); {
, := (.Target, .Target)
return , true
}
}
}
return false, false
}
func ( js_ast.S) bool {
switch .(type) {
case *js_ast.SBreak, *js_ast.SContinue, *js_ast.SReturn, *js_ast.SThrow:
return true
}
return false
}
func ( js_ast.E) bool {
switch .(type) {
case *js_ast.ENull, *js_ast.EUndefined, *js_ast.EString, *js_ast.EBoolean, *js_ast.ENumber, *js_ast.EBigInt:
return true
}
return false
}
type sideEffects uint8
const (
couldHaveSideEffects sideEffects = iota
noSideEffects
)
func ( js_ast.E) ( bool, sideEffects, bool) {
case *js_ast.ENull, *js_ast.EUndefined:
return true, noSideEffects, true
case *js_ast.EUnary:
switch .Op {
js_ast.UnOpNot, js_ast.UnOpTypeof, js_ast.UnOpDelete:
return false, couldHaveSideEffects, true
js_ast.BinOpSub, js_ast.BinOpMul, js_ast.BinOpDiv, js_ast.BinOpRem, js_ast.BinOpPow,
js_ast.BinOpSubAssign, js_ast.BinOpMulAssign, js_ast.BinOpDivAssign, js_ast.BinOpRemAssign, js_ast.BinOpPowAssign,
js_ast.BinOpShl, js_ast.BinOpShr, js_ast.BinOpUShr,
js_ast.BinOpShlAssign, js_ast.BinOpShrAssign, js_ast.BinOpUShrAssign,
js_ast.BinOpBitwiseOr, js_ast.BinOpBitwiseAnd, js_ast.BinOpBitwiseXor,
js_ast.BinOpLt, js_ast.BinOpLe, js_ast.BinOpGt, js_ast.BinOpGe, js_ast.BinOpIn, js_ast.BinOpInstanceof,
js_ast.BinOpLooseEq, js_ast.BinOpLooseNe, js_ast.BinOpStrictEq, js_ast.BinOpStrictNe:
return false, couldHaveSideEffects, true
case js_ast.BinOpComma:
if , , := (.Right.Data); {
return , couldHaveSideEffects, true
}
}
}
return false, noSideEffects, false
}
func ( js_ast.E) ( bool, sideEffects, bool) {
switch e := .(type) {
case *js_ast.ENull, *js_ast.EUndefined:
return false, noSideEffects, true
case *js_ast.EBoolean:
return .Value, noSideEffects, true
case *js_ast.ENumber:
return .Value != 0 && !math.IsNaN(.Value), noSideEffects, true
case *js_ast.EBigInt:
return .Value != "0", noSideEffects, true
case *js_ast.EString:
return len(.Value) > 0, noSideEffects, true
case *js_ast.EFunction, *js_ast.EArrow, *js_ast.ERegExp:
return true, noSideEffects, true
case *js_ast.EObject, *js_ast.EArray, *js_ast.EClass:
return true, couldHaveSideEffects, true
case *js_ast.EUnary:
switch .Op {
case js_ast.UnOpVoid:
return false, couldHaveSideEffects, true
if , , := (.Right.Data); && {
return true, couldHaveSideEffects, true
}
if , , := (.Right.Data); && ! {
return false, couldHaveSideEffects, true
}
if , , := (.Right.Data); {
return , couldHaveSideEffects, true
}
}
}
return false, couldHaveSideEffects, false
}
func ( js_ast.E) (float64, bool) {
switch e := .(type) {
case *js_ast.ENull:
return 0, true
case *js_ast.EUndefined:
return math.NaN(), true
case *js_ast.EBoolean:
if .Value {
return 1, true
} else {
return 0, true
}
case *js_ast.ENumber:
return .Value, true
}
return 0, false
}
func ( js_ast.E) (string, bool) {
switch .(type) {
case *js_ast.ENull:
return "object", true
case *js_ast.EUndefined:
return "undefined", true
case *js_ast.EBoolean:
return "boolean", true
case *js_ast.ENumber:
return "number", true
case *js_ast.EBigInt:
return "bigint", true
case *js_ast.EString:
return "string", true
case *js_ast.EFunction, *js_ast.EArrow:
return "function", true
}
return "", false
}
js_ast.BinOpSub, js_ast.BinOpMul, js_ast.BinOpDiv, js_ast.BinOpRem, js_ast.BinOpPow,
js_ast.BinOpSubAssign, js_ast.BinOpMulAssign, js_ast.BinOpDivAssign, js_ast.BinOpRemAssign, js_ast.BinOpPowAssign,
js_ast.BinOpShl, js_ast.BinOpShr, js_ast.BinOpUShr,
js_ast.BinOpShlAssign, js_ast.BinOpShrAssign, js_ast.BinOpUShrAssign,
js_ast.BinOpBitwiseOr, js_ast.BinOpBitwiseAnd, js_ast.BinOpBitwiseXor,
js_ast.BinOpBitwiseOrAssign, js_ast.BinOpBitwiseAndAssign, js_ast.BinOpBitwiseXorAssign:
return true
case js_ast.BinOpLogicalAnd, js_ast.BinOpLogicalOr, js_ast.BinOpNullishCoalescing,
js_ast.BinOpLogicalAndAssign, js_ast.BinOpLogicalOrAssign, js_ast.BinOpNullishCoalescingAssign:
return (.Left.Data) && (.Right.Data)
case js_ast.BinOpComma:
return (.Right.Data)
}
case *js_ast.EIf:
return (.Yes.Data) && (.No.Data)
}
return false
}
func ( js_ast.E, js_ast.E) (bool, bool) {
switch l := .(type) {
case *js_ast.ENull:
, := .(*js_ast.ENull)
return ,
case *js_ast.EUndefined:
, := .(*js_ast.EUndefined)
return ,
case *js_ast.EBoolean:
, := .(*js_ast.EBoolean)
return && .Value == .Value,
case *js_ast.ENumber:
, := .(*js_ast.ENumber)
return && .Value == .Value,
case *js_ast.EBigInt:
, := .(*js_ast.EBigInt)
return && .Value == .Value,
case *js_ast.EString:
, := .(*js_ast.EString)
return && js_lexer.UTF16EqualsUTF16(.Value, .Value),
}
return false, false
}
func ( js_ast.E, js_ast.E) bool {
switch a := .(type) {
case *js_ast.EIdentifier:
if , := .(*js_ast.EIdentifier); && .Ref == .Ref {
return true
}
case *js_ast.EDot:
if , := .(*js_ast.EDot); && .HasSameFlagsAs() &&
.Name == .Name && (.Target.Data, .Target.Data) {
return true
}
case *js_ast.EIndex:
if , := .(*js_ast.EIndex); && .HasSameFlagsAs() &&
(.Target.Data, .Target.Data) && (.Index.Data, .Index.Data) {
return true
}
case *js_ast.EIf:
if , := .(*js_ast.EIf); && (.Test.Data, .Test.Data) &&
(.Yes.Data, .Yes.Data) && (.No.Data, .No.Data) {
return true
}
case *js_ast.EUnary:
if , := .(*js_ast.EUnary); && .Op == .Op && (.Value.Data, .Value.Data) {
return true
}
case *js_ast.EBinary:
if , := .(*js_ast.EBinary); && .Op == .Op && (.Left.Data, .Left.Data) &&
(.Right.Data, .Right.Data) {
return true
}
case *js_ast.ECall:
if , := .(*js_ast.ECall); && .HasSameFlagsAs() &&
len(.Args) == len(.Args) && (.Target.Data, .Target.Data) {
for := range .Args {
if !(.Args[].Data, .Args[].Data) {
return false
}
}
return true
}
}
, := checkEqualityIfNoSideEffects(, )
return &&
}
func ( js_ast.S, js_ast.S) bool {
switch a := .(type) {
case *js_ast.SBreak:
, := .(*js_ast.SBreak)
return && (.Label == nil) == (.Label == nil) && (.Label == nil || .Label.Ref == .Label.Ref)
case *js_ast.SContinue:
, := .(*js_ast.SContinue)
return && (.Label == nil) == (.Label == nil) && (.Label == nil || .Label.Ref == .Label.Ref)
case *js_ast.SReturn:
, := .(*js_ast.SReturn)
return && (.Value == nil) == (.Value == nil) && (.Value == nil || valuesLookTheSame(.Value.Data, .Value.Data))
case *js_ast.SThrow:
, := .(*js_ast.SThrow)
return && valuesLookTheSame(.Value.Data, .Value.Data)
}
return false
}
func ( js_ast.Expr) bool {
switch .Data.(type) {
case *js_ast.EDot, *js_ast.EIndex:
return true
default:
return false
}
}
if .options.mode == config.ModeBundle && .currentScope.Parent == nil {
return js_ast.LocalVar
}
if .options.mode == config.ModeBundle && == js_ast.LocalConst && .options.mangleSyntax {
return js_ast.LocalLet
}
return
}
func ( *parser) ( js_ast.ScopeKind, logger.Loc) int {
:= .currentScope
:= &js_ast.Scope{
Kind: ,
Parent: ,
Members: make(map[string]js_ast.ScopeMember),
LabelRef: js_ast.InvalidRef,
}
if != nil {
.Children = append(.Children, )
.StrictMode = .StrictMode
}
.currentScope =
if len(.scopesInOrder) > 0 {
:= .scopesInOrder[len(.scopesInOrder)-1].loc.Start
if >= .Start {
panic(fmt.Sprintf("Scope location %d must be greater than %d", .Start, ))
}
}
if == js_ast.ScopeFunctionBody {
if .Parent.Kind != js_ast.ScopeFunctionArgs {
panic("Internal error")
}
:= .symbols[.Ref.InnerIndex].Kind
if != js_ast.SymbolHoistedFunction {
.Members[] =
}
}
}
:= len(.scopesInOrder)
.scopesInOrder = append(.scopesInOrder, scopeOrder{, })
return
}
if .options.mode == config.ModeBundle && .currentScope.Parent == nil &&
.symbols[.Ref.InnerIndex].Kind == js_ast.SymbolImport {
continue
}
.symbols[.Ref.InnerIndex].MustNotBeRenamed = true
}
}
.currentScope = .currentScope.Parent
}
:= .currentScope
:= .Parent
.currentScope =
.scopesInOrder = .scopesInOrder[:]
:= .currentScope
:= .Parent
.currentScope =
copy(.scopesInOrder[:], .scopesInOrder[+1:])
.scopesInOrder = .scopesInOrder[:len(.scopesInOrder)-1]
:= .currentScope.Children
for , := range .scopesInOrder[:] {
if .scope.Parent == .currentScope {
for := len() - 1; >= 0; -- {
if [] == .scope {
= append([:], [+1:]...)
break
}
}
}
}
.currentScope.Children =
.scopesInOrder = .scopesInOrder[:]
}
func ( *parser) ( js_ast.SymbolKind, string) js_ast.Ref {
:= js_ast.Ref{OuterIndex: .source.Index, InnerIndex: uint32(len(.symbols))}
.symbols = append(.symbols, js_ast.Symbol{
Kind: ,
OriginalName: ,
Link: js_ast.InvalidRef,
})
if .options.ts.Parse {
.tsUseCounts = append(.tsUseCounts, 0)
}
return
}
func ( *parser) ( js_ast.Ref, js_ast.Ref) {
:= &.symbols[.InnerIndex]
:= &.symbols[.InnerIndex]
.Link =
.UseCountEstimate += .UseCountEstimate
if .MustNotBeRenamed {
.MustNotBeRenamed = true
}
}
type mergeResult int
const (
mergeForbidden = iota
mergeReplaceWithNew
mergeOverwriteWithNew
mergeKeepExisting
mergeBecomePrivateGetSetPair
mergeBecomePrivateStaticGetSetPair
)
func ( *parser) ( *js_ast.Scope, js_ast.SymbolKind, js_ast.SymbolKind) mergeResult {
if == js_ast.SymbolUnbound {
return mergeReplaceWithNew
}
if .options.ts.Parse && == js_ast.SymbolImport {
return mergeReplaceWithNew
}
if == js_ast.SymbolTSEnum && ( == js_ast.SymbolTSEnum || == js_ast.SymbolTSNamespace) {
return mergeReplaceWithNew
}
if == js_ast.SymbolTSNamespace {
switch {
case js_ast.SymbolTSNamespace, js_ast.SymbolHoistedFunction, js_ast.SymbolGeneratorOrAsyncFunction, js_ast.SymbolTSEnum, js_ast.SymbolClass:
return mergeKeepExisting
}
}
if .IsHoistedOrFunction() && .IsHoistedOrFunction() &&
(.Kind == js_ast.ScopeEntry || .Kind == js_ast.ScopeFunctionBody ||
(.IsHoisted() && .IsHoisted())) {
return mergeKeepExisting
}
if ( == js_ast.SymbolPrivateGet && == js_ast.SymbolPrivateSet) ||
( == js_ast.SymbolPrivateSet && == js_ast.SymbolPrivateGet) {
return mergeBecomePrivateGetSetPair
}
if ( == js_ast.SymbolPrivateStaticGet && == js_ast.SymbolPrivateStaticSet) ||
( == js_ast.SymbolPrivateStaticSet && == js_ast.SymbolPrivateStaticGet) {
return mergeBecomePrivateStaticGetSetPair
}
if == js_ast.SymbolCatchIdentifier && == js_ast.SymbolHoisted {
return mergeReplaceWithNew
}
if == js_ast.SymbolArguments && == js_ast.SymbolHoisted {
return mergeKeepExisting
}
if == js_ast.SymbolArguments && != js_ast.SymbolHoisted {
return mergeOverwriteWithNew
}
return mergeForbidden
}
func ( *parser) ( js_ast.SymbolKind, logger.Loc, string) js_ast.Ref {
.checkForNonBMPCodePoint(, )
if .isStrictMode() && js_lexer.StrictModeReservedWords[] {
.markStrictModeFeature(reservedWord, js_lexer.RangeOfIdentifier(.source, ), )
}
:= .newSymbol(, )
if , := .currentScope.Members[]; {
:= &.symbols[.Ref.InnerIndex]
switch .canMergeSymbols(.currentScope, .Kind, ) {
case mergeForbidden:
:= js_lexer.RangeOfIdentifier(.source, )
.log.AddRangeErrorWithNotes(&.source, , fmt.Sprintf("%q has already been declared", ),
[]logger.MsgData{logger.RangeData(&.source, js_lexer.RangeOfIdentifier(.source, .Loc),
fmt.Sprintf("%q was originally declared here", ))})
return .Ref
case mergeKeepExisting:
= .Ref
case mergeReplaceWithNew:
.Link =
case mergeBecomePrivateGetSetPair:
= .Ref
.Kind = js_ast.SymbolPrivateGetSetPair
case mergeBecomePrivateStaticGetSetPair:
= .Ref
.Kind = js_ast.SymbolPrivateStaticGetSetPair
case mergeOverwriteWithNew:
}
}
.currentScope.Members[] = js_ast.ScopeMember{Ref: , Loc: }
return
}
func ( *parser) ( *js_ast.Scope) {
if !.Kind.StopsHoisting() {
:
for , := range .Members {
:= &.symbols[.Ref.InnerIndex]
if !.Kind.IsHoisted() {
continue
}
if .StrictMode != js_ast.SloppyMode {
continue
}
:= .newSymbol(js_ast.SymbolHoisted, .OriginalName)
.Generated = append(.Generated, )
if .hoistedRefForSloppyModeBlockFn == nil {
.hoistedRefForSloppyModeBlockFn = make(map[js_ast.Ref]js_ast.Ref)
}
.hoistedRefForSloppyModeBlockFn[.Ref] =
= &.symbols[.InnerIndex]
.Ref =
= true
}
:= .Parent
if .Kind == js_ast.ScopeWith {
.MustNotBeRenamed = true
}
if , := .Members[.OriginalName]; {
:= &.symbols[.Ref.InnerIndex]
if .Kind == js_ast.SymbolUnbound || .Kind == js_ast.SymbolHoisted ||
.Link = .Ref
.Members[.OriginalName] =
continue
}
if .Kind != js_ast.SymbolCatchIdentifier && .Kind != js_ast.SymbolHoistedFunction {
if ! {
:= js_lexer.RangeOfIdentifier(.source, .Loc)
.log.AddRangeErrorWithNotes(&.source, , fmt.Sprintf("%q has already been declared", .OriginalName),
[]logger.MsgData{logger.RangeData(&.source, js_lexer.RangeOfIdentifier(.source, .Loc),
fmt.Sprintf("%q was originally declared here", .OriginalName))})
delete(.hoistedRefForSloppyModeBlockFn, )
}
}
continue
}
.Link = .Ref
.Members[.OriginalName] =
}
.Members[.OriginalName] =
break
}
= .Parent
}
}
}
for , := range .Children {
.()
}
}
func ( *parser) ( js_ast.SymbolKind, js_ast.Binding, parseStmtOpts) {
switch b := .Data.(type) {
case *js_ast.BMissing:
case *js_ast.BIdentifier:
:= .loadNameFromRef(.Ref)
if !.isTypeScriptDeclare || (.isNamespaceScope && .isExport) {
.Ref = .declareSymbol(, .Loc, )
}
case *js_ast.BArray:
for , := range .Items {
.(, .Binding, )
}
case *js_ast.BObject:
for , := range .Properties {
.(, .Value, )
}
default:
panic("Internal error")
}
}
if !.isControlFlowDead {
.symbols[.InnerIndex].UseCountEstimate++
:= .symbolUses[]
.CountEstimate++
.symbolUses[] =
}
if .options.ts.Parse {
.tsUseCounts[.InnerIndex]++
}
}
if !.isControlFlowDead {
.symbols[.InnerIndex].UseCountEstimate--
:= .symbolUses[]
.CountEstimate--
if .CountEstimate == 0 {
delete(.symbolUses, )
} else {
.symbolUses[] =
}
}
}
func ( *parser) ( logger.Loc, string, []js_ast.Expr) js_ast.Expr {
, := .runtimeImports[]
if ! {
= .newSymbol(js_ast.SymbolOther, )
.moduleScope.Generated = append(.moduleScope.Generated, )
.runtimeImports[] =
}
.recordUsage()
return js_ast.Expr{Loc: , Data: &js_ast.ECall{
Target: js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }},
Args: ,
}}
}
func ( *parser) () js_ast.Ref {
if .promiseRef == js_ast.InvalidRef {
.promiseRef = .newSymbol(js_ast.SymbolUnbound, "Promise")
}
return .promiseRef
}
return js_ast.Ref{OuterIndex: -uint32(.Len), InnerIndex: uint32(.Data - .Data)}
:= js_ast.Ref{OuterIndex: 0x80000000, InnerIndex: uint32(len(.allocatedNames))}
.allocatedNames = append(.allocatedNames, )
return
}
}
func ( *parser) ( js_ast.Ref) string {
if .OuterIndex == 0x80000000 {
return .allocatedNames[.InnerIndex]
} else {
if (.OuterIndex & 0x80000000) == 0 {
panic("Internal error: invalid symbol reference")
}
return .source.Contents[.InnerIndex : int32(.InnerIndex)-int32(.OuterIndex)]
}
}
invalidExprDefaultValue logger.Range
invalidExprAfterQuestion logger.Range
arraySpreadFeature logger.Range
}
func ( *deferredErrors) ( *deferredErrors) {
if .invalidExprDefaultValue.Len > 0 {
.invalidExprDefaultValue = .invalidExprDefaultValue
}
if .invalidExprAfterQuestion.Len > 0 {
.invalidExprAfterQuestion = .invalidExprAfterQuestion
}
if .arraySpreadFeature.Len > 0 {
.arraySpreadFeature = .arraySpreadFeature
}
}
func ( *parser) ( *deferredErrors) {
if .invalidExprDefaultValue.Len > 0 {
.log.AddRangeError(&.source, .invalidExprDefaultValue, "Unexpected \"=\"")
}
if .invalidExprAfterQuestion.Len > 0 {
:= .invalidExprAfterQuestion
.log.AddRangeError(&.source, , fmt.Sprintf("Unexpected %q", .source.Contents[.Loc.Start:.Loc.Start+.Len]))
}
if .arraySpreadFeature.Len > 0 {
.markSyntaxFeature(compat.ArraySpread, .arraySpreadFeature)
}
}
type deferredArrowArgErrors struct {
invalidExprAwait logger.Range
invalidExprYield logger.Range
}
func ( *parser) ( *deferredArrowArgErrors) {
if .invalidExprAwait.Len > 0 {
:= .invalidExprAwait
.log.AddRangeError(&.source, , "Cannot use an \"await\" expression here")
}
if .invalidExprYield.Len > 0 {
:= .invalidExprYield
.log.AddRangeError(&.source, , "Cannot use a \"yield\" expression here")
}
}
func ( *parser) ( js_ast.Expr) string {
switch k := .Data.(type) {
case *js_ast.EString:
return fmt.Sprintf("%q", js_lexer.UTF16ToString(.Value))
case *js_ast.EPrivateIdentifier:
return fmt.Sprintf("%q", .loadNameFromRef(.Ref))
}
return "property"
}
func ( *parser) ( js_ast.E) {
if .lexer.IsLegacyOctalLiteral {
if .legacyOctalLiterals == nil {
.legacyOctalLiterals = make(map[js_ast.E]logger.Range)
}
.legacyOctalLiterals[] = .lexer.Range()
}
}
func ( *parser) () js_ast.Expr {
var logger.Loc
:= .lexer.Loc()
if .lexer.LegacyOctalLoc.Start > .Start {
= .lexer.LegacyOctalLoc
}
:= js_ast.Expr{Loc: , Data: &js_ast.EString{
Value: .lexer.StringLiteral,
LegacyOctalLoc: ,
PreferTemplate: .lexer.Token == js_lexer.TNoSubstitutionTemplateLiteral,
}}
.lexer.Next()
return
}
type propertyOpts struct {
asyncRange logger.Range
isAsync bool
isGenerator bool
isStatic bool
isClass bool
classHasExtends bool
allowTSDecorators bool
tsDecorators []js_ast.Expr
}
func ( *parser) ( js_ast.PropertyKind, propertyOpts, *deferredErrors) (js_ast.Property, bool) {
var js_ast.Expr
:= .lexer.Range()
:= false
switch .lexer.Token {
case js_lexer.TNumericLiteral:
= js_ast.Expr{Loc: .lexer.Loc(), Data: &js_ast.ENumber{Value: .lexer.Number}}
.checkForLegacyOctalLiteral(.Data)
.lexer.Next()
case js_lexer.TStringLiteral:
= .parseStringLiteral()
case js_lexer.TBigIntegerLiteral:
= js_ast.Expr{Loc: .lexer.Loc(), Data: &js_ast.EBigInt{Value: .lexer.Identifier}}
.markSyntaxFeature(compat.BigInt, .lexer.Range())
.lexer.Next()
case js_lexer.TPrivateIdentifier:
if !.isClass || len(.tsDecorators) > 0 {
.lexer.Expected(js_lexer.TIdentifier)
}
= js_ast.Expr{Loc: .lexer.Loc(), Data: &js_ast.EPrivateIdentifier{Ref: .storeNameInRef(.lexer.Identifier)}}
.lexer.Next()
case js_lexer.TOpenBracket:
= true
.markSyntaxFeature(compat.ObjectExtensions, .lexer.Range())
.lexer.Next()
:= .lexer.Token == js_lexer.TIdentifier
:= .parseExpr(js_ast.LComma)
return js_ast.Property{}, false
}
}
.lexer.Expect(js_lexer.TCloseBracket)
=
case js_lexer.TAsterisk:
if != js_ast.PropertyNormal || .isGenerator {
.lexer.Unexpected()
}
.lexer.Next()
.isGenerator = true
return .(js_ast.PropertyNormal, , )
default:
:= .lexer.Identifier
:= .lexer.Raw()
:= .lexer.Range()
if !.lexer.IsIdentifierOrKeyword() {
.lexer.Expect(js_lexer.TIdentifier)
}
.lexer.Next()
:= .lexer.IsIdentifierOrKeyword()
if ! {
switch .lexer.Token {
case js_lexer.TOpenBracket, js_lexer.TNumericLiteral, js_lexer.TStringLiteral,
js_lexer.TAsterisk, js_lexer.TPrivateIdentifier:
= true
}
}
if {
switch {
case "get":
if !.isAsync && == {
.markSyntaxFeature(compat.ObjectAccessors, )
return .(js_ast.PropertyGet, , nil)
}
case "set":
if !.isAsync && == {
.markSyntaxFeature(compat.ObjectAccessors, )
return .(js_ast.PropertySet, , nil)
}
case "async":
if !.isAsync && == && !.lexer.HasNewlineBefore {
.isAsync = true
.asyncRange =
.markLoweredSyntaxFeature(compat.AsyncAwait, , compat.Generator)
return .(, , nil)
}
case "static":
if !.isStatic && !.isAsync && .isClass && == {
.isStatic = true
return .(, , nil)
}
if !.isClass && == js_ast.PropertyNormal && .lexer.Token != js_lexer.TColon &&
.lexer.Token != js_lexer.TOpenParen && .lexer.Token != js_lexer.TLessThan && !.isGenerator &&
js_lexer.Keywords[] == js_lexer.T(0) {
if (.fnOrArrowDataParse.allowAwait && == "await") || (.fnOrArrowDataParse.allowYield && == "yield") {
.log.AddRangeError(&.source, , fmt.Sprintf("Cannot use %q as an identifier here", ))
}
:= .storeNameInRef()
:= js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: }}
if .isClass && == js_ast.PropertyNormal && !.isAsync &&
!.isGenerator && .lexer.Token != js_lexer.TOpenParen {
var *js_ast.Expr
if ! {
if , := .Data.(*js_ast.EString); && (js_lexer.UTF16EqualsString(.Value, "constructor") ||
(.isStatic && js_lexer.UTF16EqualsString(.Value, "prototype"))) {
.log.AddRangeError(&.source, , fmt.Sprintf("Invalid field name %q", js_lexer.UTF16ToString(.Value)))
}
}
if , := .Data.(*js_ast.EPrivateIdentifier); {
:= .loadNameFromRef(.Ref)
if == "#constructor" {
.log.AddRangeError(&.source, , fmt.Sprintf("Invalid field name %q", ))
}
var js_ast.SymbolKind
if .isStatic {
= js_ast.SymbolPrivateStaticField
} else {
= js_ast.SymbolPrivateField
}
.Ref = .declareSymbol(, .Loc, )
}
.lexer.ExpectOrInsertSemicolon()
return js_ast.Property{
TSDecorators: .tsDecorators,
Kind: ,
IsComputed: ,
IsStatic: .isStatic,
Key: ,
Initializer: ,
}, true
}
if .lexer.Token == js_lexer.TOpenParen || != js_ast.PropertyNormal ||
.isClass || .isAsync || .isGenerator {
if .lexer.Token == js_lexer.TOpenParen && != js_ast.PropertyGet && != js_ast.PropertySet {
.markSyntaxFeature(compat.ObjectExtensions, .lexer.Range())
}
:= .lexer.Loc()
:= .pushScopeForParsePass(js_ast.ScopeFunctionArgs, )
:= false
if .isClass && ! {
if , := .Data.(*js_ast.EString); {
if !.isStatic && js_lexer.UTF16EqualsString(.Value, "constructor") {
switch {
case == js_ast.PropertyGet:
.log.AddRangeError(&.source, , "Class constructor cannot be a getter")
case == js_ast.PropertySet:
.log.AddRangeError(&.source, , "Class constructor cannot be a setter")
case .isAsync:
.log.AddRangeError(&.source, , "Class constructor cannot be an async function")
case .isGenerator:
.log.AddRangeError(&.source, , "Class constructor cannot be a generator")
default:
= true
}
} else if .isStatic && js_lexer.UTF16EqualsString(.Value, "prototype") {
.log.AddRangeError(&.source, , "Invalid static method name \"prototype\"")
}
}
}
, := .parseFn(nil, fnOrArrowDataParse{
asyncRange: .asyncRange,
allowAwait: .isAsync,
allowYield: .isGenerator,
allowSuperCall: .classHasExtends && ,
allowTSDecorators: .allowTSDecorators,
isConstructor: ,
allowMissingBodyForTypeScript: .options.ts.Parse && .isClass,
})
switch {
case js_ast.PropertyGet:
if len(.Args) > 0 {
:= js_lexer.RangeOfIdentifier(.source, .Args[0].Binding.Loc)
.log.AddRangeError(&.source, , fmt.Sprintf("Getter %s must have zero arguments", .keyNameForError()))
}
case js_ast.PropertySet:
if len(.Args) != 1 {
:= js_lexer.RangeOfIdentifier(.source, .Loc)
if len(.Args) > 1 {
= js_lexer.RangeOfIdentifier(.source, .Args[1].Binding.Loc)
}
.log.AddRangeError(&.source, , fmt.Sprintf("Setter %s must have exactly one argument", .keyNameForError()))
}
}
if , := .Data.(*js_ast.EPrivateIdentifier); {
var js_ast.SymbolKind
var string
switch {
case js_ast.PropertyGet:
if .isStatic {
= js_ast.SymbolPrivateStaticGet
} else {
= js_ast.SymbolPrivateGet
}
= "_get"
case js_ast.PropertySet:
if .isStatic {
= js_ast.SymbolPrivateStaticSet
} else {
= js_ast.SymbolPrivateSet
}
= "_set"
default:
if .isStatic {
= js_ast.SymbolPrivateStaticMethod
} else {
= js_ast.SymbolPrivateMethod
}
= "_fn"
}
:= .loadNameFromRef(.Ref)
if == "#constructor" {
.log.AddRangeError(&.source, , fmt.Sprintf("Invalid method name %q", ))
}
.Ref = .declareSymbol(, .Loc, )
if .options.unsupportedJSFeatures.Has(.Feature()) {
:= .newSymbol(js_ast.SymbolOther, [1:]+)
if == js_ast.PropertySet {
.privateSetters[.Ref] =
} else {
.privateGetters[.Ref] =
}
}
}
return js_ast.Property{
TSDecorators: .tsDecorators,
Kind: ,
IsComputed: ,
IsMethod: true,
IsStatic: .isStatic,
Key: ,
Value: &,
}, true
}
.lexer.Expect(js_lexer.TColon)
:= .parseExprOrBindings(js_ast.LComma, )
return js_ast.Property{
Kind: ,
IsComputed: ,
Key: ,
Value: &,
}, true
}
func ( *parser) () js_ast.PropertyBinding {
var js_ast.Expr
:= false
switch .lexer.Token {
case js_lexer.TDotDotDot:
.lexer.Next()
:= js_ast.Binding{Loc: .lexer.Loc(), Data: &js_ast.BIdentifier{Ref: .storeNameInRef(.lexer.Identifier)}}
.lexer.Expect(js_lexer.TIdentifier)
return js_ast.PropertyBinding{
IsSpread: true,
Value: ,
}
case js_lexer.TNumericLiteral:
= js_ast.Expr{Loc: .lexer.Loc(), Data: &js_ast.ENumber{Value: .lexer.Number}}
.checkForLegacyOctalLiteral(.Data)
.lexer.Next()
case js_lexer.TStringLiteral:
= .parseStringLiteral()
case js_lexer.TBigIntegerLiteral:
= js_ast.Expr{Loc: .lexer.Loc(), Data: &js_ast.EBigInt{Value: .lexer.Identifier}}
.markSyntaxFeature(compat.BigInt, .lexer.Range())
.lexer.Next()
case js_lexer.TOpenBracket:
= true
.lexer.Next()
= .parseExpr(js_ast.LComma)
.lexer.Expect(js_lexer.TCloseBracket)
default:
:= .lexer.Identifier
:= .lexer.Loc()
if !.lexer.IsIdentifierOrKeyword() {
.lexer.Expect(js_lexer.TIdentifier)
}
.lexer.Next()
= js_ast.Expr{Loc: , Data: &js_ast.EString{Value: js_lexer.StringToUTF16()}}
if .lexer.Token != js_lexer.TColon && .lexer.Token != js_lexer.TOpenParen {
:= .storeNameInRef()
:= js_ast.Binding{Loc: , Data: &js_ast.BIdentifier{Ref: }}
var *js_ast.Expr
if .lexer.Token == js_lexer.TEquals {
.lexer.Next()
:= .parseExpr(js_ast.LComma)
= &
}
return js_ast.PropertyBinding{
Key: ,
Value: ,
DefaultValue: ,
}
}
}
.lexer.Expect(js_lexer.TColon)
:= .parseBinding()
var *js_ast.Expr
if .lexer.Token == js_lexer.TEquals {
.lexer.Next()
:= .parseExpr(js_ast.LComma)
= &
}
return js_ast.PropertyBinding{
IsComputed: ,
Key: ,
Value: ,
DefaultValue: ,
}
}
func ( *parser) ( []js_ast.Arg, fnOrArrowDataParse) *js_ast.EArrow {
:= .lexer.Loc()
if .lexer.HasNewlineBefore {
.log.AddRangeError(&.source, .lexer.Range(), "Unexpected newline before \"=>\"")
panic(js_lexer.LexerPanic{})
}
.lexer.Expect(js_lexer.TEqualsGreaterThan)
for , := range {
.declareBinding(js_ast.SymbolHoisted, .Binding, parseStmtOpts{})
}
.allowSuperCall = .fnOrArrowDataParse.allowSuperCall
if .lexer.Token == js_lexer.TOpenBrace {
:= .parseFnBody()
.afterArrowBodyLoc = .lexer.Loc()
return &js_ast.EArrow{Args: , Body: }
}
.pushScopeForParsePass(js_ast.ScopeFunctionBody, )
defer .popScope()
:= .fnOrArrowDataParse
.fnOrArrowDataParse =
:= .parseExpr(js_ast.LComma)
.fnOrArrowDataParse =
return &js_ast.EArrow{
Args: ,
PreferExpr: true,
Body: js_ast.FnBody{Loc: , Stmts: []js_ast.Stmt{{Loc: .Loc, Data: &js_ast.SReturn{Value: &}}}},
}
}
if !.lexer.HasNewlineBefore && .lexer.Token == js_lexer.TFunction {
return .parseFnExpr(.Loc, true /* isAsync */, )
}
if !.lexer.HasNewlineBefore && < js_ast.LMember {
case js_lexer.TEqualsGreaterThan:
:= js_ast.Arg{Binding: js_ast.Binding{Loc: .Loc, Data: &js_ast.BIdentifier{Ref: .storeNameInRef("async")}}}
.pushScopeForParsePass(js_ast.ScopeFunctionArgs, .Loc)
defer .popScope()
return js_ast.Expr{Loc: .Loc, Data: .parseArrowBody([]js_ast.Arg{}, fnOrArrowDataParse{})}
case js_lexer.TIdentifier:
.markLoweredSyntaxFeature(compat.AsyncAwait, , compat.Generator)
:= .storeNameInRef(.lexer.Identifier)
:= js_ast.Arg{Binding: js_ast.Binding{Loc: .lexer.Loc(), Data: &js_ast.BIdentifier{Ref: }}}
.lexer.Next()
.pushScopeForParsePass(js_ast.ScopeFunctionArgs, .Loc)
defer .popScope()
:= .parseArrowBody([]js_ast.Arg{}, fnOrArrowDataParse{allowAwait: true})
.IsAsync = true
return js_ast.Expr{Loc: .Loc, Data: }
case js_lexer.TOpenParen:
.lexer.Next()
return .parseParenExpr(.Loc, parenExprOpts{isAsync: true, asyncRange: })
case js_lexer.TLessThan:
if .options.ts.Parse && .trySkipTypeScriptTypeParametersThenOpenParenWithBacktracking() {
.lexer.Next()
return .parseParenExpr(.Loc, parenExprOpts{isAsync: true, asyncRange: })
}
}
}
return js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .storeNameInRef("async")}}
}
func ( *parser) ( logger.Loc, bool, logger.Range) js_ast.Expr {
.lexer.Next()
:= .lexer.Token == js_lexer.TAsterisk
if {
.markSyntaxFeature(compat.Generator, .lexer.Range())
.lexer.Next()
} else if {
.markLoweredSyntaxFeature(compat.AsyncAwait, , compat.Generator)
}
var *js_ast.LocRef
.pushScopeForParsePass(js_ast.ScopeFunctionArgs, )
defer .popScope()
= &js_ast.LocRef{Loc: .lexer.Loc()}
if := .lexer.Identifier; != "arguments" {
.Ref = .declareSymbol(js_ast.SymbolHoistedFunction, .Loc, )
} else {
.Ref = .newSymbol(js_ast.SymbolHoistedFunction, )
}
.lexer.Next()
}
if .options.ts.Parse {
.skipTypeScriptTypeParameters()
}
, := .parseFn(, fnOrArrowDataParse{
asyncRange: ,
allowAwait: ,
allowYield: ,
})
return js_ast.Expr{Loc: , Data: &js_ast.EFunction{Fn: }}
}
type parenExprOpts struct {
asyncRange logger.Range
isAsync bool
forceArrowFn bool
}
for .lexer.Token != js_lexer.TCloseParen {
:= .lexer.Loc()
:= .lexer.Token == js_lexer.TDotDotDot
if {
= .lexer.Range()
.markSyntaxFeature(compat.RestArgument, )
.lexer.Next()
}
.allowIn =
if .lexer.Token == js_lexer.TEqualsGreaterThan || .forceArrowFn || (.options.ts.Parse && .lexer.Token == js_lexer.TColon) {
:= []logger.Loc{}
:= []js_ast.Arg{}
if .isAsync {
.markLoweredSyntaxFeature(compat.AsyncAwait, .asyncRange, compat.Generator)
}
if .lexer.Token == js_lexer.TEqualsGreaterThan || (len() == 0 &&
.trySkipTypeScriptArrowReturnTypeWithBacktracking()) || .forceArrowFn {
if .Start != 0 {
.log.AddRangeError(&.source, logger.Range{Loc: , Len: 1}, "Unexpected \",\" after rest pattern")
}
.logArrowArgErrors(&)
if len() > 0 {
for , := range {
.log.AddError(&.source, , "Invalid binding pattern")
}
panic(js_lexer.LexerPanic{})
}
:= .parseArrowBody(, fnOrArrowDataParse{allowAwait: .isAsync})
.IsAsync = .isAsync
.HasRestArg = .Len > 0
.popScope()
return js_ast.Expr{Loc: , Data: }
}
}
if .Len > 0 {
.log.AddRangeError(&.source, , "Unexpected \":\"")
panic(js_lexer.LexerPanic{})
}
if len() > 0 {
.logExprErrors(&)
if .Len > 0 {
.log.AddRangeError(&.source, , "Unexpected \"...\"")
panic(js_lexer.LexerPanic{})
}
:= js_ast.JoinAllWithComma()
.markExprAsParenthesized()
return
}
.lexer.Expected(js_lexer.TEqualsGreaterThan)
return js_ast.Expr{}
}
func ( *parser) ( js_ast.Expr, []logger.Loc, bool) (js_ast.Binding, *js_ast.Expr, []logger.Loc) {
var *js_ast.Expr
if , := .Data.(*js_ast.EBinary); && .Op == js_ast.BinOpAssign {
= &.Right
= .Left
}
, := .convertExprToBinding(, )
if != nil {
:= .source.RangeOfOperatorBefore(.Loc, "=")
if {
.log.AddRangeError(&.source, , "A rest argument cannot have a default initializer")
} else {
.markSyntaxFeature(compat.DefaultArgument, )
}
}
return , ,
}
func ( *parser) ( js_ast.Expr, []logger.Loc) (js_ast.Binding, []logger.Loc) {
switch e := .Data.(type) {
case *js_ast.EMissing:
return js_ast.Binding{Loc: .Loc, Data: &js_ast.BMissing{}},
case *js_ast.EIdentifier:
return js_ast.Binding{Loc: .Loc, Data: &js_ast.BIdentifier{Ref: .Ref}},
case *js_ast.EArray:
if .CommaAfterSpread.Start != 0 {
= append(, .CommaAfterSpread)
}
if .IsParenthesized {
= append(, .source.RangeOfOperatorBefore(.Loc, "(").Loc)
}
.markSyntaxFeature(compat.Destructuring, .source.RangeOfOperatorAfter(.Loc, "["))
:= []js_ast.ArrayBinding{}
:= false
for , := range .Items {
if , := .Data.(*js_ast.ESpread); {
= true
= .Value
if , := .Data.(*js_ast.EIdentifier); ! {
.markSyntaxFeature(compat.NestedRestBinding, .source.RangeOfOperatorAfter(.Loc, "["))
}
}
, , := .convertExprToBindingAndInitializer(, , )
=
= append(, js_ast.ArrayBinding{Binding: , DefaultValue: })
}
return js_ast.Binding{Loc: .Loc, Data: &js_ast.BArray{
Items: ,
HasSpread: ,
IsSingleLine: .IsSingleLine,
}},
case *js_ast.EObject:
if .CommaAfterSpread.Start != 0 {
= append(, .CommaAfterSpread)
}
if .IsParenthesized {
= append(, .source.RangeOfOperatorBefore(.Loc, "(").Loc)
}
.markSyntaxFeature(compat.Destructuring, .source.RangeOfOperatorAfter(.Loc, "{"))
:= []js_ast.PropertyBinding{}
for , := range .Properties {
if .IsMethod || .Kind == js_ast.PropertyGet || .Kind == js_ast.PropertySet {
= append(, .Key.Loc)
continue
}
, , := .convertExprToBindingAndInitializer(*.Value, , false)
=
if == nil {
= .Initializer
}
= append(, js_ast.PropertyBinding{
IsSpread: .Kind == js_ast.PropertySpread,
IsComputed: .IsComputed,
Key: .Key,
Value: ,
DefaultValue: ,
})
}
return js_ast.Binding{Loc: .Loc, Data: &js_ast.BObject{
Properties: ,
IsSingleLine: .IsSingleLine,
}},
default:
= append(, .Loc)
return js_ast.Binding{},
}
}
func ( *parser) ( js_ast.Binding, func(logger.Loc, js_ast.Ref) js_ast.Expr) js_ast.Expr {
:= .Loc
switch b := .Data.(type) {
case *js_ast.BMissing:
return js_ast.Expr{Loc: , Data: &js_ast.EMissing{}}
case *js_ast.BIdentifier:
if != nil {
return (, .Ref)
}
return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: .Ref}}
case *js_ast.BArray:
:= make([]js_ast.Expr, len(.Items))
for , := range .Items {
:= .(.Binding, )
if .HasSpread && +1 == len(.Items) {
= js_ast.Expr{Loc: .Loc, Data: &js_ast.ESpread{Value: }}
} else if .DefaultValue != nil {
= js_ast.Assign(, *.DefaultValue)
}
[] =
}
return js_ast.Expr{Loc: , Data: &js_ast.EArray{
Items: ,
IsSingleLine: .IsSingleLine,
}}
case *js_ast.BObject:
:= make([]js_ast.Property, len(.Properties))
for , := range .Properties {
:= .(.Value, )
:= js_ast.PropertyNormal
if .IsSpread {
= js_ast.PropertySpread
}
[] = js_ast.Property{
Kind: ,
IsComputed: .IsComputed,
Key: .Key,
Value: &,
Initializer: .DefaultValue,
}
}
return js_ast.Expr{Loc: , Data: &js_ast.EObject{
Properties: ,
IsSingleLine: .IsSingleLine,
}}
default:
panic("Internal error")
}
}
type exprFlag uint8
const (
exprFlagTSDecorator exprFlag = 1 << iota
)
func ( *parser) ( js_ast.L, *deferredErrors, exprFlag) js_ast.Expr {
:= .lexer.Loc()
switch .lexer.Token {
case js_lexer.TSuper:
:= .lexer.Range()
.lexer.Next()
switch .lexer.Token {
case js_lexer.TOpenParen:
if < js_ast.LCall && .fnOrArrowDataParse.allowSuperCall {
return js_ast.Expr{Loc: , Data: &js_ast.ESuper{}}
}
case js_lexer.TDot, js_lexer.TOpenBracket:
return js_ast.Expr{Loc: , Data: &js_ast.ESuper{}}
}
.log.AddRangeError(&.source, , "Unexpected \"super\"")
return js_ast.Expr{Loc: , Data: &js_ast.ESuper{}}
case js_lexer.TOpenParen:
.lexer.Next()
:= .allowIn
.allowIn = true
:= .parseExpr(js_ast.LLowest)
.markExprAsParenthesized()
.lexer.Expect(js_lexer.TCloseParen)
.allowIn =
return
}
:= .parseParenExpr(, parenExprOpts{})
return
case js_lexer.TFalse:
.lexer.Next()
return js_ast.Expr{Loc: , Data: &js_ast.EBoolean{Value: false}}
case js_lexer.TTrue:
.lexer.Next()
return js_ast.Expr{Loc: , Data: &js_ast.EBoolean{Value: true}}
case js_lexer.TNull:
.lexer.Next()
return js_ast.Expr{Loc: , Data: &js_ast.ENull{}}
case js_lexer.TThis:
.lexer.Next()
return js_ast.Expr{Loc: , Data: &js_ast.EThis{}}
case js_lexer.TIdentifier:
:= .lexer.Identifier
:= .lexer.Range()
:= .lexer.Raw()
.lexer.Next()
switch {
case "async":
if == "async" {
return .parseAsyncPrefixExpr(, )
}
case "await":
if .fnOrArrowDataParse.allowAwait {
if != "await" {
.log.AddRangeError(&.source, , "The keyword \"await\" cannot be escaped")
} else {
if .fnOrArrowDataParse.isTopLevel {
.topLevelAwaitKeyword =
.markSyntaxFeature(compat.TopLevelAwait, )
}
if .fnOrArrowDataParse.arrowArgErrors != nil {
.fnOrArrowDataParse.arrowArgErrors.invalidExprAwait =
}
:= .parseExpr(js_ast.LPrefix)
if .lexer.Token == js_lexer.TAsteriskAsterisk {
.lexer.Unexpected()
}
return js_ast.Expr{Loc: , Data: &js_ast.EAwait{Value: }}
}
}
case "yield":
if .fnOrArrowDataParse.allowYield {
if != "yield" {
.log.AddRangeError(&.source, , "The keyword \"yield\" cannot be escaped")
} else {
if > js_ast.LAssign {
.log.AddRangeError(&.source, , "Cannot use a \"yield\" expression here without parentheses")
}
if .fnOrArrowDataParse.arrowArgErrors != nil {
.fnOrArrowDataParse.arrowArgErrors.invalidExprYield =
}
return .parseYieldExpr()
}
switch .lexer.Token {
case js_lexer.TNull, js_lexer.TIdentifier, js_lexer.TFalse, js_lexer.TTrue,
js_lexer.TNumericLiteral, js_lexer.TBigIntegerLiteral, js_lexer.TStringLiteral:
.log.AddRangeError(&.source, , "Cannot use \"yield\" outside a generator function")
return .parseYieldExpr()
}
}
}
if .lexer.Token == js_lexer.TEqualsGreaterThan {
:= .storeNameInRef()
:= js_ast.Arg{Binding: js_ast.Binding{Loc: , Data: &js_ast.BIdentifier{Ref: }}}
.pushScopeForParsePass(js_ast.ScopeFunctionArgs, )
defer .popScope()
return js_ast.Expr{Loc: , Data: .parseArrowBody([]js_ast.Arg{}, fnOrArrowDataParse{})}
}
:= .storeNameInRef()
return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}
case js_lexer.TStringLiteral, js_lexer.TNoSubstitutionTemplateLiteral:
return .parseStringLiteral()
case js_lexer.TTemplateHead:
var logger.Loc
:= .lexer.StringLiteral
if .lexer.LegacyOctalLoc.Start > .Start {
= .lexer.LegacyOctalLoc
}
, := .parseTemplateParts(false /* includeRaw */)
if .Start > 0 {
=
}
if .options.unsupportedJSFeatures.Has(compat.TemplateLiteral) {
var js_ast.Expr
= js_ast.Expr{Loc: , Data: &js_ast.EString{
Value: ,
LegacyOctalLoc: ,
}}
}
for , := range {
= js_ast.Expr{Loc: , Data: &js_ast.EBinary{
Op: js_ast.BinOpAdd,
Left: ,
Right: .Value,
}}
if len(.Tail) > 0 {
= js_ast.Expr{Loc: , Data: &js_ast.EBinary{
Op: js_ast.BinOpAdd,
Left: ,
Right: js_ast.Expr{Loc: .TailLoc, Data: &js_ast.EString{Value: .Tail}},
}}
}
}
return
}
return js_ast.Expr{Loc: , Data: &js_ast.ETemplate{
Head: ,
Parts: ,
LegacyOctalLoc: ,
}}
case js_lexer.TNumericLiteral:
:= js_ast.Expr{Loc: , Data: &js_ast.ENumber{Value: .lexer.Number}}
.checkForLegacyOctalLiteral(.Data)
.lexer.Next()
return
case js_lexer.TBigIntegerLiteral:
:= .lexer.Identifier
.markSyntaxFeature(compat.BigInt, .lexer.Range())
.lexer.Next()
return js_ast.Expr{Loc: , Data: &js_ast.EBigInt{Value: }}
case js_lexer.TSlash, js_lexer.TSlashEquals:
.lexer.ScanRegExp()
:= .lexer.Raw()
.lexer.Next()
return js_ast.Expr{Loc: , Data: &js_ast.ERegExp{Value: }}
case js_lexer.TVoid:
.lexer.Next()
:= .parseExpr(js_ast.LPrefix)
if .lexer.Token == js_lexer.TAsteriskAsterisk {
.lexer.Unexpected()
}
return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpVoid, Value: }}
case js_lexer.TTypeof:
.lexer.Next()
:= .parseExpr(js_ast.LPrefix)
if .lexer.Token == js_lexer.TAsteriskAsterisk {
.lexer.Unexpected()
}
return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpTypeof, Value: }}
case js_lexer.TDelete:
.lexer.Next()
:= .parseExpr(js_ast.LPrefix)
if .lexer.Token == js_lexer.TAsteriskAsterisk {
.lexer.Unexpected()
}
if , := .Data.(*js_ast.EIndex); {
if , := .Index.Data.(*js_ast.EPrivateIdentifier); {
:= .loadNameFromRef(.Ref)
:= logger.Range{Loc: .Index.Loc, Len: int32(len())}
.log.AddRangeError(&.source, , fmt.Sprintf("Deleting the private name %q is forbidden", ))
}
}
return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpDelete, Value: }}
case js_lexer.TPlus:
.lexer.Next()
:= .parseExpr(js_ast.LPrefix)
if .lexer.Token == js_lexer.TAsteriskAsterisk {
.lexer.Unexpected()
}
return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpPos, Value: }}
case js_lexer.TMinus:
.lexer.Next()
:= .parseExpr(js_ast.LPrefix)
if .lexer.Token == js_lexer.TAsteriskAsterisk {
.lexer.Unexpected()
}
return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpNeg, Value: }}
case js_lexer.TTilde:
.lexer.Next()
:= .parseExpr(js_ast.LPrefix)
if .lexer.Token == js_lexer.TAsteriskAsterisk {
.lexer.Unexpected()
}
return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpCpl, Value: }}
case js_lexer.TExclamation:
.lexer.Next()
:= .parseExpr(js_ast.LPrefix)
if .lexer.Token == js_lexer.TAsteriskAsterisk {
.lexer.Unexpected()
}
return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpNot, Value: }}
case js_lexer.TMinusMinus:
.lexer.Next()
return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpPreDec, Value: .parseExpr(js_ast.LPrefix)}}
case js_lexer.TPlusPlus:
.lexer.Next()
return js_ast.Expr{Loc: , Data: &js_ast.EUnary{Op: js_ast.UnOpPreInc, Value: .parseExpr(js_ast.LPrefix)}}
case js_lexer.TFunction:
return .parseFnExpr(, false /* isAsync */, logger.Range{})
case js_lexer.TClass:
:= .lexer.Range()
.markSyntaxFeature(compat.Class, )
.lexer.Next()
var *js_ast.LocRef
.pushScopeForParsePass(js_ast.ScopeClassName, )
if .lexer.Token == js_lexer.TIdentifier && !js_lexer.StrictModeReservedWords[.lexer.Identifier] {
= &js_ast.LocRef{Loc: .lexer.Loc(), Ref: .newSymbol(js_ast.SymbolOther, .lexer.Identifier)}
.lexer.Next()
}
if .lexer.Token == js_lexer.TDot {
.lexer.Next()
if .lexer.Token != js_lexer.TIdentifier || .lexer.Identifier != "target" {
.lexer.Unexpected()
}
:= logger.Range{Loc: , Len: .lexer.Range().End() - .Start}
.markSyntaxFeature(compat.NewTarget, )
.lexer.Next()
return js_ast.Expr{Loc: , Data: &js_ast.ENewTarget{}}
}
:= .parseExprWithFlags(js_ast.LMember, )
:= []js_ast.Expr{}
if .lexer.Token == js_lexer.TExclamation && !.lexer.HasNewlineBefore {
.lexer.Next()
}
if .lexer.Token == js_lexer.TLessThan {
.trySkipTypeScriptTypeArgumentsWithBacktracking()
}
}
if .lexer.Token == js_lexer.TOpenParen {
= .parseCallArgs()
}
return js_ast.Expr{Loc: , Data: &js_ast.ENew{Target: , Args: }}
case js_lexer.TOpenBracket:
.lexer.Next()
:= !.lexer.HasNewlineBefore
:= []js_ast.Expr{}
:= deferredErrors{}
:= logger.Loc{}
:= .allowIn
.allowIn = true
for .lexer.Token != js_lexer.TCloseBracket {
switch .lexer.Token {
case js_lexer.TComma:
= append(, js_ast.Expr{Loc: .lexer.Loc(), Data: &js_ast.EMissing{}})
case js_lexer.TDotDotDot:
if != nil {
.arraySpreadFeature = .lexer.Range()
} else {
.markSyntaxFeature(compat.ArraySpread, .lexer.Range())
}
:= .lexer.Loc()
.lexer.Next()
:= .parseExprOrBindings(js_ast.LComma, &)
= append(, js_ast.Expr{Loc: , Data: &js_ast.ESpread{Value: }})
if .lexer.Token == js_lexer.TComma {
= .lexer.Loc()
}
default:
:= .parseExprOrBindings(js_ast.LComma, &)
= append(, )
}
if .lexer.Token != js_lexer.TComma {
break
}
if .lexer.HasNewlineBefore {
= false
}
.lexer.Next()
if .lexer.HasNewlineBefore {
= false
}
}
if .lexer.HasNewlineBefore {
= false
}
.lexer.Expect(js_lexer.TCloseBracket)
.allowIn =
.logExprErrors(&)
.mergeInto()
}
return js_ast.Expr{Loc: , Data: &js_ast.EArray{
Items: ,
CommaAfterSpread: ,
IsSingleLine: ,
}}
case js_lexer.TOpenBrace:
.lexer.Next()
:= !.lexer.HasNewlineBefore
:= []js_ast.Property{}
:= deferredErrors{}
:= logger.Loc{}
if , := .parseProperty(js_ast.PropertyNormal, propertyOpts{}, &); {
= append(, )
}
}
if .lexer.Token != js_lexer.TComma {
break
}
if .lexer.HasNewlineBefore {
= false
}
.lexer.Next()
if .lexer.HasNewlineBefore {
= false
}
}
if .lexer.HasNewlineBefore {
= false
}
.lexer.Expect(js_lexer.TCloseBrace)
.allowIn =
.logExprErrors(&)
.mergeInto()
}
return js_ast.Expr{Loc: , Data: &js_ast.EObject{
Properties: ,
CommaAfterSpread: ,
IsSingleLine: ,
}}
.lexer =
if {
.skipTypeScriptTypeParameters()
.lexer.Expect(js_lexer.TOpenParen)
return .parseParenExpr(, parenExprOpts{forceArrowFn: true})
}
}
.lexer.NextInsideJSXElement()
:= .parseJSXElement()
if .trySkipTypeScriptTypeParametersThenOpenParenWithBacktracking() {
.lexer.Expect(js_lexer.TOpenParen)
return .parseParenExpr(, parenExprOpts{})
}
.lexer.Next()
.skipTypeScriptType(js_ast.LLowest)
.lexer.ExpectGreaterThan(false /* isInsideJSXElement */)
:= .(, , )
return
}
.lexer.Unexpected()
return js_ast.Expr{}
case js_lexer.TImport:
.lexer.Next()
return .parseImportExpr(, )
default:
.lexer.Unexpected()
return js_ast.Expr{}
}
}
switch .lexer.Token {
case js_lexer.TCloseBrace, js_lexer.TCloseBracket, js_lexer.TCloseParen,
js_lexer.TColon, js_lexer.TComma, js_lexer.TSemicolon:
default:
if || !.lexer.HasNewlineBefore {
:= .parseExpr(js_ast.LYield)
= &
}
}
return js_ast.Expr{Loc: , Data: &js_ast.EYield{Value: , IsStar: }}
}
func ( *parser) () bool {
switch .lexer.Token {
return true
return !.allowIn
return !.allowIn && .lexer.IsContextualKeyword("of")
default:
return false
}
}
if .lexer.Token == js_lexer.TDot {
.es6ImportKeyword = js_lexer.RangeOfIdentifier(.source, )
.lexer.Next()
if .lexer.IsContextualKeyword("meta") {
:= .lexer.Range()
.lexer.Next()
.hasImportMeta = true
if .options.unsupportedJSFeatures.Has(compat.ImportMeta) {
= logger.Range{Loc: , Len: .End() - .Start}
.markSyntaxFeature(compat.ImportMeta, )
}
return js_ast.Expr{Loc: , Data: &js_ast.EImportMeta{}}
} else {
.lexer.ExpectedString("\"meta\"")
}
}
if > js_ast.LCall {
:= js_lexer.RangeOfIdentifier(.source, )
.log.AddRangeError(&.source, , "Cannot use an \"import\" expression here without parentheses")
}
:= .allowIn
.allowIn = true
.lexer.PreserveAllCommentsBefore = true
.lexer.Expect(js_lexer.TOpenParen)
:= .lexer.CommentsToPreserveBefore
.lexer.PreserveAllCommentsBefore = false
:= .parseExpr(js_ast.LComma)
.lexer.Expect(js_lexer.TCloseParen)
.allowIn =
return js_ast.Expr{Loc: , Data: &js_ast.EImport{Expr: , LeadingInteriorComments: }}
}
func ( *parser) ( js_ast.L, *deferredErrors) js_ast.Expr {
return .parseExprCommon(, , 0)
}
func ( *parser) ( js_ast.L) js_ast.Expr {
return .parseExprCommon(, nil, 0)
}
func ( *parser) ( js_ast.L, exprFlag) js_ast.Expr {
return .parseExprCommon(, nil, )
}
func ( *parser) ( js_ast.L, *deferredErrors, exprFlag) js_ast.Expr {
:= .lexer.HasPureCommentBefore && !.options.ignoreDCEAnnotations
:= .parsePrefix(, , )
if && < js_ast.LCall {
= .parseSuffix(, js_ast.LCall-1, , )
switch e := .Data.(type) {
case *js_ast.ECall:
.CanBeUnwrappedIfUnused = true
case *js_ast.ENew:
.CanBeUnwrappedIfUnused = true
}
}
return .parseSuffix(, , , )
}
func ( *parser) ( js_ast.Expr, js_ast.L, *deferredErrors, exprFlag) js_ast.Expr {
:= js_ast.OptionalChainNone
for {
if .lexer.Loc() == .afterArrowBodyLoc {
for {
switch .lexer.Token {
case js_lexer.TComma:
if >= js_ast.LComma {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpComma, Left: , Right: .parseExpr(js_ast.LComma)}}
default:
return
}
}
}
if .lexer.Loc() == .forbidSuffixAfterAsLoc {
return
}
if >= js_ast.LCall {
return
}
= js_ast.Expr{Loc: .Loc, Data: &js_ast.ECall{
Target: ,
Args: .parseCallArgs(),
OptionalChain: js_ast.OptionalChainStart,
}}
if !.options.ts.Parse {
.lexer.Expected(js_lexer.TIdentifier)
}
.skipTypeScriptTypeArguments(false /* isInsideJSXElement */)
if .lexer.Token != js_lexer.TOpenParen {
.lexer.Expected(js_lexer.TOpenParen)
}
if >= js_ast.LCall {
return
}
= js_ast.Expr{Loc: .Loc, Data: &js_ast.ECall{
Target: ,
Args: .parseCallArgs(),
OptionalChain: js_ast.OptionalChainStart,
}}
default:
if !.lexer.IsIdentifierOrKeyword() {
.lexer.Expect(js_lexer.TIdentifier)
}
:= .lexer.Identifier
:= .lexer.Loc()
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
Target: ,
Name: ,
NameLoc: ,
OptionalChain: js_ast.OptionalChainStart,
}}
}
}
= js_ast.OptionalChainContinue
case js_lexer.TNoSubstitutionTemplateLiteral:
if != js_ast.OptionalChainNone {
.log.AddRangeError(&.source, .lexer.Range(), "Template literals cannot have an optional chain as a tag")
}
.markSyntaxFeature(compat.TemplateLiteral, .lexer.Range())
:= .lexer.StringLiteral
:= .lexer.RawTemplateContents()
.lexer.Next()
:=
= js_ast.Expr{Loc: .Loc, Data: &js_ast.ETemplate{Tag: &, Head: , HeadRaw: }}
case js_lexer.TTemplateHead:
if != js_ast.OptionalChainNone {
.log.AddRangeError(&.source, .lexer.Range(), "Template literals cannot have an optional chain as a tag")
}
.markSyntaxFeature(compat.TemplateLiteral, .lexer.Range())
:= .lexer.StringLiteral
:= .lexer.RawTemplateContents()
, := .parseTemplateParts(true /* includeRaw */)
:=
= js_ast.Expr{Loc: .Loc, Data: &js_ast.ETemplate{Tag: &, Head: , HeadRaw: , Parts: }}
if ( & exprFlagTSDecorator) != 0 {
return
}
.lexer.Next()
:= .allowIn
.allowIn = true
:= .parseExpr(js_ast.LLowest)
.allowIn =
.lexer.Expect(js_lexer.TCloseBracket)
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EIndex{
Target: ,
Index: ,
OptionalChain: ,
}}
=
case js_lexer.TOpenParen:
if >= js_ast.LCall {
return
}
= js_ast.Expr{Loc: .Loc, Data: &js_ast.ECall{
Target: ,
Args: .parseCallArgs(),
OptionalChain: ,
}}
=
case js_lexer.TQuestion:
if >= js_ast.LConditional {
return
}
.lexer.Next()
if .lexer.HasNewlineBefore {
return
}
if !.options.ts.Parse {
.lexer.Unexpected()
}
if >= js_ast.LPostfix {
return
}
.lexer.Next()
=
case js_lexer.TMinusMinus:
if .lexer.HasNewlineBefore || >= js_ast.LPostfix {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EUnary{Op: js_ast.UnOpPostDec, Value: }}
case js_lexer.TPlusPlus:
if .lexer.HasNewlineBefore || >= js_ast.LPostfix {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EUnary{Op: js_ast.UnOpPostInc, Value: }}
case js_lexer.TComma:
if >= js_ast.LComma {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpComma, Left: , Right: .parseExpr(js_ast.LComma)}}
case js_lexer.TPlus:
if >= js_ast.LAdd {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpAdd, Left: , Right: .parseExpr(js_ast.LAdd)}}
case js_lexer.TPlusEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpAddAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TMinus:
if >= js_ast.LAdd {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpSub, Left: , Right: .parseExpr(js_ast.LAdd)}}
case js_lexer.TMinusEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpSubAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TAsterisk:
if >= js_ast.LMultiply {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpMul, Left: , Right: .parseExpr(js_ast.LMultiply)}}
case js_lexer.TAsteriskAsterisk:
if >= js_ast.LExponentiation {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpPow, Left: , Right: .parseExpr(js_ast.LExponentiation - 1)}}
case js_lexer.TAsteriskAsteriskEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpPowAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TAsteriskEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpMulAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TPercent:
if >= js_ast.LMultiply {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpRem, Left: , Right: .parseExpr(js_ast.LMultiply)}}
case js_lexer.TPercentEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpRemAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TSlash:
if >= js_ast.LMultiply {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpDiv, Left: , Right: .parseExpr(js_ast.LMultiply)}}
case js_lexer.TSlashEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpDivAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TEqualsEquals:
if >= js_ast.LEquals {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLooseEq, Left: , Right: .parseExpr(js_ast.LEquals)}}
case js_lexer.TExclamationEquals:
if >= js_ast.LEquals {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLooseNe, Left: , Right: .parseExpr(js_ast.LEquals)}}
case js_lexer.TEqualsEqualsEquals:
if >= js_ast.LEquals {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpStrictEq, Left: , Right: .parseExpr(js_ast.LEquals)}}
case js_lexer.TExclamationEqualsEquals:
if >= js_ast.LEquals {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpStrictNe, Left: , Right: .parseExpr(js_ast.LEquals)}}
if .options.ts.Parse && .trySkipTypeScriptTypeArgumentsWithBacktracking() {
=
continue
}
if >= js_ast.LCompare {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLt, Left: , Right: .parseExpr(js_ast.LCompare)}}
case js_lexer.TLessThanEquals:
if >= js_ast.LCompare {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLe, Left: , Right: .parseExpr(js_ast.LCompare)}}
case js_lexer.TGreaterThan:
if >= js_ast.LCompare {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpGt, Left: , Right: .parseExpr(js_ast.LCompare)}}
case js_lexer.TGreaterThanEquals:
if >= js_ast.LCompare {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpGe, Left: , Right: .parseExpr(js_ast.LCompare)}}
case js_lexer.TLessThanLessThan:
if >= js_ast.LShift {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpShl, Left: , Right: .parseExpr(js_ast.LShift)}}
case js_lexer.TLessThanLessThanEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpShlAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TGreaterThanGreaterThan:
if >= js_ast.LShift {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpShr, Left: , Right: .parseExpr(js_ast.LShift)}}
case js_lexer.TGreaterThanGreaterThanEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpShrAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TGreaterThanGreaterThanGreaterThan:
if >= js_ast.LShift {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpUShr, Left: , Right: .parseExpr(js_ast.LShift)}}
case js_lexer.TGreaterThanGreaterThanGreaterThanEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpUShrAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TQuestionQuestion:
if >= js_ast.LNullishCoalescing {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpNullishCoalescing, Left: , Right: .parseExpr(js_ast.LNullishCoalescing)}}
case js_lexer.TQuestionQuestionEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpNullishCoalescingAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TBarBar:
if >= js_ast.LLogicalOr {
return
}
if < js_ast.LNullishCoalescing {
= .(, js_ast.LNullishCoalescing+1, nil, )
if .lexer.Token == js_lexer.TQuestionQuestion {
.lexer.Unexpected()
}
}
case js_lexer.TBarBarEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLogicalOrAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TAmpersandAmpersand:
if >= js_ast.LLogicalAnd {
return
}
if < js_ast.LNullishCoalescing {
= .(, js_ast.LNullishCoalescing+1, nil, )
if .lexer.Token == js_lexer.TQuestionQuestion {
.lexer.Unexpected()
}
}
case js_lexer.TAmpersandAmpersandEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLogicalAndAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TBar:
if >= js_ast.LBitwiseOr {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpBitwiseOr, Left: , Right: .parseExpr(js_ast.LBitwiseOr)}}
case js_lexer.TBarEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpBitwiseOrAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TAmpersand:
if >= js_ast.LBitwiseAnd {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpBitwiseAnd, Left: , Right: .parseExpr(js_ast.LBitwiseAnd)}}
case js_lexer.TAmpersandEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpBitwiseAndAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TCaret:
if >= js_ast.LBitwiseXor {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpBitwiseXor, Left: , Right: .parseExpr(js_ast.LBitwiseXor)}}
case js_lexer.TCaretEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpBitwiseXorAssign, Left: , Right: .parseExpr(js_ast.LAssign - 1)}}
case js_lexer.TEquals:
if >= js_ast.LAssign {
return
}
.lexer.Next()
= js_ast.Assign(, .parseExpr(js_ast.LAssign-1))
case js_lexer.TIn:
if >= js_ast.LCompare || !.allowIn {
return
}
if !.options.suppressWarningsAboutWeirdCode {
if , := .Data.(*js_ast.EUnary); && .Op == js_ast.UnOpNot {
.log.AddWarning(&.source, .Loc,
"Suspicious use of the \"!\" operator inside the \"in\" operator")
}
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpIn, Left: , Right: .parseExpr(js_ast.LCompare)}}
case js_lexer.TInstanceof:
if >= js_ast.LCompare {
return
}
if !.options.suppressWarningsAboutWeirdCode {
if , := .Data.(*js_ast.EUnary); && .Op == js_ast.UnOpNot {
.log.AddWarning(&.source, .Loc,
"Suspicious use of the \"!\" operator inside the \"instanceof\" operator")
}
}
.lexer.Next()
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpInstanceof, Left: , Right: .parseExpr(js_ast.LCompare)}}
if .options.ts.Parse && < js_ast.LCompare && !.lexer.HasNewlineBefore && .lexer.IsContextualKeyword("as") {
.lexer.Next()
.skipTypeScriptType(js_ast.LLowest)
switch .lexer.Token {
case js_lexer.TPlusPlus, js_lexer.TMinusMinus, js_lexer.TNoSubstitutionTemplateLiteral,
js_lexer.TTemplateHead, js_lexer.TOpenParen, js_lexer.TOpenBracket, js_lexer.TQuestionDot:
.forbidSuffixAfterAsLoc = .lexer.Loc()
return
}
if .lexer.Token.IsAssign() {
.forbidSuffixAfterAsLoc = .lexer.Loc()
return
}
continue
}
return
}
}
}
func ( *parser) ( parseStmtOpts) (js_ast.Expr, js_ast.Stmt, []js_ast.Decl) {
:= .lexer.Range()
:= .lexer.Raw()
if .lexer.Token != js_lexer.TIdentifier || != "let" {
return .parseExpr(js_ast.LLowest), js_ast.Stmt{}, nil
}
.lexer.Next()
switch .lexer.Token {
case js_lexer.TIdentifier, js_lexer.TOpenBracket, js_lexer.TOpenBrace:
if .lexicalDecl == lexicalDeclAllowAll || !.lexer.HasNewlineBefore || .lexer.Token == js_lexer.TOpenBracket {
if .lexicalDecl != lexicalDeclAllowAll {
.forbidLexicalDecl(.Loc)
}
.markSyntaxFeature(compat.Let, )
:= .parseAndDeclareDecls(js_ast.SymbolOther, )
return js_ast.Expr{}, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SLocal{
Kind: js_ast.LocalLet,
Decls: ,
IsExport: .isExport,
}},
}
}
:= .storeNameInRef()
:= js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: }}
return .parseSuffix(, js_ast.LLowest, nil, 0), js_ast.Stmt{}, nil
}
:= .allowIn
.allowIn = true
:= []js_ast.Expr{}
.lexer.Expect(js_lexer.TOpenParen)
for .lexer.Token != js_lexer.TCloseParen {
:= .lexer.Loc()
:= .lexer.Token == js_lexer.TDotDotDot
if {
.markSyntaxFeature(compat.RestArgument, .lexer.Range())
.lexer.Next()
}
:= .parseExpr(js_ast.LComma)
if {
= js_ast.Expr{Loc: , Data: &js_ast.ESpread{Value: }}
}
= append(, )
if .lexer.Token != js_lexer.TComma {
break
}
.lexer.Next()
}
.lexer.Expect(js_lexer.TCloseParen)
.allowIn =
return
}
func ( *parser) () (logger.Range, string, *js_ast.Expr) {
:= .lexer.Loc()
:= .lexer.Identifier
:= .lexer.Range()
.lexer.ExpectInsideJSXElement(js_lexer.TIdentifier)
:= &js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: .storeNameInRef()}}
for .lexer.Token == js_lexer.TDot {
.lexer.NextInsideJSXElement()
:= .lexer.Range()
:= .lexer.Identifier
.lexer.ExpectInsideJSXElement(js_lexer.TIdentifier)
, , := .parseJSXTag()
.skipTypeScriptTypeArguments(true /* isInsideJSXElement */)
}
.lexer.NextInsideJSXElement()
if .lexer.Token == js_lexer.TStringLiteral {
= js_ast.Expr{Loc: .lexer.Loc(), Data: &js_ast.EString{Value: .lexer.StringLiteral}}
.lexer.NextInsideJSXElement()
.lexer.NextInsideJSXElement()
default:
break
}
}
}
.lexer.NextInsideJSXElement()
if .lexer.Token != js_lexer.TGreaterThan {
.lexer.Expected(js_lexer.TGreaterThan)
}
return js_ast.Expr{Loc: , Data: &js_ast.EJSXElement{Tag: , Properties: }}
}
.lexer.ExpectJSXElementChild(js_lexer.TCloseBrace)
case js_lexer.TLessThan:
:= .lexer.Loc()
.lexer.NextInsideJSXElement()
= append(, .())
.lexer.NextJSXElementChild()
continue
}
.lexer.NextInsideJSXElement()
, , := .parseJSXTag()
if != {
.log.AddRangeErrorWithNotes(&.source, , fmt.Sprintf("Expected closing tag %q to match opening tag %q", , ),
[]logger.MsgData{logger.RangeData(&.source, , fmt.Sprintf("The opening tag %q is here", ))})
}
if .lexer.Token != js_lexer.TGreaterThan {
.lexer.Expected(js_lexer.TGreaterThan)
}
return js_ast.Expr{Loc: , Data: &js_ast.EJSXElement{Tag: , Properties: , Children: }}
default:
.lexer.Unexpected()
}
}
}
:= .allowIn
.allowIn = true
for {
.lexer.Next()
:= .parseExpr(js_ast.LLowest)
:= .lexer.Loc()
.lexer.RescanCloseBraceAsTemplateToken()
:= .lexer.StringLiteral
:= ""
if {
= .lexer.RawTemplateContents()
} else if .lexer.LegacyOctalLoc.Start > .Start {
= .lexer.LegacyOctalLoc
}
= append(, js_ast.TemplatePart{Value: , TailLoc: , Tail: , TailRaw: })
if .lexer.Token == js_lexer.TTemplateTail {
.lexer.Next()
break
}
}
.allowIn =
return ,
}
func ( *parser) ( js_ast.SymbolKind, parseStmtOpts) []js_ast.Decl {
:= []js_ast.Decl{}
if ( == js_ast.SymbolOther || == js_ast.SymbolConst) && .lexer.IsContextualKeyword("let") {
.log.AddRangeError(&.source, .lexer.Range(), "Cannot use \"let\" as an identifier here")
}
var *js_ast.Expr
:= .parseBinding()
.declareBinding(, , )
if || .lexer.Token == js_lexer.TColon {
.lexer.Expect(js_lexer.TColon)
.skipTypeScriptType(js_ast.LLowest)
}
}
if .lexer.Token == js_lexer.TEquals {
.lexer.Next()
:= .parseExpr(js_ast.LComma)
= &
}
= append(, js_ast.Decl{Binding: , Value: })
if .lexer.Token != js_lexer.TComma {
break
}
.lexer.Next()
}
return
}
func ( *parser) ( []js_ast.Decl) {
for , := range {
if .Value == nil {
if , := .Binding.Data.(*js_ast.BIdentifier); {
:= js_lexer.RangeOfIdentifier(.source, .Binding.Loc)
.log.AddRangeError(&.source, , fmt.Sprintf("The constant %q must be initialized",
.symbols[.Ref.InnerIndex].OriginalName))
} else {
.log.AddError(&.source, .Binding.Loc, "This constant must be initialized")
}
}
}
}
func ( *parser) ( []js_ast.Decl, string, bool) {
if len() > 1 {
.log.AddError(&.source, [0].Binding.Loc, fmt.Sprintf("for-%s loops must have a single declaration", ))
} else if len() == 1 && [0].Value != nil {
if {
return
}
}
.log.AddError(&.source, [0].Value.Loc, fmt.Sprintf("for-%s loop variables cannot have an initializer", ))
}
}
func ( *parser) () ([]js_ast.ClauseItem, bool) {
:= []js_ast.ClauseItem{}
.lexer.Expect(js_lexer.TOpenBrace)
:= !.lexer.HasNewlineBefore
for .lexer.Token != js_lexer.TCloseBrace {
:= .lexer.Identifier
:= .lexer.Loc()
:= js_ast.LocRef{Loc: , Ref: .storeNameInRef()}
:=
:= .lexer.Token == js_lexer.TIdentifier
if !.lexer.IsIdentifierOrKeyword() {
.lexer.Expect(js_lexer.TIdentifier)
}
.lexer.Next()
if .lexer.IsContextualKeyword("as") {
.lexer.Next()
= .lexer.Identifier
= js_ast.LocRef{Loc: .lexer.Loc(), Ref: .storeNameInRef()}
.lexer.Expect(js_lexer.TIdentifier)
.lexer.Unexpected()
}
if isEvalOrArguments() {
:= js_lexer.RangeOfIdentifier(.source, .Loc)
.log.AddRangeError(&.source, , fmt.Sprintf("Cannot use %q as an identifier here", ))
}
= append(, js_ast.ClauseItem{
Alias: ,
AliasLoc: ,
Name: ,
OriginalName: ,
})
if .lexer.Token != js_lexer.TComma {
break
}
if .lexer.HasNewlineBefore {
= false
}
.lexer.Next()
if .lexer.HasNewlineBefore {
= false
}
}
if .lexer.HasNewlineBefore {
= false
}
.lexer.Expect(js_lexer.TCloseBrace)
return ,
}
func ( *parser) () ([]js_ast.ClauseItem, bool) {
:= []js_ast.ClauseItem{}
:= logger.Loc{}
.lexer.Expect(js_lexer.TOpenBrace)
:= !.lexer.HasNewlineBefore
for .lexer.Token != js_lexer.TCloseBrace {
:= .lexer.Identifier
:= .lexer.Loc()
:= js_ast.LocRef{Loc: , Ref: .storeNameInRef()}
:=
if .lexer.Token != js_lexer.TIdentifier {
if !.lexer.IsIdentifierOrKeyword() {
.lexer.Expect(js_lexer.TIdentifier)
}
if .Start == 0 {
= .lexer.Loc()
}
}
.checkForNonBMPCodePoint(, )
.lexer.Next()
if .lexer.IsContextualKeyword("as") {
.lexer.Next()
= .lexer.Identifier
= .lexer.Loc()
if !.lexer.IsIdentifierOrKeyword() {
.lexer.Expect(js_lexer.TIdentifier)
}
.checkForNonBMPCodePoint(, )
.lexer.Next()
}
= append(, js_ast.ClauseItem{
Alias: ,
AliasLoc: ,
Name: ,
OriginalName: ,
})
if .lexer.Token != js_lexer.TComma {
break
}
if .lexer.HasNewlineBefore {
= false
}
.lexer.Next()
if .lexer.HasNewlineBefore {
= false
}
}
if .lexer.HasNewlineBefore {
= false
}
.lexer.Expect(js_lexer.TCloseBrace)
if .Start != 0 && !.lexer.IsContextualKeyword("from") {
:= js_lexer.RangeOfIdentifier(.source, )
.log.AddRangeError(&.source, , fmt.Sprintf("Expected identifier but found %q", .source.TextForRange()))
panic(js_lexer.LexerPanic{})
}
return ,
}
func ( *parser) () js_ast.Binding {
:= .lexer.Loc()
switch .lexer.Token {
case js_lexer.TIdentifier:
:= .lexer.Identifier
if (.fnOrArrowDataParse.allowAwait && == "await") || (.fnOrArrowDataParse.allowYield && == "yield") {
.log.AddRangeError(&.source, .lexer.Range(), fmt.Sprintf("Cannot use %q as an identifier here", ))
}
:= .storeNameInRef()
.lexer.Next()
return js_ast.Binding{Loc: , Data: &js_ast.BIdentifier{Ref: }}
case js_lexer.TOpenBracket:
.markSyntaxFeature(compat.Destructuring, .lexer.Range())
.lexer.Next()
:= !.lexer.HasNewlineBefore
:= []js_ast.ArrayBinding{}
:= false
if .lexer.Token != js_lexer.TIdentifier {
.markSyntaxFeature(compat.NestedRestBinding, .lexer.Range())
}
}
:= .()
var *js_ast.Expr
if ! && .lexer.Token == js_lexer.TEquals {
.lexer.Next()
:= .parseExpr(js_ast.LComma)
= &
}
= append(, js_ast.ArrayBinding{Binding: , DefaultValue: })
if && .lexer.Token == js_lexer.TComma {
.log.AddRangeError(&.source, .lexer.Range(), "Unexpected \",\" after rest pattern")
panic(js_lexer.LexerPanic{})
}
}
if .lexer.Token != js_lexer.TComma {
break
}
if .lexer.HasNewlineBefore {
= false
}
.lexer.Next()
if .lexer.HasNewlineBefore {
= false
}
}
.allowIn =
if .lexer.HasNewlineBefore {
= false
}
.lexer.Expect(js_lexer.TCloseBracket)
return js_ast.Binding{Loc: , Data: &js_ast.BArray{
Items: ,
HasSpread: ,
IsSingleLine: ,
}}
case js_lexer.TOpenBrace:
.markSyntaxFeature(compat.Destructuring, .lexer.Range())
.lexer.Next()
:= !.lexer.HasNewlineBefore
:= []js_ast.PropertyBinding{}
:= .allowIn
.allowIn = true
for .lexer.Token != js_lexer.TCloseBrace {
:= .parsePropertyBinding()
= append(, )
if .IsSpread && .lexer.Token == js_lexer.TComma {
.log.AddRangeError(&.source, .lexer.Range(), "Unexpected \",\" after rest pattern")
panic(js_lexer.LexerPanic{})
}
if .lexer.Token != js_lexer.TComma {
break
}
if .lexer.HasNewlineBefore {
= false
}
.lexer.Next()
if .lexer.HasNewlineBefore {
= false
}
}
.allowIn =
if .lexer.HasNewlineBefore {
= false
}
.lexer.Expect(js_lexer.TCloseBrace)
return js_ast.Binding{Loc: , Data: &js_ast.BObject{
Properties: ,
IsSingleLine: ,
}}
}
.lexer.Expect(js_lexer.TIdentifier)
return js_ast.Binding{}
}
func ( *parser) ( *js_ast.LocRef, fnOrArrowDataParse) ( js_ast.Fn, bool) {
if .allowAwait && .allowYield {
.markSyntaxFeature(compat.AsyncGenerator, .asyncRange)
}
.Name =
.HasRestArg = false
.IsAsync = .allowAwait
.IsGenerator = .allowYield
.ArgumentsRef = js_ast.InvalidRef
.OpenParenLoc = .lexer.Loc()
.lexer.Expect(js_lexer.TOpenParen)
if .options.ts.Parse && .lexer.Token == js_lexer.TThis {
.lexer.Next()
if .lexer.Token == js_lexer.TColon {
.lexer.Next()
.skipTypeScriptType(js_ast.LLowest)
}
if .lexer.Token != js_lexer.TComma {
break
}
.lexer.Next()
continue
}
var []js_ast.Expr
if .allowTSDecorators {
= .parseTypeScriptDecorators()
}
if !.HasRestArg && .lexer.Token == js_lexer.TDotDotDot {
.markSyntaxFeature(compat.RestArgument, .lexer.Range())
.lexer.Next()
.HasRestArg = true
}
:= false
:= .lexer.Token == js_lexer.TIdentifier
:= .lexer.Identifier
:= .parseBinding()
if && .isConstructor {
for .lexer.Token == js_lexer.TIdentifier || .lexer.Token == js_lexer.TOpenBrace || .lexer.Token == js_lexer.TOpenBracket {
if != "public" && != "private" && != "protected" && != "readonly" {
break
}
= true
if .lexer.Token != js_lexer.TIdentifier {
.lexer.Expect(js_lexer.TIdentifier)
}
= .lexer.Identifier
= .parseBinding()
}
}
if .lexer.Token == js_lexer.TColon {
.lexer.Next()
.skipTypeScriptType(js_ast.LLowest)
}
}
.declareBinding(js_ast.SymbolHoisted, , parseStmtOpts{})
var *js_ast.Expr
if !.HasRestArg && .lexer.Token == js_lexer.TEquals {
.markSyntaxFeature(compat.DefaultArgument, .lexer.Range())
.lexer.Next()
:= .parseExpr(js_ast.LComma)
= &
}
.Args = append(.Args, js_ast.Arg{
TSDecorators: ,
Binding: ,
Default: ,
IsTypeScriptCtorField: ,
})
if .lexer.Token != js_lexer.TComma {
break
}
if , := .currentScope.Members["arguments"]; ! {
.ArgumentsRef = .declareSymbol(js_ast.SymbolArguments, .OpenParenLoc, "arguments")
.symbols[.ArgumentsRef.InnerIndex].MustNotBeRenamed = true
}
.lexer.Expect(js_lexer.TCloseParen)
.fnOrArrowDataParse =
if .allowMissingBodyForTypeScript && .lexer.Token != js_lexer.TOpenBrace {
.lexer.ExpectOrInsertSemicolon()
return
}
.Body = .parseFnBody()
= true
return
}
func ( *parser) ( logger.Loc, parseStmtOpts) js_ast.Stmt {
var *js_ast.LocRef
:= .lexer.Range()
if .lexer.Token == js_lexer.TClass {
.markSyntaxFeature(compat.Class, )
.lexer.Next()
} else {
.lexer.Expected(js_lexer.TClass)
}
:= .lexer.Token == js_lexer.TIdentifier
:= && js_lexer.StrictModeReservedWords[.lexer.Identifier]
if !.isNameOptional || ( && !) {
:= .lexer.Loc()
:= .lexer.Identifier
if {
.lexer.Unexpected()
}
.lexer.Expect(js_lexer.TIdentifier)
= &js_ast.LocRef{Loc: , Ref: js_ast.InvalidRef}
if !.isTypeScriptDeclare {
.Ref = .declareSymbol(js_ast.SymbolClass, , )
}
}
if .options.ts.Parse {
.skipTypeScriptTypeParameters()
}
:= parseClassOpts{
allowTSDecorators: true,
isTypeScriptDeclare: .isTypeScriptDeclare,
}
if .tsDecorators != nil {
.tsDecorators = .tsDecorators.values
}
:= .pushScopeForParsePass(js_ast.ScopeClassName, )
:= .parseClass(, , )
if .isTypeScriptDeclare {
.popAndDiscardScope()
} else {
.popScope()
}
return js_ast.Stmt{Loc: , Data: &js_ast.SClass{Class: , IsExport: .isExport}}
}
type parseClassOpts struct {
tsDecorators []js_ast.Expr
allowTSDecorators bool
isTypeScriptDeclare bool
}
if .options.ts.Parse {
.skipTypeScriptTypeArguments(false /* isInsideJSXElement */)
}
}
if .options.ts.Parse && .lexer.IsContextualKeyword("implements") {
.lexer.Next()
for {
.skipTypeScriptType(js_ast.LLowest)
if .lexer.Token != js_lexer.TComma {
break
}
.lexer.Next()
}
}
:= .lexer.Loc()
.lexer.Expect(js_lexer.TOpenBrace)
:= []js_ast.Property{}
:= .allowIn
:= .allowPrivateIdentifiers
.allowIn = true
.allowPrivateIdentifiers = true
:= .pushScopeForParsePass(js_ast.ScopeClassBody, )
:= propertyOpts{
isClass: true,
allowTSDecorators: .allowTSDecorators,
classHasExtends: != nil,
}
for .lexer.Token != js_lexer.TCloseBrace {
if .lexer.Token == js_lexer.TSemicolon {
.lexer.Next()
continue
}
:= .lexer.Loc()
if .allowTSDecorators {
.tsDecorators = .parseTypeScriptDecorators()
} else {
.tsDecorators = nil
}
if , := .parseProperty(js_ast.PropertyNormal, , nil); {
= append(, )
if .isTypeScriptDeclare {
.popAndDiscardScope()
} else {
.popScope()
}
.allowIn =
.allowPrivateIdentifiers =
.lexer.Expect(js_lexer.TCloseBrace)
return js_ast.Class{
ClassKeyword: ,
TSDecorators: .tsDecorators,
Name: ,
Extends: ,
BodyLoc: ,
Properties: ,
}
}
func ( *parser) () *js_ast.LocRef {
if .lexer.Token != js_lexer.TIdentifier || .lexer.HasNewlineBefore {
return nil
}
:= js_ast.LocRef{Loc: .lexer.Loc(), Ref: .storeNameInRef(.lexer.Identifier)}
.lexer.Next()
return &
}
func ( *parser) () (logger.Loc, string) {
:= .lexer.Loc()
:= js_lexer.UTF16ToString(.lexer.StringLiteral)
if .lexer.Token == js_lexer.TNoSubstitutionTemplateLiteral {
.lexer.Next()
} else {
.lexer.Expect(js_lexer.TStringLiteral)
}
return ,
}
func ( *parser) ( logger.Loc, parseStmtOpts, bool, logger.Range) js_ast.Stmt {
:= .lexer.Token == js_lexer.TAsterisk
if {
.markSyntaxFeature(compat.Generator, .lexer.Range())
.lexer.Next()
} else if {
.markLoweredSyntaxFeature(compat.AsyncAwait, , compat.Generator)
}
switch .lexicalDecl {
case lexicalDeclForbid:
.forbidLexicalDecl()
case lexicalDeclAllowFnInsideIf, lexicalDeclAllowFnInsideLabel:
if .isTypeScriptDeclare || || {
.forbidLexicalDecl()
}
}
var *js_ast.LocRef
var string
if !.isNameOptional || .lexer.Token == js_lexer.TIdentifier {
:= .lexer.Loc()
= .lexer.Identifier
.lexer.Expect(js_lexer.TIdentifier)
= &js_ast.LocRef{Loc: , Ref: js_ast.InvalidRef}
}
if .options.ts.Parse {
.skipTypeScriptTypeParameters()
}
var int
:= .lexicalDecl == lexicalDeclAllowFnInsideIf
if {
= .pushScopeForParsePass(js_ast.ScopeBlock, )
}
:= .pushScopeForParsePass(js_ast.ScopeFunctionArgs, .lexer.Loc())
, := .parseFn(, fnOrArrowDataParse{
asyncRange: ,
allowAwait: ,
allowYield: ,
isTypeScriptDeclare: .isTypeScriptDeclare,
if .isTypeScriptDeclare || ! {
.popAndDiscardScope()
if {
.popAndDiscardScope()
}
return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}
}
.popScope()
if != nil {
:= js_ast.SymbolHoistedFunction
if || {
= js_ast.SymbolGeneratorOrAsyncFunction
}
.Ref = .declareSymbol(, .Loc, )
}
scopeIndex int
}
type lexicalDecl uint8
const (
lexicalDeclForbid lexicalDecl = iota
lexicalDeclAllowAll
lexicalDeclAllowFnInsideIf
lexicalDeclAllowFnInsideLabel
)
type parseStmtOpts struct {
tsDecorators *deferredTSDecorators
lexicalDecl lexicalDecl
isModuleScope bool
isNamespaceScope bool
isExport bool
isNameOptional bool // For "export default" pseudo-statements
isTypeScriptDeclare bool
}
func ( *parser) ( parseStmtOpts) js_ast.Stmt {
:= .lexer.Loc()
switch .lexer.Token {
case js_lexer.TSemicolon:
.lexer.Next()
return js_ast.Stmt{Loc: , Data: &js_ast.SEmpty{}}
case js_lexer.TExport:
:= .es6ExportKeyword
if .isModuleScope {
.es6ExportKeyword = .lexer.Range()
} else if !.isNamespaceScope {
.lexer.Unexpected()
}
.lexer.Next()
if .tsDecorators != nil && .lexer.Token != js_lexer.TClass && .lexer.Token != js_lexer.TDefault &&
!.lexer.IsContextualKeyword("abstract") && !.lexer.IsContextualKeyword("declare") {
.lexer.Expected(js_lexer.TClass)
}
switch .lexer.Token {
case js_lexer.TClass, js_lexer.TConst, js_lexer.TFunction, js_lexer.TVar:
.isExport = true
return .()
if .options.ts.Parse && (.isModuleScope || .isNamespaceScope) {
.isExport = true
return .()
}
.lexer.Unexpected()
return js_ast.Stmt{}
case js_lexer.TEnum:
if !.options.ts.Parse {
.lexer.Unexpected()
}
.isExport = true
return .()
case js_lexer.TIdentifier:
if .lexer.IsContextualKeyword("let") {
.isExport = true
return .()
}
.lexer.Next()
.lexer.ExpectContextualKeyword("namespace")
.lexer.Expect(js_lexer.TIdentifier)
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}
}
:= .lexer.Range()
.lexer.Next()
if .lexer.HasNewlineBefore {
.log.AddError(&.source, logger.Loc{Start: .End()}, "Unexpected newline after \"async\"")
panic(js_lexer.LexerPanic{})
}
.lexer.Expect(js_lexer.TFunction)
.isExport = true
return .parseFnStmt(, , true /* isAsync */, )
}
if .options.ts.Parse {
switch .lexer.Identifier {
:= .lexer.Range()
.lexer.Next()
if .lexer.HasNewlineBefore {
.log.AddError(&.source, logger.Loc{Start: .End()}, "Unexpected newline after \"type\"")
panic(js_lexer.LexerPanic{})
}
.skipTypeScriptTypeStmt(parseStmtOpts{isModuleScope: .isModuleScope, isExport: true})
return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}
.isExport = true
.lexicalDecl = lexicalDeclAllowAll
.isTypeScriptDeclare = true
return .()
}
}
.lexer.Unexpected()
return js_ast.Stmt{}
case js_lexer.TDefault:
if !.isModuleScope && (!.isNamespaceScope || !.isTypeScriptDeclare) {
.lexer.Unexpected()
}
:= .lexer.Loc()
.lexer.Next()
:= func() js_ast.LocRef {
:= js_ast.LocRef{Loc: , Ref: .newSymbol(js_ast.SymbolOther, .source.IdentifierName+"_default")}
.currentScope.Generated = append(.currentScope.Generated, .Ref)
return
}
if .tsDecorators != nil && .lexer.Token != js_lexer.TClass && !.lexer.IsContextualKeyword("abstract") {
.lexer.Expected(js_lexer.TClass)
}
if .lexer.IsContextualKeyword("async") {
:= .lexer.Range()
.lexer.Next()
if .lexer.Token == js_lexer.TFunction && !.lexer.HasNewlineBefore {
.lexer.Next()
:= .parseFnStmt(, parseStmtOpts{
isNameOptional: true,
lexicalDecl: lexicalDeclAllowAll,
}, true /* isAsync */, )
if , := .Data.(*js_ast.STypeScript); {
return // This was just a type annotation
}
var js_ast.LocRef
if , := .Data.(*js_ast.SFunction); && .Fn.Name != nil {
= js_ast.LocRef{Loc: , Ref: .Fn.Name.Ref}
} else {
= ()
}
return js_ast.Stmt{Loc: , Data: &js_ast.SExportDefault{DefaultName: , Value: js_ast.ExprOrStmt{Stmt: &}}}
}
:= ()
:= .parseSuffix(.parseAsyncPrefixExpr(, js_ast.LComma), js_ast.LComma, nil, 0)
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.SExportDefault{DefaultName: , Value: js_ast.ExprOrStmt{Expr: &}}}
}
if .lexer.Token == js_lexer.TFunction || .lexer.Token == js_lexer.TClass || .lexer.IsContextualKeyword("interface") {
:= .(parseStmtOpts{
tsDecorators: .tsDecorators,
isNameOptional: true,
lexicalDecl: lexicalDeclAllowAll,
})
if , := .Data.(*js_ast.STypeScript); {
return // This was just a type annotation
}
var js_ast.LocRef
switch s := .Data.(type) {
case *js_ast.SFunction:
if .Fn.Name != nil {
= js_ast.LocRef{Loc: , Ref: .Fn.Name.Ref}
} else {
= ()
}
case *js_ast.SClass:
if .Class.Name != nil {
= js_ast.LocRef{Loc: , Ref: .Class.Name.Ref}
} else {
= ()
}
default:
panic("Internal error")
}
return js_ast.Stmt{Loc: , Data: &js_ast.SExportDefault{DefaultName: , Value: js_ast.ExprOrStmt{Stmt: &}}}
}
:= .lexer.Token == js_lexer.TIdentifier
:= .lexer.Identifier
:= .parseExpr(js_ast.LComma)
if .options.ts.Parse && && == "abstract" {
if , := .Data.(*js_ast.EIdentifier); && (.lexer.Token == js_lexer.TClass || .tsDecorators != nil) {
:= .parseClassStmt(, parseStmtOpts{
tsDecorators: .tsDecorators,
isNameOptional: true,
})
var js_ast.LocRef
if , := .Data.(*js_ast.SClass); && .Class.Name != nil {
= js_ast.LocRef{Loc: , Ref: .Class.Name.Ref}
} else {
= ()
}
return js_ast.Stmt{Loc: , Data: &js_ast.SExportDefault{DefaultName: , Value: js_ast.ExprOrStmt{Stmt: &}}}
}
}
.lexer.ExpectOrInsertSemicolon()
:= ()
return js_ast.Stmt{Loc: , Data: &js_ast.SExportDefault{DefaultName: , Value: js_ast.ExprOrStmt{Expr: &}}}
case js_lexer.TAsterisk:
if !.isModuleScope && (!.isNamespaceScope || !.isTypeScriptDeclare) {
.lexer.Unexpected()
}
.lexer.Next()
var js_ast.Ref
var *js_ast.ExportStarAlias
var logger.Loc
var string
.lexer.Next()
:= .lexer.Identifier
= .storeNameInRef()
= &js_ast.ExportStarAlias{Loc: .lexer.Loc(), OriginalName: }
if !.lexer.IsIdentifierOrKeyword() {
.lexer.Expect(js_lexer.TIdentifier)
}
.checkForNonBMPCodePoint(.Loc, )
.lexer.Next()
.lexer.ExpectContextualKeyword("from")
, = .parsePath()
.lexer.ExpectContextualKeyword("from")
, = .parsePath()
:= js_ast.GenerateNonUniqueNameFromPath() + "_star"
= .storeNameInRef()
}
:= .addImportRecord(ast.ImportStmt, , )
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.SExportStar{
NamespaceRef: ,
Alias: ,
ImportRecordIndex: ,
}}
case js_lexer.TOpenBrace:
if !.isModuleScope && (!.isNamespaceScope || !.isTypeScriptDeclare) {
.lexer.Unexpected()
}
, := .parseExportClause()
if .lexer.IsContextualKeyword("from") {
.lexer.Next()
, := .parsePath()
:= .addImportRecord(ast.ImportStmt, , )
:= "import_" + js_ast.GenerateNonUniqueNameFromPath()
:= .storeNameInRef()
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.SExportFrom{
Items: ,
NamespaceRef: ,
ImportRecordIndex: ,
IsSingleLine: ,
}}
}
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.SExportClause{Items: , IsSingleLine: }}
.es6ExportKeyword = // This wasn't an ESM export statement after all
if .options.ts.Parse {
.lexer.Next()
:= .parseExpr(js_ast.LLowest)
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.SExportEquals{Value: }}
}
.lexer.Unexpected()
return js_ast.Stmt{}
default:
.lexer.Unexpected()
return js_ast.Stmt{}
}
case js_lexer.TFunction:
.lexer.Next()
return .parseFnStmt(, , false /* isAsync */, logger.Range{})
case js_lexer.TEnum:
if !.options.ts.Parse {
.lexer.Unexpected()
}
return .parseTypeScriptEnumStmt(, )
if .options.ts.Parse {
:= len(.scopesInOrder)
:= .parseTypeScriptDecorators()
.tsDecorators = &deferredTSDecorators{
values: ,
scopeIndex: ,
}
if .lexer.Token != js_lexer.TClass && .lexer.Token != js_lexer.TExport &&
!.lexer.IsContextualKeyword("abstract") && !.lexer.IsContextualKeyword("declare") {
.lexer.Expected(js_lexer.TClass)
}
return .()
}
.lexer.Unexpected()
return js_ast.Stmt{}
case js_lexer.TClass:
if .lexicalDecl != lexicalDeclAllowAll {
.forbidLexicalDecl()
}
return .parseClassStmt(, )
case js_lexer.TVar:
.lexer.Next()
:= .parseAndDeclareDecls(js_ast.SymbolHoisted, )
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.SLocal{
Kind: js_ast.LocalVar,
Decls: ,
IsExport: .isExport,
}}
case js_lexer.TConst:
if .lexicalDecl != lexicalDeclAllowAll {
.forbidLexicalDecl()
}
.markSyntaxFeature(compat.Const, .lexer.Range())
.lexer.Next()
if .options.ts.Parse && .lexer.Token == js_lexer.TEnum {
return .parseTypeScriptEnumStmt(, )
}
:= .parseAndDeclareDecls(js_ast.SymbolConst, )
.lexer.ExpectOrInsertSemicolon()
if !.isTypeScriptDeclare {
.requireInitializers()
}
return js_ast.Stmt{Loc: , Data: &js_ast.SLocal{
Kind: js_ast.LocalConst,
Decls: ,
IsExport: .isExport,
}}
case js_lexer.TIf:
.lexer.Next()
.lexer.Expect(js_lexer.TOpenParen)
:= .parseExpr(js_ast.LLowest)
.lexer.Expect(js_lexer.TCloseParen)
:= .(parseStmtOpts{lexicalDecl: lexicalDeclAllowFnInsideIf})
var *js_ast.Stmt = nil
if .lexer.Token == js_lexer.TElse {
.lexer.Next()
:= .(parseStmtOpts{lexicalDecl: lexicalDeclAllowFnInsideIf})
= &
}
return js_ast.Stmt{Loc: , Data: &js_ast.SIf{Test: , Yes: , No: }}
case js_lexer.TDo:
.lexer.Next()
:= .(parseStmtOpts{})
.lexer.Expect(js_lexer.TWhile)
.lexer.Expect(js_lexer.TOpenParen)
:= .parseExpr(js_ast.LLowest)
.lexer.Expect(js_lexer.TCloseParen)
if .lexer.Token == js_lexer.TSemicolon {
.lexer.Next()
}
return js_ast.Stmt{Loc: , Data: &js_ast.SDoWhile{Body: , Test: }}
case js_lexer.TWhile:
.lexer.Next()
.lexer.Expect(js_lexer.TOpenParen)
:= .parseExpr(js_ast.LLowest)
.lexer.Expect(js_lexer.TCloseParen)
:= .(parseStmtOpts{})
return js_ast.Stmt{Loc: , Data: &js_ast.SWhile{Test: , Body: }}
case js_lexer.TWith:
.lexer.Next()
.lexer.Expect(js_lexer.TOpenParen)
:= .parseExpr(js_ast.LLowest)
:= .lexer.Loc()
.lexer.Expect(js_lexer.TCloseParen)
.pushScopeForParsePass(js_ast.ScopeWith, )
:= .(parseStmtOpts{})
.popScope()
return js_ast.Stmt{Loc: , Data: &js_ast.SWith{Value: , BodyLoc: , Body: }}
case js_lexer.TSwitch:
.lexer.Next()
.lexer.Expect(js_lexer.TOpenParen)
:= .parseExpr(js_ast.LLowest)
.lexer.Expect(js_lexer.TCloseParen)
:= .lexer.Loc()
.pushScopeForParsePass(js_ast.ScopeBlock, )
defer .popScope()
.lexer.Expect(js_lexer.TOpenBrace)
:= []js_ast.Case{}
:= false
for .lexer.Token != js_lexer.TCloseBrace {
var *js_ast.Expr = nil
:= []js_ast.Stmt{}
if .lexer.Token == js_lexer.TDefault {
if {
.log.AddRangeError(&.source, .lexer.Range(), "Multiple default clauses are not allowed")
panic(js_lexer.LexerPanic{})
}
= true
.lexer.Next()
.lexer.Expect(js_lexer.TColon)
} else {
.lexer.Expect(js_lexer.TCase)
:= .parseExpr(js_ast.LLowest)
= &
.lexer.Expect(js_lexer.TColon)
}
:
for {
switch .lexer.Token {
case js_lexer.TCloseBrace, js_lexer.TCase, js_lexer.TDefault:
break
default:
= append(, .(parseStmtOpts{lexicalDecl: lexicalDeclAllowAll}))
}
}
= append(, js_ast.Case{Value: , Body: })
}
.lexer.Expect(js_lexer.TCloseBrace)
return js_ast.Stmt{Loc: , Data: &js_ast.SSwitch{
Test: ,
BodyLoc: ,
Cases: ,
}}
case js_lexer.TTry:
.lexer.Next()
:= .lexer.Loc()
.lexer.Expect(js_lexer.TOpenBrace)
.pushScopeForParsePass(js_ast.ScopeBlock, )
:= .parseStmtsUpTo(js_lexer.TCloseBrace, parseStmtOpts{})
.popScope()
.lexer.Next()
var *js_ast.Catch = nil
var *js_ast.Finally = nil
if .lexer.Token == js_lexer.TCatch {
:= .lexer.Loc()
.pushScopeForParsePass(js_ast.ScopeBlock, )
.lexer.Next()
var *js_ast.Binding
if .lexer.Token == js_lexer.TOpenBrace {
:= .newSymbol(js_ast.SymbolOther, "e")
.currentScope.Generated = append(.currentScope.Generated, )
= &js_ast.Binding{Loc: .lexer.Loc(), Data: &js_ast.BIdentifier{Ref: }}
}
} else {
.lexer.Expect(js_lexer.TOpenParen)
:= .parseBinding()
:= js_ast.SymbolOther
if , := .Data.(*js_ast.BIdentifier); {
= js_ast.SymbolCatchIdentifier
}
.declareBinding(, , parseStmtOpts{})
= &
}
.lexer.Expect(js_lexer.TOpenBrace)
:= .parseStmtsUpTo(js_lexer.TCloseBrace, parseStmtOpts{})
.lexer.Next()
= &js_ast.Catch{Loc: , Binding: , Body: }
.popScope()
}
if .lexer.Token == js_lexer.TFinally || == nil {
:= .lexer.Loc()
.pushScopeForParsePass(js_ast.ScopeBlock, )
.lexer.Expect(js_lexer.TFinally)
.lexer.Expect(js_lexer.TOpenBrace)
:= .parseStmtsUpTo(js_lexer.TCloseBrace, parseStmtOpts{})
.lexer.Next()
= &js_ast.Finally{Loc: , Stmts: }
.popScope()
}
return js_ast.Stmt{Loc: , Data: &js_ast.STry{
BodyLoc: ,
Body: ,
Catch: ,
Finally: ,
}}
case js_lexer.TFor:
.pushScopeForParsePass(js_ast.ScopeBlock, )
defer .popScope()
.lexer.Next()
:= .lexer.IsContextualKeyword("await")
if {
:= .lexer.Range()
if !.fnOrArrowDataParse.allowAwait {
.log.AddRangeError(&.source, , "Cannot use \"await\" outside an async function")
= false
} else {
:= .markSyntaxFeature(compat.ForAwait, )
if .fnOrArrowDataParse.isTopLevel && ! {
.topLevelAwaitKeyword =
.markSyntaxFeature(compat.TopLevelAwait, )
}
}
.lexer.Next()
}
.lexer.Expect(js_lexer.TOpenParen)
var *js_ast.Stmt = nil
var *js_ast.Expr = nil
var *js_ast.Expr = nil
.allowIn = false
var logger.Range
if .lexer.IsContextualKeyword("let") {
= .lexer.Range()
}
:= []js_ast.Decl{}
:= .lexer.Loc()
:= false
switch .lexer.Token {
case js_lexer.TVar:
= true
.lexer.Next()
= .parseAndDeclareDecls(js_ast.SymbolHoisted, parseStmtOpts{})
= &js_ast.Stmt{Loc: , Data: &js_ast.SLocal{Kind: js_ast.LocalVar, Decls: }}
case js_lexer.TConst:
.markSyntaxFeature(compat.Const, .lexer.Range())
.lexer.Next()
= .parseAndDeclareDecls(js_ast.SymbolConst, parseStmtOpts{})
= &js_ast.Stmt{Loc: , Data: &js_ast.SLocal{Kind: js_ast.LocalConst, Decls: }}
case js_lexer.TSemicolon:
default:
var js_ast.Expr
var js_ast.Stmt
, , = .parseExprOrLetStmt(parseStmtOpts{lexicalDecl: lexicalDeclAllowAll})
if .Data != nil {
= logger.Range{}
= &
} else {
= &js_ast.Stmt{Loc: , Data: &js_ast.SExpr{Value: }}
}
}
if .lexer.IsContextualKeyword("of") || {
if .Len > 0 {
.log.AddRangeError(&.source, , "\"let\" must be wrapped in parentheses to be used as an expression here")
}
if && !.lexer.IsContextualKeyword("of") {
if != nil {
.lexer.ExpectedString("\"of\"")
} else {
.lexer.Unexpected()
}
}
.forbidInitializers(, "of", false)
.markSyntaxFeature(compat.ForOf, .lexer.Range())
.lexer.Next()
:= .parseExpr(js_ast.LComma)
.lexer.Expect(js_lexer.TCloseParen)
:= .(parseStmtOpts{})
return js_ast.Stmt{Loc: , Data: &js_ast.SForOf{IsAwait: , Init: *, Value: , Body: }}
}
if != nil {
if , := .Data.(*js_ast.SLocal); && .Kind == js_ast.LocalConst {
.requireInitializers()
}
}
.lexer.Expect(js_lexer.TSemicolon)
if .lexer.Token != js_lexer.TSemicolon {
:= .parseExpr(js_ast.LLowest)
= &
}
.lexer.Expect(js_lexer.TSemicolon)
if .lexer.Token != js_lexer.TCloseParen {
:= .parseExpr(js_ast.LLowest)
= &
}
.lexer.Expect(js_lexer.TCloseParen)
:= .(parseStmtOpts{})
return js_ast.Stmt{Loc: , Data: &js_ast.SFor{Init: , Test: , Update: , Body: }}
case js_lexer.TImport:
:= .es6ImportKeyword
.es6ImportKeyword = .lexer.Range()
.lexer.Next()
:= js_ast.SImport{}
:= false
if (.isExport || (.isNamespaceScope && !.isTypeScriptDeclare)) && .lexer.Token != js_lexer.TIdentifier {
.lexer.Expected(js_lexer.TIdentifier)
}
switch .lexer.Token {
.es6ImportKeyword = // This wasn't an ESM import statement after all
:= .parseSuffix(.parseImportExpr(, js_ast.LLowest), js_ast.LLowest, nil, 0)
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.SExpr{Value: }}
if !.isModuleScope && (!.isNamespaceScope || !.isTypeScriptDeclare) {
.lexer.Unexpected()
return js_ast.Stmt{}
}
= true
if !.isModuleScope && (!.isNamespaceScope || !.isTypeScriptDeclare) {
.lexer.Unexpected()
return js_ast.Stmt{}
}
.lexer.Next()
.lexer.ExpectContextualKeyword("as")
.NamespaceRef = .storeNameInRef(.lexer.Identifier)
:= .lexer.Loc()
.StarNameLoc = &
.lexer.Expect(js_lexer.TIdentifier)
.lexer.ExpectContextualKeyword("from")
if !.isModuleScope && (!.isNamespaceScope || !.isTypeScriptDeclare) {
.lexer.Unexpected()
return js_ast.Stmt{}
}
, := .parseImportClause()
.Items = &
.IsSingleLine =
.lexer.ExpectContextualKeyword("from")
if !.isModuleScope && !.isNamespaceScope {
.lexer.Unexpected()
return js_ast.Stmt{}
}
:= .lexer.Identifier
.DefaultName = &js_ast.LocRef{Loc: .lexer.Loc(), Ref: .storeNameInRef()}
.lexer.Next()
if == "type" {
switch .lexer.Token {
case js_lexer.TIdentifier:
.lexer.Next()
.lexer.ExpectContextualKeyword("from")
.parsePath()
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}
}
.lexer.Next()
.lexer.ExpectContextualKeyword("as")
.lexer.Expect(js_lexer.TIdentifier)
.lexer.ExpectContextualKeyword("from")
.parsePath()
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}
.parseImportClause()
.lexer.ExpectContextualKeyword("from")
.parsePath()
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}
}
}
if .lexer.Token == js_lexer.TEquals || .isExport || (.isNamespaceScope && !.isTypeScriptDeclare) {
.es6ImportKeyword = // This wasn't an ESM import statement after all
return .parseTypeScriptImportEqualsStmt(, , .DefaultName.Loc, )
}
}
if .lexer.Token == js_lexer.TComma {
.lexer.Next()
switch .lexer.Token {
.lexer.Next()
.lexer.ExpectContextualKeyword("as")
.NamespaceRef = .storeNameInRef(.lexer.Identifier)
:= .lexer.Loc()
.StarNameLoc = &
.lexer.Expect(js_lexer.TIdentifier)
, := .parseImportClause()
.Items = &
.IsSingleLine =
default:
.lexer.Unexpected()
}
}
.lexer.ExpectContextualKeyword("from")
default:
.lexer.Unexpected()
return js_ast.Stmt{}
}
, := .parsePath()
.ImportRecordIndex = .addImportRecord(ast.ImportStmt, , )
.importRecords[.ImportRecordIndex].WasOriginallyBareImport =
.lexer.ExpectOrInsertSemicolon()
if .StarNameLoc != nil {
:= .loadNameFromRef(.NamespaceRef)
.NamespaceRef = .declareSymbol(js_ast.SymbolImport, *.StarNameLoc, )
:= "import_" + js_ast.GenerateNonUniqueNameFromPath()
.NamespaceRef = .newSymbol(js_ast.SymbolOther, )
.currentScope.Generated = append(.currentScope.Generated, .NamespaceRef)
}
:= make(map[string]js_ast.LocRef)
if .DefaultName != nil {
:= .loadNameFromRef(.DefaultName.Ref)
:= .declareSymbol(js_ast.SymbolImport, .DefaultName.Loc, )
.isImportItem[] = true
.DefaultName.Ref =
}
.importItemsForNamespace[.NamespaceRef] =
return js_ast.Stmt{Loc: , Data: &}
case js_lexer.TBreak:
.lexer.Next()
:= .parseLabelName()
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.SBreak{Label: }}
case js_lexer.TContinue:
.lexer.Next()
:= .parseLabelName()
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.SContinue{Label: }}
case js_lexer.TReturn:
.lexer.Next()
var *js_ast.Expr
if .lexer.Token != js_lexer.TSemicolon &&
!.lexer.HasNewlineBefore &&
.lexer.Token != js_lexer.TCloseBrace &&
.lexer.Token != js_lexer.TEndOfFile {
:= .parseExpr(js_ast.LLowest)
= &
}
.latestReturnHadSemicolon = .lexer.Token == js_lexer.TSemicolon
.lexer.ExpectOrInsertSemicolon()
if .fnOrArrowDataParse.isOutsideFn {
.hasTopLevelReturn = true
}
return js_ast.Stmt{Loc: , Data: &js_ast.SReturn{Value: }}
case js_lexer.TThrow:
.lexer.Next()
if .lexer.HasNewlineBefore {
.log.AddError(&.source, logger.Loc{Start: .Start + 5}, "Unexpected newline after \"throw\"")
panic(js_lexer.LexerPanic{})
}
:= .parseExpr(js_ast.LLowest)
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.SThrow{Value: }}
case js_lexer.TDebugger:
.lexer.Next()
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.SDebugger{}}
case js_lexer.TOpenBrace:
.pushScopeForParsePass(js_ast.ScopeBlock, )
defer .popScope()
.lexer.Next()
:= .parseStmtsUpTo(js_lexer.TCloseBrace, parseStmtOpts{})
.lexer.Next()
return js_ast.Stmt{Loc: , Data: &js_ast.SBlock{Stmts: }}
default:
:= .lexer.Token == js_lexer.TIdentifier
:= .lexer.Identifier
var js_ast.Expr
if && .lexer.Raw() == "async" {
:= .lexer.Range()
.lexer.Next()
if .lexer.Token == js_lexer.TFunction && !.lexer.HasNewlineBefore {
.lexer.Next()
return .parseFnStmt(.Loc, , true /* isAsync */, )
}
= .parseSuffix(.parseAsyncPrefixExpr(, js_ast.LLowest), js_ast.LLowest, nil, 0)
} else {
var js_ast.Stmt
, , _ = .parseExprOrLetStmt()
if .Data != nil {
.lexer.ExpectOrInsertSemicolon()
return
}
}
if {
if , := .Data.(*js_ast.EIdentifier); {
if .lexer.Token == js_lexer.TColon && .tsDecorators == nil {
.pushScopeForParsePass(js_ast.ScopeLabel, )
defer .popScope()
.lexer.Next()
:= js_ast.LocRef{Loc: .Loc, Ref: .Ref}
:= parseStmtOpts{}
if .lexicalDecl == lexicalDeclAllowAll || .lexicalDecl == lexicalDeclAllowFnInsideLabel {
.lexicalDecl = lexicalDeclAllowFnInsideLabel
}
:= .()
return js_ast.Stmt{Loc: , Data: &js_ast.SLabel{Name: , Stmt: }}
}
if .options.ts.Parse {
switch {
case "type":
.skipTypeScriptTypeStmt(parseStmtOpts{isModuleScope: .isModuleScope})
return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}
}
if (.isModuleScope || .isNamespaceScope) && (.lexer.Token == js_lexer.TIdentifier ||
(.lexer.Token == js_lexer.TStringLiteral && .isTypeScriptDeclare)) {
return .parseTypeScriptNamespaceStmt(, )
}
.skipTypeScriptInterfaceStmt(parseStmtOpts{isModuleScope: .isModuleScope})
return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}
case "abstract":
if .lexer.Token == js_lexer.TClass || .tsDecorators != nil {
return .parseClassStmt(, )
}
if .isNamespaceScope && .isTypeScriptDeclare && .lexer.Token == js_lexer.TOpenBrace {
.lexer.Next()
.parseStmtsUpTo(js_lexer.TCloseBrace, )
.lexer.Next()
return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}
}
case "declare":
.lexicalDecl = lexicalDeclAllowAll
.isTypeScriptDeclare = true
if .lexer.IsContextualKeyword("global") {
.lexer.Next()
.lexer.Expect(js_lexer.TOpenBrace)
.parseStmtsUpTo(js_lexer.TCloseBrace, )
.lexer.Next()
return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}
}
:= .()
if .tsDecorators != nil {
.discardScopesUpTo(.tsDecorators.scopeIndex)
}
if .isNamespaceScope && .isExport {
var []js_ast.Decl
if , := .Data.(*js_ast.SLocal); {
for , := range .Decls {
= extractDeclsForBinding(.Binding, )
}
}
if len() > 0 {
return js_ast.Stmt{Loc: , Data: &js_ast.SLocal{
Kind: js_ast.LocalVar,
IsExport: true,
Decls: ,
}}
}
}
return js_ast.Stmt{Loc: , Data: &js_ast.STypeScript{}}
}
}
}
}
.lexer.ExpectOrInsertSemicolon()
return js_ast.Stmt{Loc: , Data: &js_ast.SExpr{Value: }}
}
}
func ( js_ast.Binding, []js_ast.Decl) []js_ast.Decl {
switch b := .Data.(type) {
case *js_ast.BMissing:
case *js_ast.BIdentifier:
= append(, js_ast.Decl{Binding: })
case *js_ast.BArray:
for , := range .Items {
= (.Binding, )
}
case *js_ast.BObject:
for , := range .Properties {
= (.Value, )
}
default:
panic("Internal error")
}
return
}
func ( *parser) ( ast.ImportKind, logger.Loc, string) uint32 {
:= uint32(len(.importRecords))
.importRecords = append(.importRecords, ast.ImportRecord{
Kind: ,
Range: .source.RangeOfString(),
Path: logger.Path{Text: },
})
return
}
func ( *parser) ( fnOrArrowDataParse) js_ast.FnBody {
:= .fnOrArrowDataParse
:= .allowIn
.fnOrArrowDataParse =
.allowIn = true
:= .lexer.Loc()
.pushScopeForParsePass(js_ast.ScopeFunctionBody, )
defer .popScope()
.lexer.Expect(js_lexer.TOpenBrace)
:= .parseStmtsUpTo(js_lexer.TCloseBrace, parseStmtOpts{})
.lexer.Next()
.allowIn =
.fnOrArrowDataParse =
return js_ast.FnBody{Loc: , Stmts: }
}
func ( *parser) ( logger.Loc) {
:= js_lexer.RangeOfIdentifier(.source, )
.log.AddRangeError(&.source, , "Cannot use a declaration in a single-statement context")
}
func ( *parser) ( js_lexer.T, parseStmtOpts) []js_ast.Stmt {
:= []js_ast.Stmt{}
:= int32(-1)
.lexicalDecl = lexicalDeclAllowAll
:= true
if {
= false
if , := .Data.(*js_ast.SExpr); {
if , := .Value.Data.(*js_ast.EString); && !.PreferTemplate {
.Data = &js_ast.SDirective{Value: .Value, LegacyOctalLoc: .LegacyOctalLoc}
= true
if !.options.suppressWarningsAboutWeirdCode {
if , := .Data.(*js_ast.SReturn); && .Value == nil && !.latestReturnHadSemicolon {
= .Loc.Start
} else {
if != -1 {
if , := .Data.(*js_ast.SExpr); {
.log.AddWarning(&.source, logger.Loc{Start: + 6},
"The following expression is not returned because of an automatically-inserted semicolon")
}
}
= -1
}
}
}
return
}
type generateTempRefArg uint8
const (
tempRefNeedsDeclare generateTempRefArg = iota
tempRefNoDeclare
)
func ( *parser) ( generateTempRefArg, string) js_ast.Ref {
:= .currentScope
for !.Kind.StopsHoisting() {
= .Parent
}
if == "" {
= "_" + js_ast.DefaultNameMinifier.NumberToMinifiedName(.tempRefCount)
.tempRefCount++
}
:= .newSymbol(js_ast.SymbolOther, )
if == tempRefNeedsDeclare {
.tempRefsToDeclare = append(.tempRefsToDeclare, tempRef{ref: })
}
.Generated = append(.Generated, )
return
}
func ( *parser) ( js_ast.ScopeKind, logger.Loc) {
:= .scopesInOrder[0]
if .loc != || .scope.Kind != {
panic(fmt.Sprintf("Expected scope (%d, %d) in %s, found scope (%d, %d)",
, .Start,
.source.PrettyPath,
.scope.Kind, .loc.Start))
}
.scopesInOrder = .scopesInOrder[1:]
.currentScope = .scope
.scopesForCurrentPart = append(.scopesForCurrentPart, .scope)
}
type findSymbolResult struct {
ref js_ast.Ref
declareLoc logger.Loc
isInsideWithScope bool
}
func ( *parser) ( logger.Loc, string) findSymbolResult {
var js_ast.Ref
var logger.Loc
:= false
:= false
:= .currentScope
if .ForbidArguments && == "arguments" && ! {
:= js_lexer.RangeOfIdentifier(.source, )
.log.AddRangeError(&.source, , fmt.Sprintf("Cannot access %q here", ))
= true
}
.checkForNonBMPCodePoint(, )
= .newSymbol(js_ast.SymbolUnbound, )
=
.moduleScope.Members[] = js_ast.ScopeMember{Ref: , Loc: logger.Loc{Start: -1}}
break
}
}
if {
.symbols[.InnerIndex].MustNotBeRenamed = true
}
.recordUsage()
return findSymbolResult{, , }
}
func ( *parser) ( logger.Loc, string) ( js_ast.Ref, bool, bool) {
for := .currentScope; != nil && !.Kind.StopsHoisting(); = .Parent {
.recordUsage(.LabelRef)
= .LabelRef
= .LabelStmtIsLoop
= true
return
}
}
:= js_lexer.RangeOfIdentifier(.source, )
.log.AddRangeError(&.source, , fmt.Sprintf("There is no containing label named %q", ))
= .newSymbol(js_ast.SymbolUnbound, )
.recordUsage()
return
}
func ( js_ast.Binding, []js_ast.Decl) []js_ast.Decl {
switch b := .Data.(type) {
case *js_ast.BIdentifier:
= append(, js_ast.Decl{Binding: })
case *js_ast.BArray:
for , := range .Items {
= (.Binding, )
}
case *js_ast.BObject:
for , := range .Properties {
= (.Value, )
}
}
return
}
return false
}
:= []js_ast.Decl{}
for , := range .Decls {
= findIdentifiers(.Binding, )
}
.Decls =
return true
case *js_ast.SBlock:
for , := range .Stmts {
if () {
return true
}
}
return false
case *js_ast.SIf:
return (.Yes) || (.No != nil && (*.No))
case *js_ast.SWhile:
return (.Body)
case *js_ast.SDoWhile:
return (.Body)
case *js_ast.SFor:
return (.Init != nil && (*.Init)) || (.Body)
case *js_ast.SForIn:
return (.Init) || (.Body)
case *js_ast.SForOf:
return (.Init) || (.Body)
case *js_ast.SLabel:
return (.Stmt)
return true
}
}
type prependTempRefsOpts struct {
fnBodyLoc *logger.Loc
kind stmtsKind
}
func ( *parser) ( []js_ast.Stmt, prependTempRefsOpts) []js_ast.Stmt {
:= .tempRefsToDeclare
:= .tempRefCount
.tempRefsToDeclare = nil
.tempRefCount = 0
= .visitStmts(, .kind)
if := .fnOnlyDataVisit.thisCaptureRef; != nil {
.tempRefsToDeclare = append(.tempRefsToDeclare, tempRef{
ref: *,
value: &js_ast.Expr{Loc: *.fnBodyLoc, Data: &js_ast.EThis{}},
})
.currentScope.Generated = append(.currentScope.Generated, *)
}
if := .fnOnlyDataVisit.argumentsCaptureRef; != nil {
.tempRefsToDeclare = append(.tempRefsToDeclare, tempRef{
ref: *,
value: &js_ast.Expr{Loc: *.fnBodyLoc, Data: &js_ast.EIdentifier{Ref: *.fnOnlyDataVisit.argumentsRef}},
})
.currentScope.Generated = append(.currentScope.Generated, *)
}
}
if len(.tempRefsToDeclare) > 0 {
:= []js_ast.Decl{}
for , := range .tempRefsToDeclare {
= append(, js_ast.Decl{Binding: js_ast.Binding{Data: &js_ast.BIdentifier{Ref: .ref}}, Value: .value})
.recordDeclaredSymbol(.ref)
}
:= js_ast.Stmt{Data: &js_ast.SLocal{Kind: js_ast.LocalVar, Decls: }}
if len() > 0 && js_ast.IsSuperCall([0]) {
= append([]js_ast.Stmt{[0], }, [1:]...)
} else {
= append([]js_ast.Stmt{}, ...)
}
}
.tempRefsToDeclare =
.tempRefCount =
return
}
type stmtsKind uint8
const (
stmtsNormal stmtsKind = iota
stmtsLoopBody
stmtsFnBody
)
= .visitAndAppendStmt(, )
continue
if !.currentScope.Kind.StopsHoisting() && .symbols[int(.Fn.Name.Ref.InnerIndex)].Kind == js_ast.SymbolHoistedFunction {
= .visitAndAppendStmt(, )
continue
}
}
= .visitAndAppendStmt(, )
}
= append(, ...)
if !.options.mangleSyntax {
return
}
if .isControlFlowDead {
:= 0
for , := range {
if !shouldKeepStmtInDeadControlFlow() {
continue
}
return js_lexer.UTF16EqualsString(.Value, "use strict")
}
continue
}
continue
}
}
}
}
break
}
}
switch s := .Data.(type) {
continue
case *js_ast.SDirective:
if !isDirectiveSupported() {
continue
}
if len() > 0 {
:= [len()-1]
if , := .Data.(*js_ast.SExpr); && !js_ast.IsSuperCall() {
.Value = js_ast.JoinWithComma(.Value, .Value)
.DoesNotAffectTreeShaking = .DoesNotAffectTreeShaking && .DoesNotAffectTreeShaking
continue
}
}
.Test = js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalOr, .Test, .Test)
= [:len()-1]
}
}
if .Init == nil {
if , := .Data.(*js_ast.SLocal); && .Kind == js_ast.LocalVar && !.IsExport {
[len()-1] =
.Init = &
continue
}
} else {
if , := .Data.(*js_ast.SLocal); && .Kind == js_ast.LocalVar && !.IsExport {
if , := .Init.Data.(*js_ast.SLocal); && .Kind == js_ast.LocalVar {
[len()-1] =
.Init.Data = &js_ast.SLocal{Kind: js_ast.LocalVar, Decls: append(.Decls, .Decls...)}
continue
}
}
}
}
}
}
= append(, )
}
if len() > 0 {
switch {
= &js_ast.SThrow{Value: .mangleIfExpr(.Test.Loc, &js_ast.EIf{Test: .Test, Yes: , No: })}
}
= js_ast.Stmt{Loc: .Loc, Data: }
[] =
= [:len()-1]
default:
break
}
}
}
}
return
}
func ( *parser) ( js_ast.Stmt, js_ast.Ref, js_ast.Expr) bool {
var *js_ast.Expr
switch s := .Data.(type) {
case *js_ast.SExpr:
= &.Value
case *js_ast.SThrow:
= &.Value
case *js_ast.SReturn:
= .Value
case *js_ast.SIf:
= &.Test
case *js_ast.SSwitch:
= &.Test
if , := .Binding.Data.(*js_ast.BIdentifier); {
= .Value
}
}
}
:= .exprCanBeRemovedIfUnused()
if , := .substituteSingleUseSymbolInExpr(*, , , ); == substituteSuccess {
* =
return true
}
}
return false
}
type substituteStatus uint8
const (
substituteContinue substituteStatus = iota
substituteSuccess
substituteFailure
)
func ( *parser) (
js_ast.Expr,
js_ast.Ref,
js_ast.Expr,
bool,
) (js_ast.Expr, substituteStatus) {
switch e := .Data.(type) {
case *js_ast.EIdentifier:
if .Ref == {
.ignoreUsage()
return , substituteSuccess
}
case *js_ast.ESpread:
if , := .(.Value, , , ); != substituteContinue {
.Value =
return ,
}
case *js_ast.EAwait:
if , := .(.Value, , , ); != substituteContinue {
.Value =
return ,
}
case *js_ast.EYield:
if .Value != nil {
if , := .(*.Value, , , ); != substituteContinue {
.Value = &
return ,
}
}
case *js_ast.EImport:
if , := .(.Expr, , , ); != substituteContinue {
.Expr =
return ,
}
if && .exprCanBeRemovedIfUnused(.Expr) {
return , substituteContinue
}
case *js_ast.EUnary:
switch .Op {
default:
if , := .(.Value, , , ); != substituteContinue {
.Value =
return ,
}
}
case *js_ast.EDot:
if , := .(.Target, , , ); != substituteContinue {
.Target =
return ,
}
if .Op.BinaryAssignTarget() == js_ast.AssignTargetNone {
if , := .(.Left, , , ); != substituteContinue {
.Left =
return ,
}
return , substituteFailure
}
if || !.Op.IsShortCircuit() {
if , := .(.Right, , , ); != substituteContinue {
.Right =
return ,
}
}
case *js_ast.EIf:
if , := .(.Test, , , ); != substituteContinue {
.Test =
return ,
}
, := .(.Yes, , , )
if == substituteSuccess {
.Yes =
return ,
}
, := .(.No, , , )
if == substituteSuccess {
.No =
return ,
}
if != substituteContinue || != substituteContinue {
return , substituteFailure
}
}
case *js_ast.EIndex:
if , := .(.Target, , , ); != substituteContinue {
.Target =
return ,
}
if || .OptionalChain == js_ast.OptionalChainNone {
if , := .(.Index, , , ); != substituteContinue {
.Index =
return ,
}
}
case *js_ast.ECall:
if , := .(.Target, , , ); != substituteContinue {
.Target =
return ,
}
if || .OptionalChain == js_ast.OptionalChainNone {
for , := range .Args {
if , := .(, , , ); != substituteContinue {
.Args[] =
return ,
}
}
}
case *js_ast.EArray:
for , := range .Items {
if , := .(, , , ); != substituteContinue {
.Items[] =
return ,
}
}
case *js_ast.EObject:
if .IsComputed {
if , := .(.Key, , , ); != substituteContinue {
.Properties[].Key =
return ,
}
return , substituteFailure
}
if .Value != nil {
if , := .(*.Value, , , ); != substituteContinue {
.Properties[].Value = &
return ,
}
}
}
case *js_ast.ETemplate:
if .Tag != nil {
if , := .(*.Tag, , , ); != substituteContinue {
.Tag = &
return ,
}
}
for , := range .Parts {
if , := .(.Value, , , ); != substituteContinue {
.Parts[].Value =
if , := .Data.(*js_ast.EString); {
= .mangleTemplate(.Loc, )
}
return ,
}
}
}
if && .exprCanBeRemovedIfUnused() {
return , substituteContinue
}
return , substituteFailure
}
func ( *parser) ( js_ast.Stmt) js_ast.Stmt {
:= .fnOrArrowDataVisit.isInsideLoop
.fnOrArrowDataVisit.isInsideLoop = true
.loopBody = .Data
= .visitSingleStmt(, stmtsLoopBody)
.fnOrArrowDataVisit.isInsideLoop =
return
}
, := .Data.(*js_ast.SFunction)
:= && .Fn.HasIfScope
if {
.pushScopeForVisitPass(js_ast.ScopeBlock, .Loc)
if .isStrictMode() {
.markStrictModeFeature(ifElseFunctionStmt, js_lexer.RangeOfIdentifier(.source, .Loc), "")
}
}
:= .visitStmts([]js_ast.Stmt{}, )
if {
.popScope()
}
return stmtsToSingleStmt(.Loc, )
}
if , := [0].Data.(*js_ast.SLocal); ! || .Kind == js_ast.LocalVar {
return [0]
}
}
return js_ast.Stmt{Loc: , Data: &js_ast.SBlock{Stmts: }}
}
func ( *parser) ( js_ast.Stmt, bool) js_ast.Stmt {
switch s := .Data.(type) {
case *js_ast.SExpr:
:= js_ast.AssignTargetNone
if {
= js_ast.AssignTargetReplace
}
.Value, _ = .visitExprInOut(.Value, exprIn{assignTarget: })
case *js_ast.SLocal:
for , := range .Decls {
.visitBinding(.Binding, bindingOpts{})
if .Value != nil {
*.Value = .visitExpr(*.Value)
}
}
.Decls = .lowerObjectRestInDecls(.Decls)
.Kind = .selectLocalKind(.Kind)
default:
panic("Internal error")
}
return
}
func ( *parser) ( js_ast.Ref) {
.declaredSymbols = append(.declaredSymbols, js_ast.DeclaredSymbol{
Ref: ,
IsTopLevel: .currentScope == .moduleScope,
})
}
type bindingOpts struct {
duplicateArgCheck map[string]bool
}
func ( *parser) ( js_ast.Binding, bindingOpts) {
switch b := .Data.(type) {
case *js_ast.BMissing:
case *js_ast.BIdentifier:
.recordDeclaredSymbol(.Ref)
:= .symbols[.Ref.InnerIndex].OriginalName
if isEvalOrArguments() {
.markStrictModeFeature(evalOrArguments, js_lexer.RangeOfIdentifier(.source, .Loc), )
}
if .duplicateArgCheck != nil {
if .duplicateArgCheck[] {
.log.AddRangeError(&.source, js_lexer.RangeOfIdentifier(.source, .Loc),
fmt.Sprintf("%q cannot be bound multiple times in the same parameter list", ))
}
.duplicateArgCheck[] = true
}
case *js_ast.BArray:
for , := range .Items {
.(.Binding, )
if .DefaultValue != nil {
:= .isAnonymousNamedExpr(*.DefaultValue)
*.DefaultValue = .visitExpr(*.DefaultValue)
if , := .Binding.Data.(*js_ast.BIdentifier); {
*.DefaultValue = .maybeKeepExprSymbolName(
*.DefaultValue, .symbols[.Ref.InnerIndex].OriginalName, )
}
}
}
case *js_ast.BObject:
for , := range .Properties {
if !.IsSpread {
.Key = .visitExpr(.Key)
}
.(.Value, )
if .DefaultValue != nil {
:= .isAnonymousNamedExpr(*.DefaultValue)
*.DefaultValue = .visitExpr(*.DefaultValue)
if , := .Value.Data.(*js_ast.BIdentifier); {
*.DefaultValue = .maybeKeepExprSymbolName(
*.DefaultValue, .symbols[.Ref.InnerIndex].OriginalName, )
}
}
.Properties[] =
}
default:
panic("Internal error")
}
}
func ( js_ast.Stmt) bool {
switch s := .Data.(type) {
case *js_ast.SBlock, *js_ast.SEmpty, *js_ast.SDebugger, *js_ast.SExpr, *js_ast.SIf,
*js_ast.SFor, *js_ast.SForIn, *js_ast.SForOf, *js_ast.SDoWhile, *js_ast.SWhile,
*js_ast.SWith, *js_ast.STry, *js_ast.SSwitch, *js_ast.SReturn, *js_ast.SThrow,
*js_ast.SBreak, *js_ast.SContinue, *js_ast.SDirective:
return false
case *js_ast.SLocal:
return .Kind != js_ast.LocalVar
default:
return true
}
}
func ( js_ast.Stmt, *js_ast.Stmt) js_ast.Stmt {
if , := .Data.(*js_ast.SBlock); && len(.Stmts) > 0 {
if != nil {
.Stmts[0] = *
} else if len(.Stmts) == 2 && !statementCaresAboutScope(.Stmts[1]) {
return .Stmts[1]
} else {
.Stmts = .Stmts[1:]
}
return
}
if != nil {
return *
}
return js_ast.Stmt{Loc: .Loc, Data: &js_ast.SEmpty{}}
}
if , := .Yes.Data.(*js_ast.SBreak); && .Label == nil {
var js_ast.Expr
if , := .Test.Data.(*js_ast.EUnary); && .Op == js_ast.UnOpNot {
= .Value
} else {
= js_ast.Not(.Test)
}
if .Test != nil {
.Test = &js_ast.Expr{Loc: .Test.Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLogicalAnd, Left: *.Test, Right: }}
} else {
.Test = &
}
.Body = dropFirstStatement(.Body, .No)
return
}
if .No != nil {
if , := .No.Data.(*js_ast.SBreak); && .Label == nil {
if .Test != nil {
.Test = &js_ast.Expr{Loc: .Test.Loc, Data: &js_ast.EBinary{Op: js_ast.BinOpLogicalAnd, Left: *.Test, Right: .Test}}
} else {
.Test = &.Test
}
.Body = dropFirstStatement(.Body, &.Yes)
return
}
}
}
}
func ( []js_ast.Stmt, js_ast.Stmt) []js_ast.Stmt {
if , := .Data.(*js_ast.SBlock); {
:= false
for , := range .Stmts {
if statementCaresAboutScope() {
= true
break
}
}
if ! {
return append(, .Stmts...)
}
}
if statementCaresAboutScope() {
return append(, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SBlock{Stmts: []js_ast.Stmt{}}})
}
return append(, )
}
if , , := toBooleanWithSideEffects(.Test.Data); {
}
}
}
}
return
if .exprCanBeRemovedIfUnused(.Test) {
return .Yes
}
return js_ast.JoinWithComma(.Test, .Yes)
}
if , := .Yes.Data.(*js_ast.EIdentifier); && .Ref == .Ref {
return js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalOr, .Test, .No)
}
if , := .No.Data.(*js_ast.EIdentifier); && .Ref == .Ref {
return js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalAnd, .Test, .Yes)
}
}
if , := .No.Data.(*js_ast.EBinary); && .Op == js_ast.BinOpComma && valuesLookTheSame(.Yes.Data, .Right.Data) {
return js_ast.JoinWithComma(
js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalOr, .Test, .Left),
.Right,
)
}
if , := .Yes.Data.(*js_ast.EBinary); && .Op == js_ast.BinOpComma && valuesLookTheSame(.Right.Data, .No.Data) {
return js_ast.JoinWithComma(
js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalAnd, .Test, .Left),
.Right,
)
}
if !.options.unsupportedJSFeatures.Has(compat.NullishCoalescing) {
if , := .Test.Data.(*js_ast.EBinary); {
switch .Op {
if , := .Right.Data.(*js_ast.ENull); && .exprCanBeRemovedIfUnused(.Left) && valuesLookTheSame(.Left.Data, .No.Data) {
return js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpNullishCoalescing, .Left, .Yes)
}
if , := .Left.Data.(*js_ast.ENull); && .exprCanBeRemovedIfUnused(.Right) && valuesLookTheSame(.Right.Data, .No.Data) {
return js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpNullishCoalescing, .Right, .Yes)
}
if , := .Right.Data.(*js_ast.ENull); && .exprCanBeRemovedIfUnused(.Left) && valuesLookTheSame(.Left.Data, .Yes.Data) {
return js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpNullishCoalescing, .Left, .No)
}
if , := .Left.Data.(*js_ast.ENull); && .exprCanBeRemovedIfUnused(.Right) && valuesLookTheSame(.Right.Data, .Yes.Data) {
return js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpNullishCoalescing, .Right, .No)
}
}
}
}
return js_ast.Expr{Loc: , Data: }
}
func ( *parser) ( js_ast.Expr) bool {
switch e := .Data.(type) {
case *js_ast.EArrow:
return true
case *js_ast.EFunction:
return .Fn.Name == nil
case *js_ast.EClass:
return .Class.Name == nil
}
return false
}
func ( *parser) ( js_ast.Expr, string, bool) js_ast.Expr {
if .options.keepNames && {
return .keepExprSymbolName(, )
}
return
}
func ( *parser) ( js_ast.Expr, string) js_ast.Expr {
= .callRuntime(.Loc, "__name", []js_ast.Expr{,
{Loc: .Loc, Data: &js_ast.EString{Value: js_lexer.StringToUTF16()}},
})
.Data.(*js_ast.ECall).CanBeUnwrappedIfUnused = true
return
}
func ( *parser) ( logger.Loc, js_ast.Ref, string) js_ast.Stmt {
return js_ast.Stmt{Loc: , Data: &js_ast.SExpr{
Value: .callRuntime(, "__name", []js_ast.Expr{
{Loc: , Data: &js_ast.EIdentifier{Ref: }},
{Loc: , Data: &js_ast.EString{Value: js_lexer.StringToUTF16()}},
}),
return
case *js_ast.SDirective:
if .isStrictMode() && .LegacyOctalLoc.Start > 0 {
.markStrictModeFeature(legacyOctalEscape, .source.RangeOfLegacyOctalEscape(.LegacyOctalLoc), "")
}
case *js_ast.SImport:
.recordDeclaredSymbol(.NamespaceRef)
if .DefaultName != nil {
.recordDeclaredSymbol(.DefaultName.Ref)
}
if .Items != nil {
for , := range *.Items {
.recordDeclaredSymbol(.Name.Ref)
}
}
:= 0
for , := range .Items {
:= .loadNameFromRef(.Name.Ref)
:= .findSymbol(.AliasLoc, ).ref
for , := range .Items {
:= .loadNameFromRef(.Name.Ref)
:= .newSymbol(js_ast.SymbolOther, )
.currentScope.Generated = append(.currentScope.Generated, )
.recordDeclaredSymbol()
.Items[].Name.Ref =
}
if .options.unsupportedJSFeatures.Has(compat.ExportStarAs) {
.recordUsage(.NamespaceRef)
return append(,
js_ast.Stmt{Loc: .Loc, Data: &js_ast.SImport{
NamespaceRef: .NamespaceRef,
StarNameLoc: &.Alias.Loc,
ImportRecordIndex: .ImportRecordIndex,
}},
js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExportClause{
Items: []js_ast.ClauseItem{{
Alias: .Alias.OriginalName,
OriginalName: .Alias.OriginalName,
AliasLoc: .Alias.Loc,
Name: js_ast.LocRef{Loc: .Alias.Loc, Ref: .NamespaceRef},
}},
IsSingleLine: true,
}},
)
}
}
case *js_ast.SExportDefault:
.recordDeclaredSymbol(.DefaultName.Ref)
switch {
case .Value.Expr != nil:
:= .isAnonymousNamedExpr(*.Value.Expr)
*.Value.Expr = .visitExpr(*.Value.Expr)
*.Value.Expr = .maybeKeepExprSymbolName(*.Value.Expr, "default", )
if .options.ts.Parse {
if , := (*.Value.Expr).Data.(*js_ast.EIdentifier); {
:= .symbols[.Ref.InnerIndex]
if .Kind == js_ast.SymbolUnbound && .localTypeNames[.OriginalName] {
return
}
}
}
case .Value.Stmt != nil:
switch s2 := .Value.Stmt.Data.(type) {
var string
if .options.keepNames {
if .Fn.Name == nil {
:= .DefaultName
.Fn.Name = &
= "default"
} else {
= .symbols[.Fn.Name.Ref.InnerIndex].OriginalName
}
}
.visitFn(&.Fn, .Fn.OpenParenLoc)
= append(, )
, := .lowerClass(, js_ast.Expr{}, )
return append(, ...)
default:
panic("Internal error")
}
}
= append(, js_ast.AssignStmt(
js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
Target: js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .moduleRef}},
Name: "exports",
NameLoc: .Loc,
}},
.visitExpr(.Value),
))
.recordUsage(.moduleRef)
return
case *js_ast.SBreak:
if .Label != nil {
:= .loadNameFromRef(.Label.Ref)
.Label.Ref, _, _ = .findLabelSymbol(.Label.Loc, )
} else if !.fnOrArrowDataVisit.isInsideLoop && !.fnOrArrowDataVisit.isInsideSwitch {
:= js_lexer.RangeOfIdentifier(.source, .Loc)
.log.AddRangeError(&.source, , "Cannot use \"break\" here")
}
case *js_ast.SContinue:
if .Label != nil {
:= .loadNameFromRef(.Label.Ref)
var , bool
.Label.Ref, , = .findLabelSymbol(.Label.Loc, )
if && ! {
:= js_lexer.RangeOfIdentifier(.source, .Label.Loc)
.log.AddRangeError(&.source, , fmt.Sprintf("Cannot continue to label \"%s\"", ))
}
} else if !.fnOrArrowDataVisit.isInsideLoop {
:= js_lexer.RangeOfIdentifier(.source, .Loc)
.log.AddRangeError(&.source, , "Cannot use \"continue\" here")
}
case *js_ast.SLabel:
.pushScopeForVisitPass(js_ast.ScopeLabel, .Loc)
:= .loadNameFromRef(.Name.Ref)
:= .newSymbol(js_ast.SymbolLabel, )
.Name.Ref =
.currentScope.LabelRef =
switch .Stmt.Data.(type) {
case *js_ast.SFor, *js_ast.SForIn, *js_ast.SForOf, *js_ast.SWhile, *js_ast.SDoWhile:
.currentScope.LabelStmtIsLoop = true
}
.Stmt = .visitSingleStmt(.Stmt, stmtsNormal)
.popScope()
case *js_ast.SLocal:
for , := range .Decls {
.visitBinding(.Binding, bindingOpts{})
if .Value != nil {
:= .isAnonymousNamedExpr(*.Value)
*.Value = .visitExpr(*.Value)
if , := .Binding.Data.(*js_ast.BIdentifier); {
*.Value = .maybeKeepExprSymbolName(
*.Value, .symbols[.Ref.InnerIndex].OriginalName, )
}
if .IsExport && .enclosingNamespaceArgRef != nil {
:= func( logger.Loc, js_ast.Ref) js_ast.Expr {
.recordUsage(*.enclosingNamespaceArgRef)
return js_ast.Expr{Loc: , Data: &js_ast.EDot{
Target: js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: *.enclosingNamespaceArgRef}},
Name: .symbols[.InnerIndex].OriginalName,
NameLoc: ,
}}
}
for , := range .Decls {
if .Value != nil {
:= .convertBindingToExpr(.Binding, )
if , := .lowerObjectRestInAssign(, *.Value); {
=
} else {
= js_ast.Assign(, *.Value)
}
= append(, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: }})
}
}
return
}
.Decls = .lowerObjectRestInDecls(.Decls)
.Kind = .selectLocalKind(.Kind)
if .options.mangleSyntax {
if , := .Value.Data.(*js_ast.EUndefined); {
.Value = nil
}
}
}
case *js_ast.SBlock:
.pushScopeForVisitPass(js_ast.ScopeBlock, .Loc)
if .loopBody == {
.Stmts = .visitStmts(.Stmts, stmtsLoopBody)
} else {
.Stmts = .visitStmts(.Stmts, stmtsNormal)
}
.popScope()
if .options.mangleSyntax {
= .Stmts[0]
= js_ast.Stmt{Loc: .Loc, Data: &js_ast.SEmpty{}}
}
}
case *js_ast.SWith:
.markStrictModeFeature(withStatement, js_lexer.RangeOfIdentifier(.source, .Loc), "")
.Value = .visitExpr(.Value)
.pushScopeForVisitPass(js_ast.ScopeWith, .BodyLoc)
.Body = .visitSingleStmt(.Body, stmtsNormal)
.popScope()
case *js_ast.SWhile:
.Test = .visitExpr(.Test)
.Body = .visitLoopBody(.Body)
if .options.mangleSyntax {
.Test = .simplifyBooleanExpr(.Test)
:= &.Test
if , , := toBooleanWithSideEffects(.Test.Data); && && == noSideEffects {
= nil
}
:= &js_ast.SFor{Test: , Body: .Body}
mangleFor()
= js_ast.Stmt{Loc: .Loc, Data: }
}
case *js_ast.SDoWhile:
.Body = .visitLoopBody(.Body)
.Test = .visitExpr(.Test)
if .options.mangleSyntax {
.Test = .simplifyBooleanExpr(.Test)
}
case *js_ast.SIf:
.Test = .visitExpr(.Test)
if .options.mangleSyntax {
.Test = .simplifyBooleanExpr(.Test)
}
, , := toBooleanWithSideEffects(.Test.Data)
if && ! {
:= .isControlFlowDead
.isControlFlowDead = true
.Yes = .visitSingleStmt(.Yes, stmtsNormal)
.isControlFlowDead =
} else {
.Yes = .visitSingleStmt(.Yes, stmtsNormal)
}
if && {
:= .isControlFlowDead
.isControlFlowDead = true
*.No = .visitSingleStmt(*.No, stmtsNormal)
.isControlFlowDead =
} else {
*.No = .visitSingleStmt(*.No, stmtsNormal)
}
if .options.mangleSyntax {
if , := .No.Data.(*js_ast.SEmpty); {
.No = nil
}
}
}
if .options.mangleSyntax {
return .mangleIf(, .Loc, )
}
case *js_ast.SFor:
.pushScopeForVisitPass(js_ast.ScopeBlock, .Loc)
if .Init != nil {
.visitForLoopInit(*.Init, false)
}
if .Test != nil {
*.Test = .visitExpr(*.Test)
if .options.mangleSyntax {
*.Test = .simplifyBooleanExpr(*.Test)
if , , := toBooleanWithSideEffects(.Test.Data); && && == noSideEffects {
.Test = nil
}
}
}
if .Update != nil {
*.Update = .visitExpr(*.Update)
}
.Body = .visitLoopBody(.Body)
.popScope()
if .Init != nil {
if , := .Init.Data.(*js_ast.SLocal); && .Kind == js_ast.LocalVar {
if , := .maybeRelocateVarsToTopLevel(.Decls, relocateVarsNormal); {
if .Data != nil {
.Init = &
} else {
.Init = nil
}
}
}
}
if .options.mangleSyntax {
mangleFor()
}
case *js_ast.SForIn:
.pushScopeForVisitPass(js_ast.ScopeBlock, .Loc)
.visitForLoopInit(.Init, true)
.Value = .visitExpr(.Value)
.Body = .visitLoopBody(.Body)
.popScope()
.lowerObjectRestInForLoopInit(.Init, &.Body)
if , := .Init.Data.(*js_ast.SLocal); && .Kind == js_ast.LocalVar {
if , := .maybeRelocateVarsToTopLevel(.Decls, relocateVarsForInOrForOf); {
.Init =
}
}
case *js_ast.SForOf:
.pushScopeForVisitPass(js_ast.ScopeBlock, .Loc)
.visitForLoopInit(.Init, true)
.Value = .visitExpr(.Value)
.Body = .visitLoopBody(.Body)
.popScope()
if , := .Init.Data.(*js_ast.SLocal); && .Kind == js_ast.LocalVar {
if , := .maybeRelocateVarsToTopLevel(.Decls, relocateVarsForInOrForOf); {
.Init =
}
}
.lowerObjectRestInForLoopInit(.Init, &.Body)
case *js_ast.STry:
.pushScopeForVisitPass(js_ast.ScopeBlock, .Loc)
.fnOrArrowDataVisit.tryBodyCount++
.Body = .visitStmts(.Body, stmtsNormal)
.fnOrArrowDataVisit.tryBodyCount--
.popScope()
if .Catch != nil {
.pushScopeForVisitPass(js_ast.ScopeBlock, .Catch.Loc)
if .Catch.Binding != nil {
.visitBinding(*.Catch.Binding, bindingOpts{})
}
.Catch.Body = .visitStmts(.Catch.Body, stmtsNormal)
.lowerObjectRestInCatchBinding(.Catch)
.popScope()
}
if .Finally != nil {
.pushScopeForVisitPass(js_ast.ScopeBlock, .Finally.Loc)
.Finally.Stmts = .visitStmts(.Finally.Stmts, stmtsNormal)
.popScope()
}
case *js_ast.SSwitch:
.Test = .visitExpr(.Test)
.pushScopeForVisitPass(js_ast.ScopeBlock, .BodyLoc)
:= .fnOrArrowDataVisit.isInsideSwitch
.fnOrArrowDataVisit.isInsideSwitch = true
for , := range .Cases {
if .Value != nil {
*.Value = .visitExpr(*.Value)
.warnAboutEqualityCheck("case", *.Value, .Value.Loc)
.warnAboutTypeofAndString(.Test, *.Value)
}
.Body = .visitStmts(.Body, stmtsNormal)
.Cases[] =
}
.fnOrArrowDataVisit.isInsideSwitch =
.popScope()
.duplicateCaseChecker.reset()
for , := range .Cases {
if .Value != nil {
.duplicateCaseChecker.check(, *.Value)
}
}
case *js_ast.SFunction:
.visitFn(&.Fn, .Fn.OpenParenLoc)
if .IsExport && .enclosingNamespaceArgRef != nil {
.IsExport = false
= append(, , js_ast.AssignStmt(
js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
Target: js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: *.enclosingNamespaceArgRef}},
Name: .symbols[.Fn.Name.Ref.InnerIndex].OriginalName,
NameLoc: .Fn.Name.Loc,
}},
js_ast.Expr{Loc: .Fn.Name.Loc, Data: &js_ast.EIdentifier{Ref: .Fn.Name.Ref}},
))
} else {
= append(, )
}
:= .IsExport && .enclosingNamespaceArgRef != nil
if {
.IsExport = false
}
, := .lowerClass(, js_ast.Expr{}, )
= append(, ...)
if {
= append(, js_ast.AssignStmt(
js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
Target: js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: *.enclosingNamespaceArgRef}},
Name: .symbols[.Class.Name.Ref.InnerIndex].OriginalName,
NameLoc: .Class.Name.Loc,
}},
js_ast.Expr{Loc: .Class.Name.Loc, Data: &js_ast.EIdentifier{Ref: .Class.Name.Ref}},
))
}
return
case *js_ast.SEnum:
.recordDeclaredSymbol(.Name.Ref)
.pushScopeForVisitPass(js_ast.ScopeEntry, .Loc)
defer .popScope()
.recordDeclaredSymbol(.Arg)
for , := range .Values {
if .Ref != js_ast.InvalidRef {
.isExportedInsideNamespace[.Ref] = .Arg
}
}
:= make(map[string]float64)
.knownEnumValues[.Name.Ref] =
.knownEnumValues[.Arg] =
for , := range .Values {
:= js_lexer.UTF16ToString(.Name)
var js_ast.Expr
:= false
if .Value != nil {
*.Value = .visitExpr(*.Value)
= false
switch e := .Value.Data.(type) {
case *js_ast.ENumber:
[] = .Value
= true
= .Value + 1
case *js_ast.EString:
= true
}
} else if {
[] =
.Value = &js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: }}
++
} else {
.Value = &js_ast.Expr{Loc: .Loc, Data: &js_ast.EUndefined{}}
}
if {
= append(, )
= .generateClosureForTypeScriptNamespaceOrEnum(
, .Loc, .IsExport, .Name.Loc, .Name.Ref, .Arg, )
return
case *js_ast.SNamespace:
.recordDeclaredSymbol(.Name.Ref)
for , := range .Stmts {
if , := .Data.(*js_ast.SLocal); {
if .IsExport {
.markExportedDeclsInsideNamespace(.Arg, .Decls)
}
}
}
:= .enclosingNamespaceArgRef
.enclosingNamespaceArgRef = &.Arg
.pushScopeForVisitPass(js_ast.ScopeEntry, .Loc)
.recordDeclaredSymbol(.Arg)
:= .visitStmtsAndPrependTempRefs(.Stmts, prependTempRefsOpts{kind: stmtsFnBody})
.popScope()
.enclosingNamespaceArgRef =
= .generateClosureForTypeScriptNamespaceOrEnum(
, .Loc, .IsExport, .Name.Loc, .Name.Ref, .Arg, )
return
default:
panic("Internal error")
}
= append(, )
return
}
type relocateVarsMode uint8
const (
relocateVarsNormal relocateVarsMode = iota
relocateVarsForInOrForOf
)
if .options.mode != config.ModeBundle || .currentScope == .moduleScope {
return js_ast.Stmt{}, false
}
:= .currentScope
for !.Kind.StopsHoisting() {
= .Parent
}
if != .moduleScope {
return js_ast.Stmt{}, false
}
:= func( logger.Loc, js_ast.Ref) js_ast.Expr {
.relocatedTopLevelVars = append(.relocatedTopLevelVars, js_ast.LocRef{Loc: , Ref: })
.recordUsage()
return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}
}
var js_ast.Expr
for , := range {
:= .convertBindingToExpr(.Binding, )
if .Value != nil {
= maybeJoinWithComma(, js_ast.Assign(, *.Value))
} else if == relocateVarsForInOrForOf {
= maybeJoinWithComma(, )
}
}
return js_ast.Stmt{}, true
}
return js_ast.Stmt{Loc: .Loc, Data: &js_ast.SExpr{Value: }}, true
}
func ( *parser) ( js_ast.Expr) {
switch e := .Data.(type) {
case *js_ast.EArray:
.IsParenthesized = true
case *js_ast.EObject:
.IsParenthesized = true
}
}
func ( *parser) ( js_ast.Ref, []js_ast.Decl) {
for , := range {
.markExportedBindingInsideNamespace(, .Binding)
}
}
func ( *parser) ( js_ast.Ref, js_ast.Binding) {
switch b := .Data.(type) {
case *js_ast.BMissing:
case *js_ast.BIdentifier:
.isExportedInsideNamespace[.Ref] =
case *js_ast.BArray:
for , := range .Items {
.(, .Binding)
}
case *js_ast.BObject:
for , := range .Properties {
.(, .Value)
}
default:
panic("Internal error")
}
}
func ( *parser) ( js_ast.Expr, func(js_ast.Expr) js_ast.Expr) js_ast.Expr {
if , := .Data.(*js_ast.EIf); {
.Yes = .(.Yes, )
.No = .(.No, )
return
}
return ()
}
func ( js_ast.Expr, js_ast.Expr) js_ast.Expr {
if .Data == nil {
return
}
if .Data == nil {
return
}
return js_ast.JoinWithComma(, )
}
func ( *parser) (
logger.Loc, // The location to use for the generated references
int, // The expected number of references to generate
js_ast.Expr, // The value that might have side effects
) (
func() js_ast.Expr, // Generates reference expressions "_a"
func(js_ast.Expr) js_ast.Expr, // Call this on the final expression
) {
var func() js_ast.Expr
switch e := .Data.(type) {
case *js_ast.ENull:
= func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.ENull{}} }
case *js_ast.EUndefined:
= func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.EUndefined{}} }
case *js_ast.EThis:
= func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.EThis{}} }
case *js_ast.EBoolean:
= func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.EBoolean{Value: .Value}} }
case *js_ast.ENumber:
= func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.ENumber{Value: .Value}} }
case *js_ast.EBigInt:
= func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.EBigInt{Value: .Value}} }
case *js_ast.EString:
= func() js_ast.Expr { return js_ast.Expr{Loc: , Data: &js_ast.EString{Value: .Value}} }
case *js_ast.EIdentifier:
:= js_ast.InvalidRef
if .currentScope.Kind == js_ast.ScopeFunctionArgs {
return func() js_ast.Expr {
if == js_ast.InvalidRef {
= .generateTempRef(tempRefNoDeclare, "")
.recordUsage()
return js_ast.Assign(js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}, )
}
.recordUsage()
return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}
return js_ast.Expr{Loc: , Data: &js_ast.ECall{
Target: js_ast.Expr{Loc: , Data: &js_ast.EArrow{
Args: []js_ast.Arg{{Binding: js_ast.Binding{Loc: , Data: &js_ast.BIdentifier{Ref: }}}},
PreferExpr: true,
Body: js_ast.FnBody{Loc: , Stmts: []js_ast.Stmt{{Loc: , Data: &js_ast.SReturn{Value: &}}}},
}},
Args: []js_ast.Expr{},
}}
}
}
return func() js_ast.Expr {
if == js_ast.InvalidRef {
= .generateTempRef(tempRefNeedsDeclare, "")
.recordUsage()
return js_ast.Assign(js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}, )
}
.recordUsage()
return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: }}
},
}
func ( *parser) ( []js_ast.Expr) []js_ast.Expr {
for , := range {
[] = .visitExpr()
}
return
}
func ( *parser) ( logger.Loc, *js_ast.Class) js_ast.Ref {
.TSDecorators = .visitTSDecorators(.TSDecorators)
if .Name != nil {
.recordDeclaredSymbol(.Name.Ref)
}
:= .options.unsupportedJSFeatures.Has(compat.ClassStaticField) ||
(.options.mode == config.ModeBundle && .currentScope.Parent == nil)
.pushScopeForVisitPass(js_ast.ScopeClassName, )
:= .enclosingClassKeyword
.enclosingClassKeyword = .ClassKeyword
.currentScope.RecursiveSetStrictMode(js_ast.ImplicitStrictModeClass)
:= js_ast.InvalidRef
if .Name != nil {
= .Name.Ref
= .newSymbol(js_ast.SymbolOther, "this")
}
:= js_ast.InvalidRef
:= .symbols[.InnerIndex].OriginalName
= .newSymbol(js_ast.SymbolConst, "_"+)
.recordDeclaredSymbol()
if .Name != nil {
.currentScope.Members[] = js_ast.ScopeMember{Loc: .Name.Loc, Ref: }
}
}
if .Extends != nil {
*.Extends = .visitExpr(*.Extends)
}
.pushScopeForVisitPass(js_ast.ScopeClassBody, .BodyLoc)
defer .popScope()
for , := range .Properties {
.TSDecorators = .visitTSDecorators(.TSDecorators)
, := .Key.Data.(*js_ast.EPrivateIdentifier)
if {
.recordDeclaredSymbol(.Ref)
} else {
:= .visitExpr(.Key)
.Properties[].Key =
if .options.mangleSyntax && .IsComputed {
if , := .Data.(*js_ast.EString); && js_lexer.IsIdentifierUTF16(.Value) {
.Properties[].IsComputed = false
}
}
}
:= ""
if && .isPrivateUnsupported() {
= .symbols[.Ref.InnerIndex].OriginalName
} else if !.IsMethod && !.IsComputed &&
((!.IsStatic && .options.unsupportedJSFeatures.Has(compat.ClassField)) ||
(.IsStatic && .options.unsupportedJSFeatures.Has(compat.ClassStaticField))) {
if , := .Key.Data.(*js_ast.EString); {
= js_lexer.UTF16ToString(.Value)
}
}
if .Value != nil {
if != "" {
:= .isAnonymousNamedExpr(*.Value)
*.Value = .maybeKeepExprSymbolName(.visitExpr(*.Value), , )
} else {
*.Value = .visitExpr(*.Value)
}
}
if .Initializer != nil {
.fnOnlyDataVisit.thisClassStaticRef = &
}
if != "" {
:= .isAnonymousNamedExpr(*.Initializer)
*.Initializer = .maybeKeepExprSymbolName(.visitExpr(*.Initializer), , )
} else {
*.Initializer = .visitExpr(*.Initializer)
}
}
.currentScope.ForbidArguments = false
}
.enclosingClassKeyword =
.popScope()
if != js_ast.InvalidRef {
.Name = &js_ast.LocRef{Loc: , Ref: }
.currentScope.Generated = append(.currentScope.Generated, )
.recordDeclaredSymbol()
}
}
return
}
func ( []js_ast.Arg, bool) bool {
if {
return false
}
for , := range {
if , := .Binding.Data.(*js_ast.BIdentifier); ! || .Default != nil {
return false
}
}
return true
}
func ( []js_ast.Stmt) (logger.Loc, bool) {
for , := range {
switch s := .Data.(type) {
case *js_ast.SComment:
continue
case *js_ast.SDirective:
if js_lexer.UTF16EqualsString(.Value, "use strict") {
return .Loc, true
}
default:
return logger.Loc{}, false
}
}
return logger.Loc{}, false
}
type visitArgsOpts struct {
body []js_ast.Stmt
hasRestArg bool
isUniqueFormalParameters bool
}
func ( *parser) ( []js_ast.Arg, visitArgsOpts) {
var map[string]bool
, := fnBodyContainsUseStrict(.body)
:= isSimpleParameterList(, .hasRestArg)
if && ! {
.log.AddRangeError(&.source, .source.RangeOfString(),
"Cannot use a \"use strict\" directive in a function with a non-simple parameter list")
}
if .isUniqueFormalParameters || || ! || .isStrictMode() {
= make(map[string]bool)
}
for , := range {
.TSDecorators = .visitTSDecorators(.TSDecorators)
.visitBinding(.Binding, bindingOpts{
duplicateArgCheck: ,
})
if .Default != nil {
*.Default = .visitExpr(*.Default)
}
}
}
func ( *parser) ( js_ast.Expr, []string) bool {
switch e := .Data.(type) {
case *js_ast.EDot:
:= len() - 1
return [] == .Name && .OptionalChain == js_ast.OptionalChainNone &&
.(.Target, [:])
}
return len() == 2 && [0] == "import" && [1] == "meta"
:= .loadNameFromRef(.Ref)
if != [0] {
return false
}
:= .findSymbol(.Loc, )
if .isInsideWithScope {
return false
}
return .symbols[.ref.InnerIndex].Kind == js_ast.SymbolUnbound
}
}
return false
}
if .Data.DefineFunc != nil {
return .valueForDefine(, js_ast.AssignTargetNone, false, .Data.DefineFunc)
}
}
}
:= .findSymbol(, [0])
:= .handleIdentifier(, &js_ast.EIdentifier{
Ref: .ref,
MustKeepDueToWithStmt: .isInsideWithScope,
CanBeRemovedIfUnused: true,
}}
}
}
return
}
func ( *parser) ( logger.Loc, string) {
if .options.asciiOnly && .options.unsupportedJSFeatures.Has(compat.UnicodeEscapes) &&
js_lexer.ContainsNonBMPCodePoint() {
if .nonBMPIdentifiers == nil {
.nonBMPIdentifiers = make(map[string]bool)
}
if !.nonBMPIdentifiers[] {
.nonBMPIdentifiers[] = true
:= js_lexer.RangeOfIdentifier(.source, )
.log.AddRangeError(&.source, , fmt.Sprintf("%q cannot be escaped in the target environment ("+
"consider setting the charset to \"utf8\" or changing the target)", ))
}
}
}
func ( *parser) ( js_ast.Expr, js_ast.Expr) {
if , := .Data.(*js_ast.EUnary); && .Op == js_ast.UnOpTypeof {
if , := .Data.(*js_ast.EString); {
:= js_lexer.UTF16ToString(.Value)
switch {
case "undefined", "object", "boolean", "number", "bigint", "string", "symbol", "function", "unknown":
if !.options.suppressWarningsAboutWeirdCode {
:= .source.RangeOfString(.Loc)
.log.AddRangeWarning(&.source, , fmt.Sprintf("The \"typeof\" operator will never evaluate to %q", ))
}
}
}
}
}
func ( js_ast.Expr, js_ast.Expr) bool {
return (js_ast.IsBooleanValue() && js_ast.IsBooleanValue()) ||
(js_ast.IsNumericValue() && js_ast.IsNumericValue()) ||
(js_ast.IsStringValue() && js_ast.IsStringValue())
}
if , := .Right.Data.(*js_ast.EBoolean); && js_ast.IsBooleanValue(.Left) {
if .Value == {
return js_ast.Not(.Left), true
} else {
return .Left, true
}
}
return js_ast.Expr{}, false
}
func ( *parser) ( string, js_ast.Expr, logger.Loc) bool {
if .options.suppressWarningsAboutWeirdCode {
return false
}
switch e := .Data.(type) {
if .Value == 0 && math.Signbit(.Value) {
:= logger.Range{Loc: .Loc, Len: 0}
if int(.Loc.Start) < len(.source.Contents) && .source.Contents[.Loc.Start] == '-' {
:= .source.RangeOfNumber(logger.Loc{Start: .Loc.Start + 1})
.Len = .Len + 1
}
:= fmt.Sprintf("Comparison with -0 using the %q operator will also match 0", )
if == "case" {
= "Comparison with -0 using a case clause will also match 0"
}
.log.AddRangeWarning(&.source, , )
return true
}
if math.IsNaN(.Value) {
:= fmt.Sprintf("Comparison with NaN using the %q operator here is always %v", , [0] == '!')
if == "case" {
= "This case clause will never be evaluated because equality with NaN is always false"
}
.log.AddRangeWarning(&.source, .source.RangeOfOperatorBefore(, ), )
return true
}
case *js_ast.EArray, *js_ast.EArrow, *js_ast.EClass,
if len() > 2 {
:= fmt.Sprintf("Comparison using the %q operator here is always %v", , [0] == '!')
if == "case" {
= "This case clause will never be evaluated because the comparison is always false"
}
.log.AddRangeWarning(&.source, .source.RangeOfOperatorBefore(, ), )
return true
}
}
return false
}
func ( *parser) ( string, logger.Range) {
if .options.mode == config.ModeBundle && .options.platform == config.PlatformBrowser {
if .lackOfDefineWarnings == nil {
.lackOfDefineWarnings = make(map[string]bool)
}
if !.lackOfDefineWarnings[] {
.lackOfDefineWarnings[] = true
.log.AddRangeWarning(&.source, ,
fmt.Sprintf("Define %q when bundling for the browser", ))
}
}
}
if .options.mode == config.ModeBundle {
, := []
= js_ast.LocRef{Loc: , Ref: .newSymbol(js_ast.SymbolImport, )}
.moduleScope.Generated = append(.moduleScope.Generated, .Ref)
[] =
.isImportItem[.Ref] = true
:= &.symbols[.Ref.InnerIndex]
.NamespaceAlias = &js_ast.NamespaceAlias{
NamespaceRef: .Ref,
Alias: ,
}
.ignoreUsage(.Ref)
.recordUsage(.Ref)
return .handleIdentifier(, &js_ast.EIdentifier{Ref: .Ref}, identifierOpts{
assignTarget: ,
isDeleteTarget: ,
wasOriginallyIdentifier: false,
}), true
}
if && .Ref == .moduleRef && == "require" {
.ignoreUsage(.moduleRef)
.recordUsage(.requireRef)
return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: .requireRef}}, true
}
}
if .options.ts.Parse && == js_ast.OptionalChainNone {
if , := .knownEnumValues[.Ref]; {
if , := []; {
return js_ast.Expr{Loc: , Data: &js_ast.ENumber{Value: }}, true
}
}
}
}
return js_ast.Expr{}, false
}
func ( []uint16, []uint16) []uint16 {
:= make([]uint16, len()+len())
copy([:len()], )
copy([len():], )
return
}
func ( js_ast.Expr, js_ast.Expr) *js_ast.Expr {
switch l := .Data.(type) {
case *js_ast.EString:
switch r := .Data.(type) {
case *js_ast.EString:
return &js_ast.Expr{Loc: .Loc, Data: &js_ast.EString{
Value: joinStrings(.Value, .Value),
PreferTemplate: .PreferTemplate || .PreferTemplate,
}}
case *js_ast.ETemplate:
if .Tag == nil {
return &js_ast.Expr{Loc: .Loc, Data: &js_ast.ETemplate{Head: joinStrings(.Value, .Head), Parts: .Parts}}
}
}
case *js_ast.ETemplate:
if .Tag == nil {
switch r := .Data.(type) {
case *js_ast.EString:
:= len(.Parts)
:= .Head
:= make([]js_ast.TemplatePart, )
if == 0 {
= joinStrings(, .Value)
} else {
copy(, .Parts)
[-1].Tail = joinStrings([-1].Tail, .Value)
}
return &js_ast.Expr{Loc: .Loc, Data: &js_ast.ETemplate{Head: , Parts: }}
case *js_ast.ETemplate:
if .Tag == nil {
:= len(.Parts)
:= .Head
:= make([]js_ast.TemplatePart, +len(.Parts))
copy([:], .Parts)
if == 0 {
= joinStrings(, .Head)
} else {
copy([:], .Parts)
[-1].Tail = joinStrings([-1].Tail, .Head)
}
return &js_ast.Expr{Loc: .Loc, Data: &js_ast.ETemplate{Head: , Parts: }}
}
}
}
}
return nil
}
.Op = js_ast.BinOpComma
return .Left
}
}
case js_ast.BinOpLogicalOr:
if , , := toBooleanWithSideEffects(.Right.Data); {
.Op = js_ast.BinOpComma
return .Left
}
}
}
}
return
}
thisArgFunc func() js_ast.Expr
thisArgWrapFunc func(js_ast.Expr) js_ast.Expr
}
func ( *parser) ( js_ast.Expr) js_ast.Expr {
, _ = .visitExprInOut(, exprIn{})
return
}
if .fnOnlyDataVisit.thisClassStaticRef != nil {
.recordUsage(*.fnOnlyDataVisit.thisClassStaticRef)
return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: *.fnOnlyDataVisit.thisClassStaticRef}}, true
}
if .options.mode != config.ModePassThrough && !.fnOnlyDataVisit.isThisNested {
.recordUsage(.exportsRef)
return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: .exportsRef}}, true
}
}
return js_ast.Expr{}, false
}
func ( js_ast.Expr, js_ast.Expr, js_ast.OpCode) (js_ast.Expr, js_ast.Expr, bool) {
if , := .Data.(*js_ast.EBinary); && .Op == {
if , := .Data.(*js_ast.EBinary); && .Op == {
if , := .Left.Data.(*js_ast.EIdentifier); {
if , := .Right.Data.(*js_ast.EUndefined); {
if , := .Right.Data.(*js_ast.ENull); {
return .Left, .Right, true
}
}
}
}
}
}
return js_ast.Expr{}, js_ast.Expr{}, false
}
func ( []js_ast.Expr) ( []js_ast.Expr) {
for , := range {
if , := .Data.(*js_ast.ESpread); {
if , := .Value.Data.(*js_ast.EArray); {
for , := range .Items {
if , := .Data.(*js_ast.EMissing); {
= append(, js_ast.Expr{Loc: .Loc, Data: &js_ast.EUndefined{}})
} else {
= append(, )
}
}
continue
}
}
= append(, )
}
return
}
func ( *js_ast.EBinary) logger.Loc {
if .Left.Loc.Start < .Right.Loc.Start {
return .Right.Loc
func ( string) bool {
return == "eval" || == "arguments"
}
func ( *parser) ( js_ast.Expr) bool {
switch e := .Data.(type) {
case *js_ast.EIdentifier:
if .isStrictMode() {
if := .loadNameFromRef(.Ref); isEvalOrArguments() {
return false
}
}
return true
case *js_ast.EDot:
return .OptionalChain == js_ast.OptionalChainNone
case *js_ast.EIndex:
return .OptionalChain == js_ast.OptionalChainNone
case *js_ast.EObject:
return !.IsParenthesized
case *js_ast.EArray:
return !.IsParenthesized
}
return false
}
func ( *parser) ( js_ast.Expr, exprIn) (js_ast.Expr, exprOut) {
if .assignTarget != js_ast.AssignTargetNone && !.isValidAssignmentTarget() {
.log.AddError(&.source, .Loc, "Invalid assignment target")
}
switch e := .Data.(type) {
case *js_ast.ENull, *js_ast.ESuper,
*js_ast.EBoolean, *js_ast.EBigInt,
*js_ast.ERegExp, *js_ast.ENewTarget, *js_ast.EUndefined:
case *js_ast.EString:
if .LegacyOctalLoc.Start > 0 {
if .PreferTemplate {
.log.AddRangeError(&.source, .source.RangeOfLegacyOctalEscape(.LegacyOctalLoc),
"Legacy octal escape sequences cannot be used in template literals")
} else if .isStrictMode() {
.markStrictModeFeature(legacyOctalEscape, .source.RangeOfLegacyOctalEscape(.LegacyOctalLoc), "")
}
}
case *js_ast.ENumber:
if .legacyOctalLiterals != nil && .isStrictMode() {
if , := .legacyOctalLiterals[.Data]; {
.markStrictModeFeature(legacyOctalLiteral, , "")
}
}
case *js_ast.EThis:
if , := .valueForThis(.Loc); {
return , exprOut{}
}
if .fnOrArrowDataVisit.isArrow && .options.unsupportedJSFeatures.Has(compat.Arrow) && .fnOnlyDataVisit.isThisNested {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .captureThis()}}, exprOut{}
}
case *js_ast.EImportMeta:
:= == .deleteTarget
if , := .options.defines.DotDefines["meta"]; {
for , := range {
if .Data.DefineFunc != nil {
return .valueForDefine(.Loc, .assignTarget, , .Data.DefineFunc), exprOut{}
}
}
}
}
.recordUsage(.importMetaRef)
return js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .importMetaRef}}, exprOut{}
}
case *js_ast.ESpread:
.Value = .visitExpr(.Value)
case *js_ast.EIdentifier:
:= == .deleteTarget
:= .loadNameFromRef(.Ref)
if .isStrictMode() && js_lexer.StrictModeReservedWords[] {
.markStrictModeFeature(reservedWord, js_lexer.RangeOfIdentifier(.source, .Loc), )
}
:= .findSymbol(.Loc, )
.MustKeepDueToWithStmt = .isInsideWithScope
.Ref = .ref
if .assignTarget != js_ast.AssignTargetNone && .symbols[.ref.InnerIndex].Kind == js_ast.SymbolConst {
:= js_lexer.RangeOfIdentifier(.source, .Loc)
:= []logger.MsgData{logger.RangeData(&.source, js_lexer.RangeOfIdentifier(.source, .declareLoc),
fmt.Sprintf("%q was declared a constant here", ))}
if .options.mode == config.ModeBundle {
.log.AddRangeErrorWithNotes(&.source, , fmt.Sprintf("Cannot assign to %q because it is a constant", ), )
} else {
.log.AddRangeWarningWithNotes(&.source, , fmt.Sprintf("This assignment will throw because %q is a constant", ), )
}
}
if .symbols[.Ref.InnerIndex].Kind == js_ast.SymbolUnbound && !.isInsideWithScope && != .deleteTarget {
if , := .options.defines.IdentifierDefines[]; {
if .DefineFunc != nil {
:= .valueForDefine(.Loc, .assignTarget, , .DefineFunc)
if , := .Data.(*js_ast.EIdentifier); .assignTarget == js_ast.AssignTargetNone || {
return , exprOut{}
}
}
if .CanBeRemovedIfUnused {
.CanBeRemovedIfUnused = true
}
if .CallCanBeUnwrappedIfUnused && !.options.ignoreDCEAnnotations {
.CallCanBeUnwrappedIfUnused = true
}
if .WarnAboutLackOfDefine {
.warnAboutLackOfDefine(, js_lexer.RangeOfIdentifier(.source, .Loc))
}
}
}
return .handleIdentifier(.Loc, , identifierOpts{
assignTarget: .assignTarget,
isDeleteTarget: ,
wasOriginallyIdentifier: true,
}), exprOut{}
panic("Internal error")
for , := range .Properties {
if .Kind != js_ast.PropertySpread {
.Key = .visitExpr(.Key)
}
if .Value != nil {
*.Value = .visitExpr(*.Value)
}
if .Initializer != nil {
*.Initializer = .visitExpr(*.Initializer)
}
.Properties[] =
}
CanBeUnwrappedIfUnused: !.options.ignoreDCEAnnotations,
}}, exprOut{}
case *js_ast.ETemplate:
if .LegacyOctalLoc.Start > 0 {
.log.AddRangeError(&.source, .source.RangeOfLegacyOctalEscape(.LegacyOctalLoc),
"Legacy octal escape sequences cannot be used in template literals")
}
if .Tag != nil {
*.Tag = .visitExpr(*.Tag)
}
for , := range .Parts {
.Parts[].Value = .visitExpr(.Value)
}
if .options.mangleSyntax {
return .mangleTemplate(.Loc, ), exprOut{}
}
case *js_ast.EBinary:
:= == .callTarget
:= .isAnonymousNamedExpr(.Right)
.Left, _ = .(.Left, exprIn{assignTarget: .Op.BinaryAssignTarget()})
if .Op == js_ast.BinOpLogicalAnd && .Left.Data == .typeofRequireEqualsFn {
.typeofRequireEqualsFnTarget = .Right.Data
}
switch .Op {
case js_ast.BinOpLogicalOr:
:= .isControlFlowDead
.isControlFlowDead = true
.Right = .visitExpr(.Right)
.isControlFlowDead =
} else {
.Right = .visitExpr(.Right)
}
case js_ast.BinOpLogicalAnd:
:= .isControlFlowDead
.isControlFlowDead = true
.Right = .visitExpr(.Right)
.isControlFlowDead =
} else {
.Right = .visitExpr(.Right)
}
case js_ast.BinOpNullishCoalescing:
:= .isControlFlowDead
.isControlFlowDead = true
.Right = .visitExpr(.Right)
.isControlFlowDead =
} else {
.Right = .visitExpr(.Right)
}
default:
.Right = .visitExpr(.Right)
}
switch .Op {
case js_ast.BinOpLooseEq, js_ast.BinOpLooseNe, js_ast.BinOpStrictEq, js_ast.BinOpStrictNe:
if isPrimitiveToReorder(.Left.Data) && !isPrimitiveToReorder(.Right.Data) {
.Left, .Right = .Right, .Left
}
}
switch .Op {
if .options.mangleSyntax {
.Left = .simplifyUnusedExpr(.Left)
if && (.Left.Data == .typeofRequire || .Right.Data == .typeofRequire) {
.typeofRequireEqualsFn =
}
return js_ast.Expr{Loc: .Loc, Data: }, exprOut{}
}
:= locAfterOp()
if !.warnAboutEqualityCheck("==", .Left, ) {
.warnAboutEqualityCheck("==", .Right, )
}
.warnAboutTypeofAndString(.Left, .Right)
if , := .Right.Data.(*js_ast.EUndefined); {
.Right.Data = &js_ast.ENull{}
}
if , := maybeSimplifyEqualityComparison(, false /* isNotEqual */); {
return , exprOut{}
}
}
case js_ast.BinOpStrictEq:
if , := checkEqualityIfNoSideEffects(.Left.Data, .Right.Data); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.EBoolean{Value: }}, exprOut{}
}
:= locAfterOp()
if !.warnAboutEqualityCheck("===", .Left, ) {
.warnAboutEqualityCheck("===", .Right, )
}
.warnAboutTypeofAndString(.Left, .Right)
if canChangeStrictToLoose(.Left, .Right) {
.Op = js_ast.BinOpLooseEq
}
if , := maybeSimplifyEqualityComparison(, false /* isNotEqual */); {
return , exprOut{}
}
}
case js_ast.BinOpLooseNe:
if , := checkEqualityIfNoSideEffects(.Left.Data, .Right.Data); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.EBoolean{Value: !}}, exprOut{}
}
:= locAfterOp()
if !.warnAboutEqualityCheck("!=", .Left, ) {
.warnAboutEqualityCheck("!=", .Right, )
}
.warnAboutTypeofAndString(.Left, .Right)
if , := .Right.Data.(*js_ast.EUndefined); {
.Right.Data = &js_ast.ENull{}
}
if , := maybeSimplifyEqualityComparison(, true /* isNotEqual */); {
return , exprOut{}
}
}
case js_ast.BinOpStrictNe:
if , := checkEqualityIfNoSideEffects(.Left.Data, .Right.Data); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.EBoolean{Value: !}}, exprOut{}
}
:= locAfterOp()
if !.warnAboutEqualityCheck("!==", .Left, ) {
.warnAboutEqualityCheck("!==", .Right, )
}
.warnAboutTypeofAndString(.Left, .Right)
if canChangeStrictToLoose(.Left, .Right) {
.Op = js_ast.BinOpLooseNe
}
if , := maybeSimplifyEqualityComparison(, true /* isNotEqual */); {
return , exprOut{}
}
}
case js_ast.BinOpNullishCoalescing:
if , , := toNullOrUndefinedWithSideEffects(.Left.Data); {
if ! {
return .Left, exprOut{}
if , := .Right.Data.(*js_ast.EBinary); && .Op == js_ast.BinOpNullishCoalescing {
.Left = js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpNullishCoalescing, .Left, .Left)
.Right = .Right
}
}
if .options.unsupportedJSFeatures.Has(compat.NullishCoalescing) {
return .lowerNullishCoalescing(.Loc, .Left, .Right), exprOut{}
}
case js_ast.BinOpLogicalOr:
if , , := toBooleanWithSideEffects(.Left.Data); {
if {
return .Left, exprOut{}
if , , := isBinaryNullAndUndefined(.Left, .Right, js_ast.BinOpStrictEq); {
.Op = js_ast.BinOpLooseEq
.Left =
.Right =
}
}
case js_ast.BinOpLogicalAnd:
if , , := toBooleanWithSideEffects(.Left.Data); {
if ! {
return .Left, exprOut{}
if , , := isBinaryNullAndUndefined(.Left, .Right, js_ast.BinOpStrictNe); {
.Op = js_ast.BinOpLooseNe
.Left =
.Right =
}
}
case js_ast.BinOpAdd:
if .shouldFoldNumericConstants {
if , , := extractNumericValues(.Left, .Right); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: + }}, exprOut{}
}
}
if := foldStringAddition(.Left, .Right); != nil {
return *, exprOut{}
}
if := foldStringAddition(.Right, .Right); != nil {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.EBinary{Op: .Op, Left: .Left, Right: *}}, exprOut{}
}
}
case js_ast.BinOpSub:
if .shouldFoldNumericConstants {
if , , := extractNumericValues(.Left, .Right); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: - }}, exprOut{}
}
}
case js_ast.BinOpMul:
if .shouldFoldNumericConstants {
if , , := extractNumericValues(.Left, .Right); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: * }}, exprOut{}
}
}
case js_ast.BinOpDiv:
if .shouldFoldNumericConstants {
if , , := extractNumericValues(.Left, .Right); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: / }}, exprOut{}
}
}
case js_ast.BinOpRem:
if .shouldFoldNumericConstants {
if , , := extractNumericValues(.Left, .Right); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: math.Mod(, )}}, exprOut{}
}
}
case js_ast.BinOpPow:
if .shouldFoldNumericConstants {
if , , := extractNumericValues(.Left, .Right); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: math.Pow(, )}}, exprOut{}
}
}
if .options.unsupportedJSFeatures.Has(compat.ExponentOperator) {
return .callRuntime(.Loc, "__pow", []js_ast.Expr{.Left, .Right}), exprOut{}
}
case js_ast.BinOpShl:
if .shouldFoldNumericConstants {
if , , := extractNumericValues(.Left, .Right); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: float64(toInt32() << (toUint32() & 31))}}, exprOut{}
}
}
case js_ast.BinOpShr:
if .shouldFoldNumericConstants {
if , , := extractNumericValues(.Left, .Right); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: float64(toInt32() >> (toUint32() & 31))}}, exprOut{}
}
}
case js_ast.BinOpUShr:
if .shouldFoldNumericConstants {
if , , := extractNumericValues(.Left, .Right); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: float64(toUint32() >> (toUint32() & 31))}}, exprOut{}
}
}
case js_ast.BinOpBitwiseAnd:
if .shouldFoldNumericConstants {
if , , := extractNumericValues(.Left, .Right); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: float64(toInt32() & toInt32())}}, exprOut{}
}
}
case js_ast.BinOpBitwiseOr:
if .shouldFoldNumericConstants {
if , , := extractNumericValues(.Left, .Right); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: float64(toInt32() | toInt32())}}, exprOut{}
}
}
case js_ast.BinOpBitwiseXor:
if .shouldFoldNumericConstants {
if , , := extractNumericValues(.Left, .Right); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: float64(toInt32() ^ toInt32())}}, exprOut{}
}
}
if , := .Left.Data.(*js_ast.EIdentifier); {
.Right = .maybeKeepExprSymbolName(.Right, .symbols[.Ref.InnerIndex].OriginalName, )
}
if , , := .extractPrivateIndex(.Left); != nil {
return .lowerPrivateSet(, , , .Right), exprOut{}
}
if .assignTarget == js_ast.AssignTargetNone {
if , := .lowerObjectRestInAssign(.Left, .Right); {
return , exprOut{}
}
}
case js_ast.BinOpAddAssign:
if , , := .extractPrivateIndex(.Left); != nil {
return .lowerPrivateSetBinOp(, , , js_ast.BinOpAdd, .Right), exprOut{}
}
case js_ast.BinOpSubAssign:
if , , := .extractPrivateIndex(.Left); != nil {
return .lowerPrivateSetBinOp(, , , js_ast.BinOpSub, .Right), exprOut{}
}
case js_ast.BinOpMulAssign:
if , , := .extractPrivateIndex(.Left); != nil {
return .lowerPrivateSetBinOp(, , , js_ast.BinOpMul, .Right), exprOut{}
}
case js_ast.BinOpDivAssign:
if , , := .extractPrivateIndex(.Left); != nil {
return .lowerPrivateSetBinOp(, , , js_ast.BinOpDiv, .Right), exprOut{}
}
case js_ast.BinOpRemAssign:
if , , := .extractPrivateIndex(.Left); != nil {
return .lowerPrivateSetBinOp(, , , js_ast.BinOpRem, .Right), exprOut{}
}
if .options.unsupportedJSFeatures.Has(compat.ExponentOperator) {
return .lowerExponentiationAssignmentOperator(.Loc, ), exprOut{}
}
if , , := .extractPrivateIndex(.Left); != nil {
return .lowerPrivateSetBinOp(, , , js_ast.BinOpPow, .Right), exprOut{}
}
case js_ast.BinOpShlAssign:
if , , := .extractPrivateIndex(.Left); != nil {
return .lowerPrivateSetBinOp(, , , js_ast.BinOpShl, .Right), exprOut{}
}
case js_ast.BinOpShrAssign:
if , , := .extractPrivateIndex(.Left); != nil {
return .lowerPrivateSetBinOp(, , , js_ast.BinOpShr, .Right), exprOut{}
}
case js_ast.BinOpUShrAssign:
if , , := .extractPrivateIndex(.Left); != nil {
return .lowerPrivateSetBinOp(, , , js_ast.BinOpUShr, .Right), exprOut{}
}
case js_ast.BinOpBitwiseOrAssign:
if , , := .extractPrivateIndex(.Left); != nil {
return .lowerPrivateSetBinOp(, , , js_ast.BinOpBitwiseOr, .Right), exprOut{}
}
case js_ast.BinOpBitwiseAndAssign:
if , , := .extractPrivateIndex(.Left); != nil {
return .lowerPrivateSetBinOp(, , , js_ast.BinOpBitwiseAnd, .Right), exprOut{}
}
case js_ast.BinOpBitwiseXorAssign:
if , , := .extractPrivateIndex(.Left); != nil {
return .lowerPrivateSetBinOp(, , , js_ast.BinOpBitwiseXor, .Right), exprOut{}
}
case js_ast.BinOpNullishCoalescingAssign:
if .options.unsupportedJSFeatures.Has(compat.LogicalAssignment) {
return .lowerNullishCoalescingAssignmentOperator(.Loc, ), exprOut{}
}
case js_ast.BinOpLogicalAndAssign:
if .options.unsupportedJSFeatures.Has(compat.LogicalAssignment) {
return .lowerLogicalAssignmentOperator(.Loc, , js_ast.BinOpLogicalAnd), exprOut{}
}
case js_ast.BinOpLogicalOrAssign:
if .options.unsupportedJSFeatures.Has(compat.LogicalAssignment) {
return .lowerLogicalAssignmentOperator(.Loc, , js_ast.BinOpLogicalOr), exprOut{}
}
}
if .options.mangleSyntax {
if , := .Index.Data.(*js_ast.EString); && js_lexer.IsIdentifierUTF16(.Value) {
return .(js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
Target: .Target,
Name: js_lexer.UTF16ToString(.Value),
NameLoc: .Index.Loc,
OptionalChain: .OptionalChain,
}}, )
}
}
:= == .callTarget
:= == .deleteTarget
, := .(.Target, exprIn{
hasChainParent: .OptionalChain == js_ast.OptionalChainContinue,
})
.Target =
if , := .Index.Data.(*js_ast.EPrivateIdentifier); {
:= .loadNameFromRef(.Ref)
:= .findSymbol(.Index.Loc, )
.Ref = .ref
:= .symbols[.ref.InnerIndex].Kind
if !.IsPrivate() {
:= logger.Range{Loc: .Index.Loc, Len: int32(len())}
.log.AddRangeError(&.source, , fmt.Sprintf("Private name %q must be declared in an enclosing class", ))
} else if !.options.suppressWarningsAboutWeirdCode {
if .assignTarget != js_ast.AssignTargetNone && ( == js_ast.SymbolPrivateGet || == js_ast.SymbolPrivateStaticGet) {
:= logger.Range{Loc: .Index.Loc, Len: int32(len())}
.log.AddRangeWarning(&.source, , fmt.Sprintf("Writing to getter-only property %q will throw", ))
} else if .assignTarget != js_ast.AssignTargetReplace && ( == js_ast.SymbolPrivateSet || == js_ast.SymbolPrivateStaticSet) {
:= logger.Range{Loc: .Index.Loc, Len: int32(len())}
.log.AddRangeWarning(&.source, , fmt.Sprintf("Reading from setter-only property %q will throw", ))
}
}
if .options.unsupportedJSFeatures.Has(.Feature()) && .OptionalChain == js_ast.OptionalChainNone &&
if ! && .shouldLowerSuperPropertyAccess(.Target) {
return .lowerSuperPropertyAccess(.Loc, .Index), exprOut{}
}
:= .OptionalChain != js_ast.OptionalChainNone
if && !.hasChainParent {
return .lowerOptionalChain(, , )
}
= exprOut{
childContainsOptionalChain: ,
thisArgFunc: .thisArgFunc,
thisArgWrapFunc: .thisArgWrapFunc,
}
if !.hasChainParent {
.thisArgFunc = nil
.thisArgWrapFunc = nil
}
if , := .Index.Data.(*js_ast.EString); {
:= js_lexer.UTF16ToString(.Value)
if , := .maybeRewritePropertyAccess(
.Loc, .assignTarget, , .OptionalChain, .Target, , .Index.Loc, ); {
return ,
}
}
if .options.mode == config.ModeBundle && (.assignTarget != js_ast.AssignTargetNone || ) {
if , := .Target.Data.(*js_ast.EIdentifier); && .symbols[.Ref.InnerIndex].Kind == js_ast.SymbolImport {
:= js_lexer.RangeOfIdentifier(.source, .Target.Loc)
.log.AddRangeError(&.source, , fmt.Sprintf("Cannot assign to property on import %q", .symbols[.Ref.InnerIndex].OriginalName))
}
}
return js_ast.Expr{Loc: .Loc, Data: },
case *js_ast.EUnary:
switch .Op {
case js_ast.UnOpTypeof:
.typeofTarget = .Value.Data
, := .Value.Data.(*js_ast.EIdentifier)
.Value, _ = .(.Value, exprIn{assignTarget: .Op.UnaryAssignTarget()})
, := .Value.Data.(*js_ast.EIdentifier)
if .options.mode == config.ModeBundle {
if , := .Value.Data.(*js_ast.EIdentifier); && .Ref == .requireRef {
.ignoreUsage(.requireRef)
.typeofRequire = &js_ast.EString{Value: js_lexer.StringToUTF16("function")}
return js_ast.Expr{Loc: .Loc, Data: .typeofRequire}, exprOut{}
}
}
if , := typeofWithoutSideEffects(.Value.Data); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.EString{Value: js_lexer.StringToUTF16()}}, exprOut{}
}
var logger.Loc
switch e2 := .Value.Data.(type) {
case *js_ast.EDot:
if , := .Target.Data.(*js_ast.ESuper); {
= .Target.Loc
}
case *js_ast.EIndex:
if , := .Target.Data.(*js_ast.ESuper); {
= .Target.Loc
}
case *js_ast.EIdentifier:
.markStrictModeFeature(deleteBareName, js_lexer.RangeOfIdentifier(.source, .Value.Loc), "")
}
if !.options.suppressWarningsAboutWeirdCode && .Start != 0 {
:= js_lexer.RangeOfIdentifier(.source, )
.log.AddRangeWarning(&.source, , "Attempting to delete a property of \"super\" will throw a ReferenceError")
}
.deleteTarget = .Value.Data
:= canBeDeleted(.Value)
, := .(.Value, exprIn{hasChainParent: true})
.Value =
:= canBeDeleted(.Value)
if .childContainsOptionalChain {
return .lowerOptionalChain(, , )
}
switch .Op {
case js_ast.UnOpNot:
if .options.mangleSyntax {
.Value = .simplifyBooleanExpr(.Value)
}
if , , := toBooleanWithSideEffects(.Value.Data); && == noSideEffects {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.EBoolean{Value: !}}, exprOut{}
}
if .options.mangleSyntax {
if , := js_ast.MaybeSimplifyNot(.Value); {
return , exprOut{}
}
}
case js_ast.UnOpVoid:
if .exprCanBeRemovedIfUnused(.Value) {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.EUndefined{}}, exprOut{}
}
case js_ast.UnOpPos:
if , := toNumberWithoutSideEffects(.Value.Data); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: }}, exprOut{}
}
case js_ast.UnOpNeg:
if , := toNumberWithoutSideEffects(.Value.Data); {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENumber{Value: -}}, exprOut{}
}
case js_ast.UnOpPreDec:
if , , := .extractPrivateIndex(.Value); != nil {
return .lowerPrivateSetUnOp(, , , js_ast.BinOpSub, false), exprOut{}
}
case js_ast.UnOpPreInc:
if , , := .extractPrivateIndex(.Value); != nil {
return .lowerPrivateSetUnOp(, , , js_ast.BinOpAdd, false), exprOut{}
}
case js_ast.UnOpPostDec:
if , , := .extractPrivateIndex(.Value); != nil {
return .lowerPrivateSetUnOp(, , , js_ast.BinOpSub, true), exprOut{}
}
case js_ast.UnOpPostInc:
if , , := .extractPrivateIndex(.Value); != nil {
return .lowerPrivateSetUnOp(, , , js_ast.BinOpAdd, true), exprOut{}
}
}
}
if .options.mangleSyntax && .Op != js_ast.UnOpDelete && .Op != js_ast.UnOpTypeof {
if , := .Value.Data.(*js_ast.EBinary); && .Op == js_ast.BinOpComma {
return js_ast.JoinWithComma(.Left, js_ast.Expr{
Loc: .Right.Loc,
Data: &js_ast.EUnary{
Op: .Op,
Value: .Right,
},
}), exprOut{}
}
}
case *js_ast.EDot:
:= == .deleteTarget
:= == .callTarget
if , := .options.defines.DotDefines[.Name]; {
for , := range {
if .Data.DefineFunc != nil {
return .valueForDefine(.Loc, .assignTarget, , .Data.DefineFunc), exprOut{}
}
if .Data.CanBeRemovedIfUnused {
.CanBeRemovedIfUnused = true
}
if .Data.CallCanBeUnwrappedIfUnused && !.options.ignoreDCEAnnotations {
.CallCanBeUnwrappedIfUnused = true
}
if .Data.WarnAboutLackOfDefine {
:= js_lexer.RangeOfIdentifier(.source, .NameLoc)
= logger.Range{Loc: .Loc, Len: .End() - .Loc.Start}
.warnAboutLackOfDefine(strings.Join(.Parts, "."), )
}
break
}
}
}
if .options.outputFormat == config.FormatCommonJS {
.cjsDotTarget = .Target.Data
}
if && .thenCatchChain.nextTarget == {
if .Name == "catch" {
.thenCatchChain = thenCatchChain{
nextTarget: .Target.Data,
hasCatch: true,
}
} else if .Name == "then" {
.thenCatchChain = thenCatchChain{
nextTarget: .Target.Data,
hasCatch: .thenCatchChain.hasCatch || .thenCatchChain.hasMultipleArgs,
}
}
}
, := .(.Target, exprIn{
hasChainParent: .OptionalChain == js_ast.OptionalChainContinue,
})
.Target =
:= .OptionalChain != js_ast.OptionalChainNone
if && !.hasChainParent {
return .lowerOptionalChain(, , )
}
= exprOut{
childContainsOptionalChain: ,
thisArgFunc: .thisArgFunc,
thisArgWrapFunc: .thisArgWrapFunc,
}
if !.hasChainParent {
.thisArgFunc = nil
.thisArgWrapFunc = nil
}
if , := .maybeRewritePropertyAccess(.Loc, .assignTarget, , .OptionalChain, .Target, .Name, .NameLoc, ); {
return ,
}
return js_ast.Expr{Loc: .Loc, Data: },
case *js_ast.EIf:
:= == .callTarget
.Test = .visitExpr(.Test)
if .options.mangleSyntax {
.Test = .simplifyBooleanExpr(.Test)
}
.Yes = .visitExpr(.Yes)
:= .isControlFlowDead
.isControlFlowDead = true
.No = .visitExpr(.No)
.isControlFlowDead =
if == couldHaveSideEffects {
return maybeJoinWithComma(.simplifyUnusedExpr(.Test), .Yes), exprOut{}
}
:= .isControlFlowDead
.isControlFlowDead = true
.Yes = .visitExpr(.Yes)
.isControlFlowDead =
.No = .visitExpr(.No)
if == couldHaveSideEffects {
return maybeJoinWithComma(.simplifyUnusedExpr(.Test), .No), exprOut{}
}
if && hasValueForThisInCall(.No) {
return js_ast.JoinWithComma(js_ast.Expr{Loc: .Test.Loc, Data: &js_ast.ENumber{}}, .No), exprOut{}
}
return .No, exprOut{}
}
}
}
if .options.mangleSyntax {
return .mangleIfExpr(.Loc, ), exprOut{}
}
case *js_ast.EAwait:
.awaitTarget = .Value.Data
.Value = .visitExpr(.Value)
if .options.unsupportedJSFeatures.Has(compat.AsyncAwait) {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.EYield{Value: &.Value}}, exprOut{}
}
case *js_ast.EYield:
if .Value != nil {
*.Value = .visitExpr(*.Value)
}
case *js_ast.EArray:
if .assignTarget != js_ast.AssignTargetNone {
if .CommaAfterSpread.Start != 0 {
.log.AddRangeError(&.source, logger.Range{Loc: .CommaAfterSpread, Len: 1}, "Unexpected \",\" after rest pattern")
}
.markSyntaxFeature(compat.Destructuring, logger.Range{Loc: .Loc, Len: 1})
}
:= false
for , := range .Items {
switch e2 := .Data.(type) {
case *js_ast.EMissing:
case *js_ast.ESpread:
.Value, _ = .(.Value, exprIn{assignTarget: .assignTarget})
= true
case *js_ast.EBinary:
if .assignTarget != js_ast.AssignTargetNone && .Op == js_ast.BinOpAssign {
:= .isAnonymousNamedExpr(.Right)
.Left, _ = .(.Left, exprIn{assignTarget: js_ast.AssignTargetReplace})
.Right = .visitExpr(.Right)
if , := .Left.Data.(*js_ast.EIdentifier); {
.Right = .maybeKeepExprSymbolName(
.Right, .symbols[.Ref.InnerIndex].OriginalName, )
}
} else {
, _ = .(, exprIn{assignTarget: .assignTarget})
}
default:
, _ = .(, exprIn{assignTarget: .assignTarget})
}
.Items[] =
}
if .options.mangleSyntax && && .assignTarget == js_ast.AssignTargetNone {
.Items = inlineSpreadsOfArrayLiterals(.Items)
}
case *js_ast.EObject:
if .assignTarget != js_ast.AssignTargetNone {
if .CommaAfterSpread.Start != 0 {
.log.AddRangeError(&.source, logger.Range{Loc: .CommaAfterSpread, Len: 1}, "Unexpected \",\" after rest pattern")
}
.markSyntaxFeature(compat.Destructuring, logger.Range{Loc: .Loc, Len: 1})
}
:= false
:= false
for := range .Properties {
:= &.Properties[]
if .Kind != js_ast.PropertySpread {
:= .visitExpr(.Key)
.Properties[].Key =
if !.IsComputed && !.WasShorthand && !.IsMethod && .assignTarget == js_ast.AssignTargetNone {
if , := .Data.(*js_ast.EString); && js_lexer.UTF16EqualsString(.Value, "__proto__") {
if {
:= js_lexer.RangeOfIdentifier(.source, .Loc)
.log.AddRangeError(&.source, , "Cannot specify the \"__proto__\" property more than once per object")
}
= true
}
}
if .options.mangleSyntax && .IsComputed {
if , := .Data.(*js_ast.EString); && js_lexer.IsIdentifierUTF16(.Value) {
.IsComputed = false
}
}
} else {
= true
}
if .assignTarget != js_ast.AssignTargetNone && .Initializer == nil && .Value != nil {
if , := .Value.Data.(*js_ast.EBinary); && .Op == js_ast.BinOpAssign {
.Initializer = &.Right
.Value = &.Left
}
}
if .Value != nil {
*.Value, _ = .(*.Value, exprIn{assignTarget: .assignTarget})
}
if .Initializer != nil {
:= .isAnonymousNamedExpr(*.Initializer)
*.Initializer = .visitExpr(*.Initializer)
if .Value != nil {
if , := .Value.Data.(*js_ast.EIdentifier); {
*.Initializer = .maybeKeepExprSymbolName(
*.Initializer, .symbols[.Ref.InnerIndex].OriginalName, )
}
}
}
}
if len(.Properties) > 1 && !.options.suppressWarningsAboutWeirdCode {
type uint8
type struct {
logger.Loc
}
const (
= iota
)
:= make(map[string])
for , := range .Properties {
if .Kind != js_ast.PropertySpread {
if , := .Key.Data.(*js_ast.EString); {
:= js_lexer.UTF16ToString(.Value)
:= []
:= {: , : .Key.Loc}
if .Kind == js_ast.PropertyGet {
. =
} else if .Kind == js_ast.PropertySet {
. =
}
if . != && != "__proto__" {
if (. == && . == ) || (. == && . == ) {
. =
} else {
:= js_lexer.RangeOfIdentifier(.source, .Key.Loc)
.log.AddRangeWarningWithNotes(&.source, , fmt.Sprintf("Duplicate key %q in object literal", ),
[]logger.MsgData{logger.RangeData(&.source, js_lexer.RangeOfIdentifier(.source, .),
fmt.Sprintf("The original %q is here", ))})
}
}
[] =
}
}
}
}
if .options.mangleSyntax && {
var []js_ast.Property
for , := range .Properties {
if .Kind == js_ast.PropertySpread {
switch v := .Value.Data.(type) {
case *js_ast.EBoolean, *js_ast.ENull, *js_ast.EUndefined, *js_ast.ENumber,
if .Kind == js_ast.PropertyGet || .Kind == js_ast.PropertySet {
.Properties = .Properties[:]
= append(, )
break
}
= append(, )
}
continue
}
}
= append(, )
}
.Properties =
}
return .lowerObjectSpread(.Loc, ), exprOut{}
}
case *js_ast.EImport:
:= == .awaitTarget
:= == .thenCatchChain.nextTarget && .thenCatchChain.hasCatch
.Expr = .visitExpr(.Expr)
if .isControlFlowDead {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENull{}}
}
:= .addImportRecord(ast.ImportDynamic, .Loc, js_lexer.UTF16ToString(.Value))
.importRecordsForCurrentPart = append(.importRecordsForCurrentPart, )
return js_ast.Expr{Loc: .Loc, Data: &js_ast.EImport{
Expr: ,
ImportRecordIndex: ast.MakeIndex32(),
LeadingInteriorComments: .LeadingInteriorComments,
}}
}
:= (.fnOrArrowDataVisit.tryBodyCount != 0 && ) ||
if ! {
:= "This dynamic import will not be bundled because the argument is not a string literal"
if {
+= " (surround with a try/catch to silence this warning)"
} else {
+= " (use \"import().catch()\" to silence this warning)"
}
:= js_lexer.RangeOfIdentifier(.source, .Loc)
.log.AddRangeWarning(&.source, , )
}
}
if !.options.outputFormat.KeepES6ImportExportSyntax() {
var js_ast.Expr
:= .callRuntime(.Loc, "__toModule", []js_ast.Expr{{Loc: .Loc, Data: &js_ast.ECall{
Target: js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .requireRef}},
Args: []js_ast.Expr{},
}}})
:= js_ast.FnBody{Loc: .Loc, Stmts: []js_ast.Stmt{{Loc: .Loc, Data: &js_ast.SReturn{Value: &}}}}
if .options.unsupportedJSFeatures.Has(compat.Arrow) {
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EFunction{Fn: js_ast.Fn{Body: }}}
} else {
= js_ast.Expr{Loc: .Loc, Data: &js_ast.EArrow{Body: , PreferExpr: true}}
}
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ECall{
Target: js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
Target: js_ast.Expr{Loc: .Loc, Data: &js_ast.ECall{
Target: js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
Target: js_ast.Expr{Loc: .Loc, Data: &js_ast.EIdentifier{Ref: .makePromiseRef()}},
Name: "resolve",
NameLoc: .Loc,
}},
}},
Name: "then",
NameLoc: .Loc,
}},
Args: []js_ast.Expr{},
}}
}
return js_ast.Expr{Loc: .Loc, Data: &js_ast.EImport{
Expr: ,
LeadingInteriorComments: .LeadingInteriorComments,
}}
}), exprOut{}
case *js_ast.ECall:
.callTarget = .Target.Data
.thenCatchChain = thenCatchChain{
nextTarget: .Target.Data,
hasMultipleArgs: len(.Args) >= 2,
hasCatch: .thenCatchChain.nextTarget == && .thenCatchChain.hasCatch,
}
:= false
if len(.Args) == 1 && .options.mode != config.ModePassThrough {
if , := .Target.Data.(*js_ast.EDot); && .OptionalChain == js_ast.OptionalChainNone && .Name == "resolve" {
.resolveCallTarget = .Target.Data
= true
}
}
, := .Target.Data.(*js_ast.EIdentifier)
, := .(.Target, exprIn{
hasChainParent: .OptionalChain == js_ast.OptionalChainContinue,
storeThisArgForParentOptionalChain: .OptionalChain == js_ast.OptionalChainStart,
})
.Target =
.warnAboutImportNamespaceCallOrConstruct(.Target, false /* isConstruct */)
:= false
for , := range .Args {
= .visitExpr()
if , := .Data.(*js_ast.ESpread); {
= true
}
.Args[] =
}
if .isControlFlowDead {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENull{}}
}
:= .addImportRecord(ast.ImportRequireResolve, .Args[0].Loc, js_lexer.UTF16ToString(.Value))
.importRecords[].IsInsideTryBody = .fnOrArrowDataVisit.tryBodyCount != 0
.importRecordsForCurrentPart = append(.importRecordsForCurrentPart, )
.ignoreUsage(.requireRef)
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ERequireResolve{ImportRecordIndex: }}
}
if .options.mangleSyntax && && .assignTarget == js_ast.AssignTargetNone {
.Args = inlineSpreadsOfArrayLiterals(.Args)
}
if {
if , := .Target.Data.(*js_ast.EIdentifier); {
if := .symbols[.Ref.InnerIndex]; .OriginalName == "eval" {
.IsDirectEval = true
if .options.mode == config.ModeBundle && !.hasESModuleSyntax {
.recordUsage(.moduleRef)
.recordUsage(.exportsRef)
}
for := .currentScope; != nil; = .Parent {
.ContainsDirectEval = true
}
if .options.mode == config.ModeBundle && .es6ImportKeyword.Len > 0 && !.options.suppressWarningsAboutWeirdCode {
.log.AddRangeWarning(&.source, js_lexer.RangeOfIdentifier(.source, .Target.Loc),
"Using direct eval with a bundler is not recommended and may cause problems (more info: https://esbuild.github.io/link/direct-eval)")
}
}
}
}
switch t := .Data.(type) {
case *js_ast.EIdentifier:
if .CallCanBeUnwrappedIfUnused {
.CanBeUnwrappedIfUnused = true
}
case *js_ast.EDot:
if .CallCanBeUnwrappedIfUnused {
.CanBeUnwrappedIfUnused = true
}
}
:= .OptionalChain != js_ast.OptionalChainNone
if && !.hasChainParent {
return .lowerOptionalChain(, , )
}
if ! {
, := .captureValueWithPossibleSideEffects(.Loc, 2, )
return (js_ast.Expr{Loc: .Loc, Data: &js_ast.ECall{
Target: js_ast.Expr{Loc: .Loc, Data: &js_ast.EDot{
Target: .lowerPrivateGet((), , ),
Name: "call",
NameLoc: .Loc,
}},
Args: append([]js_ast.Expr{()}, .Args...),
CanBeUnwrappedIfUnused: .CanBeUnwrappedIfUnused,
}}), exprOut{}
}
.maybeLowerSuperPropertyAccessInsideCall()
}
if .options.mode != config.ModePassThrough && .OptionalChain == js_ast.OptionalChainNone {
:= .fnOrArrowDataVisit.tryBodyCount != 0
if .isControlFlowDead {
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ENull{}}
}
:= .addImportRecord(ast.ImportRequire, .Loc, js_lexer.UTF16ToString(.Value))
.importRecords[].IsInsideTryBody = .fnOrArrowDataVisit.tryBodyCount != 0
.importRecordsForCurrentPart = append(.importRecordsForCurrentPart, )
.ignoreUsage(.requireRef)
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ERequire{ImportRecordIndex: }}
}
if ! {
:= js_lexer.RangeOfIdentifier(.source, .Target.Loc)
.log.AddRangeWarning(&.source, ,
"This call to \"require\" will not be bundled because the argument is not a string literal (surround with a try/catch to silence this warning)")
}
return js_ast.Expr{Loc: .Loc, Data: &js_ast.ECall{
Target: js_ast.Expr{Loc: .Target.Loc, Data: &js_ast.EIdentifier{Ref: .Ref}},
Args: []js_ast.Expr{},
}}
}), exprOut{}
} else if ! {
:= js_lexer.RangeOfIdentifier(.source, .Target.Loc)
.log.AddRangeWarning(&.source, , fmt.Sprintf(
"This call to \"require\" will not be bundled because it has %d arguments (surround with a try/catch to silence this warning)", len(.Args)))
}
} else if .options.outputFormat == config.FormatESModule && ! {
:= js_lexer.RangeOfIdentifier(.source, .Target.Loc)
.log.AddRangeWarning(&.source, , "Converting \"require\" to \"esm\" is currently not supported")
}
}
}
= exprOut{
childContainsOptionalChain: ,
thisArgFunc: .thisArgFunc,
thisArgWrapFunc: .thisArgWrapFunc,
}
if !.hasChainParent {
.thisArgFunc = nil
.thisArgWrapFunc = nil
}
return ,
case *js_ast.ENew:
.Target = .visitExpr(.Target)
.warnAboutImportNamespaceCallOrConstruct(.Target, true /* isConstruct */)
for , := range .Args {
.Args[] = .visitExpr()
}
case *js_ast.EArrow:
:= .fnOrArrowDataVisit
.fnOrArrowDataVisit = fnOrArrowDataVisit{
isArrow: true,
isAsync: .IsAsync,
}
:= .fnOnlyDataVisit.isInsideAsyncArrowFn
if .IsAsync {
.fnOnlyDataVisit.isInsideAsyncArrowFn = true
}
.pushScopeForVisitPass(js_ast.ScopeFunctionArgs, .Loc)
.visitArgs(.Args, visitArgsOpts{
hasRestArg: .HasRestArg,
body: .Body.Stmts,
isUniqueFormalParameters: true,
})
.pushScopeForVisitPass(js_ast.ScopeFunctionBody, .Body.Loc)
.Body.Stmts = .visitStmtsAndPrependTempRefs(.Body.Stmts, prependTempRefsOpts{kind: stmtsFnBody})
.popScope()
.lowerFunction(&.IsAsync, &.Args, .Body.Loc, &.Body.Stmts, &.PreferExpr, &.HasRestArg, true /* isArrow */)
.popScope()
if .options.mangleSyntax && len(.Body.Stmts) == 1 {
if , := .Body.Stmts[0].Data.(*js_ast.SReturn); {
.PreferExpr = true
}
}
}
.fnOnlyDataVisit.isInsideAsyncArrowFn =
.fnOrArrowDataVisit =
if .options.mangleSyntax && != nil && .symbols[.Ref.InnerIndex].UseCountEstimate == 0 {
.Fn.Name = nil
}
if .options.keepNames && != nil {
= .keepExprSymbolName(, .symbols[.Ref.InnerIndex].OriginalName)
}
case *js_ast.EClass:
:= .visitClass(.Loc, &.Class)
_, = .lowerClass(js_ast.Stmt{}, , )
default:
panic("Internal error")
}
return , exprOut{}
}
func ( *parser) ( js_ast.Expr, bool) {
if .options.outputFormat != config.FormatPreserve {
if , := .Data.(*js_ast.EIdentifier); && .importItemsForNamespace[.Ref] != nil {
:= js_lexer.RangeOfIdentifier(.source, .Loc)
:= ""
if .options.ts.Parse {
= " (make sure to enable TypeScript's \"esModuleInterop\" setting)"
}
var []logger.MsgData
:= .symbols[.Ref.InnerIndex].OriginalName
if , := .moduleScope.Members[]; && .Ref == .Ref {
if := .source.RangeOfOperatorBefore(.Loc, "*"); .Len > 0 {
if := .source.RangeOfOperatorBefore(.Loc, "as"); .Len > 0 && .Loc.Start > .Loc.Start {
:= logger.RangeData(&.source,
logger.Range{Loc: .Loc, Len: js_lexer.RangeOfIdentifier(.source, .Loc).End() - .Loc.Start},
fmt.Sprintf("Consider changing %q to a default import instead", ))
.Location.Suggestion =
= []logger.MsgData{}
}
}
}
:= "Calling"
:= "function"
if {
= "Constructing"
= "constructor"
}
.log.AddRangeWarningWithNotes(&.source, , fmt.Sprintf(
"%s %q will crash at run-time because it's an import namespace object, not a %s%s",
,
.symbols[.Ref.InnerIndex].OriginalName,
,
),
,
)
}
}
}
func ( *parser) ( logger.Loc, js_ast.AssignTarget, bool, config.DefineFunc) js_ast.Expr {
:= js_ast.Expr{Loc: , Data: (config.DefineArgs{
Loc: ,
FindSymbol: .findSymbolHelper,
SymbolForDefine: .symbolForDefineHelper,
})}
if , := .Data.(*js_ast.EIdentifier); {
return .handleIdentifier(, , identifierOpts{
assignTarget: ,
isDeleteTarget: ,
wasOriginallyIdentifier: true,
})
}
return
}
type identifierOpts struct {
assignTarget js_ast.AssignTarget
isDeleteTarget bool
wasOriginallyIdentifier bool
}
func ( *parser) ( logger.Loc, *js_ast.EIdentifier, identifierOpts) js_ast.Expr {
:= .Ref
if .fnOnlyDataVisit.argumentsRef != nil && == *.fnOnlyDataVisit.argumentsRef {
:= .fnOrArrowDataVisit.isArrow && .options.unsupportedJSFeatures.Has(compat.Arrow)
:= .fnOnlyDataVisit.isInsideAsyncArrowFn && .options.unsupportedJSFeatures.Has(compat.AsyncAwait)
if || {
return js_ast.Expr{Loc: , Data: &js_ast.EIdentifier{Ref: .captureArguments()}}
}
}
if .options.mode == config.ModeBundle && (.assignTarget != js_ast.AssignTargetNone || .isDeleteTarget) {
:= js_lexer.RangeOfIdentifier(.source, )
.log.AddRangeError(&.source, , fmt.Sprintf("Cannot assign to import %q", .symbols[.InnerIndex].OriginalName))
:= .symbolUses[]
.IsAssigned = true
.symbolUses[] =
}
}
if .isImportItem[] {
return js_ast.Expr{Loc: , Data: &js_ast.EImportIdentifier{
Ref: ,
WasOriginallyIdentifier: .wasOriginallyIdentifier,
}}
}
if .options.ts.Parse {
if , := .isExportedInsideNamespace[]; {
:= .symbols[.InnerIndex].OriginalName
if .options.platform == config.PlatformBrowser {
return js_ast.Expr{Loc: , Data: &js_ast.EBoolean{Value: false}}
}
} else if != .resolveCallTarget {
:= js_lexer.RangeOfIdentifier(.source, )
.log.AddRangeWarning(&.source, ,
"Indirect calls to \"require\" will not be bundled (surround with a try/catch to silence this warning)")
}
}
return js_ast.Expr{Loc: , Data: }
}
func ( js_ast.Expr, js_ast.Expr) (float64, float64, bool) {
if , := .Data.(*js_ast.ENumber); {
if , := .Data.(*js_ast.ENumber); {
return .Value, .Value, true
}
}
return 0, 0, false
}
func ( *parser) ( *js_ast.Fn, logger.Loc) {
:= .fnOrArrowDataVisit
:= .fnOnlyDataVisit
.fnOrArrowDataVisit = fnOrArrowDataVisit{
isAsync: .IsAsync,
}
.fnOnlyDataVisit = fnOnlyDataVisit{
isThisNested: true,
argumentsRef: &.ArgumentsRef,
}
if .Name != nil {
.recordDeclaredSymbol(.Name.Ref)
if := .symbols[.Name.Ref.InnerIndex].OriginalName; isEvalOrArguments() {
.markStrictModeFeature(evalOrArguments, js_lexer.RangeOfIdentifier(.source, .Name.Loc), )
}
}
.pushScopeForVisitPass(js_ast.ScopeFunctionArgs, )
.visitArgs(.Args, visitArgsOpts{
hasRestArg: .HasRestArg,
body: .Body.Stmts,
isUniqueFormalParameters: .IsUniqueFormalParameters,
})
.pushScopeForVisitPass(js_ast.ScopeFunctionBody, .Body.Loc)
.Body.Stmts = .visitStmtsAndPrependTempRefs(.Body.Stmts, prependTempRefsOpts{fnBodyLoc: &.Body.Loc, kind: stmtsFnBody})
.popScope()
.lowerFunction(&.IsAsync, &.Args, .Body.Loc, &.Body.Stmts, nil, &.HasRestArg, false /* isArrow */)
.popScope()
.fnOrArrowDataVisit =
.fnOnlyDataVisit =
}
func ( *parser) ( logger.Loc, string, js_ast.Ref) {
.log.AddRangeErrorWithNotes(&.source, js_lexer.RangeOfIdentifier(.source, ),
fmt.Sprintf("Multiple exports with the same name %q", ),
[]logger.MsgData{logger.RangeData(&.source, js_lexer.RangeOfIdentifier(.source, .AliasLoc),
fmt.Sprintf("%q was originally exported here", ))})
} else {
.namedExports[] = js_ast.NamedExport{AliasLoc: , Ref: }
}
}
func ( *parser) ( js_ast.Binding) {
switch b := .Data.(type) {
case *js_ast.BMissing:
case *js_ast.BIdentifier:
.recordExport(.Loc, .symbols[.Ref.InnerIndex].OriginalName, .Ref)
case *js_ast.BArray:
for , := range .Items {
.(.Binding)
}
case *js_ast.BObject:
for , := range .Properties {
.(.Value)
}
default:
panic("Internal error")
}
}
type scanForImportsAndExportsResult struct {
stmts []js_ast.Stmt
keptImportEquals bool
removedImportEquals bool
}
func ( *parser) ( []js_ast.Stmt) ( scanForImportsAndExportsResult) {
:= 0
for , := range {
switch s := .Data.(type) {
case *js_ast.SImport:
:= .options.ts.Parse && .options.preserveUnusedImportsTS &&
.options.mode != config.ModeBundle && !.options.minifyIdentifiers
if .DefaultName != nil {
= true
:= .symbols[.DefaultName.Ref.InnerIndex]
if .options.ts.Parse && .tsUseCounts[.DefaultName.Ref.InnerIndex] != 0 {
= false
}
if .UseCountEstimate == 0 {
.DefaultName = nil
}
}
if .StarNameLoc != nil {
= true
:= .symbols[.NamespaceRef.InnerIndex]
if .options.ts.Parse && .tsUseCounts[.NamespaceRef.InnerIndex] != 0 {
= false
}
if , := .importItemsForNamespace[.NamespaceRef]; && len() == 0 {
.StarNameLoc = nil
}
}
}
if .options.ts.Parse && .tsUseCounts[.Name.Ref.InnerIndex] != 0 {
= false
}
if .UseCountEstimate != 0 {
(*.Items)[] =
++
}
}
if := &.importRecords[.ImportRecordIndex]; !.SourceIndex.IsValid() {
.IsUnused = true
continue
}
}
}
if .options.mode != config.ModePassThrough {
:= .symbols[.NamespaceRef.InnerIndex].UseCountEstimate == 0
if && ! {
.StarNameLoc = nil
}
:= make([]js_ast.ClauseItem, 0, len())
for , := range {
:= []
:= .symbols[.Ref.InnerIndex].OriginalName
= append(, js_ast.ClauseItem{
Alias: ,
AliasLoc: .Loc,
Name: ,
OriginalName: ,
})
.declaredSymbols = append(.declaredSymbols, js_ast.DeclaredSymbol{
Ref: .Ref,
IsTopLevel: true,
})
}
for , := range {
:= []
.namedImports[.Ref] = js_ast.NamedImport{
Alias: ,
AliasLoc: .Loc,
NamespaceRef: .NamespaceRef,
ImportRecordIndex: .ImportRecordIndex,
}
.symbols[.Ref.InnerIndex].NamespaceAlias = &js_ast.NamespaceAlias{
NamespaceRef: .NamespaceRef,
Alias: ,
}
}
}
}
}
if .DefaultName != nil {
.namedImports[.DefaultName.Ref] = js_ast.NamedImport{
Alias: "default",
AliasLoc: .DefaultName.Loc,
NamespaceRef: .NamespaceRef,
ImportRecordIndex: .ImportRecordIndex,
}
}
if .StarNameLoc != nil {
.namedImports[.NamespaceRef] = js_ast.NamedImport{
Alias: "*",
AliasLoc: *.StarNameLoc,
NamespaceRef: js_ast.InvalidRef,
ImportRecordIndex: .ImportRecordIndex,
}
}
if .Items != nil {
for , := range *.Items {
.namedImports[.Name.Ref] = js_ast.NamedImport{
Alias: .Alias,
AliasLoc: .AliasLoc,
NamespaceRef: .NamespaceRef,
ImportRecordIndex: .ImportRecordIndex,
}
}
}
}
.importRecordsForCurrentPart = append(.importRecordsForCurrentPart, .ImportRecordIndex)
if .StarNameLoc != nil {
.importRecords[.ImportRecordIndex].ContainsImportStar = true
}
case *js_ast.SFunction:
if .IsExport {
.recordExport(.Fn.Name.Loc, .symbols[.Fn.Name.Ref.InnerIndex].OriginalName, .Fn.Name.Ref)
}
case *js_ast.SClass:
if .IsExport {
.recordExport(.Class.Name.Loc, .symbols[.Class.Name.Ref.InnerIndex].OriginalName, .Class.Name.Ref)
}
case *js_ast.SLocal:
if .IsExport {
for , := range .Decls {
.recordExportedBinding(.Binding)
}
}
if .WasTSImportEquals && !.IsExport {
:= .Decls[0]
.ignoreUsage(.Ref)
.removedImportEquals = true
continue
} else {
.keptImportEquals = true
}
}
}
case *js_ast.SExportDefault:
.recordExport(.DefaultName.Loc, "default", .DefaultName.Ref)
case *js_ast.SExportClause:
for , := range .Items {
.recordExport(.AliasLoc, .Alias, .Name.Ref)
}
case *js_ast.SExportStar:
.importRecordsForCurrentPart = append(.importRecordsForCurrentPart, .ImportRecordIndex)
.namedImports[.NamespaceRef] = js_ast.NamedImport{
Alias: "*",
AliasLoc: .Alias.Loc,
NamespaceRef: js_ast.InvalidRef,
ImportRecordIndex: .ImportRecordIndex,
IsExported: true,
}
.recordExport(.Alias.Loc, .Alias.OriginalName, .NamespaceRef)
.namedImports[.Name.Ref] = js_ast.NamedImport{
Alias: .OriginalName,
AliasLoc: .Name.Loc,
NamespaceRef: .NamespaceRef,
ImportRecordIndex: .ImportRecordIndex,
IsExported: true,
}
.recordExport(.Name.Loc, .Alias, .Name.Ref)
}
}
[] =
++
}
.stmts = [:]
return
}
func ( *parser) ( []js_ast.Part, []js_ast.Stmt) []js_ast.Part {
.symbolUses = make(map[js_ast.Ref]js_ast.SymbolUse)
.declaredSymbols = nil
.importRecordsForCurrentPart = nil
.scopesForCurrentPart = nil
:= js_ast.Part{
Stmts: .visitStmtsAndPrependTempRefs(, prependTempRefsOpts{}),
SymbolUses: .symbolUses,
}
for {
:= .symbols[.Ref.InnerIndex].Link
if == js_ast.InvalidRef {
break
}
.Ref =
}
if ![.Ref] {
[.Ref] = true
.Stmts = append(.Stmts, js_ast.Stmt{Loc: .Loc, Data: &js_ast.SLocal{
Decls: []js_ast.Decl{{
Binding: js_ast.Binding{Loc: .Loc, Data: &js_ast.BIdentifier{Ref: .Ref}},
}},
}})
}
}
.relocatedTopLevelVars = nil
}
if len(.Stmts) > 0 {
.CanBeRemovedIfUnused = .stmtsCanBeRemovedIfUnused(.Stmts)
.DeclaredSymbols = .declaredSymbols
.ImportRecordIndices = .importRecordsForCurrentPart
.Scopes = .scopesForCurrentPart
= append(, )
}
return
}
func ( *parser) ( []js_ast.Stmt) bool {
for , := range {
switch s := .Data.(type) {
break
}
if !.exprCanBeRemovedIfUnused(.Value) {
return false
}
case *js_ast.SLocal:
for , := range .Decls {
if !.bindingCanBeRemovedIfUnused(.Binding) {
return false
}
if .Value != nil && !.exprCanBeRemovedIfUnused(*.Value) {
return false
}
}
return false
}
}
return true
}
func ( *parser) ( js_ast.Class) bool {
if .Extends != nil && !.exprCanBeRemovedIfUnused(*.Extends) {
return false
}
for , := range .Properties {
if !.exprCanBeRemovedIfUnused(.Key) {
return false
}
if .Value != nil && !.exprCanBeRemovedIfUnused(*.Value) {
return false
}
if .Initializer != nil && !.exprCanBeRemovedIfUnused(*.Initializer) {
return false
}
}
return true
}
func ( *parser) ( js_ast.Binding) bool {
switch b := .Data.(type) {
case *js_ast.BArray:
for , := range .Items {
if !.(.Binding) {
return false
}
if .DefaultValue != nil && !.exprCanBeRemovedIfUnused(*.DefaultValue) {
return false
}
}
case *js_ast.BObject:
for , := range .Properties {
if !.IsSpread && !.exprCanBeRemovedIfUnused(.Key) {
return false
}
if !.(.Value) {
return false
}
if .DefaultValue != nil && !.exprCanBeRemovedIfUnused(*.DefaultValue) {
return false
}
}
}
return true
}
func ( *parser) ( js_ast.Expr) bool {
switch e := .Data.(type) {
case *js_ast.ENull, *js_ast.EUndefined, *js_ast.EMissing, *js_ast.EBoolean, *js_ast.ENumber, *js_ast.EBigInt,
*js_ast.EString, *js_ast.EThis, *js_ast.ERegExp, *js_ast.EFunction, *js_ast.EArrow, *js_ast.EImportMeta:
return true
case *js_ast.EDot:
return .CanBeRemovedIfUnused
case *js_ast.EClass:
return .classCanBeRemovedIfUnused(.Class)
case *js_ast.EIdentifier:
if .MustKeepDueToWithStmt {
return false
}
if .CanBeRemovedIfUnused || .symbols[.Ref.InnerIndex].Kind != js_ast.SymbolUnbound {
return true
}
if .Kind == js_ast.PropertySpread || .IsComputed {
return false
}
if .Value != nil && !.(*.Value) {
return false
}
}
return true
if .CanBeUnwrappedIfUnused {
for , := range .Args {
if !.() {
return false
}
}
return true
}
case js_ast.BinOpStrictEq, js_ast.BinOpStrictNe, js_ast.BinOpComma,
js_ast.BinOpLogicalOr, js_ast.BinOpLogicalAnd, js_ast.BinOpNullishCoalescing:
return .(.Left) && .(.Right)
}
}
return false
}
func ( *parser) ( js_ast.Expr) js_ast.Expr {
switch e := .Data.(type) {
case *js_ast.ENull, *js_ast.EUndefined, *js_ast.EMissing, *js_ast.EBoolean, *js_ast.ENumber, *js_ast.EBigInt,
*js_ast.EString, *js_ast.EThis, *js_ast.ERegExp, *js_ast.EFunction, *js_ast.EArrow, *js_ast.EImportMeta:
return js_ast.Expr{}
case *js_ast.EDot:
if .CanBeRemovedIfUnused {
return js_ast.Expr{}
}
case *js_ast.EIdentifier:
if .MustKeepDueToWithStmt {
break
}
if .CanBeRemovedIfUnused || .symbols[.Ref.InnerIndex].Kind != js_ast.SymbolUnbound {
return js_ast.Expr{}
}
case *js_ast.ETemplate:
if .Tag == nil {
var js_ast.Expr
var js_ast.Expr
for , := range .Items {
= maybeJoinWithComma(, .())
}
return
for , := range .Properties {
if .Kind == js_ast.PropertySpread {
:= 0
if .Kind != js_ast.PropertySpread {
:= .(*.Value)
*.Value =
continue
.Value.Data = &js_ast.ENumber{}
}
}
.Properties[] =
++
}
.Properties = .Properties[:]
return
}
}
var js_ast.Expr
for , := range .Properties {
if .Yes.Data == nil {
return js_ast.JoinWithLeftAssociativeOp(js_ast.BinOpLogicalOr, .Test, .No)
}
case js_ast.BinOpStrictEq, js_ast.BinOpStrictNe, js_ast.BinOpComma:
return maybeJoinWithComma(.(.Left), .(.Right))
case js_ast.BinOpLooseEq, js_ast.BinOpLooseNe:
if isPrimitiveWithSideEffects(.Left.Data) && isPrimitiveWithSideEffects(.Right.Data) {
return maybeJoinWithComma(.(.Left), .(.Right))
}
if .CanBeUnwrappedIfUnused {
= js_ast.Expr{}
for , := range .Args {
= maybeJoinWithComma(, .())
}
}
if {
return , true
}
if ! {
.Right.Data = &js_ast.EString{}
return , true
}
}
return ,
}
}
return , false
}
func ( logger.Log, logger.Source, js_lexer.Lexer, *Options) *parser {
if .defines == nil {
:= config.ProcessDefines(nil)
.defines = &
}
:= &parser{
log: ,
source: ,
lexer: ,
allowIn: true,
options: *,
fnOrArrowDataParse: fnOrArrowDataParse{isOutsideFn: true},
runtimeImports: make(map[string]js_ast.Ref),
promiseRef: js_ast.InvalidRef,
afterArrowBodyLoc: logger.Loc{Start: -1},
weakMapRef: js_ast.InvalidRef,
weakSetRef: js_ast.InvalidRef,
privateGetters: make(map[js_ast.Ref]js_ast.Ref),
privateSetters: make(map[js_ast.Ref]js_ast.Ref),
importItemsForNamespace: make(map[js_ast.Ref]map[string]js_ast.LocRef),
isImportItem: make(map[js_ast.Ref]bool),
namedImports: make(map[js_ast.Ref]js_ast.NamedImport),
namedExports: make(map[string]js_ast.NamedExport),
}
.findSymbolHelper = func( logger.Loc, string) js_ast.Ref {
return .findSymbol(, ).ref
}
.symbolForDefineHelper = func( int) js_ast.Ref {
:= .injectedDefineSymbols[]
.recordUsage()
return
}
.pushScopeForParsePass(js_ast.ScopeEntry, logger.Loc{Start: locModuleScope})
return
}
var defaultJSXFactory = []string{"React", "createElement"}
var defaultJSXFragment = []string{"React", "Fragment"}
func ( logger.Log, logger.Source, Options) ( js_ast.AST, bool) {
= true
defer func() {
:= recover()
if , := .(js_lexer.LexerPanic); {
= false
} else if != nil {
panic()
}
}()
:= ""
if .options.mode != config.ModeBundle {
for , := range {
switch s := .Data.(type) {
case *js_ast.SComment:
continue
case *js_ast.SDirective:
if !isDirectiveSupported() {
continue
}
= js_lexer.UTF16ToString(.Value)
copy([1:], [:])
= [1:]
}
break
}
}
if .importMetaRef != js_ast.InvalidRef {
:= js_ast.Stmt{Data: &js_ast.SLocal{
Kind: .selectLocalKind(js_ast.LocalConst),
Decls: []js_ast.Decl{{
Binding: js_ast.Binding{Data: &js_ast.BIdentifier{Ref: .importMetaRef}},
Value: &js_ast.Expr{Data: &js_ast.EObject{}},
}},
}}
= append(append(make([]js_ast.Stmt, 0, len()+1), ), ...)
}
var []js_ast.Part
var []js_ast.Part
var []js_ast.Part
for , := range .options.injectedFiles {
:= make([]string, 0, len(.Exports))
:= make(map[string]js_ast.Ref)
if .IsDefine {
:= .newSymbol(js_ast.SymbolOther, js_ast.GenerateNonUniqueNameFromPath(.Path))
.moduleScope.Generated = append(.moduleScope.Generated, )
["default"] =
= append(, "default")
.injectedDefineSymbols = append(.injectedDefineSymbols, )
} else {
for , := range .Exports {
if , := .moduleScope.Members[]; ! {
:= .newSymbol(js_ast.SymbolOther, )
.moduleScope.Members[] = js_ast.ScopeMember{Ref: }
[] =
= append(, )
}
}
}
= .generateImportStmt(.Path, , .SourceIndex, , )
}
= .appendPart(, )
for , := range {
switch s := .Data.(type) {
= .appendPart(, []js_ast.Stmt{})
= .appendPart(, []js_ast.Stmt{})
default:
= .appendPart(, []js_ast.Stmt{})
}
}
}
.popScope()
= append(append(, ...), ...)
= .toAST(, , , )
.SourceMapComment = .lexer.SourceMappingURL
return
}
:= newParser(, , js_lexer.Lexer{}, &)
.prepareForVisitPass()
if != "" {
.symbolUses = make(map[js_ast.Ref]js_ast.SymbolUse)
= .callRuntime(.Loc, , []js_ast.Expr{})
}
:= js_ast.Part{
Stmts: []js_ast.Stmt{{Loc: .Loc, Data: &js_ast.SLazyExport{Value: }}},
SymbolUses: .symbolUses,
}
.symbolUses = nil
:= .toAST(, []js_ast.Part{}, "", "")
.HasLazyExport = true
return
}
func ( *parser) ( js_ast.Span, string) []string {
if .Text == "" {
return nil
}
:= strings.Split(.Text, ".")
for , := range {
if !js_lexer.IsIdentifier() {
.log.AddRangeWarning(&.source, .Range, fmt.Sprintf("Invalid JSX %s: %s", , .Text))
return nil
}
}
return
}
func ( *parser) () {
.pushScopeForVisitPass(js_ast.ScopeEntry, logger.Loc{Start: locModuleScope})
.moduleScope = .currentScope
.hasESModuleSyntax = .es6ImportKeyword.Len > 0 || .es6ExportKeyword.Len > 0 || .topLevelAwaitKeyword.Len > 0
if .es6ImportKeyword.Len > 0 {
.moduleScope.RecursiveSetStrictMode(js_ast.ImplicitStrictModeImport)
} else if .es6ExportKeyword.Len > 0 {
.moduleScope.RecursiveSetStrictMode(js_ast.ImplicitStrictModeExport)
} else if .topLevelAwaitKeyword.Len > 0 {
.moduleScope.RecursiveSetStrictMode(js_ast.ImplicitStrictModeTopLevelAwait)
}
.hoistSymbols(.moduleScope)
if .options.mode != config.ModePassThrough {
.exportsRef = .declareCommonJSSymbol(js_ast.SymbolHoisted, "exports")
.requireRef = .declareCommonJSSymbol(js_ast.SymbolUnbound, "require")
.moduleRef = .declareCommonJSSymbol(js_ast.SymbolHoisted, "module")
} else {
.exportsRef = .newSymbol(js_ast.SymbolHoisted, "exports")
.requireRef = .newSymbol(js_ast.SymbolUnbound, "require")
.moduleRef = .newSymbol(js_ast.SymbolHoisted, "module")
}
if .hasImportMeta && (.options.unsupportedJSFeatures.Has(compat.ImportMeta) ||
(.options.mode != config.ModePassThrough && !.options.outputFormat.KeepES6ImportExportSyntax())) {
.importMetaRef = .newSymbol(js_ast.SymbolOther, "import_meta")
.moduleScope.Generated = append(.moduleScope.Generated, .importMetaRef)
} else {
.importMetaRef = js_ast.InvalidRef
}
if .options.jsx.Parse {
if := .validateJSX(.lexer.JSXFactoryPragmaComment, "factory"); != nil {
.options.jsx.Factory =
}
if := .validateJSX(.lexer.JSXFragmentPragmaComment, "fragment"); != nil {
.options.jsx.Fragment =
}
}
}
func ( *parser) ( js_ast.SymbolKind, string) js_ast.Ref {
, := .moduleScope.Members[]
if && .symbols[.Ref.InnerIndex].Kind == js_ast.SymbolHoisted &&
== js_ast.SymbolHoisted && !.hasESModuleSyntax {
return .Ref
}
:= .newSymbol(, )
if ! {
.moduleScope.Members[] = js_ast.ScopeMember{Ref: , Loc: logger.Loc{Start: -1}}
return
}
.moduleScope.Generated = append(.moduleScope.Generated, )
return
}
func ( *parser) () *js_ast.CharFreq {
if !.options.minifyIdentifiers || .source.Index == runtime.SourceIndex {
return nil
}
for , := range .lexer.AllOriginalComments {
.Scan(.Text, -1)
}
var func(*js_ast.Scope)
= func( *js_ast.Scope) {
for , := range .Members {
:= &.symbols[.Ref.InnerIndex]
if .SlotNamespace() != js_ast.SlotMustNotBeRenamed {
.Scan(.OriginalName, -int32(.UseCountEstimate))
}
}
if .LabelRef != js_ast.InvalidRef {
:= &.symbols[.LabelRef.InnerIndex]
if .SlotNamespace() != js_ast.SlotMustNotBeRenamed {
.Scan(.OriginalName, -int32(.UseCountEstimate)-1)
}
}
for , := range .Children {
()
}
}
(.moduleScope)
return
}
func ( *parser) (
string,
[]string,
uint32,
[]js_ast.Part,
map[string]js_ast.Ref,
) []js_ast.Part {
:= .newSymbol(js_ast.SymbolOther, "import_"+js_ast.GenerateNonUniqueNameFromPath())
.moduleScope.Generated = append(.moduleScope.Generated, )
:= make([]js_ast.DeclaredSymbol, len())
:= make([]js_ast.ClauseItem, len())
:= .addImportRecord(ast.ImportStmt, logger.Loc{}, )
.importRecords[].SourceIndex = ast.MakeIndex32()
for , := range {
:= []
[] = js_ast.DeclaredSymbol{Ref: , IsTopLevel: true}
[] = js_ast.ClauseItem{Alias: , Name: js_ast.LocRef{Ref: }}
.isImportItem[] = true
.namedImports[] = js_ast.NamedImport{
Alias: ,
NamespaceRef: ,
ImportRecordIndex: ,
}
}
return append(, js_ast.Part{
DeclaredSymbols: ,
ImportRecordIndices: []uint32{},
Stmts: []js_ast.Stmt{{Data: &js_ast.SImport{
NamespaceRef: ,
Items: &,
ImportRecordIndex: ,
}}},
})
}
:= make([]string, 0, len(.runtimeImports))
for := range .runtimeImports {
= append(, )
}
sort.Strings()
= .generateImportStmt("<runtime>", , runtime.SourceIndex, , .runtimeImports)
}
:= 0
for , := range {
.importRecordsForCurrentPart = nil
.declaredSymbols = nil
:= .scanForImportsAndExports(.Stmts)
.Stmts = .stmts
= || .keptImportEquals
= || .removedImportEquals
.ImportRecordIndices = append(.ImportRecordIndices, .importRecordsForCurrentPart...)
.DeclaredSymbols = append(.DeclaredSymbols, .declaredSymbols...)
if len(.Stmts) > 0 {
.CanBeRemovedIfUnused = false
}
[] =
++
}
}
= [:]
if ! || ! {
break
}
}
for , := range {
for , := range .Stmts {
if , := .Data.(*js_ast.SExportClause); {
if , := .namedImports[.Name.Ref]; {
.IsExported = true
.namedImports[.Name.Ref] =
}
}
}
}
}
.topLevelSymbolToParts = make(map[js_ast.Ref][]uint32)
for , := range {
for , := range .DeclaredSymbols {
if .IsTopLevel {
.topLevelSymbolToParts[.Ref] = append(
.topLevelSymbolToParts[.Ref], uint32())
}
}
}
for , := range {
:= make(map[uint32]bool)
for := range .SymbolUses {
for , := range .topLevelSymbolToParts[] {
[] = true
}
if , := .namedImports[]; {
.LocalPartsWithUses = append(.LocalPartsWithUses, uint32())
.namedImports[] =
}
}
[].LocalDependencies =
}
}
:= .newSymbol(js_ast.SymbolOther, "require_"+.source.IdentifierName)
var js_ast.SlotCounts
if .options.minifyIdentifiers {
= renamer.AssignNestedScopeSlots(.moduleScope, .symbols)
}
return js_ast.AST{
Parts: ,
ModuleScope: .moduleScope,
CharFreq: .computeCharacterFrequency(),
Symbols: .symbols,
ExportsRef: .exportsRef,
ModuleRef: .moduleRef,
WrapperRef: ,
Hashbang: ,
Directive: ,
NamedImports: .namedImports,
NamedExports: .namedExports,
NestedScopeSlotCounts: ,
TopLevelSymbolToParts: .topLevelSymbolToParts,
ExportStarImportRecords: .exportStarImportRecords,
ImportRecords: .importRecords,
ApproximateLineCount: int32(.lexer.ApproximateNewlineCount) + 1,
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |