github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/compiler_expr.go (about)

     1  package goja
     2  
     3  import (
     4  	"github.com/nuvolaris/goja/ast"
     5  	"github.com/nuvolaris/goja/file"
     6  	"github.com/nuvolaris/goja/token"
     7  	"github.com/nuvolaris/goja/unistring"
     8  )
     9  
    10  type compiledExpr interface {
    11  	emitGetter(putOnStack bool)
    12  	emitSetter(valueExpr compiledExpr, putOnStack bool)
    13  	emitRef()
    14  	emitUnary(prepare, body func(), postfix, putOnStack bool)
    15  	deleteExpr() compiledExpr
    16  	constant() bool
    17  	addSrcMap()
    18  }
    19  
    20  type compiledExprOrRef interface {
    21  	compiledExpr
    22  	emitGetterOrRef()
    23  }
    24  
    25  type compiledCallExpr struct {
    26  	baseCompiledExpr
    27  	args   []compiledExpr
    28  	callee compiledExpr
    29  
    30  	isVariadic bool
    31  }
    32  
    33  type compiledNewExpr struct {
    34  	compiledCallExpr
    35  }
    36  
    37  type compiledObjectLiteral struct {
    38  	baseCompiledExpr
    39  	expr *ast.ObjectLiteral
    40  }
    41  
    42  type compiledArrayLiteral struct {
    43  	baseCompiledExpr
    44  	expr *ast.ArrayLiteral
    45  }
    46  
    47  type compiledRegexpLiteral struct {
    48  	baseCompiledExpr
    49  	expr *ast.RegExpLiteral
    50  }
    51  
    52  type compiledLiteral struct {
    53  	baseCompiledExpr
    54  	val Value
    55  }
    56  
    57  type compiledTemplateLiteral struct {
    58  	baseCompiledExpr
    59  	tag         compiledExpr
    60  	elements    []*ast.TemplateElement
    61  	expressions []compiledExpr
    62  }
    63  
    64  type compiledAssignExpr struct {
    65  	baseCompiledExpr
    66  	left, right compiledExpr
    67  	operator    token.Token
    68  }
    69  
    70  type compiledObjectAssignmentPattern struct {
    71  	baseCompiledExpr
    72  	expr *ast.ObjectPattern
    73  }
    74  
    75  type compiledArrayAssignmentPattern struct {
    76  	baseCompiledExpr
    77  	expr *ast.ArrayPattern
    78  }
    79  
    80  type deleteGlobalExpr struct {
    81  	baseCompiledExpr
    82  	name unistring.String
    83  }
    84  
    85  type deleteVarExpr struct {
    86  	baseCompiledExpr
    87  	name unistring.String
    88  }
    89  
    90  type deletePropExpr struct {
    91  	baseCompiledExpr
    92  	left compiledExpr
    93  	name unistring.String
    94  }
    95  
    96  type deleteElemExpr struct {
    97  	baseCompiledExpr
    98  	left, member compiledExpr
    99  }
   100  
   101  type constantExpr struct {
   102  	baseCompiledExpr
   103  	val Value
   104  }
   105  
   106  type baseCompiledExpr struct {
   107  	c      *compiler
   108  	offset int
   109  }
   110  
   111  type compiledIdentifierExpr struct {
   112  	baseCompiledExpr
   113  	name unistring.String
   114  }
   115  
   116  type compiledAwaitExpression struct {
   117  	baseCompiledExpr
   118  	arg compiledExpr
   119  }
   120  
   121  type compiledYieldExpression struct {
   122  	baseCompiledExpr
   123  	arg      compiledExpr
   124  	delegate bool
   125  }
   126  
   127  type funcType uint8
   128  
   129  const (
   130  	funcNone funcType = iota
   131  	funcRegular
   132  	funcArrow
   133  	funcMethod
   134  	funcClsInit
   135  	funcCtor
   136  	funcDerivedCtor
   137  )
   138  
   139  type compiledFunctionLiteral struct {
   140  	baseCompiledExpr
   141  	name            *ast.Identifier
   142  	parameterList   *ast.ParameterList
   143  	body            []ast.Statement
   144  	source          string
   145  	declarationList []*ast.VariableDeclaration
   146  	lhsName         unistring.String
   147  	strict          *ast.StringLiteral
   148  	homeObjOffset   uint32
   149  	typ             funcType
   150  	isExpr          bool
   151  
   152  	isAsync, isGenerator bool
   153  }
   154  
   155  type compiledBracketExpr struct {
   156  	baseCompiledExpr
   157  	left, member compiledExpr
   158  }
   159  
   160  type compiledThisExpr struct {
   161  	baseCompiledExpr
   162  }
   163  
   164  type compiledSuperExpr struct {
   165  	baseCompiledExpr
   166  }
   167  
   168  type compiledNewTarget struct {
   169  	baseCompiledExpr
   170  }
   171  
   172  type compiledSequenceExpr struct {
   173  	baseCompiledExpr
   174  	sequence []compiledExpr
   175  }
   176  
   177  type compiledUnaryExpr struct {
   178  	baseCompiledExpr
   179  	operand  compiledExpr
   180  	operator token.Token
   181  	postfix  bool
   182  }
   183  
   184  type compiledConditionalExpr struct {
   185  	baseCompiledExpr
   186  	test, consequent, alternate compiledExpr
   187  }
   188  
   189  type compiledLogicalOr struct {
   190  	baseCompiledExpr
   191  	left, right compiledExpr
   192  }
   193  
   194  type compiledCoalesce struct {
   195  	baseCompiledExpr
   196  	left, right compiledExpr
   197  }
   198  
   199  type compiledLogicalAnd struct {
   200  	baseCompiledExpr
   201  	left, right compiledExpr
   202  }
   203  
   204  type compiledBinaryExpr struct {
   205  	baseCompiledExpr
   206  	left, right compiledExpr
   207  	operator    token.Token
   208  }
   209  
   210  type compiledEnumGetExpr struct {
   211  	baseCompiledExpr
   212  }
   213  
   214  type defaultDeleteExpr struct {
   215  	baseCompiledExpr
   216  	expr compiledExpr
   217  }
   218  
   219  type compiledSpreadCallArgument struct {
   220  	baseCompiledExpr
   221  	expr compiledExpr
   222  }
   223  
   224  type compiledOptionalChain struct {
   225  	baseCompiledExpr
   226  	expr compiledExpr
   227  }
   228  
   229  type compiledOptional struct {
   230  	baseCompiledExpr
   231  	expr compiledExpr
   232  }
   233  
   234  func (e *defaultDeleteExpr) emitGetter(putOnStack bool) {
   235  	e.expr.emitGetter(false)
   236  	if putOnStack {
   237  		e.c.emit(loadVal(e.c.p.defineLiteralValue(valueTrue)))
   238  	}
   239  }
   240  
   241  func (c *compiler) compileExpression(v ast.Expression) compiledExpr {
   242  	// log.Printf("compileExpression: %T", v)
   243  	switch v := v.(type) {
   244  	case nil:
   245  		return nil
   246  	case *ast.AssignExpression:
   247  		return c.compileAssignExpression(v)
   248  	case *ast.NumberLiteral:
   249  		return c.compileNumberLiteral(v)
   250  	case *ast.StringLiteral:
   251  		return c.compileStringLiteral(v)
   252  	case *ast.TemplateLiteral:
   253  		return c.compileTemplateLiteral(v)
   254  	case *ast.BooleanLiteral:
   255  		return c.compileBooleanLiteral(v)
   256  	case *ast.NullLiteral:
   257  		r := &compiledLiteral{
   258  			val: _null,
   259  		}
   260  		r.init(c, v.Idx0())
   261  		return r
   262  	case *ast.Identifier:
   263  		return c.compileIdentifierExpression(v)
   264  	case *ast.CallExpression:
   265  		return c.compileCallExpression(v)
   266  	case *ast.ObjectLiteral:
   267  		return c.compileObjectLiteral(v)
   268  	case *ast.ArrayLiteral:
   269  		return c.compileArrayLiteral(v)
   270  	case *ast.RegExpLiteral:
   271  		return c.compileRegexpLiteral(v)
   272  	case *ast.BinaryExpression:
   273  		return c.compileBinaryExpression(v)
   274  	case *ast.UnaryExpression:
   275  		return c.compileUnaryExpression(v)
   276  	case *ast.ConditionalExpression:
   277  		return c.compileConditionalExpression(v)
   278  	case *ast.FunctionLiteral:
   279  		return c.compileFunctionLiteral(v, true)
   280  	case *ast.ArrowFunctionLiteral:
   281  		return c.compileArrowFunctionLiteral(v)
   282  	case *ast.ClassLiteral:
   283  		return c.compileClassLiteral(v, true)
   284  	case *ast.DotExpression:
   285  		return c.compileDotExpression(v)
   286  	case *ast.PrivateDotExpression:
   287  		return c.compilePrivateDotExpression(v)
   288  	case *ast.BracketExpression:
   289  		return c.compileBracketExpression(v)
   290  	case *ast.ThisExpression:
   291  		r := &compiledThisExpr{}
   292  		r.init(c, v.Idx0())
   293  		return r
   294  	case *ast.SuperExpression:
   295  		c.throwSyntaxError(int(v.Idx0())-1, "'super' keyword unexpected here")
   296  		panic("unreachable")
   297  	case *ast.SequenceExpression:
   298  		return c.compileSequenceExpression(v)
   299  	case *ast.NewExpression:
   300  		return c.compileNewExpression(v)
   301  	case *ast.MetaProperty:
   302  		return c.compileMetaProperty(v)
   303  	case *ast.ObjectPattern:
   304  		return c.compileObjectAssignmentPattern(v)
   305  	case *ast.ArrayPattern:
   306  		return c.compileArrayAssignmentPattern(v)
   307  	case *ast.OptionalChain:
   308  		r := &compiledOptionalChain{
   309  			expr: c.compileExpression(v.Expression),
   310  		}
   311  		r.init(c, v.Idx0())
   312  		return r
   313  	case *ast.Optional:
   314  		r := &compiledOptional{
   315  			expr: c.compileExpression(v.Expression),
   316  		}
   317  		r.init(c, v.Idx0())
   318  		return r
   319  	case *ast.AwaitExpression:
   320  		r := &compiledAwaitExpression{
   321  			arg: c.compileExpression(v.Argument),
   322  		}
   323  		r.init(c, v.Await)
   324  		return r
   325  	case *ast.YieldExpression:
   326  		r := &compiledYieldExpression{
   327  			arg:      c.compileExpression(v.Argument),
   328  			delegate: v.Delegate,
   329  		}
   330  		r.init(c, v.Yield)
   331  		return r
   332  	default:
   333  		c.assert(false, int(v.Idx0())-1, "Unknown expression type: %T", v)
   334  		panic("unreachable")
   335  	}
   336  }
   337  
   338  func (e *baseCompiledExpr) constant() bool {
   339  	return false
   340  }
   341  
   342  func (e *baseCompiledExpr) init(c *compiler, idx file.Idx) {
   343  	e.c = c
   344  	e.offset = int(idx) - 1
   345  }
   346  
   347  func (e *baseCompiledExpr) emitSetter(compiledExpr, bool) {
   348  	e.c.throwSyntaxError(e.offset, "Not a valid left-value expression")
   349  }
   350  
   351  func (e *baseCompiledExpr) emitRef() {
   352  	e.c.assert(false, e.offset, "Cannot emit reference for this type of expression")
   353  }
   354  
   355  func (e *baseCompiledExpr) deleteExpr() compiledExpr {
   356  	r := &constantExpr{
   357  		val: valueTrue,
   358  	}
   359  	r.init(e.c, file.Idx(e.offset+1))
   360  	return r
   361  }
   362  
   363  func (e *baseCompiledExpr) emitUnary(func(), func(), bool, bool) {
   364  	e.c.throwSyntaxError(e.offset, "Not a valid left-value expression")
   365  }
   366  
   367  func (e *baseCompiledExpr) addSrcMap() {
   368  	if e.offset >= 0 {
   369  		e.c.p.addSrcMap(e.offset)
   370  	}
   371  }
   372  
   373  func (e *constantExpr) emitGetter(putOnStack bool) {
   374  	if putOnStack {
   375  		e.addSrcMap()
   376  		e.c.emit(loadVal(e.c.p.defineLiteralValue(e.val)))
   377  	}
   378  }
   379  
   380  func (e *compiledIdentifierExpr) emitGetter(putOnStack bool) {
   381  	e.addSrcMap()
   382  	if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics {
   383  		e.c.assert(b != nil, e.offset, "No dynamics and not found")
   384  		if putOnStack {
   385  			b.emitGet()
   386  		} else {
   387  			b.emitGetP()
   388  		}
   389  	} else {
   390  		if b != nil {
   391  			b.emitGetVar(false)
   392  		} else {
   393  			e.c.emit(loadDynamic(e.name))
   394  		}
   395  		if !putOnStack {
   396  			e.c.emit(pop)
   397  		}
   398  	}
   399  }
   400  
   401  func (e *compiledIdentifierExpr) emitGetterOrRef() {
   402  	e.addSrcMap()
   403  	if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics {
   404  		e.c.assert(b != nil, e.offset, "No dynamics and not found")
   405  		b.emitGet()
   406  	} else {
   407  		if b != nil {
   408  			b.emitGetVar(false)
   409  		} else {
   410  			e.c.emit(loadDynamicRef(e.name))
   411  		}
   412  	}
   413  }
   414  
   415  func (e *compiledIdentifierExpr) emitGetterAndCallee() {
   416  	e.addSrcMap()
   417  	if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics {
   418  		e.c.assert(b != nil, e.offset, "No dynamics and not found")
   419  		e.c.emit(loadUndef)
   420  		b.emitGet()
   421  	} else {
   422  		if b != nil {
   423  			b.emitGetVar(true)
   424  		} else {
   425  			e.c.emit(loadDynamicCallee(e.name))
   426  		}
   427  	}
   428  }
   429  
   430  func (e *compiledIdentifierExpr) emitVarSetter1(putOnStack bool, emitRight func(isRef bool)) {
   431  	e.addSrcMap()
   432  	c := e.c
   433  
   434  	if b, noDynamics := c.scope.lookupName(e.name); noDynamics {
   435  		if c.scope.strict {
   436  			c.checkIdentifierLName(e.name, e.offset)
   437  		}
   438  		emitRight(false)
   439  		if b != nil {
   440  			if putOnStack {
   441  				b.emitSet()
   442  			} else {
   443  				b.emitSetP()
   444  			}
   445  		} else {
   446  			if c.scope.strict {
   447  				c.emit(setGlobalStrict(e.name))
   448  			} else {
   449  				c.emit(setGlobal(e.name))
   450  			}
   451  			if !putOnStack {
   452  				c.emit(pop)
   453  			}
   454  		}
   455  	} else {
   456  		c.emitVarRef(e.name, e.offset, b)
   457  		emitRight(true)
   458  		if putOnStack {
   459  			c.emit(putValue)
   460  		} else {
   461  			c.emit(putValueP)
   462  		}
   463  	}
   464  }
   465  
   466  func (e *compiledIdentifierExpr) emitVarSetter(valueExpr compiledExpr, putOnStack bool) {
   467  	e.emitVarSetter1(putOnStack, func(bool) {
   468  		e.c.emitNamedOrConst(valueExpr, e.name)
   469  	})
   470  }
   471  
   472  func (c *compiler) emitVarRef(name unistring.String, offset int, b *binding) {
   473  	if c.scope.strict {
   474  		c.checkIdentifierLName(name, offset)
   475  	}
   476  
   477  	if b != nil {
   478  		b.emitResolveVar(c.scope.strict)
   479  	} else {
   480  		if c.scope.strict {
   481  			c.emit(resolveVar1Strict(name))
   482  		} else {
   483  			c.emit(resolveVar1(name))
   484  		}
   485  	}
   486  }
   487  
   488  func (e *compiledIdentifierExpr) emitRef() {
   489  	b, _ := e.c.scope.lookupName(e.name)
   490  	e.c.emitVarRef(e.name, e.offset, b)
   491  }
   492  
   493  func (e *compiledIdentifierExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) {
   494  	e.emitVarSetter(valueExpr, putOnStack)
   495  }
   496  
   497  func (e *compiledIdentifierExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) {
   498  	if putOnStack {
   499  		e.emitVarSetter1(true, func(isRef bool) {
   500  			e.c.emit(loadUndef)
   501  			if isRef {
   502  				e.c.emit(getValue)
   503  			} else {
   504  				e.emitGetter(true)
   505  			}
   506  			if prepare != nil {
   507  				prepare()
   508  			}
   509  			if !postfix {
   510  				body()
   511  			}
   512  			e.c.emit(rdupN(1))
   513  			if postfix {
   514  				body()
   515  			}
   516  		})
   517  		e.c.emit(pop)
   518  	} else {
   519  		e.emitVarSetter1(false, func(isRef bool) {
   520  			if isRef {
   521  				e.c.emit(getValue)
   522  			} else {
   523  				e.emitGetter(true)
   524  			}
   525  			body()
   526  		})
   527  	}
   528  }
   529  
   530  func (e *compiledIdentifierExpr) deleteExpr() compiledExpr {
   531  	if e.c.scope.strict {
   532  		e.c.throwSyntaxError(e.offset, "Delete of an unqualified identifier in strict mode")
   533  		panic("Unreachable")
   534  	}
   535  	if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics {
   536  		if b == nil {
   537  			r := &deleteGlobalExpr{
   538  				name: e.name,
   539  			}
   540  			r.init(e.c, file.Idx(0))
   541  			return r
   542  		}
   543  	} else {
   544  		if b == nil {
   545  			r := &deleteVarExpr{
   546  				name: e.name,
   547  			}
   548  			r.init(e.c, file.Idx(e.offset+1))
   549  			return r
   550  		}
   551  	}
   552  	r := &compiledLiteral{
   553  		val: valueFalse,
   554  	}
   555  	r.init(e.c, file.Idx(e.offset+1))
   556  	return r
   557  }
   558  
   559  type compiledSuperDotExpr struct {
   560  	baseCompiledExpr
   561  	name unistring.String
   562  }
   563  
   564  func (e *compiledSuperDotExpr) emitGetter(putOnStack bool) {
   565  	e.c.emitLoadThis()
   566  	e.c.emit(loadSuper)
   567  	e.addSrcMap()
   568  	e.c.emit(getPropRecv(e.name))
   569  	if !putOnStack {
   570  		e.c.emit(pop)
   571  	}
   572  }
   573  
   574  func (e *compiledSuperDotExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) {
   575  	e.c.emitLoadThis()
   576  	e.c.emit(loadSuper)
   577  	valueExpr.emitGetter(true)
   578  	e.addSrcMap()
   579  	if putOnStack {
   580  		if e.c.scope.strict {
   581  			e.c.emit(setPropRecvStrict(e.name))
   582  		} else {
   583  			e.c.emit(setPropRecv(e.name))
   584  		}
   585  	} else {
   586  		if e.c.scope.strict {
   587  			e.c.emit(setPropRecvStrictP(e.name))
   588  		} else {
   589  			e.c.emit(setPropRecvP(e.name))
   590  		}
   591  	}
   592  }
   593  
   594  func (e *compiledSuperDotExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) {
   595  	if !putOnStack {
   596  		e.c.emitLoadThis()
   597  		e.c.emit(loadSuper, dupLast(2), getPropRecv(e.name))
   598  		body()
   599  		e.addSrcMap()
   600  		if e.c.scope.strict {
   601  			e.c.emit(setPropRecvStrictP(e.name))
   602  		} else {
   603  			e.c.emit(setPropRecvP(e.name))
   604  		}
   605  	} else {
   606  		if !postfix {
   607  			e.c.emitLoadThis()
   608  			e.c.emit(loadSuper, dupLast(2), getPropRecv(e.name))
   609  			if prepare != nil {
   610  				prepare()
   611  			}
   612  			body()
   613  			e.addSrcMap()
   614  			if e.c.scope.strict {
   615  				e.c.emit(setPropRecvStrict(e.name))
   616  			} else {
   617  				e.c.emit(setPropRecv(e.name))
   618  			}
   619  		} else {
   620  			e.c.emit(loadUndef)
   621  			e.c.emitLoadThis()
   622  			e.c.emit(loadSuper, dupLast(2), getPropRecv(e.name))
   623  			if prepare != nil {
   624  				prepare()
   625  			}
   626  			e.c.emit(rdupN(3))
   627  			body()
   628  			e.addSrcMap()
   629  			if e.c.scope.strict {
   630  				e.c.emit(setPropRecvStrictP(e.name))
   631  			} else {
   632  				e.c.emit(setPropRecvP(e.name))
   633  			}
   634  		}
   635  	}
   636  }
   637  
   638  func (e *compiledSuperDotExpr) emitRef() {
   639  	e.c.emitLoadThis()
   640  	e.c.emit(loadSuper)
   641  	if e.c.scope.strict {
   642  		e.c.emit(getPropRefRecvStrict(e.name))
   643  	} else {
   644  		e.c.emit(getPropRefRecv(e.name))
   645  	}
   646  }
   647  
   648  func (e *compiledSuperDotExpr) deleteExpr() compiledExpr {
   649  	return e.c.superDeleteError(e.offset)
   650  }
   651  
   652  type compiledDotExpr struct {
   653  	baseCompiledExpr
   654  	left compiledExpr
   655  	name unistring.String
   656  }
   657  
   658  type compiledPrivateDotExpr struct {
   659  	baseCompiledExpr
   660  	left compiledExpr
   661  	name unistring.String
   662  }
   663  
   664  func (c *compiler) checkSuperBase(idx file.Idx) {
   665  	if s := c.scope.nearestThis(); s != nil {
   666  		switch s.funcType {
   667  		case funcMethod, funcClsInit, funcCtor, funcDerivedCtor:
   668  			return
   669  		}
   670  	}
   671  	c.throwSyntaxError(int(idx)-1, "'super' keyword unexpected here")
   672  	panic("unreachable")
   673  }
   674  
   675  func (c *compiler) compileDotExpression(v *ast.DotExpression) compiledExpr {
   676  	if sup, ok := v.Left.(*ast.SuperExpression); ok {
   677  		c.checkSuperBase(sup.Idx)
   678  		r := &compiledSuperDotExpr{
   679  			name: v.Identifier.Name,
   680  		}
   681  		r.init(c, v.Identifier.Idx)
   682  		return r
   683  	}
   684  
   685  	r := &compiledDotExpr{
   686  		left: c.compileExpression(v.Left),
   687  		name: v.Identifier.Name,
   688  	}
   689  	r.init(c, v.Identifier.Idx)
   690  	return r
   691  }
   692  
   693  func (c *compiler) compilePrivateDotExpression(v *ast.PrivateDotExpression) compiledExpr {
   694  	r := &compiledPrivateDotExpr{
   695  		left: c.compileExpression(v.Left),
   696  		name: v.Identifier.Name,
   697  	}
   698  	r.init(c, v.Identifier.Idx)
   699  	return r
   700  }
   701  
   702  func (e *compiledPrivateDotExpr) _emitGetter(rn *resolvedPrivateName, id *privateId) {
   703  	if rn != nil {
   704  		e.c.emit((*getPrivatePropRes)(rn))
   705  	} else {
   706  		e.c.emit((*getPrivatePropId)(id))
   707  	}
   708  }
   709  
   710  func (e *compiledPrivateDotExpr) _emitSetter(rn *resolvedPrivateName, id *privateId) {
   711  	if rn != nil {
   712  		e.c.emit((*setPrivatePropRes)(rn))
   713  	} else {
   714  		e.c.emit((*setPrivatePropId)(id))
   715  	}
   716  }
   717  
   718  func (e *compiledPrivateDotExpr) _emitSetterP(rn *resolvedPrivateName, id *privateId) {
   719  	if rn != nil {
   720  		e.c.emit((*setPrivatePropResP)(rn))
   721  	} else {
   722  		e.c.emit((*setPrivatePropIdP)(id))
   723  	}
   724  }
   725  
   726  func (e *compiledPrivateDotExpr) emitGetter(putOnStack bool) {
   727  	e.left.emitGetter(true)
   728  	e.addSrcMap()
   729  	rn, id := e.c.resolvePrivateName(e.name, e.offset)
   730  	e._emitGetter(rn, id)
   731  	if !putOnStack {
   732  		e.c.emit(pop)
   733  	}
   734  }
   735  
   736  func (e *compiledPrivateDotExpr) emitSetter(v compiledExpr, putOnStack bool) {
   737  	rn, id := e.c.resolvePrivateName(e.name, e.offset)
   738  	e.left.emitGetter(true)
   739  	v.emitGetter(true)
   740  	e.addSrcMap()
   741  	if putOnStack {
   742  		e._emitSetter(rn, id)
   743  	} else {
   744  		e._emitSetterP(rn, id)
   745  	}
   746  }
   747  
   748  func (e *compiledPrivateDotExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) {
   749  	rn, id := e.c.resolvePrivateName(e.name, e.offset)
   750  	if !putOnStack {
   751  		e.left.emitGetter(true)
   752  		e.c.emit(dup)
   753  		e._emitGetter(rn, id)
   754  		body()
   755  		e.addSrcMap()
   756  		e._emitSetterP(rn, id)
   757  	} else {
   758  		if !postfix {
   759  			e.left.emitGetter(true)
   760  			e.c.emit(dup)
   761  			e._emitGetter(rn, id)
   762  			if prepare != nil {
   763  				prepare()
   764  			}
   765  			body()
   766  			e.addSrcMap()
   767  			e._emitSetter(rn, id)
   768  		} else {
   769  			e.c.emit(loadUndef)
   770  			e.left.emitGetter(true)
   771  			e.c.emit(dup)
   772  			e._emitGetter(rn, id)
   773  			if prepare != nil {
   774  				prepare()
   775  			}
   776  			e.c.emit(rdupN(2))
   777  			body()
   778  			e.addSrcMap()
   779  			e._emitSetterP(rn, id)
   780  		}
   781  	}
   782  }
   783  
   784  func (e *compiledPrivateDotExpr) deleteExpr() compiledExpr {
   785  	e.c.throwSyntaxError(e.offset, "Private fields can not be deleted")
   786  	panic("unreachable")
   787  }
   788  
   789  func (e *compiledPrivateDotExpr) emitRef() {
   790  	e.left.emitGetter(true)
   791  	rn, id := e.c.resolvePrivateName(e.name, e.offset)
   792  	if rn != nil {
   793  		e.c.emit((*getPrivateRefRes)(rn))
   794  	} else {
   795  		e.c.emit((*getPrivateRefId)(id))
   796  	}
   797  }
   798  
   799  type compiledSuperBracketExpr struct {
   800  	baseCompiledExpr
   801  	member compiledExpr
   802  }
   803  
   804  func (e *compiledSuperBracketExpr) emitGetter(putOnStack bool) {
   805  	e.c.emitLoadThis()
   806  	e.member.emitGetter(true)
   807  	e.c.emit(loadSuper)
   808  	e.addSrcMap()
   809  	e.c.emit(getElemRecv)
   810  	if !putOnStack {
   811  		e.c.emit(pop)
   812  	}
   813  }
   814  
   815  func (e *compiledSuperBracketExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) {
   816  	e.c.emitLoadThis()
   817  	e.member.emitGetter(true)
   818  	e.c.emit(loadSuper)
   819  	valueExpr.emitGetter(true)
   820  	e.addSrcMap()
   821  	if putOnStack {
   822  		if e.c.scope.strict {
   823  			e.c.emit(setElemRecvStrict)
   824  		} else {
   825  			e.c.emit(setElemRecv)
   826  		}
   827  	} else {
   828  		if e.c.scope.strict {
   829  			e.c.emit(setElemRecvStrictP)
   830  		} else {
   831  			e.c.emit(setElemRecvP)
   832  		}
   833  	}
   834  }
   835  
   836  func (e *compiledSuperBracketExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) {
   837  	if !putOnStack {
   838  		e.c.emitLoadThis()
   839  		e.member.emitGetter(true)
   840  		e.c.emit(loadSuper, dupLast(3), getElemRecv)
   841  		body()
   842  		e.addSrcMap()
   843  		if e.c.scope.strict {
   844  			e.c.emit(setElemRecvStrictP)
   845  		} else {
   846  			e.c.emit(setElemRecvP)
   847  		}
   848  	} else {
   849  		if !postfix {
   850  			e.c.emitLoadThis()
   851  			e.member.emitGetter(true)
   852  			e.c.emit(loadSuper, dupLast(3), getElemRecv)
   853  			if prepare != nil {
   854  				prepare()
   855  			}
   856  			body()
   857  			e.addSrcMap()
   858  			if e.c.scope.strict {
   859  				e.c.emit(setElemRecvStrict)
   860  			} else {
   861  				e.c.emit(setElemRecv)
   862  			}
   863  		} else {
   864  			e.c.emit(loadUndef)
   865  			e.c.emitLoadThis()
   866  			e.member.emitGetter(true)
   867  			e.c.emit(loadSuper, dupLast(3), getElemRecv)
   868  			if prepare != nil {
   869  				prepare()
   870  			}
   871  			e.c.emit(rdupN(4))
   872  			body()
   873  			e.addSrcMap()
   874  			if e.c.scope.strict {
   875  				e.c.emit(setElemRecvStrictP)
   876  			} else {
   877  				e.c.emit(setElemRecvP)
   878  			}
   879  		}
   880  	}
   881  }
   882  
   883  func (e *compiledSuperBracketExpr) emitRef() {
   884  	e.c.emitLoadThis()
   885  	e.member.emitGetter(true)
   886  	e.c.emit(loadSuper)
   887  	if e.c.scope.strict {
   888  		e.c.emit(getElemRefRecvStrict)
   889  	} else {
   890  		e.c.emit(getElemRefRecv)
   891  	}
   892  }
   893  
   894  func (c *compiler) superDeleteError(offset int) compiledExpr {
   895  	return c.compileEmitterExpr(func() {
   896  		c.emit(throwConst{referenceError("Unsupported reference to 'super'")})
   897  	}, file.Idx(offset+1))
   898  }
   899  
   900  func (e *compiledSuperBracketExpr) deleteExpr() compiledExpr {
   901  	return e.c.superDeleteError(e.offset)
   902  }
   903  
   904  func (c *compiler) checkConstantString(expr compiledExpr) (unistring.String, bool) {
   905  	if expr.constant() {
   906  		if val, ex := c.evalConst(expr); ex == nil {
   907  			if s, ok := val.(String); ok {
   908  				return s.string(), true
   909  			}
   910  		}
   911  	}
   912  	return "", false
   913  }
   914  
   915  func (c *compiler) compileBracketExpression(v *ast.BracketExpression) compiledExpr {
   916  	if sup, ok := v.Left.(*ast.SuperExpression); ok {
   917  		c.checkSuperBase(sup.Idx)
   918  		member := c.compileExpression(v.Member)
   919  		if name, ok := c.checkConstantString(member); ok {
   920  			r := &compiledSuperDotExpr{
   921  				name: name,
   922  			}
   923  			r.init(c, v.LeftBracket)
   924  			return r
   925  		}
   926  
   927  		r := &compiledSuperBracketExpr{
   928  			member: member,
   929  		}
   930  		r.init(c, v.LeftBracket)
   931  		return r
   932  	}
   933  
   934  	left := c.compileExpression(v.Left)
   935  	member := c.compileExpression(v.Member)
   936  	if name, ok := c.checkConstantString(member); ok {
   937  		r := &compiledDotExpr{
   938  			left: left,
   939  			name: name,
   940  		}
   941  		r.init(c, v.LeftBracket)
   942  		return r
   943  	}
   944  
   945  	r := &compiledBracketExpr{
   946  		left:   left,
   947  		member: member,
   948  	}
   949  	r.init(c, v.LeftBracket)
   950  	return r
   951  }
   952  
   953  func (e *compiledDotExpr) emitGetter(putOnStack bool) {
   954  	e.left.emitGetter(true)
   955  	e.addSrcMap()
   956  	e.c.emit(getProp(e.name))
   957  	if !putOnStack {
   958  		e.c.emit(pop)
   959  	}
   960  }
   961  
   962  func (e *compiledDotExpr) emitRef() {
   963  	e.left.emitGetter(true)
   964  	if e.c.scope.strict {
   965  		e.c.emit(getPropRefStrict(e.name))
   966  	} else {
   967  		e.c.emit(getPropRef(e.name))
   968  	}
   969  }
   970  
   971  func (e *compiledDotExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) {
   972  	e.left.emitGetter(true)
   973  	valueExpr.emitGetter(true)
   974  	e.addSrcMap()
   975  	if e.c.scope.strict {
   976  		if putOnStack {
   977  			e.c.emit(setPropStrict(e.name))
   978  		} else {
   979  			e.c.emit(setPropStrictP(e.name))
   980  		}
   981  	} else {
   982  		if putOnStack {
   983  			e.c.emit(setProp(e.name))
   984  		} else {
   985  			e.c.emit(setPropP(e.name))
   986  		}
   987  	}
   988  }
   989  
   990  func (e *compiledDotExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) {
   991  	if !putOnStack {
   992  		e.left.emitGetter(true)
   993  		e.c.emit(dup)
   994  		e.c.emit(getProp(e.name))
   995  		body()
   996  		e.addSrcMap()
   997  		if e.c.scope.strict {
   998  			e.c.emit(setPropStrictP(e.name))
   999  		} else {
  1000  			e.c.emit(setPropP(e.name))
  1001  		}
  1002  	} else {
  1003  		if !postfix {
  1004  			e.left.emitGetter(true)
  1005  			e.c.emit(dup)
  1006  			e.c.emit(getProp(e.name))
  1007  			if prepare != nil {
  1008  				prepare()
  1009  			}
  1010  			body()
  1011  			e.addSrcMap()
  1012  			if e.c.scope.strict {
  1013  				e.c.emit(setPropStrict(e.name))
  1014  			} else {
  1015  				e.c.emit(setProp(e.name))
  1016  			}
  1017  		} else {
  1018  			e.c.emit(loadUndef)
  1019  			e.left.emitGetter(true)
  1020  			e.c.emit(dup)
  1021  			e.c.emit(getProp(e.name))
  1022  			if prepare != nil {
  1023  				prepare()
  1024  			}
  1025  			e.c.emit(rdupN(2))
  1026  			body()
  1027  			e.addSrcMap()
  1028  			if e.c.scope.strict {
  1029  				e.c.emit(setPropStrictP(e.name))
  1030  			} else {
  1031  				e.c.emit(setPropP(e.name))
  1032  			}
  1033  		}
  1034  	}
  1035  }
  1036  
  1037  func (e *compiledDotExpr) deleteExpr() compiledExpr {
  1038  	r := &deletePropExpr{
  1039  		left: e.left,
  1040  		name: e.name,
  1041  	}
  1042  	r.init(e.c, file.Idx(e.offset)+1)
  1043  	return r
  1044  }
  1045  
  1046  func (e *compiledBracketExpr) emitGetter(putOnStack bool) {
  1047  	e.left.emitGetter(true)
  1048  	e.member.emitGetter(true)
  1049  	e.addSrcMap()
  1050  	e.c.emit(getElem)
  1051  	if !putOnStack {
  1052  		e.c.emit(pop)
  1053  	}
  1054  }
  1055  
  1056  func (e *compiledBracketExpr) emitRef() {
  1057  	e.left.emitGetter(true)
  1058  	e.member.emitGetter(true)
  1059  	if e.c.scope.strict {
  1060  		e.c.emit(getElemRefStrict)
  1061  	} else {
  1062  		e.c.emit(getElemRef)
  1063  	}
  1064  }
  1065  
  1066  func (e *compiledBracketExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) {
  1067  	e.left.emitGetter(true)
  1068  	e.member.emitGetter(true)
  1069  	valueExpr.emitGetter(true)
  1070  	e.addSrcMap()
  1071  	if e.c.scope.strict {
  1072  		if putOnStack {
  1073  			e.c.emit(setElemStrict)
  1074  		} else {
  1075  			e.c.emit(setElemStrictP)
  1076  		}
  1077  	} else {
  1078  		if putOnStack {
  1079  			e.c.emit(setElem)
  1080  		} else {
  1081  			e.c.emit(setElemP)
  1082  		}
  1083  	}
  1084  }
  1085  
  1086  func (e *compiledBracketExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) {
  1087  	if !putOnStack {
  1088  		e.left.emitGetter(true)
  1089  		e.member.emitGetter(true)
  1090  		e.c.emit(dupLast(2), getElem)
  1091  		body()
  1092  		e.addSrcMap()
  1093  		if e.c.scope.strict {
  1094  			e.c.emit(setElemStrict, pop)
  1095  		} else {
  1096  			e.c.emit(setElem, pop)
  1097  		}
  1098  	} else {
  1099  		if !postfix {
  1100  			e.left.emitGetter(true)
  1101  			e.member.emitGetter(true)
  1102  			e.c.emit(dupLast(2), getElem)
  1103  			if prepare != nil {
  1104  				prepare()
  1105  			}
  1106  			body()
  1107  			e.addSrcMap()
  1108  			if e.c.scope.strict {
  1109  				e.c.emit(setElemStrict)
  1110  			} else {
  1111  				e.c.emit(setElem)
  1112  			}
  1113  		} else {
  1114  			e.c.emit(loadUndef)
  1115  			e.left.emitGetter(true)
  1116  			e.member.emitGetter(true)
  1117  			e.c.emit(dupLast(2), getElem)
  1118  			if prepare != nil {
  1119  				prepare()
  1120  			}
  1121  			e.c.emit(rdupN(3))
  1122  			body()
  1123  			e.addSrcMap()
  1124  			if e.c.scope.strict {
  1125  				e.c.emit(setElemStrict, pop)
  1126  			} else {
  1127  				e.c.emit(setElem, pop)
  1128  			}
  1129  		}
  1130  	}
  1131  }
  1132  
  1133  func (e *compiledBracketExpr) deleteExpr() compiledExpr {
  1134  	r := &deleteElemExpr{
  1135  		left:   e.left,
  1136  		member: e.member,
  1137  	}
  1138  	r.init(e.c, file.Idx(e.offset)+1)
  1139  	return r
  1140  }
  1141  
  1142  func (e *deleteElemExpr) emitGetter(putOnStack bool) {
  1143  	e.left.emitGetter(true)
  1144  	e.member.emitGetter(true)
  1145  	e.addSrcMap()
  1146  	if e.c.scope.strict {
  1147  		e.c.emit(deleteElemStrict)
  1148  	} else {
  1149  		e.c.emit(deleteElem)
  1150  	}
  1151  	if !putOnStack {
  1152  		e.c.emit(pop)
  1153  	}
  1154  }
  1155  
  1156  func (e *deletePropExpr) emitGetter(putOnStack bool) {
  1157  	e.left.emitGetter(true)
  1158  	e.addSrcMap()
  1159  	if e.c.scope.strict {
  1160  		e.c.emit(deletePropStrict(e.name))
  1161  	} else {
  1162  		e.c.emit(deleteProp(e.name))
  1163  	}
  1164  	if !putOnStack {
  1165  		e.c.emit(pop)
  1166  	}
  1167  }
  1168  
  1169  func (e *deleteVarExpr) emitGetter(putOnStack bool) {
  1170  	/*if e.c.scope.strict {
  1171  		e.c.throwSyntaxError(e.offset, "Delete of an unqualified identifier in strict mode")
  1172  		return
  1173  	}*/
  1174  	e.c.emit(deleteVar(e.name))
  1175  	if !putOnStack {
  1176  		e.c.emit(pop)
  1177  	}
  1178  }
  1179  
  1180  func (e *deleteGlobalExpr) emitGetter(putOnStack bool) {
  1181  	/*if e.c.scope.strict {
  1182  		e.c.throwSyntaxError(e.offset, "Delete of an unqualified identifier in strict mode")
  1183  		return
  1184  	}*/
  1185  
  1186  	e.c.emit(deleteGlobal(e.name))
  1187  	if !putOnStack {
  1188  		e.c.emit(pop)
  1189  	}
  1190  }
  1191  
  1192  func (e *compiledAssignExpr) emitGetter(putOnStack bool) {
  1193  	switch e.operator {
  1194  	case token.ASSIGN:
  1195  		e.left.emitSetter(e.right, putOnStack)
  1196  	case token.PLUS:
  1197  		e.left.emitUnary(nil, func() {
  1198  			e.right.emitGetter(true)
  1199  			e.c.emit(add)
  1200  		}, false, putOnStack)
  1201  	case token.MINUS:
  1202  		e.left.emitUnary(nil, func() {
  1203  			e.right.emitGetter(true)
  1204  			e.c.emit(sub)
  1205  		}, false, putOnStack)
  1206  	case token.MULTIPLY:
  1207  		e.left.emitUnary(nil, func() {
  1208  			e.right.emitGetter(true)
  1209  			e.c.emit(mul)
  1210  		}, false, putOnStack)
  1211  	case token.EXPONENT:
  1212  		e.left.emitUnary(nil, func() {
  1213  			e.right.emitGetter(true)
  1214  			e.c.emit(exp)
  1215  		}, false, putOnStack)
  1216  	case token.SLASH:
  1217  		e.left.emitUnary(nil, func() {
  1218  			e.right.emitGetter(true)
  1219  			e.c.emit(div)
  1220  		}, false, putOnStack)
  1221  	case token.REMAINDER:
  1222  		e.left.emitUnary(nil, func() {
  1223  			e.right.emitGetter(true)
  1224  			e.c.emit(mod)
  1225  		}, false, putOnStack)
  1226  	case token.OR:
  1227  		e.left.emitUnary(nil, func() {
  1228  			e.right.emitGetter(true)
  1229  			e.c.emit(or)
  1230  		}, false, putOnStack)
  1231  	case token.AND:
  1232  		e.left.emitUnary(nil, func() {
  1233  			e.right.emitGetter(true)
  1234  			e.c.emit(and)
  1235  		}, false, putOnStack)
  1236  	case token.EXCLUSIVE_OR:
  1237  		e.left.emitUnary(nil, func() {
  1238  			e.right.emitGetter(true)
  1239  			e.c.emit(xor)
  1240  		}, false, putOnStack)
  1241  	case token.SHIFT_LEFT:
  1242  		e.left.emitUnary(nil, func() {
  1243  			e.right.emitGetter(true)
  1244  			e.c.emit(sal)
  1245  		}, false, putOnStack)
  1246  	case token.SHIFT_RIGHT:
  1247  		e.left.emitUnary(nil, func() {
  1248  			e.right.emitGetter(true)
  1249  			e.c.emit(sar)
  1250  		}, false, putOnStack)
  1251  	case token.UNSIGNED_SHIFT_RIGHT:
  1252  		e.left.emitUnary(nil, func() {
  1253  			e.right.emitGetter(true)
  1254  			e.c.emit(shr)
  1255  		}, false, putOnStack)
  1256  	default:
  1257  		e.c.assert(false, e.offset, "Unknown assign operator: %s", e.operator.String())
  1258  		panic("unreachable")
  1259  	}
  1260  }
  1261  
  1262  func (e *compiledLiteral) emitGetter(putOnStack bool) {
  1263  	if putOnStack {
  1264  		e.c.emit(loadVal(e.c.p.defineLiteralValue(e.val)))
  1265  	}
  1266  }
  1267  
  1268  func (e *compiledLiteral) constant() bool {
  1269  	return true
  1270  }
  1271  
  1272  func (e *compiledTemplateLiteral) emitGetter(putOnStack bool) {
  1273  	if e.tag == nil {
  1274  		if len(e.elements) == 0 {
  1275  			e.c.emit(loadVal(e.c.p.defineLiteralValue(stringEmpty)))
  1276  		} else {
  1277  			tail := e.elements[len(e.elements)-1].Parsed
  1278  			if len(e.elements) == 1 {
  1279  				e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(tail))))
  1280  			} else {
  1281  				stringCount := 0
  1282  				if head := e.elements[0].Parsed; head != "" {
  1283  					e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(head))))
  1284  					stringCount++
  1285  				}
  1286  				e.expressions[0].emitGetter(true)
  1287  				e.c.emit(_toString{})
  1288  				stringCount++
  1289  				for i := 1; i < len(e.elements)-1; i++ {
  1290  					if elt := e.elements[i].Parsed; elt != "" {
  1291  						e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(elt))))
  1292  						stringCount++
  1293  					}
  1294  					e.expressions[i].emitGetter(true)
  1295  					e.c.emit(_toString{})
  1296  					stringCount++
  1297  				}
  1298  				if tail != "" {
  1299  					e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(tail))))
  1300  					stringCount++
  1301  				}
  1302  				e.c.emit(concatStrings(stringCount))
  1303  			}
  1304  		}
  1305  	} else {
  1306  		cooked := make([]Value, len(e.elements))
  1307  		raw := make([]Value, len(e.elements))
  1308  		for i, elt := range e.elements {
  1309  			raw[i] = &valueProperty{
  1310  				enumerable: true,
  1311  				value:      newStringValue(elt.Literal),
  1312  			}
  1313  			var cookedVal Value
  1314  			if elt.Valid {
  1315  				cookedVal = stringValueFromRaw(elt.Parsed)
  1316  			} else {
  1317  				cookedVal = _undefined
  1318  			}
  1319  			cooked[i] = &valueProperty{
  1320  				enumerable: true,
  1321  				value:      cookedVal,
  1322  			}
  1323  		}
  1324  		e.c.emitCallee(e.tag)
  1325  		e.c.emit(&getTaggedTmplObject{
  1326  			raw:    raw,
  1327  			cooked: cooked,
  1328  		})
  1329  		for _, expr := range e.expressions {
  1330  			expr.emitGetter(true)
  1331  		}
  1332  		e.c.emit(call(len(e.expressions) + 1))
  1333  	}
  1334  	if !putOnStack {
  1335  		e.c.emit(pop)
  1336  	}
  1337  }
  1338  
  1339  func (c *compiler) compileParameterBindingIdentifier(name unistring.String, offset int) (*binding, bool) {
  1340  	if c.scope.strict {
  1341  		c.checkIdentifierName(name, offset)
  1342  		c.checkIdentifierLName(name, offset)
  1343  	}
  1344  	return c.scope.bindNameShadow(name)
  1345  }
  1346  
  1347  func (c *compiler) compileParameterPatternIdBinding(name unistring.String, offset int) {
  1348  	if _, unique := c.compileParameterBindingIdentifier(name, offset); !unique {
  1349  		c.throwSyntaxError(offset, "Duplicate parameter name not allowed in this context")
  1350  	}
  1351  }
  1352  
  1353  func (c *compiler) compileParameterPatternBinding(item ast.Expression) {
  1354  	c.createBindings(item, c.compileParameterPatternIdBinding)
  1355  }
  1356  
  1357  func (c *compiler) newCode(length, minCap int) (buf []instruction) {
  1358  	if c.codeScratchpad != nil {
  1359  		buf = c.codeScratchpad
  1360  		c.codeScratchpad = nil
  1361  	}
  1362  	if cap(buf) < minCap {
  1363  		buf = make([]instruction, length, minCap)
  1364  	} else {
  1365  		buf = buf[:length]
  1366  	}
  1367  	return
  1368  }
  1369  
  1370  func (e *compiledFunctionLiteral) compile() (prg *Program, name unistring.String, length int, strict bool) {
  1371  	e.c.assert(e.typ != funcNone, e.offset, "compiledFunctionLiteral.typ is not set")
  1372  
  1373  	savedPrg := e.c.p
  1374  	preambleLen := 8 // enter, boxThis, loadStack(0), initThis, createArgs, set, loadCallee, init
  1375  	e.c.p = &Program{
  1376  		src:    e.c.p.src,
  1377  		code:   e.c.newCode(preambleLen, 16),
  1378  		srcMap: []srcMapItem{{srcPos: e.offset}},
  1379  	}
  1380  	e.c.newScope()
  1381  	s := e.c.scope
  1382  	s.funcType = e.typ
  1383  
  1384  	if e.name != nil {
  1385  		name = e.name.Name
  1386  	} else {
  1387  		name = e.lhsName
  1388  	}
  1389  
  1390  	if name != "" {
  1391  		e.c.p.funcName = name
  1392  	}
  1393  	savedBlock := e.c.block
  1394  	defer func() {
  1395  		e.c.block = savedBlock
  1396  	}()
  1397  
  1398  	e.c.block = &block{
  1399  		typ: blockScope,
  1400  	}
  1401  
  1402  	if !s.strict {
  1403  		s.strict = e.strict != nil
  1404  	}
  1405  
  1406  	hasPatterns := false
  1407  	hasInits := false
  1408  	firstDupIdx := -1
  1409  
  1410  	if e.parameterList.Rest != nil {
  1411  		hasPatterns = true // strictly speaking not, but we need to activate all the checks
  1412  	}
  1413  
  1414  	// First, make sure that the first bindings correspond to the formal parameters
  1415  	for _, item := range e.parameterList.List {
  1416  		switch tgt := item.Target.(type) {
  1417  		case *ast.Identifier:
  1418  			offset := int(tgt.Idx) - 1
  1419  			b, unique := e.c.compileParameterBindingIdentifier(tgt.Name, offset)
  1420  			if !unique {
  1421  				firstDupIdx = offset
  1422  			}
  1423  			b.isArg = true
  1424  		case ast.Pattern:
  1425  			b := s.addBinding(int(item.Idx0()) - 1)
  1426  			b.isArg = true
  1427  			hasPatterns = true
  1428  		default:
  1429  			e.c.throwSyntaxError(int(item.Idx0())-1, "Unsupported BindingElement type: %T", item)
  1430  			return
  1431  		}
  1432  		if item.Initializer != nil {
  1433  			hasInits = true
  1434  		}
  1435  
  1436  		if firstDupIdx >= 0 && (hasPatterns || hasInits || s.strict || e.typ == funcArrow || e.typ == funcMethod) {
  1437  			e.c.throwSyntaxError(firstDupIdx, "Duplicate parameter name not allowed in this context")
  1438  			return
  1439  		}
  1440  
  1441  		if (hasPatterns || hasInits) && e.strict != nil {
  1442  			e.c.throwSyntaxError(int(e.strict.Idx)-1, "Illegal 'use strict' directive in function with non-simple parameter list")
  1443  			return
  1444  		}
  1445  
  1446  		if !hasInits {
  1447  			length++
  1448  		}
  1449  	}
  1450  
  1451  	var thisBinding *binding
  1452  	if e.typ != funcArrow {
  1453  		thisBinding = s.createThisBinding()
  1454  	}
  1455  
  1456  	// create pattern bindings
  1457  	if hasPatterns {
  1458  		for _, item := range e.parameterList.List {
  1459  			switch tgt := item.Target.(type) {
  1460  			case *ast.Identifier:
  1461  				// we already created those in the previous loop, skipping
  1462  			default:
  1463  				e.c.compileParameterPatternBinding(tgt)
  1464  			}
  1465  		}
  1466  		if rest := e.parameterList.Rest; rest != nil {
  1467  			e.c.compileParameterPatternBinding(rest)
  1468  		}
  1469  	}
  1470  
  1471  	paramsCount := len(e.parameterList.List)
  1472  
  1473  	s.numArgs = paramsCount
  1474  	body := e.body
  1475  	funcs := e.c.extractFunctions(body)
  1476  	var calleeBinding *binding
  1477  
  1478  	emitArgsRestMark := -1
  1479  	firstForwardRef := -1
  1480  	enterFunc2Mark := -1
  1481  
  1482  	if hasPatterns || hasInits {
  1483  		if e.isExpr && e.name != nil {
  1484  			if b, created := s.bindNameLexical(e.name.Name, false, 0); created {
  1485  				b.isConst = true
  1486  				calleeBinding = b
  1487  			}
  1488  		}
  1489  		for i, item := range e.parameterList.List {
  1490  			if pattern, ok := item.Target.(ast.Pattern); ok {
  1491  				i := i
  1492  				e.c.compilePatternInitExpr(func() {
  1493  					if firstForwardRef == -1 {
  1494  						s.bindings[i].emitGet()
  1495  					} else {
  1496  						e.c.emit(loadStackLex(-i - 1))
  1497  					}
  1498  				}, item.Initializer, item.Target.Idx0()).emitGetter(true)
  1499  				e.c.emitPattern(pattern, func(target, init compiledExpr) {
  1500  					e.c.emitPatternLexicalAssign(target, init)
  1501  				}, false)
  1502  			} else if item.Initializer != nil {
  1503  				markGet := len(e.c.p.code)
  1504  				e.c.emit(nil)
  1505  				mark := len(e.c.p.code)
  1506  				e.c.emit(nil)
  1507  				e.c.emitExpr(e.c.compileExpression(item.Initializer), true)
  1508  				if firstForwardRef == -1 && (s.isDynamic() || s.bindings[i].useCount() > 0) {
  1509  					firstForwardRef = i
  1510  				}
  1511  				if firstForwardRef == -1 {
  1512  					s.bindings[i].emitGetAt(markGet)
  1513  				} else {
  1514  					e.c.p.code[markGet] = loadStackLex(-i - 1)
  1515  				}
  1516  				s.bindings[i].emitInitP()
  1517  				e.c.p.code[mark] = jdefP(len(e.c.p.code) - mark)
  1518  			} else {
  1519  				if firstForwardRef == -1 && s.bindings[i].useCount() > 0 {
  1520  					firstForwardRef = i
  1521  				}
  1522  				if firstForwardRef != -1 {
  1523  					e.c.emit(loadStackLex(-i - 1))
  1524  					s.bindings[i].emitInitP()
  1525  				}
  1526  			}
  1527  		}
  1528  		if rest := e.parameterList.Rest; rest != nil {
  1529  			e.c.emitAssign(rest, e.c.compileEmitterExpr(
  1530  				func() {
  1531  					emitArgsRestMark = len(e.c.p.code)
  1532  					e.c.emit(createArgsRestStack(paramsCount))
  1533  				}, rest.Idx0()),
  1534  				func(target, init compiledExpr) {
  1535  					e.c.emitPatternLexicalAssign(target, init)
  1536  				})
  1537  		}
  1538  		if firstForwardRef != -1 {
  1539  			for _, b := range s.bindings {
  1540  				b.inStash = true
  1541  			}
  1542  			s.argsInStash = true
  1543  			s.needStash = true
  1544  		}
  1545  
  1546  		e.c.newBlockScope()
  1547  		varScope := e.c.scope
  1548  		varScope.variable = true
  1549  		enterFunc2Mark = len(e.c.p.code)
  1550  		e.c.emit(nil)
  1551  		e.c.compileDeclList(e.declarationList, false)
  1552  		e.c.createFunctionBindings(funcs)
  1553  		e.c.compileLexicalDeclarationsFuncBody(body, calleeBinding)
  1554  		for _, b := range varScope.bindings {
  1555  			if b.isVar {
  1556  				if parentBinding := s.boundNames[b.name]; parentBinding != nil && parentBinding != calleeBinding {
  1557  					parentBinding.emitGet()
  1558  					b.emitSetP()
  1559  				}
  1560  			}
  1561  		}
  1562  	} else {
  1563  		// To avoid triggering variable conflict when binding from non-strict direct eval().
  1564  		// Parameters are supposed to be in a parent scope, hence no conflict.
  1565  		for _, b := range s.bindings[:paramsCount] {
  1566  			b.isVar = true
  1567  		}
  1568  		e.c.compileDeclList(e.declarationList, true)
  1569  		e.c.createFunctionBindings(funcs)
  1570  		e.c.compileLexicalDeclarations(body, true)
  1571  		if e.isExpr && e.name != nil {
  1572  			if b, created := s.bindNameLexical(e.name.Name, false, 0); created {
  1573  				b.isConst = true
  1574  				calleeBinding = b
  1575  			}
  1576  		}
  1577  		if calleeBinding != nil {
  1578  			e.c.emit(loadCallee)
  1579  			calleeBinding.emitInitP()
  1580  		}
  1581  	}
  1582  
  1583  	e.c.compileFunctions(funcs)
  1584  	if e.isGenerator {
  1585  		e.c.emit(yieldEmpty)
  1586  	}
  1587  	e.c.compileStatements(body, false)
  1588  
  1589  	var last ast.Statement
  1590  	if l := len(body); l > 0 {
  1591  		last = body[l-1]
  1592  	}
  1593  	if _, ok := last.(*ast.ReturnStatement); !ok {
  1594  		if e.typ == funcDerivedCtor {
  1595  			e.c.emit(loadUndef)
  1596  			thisBinding.markAccessPoint()
  1597  			e.c.emit(ret)
  1598  		} else {
  1599  			e.c.emit(loadUndef, ret)
  1600  		}
  1601  	}
  1602  
  1603  	delta := 0
  1604  	code := e.c.p.code
  1605  
  1606  	if s.isDynamic() && !s.argsInStash {
  1607  		s.moveArgsToStash()
  1608  	}
  1609  
  1610  	if s.argsNeeded || s.isDynamic() && e.typ != funcArrow && e.typ != funcClsInit {
  1611  		if e.typ == funcClsInit {
  1612  			e.c.throwSyntaxError(e.offset, "'arguments' is not allowed in class field initializer or static initialization block")
  1613  		}
  1614  		b, created := s.bindNameLexical("arguments", false, 0)
  1615  		if created || b.isVar {
  1616  			if !s.argsInStash {
  1617  				s.moveArgsToStash()
  1618  			}
  1619  			if s.strict {
  1620  				b.isConst = true
  1621  			} else {
  1622  				b.isVar = e.c.scope.isFunction()
  1623  			}
  1624  			pos := preambleLen - 2
  1625  			delta += 2
  1626  			if s.strict || hasPatterns || hasInits {
  1627  				code[pos] = createArgsUnmapped(paramsCount)
  1628  			} else {
  1629  				code[pos] = createArgsMapped(paramsCount)
  1630  			}
  1631  			pos++
  1632  			b.emitInitPAtScope(s, pos)
  1633  		}
  1634  	}
  1635  
  1636  	if calleeBinding != nil {
  1637  		if !s.isDynamic() && calleeBinding.useCount() == 0 {
  1638  			s.deleteBinding(calleeBinding)
  1639  			calleeBinding = nil
  1640  		} else {
  1641  			delta++
  1642  			calleeBinding.emitInitPAtScope(s, preambleLen-delta)
  1643  			delta++
  1644  			code[preambleLen-delta] = loadCallee
  1645  		}
  1646  	}
  1647  
  1648  	if thisBinding != nil {
  1649  		if !s.isDynamic() && thisBinding.useCount() == 0 {
  1650  			s.deleteBinding(thisBinding)
  1651  			thisBinding = nil
  1652  		} else {
  1653  			if thisBinding.inStash || s.isDynamic() {
  1654  				delta++
  1655  				thisBinding.emitInitAtScope(s, preambleLen-delta)
  1656  			}
  1657  		}
  1658  	}
  1659  
  1660  	stashSize, stackSize := s.finaliseVarAlloc(0)
  1661  
  1662  	if thisBinding != nil && thisBinding.inStash && (!s.argsInStash || stackSize > 0) {
  1663  		delta++
  1664  		code[preambleLen-delta] = loadStack(0)
  1665  	} // otherwise, 'this' will be at stack[sp-1], no need to load
  1666  
  1667  	if !s.strict && thisBinding != nil {
  1668  		delta++
  1669  		code[preambleLen-delta] = boxThis
  1670  	}
  1671  	delta++
  1672  	delta = preambleLen - delta
  1673  	var enter instruction
  1674  	if stashSize > 0 || s.argsInStash {
  1675  		if firstForwardRef == -1 {
  1676  			enter1 := enterFunc{
  1677  				numArgs:     uint32(paramsCount),
  1678  				argsToStash: s.argsInStash,
  1679  				stashSize:   uint32(stashSize),
  1680  				stackSize:   uint32(stackSize),
  1681  				extensible:  s.dynamic,
  1682  				funcType:    e.typ,
  1683  			}
  1684  			if s.isDynamic() {
  1685  				enter1.names = s.makeNamesMap()
  1686  			}
  1687  			enter = &enter1
  1688  			if enterFunc2Mark != -1 {
  1689  				ef2 := &enterFuncBody{
  1690  					extensible: e.c.scope.dynamic,
  1691  					funcType:   e.typ,
  1692  				}
  1693  				e.c.updateEnterBlock(&ef2.enterBlock)
  1694  				e.c.p.code[enterFunc2Mark] = ef2
  1695  			}
  1696  		} else {
  1697  			enter1 := enterFunc1{
  1698  				stashSize:  uint32(stashSize),
  1699  				numArgs:    uint32(paramsCount),
  1700  				argsToCopy: uint32(firstForwardRef),
  1701  				extensible: s.dynamic,
  1702  				funcType:   e.typ,
  1703  			}
  1704  			if s.isDynamic() {
  1705  				enter1.names = s.makeNamesMap()
  1706  			}
  1707  			enter = &enter1
  1708  			if enterFunc2Mark != -1 {
  1709  				ef2 := &enterFuncBody{
  1710  					adjustStack: true,
  1711  					extensible:  e.c.scope.dynamic,
  1712  					funcType:    e.typ,
  1713  				}
  1714  				e.c.updateEnterBlock(&ef2.enterBlock)
  1715  				e.c.p.code[enterFunc2Mark] = ef2
  1716  			}
  1717  		}
  1718  		if emitArgsRestMark != -1 && s.argsInStash {
  1719  			e.c.p.code[emitArgsRestMark] = createArgsRestStash
  1720  		}
  1721  	} else {
  1722  		enter = &enterFuncStashless{
  1723  			stackSize: uint32(stackSize),
  1724  			args:      uint32(paramsCount),
  1725  		}
  1726  		if enterFunc2Mark != -1 {
  1727  			ef2 := &enterFuncBody{
  1728  				extensible: e.c.scope.dynamic,
  1729  				funcType:   e.typ,
  1730  			}
  1731  			e.c.updateEnterBlock(&ef2.enterBlock)
  1732  			e.c.p.code[enterFunc2Mark] = ef2
  1733  		}
  1734  	}
  1735  	code[delta] = enter
  1736  	e.c.p.srcMap[0].pc = delta
  1737  	s.trimCode(delta)
  1738  
  1739  	strict = s.strict
  1740  	prg = e.c.p
  1741  	// e.c.p.dumpCode()
  1742  	if enterFunc2Mark != -1 {
  1743  		e.c.popScope()
  1744  	}
  1745  	e.c.popScope()
  1746  	e.c.p = savedPrg
  1747  
  1748  	return
  1749  }
  1750  
  1751  func (e *compiledFunctionLiteral) emitGetter(putOnStack bool) {
  1752  	p, name, length, strict := e.compile()
  1753  	switch e.typ {
  1754  	case funcArrow:
  1755  		if e.isAsync {
  1756  			e.c.emit(&newAsyncArrowFunc{newArrowFunc: newArrowFunc{newFunc: newFunc{prg: p, length: length, name: name, source: e.source, strict: strict}}})
  1757  		} else {
  1758  			e.c.emit(&newArrowFunc{newFunc: newFunc{prg: p, length: length, name: name, source: e.source, strict: strict}})
  1759  		}
  1760  	case funcMethod, funcClsInit:
  1761  		if e.isAsync {
  1762  			e.c.emit(&newAsyncMethod{newMethod: newMethod{newFunc: newFunc{prg: p, length: length, name: name, source: e.source, strict: strict}, homeObjOffset: e.homeObjOffset}})
  1763  		} else {
  1764  			if e.isGenerator {
  1765  				e.c.emit(&newGeneratorMethod{newMethod: newMethod{newFunc: newFunc{prg: p, length: length, name: name, source: e.source, strict: strict}, homeObjOffset: e.homeObjOffset}})
  1766  			} else {
  1767  				e.c.emit(&newMethod{newFunc: newFunc{prg: p, length: length, name: name, source: e.source, strict: strict}, homeObjOffset: e.homeObjOffset})
  1768  			}
  1769  		}
  1770  	case funcRegular:
  1771  		if e.isAsync {
  1772  			e.c.emit(&newAsyncFunc{newFunc: newFunc{prg: p, length: length, name: name, source: e.source, strict: strict}})
  1773  		} else {
  1774  			if e.isGenerator {
  1775  				e.c.emit(&newGeneratorFunc{newFunc: newFunc{prg: p, length: length, name: name, source: e.source, strict: strict}})
  1776  			} else {
  1777  				e.c.emit(&newFunc{prg: p, length: length, name: name, source: e.source, strict: strict})
  1778  			}
  1779  		}
  1780  	default:
  1781  		e.c.throwSyntaxError(e.offset, "Unsupported func type: %v", e.typ)
  1782  	}
  1783  	if !putOnStack {
  1784  		e.c.emit(pop)
  1785  	}
  1786  }
  1787  
  1788  func (c *compiler) compileFunctionLiteral(v *ast.FunctionLiteral, isExpr bool) *compiledFunctionLiteral {
  1789  	strictBody := c.isStrictStatement(v.Body)
  1790  	if v.Name != nil && (c.scope.strict || strictBody != nil) {
  1791  		c.checkIdentifierName(v.Name.Name, int(v.Name.Idx)-1)
  1792  		c.checkIdentifierLName(v.Name.Name, int(v.Name.Idx)-1)
  1793  	}
  1794  	if v.Async && v.Generator {
  1795  		c.throwSyntaxError(int(v.Function)-1, "Async generators are not supported yet")
  1796  	}
  1797  	r := &compiledFunctionLiteral{
  1798  		name:            v.Name,
  1799  		parameterList:   v.ParameterList,
  1800  		body:            v.Body.List,
  1801  		source:          v.Source,
  1802  		declarationList: v.DeclarationList,
  1803  		isExpr:          isExpr,
  1804  		typ:             funcRegular,
  1805  		strict:          strictBody,
  1806  		isAsync:         v.Async,
  1807  		isGenerator:     v.Generator,
  1808  	}
  1809  	r.init(c, v.Idx0())
  1810  	return r
  1811  }
  1812  
  1813  type compiledClassLiteral struct {
  1814  	baseCompiledExpr
  1815  	name       *ast.Identifier
  1816  	superClass compiledExpr
  1817  	body       []ast.ClassElement
  1818  	lhsName    unistring.String
  1819  	source     string
  1820  	isExpr     bool
  1821  }
  1822  
  1823  func (c *compiler) processKey(expr ast.Expression) (val unistring.String, computed bool) {
  1824  	keyExpr := c.compileExpression(expr)
  1825  	if keyExpr.constant() {
  1826  		v, ex := c.evalConst(keyExpr)
  1827  		if ex == nil {
  1828  			return v.string(), false
  1829  		}
  1830  	}
  1831  	keyExpr.emitGetter(true)
  1832  	computed = true
  1833  	return
  1834  }
  1835  
  1836  func (e *compiledClassLiteral) processClassKey(expr ast.Expression) (privateName *privateName, key unistring.String, computed bool) {
  1837  	if p, ok := expr.(*ast.PrivateIdentifier); ok {
  1838  		privateName = e.c.classScope.getDeclaredPrivateId(p.Name)
  1839  		key = privateIdString(p.Name)
  1840  		return
  1841  	}
  1842  	key, computed = e.c.processKey(expr)
  1843  	return
  1844  }
  1845  
  1846  type clsElement struct {
  1847  	key         unistring.String
  1848  	privateName *privateName
  1849  	initializer compiledExpr
  1850  	body        *compiledFunctionLiteral
  1851  	computed    bool
  1852  }
  1853  
  1854  func (e *compiledClassLiteral) emitGetter(putOnStack bool) {
  1855  	e.c.newBlockScope()
  1856  	s := e.c.scope
  1857  	s.strict = true
  1858  
  1859  	enter := &enterBlock{}
  1860  	mark0 := len(e.c.p.code)
  1861  	e.c.emit(enter)
  1862  	e.c.block = &block{
  1863  		typ:   blockScope,
  1864  		outer: e.c.block,
  1865  	}
  1866  	var clsBinding *binding
  1867  	var clsName unistring.String
  1868  	if name := e.name; name != nil {
  1869  		clsName = name.Name
  1870  		clsBinding = e.c.createLexicalIdBinding(clsName, true, int(name.Idx)-1)
  1871  	} else {
  1872  		clsName = e.lhsName
  1873  	}
  1874  
  1875  	var ctorMethod *ast.MethodDefinition
  1876  	ctorMethodIdx := -1
  1877  	staticsCount := 0
  1878  	instanceFieldsCount := 0
  1879  	hasStaticPrivateMethods := false
  1880  	cs := &classScope{
  1881  		c:     e.c,
  1882  		outer: e.c.classScope,
  1883  	}
  1884  
  1885  	for idx, elt := range e.body {
  1886  		switch elt := elt.(type) {
  1887  		case *ast.ClassStaticBlock:
  1888  			if len(elt.Block.List) > 0 {
  1889  				staticsCount++
  1890  			}
  1891  		case *ast.FieldDefinition:
  1892  			if id, ok := elt.Key.(*ast.PrivateIdentifier); ok {
  1893  				cs.declarePrivateId(id.Name, ast.PropertyKindValue, elt.Static, int(elt.Idx)-1)
  1894  			}
  1895  			if elt.Static {
  1896  				staticsCount++
  1897  			} else {
  1898  				instanceFieldsCount++
  1899  			}
  1900  		case *ast.MethodDefinition:
  1901  			if !elt.Static {
  1902  				if id, ok := elt.Key.(*ast.StringLiteral); ok {
  1903  					if !elt.Computed && id.Value == "constructor" {
  1904  						if ctorMethod != nil {
  1905  							e.c.throwSyntaxError(int(id.Idx)-1, "A class may only have one constructor")
  1906  						}
  1907  						ctorMethod = elt
  1908  						ctorMethodIdx = idx
  1909  						continue
  1910  					}
  1911  				}
  1912  			}
  1913  			if id, ok := elt.Key.(*ast.PrivateIdentifier); ok {
  1914  				cs.declarePrivateId(id.Name, elt.Kind, elt.Static, int(elt.Idx)-1)
  1915  				if elt.Static {
  1916  					hasStaticPrivateMethods = true
  1917  				}
  1918  			}
  1919  		default:
  1920  			e.c.assert(false, int(elt.Idx0())-1, "Unsupported static element: %T", elt)
  1921  		}
  1922  	}
  1923  
  1924  	var staticInit *newStaticFieldInit
  1925  	if staticsCount > 0 || hasStaticPrivateMethods {
  1926  		staticInit = &newStaticFieldInit{}
  1927  		e.c.emit(staticInit)
  1928  	}
  1929  
  1930  	var derived bool
  1931  	var newClassIns *newClass
  1932  	if superClass := e.superClass; superClass != nil {
  1933  		derived = true
  1934  		superClass.emitGetter(true)
  1935  		ndc := &newDerivedClass{
  1936  			newClass: newClass{
  1937  				name:   clsName,
  1938  				source: e.source,
  1939  			},
  1940  		}
  1941  		e.addSrcMap()
  1942  		e.c.emit(ndc)
  1943  		newClassIns = &ndc.newClass
  1944  	} else {
  1945  		newClassIns = &newClass{
  1946  			name:   clsName,
  1947  			source: e.source,
  1948  		}
  1949  		e.addSrcMap()
  1950  		e.c.emit(newClassIns)
  1951  	}
  1952  
  1953  	e.c.classScope = cs
  1954  
  1955  	if ctorMethod != nil {
  1956  		newClassIns.ctor, newClassIns.length = e.c.compileCtor(ctorMethod.Body, derived)
  1957  	}
  1958  
  1959  	curIsPrototype := false
  1960  
  1961  	instanceFields := make([]clsElement, 0, instanceFieldsCount)
  1962  	staticElements := make([]clsElement, 0, staticsCount)
  1963  
  1964  	// stack at this point:
  1965  	//
  1966  	// staticFieldInit (if staticsCount > 0 || hasStaticPrivateMethods)
  1967  	// prototype
  1968  	// class function
  1969  	// <- sp
  1970  
  1971  	for idx, elt := range e.body {
  1972  		if idx == ctorMethodIdx {
  1973  			continue
  1974  		}
  1975  		switch elt := elt.(type) {
  1976  		case *ast.ClassStaticBlock:
  1977  			if len(elt.Block.List) > 0 {
  1978  				f := e.c.compileFunctionLiteral(&ast.FunctionLiteral{
  1979  					Function:        elt.Idx0(),
  1980  					ParameterList:   &ast.ParameterList{},
  1981  					Body:            elt.Block,
  1982  					Source:          elt.Source,
  1983  					DeclarationList: elt.DeclarationList,
  1984  				}, true)
  1985  				f.typ = funcClsInit
  1986  				//f.lhsName = "<static_initializer>"
  1987  				f.homeObjOffset = 1
  1988  				staticElements = append(staticElements, clsElement{
  1989  					body: f,
  1990  				})
  1991  			}
  1992  		case *ast.FieldDefinition:
  1993  			privateName, key, computed := e.processClassKey(elt.Key)
  1994  			var el clsElement
  1995  			if elt.Initializer != nil {
  1996  				el.initializer = e.c.compileExpression(elt.Initializer)
  1997  			}
  1998  			el.computed = computed
  1999  			if computed {
  2000  				if elt.Static {
  2001  					if curIsPrototype {
  2002  						e.c.emit(defineComputedKey(5))
  2003  					} else {
  2004  						e.c.emit(defineComputedKey(4))
  2005  					}
  2006  				} else {
  2007  					if curIsPrototype {
  2008  						e.c.emit(defineComputedKey(3))
  2009  					} else {
  2010  						e.c.emit(defineComputedKey(2))
  2011  					}
  2012  				}
  2013  			} else {
  2014  				el.privateName = privateName
  2015  				el.key = key
  2016  			}
  2017  			if elt.Static {
  2018  				staticElements = append(staticElements, el)
  2019  			} else {
  2020  				instanceFields = append(instanceFields, el)
  2021  			}
  2022  		case *ast.MethodDefinition:
  2023  			if elt.Static {
  2024  				if curIsPrototype {
  2025  					e.c.emit(pop)
  2026  					curIsPrototype = false
  2027  				}
  2028  			} else {
  2029  				if !curIsPrototype {
  2030  					e.c.emit(dupN(1))
  2031  					curIsPrototype = true
  2032  				}
  2033  			}
  2034  			privateName, key, computed := e.processClassKey(elt.Key)
  2035  			lit := e.c.compileFunctionLiteral(elt.Body, true)
  2036  			lit.typ = funcMethod
  2037  			if computed {
  2038  				e.c.emit(_toPropertyKey{})
  2039  				lit.homeObjOffset = 2
  2040  			} else {
  2041  				lit.homeObjOffset = 1
  2042  				lit.lhsName = key
  2043  			}
  2044  			lit.emitGetter(true)
  2045  			if privateName != nil {
  2046  				var offset int
  2047  				if elt.Static {
  2048  					if curIsPrototype {
  2049  						/*
  2050  							staticInit
  2051  							proto
  2052  							cls
  2053  							proto
  2054  							method
  2055  							<- sp
  2056  						*/
  2057  						offset = 5
  2058  					} else {
  2059  						/*
  2060  							staticInit
  2061  							proto
  2062  							cls
  2063  							method
  2064  							<- sp
  2065  						*/
  2066  						offset = 4
  2067  					}
  2068  				} else {
  2069  					if curIsPrototype {
  2070  						offset = 3
  2071  					} else {
  2072  						offset = 2
  2073  					}
  2074  				}
  2075  				switch elt.Kind {
  2076  				case ast.PropertyKindGet:
  2077  					e.c.emit(&definePrivateGetter{
  2078  						definePrivateMethod: definePrivateMethod{
  2079  							idx:          privateName.idx,
  2080  							targetOffset: offset,
  2081  						},
  2082  					})
  2083  				case ast.PropertyKindSet:
  2084  					e.c.emit(&definePrivateSetter{
  2085  						definePrivateMethod: definePrivateMethod{
  2086  							idx:          privateName.idx,
  2087  							targetOffset: offset,
  2088  						},
  2089  					})
  2090  				default:
  2091  					e.c.emit(&definePrivateMethod{
  2092  						idx:          privateName.idx,
  2093  						targetOffset: offset,
  2094  					})
  2095  				}
  2096  			} else if computed {
  2097  				switch elt.Kind {
  2098  				case ast.PropertyKindGet:
  2099  					e.c.emit(&defineGetter{})
  2100  				case ast.PropertyKindSet:
  2101  					e.c.emit(&defineSetter{})
  2102  				default:
  2103  					e.c.emit(&defineMethod{})
  2104  				}
  2105  			} else {
  2106  				switch elt.Kind {
  2107  				case ast.PropertyKindGet:
  2108  					e.c.emit(&defineGetterKeyed{key: key})
  2109  				case ast.PropertyKindSet:
  2110  					e.c.emit(&defineSetterKeyed{key: key})
  2111  				default:
  2112  					e.c.emit(&defineMethodKeyed{key: key})
  2113  				}
  2114  			}
  2115  		}
  2116  	}
  2117  	if curIsPrototype {
  2118  		e.c.emit(pop)
  2119  	}
  2120  
  2121  	if len(instanceFields) > 0 {
  2122  		newClassIns.initFields = e.compileFieldsAndStaticBlocks(instanceFields, "<instance_members_initializer>")
  2123  	}
  2124  	if staticInit != nil {
  2125  		if len(staticElements) > 0 {
  2126  			staticInit.initFields = e.compileFieldsAndStaticBlocks(staticElements, "<static_initializer>")
  2127  		}
  2128  	}
  2129  
  2130  	env := e.c.classScope.instanceEnv
  2131  	if s.dynLookup {
  2132  		newClassIns.privateMethods, newClassIns.privateFields = env.methods, env.fields
  2133  	}
  2134  	newClassIns.numPrivateMethods = uint32(len(env.methods))
  2135  	newClassIns.numPrivateFields = uint32(len(env.fields))
  2136  	newClassIns.hasPrivateEnv = len(e.c.classScope.privateNames) > 0
  2137  
  2138  	if (clsBinding != nil && clsBinding.useCount() > 0) || s.dynLookup {
  2139  		if clsBinding != nil {
  2140  			// Because this block may be in the middle of an expression, its initial stack position
  2141  			// cannot be known, and therefore it may not have any stack variables.
  2142  			// Note, because clsBinding would be accessed through a function, it should already be in stash,
  2143  			// this is just to make sure.
  2144  			clsBinding.moveToStash()
  2145  			clsBinding.emitInit()
  2146  		}
  2147  	} else {
  2148  		if clsBinding != nil {
  2149  			s.deleteBinding(clsBinding)
  2150  			clsBinding = nil
  2151  		}
  2152  		e.c.p.code[mark0] = jump(1)
  2153  	}
  2154  
  2155  	if staticsCount > 0 || hasStaticPrivateMethods {
  2156  		ise := &initStaticElements{}
  2157  		e.c.emit(ise)
  2158  		env := e.c.classScope.staticEnv
  2159  		staticInit.numPrivateFields = uint32(len(env.fields))
  2160  		staticInit.numPrivateMethods = uint32(len(env.methods))
  2161  		if s.dynLookup {
  2162  			// These cannot be set on staticInit, because it is executed before ClassHeritage, and therefore
  2163  			// the VM's PrivateEnvironment is still not set.
  2164  			ise.privateFields = env.fields
  2165  			ise.privateMethods = env.methods
  2166  		}
  2167  	} else {
  2168  		e.c.emit(endVariadic) // re-using as semantics match
  2169  	}
  2170  
  2171  	if !putOnStack {
  2172  		e.c.emit(pop)
  2173  	}
  2174  
  2175  	if clsBinding != nil || s.dynLookup {
  2176  		e.c.leaveScopeBlock(enter)
  2177  		e.c.assert(enter.stackSize == 0, e.offset, "enter.StackSize != 0 in compiledClassLiteral")
  2178  	} else {
  2179  		e.c.block = e.c.block.outer
  2180  	}
  2181  	if len(e.c.classScope.privateNames) > 0 {
  2182  		e.c.emit(popPrivateEnv{})
  2183  	}
  2184  	e.c.classScope = e.c.classScope.outer
  2185  	e.c.popScope()
  2186  }
  2187  
  2188  func (e *compiledClassLiteral) compileFieldsAndStaticBlocks(elements []clsElement, funcName unistring.String) *Program {
  2189  	savedPrg := e.c.p
  2190  	savedBlock := e.c.block
  2191  	defer func() {
  2192  		e.c.p = savedPrg
  2193  		e.c.block = savedBlock
  2194  	}()
  2195  
  2196  	e.c.block = &block{
  2197  		typ: blockScope,
  2198  	}
  2199  
  2200  	e.c.p = &Program{
  2201  		src:      savedPrg.src,
  2202  		funcName: funcName,
  2203  		code:     e.c.newCode(2, 16),
  2204  	}
  2205  
  2206  	e.c.newScope()
  2207  	s := e.c.scope
  2208  	s.funcType = funcClsInit
  2209  	thisBinding := s.createThisBinding()
  2210  
  2211  	valIdx := 0
  2212  	for _, elt := range elements {
  2213  		if elt.body != nil {
  2214  			e.c.emit(dup) // this
  2215  			elt.body.emitGetter(true)
  2216  			elt.body.addSrcMap()
  2217  			e.c.emit(call(0), pop)
  2218  		} else {
  2219  			if elt.computed {
  2220  				e.c.emit(loadComputedKey(valIdx))
  2221  				valIdx++
  2222  			}
  2223  			if init := elt.initializer; init != nil {
  2224  				if !elt.computed {
  2225  					e.c.emitNamedOrConst(init, elt.key)
  2226  				} else {
  2227  					e.c.emitExpr(init, true)
  2228  				}
  2229  			} else {
  2230  				e.c.emit(loadUndef)
  2231  			}
  2232  			if elt.privateName != nil {
  2233  				e.c.emit(&definePrivateProp{
  2234  					idx: elt.privateName.idx,
  2235  				})
  2236  			} else if elt.computed {
  2237  				e.c.emit(defineProp{})
  2238  			} else {
  2239  				e.c.emit(definePropKeyed(elt.key))
  2240  			}
  2241  		}
  2242  	}
  2243  	//e.c.emit(halt)
  2244  	if s.isDynamic() || thisBinding.useCount() > 0 {
  2245  		if s.isDynamic() || thisBinding.inStash {
  2246  			thisBinding.emitInitAt(1)
  2247  		}
  2248  	} else {
  2249  		s.deleteBinding(thisBinding)
  2250  	}
  2251  	stashSize, stackSize := s.finaliseVarAlloc(0)
  2252  	e.c.assert(stackSize == 0, e.offset, "stackSize != 0 in initFields")
  2253  	if stashSize > 0 {
  2254  		e.c.assert(stashSize == 1, e.offset, "stashSize != 1 in initFields")
  2255  		enter := &enterFunc{
  2256  			stashSize: 1,
  2257  			funcType:  funcClsInit,
  2258  		}
  2259  		if s.dynLookup {
  2260  			enter.names = s.makeNamesMap()
  2261  		}
  2262  		e.c.p.code[0] = enter
  2263  		s.trimCode(0)
  2264  	} else {
  2265  		s.trimCode(2)
  2266  	}
  2267  	res := e.c.p
  2268  	e.c.popScope()
  2269  	return res
  2270  }
  2271  
  2272  func (c *compiler) compileClassLiteral(v *ast.ClassLiteral, isExpr bool) *compiledClassLiteral {
  2273  	if v.Name != nil {
  2274  		c.checkIdentifierLName(v.Name.Name, int(v.Name.Idx)-1)
  2275  	}
  2276  	r := &compiledClassLiteral{
  2277  		name:       v.Name,
  2278  		superClass: c.compileExpression(v.SuperClass),
  2279  		body:       v.Body,
  2280  		source:     v.Source,
  2281  		isExpr:     isExpr,
  2282  	}
  2283  	r.init(c, v.Idx0())
  2284  	return r
  2285  }
  2286  
  2287  func (c *compiler) compileCtor(ctor *ast.FunctionLiteral, derived bool) (p *Program, length int) {
  2288  	f := c.compileFunctionLiteral(ctor, true)
  2289  	if derived {
  2290  		f.typ = funcDerivedCtor
  2291  	} else {
  2292  		f.typ = funcCtor
  2293  	}
  2294  	p, _, length, _ = f.compile()
  2295  	return
  2296  }
  2297  
  2298  func (c *compiler) compileArrowFunctionLiteral(v *ast.ArrowFunctionLiteral) *compiledFunctionLiteral {
  2299  	var strictBody *ast.StringLiteral
  2300  	var body []ast.Statement
  2301  	switch b := v.Body.(type) {
  2302  	case *ast.BlockStatement:
  2303  		strictBody = c.isStrictStatement(b)
  2304  		body = b.List
  2305  	case *ast.ExpressionBody:
  2306  		body = []ast.Statement{
  2307  			&ast.ReturnStatement{
  2308  				Argument: b.Expression,
  2309  			},
  2310  		}
  2311  	default:
  2312  		c.throwSyntaxError(int(b.Idx0())-1, "Unsupported ConciseBody type: %T", b)
  2313  	}
  2314  	r := &compiledFunctionLiteral{
  2315  		parameterList:   v.ParameterList,
  2316  		body:            body,
  2317  		source:          v.Source,
  2318  		declarationList: v.DeclarationList,
  2319  		isExpr:          true,
  2320  		typ:             funcArrow,
  2321  		strict:          strictBody,
  2322  		isAsync:         v.Async,
  2323  	}
  2324  	r.init(c, v.Idx0())
  2325  	return r
  2326  }
  2327  
  2328  func (c *compiler) emitLoadThis() {
  2329  	b, eval := c.scope.lookupThis()
  2330  	if b != nil {
  2331  		b.emitGet()
  2332  	} else {
  2333  		if eval {
  2334  			c.emit(getThisDynamic{})
  2335  		} else {
  2336  			c.emit(loadGlobalObject)
  2337  		}
  2338  	}
  2339  }
  2340  
  2341  func (e *compiledThisExpr) emitGetter(putOnStack bool) {
  2342  	e.addSrcMap()
  2343  	e.c.emitLoadThis()
  2344  	if !putOnStack {
  2345  		e.c.emit(pop)
  2346  	}
  2347  }
  2348  
  2349  func (e *compiledSuperExpr) emitGetter(putOnStack bool) {
  2350  	if putOnStack {
  2351  		e.c.emit(loadSuper)
  2352  	}
  2353  }
  2354  
  2355  func (e *compiledNewExpr) emitGetter(putOnStack bool) {
  2356  	if e.isVariadic {
  2357  		e.c.emit(startVariadic)
  2358  	}
  2359  	e.callee.emitGetter(true)
  2360  	for _, expr := range e.args {
  2361  		expr.emitGetter(true)
  2362  	}
  2363  	e.addSrcMap()
  2364  	if e.isVariadic {
  2365  		e.c.emit(newVariadic, endVariadic)
  2366  	} else {
  2367  		e.c.emit(_new(len(e.args)))
  2368  	}
  2369  	if !putOnStack {
  2370  		e.c.emit(pop)
  2371  	}
  2372  }
  2373  
  2374  func (c *compiler) compileCallArgs(list []ast.Expression) (args []compiledExpr, isVariadic bool) {
  2375  	args = make([]compiledExpr, len(list))
  2376  	for i, argExpr := range list {
  2377  		if spread, ok := argExpr.(*ast.SpreadElement); ok {
  2378  			args[i] = c.compileSpreadCallArgument(spread)
  2379  			isVariadic = true
  2380  		} else {
  2381  			args[i] = c.compileExpression(argExpr)
  2382  		}
  2383  	}
  2384  	return
  2385  }
  2386  
  2387  func (c *compiler) compileNewExpression(v *ast.NewExpression) compiledExpr {
  2388  	args, isVariadic := c.compileCallArgs(v.ArgumentList)
  2389  	r := &compiledNewExpr{
  2390  		compiledCallExpr: compiledCallExpr{
  2391  			callee:     c.compileExpression(v.Callee),
  2392  			args:       args,
  2393  			isVariadic: isVariadic,
  2394  		},
  2395  	}
  2396  	r.init(c, v.Idx0())
  2397  	return r
  2398  }
  2399  
  2400  func (e *compiledNewTarget) emitGetter(putOnStack bool) {
  2401  	if s := e.c.scope.nearestThis(); s == nil || s.funcType == funcNone {
  2402  		e.c.throwSyntaxError(e.offset, "new.target expression is not allowed here")
  2403  	}
  2404  	if putOnStack {
  2405  		e.addSrcMap()
  2406  		e.c.emit(loadNewTarget)
  2407  	}
  2408  }
  2409  
  2410  func (c *compiler) compileMetaProperty(v *ast.MetaProperty) compiledExpr {
  2411  	if v.Meta.Name == "new" || v.Property.Name != "target" {
  2412  		r := &compiledNewTarget{}
  2413  		r.init(c, v.Idx0())
  2414  		return r
  2415  	}
  2416  	c.throwSyntaxError(int(v.Idx)-1, "Unsupported meta property: %s.%s", v.Meta.Name, v.Property.Name)
  2417  	return nil
  2418  }
  2419  
  2420  func (e *compiledSequenceExpr) emitGetter(putOnStack bool) {
  2421  	if len(e.sequence) > 0 {
  2422  		for i := 0; i < len(e.sequence)-1; i++ {
  2423  			e.sequence[i].emitGetter(false)
  2424  		}
  2425  		e.sequence[len(e.sequence)-1].emitGetter(putOnStack)
  2426  	}
  2427  }
  2428  
  2429  func (c *compiler) compileSequenceExpression(v *ast.SequenceExpression) compiledExpr {
  2430  	s := make([]compiledExpr, len(v.Sequence))
  2431  	for i, expr := range v.Sequence {
  2432  		s[i] = c.compileExpression(expr)
  2433  	}
  2434  	r := &compiledSequenceExpr{
  2435  		sequence: s,
  2436  	}
  2437  	var idx file.Idx
  2438  	if len(v.Sequence) > 0 {
  2439  		idx = v.Idx0()
  2440  	}
  2441  	r.init(c, idx)
  2442  	return r
  2443  }
  2444  
  2445  func (c *compiler) emitThrow(v Value) {
  2446  	if o, ok := v.(*Object); ok {
  2447  		t := nilSafe(o.self.getStr("name", nil)).toString().String()
  2448  		switch t {
  2449  		case "TypeError":
  2450  			c.emit(loadDynamic(t))
  2451  			msg := o.self.getStr("message", nil)
  2452  			if msg != nil {
  2453  				c.emit(loadVal(c.p.defineLiteralValue(msg)))
  2454  				c.emit(_new(1))
  2455  			} else {
  2456  				c.emit(_new(0))
  2457  			}
  2458  			c.emit(throw)
  2459  			return
  2460  		}
  2461  	}
  2462  	c.assert(false, 0, "unknown exception type thrown while evaluating constant expression: %s", v.String())
  2463  	panic("unreachable")
  2464  }
  2465  
  2466  func (c *compiler) emitConst(expr compiledExpr, putOnStack bool) {
  2467  	v, ex := c.evalConst(expr)
  2468  	if ex == nil {
  2469  		if putOnStack {
  2470  			c.emit(loadVal(c.p.defineLiteralValue(v)))
  2471  		}
  2472  	} else {
  2473  		c.emitThrow(ex.val)
  2474  	}
  2475  }
  2476  
  2477  func (c *compiler) evalConst(expr compiledExpr) (Value, *Exception) {
  2478  	if expr, ok := expr.(*compiledLiteral); ok {
  2479  		return expr.val, nil
  2480  	}
  2481  	if c.evalVM == nil {
  2482  		c.evalVM = New().vm
  2483  	}
  2484  	var savedPrg *Program
  2485  	createdPrg := false
  2486  	if c.evalVM.prg == nil {
  2487  		c.evalVM.prg = &Program{
  2488  			src: c.p.src,
  2489  		}
  2490  		savedPrg = c.p
  2491  		c.p = c.evalVM.prg
  2492  		createdPrg = true
  2493  	}
  2494  	savedPc := len(c.p.code)
  2495  	expr.emitGetter(true)
  2496  	c.evalVM.pc = savedPc
  2497  	ex := c.evalVM.runTry()
  2498  	if createdPrg {
  2499  		c.evalVM.prg = nil
  2500  		c.evalVM.pc = 0
  2501  		c.p = savedPrg
  2502  	} else {
  2503  		c.evalVM.prg.code = c.evalVM.prg.code[:savedPc]
  2504  		c.p.code = c.evalVM.prg.code
  2505  	}
  2506  	if ex == nil {
  2507  		return c.evalVM.pop(), nil
  2508  	}
  2509  	return nil, ex
  2510  }
  2511  
  2512  func (e *compiledUnaryExpr) constant() bool {
  2513  	return e.operand.constant()
  2514  }
  2515  
  2516  func (e *compiledUnaryExpr) emitGetter(putOnStack bool) {
  2517  	var prepare, body func()
  2518  
  2519  	toNumber := func() {
  2520  		e.addSrcMap()
  2521  		e.c.emit(toNumber)
  2522  	}
  2523  
  2524  	switch e.operator {
  2525  	case token.NOT:
  2526  		e.operand.emitGetter(true)
  2527  		e.c.emit(not)
  2528  		goto end
  2529  	case token.BITWISE_NOT:
  2530  		e.operand.emitGetter(true)
  2531  		e.c.emit(bnot)
  2532  		goto end
  2533  	case token.TYPEOF:
  2534  		if o, ok := e.operand.(compiledExprOrRef); ok {
  2535  			o.emitGetterOrRef()
  2536  		} else {
  2537  			e.operand.emitGetter(true)
  2538  		}
  2539  		e.c.emit(typeof)
  2540  		goto end
  2541  	case token.DELETE:
  2542  		e.operand.deleteExpr().emitGetter(putOnStack)
  2543  		return
  2544  	case token.MINUS:
  2545  		e.c.emitExpr(e.operand, true)
  2546  		e.c.emit(neg)
  2547  		goto end
  2548  	case token.PLUS:
  2549  		e.c.emitExpr(e.operand, true)
  2550  		e.c.emit(plus)
  2551  		goto end
  2552  	case token.INCREMENT:
  2553  		prepare = toNumber
  2554  		body = func() {
  2555  			e.c.emit(inc)
  2556  		}
  2557  	case token.DECREMENT:
  2558  		prepare = toNumber
  2559  		body = func() {
  2560  			e.c.emit(dec)
  2561  		}
  2562  	case token.VOID:
  2563  		e.c.emitExpr(e.operand, false)
  2564  		if putOnStack {
  2565  			e.c.emit(loadUndef)
  2566  		}
  2567  		return
  2568  	default:
  2569  		e.c.assert(false, e.offset, "Unknown unary operator: %s", e.operator.String())
  2570  		panic("unreachable")
  2571  	}
  2572  
  2573  	e.operand.emitUnary(prepare, body, e.postfix, putOnStack)
  2574  	return
  2575  
  2576  end:
  2577  	if !putOnStack {
  2578  		e.c.emit(pop)
  2579  	}
  2580  }
  2581  
  2582  func (c *compiler) compileUnaryExpression(v *ast.UnaryExpression) compiledExpr {
  2583  	r := &compiledUnaryExpr{
  2584  		operand:  c.compileExpression(v.Operand),
  2585  		operator: v.Operator,
  2586  		postfix:  v.Postfix,
  2587  	}
  2588  	r.init(c, v.Idx0())
  2589  	return r
  2590  }
  2591  
  2592  func (e *compiledConditionalExpr) emitGetter(putOnStack bool) {
  2593  	e.test.emitGetter(true)
  2594  	j := len(e.c.p.code)
  2595  	e.c.emit(nil)
  2596  	e.consequent.emitGetter(putOnStack)
  2597  	j1 := len(e.c.p.code)
  2598  	e.c.emit(nil)
  2599  	e.c.p.code[j] = jne(len(e.c.p.code) - j)
  2600  	e.alternate.emitGetter(putOnStack)
  2601  	e.c.p.code[j1] = jump(len(e.c.p.code) - j1)
  2602  }
  2603  
  2604  func (c *compiler) compileConditionalExpression(v *ast.ConditionalExpression) compiledExpr {
  2605  	r := &compiledConditionalExpr{
  2606  		test:       c.compileExpression(v.Test),
  2607  		consequent: c.compileExpression(v.Consequent),
  2608  		alternate:  c.compileExpression(v.Alternate),
  2609  	}
  2610  	r.init(c, v.Idx0())
  2611  	return r
  2612  }
  2613  
  2614  func (e *compiledLogicalOr) constant() bool {
  2615  	if e.left.constant() {
  2616  		if v, ex := e.c.evalConst(e.left); ex == nil {
  2617  			if v.ToBoolean() {
  2618  				return true
  2619  			}
  2620  			return e.right.constant()
  2621  		} else {
  2622  			return true
  2623  		}
  2624  	}
  2625  
  2626  	return false
  2627  }
  2628  
  2629  func (e *compiledLogicalOr) emitGetter(putOnStack bool) {
  2630  	if e.left.constant() {
  2631  		if v, ex := e.c.evalConst(e.left); ex == nil {
  2632  			if !v.ToBoolean() {
  2633  				e.c.emitExpr(e.right, putOnStack)
  2634  			} else {
  2635  				if putOnStack {
  2636  					e.c.emit(loadVal(e.c.p.defineLiteralValue(v)))
  2637  				}
  2638  			}
  2639  		} else {
  2640  			e.c.emitThrow(ex.val)
  2641  		}
  2642  		return
  2643  	}
  2644  	e.c.emitExpr(e.left, true)
  2645  	j := len(e.c.p.code)
  2646  	e.addSrcMap()
  2647  	e.c.emit(nil)
  2648  	e.c.emitExpr(e.right, true)
  2649  	e.c.p.code[j] = jeq1(len(e.c.p.code) - j)
  2650  	if !putOnStack {
  2651  		e.c.emit(pop)
  2652  	}
  2653  }
  2654  
  2655  func (e *compiledCoalesce) constant() bool {
  2656  	if e.left.constant() {
  2657  		if v, ex := e.c.evalConst(e.left); ex == nil {
  2658  			if v != _null && v != _undefined {
  2659  				return true
  2660  			}
  2661  			return e.right.constant()
  2662  		} else {
  2663  			return true
  2664  		}
  2665  	}
  2666  
  2667  	return false
  2668  }
  2669  
  2670  func (e *compiledCoalesce) emitGetter(putOnStack bool) {
  2671  	if e.left.constant() {
  2672  		if v, ex := e.c.evalConst(e.left); ex == nil {
  2673  			if v == _undefined || v == _null {
  2674  				e.c.emitExpr(e.right, putOnStack)
  2675  			} else {
  2676  				if putOnStack {
  2677  					e.c.emit(loadVal(e.c.p.defineLiteralValue(v)))
  2678  				}
  2679  			}
  2680  		} else {
  2681  			e.c.emitThrow(ex.val)
  2682  		}
  2683  		return
  2684  	}
  2685  	e.c.emitExpr(e.left, true)
  2686  	j := len(e.c.p.code)
  2687  	e.addSrcMap()
  2688  	e.c.emit(nil)
  2689  	e.c.emitExpr(e.right, true)
  2690  	e.c.p.code[j] = jcoalesc(len(e.c.p.code) - j)
  2691  	if !putOnStack {
  2692  		e.c.emit(pop)
  2693  	}
  2694  }
  2695  
  2696  func (e *compiledLogicalAnd) constant() bool {
  2697  	if e.left.constant() {
  2698  		if v, ex := e.c.evalConst(e.left); ex == nil {
  2699  			if !v.ToBoolean() {
  2700  				return true
  2701  			} else {
  2702  				return e.right.constant()
  2703  			}
  2704  		} else {
  2705  			return true
  2706  		}
  2707  	}
  2708  
  2709  	return false
  2710  }
  2711  
  2712  func (e *compiledLogicalAnd) emitGetter(putOnStack bool) {
  2713  	var j int
  2714  	if e.left.constant() {
  2715  		if v, ex := e.c.evalConst(e.left); ex == nil {
  2716  			if !v.ToBoolean() {
  2717  				e.c.emit(loadVal(e.c.p.defineLiteralValue(v)))
  2718  			} else {
  2719  				e.c.emitExpr(e.right, putOnStack)
  2720  			}
  2721  		} else {
  2722  			e.c.emitThrow(ex.val)
  2723  		}
  2724  		return
  2725  	}
  2726  	e.left.emitGetter(true)
  2727  	j = len(e.c.p.code)
  2728  	e.addSrcMap()
  2729  	e.c.emit(nil)
  2730  	e.c.emitExpr(e.right, true)
  2731  	e.c.p.code[j] = jneq1(len(e.c.p.code) - j)
  2732  	if !putOnStack {
  2733  		e.c.emit(pop)
  2734  	}
  2735  }
  2736  
  2737  func (e *compiledBinaryExpr) constant() bool {
  2738  	return e.left.constant() && e.right.constant()
  2739  }
  2740  
  2741  func (e *compiledBinaryExpr) emitGetter(putOnStack bool) {
  2742  	e.c.emitExpr(e.left, true)
  2743  	e.c.emitExpr(e.right, true)
  2744  	e.addSrcMap()
  2745  
  2746  	switch e.operator {
  2747  	case token.LESS:
  2748  		e.c.emit(op_lt)
  2749  	case token.GREATER:
  2750  		e.c.emit(op_gt)
  2751  	case token.LESS_OR_EQUAL:
  2752  		e.c.emit(op_lte)
  2753  	case token.GREATER_OR_EQUAL:
  2754  		e.c.emit(op_gte)
  2755  	case token.EQUAL:
  2756  		e.c.emit(op_eq)
  2757  	case token.NOT_EQUAL:
  2758  		e.c.emit(op_neq)
  2759  	case token.STRICT_EQUAL:
  2760  		e.c.emit(op_strict_eq)
  2761  	case token.STRICT_NOT_EQUAL:
  2762  		e.c.emit(op_strict_neq)
  2763  	case token.PLUS:
  2764  		e.c.emit(add)
  2765  	case token.MINUS:
  2766  		e.c.emit(sub)
  2767  	case token.MULTIPLY:
  2768  		e.c.emit(mul)
  2769  	case token.EXPONENT:
  2770  		e.c.emit(exp)
  2771  	case token.SLASH:
  2772  		e.c.emit(div)
  2773  	case token.REMAINDER:
  2774  		e.c.emit(mod)
  2775  	case token.AND:
  2776  		e.c.emit(and)
  2777  	case token.OR:
  2778  		e.c.emit(or)
  2779  	case token.EXCLUSIVE_OR:
  2780  		e.c.emit(xor)
  2781  	case token.INSTANCEOF:
  2782  		e.c.emit(op_instanceof)
  2783  	case token.IN:
  2784  		e.c.emit(op_in)
  2785  	case token.SHIFT_LEFT:
  2786  		e.c.emit(sal)
  2787  	case token.SHIFT_RIGHT:
  2788  		e.c.emit(sar)
  2789  	case token.UNSIGNED_SHIFT_RIGHT:
  2790  		e.c.emit(shr)
  2791  	default:
  2792  		e.c.assert(false, e.offset, "Unknown operator: %s", e.operator.String())
  2793  		panic("unreachable")
  2794  	}
  2795  
  2796  	if !putOnStack {
  2797  		e.c.emit(pop)
  2798  	}
  2799  }
  2800  
  2801  func (c *compiler) compileBinaryExpression(v *ast.BinaryExpression) compiledExpr {
  2802  
  2803  	switch v.Operator {
  2804  	case token.LOGICAL_OR:
  2805  		return c.compileLogicalOr(v.Left, v.Right, v.Idx0())
  2806  	case token.COALESCE:
  2807  		return c.compileCoalesce(v.Left, v.Right, v.Idx0())
  2808  	case token.LOGICAL_AND:
  2809  		return c.compileLogicalAnd(v.Left, v.Right, v.Idx0())
  2810  	}
  2811  
  2812  	if id, ok := v.Left.(*ast.PrivateIdentifier); ok {
  2813  		return c.compilePrivateIn(id, v.Right, id.Idx)
  2814  	}
  2815  
  2816  	r := &compiledBinaryExpr{
  2817  		left:     c.compileExpression(v.Left),
  2818  		right:    c.compileExpression(v.Right),
  2819  		operator: v.Operator,
  2820  	}
  2821  	r.init(c, v.Idx0())
  2822  	return r
  2823  }
  2824  
  2825  type compiledPrivateIn struct {
  2826  	baseCompiledExpr
  2827  	id    unistring.String
  2828  	right compiledExpr
  2829  }
  2830  
  2831  func (e *compiledPrivateIn) emitGetter(putOnStack bool) {
  2832  	e.right.emitGetter(true)
  2833  	rn, id := e.c.resolvePrivateName(e.id, e.offset)
  2834  	if rn != nil {
  2835  		e.c.emit((*privateInRes)(rn))
  2836  	} else {
  2837  		e.c.emit((*privateInId)(id))
  2838  	}
  2839  	if !putOnStack {
  2840  		e.c.emit(pop)
  2841  	}
  2842  }
  2843  
  2844  func (c *compiler) compilePrivateIn(id *ast.PrivateIdentifier, right ast.Expression, idx file.Idx) compiledExpr {
  2845  	r := &compiledPrivateIn{
  2846  		id:    id.Name,
  2847  		right: c.compileExpression(right),
  2848  	}
  2849  	r.init(c, idx)
  2850  	return r
  2851  }
  2852  
  2853  func (c *compiler) compileLogicalOr(left, right ast.Expression, idx file.Idx) compiledExpr {
  2854  	r := &compiledLogicalOr{
  2855  		left:  c.compileExpression(left),
  2856  		right: c.compileExpression(right),
  2857  	}
  2858  	r.init(c, idx)
  2859  	return r
  2860  }
  2861  
  2862  func (c *compiler) compileCoalesce(left, right ast.Expression, idx file.Idx) compiledExpr {
  2863  	r := &compiledCoalesce{
  2864  		left:  c.compileExpression(left),
  2865  		right: c.compileExpression(right),
  2866  	}
  2867  	r.init(c, idx)
  2868  	return r
  2869  }
  2870  
  2871  func (c *compiler) compileLogicalAnd(left, right ast.Expression, idx file.Idx) compiledExpr {
  2872  	r := &compiledLogicalAnd{
  2873  		left:  c.compileExpression(left),
  2874  		right: c.compileExpression(right),
  2875  	}
  2876  	r.init(c, idx)
  2877  	return r
  2878  }
  2879  
  2880  func (e *compiledObjectLiteral) emitGetter(putOnStack bool) {
  2881  	e.addSrcMap()
  2882  	e.c.emit(newObject)
  2883  	hasProto := false
  2884  	for _, prop := range e.expr.Value {
  2885  		switch prop := prop.(type) {
  2886  		case *ast.PropertyKeyed:
  2887  			key, computed := e.c.processKey(prop.Key)
  2888  			valueExpr := e.c.compileExpression(prop.Value)
  2889  			var ne namedEmitter
  2890  			if fn, ok := valueExpr.(*compiledFunctionLiteral); ok {
  2891  				if fn.name == nil {
  2892  					ne = fn
  2893  				}
  2894  				switch prop.Kind {
  2895  				case ast.PropertyKindMethod, ast.PropertyKindGet, ast.PropertyKindSet:
  2896  					fn.typ = funcMethod
  2897  					if computed {
  2898  						fn.homeObjOffset = 2
  2899  					} else {
  2900  						fn.homeObjOffset = 1
  2901  					}
  2902  				}
  2903  			} else if v, ok := valueExpr.(namedEmitter); ok {
  2904  				ne = v
  2905  			}
  2906  			if computed {
  2907  				e.c.emit(_toPropertyKey{})
  2908  				e.c.emitExpr(valueExpr, true)
  2909  				switch prop.Kind {
  2910  				case ast.PropertyKindValue:
  2911  					if ne != nil {
  2912  						e.c.emit(setElem1Named)
  2913  					} else {
  2914  						e.c.emit(setElem1)
  2915  					}
  2916  				case ast.PropertyKindMethod:
  2917  					e.c.emit(&defineMethod{enumerable: true})
  2918  				case ast.PropertyKindGet:
  2919  					e.c.emit(&defineGetter{enumerable: true})
  2920  				case ast.PropertyKindSet:
  2921  					e.c.emit(&defineSetter{enumerable: true})
  2922  				default:
  2923  					e.c.assert(false, e.offset, "unknown property kind: %s", prop.Kind)
  2924  					panic("unreachable")
  2925  				}
  2926  			} else {
  2927  				isProto := key == __proto__ && !prop.Computed
  2928  				if isProto {
  2929  					if hasProto {
  2930  						e.c.throwSyntaxError(int(prop.Idx0())-1, "Duplicate __proto__ fields are not allowed in object literals")
  2931  					} else {
  2932  						hasProto = true
  2933  					}
  2934  				}
  2935  				if ne != nil && !isProto {
  2936  					ne.emitNamed(key)
  2937  				} else {
  2938  					e.c.emitExpr(valueExpr, true)
  2939  				}
  2940  				switch prop.Kind {
  2941  				case ast.PropertyKindValue:
  2942  					if isProto {
  2943  						e.c.emit(setProto)
  2944  					} else {
  2945  						e.c.emit(putProp(key))
  2946  					}
  2947  				case ast.PropertyKindMethod:
  2948  					e.c.emit(&defineMethodKeyed{key: key, enumerable: true})
  2949  				case ast.PropertyKindGet:
  2950  					e.c.emit(&defineGetterKeyed{key: key, enumerable: true})
  2951  				case ast.PropertyKindSet:
  2952  					e.c.emit(&defineSetterKeyed{key: key, enumerable: true})
  2953  				default:
  2954  					e.c.assert(false, e.offset, "unknown property kind: %s", prop.Kind)
  2955  					panic("unreachable")
  2956  				}
  2957  			}
  2958  		case *ast.PropertyShort:
  2959  			key := prop.Name.Name
  2960  			if prop.Initializer != nil {
  2961  				e.c.throwSyntaxError(int(prop.Initializer.Idx0())-1, "Invalid shorthand property initializer")
  2962  			}
  2963  			if e.c.scope.strict && key == "let" {
  2964  				e.c.throwSyntaxError(e.offset, "'let' cannot be used as a shorthand property in strict mode")
  2965  			}
  2966  			e.c.compileIdentifierExpression(&prop.Name).emitGetter(true)
  2967  			e.c.emit(putProp(key))
  2968  		case *ast.SpreadElement:
  2969  			e.c.compileExpression(prop.Expression).emitGetter(true)
  2970  			e.c.emit(copySpread)
  2971  		default:
  2972  			e.c.assert(false, e.offset, "unknown Property type: %T", prop)
  2973  			panic("unreachable")
  2974  		}
  2975  	}
  2976  	if !putOnStack {
  2977  		e.c.emit(pop)
  2978  	}
  2979  }
  2980  
  2981  func (c *compiler) compileObjectLiteral(v *ast.ObjectLiteral) compiledExpr {
  2982  	r := &compiledObjectLiteral{
  2983  		expr: v,
  2984  	}
  2985  	r.init(c, v.Idx0())
  2986  	return r
  2987  }
  2988  
  2989  func (e *compiledArrayLiteral) emitGetter(putOnStack bool) {
  2990  	e.addSrcMap()
  2991  	hasSpread := false
  2992  	mark := len(e.c.p.code)
  2993  	e.c.emit(nil)
  2994  	for _, v := range e.expr.Value {
  2995  		if spread, ok := v.(*ast.SpreadElement); ok {
  2996  			hasSpread = true
  2997  			e.c.compileExpression(spread.Expression).emitGetter(true)
  2998  			e.c.emit(pushArraySpread)
  2999  		} else {
  3000  			if v != nil {
  3001  				e.c.emitExpr(e.c.compileExpression(v), true)
  3002  			} else {
  3003  				e.c.emit(loadNil)
  3004  			}
  3005  			e.c.emit(pushArrayItem)
  3006  		}
  3007  	}
  3008  	var objCount uint32
  3009  	if !hasSpread {
  3010  		objCount = uint32(len(e.expr.Value))
  3011  	}
  3012  	e.c.p.code[mark] = newArray(objCount)
  3013  	if !putOnStack {
  3014  		e.c.emit(pop)
  3015  	}
  3016  }
  3017  
  3018  func (c *compiler) compileArrayLiteral(v *ast.ArrayLiteral) compiledExpr {
  3019  	r := &compiledArrayLiteral{
  3020  		expr: v,
  3021  	}
  3022  	r.init(c, v.Idx0())
  3023  	return r
  3024  }
  3025  
  3026  func (e *compiledRegexpLiteral) emitGetter(putOnStack bool) {
  3027  	if putOnStack {
  3028  		pattern, err := compileRegexp(e.expr.Pattern, e.expr.Flags)
  3029  		if err != nil {
  3030  			e.c.throwSyntaxError(e.offset, err.Error())
  3031  		}
  3032  
  3033  		e.c.emit(&newRegexp{pattern: pattern, src: newStringValue(e.expr.Pattern)})
  3034  	}
  3035  }
  3036  
  3037  func (c *compiler) compileRegexpLiteral(v *ast.RegExpLiteral) compiledExpr {
  3038  	r := &compiledRegexpLiteral{
  3039  		expr: v,
  3040  	}
  3041  	r.init(c, v.Idx0())
  3042  	return r
  3043  }
  3044  
  3045  func (c *compiler) emitCallee(callee compiledExpr) (calleeName unistring.String) {
  3046  	switch callee := callee.(type) {
  3047  	case *compiledDotExpr:
  3048  		callee.left.emitGetter(true)
  3049  		c.emit(getPropCallee(callee.name))
  3050  	case *compiledPrivateDotExpr:
  3051  		callee.left.emitGetter(true)
  3052  		rn, id := c.resolvePrivateName(callee.name, callee.offset)
  3053  		if rn != nil {
  3054  			c.emit((*getPrivatePropResCallee)(rn))
  3055  		} else {
  3056  			c.emit((*getPrivatePropIdCallee)(id))
  3057  		}
  3058  	case *compiledSuperDotExpr:
  3059  		c.emitLoadThis()
  3060  		c.emit(loadSuper)
  3061  		c.emit(getPropRecvCallee(callee.name))
  3062  	case *compiledBracketExpr:
  3063  		callee.left.emitGetter(true)
  3064  		callee.member.emitGetter(true)
  3065  		c.emit(getElemCallee)
  3066  	case *compiledSuperBracketExpr:
  3067  		c.emitLoadThis()
  3068  		c.emit(loadSuper)
  3069  		callee.member.emitGetter(true)
  3070  		c.emit(getElemRecvCallee)
  3071  	case *compiledIdentifierExpr:
  3072  		calleeName = callee.name
  3073  		callee.emitGetterAndCallee()
  3074  	case *compiledOptionalChain:
  3075  		c.startOptChain()
  3076  		c.emitCallee(callee.expr)
  3077  		c.endOptChain()
  3078  	case *compiledOptional:
  3079  		c.emitCallee(callee.expr)
  3080  		c.block.conts = append(c.block.conts, len(c.p.code))
  3081  		c.emit(nil)
  3082  	case *compiledSuperExpr:
  3083  		// no-op
  3084  	default:
  3085  		c.emit(loadUndef)
  3086  		callee.emitGetter(true)
  3087  	}
  3088  	return
  3089  }
  3090  
  3091  func (e *compiledCallExpr) emitGetter(putOnStack bool) {
  3092  	if e.isVariadic {
  3093  		e.c.emit(startVariadic)
  3094  	}
  3095  	calleeName := e.c.emitCallee(e.callee)
  3096  
  3097  	for _, expr := range e.args {
  3098  		expr.emitGetter(true)
  3099  	}
  3100  
  3101  	e.addSrcMap()
  3102  	if _, ok := e.callee.(*compiledSuperExpr); ok {
  3103  		b, eval := e.c.scope.lookupThis()
  3104  		e.c.assert(eval || b != nil, e.offset, "super call, but no 'this' binding")
  3105  		if eval {
  3106  			e.c.emit(resolveThisDynamic{})
  3107  		} else {
  3108  			b.markAccessPoint()
  3109  			e.c.emit(resolveThisStack{})
  3110  		}
  3111  		if e.isVariadic {
  3112  			e.c.emit(superCallVariadic)
  3113  		} else {
  3114  			e.c.emit(superCall(len(e.args)))
  3115  		}
  3116  	} else if calleeName == "eval" {
  3117  		foundVar := false
  3118  		for sc := e.c.scope; sc != nil; sc = sc.outer {
  3119  			if !foundVar && (sc.variable || sc.isFunction()) {
  3120  				foundVar = true
  3121  				if !sc.strict {
  3122  					sc.dynamic = true
  3123  				}
  3124  			}
  3125  			sc.dynLookup = true
  3126  		}
  3127  
  3128  		if e.c.scope.strict {
  3129  			if e.isVariadic {
  3130  				e.c.emit(callEvalVariadicStrict)
  3131  			} else {
  3132  				e.c.emit(callEvalStrict(len(e.args)))
  3133  			}
  3134  		} else {
  3135  			if e.isVariadic {
  3136  				e.c.emit(callEvalVariadic)
  3137  			} else {
  3138  				e.c.emit(callEval(len(e.args)))
  3139  			}
  3140  		}
  3141  	} else {
  3142  		if e.isVariadic {
  3143  			e.c.emit(callVariadic)
  3144  		} else {
  3145  			e.c.emit(call(len(e.args)))
  3146  		}
  3147  	}
  3148  	if e.isVariadic {
  3149  		e.c.emit(endVariadic)
  3150  	}
  3151  	if !putOnStack {
  3152  		e.c.emit(pop)
  3153  	}
  3154  }
  3155  
  3156  func (e *compiledCallExpr) deleteExpr() compiledExpr {
  3157  	r := &defaultDeleteExpr{
  3158  		expr: e,
  3159  	}
  3160  	r.init(e.c, file.Idx(e.offset+1))
  3161  	return r
  3162  }
  3163  
  3164  func (c *compiler) compileSpreadCallArgument(spread *ast.SpreadElement) compiledExpr {
  3165  	r := &compiledSpreadCallArgument{
  3166  		expr: c.compileExpression(spread.Expression),
  3167  	}
  3168  	r.init(c, spread.Idx0())
  3169  	return r
  3170  }
  3171  
  3172  func (c *compiler) compileCallee(v ast.Expression) compiledExpr {
  3173  	if sup, ok := v.(*ast.SuperExpression); ok {
  3174  		if s := c.scope.nearestThis(); s != nil && s.funcType == funcDerivedCtor {
  3175  			e := &compiledSuperExpr{}
  3176  			e.init(c, sup.Idx)
  3177  			return e
  3178  		}
  3179  		c.throwSyntaxError(int(v.Idx0())-1, "'super' keyword unexpected here")
  3180  		panic("unreachable")
  3181  	}
  3182  	return c.compileExpression(v)
  3183  }
  3184  
  3185  func (c *compiler) compileCallExpression(v *ast.CallExpression) compiledExpr {
  3186  
  3187  	args := make([]compiledExpr, len(v.ArgumentList))
  3188  	isVariadic := false
  3189  	for i, argExpr := range v.ArgumentList {
  3190  		if spread, ok := argExpr.(*ast.SpreadElement); ok {
  3191  			args[i] = c.compileSpreadCallArgument(spread)
  3192  			isVariadic = true
  3193  		} else {
  3194  			args[i] = c.compileExpression(argExpr)
  3195  		}
  3196  	}
  3197  
  3198  	r := &compiledCallExpr{
  3199  		args:       args,
  3200  		callee:     c.compileCallee(v.Callee),
  3201  		isVariadic: isVariadic,
  3202  	}
  3203  	r.init(c, v.LeftParenthesis)
  3204  	return r
  3205  }
  3206  
  3207  func (c *compiler) compileIdentifierExpression(v *ast.Identifier) compiledExpr {
  3208  	if c.scope.strict {
  3209  		c.checkIdentifierName(v.Name, int(v.Idx)-1)
  3210  	}
  3211  
  3212  	r := &compiledIdentifierExpr{
  3213  		name: v.Name,
  3214  	}
  3215  	r.offset = int(v.Idx) - 1
  3216  	r.init(c, v.Idx0())
  3217  	return r
  3218  }
  3219  
  3220  func (c *compiler) compileNumberLiteral(v *ast.NumberLiteral) compiledExpr {
  3221  	if c.scope.strict && len(v.Literal) > 1 && v.Literal[0] == '0' && v.Literal[1] <= '7' && v.Literal[1] >= '0' {
  3222  		c.throwSyntaxError(int(v.Idx)-1, "Octal literals are not allowed in strict mode")
  3223  		panic("Unreachable")
  3224  	}
  3225  	var val Value
  3226  	switch num := v.Value.(type) {
  3227  	case int64:
  3228  		val = intToValue(num)
  3229  	case float64:
  3230  		val = floatToValue(num)
  3231  	default:
  3232  		c.assert(false, int(v.Idx)-1, "Unsupported number literal type: %T", v.Value)
  3233  		panic("unreachable")
  3234  	}
  3235  	r := &compiledLiteral{
  3236  		val: val,
  3237  	}
  3238  	r.init(c, v.Idx0())
  3239  	return r
  3240  }
  3241  
  3242  func (c *compiler) compileStringLiteral(v *ast.StringLiteral) compiledExpr {
  3243  	r := &compiledLiteral{
  3244  		val: stringValueFromRaw(v.Value),
  3245  	}
  3246  	r.init(c, v.Idx0())
  3247  	return r
  3248  }
  3249  
  3250  func (c *compiler) compileTemplateLiteral(v *ast.TemplateLiteral) compiledExpr {
  3251  	r := &compiledTemplateLiteral{}
  3252  	if v.Tag != nil {
  3253  		r.tag = c.compileExpression(v.Tag)
  3254  	}
  3255  	ce := make([]compiledExpr, len(v.Expressions))
  3256  	for i, expr := range v.Expressions {
  3257  		ce[i] = c.compileExpression(expr)
  3258  	}
  3259  	r.expressions = ce
  3260  	r.elements = v.Elements
  3261  	r.init(c, v.Idx0())
  3262  	return r
  3263  }
  3264  
  3265  func (c *compiler) compileBooleanLiteral(v *ast.BooleanLiteral) compiledExpr {
  3266  	var val Value
  3267  	if v.Value {
  3268  		val = valueTrue
  3269  	} else {
  3270  		val = valueFalse
  3271  	}
  3272  
  3273  	r := &compiledLiteral{
  3274  		val: val,
  3275  	}
  3276  	r.init(c, v.Idx0())
  3277  	return r
  3278  }
  3279  
  3280  func (c *compiler) compileAssignExpression(v *ast.AssignExpression) compiledExpr {
  3281  	// log.Printf("compileAssignExpression(): %+v", v)
  3282  
  3283  	r := &compiledAssignExpr{
  3284  		left:     c.compileExpression(v.Left),
  3285  		right:    c.compileExpression(v.Right),
  3286  		operator: v.Operator,
  3287  	}
  3288  	r.init(c, v.Idx0())
  3289  	return r
  3290  }
  3291  
  3292  func (e *compiledEnumGetExpr) emitGetter(putOnStack bool) {
  3293  	e.c.emit(enumGet)
  3294  	if !putOnStack {
  3295  		e.c.emit(pop)
  3296  	}
  3297  }
  3298  
  3299  func (c *compiler) compileObjectAssignmentPattern(v *ast.ObjectPattern) compiledExpr {
  3300  	r := &compiledObjectAssignmentPattern{
  3301  		expr: v,
  3302  	}
  3303  	r.init(c, v.Idx0())
  3304  	return r
  3305  }
  3306  
  3307  func (e *compiledObjectAssignmentPattern) emitGetter(putOnStack bool) {
  3308  	if putOnStack {
  3309  		e.c.emit(loadUndef)
  3310  	}
  3311  }
  3312  
  3313  func (c *compiler) compileArrayAssignmentPattern(v *ast.ArrayPattern) compiledExpr {
  3314  	r := &compiledArrayAssignmentPattern{
  3315  		expr: v,
  3316  	}
  3317  	r.init(c, v.Idx0())
  3318  	return r
  3319  }
  3320  
  3321  func (e *compiledArrayAssignmentPattern) emitGetter(putOnStack bool) {
  3322  	if putOnStack {
  3323  		e.c.emit(loadUndef)
  3324  	}
  3325  }
  3326  
  3327  func (c *compiler) emitExpr(expr compiledExpr, putOnStack bool) {
  3328  	if expr.constant() {
  3329  		c.emitConst(expr, putOnStack)
  3330  	} else {
  3331  		expr.emitGetter(putOnStack)
  3332  	}
  3333  }
  3334  
  3335  type namedEmitter interface {
  3336  	emitNamed(name unistring.String)
  3337  }
  3338  
  3339  func (c *compiler) emitNamed(expr compiledExpr, name unistring.String) {
  3340  	if en, ok := expr.(namedEmitter); ok {
  3341  		en.emitNamed(name)
  3342  	} else {
  3343  		expr.emitGetter(true)
  3344  	}
  3345  }
  3346  
  3347  func (c *compiler) emitNamedOrConst(expr compiledExpr, name unistring.String) {
  3348  	if expr.constant() {
  3349  		c.emitConst(expr, true)
  3350  	} else {
  3351  		c.emitNamed(expr, name)
  3352  	}
  3353  }
  3354  
  3355  func (e *compiledFunctionLiteral) emitNamed(name unistring.String) {
  3356  	e.lhsName = name
  3357  	e.emitGetter(true)
  3358  }
  3359  
  3360  func (e *compiledClassLiteral) emitNamed(name unistring.String) {
  3361  	e.lhsName = name
  3362  	e.emitGetter(true)
  3363  }
  3364  
  3365  func (c *compiler) emitPattern(pattern ast.Pattern, emitter func(target, init compiledExpr), putOnStack bool) {
  3366  	switch pattern := pattern.(type) {
  3367  	case *ast.ObjectPattern:
  3368  		c.emitObjectPattern(pattern, emitter, putOnStack)
  3369  	case *ast.ArrayPattern:
  3370  		c.emitArrayPattern(pattern, emitter, putOnStack)
  3371  	default:
  3372  		c.assert(false, int(pattern.Idx0())-1, "unsupported Pattern: %T", pattern)
  3373  		panic("unreachable")
  3374  	}
  3375  }
  3376  
  3377  func (c *compiler) emitAssign(target ast.Expression, init compiledExpr, emitAssignSimple func(target, init compiledExpr)) {
  3378  	pattern, isPattern := target.(ast.Pattern)
  3379  	if isPattern {
  3380  		init.emitGetter(true)
  3381  		c.emitPattern(pattern, emitAssignSimple, false)
  3382  	} else {
  3383  		emitAssignSimple(c.compileExpression(target), init)
  3384  	}
  3385  }
  3386  
  3387  func (c *compiler) emitObjectPattern(pattern *ast.ObjectPattern, emitAssign func(target, init compiledExpr), putOnStack bool) {
  3388  	if pattern.Rest != nil {
  3389  		c.emit(createDestructSrc)
  3390  	} else {
  3391  		c.emit(checkObjectCoercible)
  3392  	}
  3393  	for _, prop := range pattern.Properties {
  3394  		switch prop := prop.(type) {
  3395  		case *ast.PropertyShort:
  3396  			c.emit(dup)
  3397  			emitAssign(c.compileIdentifierExpression(&prop.Name), c.compilePatternInitExpr(func() {
  3398  				c.emit(getProp(prop.Name.Name))
  3399  			}, prop.Initializer, prop.Idx0()))
  3400  		case *ast.PropertyKeyed:
  3401  			c.emit(dup)
  3402  			c.compileExpression(prop.Key).emitGetter(true)
  3403  			c.emit(_toPropertyKey{})
  3404  			var target ast.Expression
  3405  			var initializer ast.Expression
  3406  			if e, ok := prop.Value.(*ast.AssignExpression); ok {
  3407  				target = e.Left
  3408  				initializer = e.Right
  3409  			} else {
  3410  				target = prop.Value
  3411  			}
  3412  			c.emitAssign(target, c.compilePatternInitExpr(func() {
  3413  				c.emit(getKey)
  3414  			}, initializer, prop.Idx0()), emitAssign)
  3415  		default:
  3416  			c.throwSyntaxError(int(prop.Idx0()-1), "Unsupported AssignmentProperty type: %T", prop)
  3417  		}
  3418  	}
  3419  	if pattern.Rest != nil {
  3420  		emitAssign(c.compileExpression(pattern.Rest), c.compileEmitterExpr(func() {
  3421  			c.emit(copyRest)
  3422  		}, pattern.Rest.Idx0()))
  3423  		c.emit(pop)
  3424  	}
  3425  	if !putOnStack {
  3426  		c.emit(pop)
  3427  	}
  3428  }
  3429  
  3430  func (c *compiler) emitArrayPattern(pattern *ast.ArrayPattern, emitAssign func(target, init compiledExpr), putOnStack bool) {
  3431  	c.emit(iterate)
  3432  	for _, elt := range pattern.Elements {
  3433  		switch elt := elt.(type) {
  3434  		case nil:
  3435  			c.emit(iterGetNextOrUndef{}, pop)
  3436  		case *ast.AssignExpression:
  3437  			c.emitAssign(elt.Left, c.compilePatternInitExpr(func() {
  3438  				c.emit(iterGetNextOrUndef{})
  3439  			}, elt.Right, elt.Idx0()), emitAssign)
  3440  		default:
  3441  			c.emitAssign(elt, c.compileEmitterExpr(func() {
  3442  				c.emit(iterGetNextOrUndef{})
  3443  			}, elt.Idx0()), emitAssign)
  3444  		}
  3445  	}
  3446  	if pattern.Rest != nil {
  3447  		c.emitAssign(pattern.Rest, c.compileEmitterExpr(func() {
  3448  			c.emit(newArrayFromIter)
  3449  		}, pattern.Rest.Idx0()), emitAssign)
  3450  	} else {
  3451  		c.emit(enumPopClose)
  3452  	}
  3453  
  3454  	if !putOnStack {
  3455  		c.emit(pop)
  3456  	}
  3457  }
  3458  
  3459  func (e *compiledObjectAssignmentPattern) emitSetter(valueExpr compiledExpr, putOnStack bool) {
  3460  	valueExpr.emitGetter(true)
  3461  	e.c.emitObjectPattern(e.expr, e.c.emitPatternAssign, putOnStack)
  3462  }
  3463  
  3464  func (e *compiledArrayAssignmentPattern) emitSetter(valueExpr compiledExpr, putOnStack bool) {
  3465  	valueExpr.emitGetter(true)
  3466  	e.c.emitArrayPattern(e.expr, e.c.emitPatternAssign, putOnStack)
  3467  }
  3468  
  3469  type compiledPatternInitExpr struct {
  3470  	baseCompiledExpr
  3471  	emitSrc func()
  3472  	def     compiledExpr
  3473  }
  3474  
  3475  func (e *compiledPatternInitExpr) emitGetter(putOnStack bool) {
  3476  	if !putOnStack {
  3477  		return
  3478  	}
  3479  	e.emitSrc()
  3480  	if e.def != nil {
  3481  		mark := len(e.c.p.code)
  3482  		e.c.emit(nil)
  3483  		e.c.emitExpr(e.def, true)
  3484  		e.c.p.code[mark] = jdef(len(e.c.p.code) - mark)
  3485  	}
  3486  }
  3487  
  3488  func (e *compiledPatternInitExpr) emitNamed(name unistring.String) {
  3489  	e.emitSrc()
  3490  	if e.def != nil {
  3491  		mark := len(e.c.p.code)
  3492  		e.c.emit(nil)
  3493  		e.c.emitNamedOrConst(e.def, name)
  3494  		e.c.p.code[mark] = jdef(len(e.c.p.code) - mark)
  3495  	}
  3496  }
  3497  
  3498  func (c *compiler) compilePatternInitExpr(emitSrc func(), def ast.Expression, idx file.Idx) compiledExpr {
  3499  	r := &compiledPatternInitExpr{
  3500  		emitSrc: emitSrc,
  3501  		def:     c.compileExpression(def),
  3502  	}
  3503  	r.init(c, idx)
  3504  	return r
  3505  }
  3506  
  3507  type compiledEmitterExpr struct {
  3508  	baseCompiledExpr
  3509  	emitter      func()
  3510  	namedEmitter func(name unistring.String)
  3511  }
  3512  
  3513  func (e *compiledEmitterExpr) emitGetter(putOnStack bool) {
  3514  	if e.emitter != nil {
  3515  		e.emitter()
  3516  	} else {
  3517  		e.namedEmitter("")
  3518  	}
  3519  	if !putOnStack {
  3520  		e.c.emit(pop)
  3521  	}
  3522  }
  3523  
  3524  func (e *compiledEmitterExpr) emitNamed(name unistring.String) {
  3525  	if e.namedEmitter != nil {
  3526  		e.namedEmitter(name)
  3527  	} else {
  3528  		e.emitter()
  3529  	}
  3530  }
  3531  
  3532  func (c *compiler) compileEmitterExpr(emitter func(), idx file.Idx) *compiledEmitterExpr {
  3533  	r := &compiledEmitterExpr{
  3534  		emitter: emitter,
  3535  	}
  3536  	r.init(c, idx)
  3537  	return r
  3538  }
  3539  
  3540  func (e *compiledSpreadCallArgument) emitGetter(putOnStack bool) {
  3541  	e.expr.emitGetter(putOnStack)
  3542  	if putOnStack {
  3543  		e.c.emit(pushSpread)
  3544  	}
  3545  }
  3546  
  3547  func (c *compiler) startOptChain() {
  3548  	c.block = &block{
  3549  		typ:   blockOptChain,
  3550  		outer: c.block,
  3551  	}
  3552  }
  3553  
  3554  func (c *compiler) endOptChain() {
  3555  	lbl := len(c.p.code)
  3556  	for _, item := range c.block.breaks {
  3557  		c.p.code[item] = jopt(lbl - item)
  3558  	}
  3559  	for _, item := range c.block.conts {
  3560  		c.p.code[item] = joptc(lbl - item)
  3561  	}
  3562  	c.block = c.block.outer
  3563  }
  3564  
  3565  func (e *compiledOptionalChain) emitGetter(putOnStack bool) {
  3566  	e.c.startOptChain()
  3567  	e.expr.emitGetter(true)
  3568  	e.c.endOptChain()
  3569  	if !putOnStack {
  3570  		e.c.emit(pop)
  3571  	}
  3572  }
  3573  
  3574  func (e *compiledOptional) emitGetter(putOnStack bool) {
  3575  	e.expr.emitGetter(putOnStack)
  3576  	if putOnStack {
  3577  		e.c.block.breaks = append(e.c.block.breaks, len(e.c.p.code))
  3578  		e.c.emit(nil)
  3579  	}
  3580  }
  3581  
  3582  func (e *compiledAwaitExpression) emitGetter(putOnStack bool) {
  3583  	e.arg.emitGetter(true)
  3584  	e.c.emit(await)
  3585  	if !putOnStack {
  3586  		e.c.emit(pop)
  3587  	}
  3588  }
  3589  
  3590  func (e *compiledYieldExpression) emitGetter(putOnStack bool) {
  3591  	if e.arg != nil {
  3592  		e.arg.emitGetter(true)
  3593  	} else {
  3594  		e.c.emit(loadUndef)
  3595  	}
  3596  	if putOnStack {
  3597  		if e.delegate {
  3598  			e.c.emit(yieldDelegateRes)
  3599  		} else {
  3600  			e.c.emit(yieldRes)
  3601  		}
  3602  	} else {
  3603  		if e.delegate {
  3604  			e.c.emit(yieldDelegate)
  3605  		} else {
  3606  			e.c.emit(yield)
  3607  		}
  3608  	}
  3609  }