go.ketch.com/lib/goja@v0.0.1/compiler_expr.go (about)

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