1package js 2 3import ( 4 "bytes" 5 "fmt" 6 "strconv" 7) 8 9var ErrInvalidJSON = fmt.Errorf("invalid JSON") 10 11// AST is the full ECMAScript abstract syntax tree. 12type AST struct { 13 Comments [][]byte // first comments in file 14 BlockStmt // module 15} 16 17func (ast *AST) String() string { 18 s := "" 19 for i, item := range ast.BlockStmt.List { 20 if i != 0 { 21 s += " " 22 } 23 s += item.String() 24 } 25 return s 26} 27 28//////////////////////////////////////////////////////////////// 29 30// DeclType specifies the kind of declaration. 31type DeclType uint16 32 33// DeclType values. 34const ( 35 NoDecl DeclType = iota // undeclared variables 36 VariableDecl // var 37 FunctionDecl // function 38 ArgumentDecl // function and method arguments 39 LexicalDecl // let, const, class 40 CatchDecl // catch statement argument 41 ExprDecl // function expression name or class expression name 42) 43 44func (decl DeclType) String() string { 45 switch decl { 46 case NoDecl: 47 return "NoDecl" 48 case VariableDecl: 49 return "VariableDecl" 50 case FunctionDecl: 51 return "FunctionDecl" 52 case ArgumentDecl: 53 return "ArgumentDecl" 54 case LexicalDecl: 55 return "LexicalDecl" 56 case CatchDecl: 57 return "CatchDecl" 58 case ExprDecl: 59 return "ExprDecl" 60 } 61 return "Invalid(" + strconv.Itoa(int(decl)) + ")" 62} 63 64// Var is a variable, where Decl is the type of declaration and can be var|function for function scoped variables, let|const|class for block scoped variables. 65type Var struct { 66 Data []byte 67 Link *Var // is set when merging variable uses, as in: {a} {var a} where the first links to the second, only used for undeclared variables 68 Uses uint16 69 Decl DeclType 70} 71 72// Name returns the variable name. 73func (v *Var) Name() []byte { 74 for v.Link != nil { 75 v = v.Link 76 } 77 return v.Data 78} 79 80func (v Var) String() string { 81 return string(v.Name()) 82} 83 84// JS converts the node back to valid JavaScript 85func (v Var) JS() string { 86 return v.String() 87} 88 89// JSON converts the node back to valid JSON 90func (n Var) JSON() (string, error) { 91 return "", ErrInvalidJSON 92} 93 94// VarsByUses is sortable by uses in descending order. 95type VarsByUses VarArray 96 97func (vs VarsByUses) Len() int { 98 return len(vs) 99} 100 101func (vs VarsByUses) Swap(i, j int) { 102 vs[i], vs[j] = vs[j], vs[i] 103} 104 105func (vs VarsByUses) Less(i, j int) bool { 106 return vs[i].Uses > vs[j].Uses 107} 108 109//////////////////////////////////////////////////////////////// 110 111// VarArray is a set of variables in scopes. 112type VarArray []*Var 113 114func (vs VarArray) String() string { 115 s := "[" 116 for i, v := range vs { 117 if i != 0 { 118 s += ", " 119 } 120 links := 0 121 for v.Link != nil { 122 v = v.Link 123 links++ 124 } 125 s += fmt.Sprintf("Var{%v %s %v %v}", v.Decl, string(v.Data), links, v.Uses) 126 } 127 return s + "]" 128} 129 130// Scope is a function or block scope with a list of variables declared and used. 131type Scope struct { 132 Parent, Func *Scope // Parent is nil for global scope, Parent equals Func for function scope 133 Declared VarArray // Link in Var are always nil 134 Undeclared VarArray 135 NumVarDecls uint16 // number of variable declaration statements in a function scope 136 NumForInit uint16 // offset into Declared to mark variables used in for initializer 137 NumArguments uint16 // offset into Undeclared to mark variables used in arguments 138 IsGlobalOrFunc bool 139 HasWith bool 140} 141 142func (s Scope) String() string { 143 return "Scope{Declared: " + s.Declared.String() + ", Undeclared: " + s.Undeclared.String() + "}" 144} 145 146// Declare declares a new variable. 147func (s *Scope) Declare(decl DeclType, name []byte) (*Var, bool) { 148 // refer to new variable for previously undeclared symbols in the current and lower scopes 149 // this happens in `{ a = 5; } var a` where both a's refer to the same variable 150 curScope := s 151 if decl == VariableDecl || decl == FunctionDecl { 152 // find function scope for var and function declarations 153 for s != s.Func { 154 // make sure that `{let i;{var i}}` is an error 155 if v := s.findDeclared(name, false); v != nil && v.Decl != decl && v.Decl != CatchDecl { 156 return nil, false 157 } 158 s = s.Parent 159 } 160 } 161 162 if v := s.findDeclared(name, true); v != nil { 163 // variable already declared, might be an error or a duplicate declaration 164 if (LexicalDecl <= v.Decl || LexicalDecl <= decl) && v.Decl != ExprDecl { 165 // redeclaration of let, const, class on an already declared name is an error, except if the declared name is a function expression name 166 return nil, false 167 } 168 if v.Decl == ExprDecl { 169 v.Decl = decl 170 } 171 v.Uses++ 172 for s != curScope { 173 curScope.addUndeclared(v) // add variable declaration as used variable to the current scope 174 curScope = curScope.Parent 175 } 176 return v, true 177 } 178 179 var v *Var 180 // reuse variable if previously used, as in: a;var a 181 if decl != ArgumentDecl { // in case of function f(a=b,b), where the first b is different from the second 182 for i, uv := range s.Undeclared[s.NumArguments:] { 183 // no need to evaluate v.Link as v.Data stays the same and Link is nil in the active scope 184 if 0 < uv.Uses && uv.Decl == NoDecl && bytes.Equal(name, uv.Data) { 185 // must be NoDecl so that it can't be a var declaration that has been added 186 v = uv 187 s.Undeclared = append(s.Undeclared[:int(s.NumArguments)+i], s.Undeclared[int(s.NumArguments)+i+1:]...) 188 break 189 } 190 } 191 } 192 if v == nil { 193 // add variable to the context list and to the scope 194 v = &Var{name, nil, 0, decl} 195 } else { 196 v.Decl = decl 197 } 198 v.Uses++ 199 s.Declared = append(s.Declared, v) 200 for s != curScope { 201 curScope.addUndeclared(v) // add variable declaration as used variable to the current scope 202 curScope = curScope.Parent 203 } 204 return v, true 205} 206 207// Use increments the usage of a variable. 208func (s *Scope) Use(name []byte) *Var { 209 // check if variable is declared in the current scope 210 v := s.findDeclared(name, false) 211 if v == nil { 212 // check if variable is already used before in the current or lower scopes 213 v = s.findUndeclared(name) 214 if v == nil { 215 // add variable to the context list and to the scope's undeclared 216 v = &Var{name, nil, 0, NoDecl} 217 s.Undeclared = append(s.Undeclared, v) 218 } 219 } 220 v.Uses++ 221 return v 222} 223 224// findDeclared finds a declared variable in the current scope. 225func (s *Scope) findDeclared(name []byte, skipForInit bool) *Var { 226 start := 0 227 if skipForInit { 228 // we skip the for initializer for declarations (only has effect for let/const) 229 start = int(s.NumForInit) 230 } 231 // reverse order to find the inner let first in `for(let a in []){let a; {a}}` 232 for i := len(s.Declared) - 1; start <= i; i-- { 233 v := s.Declared[i] 234 // no need to evaluate v.Link as v.Data stays the same, and Link is always nil in Declared 235 if bytes.Equal(name, v.Data) { 236 return v 237 } 238 } 239 return nil 240} 241 242// findUndeclared finds an undeclared variable in the current and contained scopes. 243func (s *Scope) findUndeclared(name []byte) *Var { 244 for _, v := range s.Undeclared { 245 // no need to evaluate v.Link as v.Data stays the same and Link is nil in the active scope 246 if 0 < v.Uses && bytes.Equal(name, v.Data) { 247 return v 248 } 249 } 250 return nil 251} 252 253// add undeclared variable to scope, this is called for the block scope when declaring a var in it 254func (s *Scope) addUndeclared(v *Var) { 255 // don't add undeclared symbol if it's already there 256 for _, vorig := range s.Undeclared { 257 if v == vorig { 258 return 259 } 260 } 261 s.Undeclared = append(s.Undeclared, v) // add variable declaration as used variable to the current scope 262} 263 264// MarkForInit marks the declared variables in current scope as for statement initializer to distinguish from declarations in body. 265func (s *Scope) MarkForInit() { 266 s.NumForInit = uint16(len(s.Declared)) 267} 268 269// MarkArguments marks the undeclared variables in the current scope as function arguments. It ensures different b's in `function f(a=b){var b}`. 270func (s *Scope) MarkArguments() { 271 s.NumArguments = uint16(len(s.Undeclared)) 272} 273 274// HoistUndeclared copies all undeclared variables of the current scope to the parent scope. 275func (s *Scope) HoistUndeclared() { 276 for i, vorig := range s.Undeclared { 277 // no need to evaluate vorig.Link as vorig.Data stays the same 278 if 0 < vorig.Uses && vorig.Decl == NoDecl { 279 if v := s.Parent.findDeclared(vorig.Data, false); v != nil { 280 // check if variable is declared in parent scope 281 v.Uses += vorig.Uses 282 vorig.Link = v 283 s.Undeclared[i] = v // point reference to existing var (to avoid many Link chains) 284 } else if v := s.Parent.findUndeclared(vorig.Data); v != nil { 285 // check if variable is already used before in parent scope 286 v.Uses += vorig.Uses 287 vorig.Link = v 288 s.Undeclared[i] = v // point reference to existing var (to avoid many Link chains) 289 } else { 290 // add variable to the context list and to the scope's undeclared 291 s.Parent.Undeclared = append(s.Parent.Undeclared, vorig) 292 } 293 } 294 } 295} 296 297// UndeclareScope undeclares all declared variables in the current scope and adds them to the parent scope. 298// Called when possible arrow func ends up being a parenthesized expression, scope is not further used. 299func (s *Scope) UndeclareScope() { 300 // look if the variable already exists in the parent scope, if so replace the Var pointer in original use 301 for _, vorig := range s.Declared { 302 // no need to evaluate vorig.Link as vorig.Data stays the same, and Link is always nil in Declared 303 // vorig.Uses will be atleast 1 304 if v := s.Parent.findDeclared(vorig.Data, false); v != nil { 305 // check if variable has been declared in this scope 306 v.Uses += vorig.Uses 307 vorig.Link = v 308 } else if v := s.Parent.findUndeclared(vorig.Data); v != nil { 309 // check if variable is already used before in the current or lower scopes 310 v.Uses += vorig.Uses 311 vorig.Link = v 312 } else { 313 // add variable to the context list and to the scope's undeclared 314 vorig.Decl = NoDecl 315 s.Parent.Undeclared = append(s.Parent.Undeclared, vorig) 316 } 317 } 318 s.Declared = s.Declared[:0] 319 s.Undeclared = s.Undeclared[:0] 320} 321 322// Unscope moves all declared variables of the current scope to the parent scope. Undeclared variables are already in the parent scope. 323func (s *Scope) Unscope() { 324 for _, vorig := range s.Declared { 325 // no need to evaluate vorig.Link as vorig.Data stays the same, and Link is always nil in Declared 326 // vorig.Uses will be atleast 1 327 s.Parent.Declared = append(s.Parent.Declared, vorig) 328 } 329 s.Declared = s.Declared[:0] 330 s.Undeclared = s.Undeclared[:0] 331} 332 333//////////////////////////////////////////////////////////////// 334 335// INode is an interface for AST nodes 336type INode interface { 337 String() string 338 JS() string 339 JSON() (string, error) 340} 341 342// IStmt is a dummy interface for statements. 343type IStmt interface { 344 INode 345 stmtNode() 346} 347 348// IBinding is a dummy interface for bindings. 349type IBinding interface { 350 INode 351 bindingNode() 352} 353 354// IExpr is a dummy interface for expressions. 355type IExpr interface { 356 INode 357 exprNode() 358} 359 360//////////////////////////////////////////////////////////////// 361 362// BlockStmt is a block statement. 363type BlockStmt struct { 364 List []IStmt 365 Scope 366} 367 368func (n BlockStmt) String() string { 369 s := "Stmt({" 370 for _, item := range n.List { 371 s += " " + item.String() 372 } 373 return s + " })" 374} 375 376// JS converts the node back to valid JavaScript 377func (n BlockStmt) JS() string { 378 s := "" 379 if n.Scope.Parent != nil { 380 s += "{ " 381 } 382 for _, item := range n.List { 383 s += item.JS() + "; " 384 } 385 if n.Scope.Parent != nil { 386 s += "}" 387 } 388 return s 389} 390 391// JSON converts the node back to valid JSON 392func (n BlockStmt) JSON() (string, error) { 393 if len(n.List) != 1 { 394 return "", ErrInvalidJSON 395 } 396 return n.List[0].JSON() 397} 398 399// EmptyStmt is an empty statement. 400type EmptyStmt struct { 401} 402 403func (n EmptyStmt) String() string { 404 return "Stmt(;)" 405} 406 407// JS converts the node back to valid JavaScript 408func (n EmptyStmt) JS() string { 409 return ";" 410} 411 412// JSON converts the node back to valid JSON 413func (n EmptyStmt) JSON() (string, error) { 414 return "", ErrInvalidJSON 415} 416 417// ExprStmt is an expression statement. 418type ExprStmt struct { 419 Value IExpr 420} 421 422func (n ExprStmt) String() string { 423 val := n.Value.String() 424 if val[0] == '(' && val[len(val)-1] == ')' { 425 return "Stmt" + n.Value.String() 426 } 427 return "Stmt(" + n.Value.String() + ")" 428} 429 430// JS converts the node back to valid JavaScript 431func (n ExprStmt) JS() string { 432 return n.Value.JS() 433} 434 435// JSON converts the node back to valid JSON 436func (n ExprStmt) JSON() (string, error) { 437 return n.Value.JSON() 438} 439 440// IfStmt is an if statement. 441type IfStmt struct { 442 Cond IExpr 443 Body IStmt 444 Else IStmt // can be nil 445} 446 447func (n IfStmt) String() string { 448 s := "Stmt(if " + n.Cond.String() + " " + n.Body.String() 449 if n.Else != nil { 450 s += " else " + n.Else.String() 451 } 452 return s + ")" 453} 454 455// JS converts the node back to valid JavaScript 456func (n IfStmt) JS() string { 457 s := "if (" + n.Cond.JS() + ") " 458 switch n.Body.(type) { 459 case *BlockStmt: 460 s += n.Body.JS() 461 default: 462 s += "{ " + n.Body.JS() + " }" 463 } 464 if n.Else != nil { 465 switch n.Else.(type) { 466 case *BlockStmt: 467 s += " else " + n.Else.JS() 468 default: 469 s += " else { " + n.Else.JS() + " }" 470 } 471 } 472 return s 473} 474 475// JSON converts the node back to valid JSON 476func (n IfStmt) JSON() (string, error) { 477 return "", ErrInvalidJSON 478} 479 480// DoWhileStmt is a do-while iteration statement. 481type DoWhileStmt struct { 482 Cond IExpr 483 Body IStmt 484} 485 486func (n DoWhileStmt) String() string { 487 return "Stmt(do " + n.Body.String() + " while " + n.Cond.String() + ")" 488} 489 490// JS converts the node back to valid JavaScript 491func (n DoWhileStmt) JS() string { 492 s := "do " 493 switch n.Body.(type) { 494 case *BlockStmt: 495 s += n.Body.JS() 496 default: 497 s += "{ " + n.Body.JS() + " }" 498 } 499 return s + " while (" + n.Cond.JS() + ")" 500} 501 502// JSON converts the node back to valid JSON 503func (n DoWhileStmt) JSON() (string, error) { 504 return "", ErrInvalidJSON 505} 506 507// WhileStmt is a while iteration statement. 508type WhileStmt struct { 509 Cond IExpr 510 Body IStmt 511} 512 513func (n WhileStmt) String() string { 514 return "Stmt(while " + n.Cond.String() + " " + n.Body.String() + ")" 515} 516 517// JS converts the node back to valid JavaScript 518func (n WhileStmt) JS() string { 519 s := "while (" + n.Cond.JS() + ") " 520 if n.Body != nil { 521 s += n.Body.JS() 522 } 523 return s 524} 525 526// JSON converts the node back to valid JSON 527func (n WhileStmt) JSON() (string, error) { 528 return "", ErrInvalidJSON 529} 530 531// ForStmt is a regular for iteration statement. 532type ForStmt struct { 533 Init IExpr // can be nil 534 Cond IExpr // can be nil 535 Post IExpr // can be nil 536 Body *BlockStmt 537} 538 539func (n ForStmt) String() string { 540 s := "Stmt(for" 541 if n.Init != nil { 542 s += " " + n.Init.String() 543 } 544 s += " ;" 545 if n.Cond != nil { 546 s += " " + n.Cond.String() 547 } 548 s += " ;" 549 if n.Post != nil { 550 s += " " + n.Post.String() 551 } 552 return s + " " + n.Body.String() + ")" 553} 554 555// JS converts the node back to valid JavaScript 556func (n ForStmt) JS() string { 557 s := "for (" 558 if n.Init != nil { 559 s += n.Init.JS() 560 } else { 561 s += " " 562 } 563 s += "; " 564 if n.Cond != nil { 565 s += n.Cond.JS() 566 } 567 s += "; " 568 if n.Post != nil { 569 s += n.Post.JS() 570 } 571 return s + ") " + n.Body.JS() 572} 573 574// JSON converts the node back to valid JSON 575func (n ForStmt) JSON() (string, error) { 576 return "", ErrInvalidJSON 577} 578 579// ForInStmt is a for-in iteration statement. 580type ForInStmt struct { 581 Init IExpr 582 Value IExpr 583 Body *BlockStmt 584} 585 586func (n ForInStmt) String() string { 587 return "Stmt(for " + n.Init.String() + " in " + n.Value.String() + " " + n.Body.String() + ")" 588} 589 590// JS converts the node back to valid JavaScript 591func (n ForInStmt) JS() string { 592 return "for (" + n.Init.JS() + " in " + n.Value.JS() + ") " + n.Body.JS() 593} 594 595// JSON converts the node back to valid JSON 596func (n ForInStmt) JSON() (string, error) { 597 return "", ErrInvalidJSON 598} 599 600// ForOfStmt is a for-of iteration statement. 601type ForOfStmt struct { 602 Await bool 603 Init IExpr 604 Value IExpr 605 Body *BlockStmt 606} 607 608func (n ForOfStmt) String() string { 609 s := "Stmt(for" 610 if n.Await { 611 s += " await" 612 } 613 return s + " " + n.Init.String() + " of " + n.Value.String() + " " + n.Body.String() + ")" 614} 615 616// JS converts the node back to valid JavaScript 617func (n ForOfStmt) JS() string { 618 s := "for" 619 if n.Await { 620 s += " await" 621 } 622 return s + " (" + n.Init.JS() + " of " + n.Value.JS() + ") " + n.Body.JS() 623} 624 625// JSON converts the node back to valid JSON 626func (n ForOfStmt) JSON() (string, error) { 627 return "", ErrInvalidJSON 628} 629 630// CaseClause is a case clause or default clause for a switch statement. 631type CaseClause struct { 632 TokenType 633 Cond IExpr // can be nil 634 List []IStmt 635} 636 637func (n CaseClause) String() string { 638 s := " Clause(" + n.TokenType.String() 639 if n.Cond != nil { 640 s += " " + n.Cond.String() 641 } 642 for _, item := range n.List { 643 s += " " + item.String() 644 } 645 return s + ")" 646} 647 648// JS converts the node back to valid JavaScript 649func (n CaseClause) JS() string { 650 s := " " 651 if n.Cond != nil { 652 s += "case " + n.Cond.JS() 653 } else { 654 s += "default" 655 } 656 s += ":" 657 for _, item := range n.List { 658 s += " " + item.JS() + ";" 659 } 660 return s 661} 662 663// JSON converts the node back to valid JSON 664func (n CaseClause) JSON() (string, error) { 665 return "", ErrInvalidJSON 666} 667 668// SwitchStmt is a switch statement. 669type SwitchStmt struct { 670 Init IExpr 671 List []CaseClause 672 Scope 673} 674 675func (n SwitchStmt) String() string { 676 s := "Stmt(switch " + n.Init.String() 677 for _, clause := range n.List { 678 s += clause.String() 679 } 680 return s + ")" 681} 682 683// JS converts the node back to valid JavaScript 684func (n SwitchStmt) JS() string { 685 s := "switch (" + n.Init.JS() + ") {" 686 for _, clause := range n.List { 687 s += clause.JS() 688 } 689 return s + " }" 690} 691 692// JSON converts the node back to valid JSON 693func (n SwitchStmt) JSON() (string, error) { 694 return "", ErrInvalidJSON 695} 696 697// BranchStmt is a continue or break statement. 698type BranchStmt struct { 699 Type TokenType 700 Label []byte // can be nil 701} 702 703func (n BranchStmt) String() string { 704 s := "Stmt(" + n.Type.String() 705 if n.Label != nil { 706 s += " " + string(n.Label) 707 } 708 return s + ")" 709} 710 711// JS converts the node back to valid JavaScript 712func (n BranchStmt) JS() string { 713 s := n.Type.String() 714 if n.Label != nil { 715 s += " " + string(n.Label) 716 } 717 return s 718} 719 720// JSON converts the node back to valid JSON 721func (n BranchStmt) JSON() (string, error) { 722 return "", ErrInvalidJSON 723} 724 725// ReturnStmt is a return statement. 726type ReturnStmt struct { 727 Value IExpr // can be nil 728} 729 730func (n ReturnStmt) String() string { 731 s := "Stmt(return" 732 if n.Value != nil { 733 s += " " + n.Value.String() 734 } 735 return s + ")" 736} 737 738// JS converts the node back to valid JavaScript 739func (n ReturnStmt) JS() string { 740 s := "return" 741 if n.Value != nil { 742 s += " " + n.Value.JS() 743 } 744 return s 745} 746 747// JSON converts the node back to valid JSON 748func (n ReturnStmt) JSON() (string, error) { 749 return "", ErrInvalidJSON 750} 751 752// WithStmt is a with statement. 753type WithStmt struct { 754 Cond IExpr 755 Body IStmt 756} 757 758func (n WithStmt) String() string { 759 return "Stmt(with " + n.Cond.String() + " " + n.Body.String() + ")" 760} 761 762// JS converts the node back to valid JavaScript 763func (n WithStmt) JS() string { 764 return "with (" + n.Cond.JS() + ") " + n.Body.JS() 765} 766 767// JSON converts the node back to valid JSON 768func (n WithStmt) JSON() (string, error) { 769 return "", ErrInvalidJSON 770} 771 772// LabelledStmt is a labelled statement. 773type LabelledStmt struct { 774 Label []byte 775 Value IStmt 776} 777 778func (n LabelledStmt) String() string { 779 return "Stmt(" + string(n.Label) + " : " + n.Value.String() + ")" 780} 781 782// JS converts the node back to valid JavaScript 783func (n LabelledStmt) JS() string { 784 return string(n.Label) + ": " + n.Value.JS() 785} 786 787// JSON converts the node back to valid JSON 788func (n LabelledStmt) JSON() (string, error) { 789 return "", ErrInvalidJSON 790} 791 792// ThrowStmt is a throw statement. 793type ThrowStmt struct { 794 Value IExpr 795} 796 797func (n ThrowStmt) String() string { 798 return "Stmt(throw " + n.Value.String() + ")" 799} 800 801// JS converts the node back to valid JavaScript 802func (n ThrowStmt) JS() string { 803 return "throw " + n.Value.JS() 804} 805 806// JSON converts the node back to valid JSON 807func (n ThrowStmt) JSON() (string, error) { 808 return "", ErrInvalidJSON 809} 810 811// TryStmt is a try statement. 812type TryStmt struct { 813 Body *BlockStmt 814 Binding IBinding // can be nil 815 Catch *BlockStmt // can be nil 816 Finally *BlockStmt // can be nil 817} 818 819func (n TryStmt) String() string { 820 s := "Stmt(try " + n.Body.String() 821 if n.Catch != nil { 822 s += " catch" 823 if n.Binding != nil { 824 s += " Binding(" + n.Binding.String() + ")" 825 } 826 s += " " + n.Catch.String() 827 } 828 if n.Finally != nil { 829 s += " finally " + n.Finally.String() 830 } 831 return s + ")" 832} 833 834// JS converts the node back to valid JavaScript 835func (n TryStmt) JS() string { 836 s := "try " + n.Body.JS() 837 if n.Catch != nil { 838 s += " catch" 839 if n.Binding != nil { 840 s += "(" + n.Binding.JS() + ")" 841 } 842 s += " " + n.Catch.JS() 843 } 844 if n.Finally != nil { 845 s += " finally " + n.Finally.JS() 846 } 847 return s 848} 849 850// JSON converts the node back to valid JSON 851func (n TryStmt) JSON() (string, error) { 852 return "", ErrInvalidJSON 853} 854 855// DebuggerStmt is a debugger statement. 856type DebuggerStmt struct { 857} 858 859func (n DebuggerStmt) String() string { 860 return "Stmt(debugger)" 861} 862 863// JS converts the node back to valid JavaScript 864func (n DebuggerStmt) JS() string { 865 return "debugger" 866} 867 868// JSON converts the node back to valid JSON 869func (n DebuggerStmt) JSON() (string, error) { 870 return "", ErrInvalidJSON 871} 872 873// Alias is a name space import or import/export specifier for import/export statements. 874type Alias struct { 875 Name []byte // can be nil 876 Binding []byte // can be nil 877} 878 879func (alias Alias) String() string { 880 s := "" 881 if alias.Name != nil { 882 s += string(alias.Name) + " as " 883 } 884 return s + string(alias.Binding) 885} 886 887// JS converts the node back to valid JavaScript 888func (alias Alias) JS() string { 889 return alias.String() 890} 891 892// JSON converts the node back to valid JSON 893func (n Alias) JSON() (string, error) { 894 return "", ErrInvalidJSON 895} 896 897// ImportStmt is an import statement. 898type ImportStmt struct { 899 List []Alias 900 Default []byte // can be nil 901 Module []byte 902} 903 904func (n ImportStmt) String() string { 905 s := "Stmt(import" 906 if n.Default != nil { 907 s += " " + string(n.Default) 908 if len(n.List) != 0 { 909 s += " ," 910 } 911 } 912 if len(n.List) == 1 && len(n.List[0].Name) == 1 && n.List[0].Name[0] == '*' { 913 s += " " + n.List[0].String() 914 } else if 0 < len(n.List) { 915 s += " {" 916 for i, item := range n.List { 917 if i != 0 { 918 s += " ," 919 } 920 if item.Binding != nil { 921 s += " " + item.String() 922 } 923 } 924 s += " }" 925 } 926 if n.Default != nil || len(n.List) != 0 { 927 s += " from" 928 } 929 return s + " " + string(n.Module) + ")" 930} 931 932// JS converts the node back to valid JavaScript 933func (n ImportStmt) JS() string { 934 s := "import" 935 if n.Default != nil { 936 s += " " + string(n.Default) 937 if len(n.List) != 0 { 938 s += " ," 939 } 940 } 941 if len(n.List) == 1 && len(n.List[0].Name) == 1 && n.List[0].Name[0] == '*' { 942 s += " " + n.List[0].JS() 943 } else if 0 < len(n.List) { 944 s += " {" 945 for i, item := range n.List { 946 if i != 0 { 947 s += " ," 948 } 949 if item.Binding != nil { 950 s += " " + item.JS() 951 } 952 } 953 s += " }" 954 } 955 if n.Default != nil || len(n.List) != 0 { 956 s += " from" 957 } 958 return s + " " + string(n.Module) 959} 960 961// JSON converts the node back to valid JSON 962func (n ImportStmt) JSON() (string, error) { 963 return "", ErrInvalidJSON 964} 965 966// ExportStmt is an export statement. 967type ExportStmt struct { 968 List []Alias 969 Module []byte // can be nil 970 Default bool 971 Decl IExpr 972} 973 974func (n ExportStmt) String() string { 975 s := "Stmt(export" 976 if n.Decl != nil { 977 if n.Default { 978 s += " default" 979 } 980 return s + " " + n.Decl.String() + ")" 981 } else if len(n.List) == 1 && (len(n.List[0].Name) == 1 && n.List[0].Name[0] == '*' || n.List[0].Name == nil && len(n.List[0].Binding) == 1 && n.List[0].Binding[0] == '*') { 982 s += " " + n.List[0].String() 983 } else if 0 < len(n.List) { 984 s += " {" 985 for i, item := range n.List { 986 if i != 0 { 987 s += " ," 988 } 989 if item.Binding != nil { 990 s += " " + item.String() 991 } 992 } 993 s += " }" 994 } 995 if n.Module != nil { 996 s += " from " + string(n.Module) 997 } 998 return s + ")" 999} 1000 1001// JS converts the node back to valid JavaScript 1002func (n ExportStmt) JS() string { 1003 s := "export" 1004 if n.Decl != nil { 1005 if n.Default { 1006 s += " default" 1007 } 1008 return s + " " + n.Decl.JS() 1009 } else if len(n.List) == 1 && (len(n.List[0].Name) == 1 && n.List[0].Name[0] == '*' || n.List[0].Name == nil && len(n.List[0].Binding) == 1 && n.List[0].Binding[0] == '*') { 1010 s += " " + n.List[0].JS() 1011 } else if 0 < len(n.List) { 1012 s += " {" 1013 for i, item := range n.List { 1014 if i != 0 { 1015 s += " ," 1016 } 1017 if item.Binding != nil { 1018 s += " " + item.JS() 1019 } 1020 } 1021 s += " }" 1022 } 1023 if n.Module != nil { 1024 s += " from " + string(n.Module) 1025 } 1026 return s 1027} 1028 1029// JSON converts the node back to valid JSON 1030func (n ExportStmt) JSON() (string, error) { 1031 return "", ErrInvalidJSON 1032} 1033 1034// DirectivePrologueStmt is a string literal at the beginning of a function or module (usually "use strict"). 1035type DirectivePrologueStmt struct { 1036 Value []byte 1037} 1038 1039func (n DirectivePrologueStmt) String() string { 1040 return "Stmt(" + string(n.Value) + ")" 1041} 1042 1043// JS converts the node back to valid JavaScript 1044func (n DirectivePrologueStmt) JS() string { 1045 return string(n.Value) 1046} 1047 1048// JSON converts the node back to valid JSON 1049func (n DirectivePrologueStmt) JSON() (string, error) { 1050 return "", ErrInvalidJSON 1051} 1052 1053func (n BlockStmt) stmtNode() {} 1054func (n EmptyStmt) stmtNode() {} 1055func (n ExprStmt) stmtNode() {} 1056func (n IfStmt) stmtNode() {} 1057func (n DoWhileStmt) stmtNode() {} 1058func (n WhileStmt) stmtNode() {} 1059func (n ForStmt) stmtNode() {} 1060func (n ForInStmt) stmtNode() {} 1061func (n ForOfStmt) stmtNode() {} 1062func (n SwitchStmt) stmtNode() {} 1063func (n BranchStmt) stmtNode() {} 1064func (n ReturnStmt) stmtNode() {} 1065func (n WithStmt) stmtNode() {} 1066func (n LabelledStmt) stmtNode() {} 1067func (n ThrowStmt) stmtNode() {} 1068func (n TryStmt) stmtNode() {} 1069func (n DebuggerStmt) stmtNode() {} 1070func (n ImportStmt) stmtNode() {} 1071func (n ExportStmt) stmtNode() {} 1072func (n DirectivePrologueStmt) stmtNode() {} 1073 1074//////////////////////////////////////////////////////////////// 1075 1076// PropertyName is a property name for binding properties, method names, and in object literals. 1077type PropertyName struct { 1078 Literal LiteralExpr 1079 Computed IExpr // can be nil 1080} 1081 1082// IsSet returns true is PropertyName is not nil. 1083func (n PropertyName) IsSet() bool { 1084 return n.IsComputed() || n.Literal.TokenType != ErrorToken 1085} 1086 1087// IsComputed returns true if PropertyName is computed. 1088func (n PropertyName) IsComputed() bool { 1089 return n.Computed != nil 1090} 1091 1092// IsIdent returns true if PropertyName equals the given identifier name. 1093func (n PropertyName) IsIdent(data []byte) bool { 1094 return !n.IsComputed() && n.Literal.TokenType == IdentifierToken && bytes.Equal(data, n.Literal.Data) 1095} 1096 1097func (n PropertyName) String() string { 1098 if n.Computed != nil { 1099 val := n.Computed.String() 1100 if val[0] == '(' { 1101 return "[" + val[1:len(val)-1] + "]" 1102 } 1103 return "[" + val + "]" 1104 } 1105 return string(n.Literal.Data) 1106} 1107 1108// JS converts the node back to valid JavaScript 1109func (n PropertyName) JS() string { 1110 return n.String() 1111} 1112 1113// JSON converts the node back to valid JSON 1114func (n PropertyName) JSON() (string, error) { 1115 return "", ErrInvalidJSON 1116} 1117 1118// BindingArray is an array binding pattern. 1119type BindingArray struct { 1120 List []BindingElement 1121 Rest IBinding // can be nil 1122} 1123 1124func (n BindingArray) String() string { 1125 s := "[" 1126 for i, item := range n.List { 1127 if i != 0 { 1128 s += "," 1129 } 1130 s += " " + item.String() 1131 } 1132 if n.Rest != nil { 1133 if len(n.List) != 0 { 1134 s += "," 1135 } 1136 s += " ...Binding(" + n.Rest.String() + ")" 1137 } 1138 return s + " ]" 1139} 1140 1141// JS converts the node back to valid JavaScript 1142func (n BindingArray) JS() string { 1143 s := "[" 1144 for i, item := range n.List { 1145 if i != 0 { 1146 s += "," 1147 } 1148 s += item.JS() 1149 } 1150 if n.Rest != nil { 1151 if len(n.List) != 0 { 1152 s += "," 1153 } 1154 s += " ..." + n.Rest.JS() 1155 } 1156 return s + "]" 1157} 1158 1159// JSON converts the node back to valid JSON 1160func (n BindingArray) JSON() (string, error) { 1161 return "", ErrInvalidJSON 1162} 1163 1164// BindingObjectItem is a binding property. 1165type BindingObjectItem struct { 1166 Key *PropertyName // can be nil 1167 Value BindingElement 1168} 1169 1170func (n BindingObjectItem) String() string { 1171 s := "" 1172 if n.Key != nil { 1173 if v, ok := n.Value.Binding.(*Var); !ok || !n.Key.IsIdent(v.Data) { 1174 s += " " + n.Key.String() + ":" 1175 } 1176 } 1177 return " " + n.Value.String() 1178} 1179 1180// JS converts the node back to valid JavaScript 1181func (n BindingObjectItem) JS() string { 1182 s := "" 1183 if n.Key != nil { 1184 if v, ok := n.Value.Binding.(*Var); !ok || !n.Key.IsIdent(v.Data) { 1185 s += " " + n.Key.JS() + ":" 1186 } 1187 } 1188 return " " + n.Value.JS() 1189} 1190 1191// JSON converts the node back to valid JSON 1192func (n BindingObjectItem) JSON() (string, error) { 1193 return "", ErrInvalidJSON 1194} 1195 1196// BindingObject is an object binding pattern. 1197type BindingObject struct { 1198 List []BindingObjectItem 1199 Rest *Var // can be nil 1200} 1201 1202func (n BindingObject) String() string { 1203 s := "{" 1204 for i, item := range n.List { 1205 if i != 0 { 1206 s += "," 1207 } 1208 if item.Key != nil { 1209 if v, ok := item.Value.Binding.(*Var); !ok || !item.Key.IsIdent(v.Data) { 1210 s += " " + item.Key.String() + ":" 1211 } 1212 } 1213 s += " " + item.Value.String() 1214 } 1215 if n.Rest != nil { 1216 if len(n.List) != 0 { 1217 s += "," 1218 } 1219 s += " ...Binding(" + string(n.Rest.Data) + ")" 1220 } 1221 return s + " }" 1222} 1223 1224// JS converts the node back to valid JavaScript 1225func (n BindingObject) JS() string { 1226 s := "{" 1227 for i, item := range n.List { 1228 if i != 0 { 1229 s += "," 1230 } 1231 if item.Key != nil { 1232 if v, ok := item.Value.Binding.(*Var); !ok || !item.Key.IsIdent(v.Data) { 1233 s += " " + item.Key.JS() + ":" 1234 } 1235 } 1236 s += " " + item.Value.JS() 1237 } 1238 if n.Rest != nil { 1239 if len(n.List) != 0 { 1240 s += "," 1241 } 1242 s += " ..." + string(n.Rest.Data) 1243 } 1244 return s + " }" 1245} 1246 1247// JSON converts the node back to valid JSON 1248func (n BindingObject) JSON() (string, error) { 1249 return "", ErrInvalidJSON 1250} 1251 1252// BindingElement is a binding element. 1253type BindingElement struct { 1254 Binding IBinding // can be nil (in case of ellision) 1255 Default IExpr // can be nil 1256} 1257 1258func (n BindingElement) String() string { 1259 if n.Binding == nil { 1260 return "Binding()" 1261 } 1262 s := "Binding(" + n.Binding.String() 1263 if n.Default != nil { 1264 s += " = " + n.Default.String() 1265 } 1266 return s + ")" 1267} 1268 1269// JS converts the node back to valid JavaScript 1270func (n BindingElement) JS() string { 1271 if n.Binding == nil { 1272 return "" 1273 } 1274 s := n.Binding.JS() 1275 if n.Default != nil { 1276 s += " = " + n.Default.JS() 1277 } 1278 return s 1279} 1280 1281// JSON converts the node back to valid JSON 1282func (n BindingElement) JSON() (string, error) { 1283 return "", ErrInvalidJSON 1284} 1285 1286func (v *Var) bindingNode() {} 1287func (n BindingArray) bindingNode() {} 1288func (n BindingObject) bindingNode() {} 1289 1290//////////////////////////////////////////////////////////////// 1291 1292// VarDecl is a variable statement or lexical declaration. 1293type VarDecl struct { 1294 TokenType 1295 List []BindingElement 1296} 1297 1298func (n VarDecl) String() string { 1299 s := "Decl(" + n.TokenType.String() 1300 for _, item := range n.List { 1301 s += " " + item.String() 1302 } 1303 return s + ")" 1304} 1305 1306// JS converts the node back to valid JavaScript 1307func (n VarDecl) JS() string { 1308 s := n.TokenType.String() 1309 for i, item := range n.List { 1310 if i != 0 { 1311 s += "," 1312 } 1313 s += " " + item.JS() 1314 } 1315 return s 1316} 1317 1318// JSON converts the node back to valid JSON 1319func (n VarDecl) JSON() (string, error) { 1320 return "", ErrInvalidJSON 1321} 1322 1323// Params is a list of parameters for functions, methods, and arrow function. 1324type Params struct { 1325 List []BindingElement 1326 Rest IBinding // can be nil 1327} 1328 1329func (n Params) String() string { 1330 s := "Params(" 1331 for i, item := range n.List { 1332 if i != 0 { 1333 s += ", " 1334 } 1335 s += item.String() 1336 } 1337 if n.Rest != nil { 1338 if len(n.List) != 0 { 1339 s += ", " 1340 } 1341 s += "...Binding(" + n.Rest.String() + ")" 1342 } 1343 return s + ")" 1344} 1345 1346// JS converts the node back to valid JavaScript 1347func (n Params) JS() string { 1348 s := "(" 1349 for i, item := range n.List { 1350 if i != 0 { 1351 s += ", " 1352 } 1353 s += item.JS() 1354 } 1355 if n.Rest != nil { 1356 if len(n.List) != 0 { 1357 s += ", " 1358 } 1359 s += "..." + n.Rest.JS() 1360 } 1361 return s + ")" 1362} 1363 1364// JSON converts the node back to valid JSON 1365func (n Params) JSON() (string, error) { 1366 return "", ErrInvalidJSON 1367} 1368 1369// FuncDecl is an (async) (generator) function declaration or expression. 1370type FuncDecl struct { 1371 Async bool 1372 Generator bool 1373 Name *Var // can be nil 1374 Params Params 1375 Body BlockStmt 1376} 1377 1378func (n FuncDecl) String() string { 1379 s := "Decl(" 1380 if n.Async { 1381 s += "async function" 1382 } else { 1383 s += "function" 1384 } 1385 if n.Generator { 1386 s += "*" 1387 } 1388 if n.Name != nil { 1389 s += " " + string(n.Name.Data) 1390 } 1391 return s + " " + n.Params.String() + " " + n.Body.String() + ")" 1392} 1393 1394// JS converts the node back to valid JavaScript 1395func (n FuncDecl) JS() string { 1396 s := "" 1397 if n.Async { 1398 s += "async function" 1399 } else { 1400 s += "function" 1401 } 1402 if n.Generator { 1403 s += "*" 1404 } 1405 if n.Name != nil { 1406 s += " " + string(n.Name.Data) 1407 } 1408 return s + " " + n.Params.JS() + " " + n.Body.JS() 1409} 1410 1411// JSON converts the node back to valid JSON 1412func (n FuncDecl) JSON() (string, error) { 1413 return "", ErrInvalidJSON 1414} 1415 1416// MethodDecl is a method definition in a class declaration. 1417type MethodDecl struct { 1418 Static bool 1419 Async bool 1420 Generator bool 1421 Get bool 1422 Set bool 1423 Name PropertyName 1424 Params Params 1425 Body BlockStmt 1426} 1427 1428func (n MethodDecl) String() string { 1429 s := "" 1430 if n.Static { 1431 s += " static" 1432 } 1433 if n.Async { 1434 s += " async" 1435 } 1436 if n.Generator { 1437 s += " *" 1438 } 1439 if n.Get { 1440 s += " get" 1441 } 1442 if n.Set { 1443 s += " set" 1444 } 1445 s += " " + n.Name.String() + " " + n.Params.String() + " " + n.Body.String() 1446 return "Method(" + s[1:] + ")" 1447} 1448 1449// JS converts the node back to valid JavaScript 1450func (n MethodDecl) JS() string { 1451 s := "" 1452 if n.Static { 1453 s += " static" 1454 } 1455 if n.Async { 1456 s += " async" 1457 } 1458 if n.Generator { 1459 s += " *" 1460 } 1461 if n.Get { 1462 s += " get" 1463 } 1464 if n.Set { 1465 s += " set" 1466 } 1467 s += " " + n.Name.JS() + " " + n.Params.JS() + " " + n.Body.JS() 1468 return s[1:] 1469} 1470 1471// JSON converts the node back to valid JSON 1472func (n MethodDecl) JSON() (string, error) { 1473 return "", ErrInvalidJSON 1474} 1475 1476// FieldDefinition is a field definition in a class declaration. 1477type FieldDefinition struct { 1478 Name PropertyName 1479 Init IExpr 1480} 1481 1482func (n FieldDefinition) String() string { 1483 s := "Definition(" + n.Name.String() 1484 if n.Init != nil { 1485 s += " = " + n.Init.String() 1486 } 1487 return s + ")" 1488} 1489 1490// JS converts the node back to valid JavaScript 1491func (n FieldDefinition) JS() string { 1492 s := n.Name.String() 1493 if n.Init != nil { 1494 s += " = " + n.Init.JS() 1495 } 1496 return s 1497} 1498 1499// JSON converts the node back to valid JSON 1500func (n FieldDefinition) JSON() (string, error) { 1501 return "", ErrInvalidJSON 1502} 1503 1504// ClassDecl is a class declaration. 1505type ClassDecl struct { 1506 Name *Var // can be nil 1507 Extends IExpr // can be nil 1508 Definitions []FieldDefinition 1509 Methods []*MethodDecl 1510} 1511 1512func (n ClassDecl) String() string { 1513 s := "Decl(class" 1514 if n.Name != nil { 1515 s += " " + string(n.Name.Data) 1516 } 1517 if n.Extends != nil { 1518 s += " extends " + n.Extends.String() 1519 } 1520 for _, item := range n.Definitions { 1521 s += " " + item.String() 1522 } 1523 for _, item := range n.Methods { 1524 s += " " + item.String() 1525 } 1526 return s + ")" 1527} 1528 1529// JS converts the node back to valid JavaScript 1530func (n ClassDecl) JS() string { 1531 s := "class" 1532 if n.Name != nil { 1533 s += " " + string(n.Name.Data) 1534 } 1535 if n.Extends != nil { 1536 s += " extends " + n.Extends.JS() 1537 } 1538 s += " { " 1539 for _, item := range n.Definitions { 1540 s += item.JS() + "; " 1541 } 1542 for _, item := range n.Methods { 1543 s += item.JS() + "; " 1544 } 1545 return s + "}" 1546} 1547 1548// JSON converts the node back to valid JSON 1549func (n ClassDecl) JSON() (string, error) { 1550 return "", ErrInvalidJSON 1551} 1552 1553func (n VarDecl) stmtNode() {} 1554func (n FuncDecl) stmtNode() {} 1555func (n ClassDecl) stmtNode() {} 1556 1557func (n VarDecl) exprNode() {} // not a real IExpr, used for ForInit and ExportDecl 1558func (n FuncDecl) exprNode() {} 1559func (n ClassDecl) exprNode() {} 1560func (n MethodDecl) exprNode() {} // not a real IExpr, used for ObjectExpression PropertyName 1561 1562//////////////////////////////////////////////////////////////// 1563 1564// LiteralExpr can be this, null, boolean, numeric, string, or regular expression literals. 1565type LiteralExpr struct { 1566 TokenType 1567 Data []byte 1568} 1569 1570func (n LiteralExpr) String() string { 1571 return string(n.Data) 1572} 1573 1574// JS converts the node back to valid JavaScript 1575func (n LiteralExpr) JS() string { 1576 return string(n.Data) 1577} 1578 1579// JSON converts the node back to valid JSON 1580func (n LiteralExpr) JSON() (string, error) { 1581 if n.TokenType == TrueToken || n.TokenType == FalseToken || n.TokenType == NullToken || n.TokenType == DecimalToken { 1582 return string(n.Data), nil 1583 } else if n.TokenType == StringToken { 1584 if n.Data[0] == '\'' { 1585 n.Data[0] = '"' 1586 n.Data[len(n.Data)-1] = '"' 1587 } 1588 return string(n.Data), nil 1589 } 1590 return "", ErrInvalidJSON 1591} 1592 1593// Element is an array literal element. 1594type Element struct { 1595 Value IExpr // can be nil 1596 Spread bool 1597} 1598 1599func (n Element) String() string { 1600 s := "" 1601 if n.Value != nil { 1602 if n.Spread { 1603 s += "..." 1604 } 1605 s += n.Value.String() 1606 } 1607 return s 1608} 1609 1610// JS converts the node back to valid JavaScript 1611func (n Element) JS() string { 1612 s := "" 1613 if n.Value != nil { 1614 if n.Spread { 1615 s += "..." 1616 } 1617 s += n.Value.JS() 1618 } 1619 return s 1620} 1621 1622// JSON converts the node back to valid JSON 1623func (n Element) JSON() (string, error) { 1624 return "", ErrInvalidJSON 1625} 1626 1627// ArrayExpr is an array literal. 1628type ArrayExpr struct { 1629 List []Element 1630} 1631 1632func (n ArrayExpr) String() string { 1633 s := "[" 1634 for i, item := range n.List { 1635 if i != 0 { 1636 s += ", " 1637 } 1638 if item.Value != nil { 1639 if item.Spread { 1640 s += "..." 1641 } 1642 s += item.Value.String() 1643 } 1644 } 1645 if 0 < len(n.List) && n.List[len(n.List)-1].Value == nil { 1646 s += "," 1647 } 1648 return s + "]" 1649} 1650 1651// JS converts the node back to valid JavaScript 1652func (n ArrayExpr) JS() string { 1653 s := "[" 1654 for i, item := range n.List { 1655 if i != 0 { 1656 s += ", " 1657 } 1658 if item.Value != nil { 1659 if item.Spread { 1660 s += "..." 1661 } 1662 s += item.Value.JS() 1663 } 1664 } 1665 if 0 < len(n.List) && n.List[len(n.List)-1].Value == nil { 1666 s += "," 1667 } 1668 return s + "]" 1669} 1670 1671// JSON converts the node back to valid JSON 1672func (n ArrayExpr) JSON() (string, error) { 1673 s := "[" 1674 for i, item := range n.List { 1675 if i != 0 { 1676 s += ", " 1677 } 1678 if item.Value != nil { 1679 if item.Spread { 1680 return "", ErrInvalidJSON 1681 } 1682 ss, err := item.Value.JSON() 1683 if err != nil { 1684 return "", err 1685 } 1686 s += ss 1687 } 1688 } 1689 if 0 < len(n.List) && n.List[len(n.List)-1].Value == nil { 1690 return "", ErrInvalidJSON 1691 } 1692 return s + "]", nil 1693} 1694 1695// Property is a property definition in an object literal. 1696type Property struct { 1697 // either Name or Spread are set. When Spread is set then Value is AssignmentExpression 1698 // if Init is set then Value is IdentifierReference, otherwise it can also be MethodDefinition 1699 Name *PropertyName // can be nil 1700 Spread bool 1701 Value IExpr 1702 Init IExpr // can be nil 1703} 1704 1705func (n Property) String() string { 1706 s := "" 1707 if n.Name != nil { 1708 if v, ok := n.Value.(*Var); !ok || !n.Name.IsIdent(v.Data) { 1709 s += n.Name.String() + ": " 1710 } 1711 } else if n.Spread { 1712 s += "..." 1713 } 1714 s += n.Value.String() 1715 if n.Init != nil { 1716 s += " = " + n.Init.String() 1717 } 1718 return s 1719} 1720 1721// JS converts the node back to valid JavaScript 1722func (n Property) JS() string { 1723 s := "" 1724 if n.Name != nil { 1725 if v, ok := n.Value.(*Var); !ok || !n.Name.IsIdent(v.Data) { 1726 s += n.Name.JS() + ": " 1727 } 1728 } else if n.Spread { 1729 s += "..." 1730 } 1731 s += n.Value.JS() 1732 if n.Init != nil { 1733 s += " = " + n.Init.JS() 1734 } 1735 return s 1736} 1737 1738// JSON converts the node back to valid JSON 1739func (n Property) JSON() (string, error) { 1740 s := "" 1741 if n.Name == nil || n.Name.Literal.TokenType != StringToken && n.Name.Literal.TokenType != IdentifierToken || n.Spread || n.Init != nil { 1742 return "", ErrInvalidJSON 1743 } else if n.Name.Literal.TokenType == IdentifierToken { 1744 n.Name.Literal.TokenType = StringToken 1745 n.Name.Literal.Data = append(append([]byte{'"'}, n.Name.Literal.Data...), '"') 1746 } 1747 1748 ss, _ := n.Name.Literal.JSON() 1749 s += ss + ": " 1750 1751 var err error 1752 ss, err = n.Value.JSON() 1753 if err != nil { 1754 fmt.Println("b") 1755 return "", err 1756 } 1757 s += ss 1758 return s, nil 1759} 1760 1761// ObjectExpr is an object literal. 1762type ObjectExpr struct { 1763 List []Property 1764} 1765 1766func (n ObjectExpr) String() string { 1767 s := "{" 1768 for i, item := range n.List { 1769 if i != 0 { 1770 s += ", " 1771 } 1772 s += item.String() 1773 } 1774 return s + "}" 1775} 1776 1777// JS converts the node back to valid JavaScript 1778func (n ObjectExpr) JS() string { 1779 s := "{" 1780 for i, item := range n.List { 1781 if i != 0 { 1782 s += ", " 1783 } 1784 s += item.JS() 1785 } 1786 return s + "}" 1787} 1788 1789// JSON converts the node back to valid JSON 1790func (n ObjectExpr) JSON() (string, error) { 1791 s := "{" 1792 for i, item := range n.List { 1793 if i != 0 { 1794 s += ", " 1795 } 1796 ss, err := item.JSON() 1797 if err != nil { 1798 return "", err 1799 } 1800 s += ss 1801 } 1802 return s + "}", nil 1803} 1804 1805// TemplatePart is a template head or middle. 1806type TemplatePart struct { 1807 Value []byte 1808 Expr IExpr 1809} 1810 1811func (n TemplatePart) String() string { 1812 return string(n.Value) + n.Expr.String() 1813} 1814 1815// JS converts the node back to valid JavaScript 1816func (n TemplatePart) JS() string { 1817 return string(n.Value) + n.Expr.JS() 1818} 1819 1820// JSON converts the node back to valid JSON 1821func (n TemplatePart) JSON() (string, error) { 1822 return "", ErrInvalidJSON 1823} 1824 1825// TemplateExpr is a template literal or member/call expression, super property, or optional chain with template literal. 1826type TemplateExpr struct { 1827 Tag IExpr // can be nil 1828 List []TemplatePart 1829 Tail []byte 1830 Prec OpPrec 1831} 1832 1833func (n TemplateExpr) String() string { 1834 s := "" 1835 if n.Tag != nil { 1836 s += n.Tag.String() 1837 } 1838 for _, item := range n.List { 1839 s += item.String() 1840 } 1841 return s + string(n.Tail) 1842} 1843 1844// JS converts the node back to valid JavaScript 1845func (n TemplateExpr) JS() string { 1846 s := "" 1847 if n.Tag != nil { 1848 s += n.Tag.JS() 1849 } 1850 for _, item := range n.List { 1851 s += item.JS() 1852 } 1853 return s + string(n.Tail) 1854} 1855 1856// JSON converts the node back to valid JSON 1857func (n TemplateExpr) JSON() (string, error) { 1858 return "", ErrInvalidJSON 1859} 1860 1861// GroupExpr is a parenthesized expression. 1862type GroupExpr struct { 1863 X IExpr 1864} 1865 1866func (n GroupExpr) String() string { 1867 return "(" + n.X.String() + ")" 1868} 1869 1870// JS converts the node back to valid JavaScript 1871func (n GroupExpr) JS() string { 1872 return "(" + n.X.JS() + ")" 1873} 1874 1875// JSON converts the node back to valid JSON 1876func (n GroupExpr) JSON() (string, error) { 1877 return "", ErrInvalidJSON 1878} 1879 1880// IndexExpr is a member/call expression, super property, or optional chain with an index expression. 1881type IndexExpr struct { 1882 X IExpr 1883 Y IExpr 1884 Prec OpPrec 1885} 1886 1887func (n IndexExpr) String() string { 1888 return "(" + n.X.String() + "[" + n.Y.String() + "])" 1889} 1890 1891// JS converts the node back to valid JavaScript 1892func (n IndexExpr) JS() string { 1893 return n.X.JS() + "[" + n.Y.JS() + "]" 1894} 1895 1896// JSON converts the node back to valid JSON 1897func (n IndexExpr) JSON() (string, error) { 1898 return "", ErrInvalidJSON 1899} 1900 1901// DotExpr is a member/call expression, super property, or optional chain with a dot expression. 1902type DotExpr struct { 1903 X IExpr 1904 Y LiteralExpr 1905 Prec OpPrec 1906} 1907 1908func (n DotExpr) String() string { 1909 return "(" + n.X.String() + "." + n.Y.String() + ")" 1910} 1911 1912// JS converts the node back to valid JavaScript 1913func (n DotExpr) JS() string { 1914 return n.X.JS() + "." + n.Y.JS() 1915} 1916 1917// JSON converts the node back to valid JSON 1918func (n DotExpr) JSON() (string, error) { 1919 return "", ErrInvalidJSON 1920} 1921 1922// NewTargetExpr is a new target meta property. 1923type NewTargetExpr struct { 1924} 1925 1926func (n NewTargetExpr) String() string { 1927 return "(new.target)" 1928} 1929 1930// JS converts the node back to valid JavaScript 1931func (n NewTargetExpr) JS() string { 1932 return "new.target" 1933} 1934 1935// JSON converts the node back to valid JSON 1936func (n NewTargetExpr) JSON() (string, error) { 1937 return "", ErrInvalidJSON 1938} 1939 1940// ImportMetaExpr is a import meta meta property. 1941type ImportMetaExpr struct { 1942} 1943 1944func (n ImportMetaExpr) String() string { 1945 return "(import.meta)" 1946} 1947 1948// JS converts the node back to valid JavaScript 1949func (n ImportMetaExpr) JS() string { 1950 return "import.meta" 1951} 1952 1953// JSON converts the node back to valid JSON 1954func (n ImportMetaExpr) JSON() (string, error) { 1955 return "", ErrInvalidJSON 1956} 1957 1958type Arg struct { 1959 Value IExpr 1960 Rest bool 1961} 1962 1963func (n Arg) String() string { 1964 s := "" 1965 if n.Rest { 1966 s += "..." 1967 } 1968 return s + n.Value.String() 1969} 1970 1971// JS converts the node back to valid JavaScript 1972func (n Arg) JS() string { 1973 s := "" 1974 if n.Rest { 1975 s += "..." 1976 } 1977 return s + n.Value.JS() 1978} 1979 1980// JSON converts the node back to valid JSON 1981func (n Arg) JSON() (string, error) { 1982 return "", ErrInvalidJSON 1983} 1984 1985// Args is a list of arguments as used by new and call expressions. 1986type Args struct { 1987 List []Arg 1988} 1989 1990func (n Args) String() string { 1991 s := "(" 1992 for i, item := range n.List { 1993 if i != 0 { 1994 s += ", " 1995 } 1996 s += item.String() 1997 } 1998 return s + ")" 1999} 2000 2001// JS converts the node back to valid JavaScript 2002func (n Args) JS() string { 2003 s := "" 2004 for i, item := range n.List { 2005 if i != 0 { 2006 s += ", " 2007 } 2008 s += item.JS() 2009 } 2010 return s 2011} 2012 2013// JSON converts the node back to valid JSON 2014func (n Args) JSON() (string, error) { 2015 return "", ErrInvalidJSON 2016} 2017 2018// NewExpr is a new expression or new member expression. 2019type NewExpr struct { 2020 X IExpr 2021 Args *Args // can be nil 2022} 2023 2024func (n NewExpr) String() string { 2025 if n.Args != nil { 2026 return "(new " + n.X.String() + n.Args.String() + ")" 2027 } 2028 return "(new " + n.X.String() + ")" 2029} 2030 2031// JS converts the node back to valid JavaScript 2032func (n NewExpr) JS() string { 2033 if n.Args != nil { 2034 return "new " + n.X.JS() + "(" + n.Args.JS() + ")" 2035 } 2036 2037 // always use parentheses to prevent errors when chaining e.g. new Date().getTime() 2038 return "new " + n.X.JS() + "()" 2039} 2040 2041// JSON converts the node back to valid JSON 2042func (n NewExpr) JSON() (string, error) { 2043 return "", ErrInvalidJSON 2044} 2045 2046// CallExpr is a call expression. 2047type CallExpr struct { 2048 X IExpr 2049 Args Args 2050} 2051 2052func (n CallExpr) String() string { 2053 return "(" + n.X.String() + n.Args.String() + ")" 2054} 2055 2056// JS converts the node back to valid JavaScript 2057func (n CallExpr) JS() string { 2058 return n.X.JS() + "(" + n.Args.JS() + ")" 2059} 2060 2061// JSON converts the node back to valid JSON 2062func (n CallExpr) JSON() (string, error) { 2063 return "", ErrInvalidJSON 2064} 2065 2066// OptChainExpr is an optional chain. 2067type OptChainExpr struct { 2068 X IExpr 2069 Y IExpr // can be CallExpr, IndexExpr, LiteralExpr, or TemplateExpr 2070} 2071 2072func (n OptChainExpr) String() string { 2073 s := "(" + n.X.String() + "?." 2074 switch y := n.Y.(type) { 2075 case *CallExpr: 2076 return s + y.Args.String() + ")" 2077 case *IndexExpr: 2078 return s + "[" + y.Y.String() + "])" 2079 default: 2080 return s + y.String() + ")" 2081 } 2082} 2083 2084// JS converts the node back to valid JavaScript 2085func (n OptChainExpr) JS() string { 2086 s := n.X.String() + "?." 2087 switch y := n.Y.(type) { 2088 case *CallExpr: 2089 return s + y.Args.JS() + ")" 2090 case *IndexExpr: 2091 return s + "[" + y.Y.JS() + "])" 2092 default: 2093 return s + y.JS() 2094 } 2095} 2096 2097// JSON converts the node back to valid JSON 2098func (n OptChainExpr) JSON() (string, error) { 2099 return "", ErrInvalidJSON 2100} 2101 2102// UnaryExpr is an update or unary expression. 2103type UnaryExpr struct { 2104 Op TokenType 2105 X IExpr 2106} 2107 2108func (n UnaryExpr) String() string { 2109 if n.Op == PostIncrToken || n.Op == PostDecrToken { 2110 return "(" + n.X.String() + n.Op.String() + ")" 2111 } else if IsIdentifierName(n.Op) { 2112 return "(" + n.Op.String() + " " + n.X.String() + ")" 2113 } 2114 return "(" + n.Op.String() + n.X.String() + ")" 2115} 2116 2117// JS converts the node back to valid JavaScript 2118func (n UnaryExpr) JS() string { 2119 if n.Op == PostIncrToken || n.Op == PostDecrToken { 2120 return n.X.JS() + n.Op.String() 2121 } else if IsIdentifierName(n.Op) { 2122 return n.Op.String() + " " + n.X.JS() 2123 } 2124 return n.Op.String() + n.X.JS() 2125} 2126 2127// JSON converts the node back to valid JSON 2128func (n UnaryExpr) JSON() (string, error) { 2129 return "", ErrInvalidJSON 2130} 2131 2132// BinaryExpr is a binary expression. 2133type BinaryExpr struct { 2134 Op TokenType 2135 X, Y IExpr 2136} 2137 2138func (n BinaryExpr) String() string { 2139 if IsIdentifierName(n.Op) { 2140 return "(" + n.X.String() + " " + n.Op.String() + " " + n.Y.String() + ")" 2141 } 2142 return "(" + n.X.String() + n.Op.String() + n.Y.String() + ")" 2143} 2144 2145// JS converts the node back to valid JavaScript 2146func (n BinaryExpr) JS() string { 2147 return n.X.JS() + " " + n.Op.String() + " " + n.Y.JS() 2148} 2149 2150// JSON converts the node back to valid JSON 2151func (n BinaryExpr) JSON() (string, error) { 2152 return "", ErrInvalidJSON 2153} 2154 2155// CondExpr is a conditional expression. 2156type CondExpr struct { 2157 Cond, X, Y IExpr 2158} 2159 2160func (n CondExpr) String() string { 2161 return "(" + n.Cond.String() + " ? " + n.X.String() + " : " + n.Y.String() + ")" 2162} 2163 2164// JS converts the node back to valid JavaScript 2165func (n CondExpr) JS() string { 2166 return n.Cond.JS() + " ? " + n.X.JS() + " : " + n.Y.JS() 2167} 2168 2169// JSON converts the node back to valid JSON 2170func (n CondExpr) JSON() (string, error) { 2171 return "", ErrInvalidJSON 2172} 2173 2174// YieldExpr is a yield expression. 2175type YieldExpr struct { 2176 Generator bool 2177 X IExpr // can be nil 2178} 2179 2180func (n YieldExpr) String() string { 2181 if n.X == nil { 2182 return "(yield)" 2183 } 2184 s := "(yield" 2185 if n.Generator { 2186 s += "*" 2187 } 2188 return s + " " + n.X.String() + ")" 2189} 2190 2191// JS converts the node back to valid JavaScript 2192func (n YieldExpr) JS() string { 2193 if n.X == nil { 2194 return "yield" 2195 } 2196 s := "yield" 2197 if n.Generator { 2198 s += "*" 2199 } 2200 return s + " " + n.X.JS() 2201} 2202 2203// JSON converts the node back to valid JSON 2204func (n YieldExpr) JSON() (string, error) { 2205 return "", ErrInvalidJSON 2206} 2207 2208// ArrowFunc is an (async) arrow function. 2209type ArrowFunc struct { 2210 Async bool 2211 Params Params 2212 Body BlockStmt 2213} 2214 2215func (n ArrowFunc) String() string { 2216 s := "(" 2217 if n.Async { 2218 s += "async " 2219 } 2220 return s + n.Params.String() + " => " + n.Body.String() + ")" 2221} 2222 2223// JS converts the node back to valid JavaScript 2224func (n ArrowFunc) JS() string { 2225 s := "" 2226 if n.Async { 2227 s += "async " 2228 } 2229 return s + n.Params.JS() + " => " + n.Body.JS() 2230} 2231 2232// JSON converts the node back to valid JSON 2233func (n ArrowFunc) JSON() (string, error) { 2234 return "", ErrInvalidJSON 2235} 2236 2237func (v *Var) exprNode() {} 2238func (n LiteralExpr) exprNode() {} 2239func (n ArrayExpr) exprNode() {} 2240func (n ObjectExpr) exprNode() {} 2241func (n TemplateExpr) exprNode() {} 2242func (n GroupExpr) exprNode() {} 2243func (n DotExpr) exprNode() {} 2244func (n IndexExpr) exprNode() {} 2245func (n NewTargetExpr) exprNode() {} 2246func (n ImportMetaExpr) exprNode() {} 2247func (n NewExpr) exprNode() {} 2248func (n CallExpr) exprNode() {} 2249func (n OptChainExpr) exprNode() {} 2250func (n UnaryExpr) exprNode() {} 2251func (n BinaryExpr) exprNode() {} 2252func (n CondExpr) exprNode() {} 2253func (n YieldExpr) exprNode() {} 2254func (n ArrowFunc) exprNode() {} 2255