1package js
   2
   3import (
   4	"bytes"
   5	"fmt"
   6	"io"
   7	"strconv"
   8
   9	"github.com/tdewolff/parse/v2"
  10)
  11
  12var ErrInvalidJSON = fmt.Errorf("invalid JSON")
  13
  14type JSONer interface {
  15	JSON(*bytes.Buffer) error
  16}
  17
  18// AST is the full ECMAScript abstract syntax tree.
  19type AST struct {
  20	Comments  [][]byte // first comments in file
  21	BlockStmt          // module
  22}
  23
  24func (ast *AST) String() string {
  25	s := ""
  26	for i, item := range ast.BlockStmt.List {
  27		if i != 0 {
  28			s += " "
  29		}
  30		s += item.String()
  31	}
  32	return s
  33}
  34
  35////////////////////////////////////////////////////////////////
  36
  37// DeclType specifies the kind of declaration.
  38type DeclType uint16
  39
  40// DeclType values.
  41const (
  42	NoDecl       DeclType = iota // undeclared variables
  43	VariableDecl                 // var
  44	FunctionDecl                 // function
  45	ArgumentDecl                 // function and method arguments
  46	LexicalDecl                  // let, const, class
  47	CatchDecl                    // catch statement argument
  48	ExprDecl                     // function expression name or class expression name
  49)
  50
  51func (decl DeclType) String() string {
  52	switch decl {
  53	case NoDecl:
  54		return "NoDecl"
  55	case VariableDecl:
  56		return "VariableDecl"
  57	case FunctionDecl:
  58		return "FunctionDecl"
  59	case ArgumentDecl:
  60		return "ArgumentDecl"
  61	case LexicalDecl:
  62		return "LexicalDecl"
  63	case CatchDecl:
  64		return "CatchDecl"
  65	case ExprDecl:
  66		return "ExprDecl"
  67	}
  68	return "Invalid(" + strconv.Itoa(int(decl)) + ")"
  69}
  70
  71// 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.
  72type Var struct {
  73	Data []byte
  74	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
  75	Uses uint16
  76	Decl DeclType
  77}
  78
  79// Name returns the variable name.
  80func (v *Var) Name() []byte {
  81	for v.Link != nil {
  82		v = v.Link
  83	}
  84	return v.Data
  85}
  86
  87func (v Var) String() string {
  88	return string(v.Name())
  89}
  90
  91// JS converts the node back to valid JavaScript
  92func (v Var) JS() string {
  93	return v.String()
  94}
  95
  96// JS converts the node back to valid JavaScript (writes to io.Writer)
  97func (v Var) JSWriteTo(w io.Writer) (i int, err error) {
  98	return w.Write(v.Name())
  99}
 100
 101// VarsByUses is sortable by uses in descending order.
 102// TODO: write custom sorter for varsbyuses
 103type VarsByUses VarArray
 104
 105func (vs VarsByUses) Len() int {
 106	return len(vs)
 107}
 108
 109func (vs VarsByUses) Swap(i, j int) {
 110	vs[i], vs[j] = vs[j], vs[i]
 111}
 112
 113func (vs VarsByUses) Less(i, j int) bool {
 114	return vs[i].Uses > vs[j].Uses
 115}
 116
 117////////////////////////////////////////////////////////////////
 118
 119// VarArray is a set of variables in scopes.
 120type VarArray []*Var
 121
 122func (vs VarArray) String() string {
 123	s := "["
 124	for i, v := range vs {
 125		if i != 0 {
 126			s += ", "
 127		}
 128		links := 0
 129		for v.Link != nil {
 130			v = v.Link
 131			links++
 132		}
 133		s += fmt.Sprintf("Var{%v %s %v %v}", v.Decl, string(v.Data), links, v.Uses)
 134	}
 135	return s + "]"
 136}
 137
 138// Scope is a function or block scope with a list of variables declared and used.
 139type Scope struct {
 140	Parent, Func   *Scope   // Parent is nil for global scope
 141	Declared       VarArray // Link in Var are always nil
 142	Undeclared     VarArray
 143	VarDecls       []*VarDecl
 144	NumForDecls    uint16 // offset into Declared to mark variables used in for statements
 145	NumFuncArgs    uint16 // offset into Declared to mark variables used in function arguments
 146	NumArgUses     uint16 // offset into Undeclared to mark variables used in arguments
 147	IsGlobalOrFunc bool
 148	HasWith        bool
 149}
 150
 151func (s Scope) String() string {
 152	return "Scope{Declared: " + s.Declared.String() + ", Undeclared: " + s.Undeclared.String() + "}"
 153}
 154
 155// Declare declares a new variable.
 156func (s *Scope) Declare(decl DeclType, name []byte) (*Var, bool) {
 157	// refer to new variable for previously undeclared symbols in the current and lower scopes
 158	// this happens in `{ a = 5; } var a` where both a's refer to the same variable
 159	curScope := s
 160	if decl == VariableDecl || decl == FunctionDecl {
 161		// find function scope for var and function declarations
 162		for s != s.Func {
 163			// make sure that `{let i;{var i}}` is an error
 164			if v := s.findDeclared(name, false); v != nil && v.Decl != decl && v.Decl != CatchDecl {
 165				return nil, false
 166			}
 167			s = s.Parent
 168		}
 169	}
 170
 171	if v := s.findDeclared(name, true); v != nil {
 172		// variable already declared, might be an error or a duplicate declaration
 173		if (ArgumentDecl < v.Decl || FunctionDecl < decl) && v.Decl != ExprDecl {
 174			// only allow (v.Decl,decl) of: (var|function|argument,var|function), (expr,*), any other combination is a syntax error
 175			return nil, false
 176		}
 177		if v.Decl == ExprDecl {
 178			v.Decl = decl
 179		}
 180		v.Uses++
 181		for s != curScope {
 182			curScope.AddUndeclared(v) // add variable declaration as used variable to the current scope
 183			curScope = curScope.Parent
 184		}
 185		return v, true
 186	}
 187
 188	var v *Var
 189	// reuse variable if previously used, as in:  a;var a
 190	if decl != ArgumentDecl { // in case of function f(a=b,b), where the first b is different from the second
 191		for i, uv := range s.Undeclared[s.NumArgUses:] {
 192			// no need to evaluate v.Link as v.Data stays the same and Link is nil in the active scope
 193			if 0 < uv.Uses && uv.Decl == NoDecl && bytes.Equal(name, uv.Data) {
 194				// must be NoDecl so that it can't be a var declaration that has been added
 195				v = uv
 196				s.Undeclared = append(s.Undeclared[:int(s.NumArgUses)+i], s.Undeclared[int(s.NumArgUses)+i+1:]...)
 197				break
 198			}
 199		}
 200	}
 201	if v == nil {
 202		// add variable to the context list and to the scope
 203		v = &Var{name, nil, 0, decl}
 204	} else {
 205		v.Decl = decl
 206	}
 207	v.Uses++
 208	s.Declared = append(s.Declared, v)
 209	for s != curScope {
 210		curScope.AddUndeclared(v) // add variable declaration as used variable to the current scope
 211		curScope = curScope.Parent
 212	}
 213	return v, true
 214}
 215
 216// Use increments the usage of a variable.
 217func (s *Scope) Use(name []byte) *Var {
 218	// check if variable is declared in the current scope
 219	v := s.findDeclared(name, false)
 220	if v == nil {
 221		// check if variable is already used before in the current or lower scopes
 222		v = s.findUndeclared(name)
 223		if v == nil {
 224			// add variable to the context list and to the scope's undeclared
 225			v = &Var{name, nil, 0, NoDecl}
 226			s.Undeclared = append(s.Undeclared, v)
 227		}
 228	}
 229	v.Uses++
 230	return v
 231}
 232
 233// findDeclared finds a declared variable in the current scope.
 234func (s *Scope) findDeclared(name []byte, skipForDeclared bool) *Var {
 235	start := 0
 236	if skipForDeclared {
 237		// we skip the for initializer for declarations (only has effect for let/const)
 238		start = int(s.NumForDecls)
 239	}
 240	// reverse order to find the inner let first in `for(let a in []){let a; {a}}`
 241	for i := len(s.Declared) - 1; start <= i; i-- {
 242		v := s.Declared[i]
 243		// no need to evaluate v.Link as v.Data stays the same, and Link is always nil in Declared
 244		if bytes.Equal(name, v.Data) {
 245			return v
 246		}
 247	}
 248	return nil
 249}
 250
 251// findUndeclared finds an undeclared variable in the current and contained scopes.
 252func (s *Scope) findUndeclared(name []byte) *Var {
 253	for _, v := range s.Undeclared {
 254		// no need to evaluate v.Link as v.Data stays the same and Link is nil in the active scope
 255		if 0 < v.Uses && bytes.Equal(name, v.Data) {
 256			return v
 257		}
 258	}
 259	return nil
 260}
 261
 262// add undeclared variable to scope, this is called for the block scope when declaring a var in it
 263func (s *Scope) AddUndeclared(v *Var) {
 264	// don't add undeclared symbol if it's already there
 265	for _, vorig := range s.Undeclared {
 266		if v == vorig {
 267			return
 268		}
 269	}
 270	s.Undeclared = append(s.Undeclared, v) // add variable declaration as used variable to the current scope
 271}
 272
 273// MarkForStmt marks the declared variables in current scope as for statement initializer to distinguish from declarations in body.
 274func (s *Scope) MarkForStmt() {
 275	s.NumForDecls = uint16(len(s.Declared))
 276	s.NumArgUses = uint16(len(s.Undeclared)) // ensures for different b's in for(var a in b){let b}
 277}
 278
 279// MarkFuncArgs marks the declared/undeclared variables in the current scope as function arguments.
 280func (s *Scope) MarkFuncArgs() {
 281	s.NumFuncArgs = uint16(len(s.Declared))
 282	s.NumArgUses = uint16(len(s.Undeclared)) // ensures different b's in `function f(a=b){var b}`.
 283}
 284
 285// HoistUndeclared copies all undeclared variables of the current scope to the parent scope.
 286func (s *Scope) HoistUndeclared() {
 287	for i, vorig := range s.Undeclared {
 288		// no need to evaluate vorig.Link as vorig.Data stays the same
 289		if 0 < vorig.Uses && vorig.Decl == NoDecl {
 290			if v := s.Parent.findDeclared(vorig.Data, false); v != nil {
 291				// check if variable is declared in parent scope
 292				v.Uses += vorig.Uses
 293				vorig.Link = v
 294				s.Undeclared[i] = v // point reference to existing var (to avoid many Link chains)
 295			} else if v := s.Parent.findUndeclared(vorig.Data); v != nil {
 296				// check if variable is already used before in parent scope
 297				v.Uses += vorig.Uses
 298				vorig.Link = v
 299				s.Undeclared[i] = v // point reference to existing var (to avoid many Link chains)
 300			} else {
 301				// add variable to the context list and to the scope's undeclared
 302				s.Parent.Undeclared = append(s.Parent.Undeclared, vorig)
 303			}
 304		}
 305	}
 306}
 307
 308// UndeclareScope undeclares all declared variables in the current scope and adds them to the parent scope.
 309// Called when possible arrow func ends up being a parenthesized expression, scope is not further used.
 310func (s *Scope) UndeclareScope() {
 311	// look if the variable already exists in the parent scope, if so replace the Var pointer in original use
 312	for _, vorig := range s.Declared {
 313		// no need to evaluate vorig.Link as vorig.Data stays the same, and Link is always nil in Declared
 314		// vorig.Uses will be atleast 1
 315		if v := s.Parent.findDeclared(vorig.Data, false); v != nil {
 316			// check if variable has been declared in this scope
 317			v.Uses += vorig.Uses
 318			vorig.Link = v
 319		} else if v := s.Parent.findUndeclared(vorig.Data); v != nil {
 320			// check if variable is already used before in the current or lower scopes
 321			v.Uses += vorig.Uses
 322			vorig.Link = v
 323		} else {
 324			// add variable to the context list and to the scope's undeclared
 325			vorig.Decl = NoDecl
 326			s.Parent.Undeclared = append(s.Parent.Undeclared, vorig)
 327		}
 328	}
 329	s.Declared = s.Declared[:0]
 330	s.Undeclared = s.Undeclared[:0]
 331}
 332
 333// Unscope moves all declared variables of the current scope to the parent scope. Undeclared variables are already in the parent scope.
 334func (s *Scope) Unscope() {
 335	for _, vorig := range s.Declared {
 336		// no need to evaluate vorig.Link as vorig.Data stays the same, and Link is always nil in Declared
 337		// vorig.Uses will be atleast 1
 338		s.Parent.Declared = append(s.Parent.Declared, vorig)
 339	}
 340	s.Declared = s.Declared[:0]
 341	s.Undeclared = s.Undeclared[:0]
 342}
 343
 344////////////////////////////////////////////////////////////////
 345
 346// INode is an interface for AST nodes
 347type INode interface {
 348	String() string
 349	JS() string
 350	JSWriteTo(io.Writer) (int, error)
 351}
 352
 353// IStmt is a dummy interface for statements.
 354type IStmt interface {
 355	INode
 356	stmtNode()
 357}
 358
 359// IBinding is a dummy interface for bindings.
 360type IBinding interface {
 361	INode
 362	bindingNode()
 363}
 364
 365// IExpr is a dummy interface for expressions.
 366type IExpr interface {
 367	INode
 368	exprNode()
 369}
 370
 371////////////////////////////////////////////////////////////////
 372
 373// BlockStmt is a block statement.
 374type BlockStmt struct {
 375	List []IStmt
 376	Scope
 377}
 378
 379func (n BlockStmt) String() string {
 380	s := "Stmt({"
 381	for _, item := range n.List {
 382		s += " " + item.String()
 383	}
 384	return s + " })"
 385}
 386
 387// JS converts the node back to valid JavaScript
 388func (n BlockStmt) JS() string {
 389	s := ""
 390	if n.Scope.Parent != nil {
 391		s += "{ "
 392	}
 393	for _, item := range n.List {
 394		if _, isEmpty := item.(*EmptyStmt); !isEmpty {
 395			s += item.JS() + "; "
 396		}
 397	}
 398	if n.Scope.Parent != nil {
 399		s += "}"
 400	}
 401	return s
 402}
 403
 404// JS converts the node back to valid JavaScript (writes to io.Writer)
 405func (n BlockStmt) JSWriteTo(w io.Writer) (i int, err error) {
 406	var wn int
 407	if n.Scope.Parent != nil {
 408		wn, err = w.Write([]byte("{ "))
 409		i += wn
 410		if err != nil {
 411			return
 412		}
 413	}
 414	for _, item := range n.List {
 415		if _, isEmpty := item.(*EmptyStmt); !isEmpty {
 416			wn, err = item.JSWriteTo(w)
 417			i += wn
 418			if err != nil {
 419				return
 420			}
 421			wn, err = w.Write([]byte("; "))
 422			i += wn
 423			if err != nil {
 424				return
 425			}
 426		}
 427	}
 428	if n.Scope.Parent != nil {
 429		wn, err = w.Write([]byte{'}'})
 430		i += wn
 431		if err != nil {
 432			return
 433		}
 434	}
 435	return
 436}
 437
 438// EmptyStmt is an empty statement.
 439type EmptyStmt struct {
 440}
 441
 442func (n EmptyStmt) String() string {
 443	return "Stmt(;)"
 444}
 445
 446// JS converts the node back to valid JavaScript
 447func (n EmptyStmt) JS() string {
 448	return ";"
 449}
 450
 451// JS converts the node back to valid JavaScript (writes to io.Writer)
 452func (n EmptyStmt) JSWriteTo(w io.Writer) (i int, err error) {
 453	wn, err := w.Write([]byte{';'})
 454	i = wn
 455	return
 456}
 457
 458// ExprStmt is an expression statement.
 459type ExprStmt struct {
 460	Value IExpr
 461}
 462
 463func (n ExprStmt) String() string {
 464	val := n.Value.String()
 465	if val[0] == '(' && val[len(val)-1] == ')' {
 466		return "Stmt" + n.Value.String()
 467	}
 468	return "Stmt(" + n.Value.String() + ")"
 469}
 470
 471// JS converts the node back to valid JavaScript
 472func (n ExprStmt) JS() string {
 473	return n.Value.JS()
 474}
 475
 476// JS converts the node back to valid JavaScript (writes to io.Writer)
 477func (n ExprStmt) JSWriteTo(w io.Writer) (i int, err error) {
 478	return n.Value.JSWriteTo(w)
 479}
 480
 481// IfStmt is an if statement.
 482type IfStmt struct {
 483	Cond IExpr
 484	Body IStmt
 485	Else IStmt // can be nil
 486}
 487
 488func (n IfStmt) String() string {
 489	s := "Stmt(if " + n.Cond.String() + " " + n.Body.String()
 490	if n.Else != nil {
 491		s += " else " + n.Else.String()
 492	}
 493	return s + ")"
 494}
 495
 496// JS converts the node back to valid JavaScript
 497func (n IfStmt) JS() string {
 498	s := "if (" + n.Cond.JS() + ") "
 499	switch n.Body.(type) {
 500	case *BlockStmt:
 501		s += n.Body.JS()
 502	default:
 503		s += "{ " + n.Body.JS() + " }"
 504	}
 505	if n.Else != nil {
 506		switch n.Else.(type) {
 507		case *BlockStmt:
 508			s += " else " + n.Else.JS()
 509		default:
 510			s += " else { " + n.Else.JS() + " }"
 511		}
 512	}
 513	return s
 514}
 515
 516// JS converts the node back to valid JavaScript (writes to io.Writer)
 517func (n IfStmt) JSWriteTo(w io.Writer) (i int, err error) {
 518	var wn int
 519	wn, err = w.Write([]byte("if ("))
 520	i += wn
 521	if err != nil {
 522		return
 523	}
 524	wn, err = n.Cond.JSWriteTo(w)
 525	i += wn
 526	if err != nil {
 527		return
 528	}
 529	wn, err = w.Write([]byte(") "))
 530	i += wn
 531	if err != nil {
 532		return
 533	}
 534	switch n.Body.(type) {
 535	case *BlockStmt:
 536		wn, err = n.Body.JSWriteTo(w)
 537		i += wn
 538		if err != nil {
 539			return
 540		}
 541	default:
 542		wn, err = w.Write([]byte("{ "))
 543		i += wn
 544		if err != nil {
 545			return
 546		}
 547		wn, err = n.Body.JSWriteTo(w)
 548		i += wn
 549		if err != nil {
 550			return
 551		}
 552		wn, err = w.Write([]byte(" }"))
 553		i += wn
 554		if err != nil {
 555			return
 556		}
 557	}
 558	if n.Else != nil {
 559		switch n.Else.(type) {
 560		case *BlockStmt:
 561			wn, err = w.Write([]byte(" else "))
 562			i += wn
 563			if err != nil {
 564				return
 565			}
 566			wn, err = n.Else.JSWriteTo(w)
 567			i += wn
 568			if err != nil {
 569				return
 570			}
 571		default:
 572			wn, err = w.Write([]byte(" else { "))
 573			i += wn
 574			if err != nil {
 575				return
 576			}
 577			wn, err = n.Else.JSWriteTo(w)
 578			i += wn
 579			if err != nil {
 580				return
 581			}
 582			wn, err = w.Write([]byte(" }"))
 583			i += wn
 584			if err != nil {
 585				return
 586			}
 587		}
 588	}
 589	return
 590}
 591
 592// DoWhileStmt is a do-while iteration statement.
 593type DoWhileStmt struct {
 594	Cond IExpr
 595	Body IStmt
 596}
 597
 598func (n DoWhileStmt) String() string {
 599	return "Stmt(do " + n.Body.String() + " while " + n.Cond.String() + ")"
 600}
 601
 602// JS converts the node back to valid JavaScript
 603func (n DoWhileStmt) JS() string {
 604	s := "do "
 605	switch n.Body.(type) {
 606	case *BlockStmt:
 607		s += n.Body.JS()
 608	default:
 609		s += "{ " + n.Body.JS() + " }"
 610	}
 611	return s + " while (" + n.Cond.JS() + ")"
 612}
 613
 614// JS converts the node back to valid JavaScript (writes to io.Writer)
 615func (n DoWhileStmt) JSWriteTo(w io.Writer) (i int, err error) {
 616	var wn int
 617	wn, err = w.Write([]byte("do "))
 618	i += wn
 619	if err != nil {
 620		return
 621	}
 622	switch n.Body.(type) {
 623	case *BlockStmt:
 624		wn, err = n.Body.JSWriteTo(w)
 625		i += wn
 626		if err != nil {
 627			return
 628		}
 629	default:
 630		wn, err = w.Write([]byte("{ "))
 631		i += wn
 632		if err != nil {
 633			return
 634		}
 635		wn, err = n.Body.JSWriteTo(w)
 636		i += wn
 637		if err != nil {
 638			return
 639		}
 640		wn, err = w.Write([]byte(" }"))
 641		i += wn
 642		if err != nil {
 643			return
 644		}
 645	}
 646	wn, err = w.Write([]byte(" while ("))
 647	i += wn
 648	if err != nil {
 649		return
 650	}
 651	wn, err = n.Cond.JSWriteTo(w)
 652	i += wn
 653	if err != nil {
 654		return
 655	}
 656	wn, err = w.Write([]byte(")"))
 657	i += wn
 658	return
 659}
 660
 661// WhileStmt is a while iteration statement.
 662type WhileStmt struct {
 663	Cond IExpr
 664	Body IStmt
 665}
 666
 667func (n WhileStmt) String() string {
 668	return "Stmt(while " + n.Cond.String() + " " + n.Body.String() + ")"
 669}
 670
 671// JS converts the node back to valid JavaScript
 672func (n WhileStmt) JS() string {
 673	s := "while (" + n.Cond.JS() + ") "
 674	if n.Body != nil {
 675		s += n.Body.JS()
 676	}
 677	return s
 678}
 679
 680// JS converts the node back to valid JavaScript (writes to io.Writer)
 681func (n WhileStmt) JSWriteTo(w io.Writer) (i int, err error) {
 682	var wn int
 683	wn, err = w.Write([]byte("while ("))
 684	i += wn
 685	if err != nil {
 686		return
 687	}
 688	wn, err = n.Cond.JSWriteTo(w)
 689	i += wn
 690	if err != nil {
 691		return
 692	}
 693	wn, err = w.Write([]byte(") "))
 694	i += wn
 695	if err != nil {
 696		return
 697	}
 698	if n.Body != nil {
 699		wn, err = n.Body.JSWriteTo(w)
 700		i += wn
 701		if err != nil {
 702			return
 703		}
 704	}
 705	return
 706}
 707
 708// ForStmt is a regular for iteration statement.
 709type ForStmt struct {
 710	Init IExpr // can be nil
 711	Cond IExpr // can be nil
 712	Post IExpr // can be nil
 713	Body *BlockStmt
 714}
 715
 716func (n ForStmt) String() string {
 717	s := "Stmt(for"
 718	if v, ok := n.Init.(*VarDecl); !ok && n.Init != nil || ok && len(v.List) != 0 {
 719		s += " " + n.Init.String()
 720	}
 721	s += " ;"
 722	if n.Cond != nil {
 723		s += " " + n.Cond.String()
 724	}
 725	s += " ;"
 726	if n.Post != nil {
 727		s += " " + n.Post.String()
 728	}
 729	return s + " " + n.Body.String() + ")"
 730}
 731
 732// JS converts the node back to valid JavaScript
 733func (n ForStmt) JS() string {
 734	s := "for ("
 735	if v, ok := n.Init.(*VarDecl); !ok && n.Init != nil || ok && len(v.List) != 0 {
 736		s += n.Init.JS()
 737	} else {
 738		s += " "
 739	}
 740	s += "; "
 741	if n.Cond != nil {
 742		s += n.Cond.JS()
 743	}
 744	s += "; "
 745	if n.Post != nil {
 746		s += n.Post.JS()
 747	}
 748	return s + ") " + n.Body.JS()
 749}
 750
 751// JS converts the node back to valid JavaScript (writes to io.Writer)
 752func (n ForStmt) JSWriteTo(w io.Writer) (i int, err error) {
 753	var wn int
 754	wn, err = w.Write([]byte("for ("))
 755	i += wn
 756	if err != nil {
 757		return
 758	}
 759	if v, ok := n.Init.(*VarDecl); !ok && n.Init != nil || ok && len(v.List) != 0 {
 760		wn, err = n.Init.JSWriteTo(w)
 761		i += wn
 762		if err != nil {
 763			return
 764		}
 765	} else {
 766		wn, err = w.Write([]byte(" "))
 767		i += wn
 768		if err != nil {
 769			return
 770		}
 771	}
 772	wn, err = w.Write([]byte("; "))
 773	i += wn
 774	if err != nil {
 775		return
 776	}
 777	if n.Cond != nil {
 778		wn, err = n.Cond.JSWriteTo(w)
 779		i += wn
 780		if err != nil {
 781			return
 782		}
 783	}
 784	wn, err = w.Write([]byte("; "))
 785	i += wn
 786	if err != nil {
 787		return
 788	}
 789	if n.Post != nil {
 790		wn, err = n.Post.JSWriteTo(w)
 791		i += wn
 792		if err != nil {
 793			return
 794		}
 795	}
 796	wn, err = w.Write([]byte(") "))
 797	i += wn
 798	if err != nil {
 799		return
 800	}
 801	wn, err = n.Body.JSWriteTo(w)
 802	i += wn
 803	return
 804}
 805
 806// ForInStmt is a for-in iteration statement.
 807type ForInStmt struct {
 808	Init  IExpr
 809	Value IExpr
 810	Body  *BlockStmt
 811}
 812
 813func (n ForInStmt) String() string {
 814	return "Stmt(for " + n.Init.String() + " in " + n.Value.String() + " " + n.Body.String() + ")"
 815}
 816
 817// JS converts the node back to valid JavaScript
 818func (n ForInStmt) JS() string {
 819	return "for (" + n.Init.JS() + " in " + n.Value.JS() + ") " + n.Body.JS()
 820}
 821
 822// JS converts the node back to valid JavaScript (writes to io.Writer)
 823func (n ForInStmt) JSWriteTo(w io.Writer) (i int, err error) {
 824	var wn int
 825	wn, err = w.Write([]byte("for ("))
 826	i += wn
 827	if err != nil {
 828		return
 829	}
 830	wn, err = n.Init.JSWriteTo(w)
 831	i += wn
 832	if err != nil {
 833		return
 834	}
 835	wn, err = w.Write([]byte(" in "))
 836	i += wn
 837	if err != nil {
 838		return
 839	}
 840	wn, err = n.Value.JSWriteTo(w)
 841	i += wn
 842	if err != nil {
 843		return
 844	}
 845	wn, err = w.Write([]byte(") "))
 846	i += wn
 847	if err != nil {
 848		return
 849	}
 850	wn, err = n.Body.JSWriteTo(w)
 851	i += wn
 852	return
 853}
 854
 855// ForOfStmt is a for-of iteration statement.
 856type ForOfStmt struct {
 857	Await bool
 858	Init  IExpr
 859	Value IExpr
 860	Body  *BlockStmt
 861}
 862
 863func (n ForOfStmt) String() string {
 864	s := "Stmt(for"
 865	if n.Await {
 866		s += " await"
 867	}
 868	return s + " " + n.Init.String() + " of " + n.Value.String() + " " + n.Body.String() + ")"
 869}
 870
 871// JS converts the node back to valid JavaScript
 872func (n ForOfStmt) JS() string {
 873	s := "for"
 874	if n.Await {
 875		s += " await"
 876	}
 877	return s + " (" + n.Init.JS() + " of " + n.Value.JS() + ") " + n.Body.JS()
 878}
 879
 880// JS converts the node back to valid JavaScript (writes to io.Writer)
 881func (n ForOfStmt) JSWriteTo(w io.Writer) (i int, err error) {
 882	var wn int
 883	wn, err = w.Write([]byte("for"))
 884	i += wn
 885	if err != nil {
 886		return
 887	}
 888	if n.Await {
 889		wn, err = w.Write([]byte(" await"))
 890		i += wn
 891		if err != nil {
 892			return
 893		}
 894	}
 895	wn, err = w.Write([]byte(" ("))
 896	i += wn
 897	if err != nil {
 898		return
 899	}
 900	wn, err = n.Init.JSWriteTo(w)
 901	i += wn
 902	if err != nil {
 903		return
 904	}
 905	wn, err = w.Write([]byte(" of "))
 906	i += wn
 907	if err != nil {
 908		return
 909	}
 910	wn, err = n.Value.JSWriteTo(w)
 911	i += wn
 912	if err != nil {
 913		return
 914	}
 915	wn, err = w.Write([]byte(") "))
 916	i += wn
 917	if err != nil {
 918		return
 919	}
 920	wn, err = n.Body.JSWriteTo(w)
 921	i += wn
 922	return
 923}
 924
 925// CaseClause is a case clause or default clause for a switch statement.
 926type CaseClause struct {
 927	TokenType
 928	Cond IExpr // can be nil
 929	List []IStmt
 930}
 931
 932func (n CaseClause) String() string {
 933	s := " Clause(" + n.TokenType.String()
 934	if n.Cond != nil {
 935		s += " " + n.Cond.String()
 936	}
 937	for _, item := range n.List {
 938		s += " " + item.String()
 939	}
 940	return s + ")"
 941}
 942
 943// JS converts the node back to valid JavaScript
 944func (n CaseClause) JS() string {
 945	s := " "
 946	if n.Cond != nil {
 947		s += "case " + n.Cond.JS()
 948	} else {
 949		s += "default"
 950	}
 951	s += ":"
 952	for _, item := range n.List {
 953		s += " " + item.JS() + ";"
 954	}
 955	return s
 956}
 957
 958// JS converts the node back to valid JavaScript (writes to io.Writer)
 959func (n CaseClause) JSWriteTo(w io.Writer) (i int, err error) {
 960	var wn int
 961	wn, err = w.Write([]byte(" "))
 962	i += wn
 963	if err != nil {
 964		return
 965	}
 966	if n.Cond != nil {
 967		wn, err = w.Write([]byte("case "))
 968		i += wn
 969		if err != nil {
 970			return
 971		}
 972		wn, err = n.Cond.JSWriteTo(w)
 973		i += wn
 974		if err != nil {
 975			return
 976		}
 977	} else {
 978		wn, err = w.Write([]byte("default"))
 979		i += wn
 980		if err != nil {
 981			return
 982		}
 983	}
 984	wn, err = w.Write([]byte(":"))
 985	i += wn
 986	if err != nil {
 987		return
 988	}
 989	for _, item := range n.List {
 990		wn, err = w.Write([]byte(" "))
 991		i += wn
 992		if err != nil {
 993			return
 994		}
 995		wn, err = item.JSWriteTo(w)
 996		i += wn
 997		if err != nil {
 998			return
 999		}
1000		wn, err = w.Write([]byte(";"))
1001		i += wn
1002		if err != nil {
1003			return
1004		}
1005	}
1006	return
1007}
1008
1009// SwitchStmt is a switch statement.
1010type SwitchStmt struct {
1011	Init IExpr
1012	List []CaseClause
1013	Scope
1014}
1015
1016func (n SwitchStmt) String() string {
1017	s := "Stmt(switch " + n.Init.String()
1018	for _, clause := range n.List {
1019		s += clause.String()
1020	}
1021	return s + ")"
1022}
1023
1024// JS converts the node back to valid JavaScript
1025func (n SwitchStmt) JS() string {
1026	s := "switch (" + n.Init.JS() + ") {"
1027	for _, clause := range n.List {
1028		s += clause.JS()
1029	}
1030	return s + " }"
1031}
1032
1033// JS converts the node back to valid JavaScript (writes to io.Writer)
1034func (n SwitchStmt) JSWriteTo(w io.Writer) (i int, err error) {
1035	var wn int
1036	wn, err = w.Write([]byte("switch ("))
1037	i += wn
1038	if err != nil {
1039		return
1040	}
1041	wn, err = n.Init.JSWriteTo(w)
1042	i += wn
1043	if err != nil {
1044		return
1045	}
1046	wn, err = w.Write([]byte(") {"))
1047	i += wn
1048	if err != nil {
1049		return
1050	}
1051	for _, clause := range n.List {
1052		wn, err = clause.JSWriteTo(w)
1053		i += wn
1054		if err != nil {
1055			return
1056		}
1057	}
1058	wn, err = w.Write([]byte(" }"))
1059	i += wn
1060	return
1061}
1062
1063// BranchStmt is a continue or break statement.
1064type BranchStmt struct {
1065	Type  TokenType
1066	Label []byte // can be nil
1067}
1068
1069func (n BranchStmt) String() string {
1070	s := "Stmt(" + n.Type.String()
1071	if n.Label != nil {
1072		s += " " + string(n.Label)
1073	}
1074	return s + ")"
1075}
1076
1077// JS converts the node back to valid JavaScript
1078func (n BranchStmt) JS() string {
1079	s := n.Type.String()
1080	if n.Label != nil {
1081		s += " " + string(n.Label)
1082	}
1083	return s
1084}
1085
1086// JS converts the node back to valid JavaScript (writes to io.Writer)
1087func (n BranchStmt) JSWriteTo(w io.Writer) (i int, err error) {
1088	var wn int
1089	wn, err = w.Write(n.Type.Bytes())
1090	i += wn
1091	if err != nil {
1092		return
1093	}
1094	if n.Label != nil {
1095		wn, err = w.Write([]byte(" "))
1096		i += wn
1097		if err != nil {
1098			return
1099		}
1100		wn, err = w.Write(n.Label)
1101		i += wn
1102		if err != nil {
1103			return
1104		}
1105	}
1106	return
1107}
1108
1109// ReturnStmt is a return statement.
1110type ReturnStmt struct {
1111	Value IExpr // can be nil
1112}
1113
1114func (n ReturnStmt) String() string {
1115	s := "Stmt(return"
1116	if n.Value != nil {
1117		s += " " + n.Value.String()
1118	}
1119	return s + ")"
1120}
1121
1122// JS converts the node back to valid JavaScript
1123func (n ReturnStmt) JS() string {
1124	s := "return"
1125	if n.Value != nil {
1126		s += " " + n.Value.JS()
1127	}
1128	return s
1129}
1130
1131// JS converts the node back to valid JavaScript (writes to io.Writer)
1132func (n ReturnStmt) JSWriteTo(w io.Writer) (i int, err error) {
1133	var wn int
1134	wn, err = w.Write([]byte("return"))
1135	i += wn
1136	if err != nil {
1137		return
1138	}
1139	if n.Value != nil {
1140		wn, err = w.Write([]byte(" "))
1141		i += wn
1142		if err != nil {
1143			return
1144		}
1145		wn, err = n.Value.JSWriteTo(w)
1146		i += wn
1147		if err != nil {
1148			return
1149		}
1150	}
1151	return
1152}
1153
1154// WithStmt is a with statement.
1155type WithStmt struct {
1156	Cond IExpr
1157	Body IStmt
1158}
1159
1160func (n WithStmt) String() string {
1161	return "Stmt(with " + n.Cond.String() + " " + n.Body.String() + ")"
1162}
1163
1164// JS converts the node back to valid JavaScript
1165func (n WithStmt) JS() string {
1166	return "with (" + n.Cond.JS() + ") " + n.Body.JS()
1167}
1168
1169// JS converts the node back to valid JavaScript (writes to io.Writer)
1170func (n WithStmt) JSWriteTo(w io.Writer) (i int, err error) {
1171	var wn int
1172	wn, err = w.Write([]byte("with ("))
1173	i += wn
1174	if err != nil {
1175		return
1176	}
1177	wn, err = n.Cond.JSWriteTo(w)
1178	i += wn
1179	if err != nil {
1180		return
1181	}
1182	wn, err = w.Write([]byte(") "))
1183	i += wn
1184	if err != nil {
1185		return
1186	}
1187	wn, err = n.Body.JSWriteTo(w)
1188	i += wn
1189	return
1190}
1191
1192// LabelledStmt is a labelled statement.
1193type LabelledStmt struct {
1194	Label []byte
1195	Value IStmt
1196}
1197
1198func (n LabelledStmt) String() string {
1199	return "Stmt(" + string(n.Label) + " : " + n.Value.String() + ")"
1200}
1201
1202// JS converts the node back to valid JavaScript
1203func (n LabelledStmt) JS() string {
1204	return string(n.Label) + ": " + n.Value.JS()
1205}
1206
1207// JS converts the node back to valid JavaScript (writes to io.Writer)
1208func (n LabelledStmt) JSWriteTo(w io.Writer) (i int, err error) {
1209	var wn int
1210	wn, err = w.Write(n.Label)
1211	i += wn
1212	if err != nil {
1213		return
1214	}
1215	wn, err = w.Write([]byte(": "))
1216	i += wn
1217	if err != nil {
1218		return
1219	}
1220	wn, err = n.Value.JSWriteTo(w)
1221	i += wn
1222	return
1223}
1224
1225// ThrowStmt is a throw statement.
1226type ThrowStmt struct {
1227	Value IExpr
1228}
1229
1230func (n ThrowStmt) String() string {
1231	return "Stmt(throw " + n.Value.String() + ")"
1232}
1233
1234// JS converts the node back to valid JavaScript
1235func (n ThrowStmt) JS() string {
1236	return "throw " + n.Value.JS()
1237}
1238
1239// JS converts the node back to valid JavaScript (writes to io.Writer)
1240func (n ThrowStmt) JSWriteTo(w io.Writer) (i int, err error) {
1241	var wn int
1242	wn, err = w.Write([]byte("throw "))
1243	i += wn
1244	if err != nil {
1245		return
1246	}
1247	wn, err = n.Value.JSWriteTo(w)
1248	i += wn
1249	return
1250}
1251
1252// TryStmt is a try statement.
1253type TryStmt struct {
1254	Body    *BlockStmt
1255	Binding IBinding   // can be nil
1256	Catch   *BlockStmt // can be nil
1257	Finally *BlockStmt // can be nil
1258}
1259
1260func (n TryStmt) String() string {
1261	s := "Stmt(try " + n.Body.String()
1262	if n.Catch != nil {
1263		s += " catch"
1264		if n.Binding != nil {
1265			s += " Binding(" + n.Binding.String() + ")"
1266		}
1267		s += " " + n.Catch.String()
1268	}
1269	if n.Finally != nil {
1270		s += " finally " + n.Finally.String()
1271	}
1272	return s + ")"
1273}
1274
1275// JS converts the node back to valid JavaScript
1276func (n TryStmt) JS() string {
1277	s := "try " + n.Body.JS()
1278	if n.Catch != nil {
1279		s += " catch"
1280		if n.Binding != nil {
1281			s += "(" + n.Binding.JS() + ")"
1282		}
1283		s += " " + n.Catch.JS()
1284	}
1285	if n.Finally != nil {
1286		s += " finally " + n.Finally.JS()
1287	}
1288	return s
1289}
1290
1291// JS converts the node back to valid JavaScript (writes to io.Writer)
1292func (n TryStmt) JSWriteTo(w io.Writer) (i int, err error) {
1293	var wn int
1294	wn, err = w.Write([]byte("try "))
1295	i += wn
1296	if err != nil {
1297		return
1298	}
1299	wn, err = n.Body.JSWriteTo(w)
1300	i += wn
1301	if err != nil {
1302		return
1303	}
1304	if n.Catch != nil {
1305		wn, err = w.Write([]byte(" catch"))
1306		i += wn
1307		if err != nil {
1308			return
1309		}
1310		if n.Binding != nil {
1311			wn, err = w.Write([]byte("("))
1312			i += wn
1313			if err != nil {
1314				return
1315			}
1316			wn, err = n.Binding.JSWriteTo(w)
1317			i += wn
1318			if err != nil {
1319				return
1320			}
1321			wn, err = w.Write([]byte(")"))
1322			i += wn
1323			if err != nil {
1324				return
1325			}
1326		}
1327		wn, err = w.Write([]byte(" "))
1328		i += wn
1329		if err != nil {
1330			return
1331		}
1332		wn, err = n.Catch.JSWriteTo(w)
1333		i += wn
1334		if err != nil {
1335			return
1336		}
1337	}
1338	if n.Finally != nil {
1339		wn, err = w.Write([]byte(" finally "))
1340		i += wn
1341		if err != nil {
1342			return
1343		}
1344		wn, err = n.Finally.JSWriteTo(w)
1345		i += wn
1346	}
1347	return
1348}
1349
1350// DebuggerStmt is a debugger statement.
1351type DebuggerStmt struct {
1352}
1353
1354func (n DebuggerStmt) String() string {
1355	return "Stmt(debugger)"
1356}
1357
1358// JS converts the node back to valid JavaScript
1359func (n DebuggerStmt) JS() string {
1360	return "debugger"
1361}
1362
1363// JS converts the node back to valid JavaScript (writes to io.Writer)
1364func (n DebuggerStmt) JSWriteTo(w io.Writer) (i int, err error) {
1365	var wn int
1366	wn, err = w.Write([]byte("debugger"))
1367	i += wn
1368	return
1369}
1370
1371// Alias is a name space import or import/export specifier for import/export statements.
1372type Alias struct {
1373	Name    []byte // can be nil
1374	Binding []byte // can be nil
1375}
1376
1377func (alias Alias) String() string {
1378	s := ""
1379	if alias.Name != nil {
1380		s += string(alias.Name) + " as "
1381	}
1382	return s + string(alias.Binding)
1383}
1384
1385// JS converts the node back to valid JavaScript
1386func (alias Alias) JS() string {
1387	return alias.String()
1388}
1389
1390// JS converts the node back to valid JavaScript (writes to io.Writer)
1391func (alias Alias) JSWriteTo(w io.Writer) (i int, err error) {
1392	var wn int
1393	if alias.Name != nil {
1394		wn, err = w.Write(alias.Name)
1395		i += wn
1396		if err != nil {
1397			return
1398		}
1399		wn, err = w.Write([]byte(" as "))
1400		i += wn
1401		if err != nil {
1402			return
1403		}
1404	}
1405	wn, err = w.Write(alias.Binding)
1406	i += wn
1407	return
1408}
1409
1410// ImportStmt is an import statement.
1411type ImportStmt struct {
1412	List    []Alias
1413	Default []byte // can be nil
1414	Module  []byte
1415}
1416
1417func (n ImportStmt) String() string {
1418	s := "Stmt(import"
1419	if n.Default != nil {
1420		s += " " + string(n.Default)
1421		if len(n.List) != 0 {
1422			s += " ,"
1423		}
1424	}
1425	if len(n.List) == 1 && len(n.List[0].Name) == 1 && n.List[0].Name[0] == '*' {
1426		s += " " + n.List[0].String()
1427	} else if 0 < len(n.List) {
1428		s += " {"
1429		for i, item := range n.List {
1430			if i != 0 {
1431				s += " ,"
1432			}
1433			if item.Binding != nil {
1434				s += " " + item.String()
1435			}
1436		}
1437		s += " }"
1438	}
1439	if n.Default != nil || len(n.List) != 0 {
1440		s += " from"
1441	}
1442	return s + " " + string(n.Module) + ")"
1443}
1444
1445// JS converts the node back to valid JavaScript
1446func (n ImportStmt) JS() string {
1447	s := "import"
1448	if n.Default != nil {
1449		s += " " + string(n.Default)
1450		if len(n.List) != 0 {
1451			s += " ,"
1452		}
1453	}
1454	if len(n.List) == 1 && len(n.List[0].Name) == 1 && n.List[0].Name[0] == '*' {
1455		s += " " + n.List[0].JS()
1456	} else if 0 < len(n.List) {
1457		s += " {"
1458		for i, item := range n.List {
1459			if i != 0 {
1460				s += " ,"
1461			}
1462			if item.Binding != nil {
1463				s += " " + item.JS()
1464			}
1465		}
1466		s += " }"
1467	}
1468	if n.Default != nil || len(n.List) != 0 {
1469		s += " from"
1470	}
1471	return s + " " + string(n.Module)
1472}
1473
1474// JS converts the node back to valid JavaScript (writes to io.Writer)
1475func (n ImportStmt) JSWriteTo(w io.Writer) (i int, err error) {
1476	var wn int
1477	wn, err = w.Write([]byte("import"))
1478	i += wn
1479	if err != nil {
1480		return
1481	}
1482	if n.Default != nil {
1483		wn, err = w.Write([]byte(" "))
1484		i += wn
1485		if err != nil {
1486			return
1487		}
1488		wn, err = w.Write(n.Default)
1489		i += wn
1490		if err != nil {
1491			return
1492		}
1493		if len(n.List) != 0 {
1494			wn, err = w.Write([]byte(" ,"))
1495			i += wn
1496			if err != nil {
1497				return
1498			}
1499		}
1500	}
1501	if len(n.List) == 1 && len(n.List[0].Name) == 1 && n.List[0].Name[0] == '*' {
1502		wn, err = w.Write([]byte(" "))
1503		i += wn
1504		if err != nil {
1505			return
1506		}
1507		wn, err = n.List[0].JSWriteTo(w)
1508		i += wn
1509		if err != nil {
1510			return
1511		}
1512	} else if 0 < len(n.List) {
1513		wn, err = w.Write([]byte(" {"))
1514		i += wn
1515		if err != nil {
1516			return
1517		}
1518		for j, item := range n.List {
1519			if j != 0 {
1520				wn, err = w.Write([]byte(" ,"))
1521				i += wn
1522				if err != nil {
1523					return
1524				}
1525			}
1526			if item.Binding != nil {
1527				wn, err = w.Write([]byte(" "))
1528				i += wn
1529				if err != nil {
1530					return
1531				}
1532				wn, err = item.JSWriteTo(w)
1533				i += wn
1534				if err != nil {
1535					return
1536				}
1537			}
1538		}
1539		wn, err = w.Write([]byte(" }"))
1540		i += wn
1541		if err != nil {
1542			return
1543		}
1544	}
1545	if n.Default != nil || len(n.List) != 0 {
1546		wn, err = w.Write([]byte(" from"))
1547		i += wn
1548		if err != nil {
1549			return
1550		}
1551	}
1552	wn, err = w.Write([]byte(" "))
1553	i += wn
1554	if err != nil {
1555		return
1556	}
1557	wn, err = w.Write(n.Module)
1558	i += wn
1559	return
1560}
1561
1562// ExportStmt is an export statement.
1563type ExportStmt struct {
1564	List    []Alias
1565	Module  []byte // can be nil
1566	Default bool
1567	Decl    IExpr
1568}
1569
1570func (n ExportStmt) String() string {
1571	s := "Stmt(export"
1572	if n.Decl != nil {
1573		if n.Default {
1574			s += " default"
1575		}
1576		return s + " " + n.Decl.String() + ")"
1577	} 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] == '*') {
1578		s += " " + n.List[0].String()
1579	} else if 0 < len(n.List) {
1580		s += " {"
1581		for i, item := range n.List {
1582			if i != 0 {
1583				s += " ,"
1584			}
1585			if item.Binding != nil {
1586				s += " " + item.String()
1587			}
1588		}
1589		s += " }"
1590	}
1591	if n.Module != nil {
1592		s += " from " + string(n.Module)
1593	}
1594	return s + ")"
1595}
1596
1597// JS converts the node back to valid JavaScript
1598func (n ExportStmt) JS() string {
1599	s := "export"
1600	if n.Decl != nil {
1601		if n.Default {
1602			s += " default"
1603		}
1604		return s + " " + n.Decl.JS()
1605	} 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] == '*') {
1606		s += " " + n.List[0].JS()
1607	} else if 0 < len(n.List) {
1608		s += " {"
1609		for i, item := range n.List {
1610			if i != 0 {
1611				s += " ,"
1612			}
1613			if item.Binding != nil {
1614				s += " " + item.JS()
1615			}
1616		}
1617		s += " }"
1618	}
1619	if n.Module != nil {
1620		s += " from " + string(n.Module)
1621	}
1622	return s
1623}
1624
1625// JS converts the node back to valid JavaScript (writes to io.Writer)
1626func (n ExportStmt) JSWriteTo(w io.Writer) (i int, err error) {
1627	var wn int
1628	wn, err = w.Write([]byte("export"))
1629	i += wn
1630	if err != nil {
1631		return
1632	}
1633	if n.Decl != nil {
1634		if n.Default {
1635			wn, err = w.Write([]byte(" default"))
1636			i += wn
1637			if err != nil {
1638				return
1639			}
1640		}
1641		wn, err = w.Write([]byte(" "))
1642		i += wn
1643		if err != nil {
1644			return
1645		}
1646		wn, err = n.Decl.JSWriteTo(w)
1647		i += wn
1648		return
1649	} 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] == '*') {
1650		wn, err = w.Write([]byte(" "))
1651		i += wn
1652		if err != nil {
1653			return
1654		}
1655		wn, err = n.List[0].JSWriteTo(w)
1656		i += wn
1657		if err != nil {
1658			return
1659		}
1660	} else if 0 < len(n.List) {
1661		wn, err = w.Write([]byte(" {"))
1662		i += wn
1663		if err != nil {
1664			return
1665		}
1666		for j, item := range n.List {
1667			if j != 0 {
1668				wn, err = w.Write([]byte(" ,"))
1669				i += wn
1670				if err != nil {
1671					return
1672				}
1673			}
1674			if item.Binding != nil {
1675				wn, err = w.Write([]byte(" "))
1676				i += wn
1677				if err != nil {
1678					return
1679				}
1680				wn, err = item.JSWriteTo(w)
1681				i += wn
1682				if err != nil {
1683					return
1684				}
1685			}
1686		}
1687		wn, err = w.Write([]byte(" }"))
1688		i += wn
1689		if err != nil {
1690			return
1691		}
1692	}
1693	if n.Module != nil {
1694		wn, err = w.Write([]byte(" from "))
1695		i += wn
1696		if err != nil {
1697			return
1698		}
1699		wn, err = w.Write(n.Module)
1700		i += wn
1701		if err != nil {
1702			return
1703		}
1704	}
1705	return
1706}
1707
1708// DirectivePrologueStmt is a string literal at the beginning of a function or module (usually "use strict").
1709type DirectivePrologueStmt struct {
1710	Value []byte
1711}
1712
1713func (n DirectivePrologueStmt) String() string {
1714	return "Stmt(" + string(n.Value) + ")"
1715}
1716
1717// JS converts the node back to valid JavaScript
1718func (n DirectivePrologueStmt) JS() string {
1719	return string(n.Value)
1720}
1721
1722// JS converts the node back to valid JavaScript (writes to io.Writer)
1723func (n DirectivePrologueStmt) JSWriteTo(w io.Writer) (i int, err error) {
1724	var wn int
1725	wn, err = w.Write(n.Value)
1726	i += wn
1727	return
1728}
1729
1730func (n BlockStmt) stmtNode()             {}
1731func (n EmptyStmt) stmtNode()             {}
1732func (n ExprStmt) stmtNode()              {}
1733func (n IfStmt) stmtNode()                {}
1734func (n DoWhileStmt) stmtNode()           {}
1735func (n WhileStmt) stmtNode()             {}
1736func (n ForStmt) stmtNode()               {}
1737func (n ForInStmt) stmtNode()             {}
1738func (n ForOfStmt) stmtNode()             {}
1739func (n SwitchStmt) stmtNode()            {}
1740func (n BranchStmt) stmtNode()            {}
1741func (n ReturnStmt) stmtNode()            {}
1742func (n WithStmt) stmtNode()              {}
1743func (n LabelledStmt) stmtNode()          {}
1744func (n ThrowStmt) stmtNode()             {}
1745func (n TryStmt) stmtNode()               {}
1746func (n DebuggerStmt) stmtNode()          {}
1747func (n ImportStmt) stmtNode()            {}
1748func (n ExportStmt) stmtNode()            {}
1749func (n DirectivePrologueStmt) stmtNode() {}
1750
1751////////////////////////////////////////////////////////////////
1752
1753// PropertyName is a property name for binding properties, method names, and in object literals.
1754type PropertyName struct {
1755	Literal  LiteralExpr
1756	Computed IExpr // can be nil
1757}
1758
1759// IsSet returns true is PropertyName is not nil.
1760func (n PropertyName) IsSet() bool {
1761	return n.IsComputed() || n.Literal.TokenType != ErrorToken
1762}
1763
1764// IsComputed returns true if PropertyName is computed.
1765func (n PropertyName) IsComputed() bool {
1766	return n.Computed != nil
1767}
1768
1769// IsIdent returns true if PropertyName equals the given identifier name.
1770func (n PropertyName) IsIdent(data []byte) bool {
1771	return !n.IsComputed() && n.Literal.TokenType == IdentifierToken && bytes.Equal(data, n.Literal.Data)
1772}
1773
1774func (n PropertyName) String() string {
1775	if n.Computed != nil {
1776		val := n.Computed.String()
1777		if val[0] == '(' {
1778			return "[" + val[1:len(val)-1] + "]"
1779		}
1780		return "[" + val + "]"
1781	}
1782	return string(n.Literal.Data)
1783}
1784
1785// JS converts the node back to valid JavaScript
1786func (n PropertyName) JS() string {
1787	if n.Computed != nil {
1788		return "[" + n.Computed.JS() + "]"
1789	}
1790	return string(n.Literal.Data)
1791}
1792
1793// JS converts the node back to valid JavaScript (writes to io.Writer)
1794func (n PropertyName) JSWriteTo(w io.Writer) (i int, err error) {
1795	var wn int
1796	if n.Computed != nil {
1797		wn, err = w.Write([]byte("["))
1798		i += wn
1799		if err != nil {
1800			return
1801		}
1802		wn, err = n.Computed.JSWriteTo(w)
1803		i += wn
1804		if err != nil {
1805			return
1806		}
1807		wn, err = w.Write([]byte("]"))
1808		i += wn
1809		return
1810	}
1811	wn, err = w.Write(n.Literal.Data)
1812	i += wn
1813	return
1814}
1815
1816// BindingArray is an array binding pattern.
1817type BindingArray struct {
1818	List []BindingElement
1819	Rest IBinding // can be nil
1820}
1821
1822func (n BindingArray) String() string {
1823	s := "["
1824	for i, item := range n.List {
1825		if i != 0 {
1826			s += ","
1827		}
1828		s += " " + item.String()
1829	}
1830	if n.Rest != nil {
1831		if len(n.List) != 0 {
1832			s += ","
1833		}
1834		s += " ...Binding(" + n.Rest.String() + ")"
1835	}
1836	return s + " ]"
1837}
1838
1839// JS converts the node back to valid JavaScript
1840func (n BindingArray) JS() string {
1841	s := "["
1842	for i, item := range n.List {
1843		if i != 0 {
1844			s += ", "
1845		}
1846		s += item.JS()
1847	}
1848	if n.Rest != nil {
1849		if len(n.List) != 0 {
1850			s += ", "
1851		}
1852		s += "..." + n.Rest.JS()
1853	}
1854	return s + "]"
1855}
1856
1857// JS converts the node back to valid JavaScript (writes to io.Writer)
1858func (n BindingArray) JSWriteTo(w io.Writer) (i int, err error) {
1859	var wn int
1860	wn, err = w.Write([]byte("["))
1861	i += wn
1862	if err != nil {
1863		return
1864	}
1865	for j, item := range n.List {
1866		if j != 0 {
1867			wn, err = w.Write([]byte(", "))
1868			i += wn
1869			if err != nil {
1870				return
1871			}
1872		}
1873		wn, err = item.JSWriteTo(w)
1874		i += wn
1875		if err != nil {
1876			return
1877		}
1878	}
1879	if n.Rest != nil {
1880		if len(n.List) != 0 {
1881			wn, err = w.Write([]byte(", "))
1882			i += wn
1883			if err != nil {
1884				return
1885			}
1886		}
1887		wn, err = w.Write([]byte("..."))
1888		i += wn
1889		if err != nil {
1890			return
1891		}
1892		wn, err = n.Rest.JSWriteTo(w)
1893		i += wn
1894		if err != nil {
1895			return
1896		}
1897	}
1898	wn, err = w.Write([]byte("]"))
1899	i += wn
1900	return
1901}
1902
1903// BindingObjectItem is a binding property.
1904type BindingObjectItem struct {
1905	Key   *PropertyName // can be nil
1906	Value BindingElement
1907}
1908
1909func (n BindingObjectItem) String() string {
1910	s := ""
1911	if n.Key != nil {
1912		if v, ok := n.Value.Binding.(*Var); !ok || !n.Key.IsIdent(v.Data) {
1913			s += " " + n.Key.String() + ":"
1914		}
1915	}
1916	return s + " " + n.Value.String()
1917}
1918
1919// JS converts the node back to valid JavaScript
1920func (n BindingObjectItem) JS() string {
1921	s := ""
1922	if n.Key != nil {
1923		if v, ok := n.Value.Binding.(*Var); !ok || !n.Key.IsIdent(v.Data) {
1924			s += n.Key.JS() + ": "
1925		}
1926	}
1927	return s + n.Value.JS()
1928}
1929
1930// JS converts the node back to valid JavaScript (writes to io.Writer)
1931func (n BindingObjectItem) JSWriteTo(w io.Writer) (i int, err error) {
1932	var wn int
1933	if n.Key != nil {
1934		if v, ok := n.Value.Binding.(*Var); !ok || !n.Key.IsIdent(v.Data) {
1935			wn, err = n.Key.JSWriteTo(w)
1936			i += wn
1937			if err != nil {
1938				return
1939			}
1940			wn, err = w.Write([]byte(": "))
1941			i += wn
1942			if err != nil {
1943				return
1944			}
1945		}
1946	}
1947	wn, err = n.Value.JSWriteTo(w)
1948	i += wn
1949	return
1950}
1951
1952// BindingObject is an object binding pattern.
1953type BindingObject struct {
1954	List []BindingObjectItem
1955	Rest *Var // can be nil
1956}
1957
1958func (n BindingObject) String() string {
1959	s := "{"
1960	for i, item := range n.List {
1961		if i != 0 {
1962			s += ","
1963		}
1964		s += item.String()
1965	}
1966	if n.Rest != nil {
1967		if len(n.List) != 0 {
1968			s += ","
1969		}
1970		s += " ...Binding(" + string(n.Rest.Data) + ")"
1971	}
1972	return s + " }"
1973}
1974
1975// JS converts the node back to valid JavaScript
1976func (n BindingObject) JS() string {
1977	s := "{"
1978	for i, item := range n.List {
1979		if i != 0 {
1980			s += ", "
1981		}
1982		s += item.JS()
1983	}
1984	if n.Rest != nil {
1985		if len(n.List) != 0 {
1986			s += ", "
1987		}
1988		s += "..." + string(n.Rest.Data)
1989	}
1990	return s + "}"
1991}
1992
1993// JS converts the node back to valid JavaScript (writes to io.Writer)
1994func (n BindingObject) JSWriteTo(w io.Writer) (i int, err error) {
1995	var wn int
1996	wn, err = w.Write([]byte("{"))
1997	i += wn
1998	if err != nil {
1999		return
2000	}
2001	for j, item := range n.List {
2002		if j != 0 {
2003			wn, err = w.Write([]byte(", "))
2004			i += wn
2005			if err != nil {
2006				return
2007			}
2008		}
2009		wn, err = item.JSWriteTo(w)
2010		i += wn
2011		if err != nil {
2012			return
2013		}
2014	}
2015	if n.Rest != nil {
2016		if len(n.List) != 0 {
2017			wn, err = w.Write([]byte(", "))
2018			i += wn
2019			if err != nil {
2020				return
2021			}
2022		}
2023		wn, err = w.Write([]byte("..."))
2024		i += wn
2025		if err != nil {
2026			return
2027		}
2028		wn, err = w.Write(n.Rest.Data)
2029		i += wn
2030		if err != nil {
2031			return
2032		}
2033	}
2034	wn, err = w.Write([]byte("}"))
2035	i += wn
2036	return
2037}
2038
2039// BindingElement is a binding element.
2040type BindingElement struct {
2041	Binding IBinding // can be nil (in case of ellision)
2042	Default IExpr    // can be nil
2043}
2044
2045func (n BindingElement) String() string {
2046	if n.Binding == nil {
2047		return "Binding()"
2048	}
2049	s := "Binding(" + n.Binding.String()
2050	if n.Default != nil {
2051		s += " = " + n.Default.String()
2052	}
2053	return s + ")"
2054}
2055
2056// JS converts the node back to valid JavaScript
2057func (n BindingElement) JS() string {
2058	if n.Binding == nil {
2059		return ""
2060	}
2061	s := n.Binding.JS()
2062	if n.Default != nil {
2063		s += " = " + n.Default.JS()
2064	}
2065	return s
2066}
2067
2068// JS converts the node back to valid JavaScript (writes to io.Writer)
2069func (n BindingElement) JSWriteTo(w io.Writer) (i int, err error) {
2070	if n.Binding == nil {
2071		return
2072	}
2073	var wn int
2074	wn, err = n.Binding.JSWriteTo(w)
2075	i += wn
2076	if err != nil {
2077		return
2078	}
2079	if n.Default != nil {
2080		wn, err = w.Write([]byte(" = "))
2081		i += wn
2082		if err != nil {
2083			return
2084		}
2085		wn, err = n.Default.JSWriteTo(w)
2086		i += wn
2087		if err != nil {
2088			return
2089		}
2090	}
2091	return
2092}
2093
2094func (v *Var) bindingNode()          {}
2095func (n BindingArray) bindingNode()  {}
2096func (n BindingObject) bindingNode() {}
2097
2098////////////////////////////////////////////////////////////////
2099
2100// VarDecl is a variable statement or lexical declaration.
2101type VarDecl struct {
2102	TokenType
2103	List             []BindingElement
2104	Scope            *Scope
2105	InFor, InForInOf bool
2106}
2107
2108func (n VarDecl) String() string {
2109	s := "Decl(" + n.TokenType.String()
2110	for _, item := range n.List {
2111		s += " " + item.String()
2112	}
2113	return s + ")"
2114}
2115
2116// JS converts the node back to valid JavaScript
2117func (n VarDecl) JS() string {
2118	s := n.TokenType.String()
2119	for i, item := range n.List {
2120		if i != 0 {
2121			s += ","
2122		}
2123		s += " " + item.JS()
2124	}
2125	return s
2126}
2127
2128// JS converts the node back to valid JavaScript (writes to io.Writer)
2129func (n VarDecl) JSWriteTo(w io.Writer) (i int, err error) {
2130	var wn int
2131	wn, err = w.Write(n.TokenType.Bytes())
2132	i += wn
2133	if err != nil {
2134		return
2135	}
2136	for j, item := range n.List {
2137		if j != 0 {
2138			wn, err = w.Write([]byte(","))
2139			i += wn
2140			if err != nil {
2141				return
2142			}
2143		}
2144		wn, err = w.Write([]byte(" "))
2145		i += wn
2146		if err != nil {
2147			return
2148		}
2149		wn, err = item.JSWriteTo(w)
2150		i += wn
2151		if err != nil {
2152			return
2153		}
2154	}
2155	return
2156}
2157
2158// Params is a list of parameters for functions, methods, and arrow function.
2159type Params struct {
2160	List []BindingElement
2161	Rest IBinding // can be nil
2162}
2163
2164func (n Params) String() string {
2165	s := "Params("
2166	for i, item := range n.List {
2167		if i != 0 {
2168			s += ", "
2169		}
2170		s += item.String()
2171	}
2172	if n.Rest != nil {
2173		if len(n.List) != 0 {
2174			s += ", "
2175		}
2176		s += "...Binding(" + n.Rest.String() + ")"
2177	}
2178	return s + ")"
2179}
2180
2181// JS converts the node back to valid JavaScript
2182func (n Params) JS() string {
2183	s := "("
2184	for i, item := range n.List {
2185		if i != 0 {
2186			s += ", "
2187		}
2188		s += item.JS()
2189	}
2190	if n.Rest != nil {
2191		if len(n.List) != 0 {
2192			s += ", "
2193		}
2194		s += "..." + n.Rest.JS()
2195	}
2196	return s + ")"
2197}
2198
2199// JS converts the node back to valid JavaScript (writes to io.Writer)
2200func (n Params) JSWriteTo(w io.Writer) (i int, err error) {
2201	var wn int
2202	wn, err = w.Write([]byte("("))
2203	i += wn
2204	if err != nil {
2205		return
2206	}
2207	for j, item := range n.List {
2208		if j != 0 {
2209			wn, err = w.Write([]byte(", "))
2210			i += wn
2211			if err != nil {
2212				return
2213			}
2214		}
2215		wn, err = item.JSWriteTo(w)
2216		i += wn
2217		if err != nil {
2218			return
2219		}
2220	}
2221	if n.Rest != nil {
2222		if len(n.List) != 0 {
2223			wn, err = w.Write([]byte(", "))
2224			i += wn
2225			if err != nil {
2226				return
2227			}
2228		}
2229		wn, err = w.Write([]byte("..."))
2230		i += wn
2231		if err != nil {
2232			return
2233		}
2234		wn, err = n.Rest.JSWriteTo(w)
2235		i += wn
2236		if err != nil {
2237			return
2238		}
2239	}
2240	wn, err = w.Write([]byte(")"))
2241	i += wn
2242	return
2243}
2244
2245// FuncDecl is an (async) (generator) function declaration or expression.
2246type FuncDecl struct {
2247	Async     bool
2248	Generator bool
2249	Name      *Var // can be nil
2250	Params    Params
2251	Body      BlockStmt
2252}
2253
2254func (n FuncDecl) String() string {
2255	s := "Decl("
2256	if n.Async {
2257		s += "async function"
2258	} else {
2259		s += "function"
2260	}
2261	if n.Generator {
2262		s += "*"
2263	}
2264	if n.Name != nil {
2265		s += " " + string(n.Name.Data)
2266	}
2267	return s + " " + n.Params.String() + " " + n.Body.String() + ")"
2268}
2269
2270// JS converts the node back to valid JavaScript
2271func (n FuncDecl) JS() string {
2272	s := ""
2273	if n.Async {
2274		s += "async function"
2275	} else {
2276		s += "function"
2277	}
2278	if n.Generator {
2279		s += "*"
2280	}
2281	if n.Name != nil {
2282		s += " " + string(n.Name.Data)
2283	}
2284	return s + " " + n.Params.JS() + " " + n.Body.JS()
2285}
2286
2287// JS converts the node back to valid JavaScript (writes to io.Writer)
2288func (n FuncDecl) JSWriteTo(w io.Writer) (i int, err error) {
2289	var wn int
2290	if n.Async {
2291		wn, err = w.Write([]byte("async function"))
2292	} else {
2293		wn, err = w.Write([]byte("function"))
2294	}
2295	i += wn
2296	if err != nil {
2297		return
2298	}
2299
2300	if n.Generator {
2301		wn, err = w.Write([]byte("*"))
2302		i += wn
2303		if err != nil {
2304			return
2305		}
2306	}
2307	if n.Name != nil {
2308		wn, err = w.Write([]byte(" "))
2309		i += wn
2310		if err != nil {
2311			return
2312		}
2313		wn, err = w.Write(n.Name.Data)
2314		i += wn
2315		if err != nil {
2316			return
2317		}
2318	}
2319	wn, err = w.Write([]byte(" "))
2320	i += wn
2321	if err != nil {
2322		return
2323	}
2324	wn, err = n.Params.JSWriteTo(w)
2325	i += wn
2326	if err != nil {
2327		return
2328	}
2329	wn, err = w.Write([]byte(" "))
2330	i += wn
2331	if err != nil {
2332		return
2333	}
2334	wn, err = n.Body.JSWriteTo(w)
2335	i += wn
2336	return
2337}
2338
2339// MethodDecl is a method definition in a class declaration.
2340type MethodDecl struct {
2341	Static    bool
2342	Async     bool
2343	Generator bool
2344	Get       bool
2345	Set       bool
2346	Name      PropertyName
2347	Params    Params
2348	Body      BlockStmt
2349}
2350
2351func (n MethodDecl) String() string {
2352	s := ""
2353	if n.Static {
2354		s += " static"
2355	}
2356	if n.Async {
2357		s += " async"
2358	}
2359	if n.Generator {
2360		s += " *"
2361	}
2362	if n.Get {
2363		s += " get"
2364	}
2365	if n.Set {
2366		s += " set"
2367	}
2368	s += " " + n.Name.String() + " " + n.Params.String() + " " + n.Body.String()
2369	return "Method(" + s[1:] + ")"
2370}
2371
2372// JS converts the node back to valid JavaScript
2373func (n MethodDecl) JS() string {
2374	s := ""
2375	if n.Static {
2376		s += " static"
2377	}
2378	if n.Async {
2379		s += " async"
2380	}
2381	if n.Generator {
2382		s += " *"
2383	}
2384	if n.Get {
2385		s += " get"
2386	}
2387	if n.Set {
2388		s += " set"
2389	}
2390	s += " " + n.Name.JS() + " " + n.Params.JS() + " " + n.Body.JS()
2391	return s[1:]
2392}
2393
2394// JS converts the node back to valid JavaScript (writes to io.Writer)
2395func (n MethodDecl) JSWriteTo(w io.Writer) (i int, err error) {
2396	var wn int
2397	if n.Static {
2398		wn, err = w.Write([]byte("static"))
2399		i += wn
2400		if err != nil {
2401			return
2402		}
2403	}
2404	if n.Async {
2405		if wn > 0 {
2406			wn, err = w.Write([]byte(" "))
2407			i += wn
2408			if err != nil {
2409				return
2410			}
2411		}
2412		wn, err = w.Write([]byte("async"))
2413		i += wn
2414		if err != nil {
2415			return
2416		}
2417	}
2418	if n.Generator {
2419		if wn > 0 {
2420			wn, err = w.Write([]byte(" "))
2421			i += wn
2422			if err != nil {
2423				return
2424			}
2425		}
2426		wn, err = w.Write([]byte("*"))
2427		i += wn
2428		if err != nil {
2429			return
2430		}
2431	}
2432	if n.Get {
2433		if wn > 0 {
2434			wn, err = w.Write([]byte(" "))
2435			i += wn
2436			if err != nil {
2437				return
2438			}
2439		}
2440		wn, err = w.Write([]byte("get"))
2441		i += wn
2442		if err != nil {
2443			return
2444		}
2445	}
2446	if n.Set {
2447		if wn > 0 {
2448			wn, err = w.Write([]byte(" "))
2449			i += wn
2450			if err != nil {
2451				return
2452			}
2453		}
2454		wn, err = w.Write([]byte("set"))
2455		i += wn
2456		if err != nil {
2457			return
2458		}
2459	}
2460	if wn > 0 {
2461		wn, err = w.Write([]byte(" "))
2462		i += wn
2463		if err != nil {
2464			return
2465		}
2466	}
2467	wn, err = n.Name.JSWriteTo(w)
2468	i += wn
2469	if err != nil {
2470		return
2471	}
2472	wn, err = w.Write([]byte(" "))
2473	i += wn
2474	if err != nil {
2475		return
2476	}
2477	wn, err = n.Params.JSWriteTo(w)
2478	i += wn
2479	if err != nil {
2480		return
2481	}
2482	wn, err = w.Write([]byte(" "))
2483	i += wn
2484	if err != nil {
2485		return
2486	}
2487	wn, err = n.Body.JSWriteTo(w)
2488	i += wn
2489	return
2490}
2491
2492// Field is a field definition in a class declaration.
2493type Field struct {
2494	Static bool
2495	Name   PropertyName
2496	Init   IExpr
2497}
2498
2499func (n Field) String() string {
2500	s := "Field("
2501	if n.Static {
2502		s += "static "
2503	}
2504	s += n.Name.String()
2505	if n.Init != nil {
2506		s += " = " + n.Init.String()
2507	}
2508	return s + ")"
2509}
2510
2511// JS converts the node back to valid JavaScript
2512func (n Field) JS() string {
2513	s := ""
2514	if n.Static {
2515		s += "static "
2516	}
2517	s += n.Name.String()
2518	if n.Init != nil {
2519		s += " = " + n.Init.JS()
2520	}
2521	return s
2522}
2523
2524// JS converts the node back to valid JavaScript (writes to io.Writer)
2525func (n Field) JSWriteTo(w io.Writer) (i int, err error) {
2526	var wn int
2527	if n.Static {
2528		wn, err = w.Write([]byte("static "))
2529		i += wn
2530		if err != nil {
2531			return
2532		}
2533	}
2534	wn, err = n.Name.JSWriteTo(w)
2535	i += wn
2536	if err != nil {
2537		return
2538	}
2539	if n.Init != nil {
2540		wn, err = w.Write([]byte(" = "))
2541		i += wn
2542		if err != nil {
2543			return
2544		}
2545		wn, err = n.Init.JSWriteTo(w)
2546		i += wn
2547		if err != nil {
2548			return
2549		}
2550	}
2551	return
2552}
2553
2554// ClassElement is a class element that is either a static block, a field definition, or a class method
2555type ClassElement struct {
2556	StaticBlock *BlockStmt  // can be nil
2557	Method      *MethodDecl // can be nil
2558	Field
2559}
2560
2561func (n ClassElement) String() string {
2562	if n.StaticBlock != nil {
2563		return "Static(" + n.StaticBlock.String() + ")"
2564	} else if n.Method != nil {
2565		return n.Method.String()
2566	}
2567	return n.Field.String()
2568}
2569
2570// JS converts the node back to valid JavaScript
2571func (n ClassElement) JS() string {
2572	if n.StaticBlock != nil {
2573		return "static " + n.StaticBlock.JS()
2574	} else if n.Method != nil {
2575		return n.Method.JS()
2576	}
2577	return n.Field.JS()
2578}
2579
2580// JS converts the node back to valid JavaScript (writes to io.Writer)
2581func (n ClassElement) JSWriteTo(w io.Writer) (i int, err error) {
2582	var wn int
2583	if n.StaticBlock != nil {
2584		wn, err = w.Write([]byte("static "))
2585		i += wn
2586		if err != nil {
2587			return
2588		}
2589		wn, err = n.StaticBlock.JSWriteTo(w)
2590		i += wn
2591		return
2592	} else if n.Method != nil {
2593		wn, err = n.Method.JSWriteTo(w)
2594		i += wn
2595		return
2596	}
2597	wn, err = n.Field.JSWriteTo(w)
2598	i += wn
2599	return
2600}
2601
2602// ClassDecl is a class declaration.
2603type ClassDecl struct {
2604	Name    *Var  // can be nil
2605	Extends IExpr // can be nil
2606	List    []ClassElement
2607}
2608
2609func (n ClassDecl) String() string {
2610	s := "Decl(class"
2611	if n.Name != nil {
2612		s += " " + string(n.Name.Data)
2613	}
2614	if n.Extends != nil {
2615		s += " extends " + n.Extends.String()
2616	}
2617	for _, item := range n.List {
2618		s += " " + item.String()
2619	}
2620	return s + ")"
2621}
2622
2623// JS converts the node back to valid JavaScript
2624func (n ClassDecl) JS() string {
2625	s := "class"
2626	if n.Name != nil {
2627		s += " " + string(n.Name.Data)
2628	}
2629	if n.Extends != nil {
2630		s += " extends " + n.Extends.JS()
2631	}
2632	s += " { "
2633	for _, item := range n.List {
2634		s += item.JS() + "; "
2635	}
2636	return s + "}"
2637}
2638
2639// JS converts the node back to valid JavaScript (writes to io.Writer)
2640func (n ClassDecl) JSWriteTo(w io.Writer) (i int, err error) {
2641	var wn int
2642	wn, err = w.Write([]byte("class"))
2643	i += wn
2644	if err != nil {
2645		return
2646	}
2647	if n.Name != nil {
2648		wn, err = w.Write([]byte(" "))
2649		i += wn
2650		if err != nil {
2651			return
2652		}
2653		wn, err = w.Write(n.Name.Data)
2654		i += wn
2655		if err != nil {
2656			return
2657		}
2658	}
2659	if n.Extends != nil {
2660		wn, err = w.Write([]byte(" extends "))
2661		i += wn
2662		if err != nil {
2663			return
2664		}
2665		wn, err = n.Extends.JSWriteTo(w)
2666		i += wn
2667		if err != nil {
2668			return
2669		}
2670	}
2671	wn, err = w.Write([]byte(" { "))
2672	i += wn
2673	if err != nil {
2674		return
2675	}
2676	for _, item := range n.List {
2677		wn, err = item.JSWriteTo(w)
2678		i += wn
2679		if err != nil {
2680			return
2681		}
2682		wn, err = w.Write([]byte("; "))
2683		i += wn
2684		if err != nil {
2685			return
2686		}
2687	}
2688	wn, err = w.Write([]byte("}"))
2689	i += wn
2690	return
2691}
2692
2693func (n VarDecl) stmtNode()   {}
2694func (n FuncDecl) stmtNode()  {}
2695func (n ClassDecl) stmtNode() {}
2696
2697func (n VarDecl) exprNode()    {} // not a real IExpr, used for ForInit and ExportDecl
2698func (n FuncDecl) exprNode()   {}
2699func (n ClassDecl) exprNode()  {}
2700func (n MethodDecl) exprNode() {} // not a real IExpr, used for ObjectExpression PropertyName
2701
2702////////////////////////////////////////////////////////////////
2703
2704// LiteralExpr can be this, null, boolean, numeric, string, or regular expression literals.
2705type LiteralExpr struct {
2706	TokenType
2707	Data []byte
2708}
2709
2710func (n LiteralExpr) String() string {
2711	return string(n.Data)
2712}
2713
2714// JS converts the node back to valid JavaScript
2715func (n LiteralExpr) JS() string {
2716	return string(n.Data)
2717}
2718
2719// JS converts the node back to valid JavaScript (writes to io.Writer)
2720func (n LiteralExpr) JSWriteTo(w io.Writer) (i int, err error) {
2721	var wn int
2722	wn, err = w.Write(n.Data)
2723	i += wn
2724	return
2725}
2726
2727// JSON converts the node back to valid JSON
2728func (n LiteralExpr) JSON(buf *bytes.Buffer) error {
2729	if n.TokenType == TrueToken || n.TokenType == FalseToken || n.TokenType == NullToken || n.TokenType == DecimalToken {
2730		buf.Write(n.Data)
2731		return nil
2732	} else if n.TokenType == StringToken {
2733		data := n.Data
2734		if n.Data[0] == '\'' {
2735			data = parse.Copy(data)
2736			data = bytes.ReplaceAll(data, []byte(`"`), []byte(`\"`))
2737			data[0] = '"'
2738			data[len(data)-1] = '"'
2739		}
2740		buf.Write(data)
2741		return nil
2742	}
2743	return ErrInvalidJSON
2744}
2745
2746// Element is an array literal element.
2747type Element struct {
2748	Value  IExpr // can be nil
2749	Spread bool
2750}
2751
2752func (n Element) String() string {
2753	s := ""
2754	if n.Value != nil {
2755		if n.Spread {
2756			s += "..."
2757		}
2758		s += n.Value.String()
2759	}
2760	return s
2761}
2762
2763// JS converts the node back to valid JavaScript
2764func (n Element) JS() string {
2765	s := ""
2766	if n.Value != nil {
2767		if n.Spread {
2768			s += "..."
2769		}
2770		s += n.Value.JS()
2771	}
2772	return s
2773}
2774
2775// JS converts the node back to valid JavaScript (writes to io.Writer)
2776func (n Element) JSWriteTo(w io.Writer) (i int, err error) {
2777	var wn int
2778	if n.Value != nil {
2779		if n.Spread {
2780			wn, err = w.Write([]byte("..."))
2781			i += wn
2782			if err != nil {
2783				return
2784			}
2785		}
2786		wn, err = n.Value.JSWriteTo(w)
2787		i += wn
2788	}
2789	return
2790}
2791
2792// ArrayExpr is an array literal.
2793type ArrayExpr struct {
2794	List []Element
2795}
2796
2797func (n ArrayExpr) String() string {
2798	s := "["
2799	for i, item := range n.List {
2800		if i != 0 {
2801			s += ", "
2802		}
2803		if item.Value != nil {
2804			if item.Spread {
2805				s += "..."
2806			}
2807			s += item.Value.String()
2808		}
2809	}
2810	if 0 < len(n.List) && n.List[len(n.List)-1].Value == nil {
2811		s += ","
2812	}
2813	return s + "]"
2814}
2815
2816// JS converts the node back to valid JavaScript
2817func (n ArrayExpr) JS() string {
2818	s := "["
2819	for i, item := range n.List {
2820		if i != 0 {
2821			s += ", "
2822		}
2823		if item.Value != nil {
2824			if item.Spread {
2825				s += "..."
2826			}
2827			s += item.Value.JS()
2828		}
2829	}
2830	if 0 < len(n.List) && n.List[len(n.List)-1].Value == nil {
2831		s += ","
2832	}
2833	return s + "]"
2834}
2835
2836// JS converts the node back to valid JavaScript (writes to io.Writer)
2837func (n ArrayExpr) JSWriteTo(w io.Writer) (i int, err error) {
2838	var wn int
2839	wn, err = w.Write([]byte("["))
2840	i += wn
2841	if err != nil {
2842		return
2843	}
2844	for j, item := range n.List {
2845		if j != 0 {
2846			wn, err = w.Write([]byte(", "))
2847			i += wn
2848			if err != nil {
2849				return
2850			}
2851		}
2852		if item.Value != nil {
2853			if item.Spread {
2854				wn, err = w.Write([]byte("..."))
2855				i += wn
2856				if err != nil {
2857					return
2858				}
2859			}
2860			wn, err = item.Value.JSWriteTo(w)
2861			i += wn
2862			if err != nil {
2863				return
2864			}
2865		}
2866	}
2867	if 0 < len(n.List) && n.List[len(n.List)-1].Value == nil {
2868		wn, err = w.Write([]byte(","))
2869		i += wn
2870		if err != nil {
2871			return
2872		}
2873	}
2874	wn, err = w.Write([]byte("]"))
2875	i += wn
2876	return
2877}
2878
2879// JSON converts the node back to valid JSON
2880func (n ArrayExpr) JSON(buf *bytes.Buffer) error {
2881	buf.WriteByte('[')
2882	for i, item := range n.List {
2883		if i != 0 {
2884			buf.WriteString(", ")
2885		}
2886		if item.Value == nil || item.Spread {
2887			return ErrInvalidJSON
2888		}
2889		val, ok := item.Value.(JSONer)
2890		if !ok {
2891			return ErrInvalidJSON
2892		} else if err := val.JSON(buf); err != nil {
2893			return err
2894		}
2895	}
2896	buf.WriteByte(']')
2897	return nil
2898}
2899
2900// Property is a property definition in an object literal.
2901type Property struct {
2902	// either Name or Spread are set. When Spread is set then Value is AssignmentExpression
2903	// if Init is set then Value is IdentifierReference, otherwise it can also be MethodDefinition
2904	Name   *PropertyName // can be nil
2905	Spread bool
2906	Value  IExpr
2907	Init   IExpr // can be nil
2908}
2909
2910func (n Property) String() string {
2911	s := ""
2912	if n.Name != nil {
2913		if v, ok := n.Value.(*Var); !ok || !n.Name.IsIdent(v.Data) {
2914			s += n.Name.String() + ": "
2915		}
2916	} else if n.Spread {
2917		s += "..."
2918	}
2919	s += n.Value.String()
2920	if n.Init != nil {
2921		s += " = " + n.Init.String()
2922	}
2923	return s
2924}
2925
2926// JS converts the node back to valid JavaScript
2927func (n Property) JS() string {
2928	s := ""
2929	if n.Name != nil {
2930		if v, ok := n.Value.(*Var); !ok || !n.Name.IsIdent(v.Data) {
2931			s += n.Name.JS() + ": "
2932		}
2933	} else if n.Spread {
2934		s += "..."
2935	}
2936	s += n.Value.JS()
2937	if n.Init != nil {
2938		s += " = " + n.Init.JS()
2939	}
2940	return s
2941}
2942
2943// JS converts the node back to valid JavaScript (writes to io.Writer)
2944func (n Property) JSWriteTo(w io.Writer) (i int, err error) {
2945	var wn int
2946	if n.Name != nil {
2947		if v, ok := n.Value.(*Var); !ok || !n.Name.IsIdent(v.Data) {
2948			wn, err = n.Name.JSWriteTo(w)
2949			i += wn
2950			if err != nil {
2951				return
2952			}
2953			wn, err = w.Write([]byte(": "))
2954			i += wn
2955			if err != nil {
2956				return
2957			}
2958		}
2959	} else if n.Spread {
2960		wn, err = w.Write([]byte("..."))
2961		i += wn
2962		if err != nil {
2963			return
2964		}
2965	}
2966	wn, err = n.Value.JSWriteTo(w)
2967	i += wn
2968	if err != nil {
2969		return
2970	}
2971	if n.Init != nil {
2972		wn, err = w.Write([]byte(" = "))
2973		i += wn
2974		if err != nil {
2975			return
2976		}
2977		wn, err = n.Init.JSWriteTo(w)
2978		i += wn
2979		if err != nil {
2980			return
2981		}
2982	}
2983	return
2984}
2985
2986// JSON converts the node back to valid JSON
2987func (n Property) JSON(buf *bytes.Buffer) error {
2988	if n.Name == nil || n.Name.Literal.TokenType != StringToken && n.Name.Literal.TokenType != IdentifierToken || n.Spread || n.Init != nil {
2989		return ErrInvalidJSON
2990	} else if n.Name.Literal.TokenType == IdentifierToken {
2991		buf.WriteByte('"')
2992		buf.Write(n.Name.Literal.Data)
2993		buf.WriteByte('"')
2994	} else {
2995		_ = n.Name.Literal.JSON(buf)
2996	}
2997	buf.WriteString(": ")
2998
2999	val, ok := n.Value.(JSONer)
3000	if !ok {
3001		return ErrInvalidJSON
3002	} else if err := val.JSON(buf); err != nil {
3003		return err
3004	}
3005	return nil
3006}
3007
3008// ObjectExpr is an object literal.
3009type ObjectExpr struct {
3010	List []Property
3011}
3012
3013func (n ObjectExpr) String() string {
3014	s := "{"
3015	for i, item := range n.List {
3016		if i != 0 {
3017			s += ", "
3018		}
3019		s += item.String()
3020	}
3021	return s + "}"
3022}
3023
3024// JS converts the node back to valid JavaScript
3025func (n ObjectExpr) JS() string {
3026	s := "{"
3027	for i, item := range n.List {
3028		if i != 0 {
3029			s += ", "
3030		}
3031		s += item.JS()
3032	}
3033	return s + "}"
3034}
3035
3036// JS converts the node back to valid JavaScript (writes to io.Writer)
3037func (n ObjectExpr) JSWriteTo(w io.Writer) (i int, err error) {
3038	var wn int
3039	wn, err = w.Write([]byte("{"))
3040	i += wn
3041	if err != nil {
3042		return
3043	}
3044	for j, item := range n.List {
3045		if j != 0 {
3046			wn, err = w.Write([]byte(", "))
3047			i += wn
3048			if err != nil {
3049				return
3050			}
3051		}
3052		wn, err = item.JSWriteTo(w)
3053		i += wn
3054		if err != nil {
3055			return
3056		}
3057	}
3058	wn, err = w.Write([]byte("}"))
3059	i += wn
3060	return
3061}
3062
3063// JSON converts the node back to valid JSON
3064func (n ObjectExpr) JSON(buf *bytes.Buffer) error {
3065	buf.WriteByte('{')
3066	for i, item := range n.List {
3067		if i != 0 {
3068			buf.WriteString(", ")
3069		}
3070		if err := item.JSON(buf); err != nil {
3071			return err
3072		}
3073	}
3074	buf.WriteByte('}')
3075	return nil
3076}
3077
3078// TemplatePart is a template head or middle.
3079type TemplatePart struct {
3080	Value []byte
3081	Expr  IExpr
3082}
3083
3084func (n TemplatePart) String() string {
3085	return string(n.Value) + n.Expr.String()
3086}
3087
3088// JS converts the node back to valid JavaScript
3089func (n TemplatePart) JS() string {
3090	return string(n.Value) + n.Expr.JS()
3091}
3092
3093// JS converts the node back to valid JavaScript (writes to io.Writer)
3094func (n TemplatePart) JSWriteTo(w io.Writer) (i int, err error) {
3095	var wn int
3096	wn, err = w.Write(n.Value)
3097	i += wn
3098	if err != nil {
3099		return
3100	}
3101	wn, err = n.Expr.JSWriteTo(w)
3102	i += wn
3103	return
3104}
3105
3106// TemplateExpr is a template literal or member/call expression, super property, or optional chain with template literal.
3107type TemplateExpr struct {
3108	Tag      IExpr // can be nil
3109	List     []TemplatePart
3110	Tail     []byte
3111	Prec     OpPrec
3112	Optional bool
3113}
3114
3115func (n TemplateExpr) String() string {
3116	s := ""
3117	if n.Tag != nil {
3118		s += n.Tag.String()
3119		if n.Optional {
3120			s += "?."
3121		}
3122	}
3123	for _, item := range n.List {
3124		s += item.String()
3125	}
3126	return s + string(n.Tail)
3127}
3128
3129// JS converts the node back to valid JavaScript
3130func (n TemplateExpr) JS() string {
3131	s := ""
3132	if n.Tag != nil {
3133		s += n.Tag.JS()
3134		if n.Optional {
3135			s += "?."
3136		}
3137	}
3138	for _, item := range n.List {
3139		s += item.JS()
3140	}
3141	return s + string(n.Tail)
3142}
3143
3144// JS converts the node back to valid JavaScript (writes to io.Writer)
3145func (n TemplateExpr) JSWriteTo(w io.Writer) (i int, err error) {
3146	var wn int
3147	if n.Tag != nil {
3148		wn, err = n.Tag.JSWriteTo(w)
3149		i += wn
3150		if err != nil {
3151			return
3152		}
3153		if n.Optional {
3154			wn, err = w.Write([]byte("?."))
3155			i += wn
3156			if err != nil {
3157				return
3158			}
3159		}
3160	}
3161	for _, item := range n.List {
3162		wn, err = item.JSWriteTo(w)
3163		i += wn
3164		if err != nil {
3165			return
3166		}
3167	}
3168	wn, err = w.Write(n.Tail)
3169	i += wn
3170	return
3171}
3172
3173// GroupExpr is a parenthesized expression.
3174type GroupExpr struct {
3175	X IExpr
3176}
3177
3178func (n GroupExpr) String() string {
3179	return "(" + n.X.String() + ")"
3180}
3181
3182// JS converts the node back to valid JavaScript
3183func (n GroupExpr) JS() string {
3184	return "(" + n.X.JS() + ")"
3185}
3186
3187// JS converts the node back to valid JavaScript (writes to io.Writer)
3188func (n GroupExpr) JSWriteTo(w io.Writer) (i int, err error) {
3189	var wn int
3190	wn, err = w.Write([]byte("("))
3191	i += wn
3192	if err != nil {
3193		return
3194	}
3195	wn, err = n.X.JSWriteTo(w)
3196	i += wn
3197	if err != nil {
3198		return
3199	}
3200	wn, err = w.Write([]byte(")"))
3201	i += wn
3202	return
3203}
3204
3205// IndexExpr is a member/call expression, super property, or optional chain with an index expression.
3206type IndexExpr struct {
3207	X        IExpr
3208	Y        IExpr
3209	Prec     OpPrec
3210	Optional bool
3211}
3212
3213func (n IndexExpr) String() string {
3214	if n.Optional {
3215		return "(" + n.X.String() + "?.[" + n.Y.String() + "])"
3216	}
3217	return "(" + n.X.String() + "[" + n.Y.String() + "])"
3218}
3219
3220// JS converts the node back to valid JavaScript
3221func (n IndexExpr) JS() string {
3222	if n.Optional {
3223		return n.X.JS() + "?.[" + n.Y.JS() + "]"
3224	}
3225	return n.X.JS() + "[" + n.Y.JS() + "]"
3226}
3227
3228// JS converts the node back to valid JavaScript (writes to io.Writer)
3229func (n IndexExpr) JSWriteTo(w io.Writer) (i int, err error) {
3230	var wn int
3231	wn, err = n.X.JSWriteTo(w)
3232	i += wn
3233	if err != nil {
3234		return
3235	}
3236	if n.Optional {
3237		wn, err = w.Write([]byte("?.["))
3238		i += wn
3239		if err != nil {
3240			return
3241		}
3242	} else {
3243		wn, err = w.Write([]byte("["))
3244		i += wn
3245		if err != nil {
3246			return
3247		}
3248	}
3249	wn, err = n.Y.JSWriteTo(w)
3250	i += wn
3251	if err != nil {
3252		return
3253	}
3254	wn, err = w.Write([]byte("]"))
3255	i += wn
3256	return
3257}
3258
3259// DotExpr is a member/call expression, super property, or optional chain with a dot expression.
3260type DotExpr struct {
3261	X        IExpr
3262	Y        LiteralExpr
3263	Prec     OpPrec
3264	Optional bool
3265}
3266
3267func (n DotExpr) String() string {
3268	if n.Optional {
3269		return "(" + n.X.String() + "?." + n.Y.String() + ")"
3270	}
3271	return "(" + n.X.String() + "." + n.Y.String() + ")"
3272}
3273
3274// JS converts the node back to valid JavaScript
3275func (n DotExpr) JS() string {
3276	if n.Optional {
3277		return n.X.JS() + "?." + n.Y.JS()
3278	}
3279	return n.X.JS() + "." + n.Y.JS()
3280}
3281
3282// JS converts the node back to valid JavaScript (writes to io.Writer)
3283func (n DotExpr) JSWriteTo(w io.Writer) (i int, err error) {
3284	var wn int
3285	wn, err = n.X.JSWriteTo(w)
3286	i += wn
3287	if err != nil {
3288		return
3289	}
3290	if n.Optional {
3291		wn, err = w.Write([]byte("?."))
3292		i += wn
3293		if err != nil {
3294			return
3295		}
3296	} else {
3297		wn, err = w.Write([]byte("."))
3298		i += wn
3299		if err != nil {
3300			return
3301		}
3302	}
3303	wn, err = n.Y.JSWriteTo(w)
3304	i += wn
3305	return
3306}
3307
3308// NewTargetExpr is a new target meta property.
3309type NewTargetExpr struct {
3310}
3311
3312func (n NewTargetExpr) String() string {
3313	return "(new.target)"
3314}
3315
3316// JS converts the node back to valid JavaScript
3317func (n NewTargetExpr) JS() string {
3318	return "new.target"
3319}
3320
3321// JS converts the node back to valid JavaScript (writes to io.Writer)
3322func (n NewTargetExpr) JSWriteTo(w io.Writer) (i int, err error) {
3323	var wn int
3324	wn, err = w.Write([]byte("new.target"))
3325	i += wn
3326	return
3327}
3328
3329// ImportMetaExpr is a import meta meta property.
3330type ImportMetaExpr struct {
3331}
3332
3333func (n ImportMetaExpr) String() string {
3334	return "(import.meta)"
3335}
3336
3337// JS converts the node back to valid JavaScript
3338func (n ImportMetaExpr) JS() string {
3339	return "import.meta"
3340}
3341
3342// JS converts the node back to valid JavaScript (writes to io.Writer)
3343func (n ImportMetaExpr) JSWriteTo(w io.Writer) (i int, err error) {
3344	var wn int
3345	wn, err = w.Write([]byte("import.meta"))
3346	i += wn
3347	return
3348}
3349
3350type Arg struct {
3351	Value IExpr
3352	Rest  bool
3353}
3354
3355func (n Arg) String() string {
3356	s := ""
3357	if n.Rest {
3358		s += "..."
3359	}
3360	return s + n.Value.String()
3361}
3362
3363// JS converts the node back to valid JavaScript
3364func (n Arg) JS() string {
3365	s := ""
3366	if n.Rest {
3367		s += "..."
3368	}
3369	return s + n.Value.JS()
3370}
3371
3372// JS converts the node back to valid JavaScript (writes to io.Writer)
3373func (n Arg) JSWriteTo(w io.Writer) (i int, err error) {
3374	var wn int
3375	if n.Rest {
3376		wn, err = w.Write([]byte("..."))
3377		i += wn
3378		if err != nil {
3379			return
3380		}
3381	}
3382	wn, err = n.Value.JSWriteTo(w)
3383	i += wn
3384	return
3385}
3386
3387// Args is a list of arguments as used by new and call expressions.
3388type Args struct {
3389	List []Arg
3390}
3391
3392func (n Args) String() string {
3393	s := "("
3394	for i, item := range n.List {
3395		if i != 0 {
3396			s += ", "
3397		}
3398		s += item.String()
3399	}
3400	return s + ")"
3401}
3402
3403// JS converts the node back to valid JavaScript
3404func (n Args) JS() string {
3405	s := ""
3406	for i, item := range n.List {
3407		if i != 0 {
3408			s += ", "
3409		}
3410		s += item.JS()
3411	}
3412	return s
3413}
3414
3415// JS converts the node back to valid JavaScript (writes to io.Writer)
3416func (n Args) JSWriteTo(w io.Writer) (i int, err error) {
3417	var wn int
3418	for j, item := range n.List {
3419		if j != 0 {
3420			wn, err = w.Write([]byte(", "))
3421			i += wn
3422			if err != nil {
3423				return
3424			}
3425		}
3426		wn, err = item.JSWriteTo(w)
3427		i += wn
3428		if err != nil {
3429			return
3430		}
3431	}
3432	return
3433}
3434
3435// NewExpr is a new expression or new member expression.
3436type NewExpr struct {
3437	X    IExpr
3438	Args *Args // can be nil
3439}
3440
3441func (n NewExpr) String() string {
3442	if n.Args != nil {
3443		return "(new " + n.X.String() + n.Args.String() + ")"
3444	}
3445	return "(new " + n.X.String() + ")"
3446}
3447
3448// JS converts the node back to valid JavaScript
3449func (n NewExpr) JS() string {
3450	if n.Args != nil {
3451		return "new " + n.X.JS() + "(" + n.Args.JS() + ")"
3452	}
3453
3454	// always use parentheses to prevent errors when chaining e.g. new Date().getTime()
3455	return "new " + n.X.JS() + "()"
3456}
3457
3458// JS converts the node back to valid JavaScript (writes to io.Writer)
3459func (n NewExpr) JSWriteTo(w io.Writer) (i int, err error) {
3460	var wn int
3461	wn, err = w.Write([]byte("new "))
3462	i += wn
3463	if err != nil {
3464		return
3465	}
3466	wn, err = n.X.JSWriteTo(w)
3467	i += wn
3468	if err != nil {
3469		return
3470	}
3471	if n.Args != nil {
3472		wn, err = w.Write([]byte("("))
3473		i += wn
3474		if err != nil {
3475			return
3476		}
3477		wn, err = n.Args.JSWriteTo(w)
3478		i += wn
3479		if err != nil {
3480			return
3481		}
3482		wn, err = w.Write([]byte(")"))
3483		i += wn
3484		if err != nil {
3485			return
3486		}
3487	} else {
3488		wn, err = w.Write([]byte("()"))
3489		i += wn
3490		if err != nil {
3491			return
3492		}
3493	}
3494	return
3495}
3496
3497// CallExpr is a call expression.
3498type CallExpr struct {
3499	X        IExpr
3500	Args     Args
3501	Optional bool
3502}
3503
3504func (n CallExpr) String() string {
3505	if n.Optional {
3506		return "(" + n.X.String() + "?." + n.Args.String() + ")"
3507	}
3508	return "(" + n.X.String() + n.Args.String() + ")"
3509}
3510
3511// JS converts the node back to valid JavaScript
3512func (n CallExpr) JS() string {
3513	if n.Optional {
3514		return n.X.JS() + "?.(" + n.Args.JS() + ")"
3515	}
3516	return n.X.JS() + "(" + n.Args.JS() + ")"
3517}
3518
3519// JS converts the node back to valid JavaScript (writes to io.Writer)
3520func (n CallExpr) JSWriteTo(w io.Writer) (i int, err error) {
3521	var wn int
3522	wn, err = n.X.JSWriteTo(w)
3523	i += wn
3524	if err != nil {
3525		return
3526	}
3527	if n.Optional {
3528		wn, err = w.Write([]byte("?.("))
3529		i += wn
3530		if err != nil {
3531			return
3532		}
3533	} else {
3534		wn, err = w.Write([]byte("("))
3535		i += wn
3536		if err != nil {
3537			return
3538		}
3539	}
3540	wn, err = n.Args.JSWriteTo(w)
3541	i += wn
3542	if err != nil {
3543		return
3544	}
3545	wn, err = w.Write([]byte(")"))
3546	i += wn
3547	if err != nil {
3548		return
3549	}
3550	return
3551}
3552
3553// UnaryExpr is an update or unary expression.
3554type UnaryExpr struct {
3555	Op TokenType
3556	X  IExpr
3557}
3558
3559func (n UnaryExpr) String() string {
3560	if n.Op == PostIncrToken || n.Op == PostDecrToken {
3561		return "(" + n.X.String() + n.Op.String() + ")"
3562	} else if IsIdentifierName(n.Op) {
3563		return "(" + n.Op.String() + " " + n.X.String() + ")"
3564	}
3565	return "(" + n.Op.String() + n.X.String() + ")"
3566}
3567
3568// JS converts the node back to valid JavaScript
3569func (n UnaryExpr) JS() string {
3570	if n.Op == PostIncrToken || n.Op == PostDecrToken {
3571		return n.X.JS() + n.Op.String()
3572	} else if IsIdentifierName(n.Op) {
3573		return n.Op.String() + " " + n.X.JS()
3574	}
3575	return n.Op.String() + n.X.JS()
3576}
3577
3578// JS converts the node back to valid JavaScript (writes to io.Writer)
3579func (n UnaryExpr) JSWriteTo(w io.Writer) (i int, err error) {
3580	var wn int
3581	if n.Op == PostIncrToken || n.Op == PostDecrToken {
3582		wn, err = n.X.JSWriteTo(w)
3583		i += wn
3584		if err != nil {
3585			return
3586		}
3587		wn, err = w.Write(n.Op.Bytes())
3588		i += wn
3589		return
3590	} else if IsIdentifierName(n.Op) {
3591		wn, err = w.Write(n.Op.Bytes())
3592		i += wn
3593		if err != nil {
3594			return
3595		}
3596		wn, err = w.Write([]byte(" "))
3597		i += wn
3598		if err != nil {
3599			return
3600		}
3601		wn, err = n.X.JSWriteTo(w)
3602		i += wn
3603		return
3604	}
3605	wn, err = w.Write(n.Op.Bytes())
3606	i += wn
3607	if err != nil {
3608		return
3609	}
3610	wn, err = n.X.JSWriteTo(w)
3611	i += wn
3612	return
3613}
3614
3615// JSON converts the node back to valid JSON
3616func (n UnaryExpr) JSON(buf *bytes.Buffer) error {
3617	if lit, ok := n.X.(*LiteralExpr); ok && n.Op == NegToken && lit.TokenType == DecimalToken {
3618		buf.WriteByte('-')
3619		buf.Write(lit.Data)
3620		return nil
3621	}
3622	return ErrInvalidJSON
3623}
3624
3625// BinaryExpr is a binary expression.
3626type BinaryExpr struct {
3627	Op   TokenType
3628	X, Y IExpr
3629}
3630
3631func (n BinaryExpr) String() string {
3632	if IsIdentifierName(n.Op) {
3633		return "(" + n.X.String() + " " + n.Op.String() + " " + n.Y.String() + ")"
3634	}
3635	return "(" + n.X.String() + n.Op.String() + n.Y.String() + ")"
3636}
3637
3638// JS converts the node back to valid JavaScript
3639func (n BinaryExpr) JS() string {
3640	return n.X.JS() + " " + n.Op.String() + " " + n.Y.JS()
3641}
3642
3643// JS converts the node back to valid JavaScript (writes to io.Writer)
3644func (n BinaryExpr) JSWriteTo(w io.Writer) (i int, err error) {
3645	var wn int
3646	wn, err = n.X.JSWriteTo(w)
3647	i += wn
3648	if err != nil {
3649		return
3650	}
3651	wn, err = w.Write([]byte(" "))
3652	i += wn
3653	if err != nil {
3654		return
3655	}
3656	wn, err = w.Write(n.Op.Bytes())
3657	i += wn
3658	if err != nil {
3659		return
3660	}
3661	wn, err = w.Write([]byte(" "))
3662	i += wn
3663	if err != nil {
3664		return
3665	}
3666	wn, err = n.Y.JSWriteTo(w)
3667	i += wn
3668	return
3669}
3670
3671// CondExpr is a conditional expression.
3672type CondExpr struct {
3673	Cond, X, Y IExpr
3674}
3675
3676func (n CondExpr) String() string {
3677	return "(" + n.Cond.String() + " ? " + n.X.String() + " : " + n.Y.String() + ")"
3678}
3679
3680// JS converts the node back to valid JavaScript
3681func (n CondExpr) JS() string {
3682	return n.Cond.JS() + " ? " + n.X.JS() + " : " + n.Y.JS()
3683}
3684
3685// JS converts the node back to valid JavaScript (writes to io.Writer)
3686func (n CondExpr) JSWriteTo(w io.Writer) (i int, err error) {
3687	var wn int
3688	wn, err = n.Cond.JSWriteTo(w)
3689	i += wn
3690	if err != nil {
3691		return
3692	}
3693	wn, err = w.Write([]byte(" ? "))
3694	i += wn
3695	if err != nil {
3696		return
3697	}
3698	wn, err = n.X.JSWriteTo(w)
3699	i += wn
3700	if err != nil {
3701		return
3702	}
3703	wn, err = w.Write([]byte(" : "))
3704	i += wn
3705	if err != nil {
3706		return
3707	}
3708	wn, err = n.Y.JSWriteTo(w)
3709	i += wn
3710	return
3711}
3712
3713// YieldExpr is a yield expression.
3714type YieldExpr struct {
3715	Generator bool
3716	X         IExpr // can be nil
3717}
3718
3719func (n YieldExpr) String() string {
3720	if n.X == nil {
3721		return "(yield)"
3722	}
3723	s := "(yield"
3724	if n.Generator {
3725		s += "*"
3726	}
3727	return s + " " + n.X.String() + ")"
3728}
3729
3730// JS converts the node back to valid JavaScript
3731func (n YieldExpr) JS() string {
3732	if n.X == nil {
3733		return "yield"
3734	}
3735	s := "yield"
3736	if n.Generator {
3737		s += "*"
3738	}
3739	return s + " " + n.X.JS()
3740}
3741
3742// JS converts the node back to valid JavaScript (writes to io.Writer)
3743func (n YieldExpr) JSWriteTo(w io.Writer) (i int, err error) {
3744	var wn int
3745	wn, err = w.Write([]byte("yield"))
3746	i += wn
3747	if err != nil {
3748		return
3749	}
3750	if n.X == nil {
3751		return
3752	}
3753	if n.Generator {
3754		wn, err = w.Write([]byte("*"))
3755		i += wn
3756		if err != nil {
3757			return
3758		}
3759	}
3760	wn, err = w.Write([]byte(" "))
3761	i += wn
3762	if err != nil {
3763		return
3764	}
3765	wn, err = n.X.JSWriteTo(w)
3766	i += wn
3767	return
3768}
3769
3770// ArrowFunc is an (async) arrow function.
3771type ArrowFunc struct {
3772	Async  bool
3773	Params Params
3774	Body   BlockStmt
3775}
3776
3777func (n ArrowFunc) String() string {
3778	s := "("
3779	if n.Async {
3780		s += "async "
3781	}
3782	return s + n.Params.String() + " => " + n.Body.String() + ")"
3783}
3784
3785// JS converts the node back to valid JavaScript
3786func (n ArrowFunc) JS() string {
3787	s := ""
3788	if n.Async {
3789		s += "async "
3790	}
3791	return s + n.Params.JS() + " => " + n.Body.JS()
3792}
3793
3794// JS converts the node back to valid JavaScript (writes to io.Writer)
3795func (n ArrowFunc) JSWriteTo(w io.Writer) (i int, err error) {
3796	var wn int
3797	if n.Async {
3798		wn, err = w.Write([]byte("async "))
3799		i += wn
3800		if err != nil {
3801			return
3802		}
3803	}
3804	wn, err = n.Params.JSWriteTo(w)
3805	i += wn
3806	if err != nil {
3807		return
3808	}
3809	wn, err = w.Write([]byte(" => "))
3810	i += wn
3811	if err != nil {
3812		return
3813	}
3814	wn, err = n.Body.JSWriteTo(w)
3815	i += wn
3816	return
3817}
3818
3819// CommaExpr is a series of comma expressions.
3820type CommaExpr struct {
3821	List []IExpr
3822}
3823
3824func (n CommaExpr) String() string {
3825	s := "("
3826	for i, item := range n.List {
3827		if i != 0 {
3828			s += ","
3829		}
3830		s += item.String()
3831	}
3832	return s + ")"
3833}
3834
3835// JS converts the node back to valid JavaScript
3836func (n CommaExpr) JS() string {
3837	s := ""
3838	for i, item := range n.List {
3839		if i != 0 {
3840			s += ","
3841		}
3842		s += item.JS()
3843	}
3844	return s
3845}
3846
3847// JS converts the node back to valid JavaScript (writes to io.Writer)
3848func (n CommaExpr) JSWriteTo(w io.Writer) (i int, err error) {
3849	var wn int
3850	for j, item := range n.List {
3851		if j != 0 {
3852			wn, err = w.Write([]byte(","))
3853			i += wn
3854			if err != nil {
3855				return
3856			}
3857		}
3858		wn, err = item.JSWriteTo(w)
3859		i += wn
3860		if err != nil {
3861			return
3862		}
3863	}
3864	return
3865}
3866
3867func (v *Var) exprNode()           {}
3868func (n LiteralExpr) exprNode()    {}
3869func (n ArrayExpr) exprNode()      {}
3870func (n ObjectExpr) exprNode()     {}
3871func (n TemplateExpr) exprNode()   {}
3872func (n GroupExpr) exprNode()      {}
3873func (n DotExpr) exprNode()        {}
3874func (n IndexExpr) exprNode()      {}
3875func (n NewTargetExpr) exprNode()  {}
3876func (n ImportMetaExpr) exprNode() {}
3877func (n NewExpr) exprNode()        {}
3878func (n CallExpr) exprNode()       {}
3879func (n UnaryExpr) exprNode()      {}
3880func (n BinaryExpr) exprNode()     {}
3881func (n CondExpr) exprNode()       {}
3882func (n YieldExpr) exprNode()      {}
3883func (n ArrowFunc) exprNode()      {}
3884func (n CommaExpr) exprNode()      {}