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

     1  package goja
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"runtime"
     7  	"strconv"
     8  	"strings"
     9  	"sync"
    10  	"sync/atomic"
    11  
    12  	"go.ketch.com/lib/goja/unistring"
    13  )
    14  
    15  const (
    16  	maxInt = 1 << 53
    17  )
    18  
    19  type valueStack []Value
    20  
    21  type stash struct {
    22  	values    []Value
    23  	extraArgs []Value
    24  	names     map[unistring.String]uint32
    25  	obj       *Object
    26  
    27  	outer *stash
    28  
    29  	// If this is a top-level function stash, sets the type of the function. If set, dynamic var declarations
    30  	// created by direct eval go here.
    31  	funcType funcType
    32  }
    33  
    34  type context struct {
    35  	prg       *Program
    36  	funcName  unistring.String // only valid when prg is nil
    37  	stash     *stash
    38  	privEnv   *privateEnv
    39  	newTarget Value
    40  	result    Value
    41  	pc, sb    int
    42  	args      int
    43  }
    44  
    45  type iterStackItem struct {
    46  	val  Value
    47  	f    iterNextFunc
    48  	iter *iteratorRecord
    49  }
    50  
    51  type ref interface {
    52  	get() Value
    53  	set(Value)
    54  	init(Value)
    55  	refname() unistring.String
    56  }
    57  
    58  type stashRef struct {
    59  	n   unistring.String
    60  	v   *[]Value
    61  	idx int
    62  }
    63  
    64  func (r *stashRef) get() Value {
    65  	return nilSafe((*r.v)[r.idx])
    66  }
    67  
    68  func (r *stashRef) set(v Value) {
    69  	(*r.v)[r.idx] = v
    70  }
    71  
    72  func (r *stashRef) init(v Value) {
    73  	r.set(v)
    74  }
    75  
    76  func (r *stashRef) refname() unistring.String {
    77  	return r.n
    78  }
    79  
    80  type thisRef struct {
    81  	v   *[]Value
    82  	idx int
    83  }
    84  
    85  func (r *thisRef) get() Value {
    86  	v := (*r.v)[r.idx]
    87  	if v == nil {
    88  		panic(referenceError("Must call super constructor in derived class before accessing 'this'"))
    89  	}
    90  
    91  	return v
    92  }
    93  
    94  func (r *thisRef) set(v Value) {
    95  	ptr := &(*r.v)[r.idx]
    96  	if *ptr != nil {
    97  		panic(referenceError("Super constructor may only be called once"))
    98  	}
    99  	*ptr = v
   100  }
   101  
   102  func (r *thisRef) init(v Value) {
   103  	r.set(v)
   104  }
   105  
   106  func (r *thisRef) refname() unistring.String {
   107  	return thisBindingName
   108  }
   109  
   110  type stashRefLex struct {
   111  	stashRef
   112  }
   113  
   114  func (r *stashRefLex) get() Value {
   115  	v := (*r.v)[r.idx]
   116  	if v == nil {
   117  		panic(errAccessBeforeInit)
   118  	}
   119  	return v
   120  }
   121  
   122  func (r *stashRefLex) set(v Value) {
   123  	p := &(*r.v)[r.idx]
   124  	if *p == nil {
   125  		panic(errAccessBeforeInit)
   126  	}
   127  	*p = v
   128  }
   129  
   130  func (r *stashRefLex) init(v Value) {
   131  	(*r.v)[r.idx] = v
   132  }
   133  
   134  type stashRefConst struct {
   135  	stashRefLex
   136  	strictConst bool
   137  }
   138  
   139  func (r *stashRefConst) set(v Value) {
   140  	if r.strictConst {
   141  		panic(errAssignToConst)
   142  	}
   143  }
   144  
   145  type objRef struct {
   146  	base    *Object
   147  	name    unistring.String
   148  	this    Value
   149  	strict  bool
   150  	binding bool
   151  }
   152  
   153  func (r *objRef) get() Value {
   154  	return r.base.self.getStr(r.name, r.this)
   155  }
   156  
   157  func (r *objRef) set(v Value) {
   158  	if r.strict && r.binding && !r.base.self.hasOwnPropertyStr(r.name) {
   159  		panic(referenceError(fmt.Sprintf("%s is not defined", r.name)))
   160  	}
   161  	if r.this != nil {
   162  		r.base.setStr(r.name, v, r.this, r.strict)
   163  	} else {
   164  		r.base.self.setOwnStr(r.name, v, r.strict)
   165  	}
   166  }
   167  
   168  func (r *objRef) init(v Value) {
   169  	if r.this != nil {
   170  		r.base.setStr(r.name, v, r.this, r.strict)
   171  	} else {
   172  		r.base.self.setOwnStr(r.name, v, r.strict)
   173  	}
   174  }
   175  
   176  func (r *objRef) refname() unistring.String {
   177  	return r.name
   178  }
   179  
   180  type privateRefRes struct {
   181  	base *Object
   182  	name *resolvedPrivateName
   183  }
   184  
   185  func (p *privateRefRes) get() Value {
   186  	return (*getPrivatePropRes)(p.name)._get(p.base, p.base.runtime.vm)
   187  }
   188  
   189  func (p *privateRefRes) set(value Value) {
   190  	(*setPrivatePropRes)(p.name)._set(p.base, value, p.base.runtime.vm)
   191  }
   192  
   193  func (p *privateRefRes) init(value Value) {
   194  	panic("not supported")
   195  }
   196  
   197  func (p *privateRefRes) refname() unistring.String {
   198  	return p.name.string()
   199  }
   200  
   201  type privateRefId struct {
   202  	base *Object
   203  	id   *privateId
   204  }
   205  
   206  func (p *privateRefId) get() Value {
   207  	return p.base.runtime.vm.getPrivateProp(p.base, p.id.name, p.id.typ, p.id.idx, p.id.isMethod)
   208  }
   209  
   210  func (p *privateRefId) set(value Value) {
   211  	p.base.runtime.vm.setPrivateProp(p.base, p.id.name, p.id.typ, p.id.idx, p.id.isMethod, value)
   212  }
   213  
   214  func (p *privateRefId) init(value Value) {
   215  	panic("not supported")
   216  }
   217  
   218  func (p *privateRefId) refname() unistring.String {
   219  	return p.id.string()
   220  }
   221  
   222  type unresolvedRef struct {
   223  	runtime *Runtime
   224  	name    unistring.String
   225  }
   226  
   227  func (r *unresolvedRef) get() Value {
   228  	r.runtime.throwReferenceError(r.name)
   229  	panic("Unreachable")
   230  }
   231  
   232  func (r *unresolvedRef) set(Value) {
   233  	r.get()
   234  }
   235  
   236  func (r *unresolvedRef) init(Value) {
   237  	r.get()
   238  }
   239  
   240  func (r *unresolvedRef) refname() unistring.String {
   241  	return r.name
   242  }
   243  
   244  type vm struct {
   245  	r            *Runtime
   246  	prg          *Program
   247  	funcName     unistring.String // only valid when prg == nil
   248  	pc           int
   249  	stack        valueStack
   250  	sp, sb, args int
   251  
   252  	stash     *stash
   253  	privEnv   *privateEnv
   254  	callStack []context
   255  	iterStack []iterStackItem
   256  	refStack  []ref
   257  	newTarget Value
   258  	result    Value
   259  
   260  	maxCallStackSize int
   261  
   262  	stashAllocs int
   263  	halt        bool
   264  
   265  	interrupted   uint32
   266  	interruptVal  interface{}
   267  	interruptLock sync.Mutex
   268  }
   269  
   270  type instruction interface {
   271  	exec(*vm)
   272  }
   273  
   274  func intToValue(i int64) Value {
   275  	if i >= -maxInt && i <= maxInt {
   276  		if i >= -128 && i <= 127 {
   277  			return intCache[i+128]
   278  		}
   279  		return valueInt(i)
   280  	}
   281  	return valueFloat(i)
   282  }
   283  
   284  func floatToInt(f float64) (result int64, ok bool) {
   285  	if (f != 0 || !math.Signbit(f)) && !math.IsInf(f, 0) && f == math.Trunc(f) && f >= -maxInt && f <= maxInt {
   286  		return int64(f), true
   287  	}
   288  	return 0, false
   289  }
   290  
   291  func floatToValue(f float64) (result Value) {
   292  	if i, ok := floatToInt(f); ok {
   293  		return intToValue(i)
   294  	}
   295  	switch {
   296  	case f == 0:
   297  		return _negativeZero
   298  	case math.IsNaN(f):
   299  		return _NaN
   300  	case math.IsInf(f, 1):
   301  		return _positiveInf
   302  	case math.IsInf(f, -1):
   303  		return _negativeInf
   304  	}
   305  	return valueFloat(f)
   306  }
   307  
   308  func assertInt64(v Value) (int64, bool) {
   309  	num := v.ToNumber()
   310  	if i, ok := num.(valueInt); ok {
   311  		return int64(i), true
   312  	}
   313  	if f, ok := num.(valueFloat); ok {
   314  		if i, ok := floatToInt(float64(f)); ok {
   315  			return i, true
   316  		}
   317  	}
   318  	return 0, false
   319  }
   320  
   321  func (s *valueStack) expand(idx int) {
   322  	if idx < len(*s) {
   323  		return
   324  	}
   325  	idx++
   326  	if idx < cap(*s) {
   327  		*s = (*s)[:idx]
   328  	} else {
   329  		var newCap int
   330  		if idx < 1024 {
   331  			newCap = idx * 2
   332  		} else {
   333  			newCap = (idx + 1025) &^ 1023
   334  		}
   335  		n := make([]Value, idx, newCap)
   336  		copy(n, *s)
   337  		*s = n
   338  	}
   339  }
   340  
   341  func stashObjHas(obj *Object, name unistring.String) bool {
   342  	if obj.self.hasPropertyStr(name) {
   343  		if unscopables, ok := obj.self.getSym(SymUnscopables, nil).(*Object); ok {
   344  			if b := unscopables.self.getStr(name, nil); b != nil {
   345  				return !b.ToBoolean()
   346  			}
   347  		}
   348  		return true
   349  	}
   350  	return false
   351  }
   352  
   353  func (s *stash) isVariable() bool {
   354  	return s.funcType != funcNone
   355  }
   356  
   357  func (s *stash) initByIdx(idx uint32, v Value) {
   358  	if s.obj != nil {
   359  		panic("Attempt to init by idx into an object scope")
   360  	}
   361  	s.values[idx] = v
   362  }
   363  
   364  func (s *stash) initByName(name unistring.String, v Value) {
   365  	if idx, exists := s.names[name]; exists {
   366  		s.values[idx&^maskTyp] = v
   367  	} else {
   368  		panic(referenceError(fmt.Sprintf("%s is not defined", name)))
   369  	}
   370  }
   371  
   372  func (s *stash) getByIdx(idx uint32) Value {
   373  	return s.values[idx]
   374  }
   375  
   376  func (s *stash) getByName(name unistring.String) (v Value, exists bool) {
   377  	if s.obj != nil {
   378  		if stashObjHas(s.obj, name) {
   379  			return nilSafe(s.obj.self.getStr(name, nil)), true
   380  		}
   381  		return nil, false
   382  	}
   383  	if idx, exists := s.names[name]; exists {
   384  		v := s.values[idx&^maskTyp]
   385  		if v == nil {
   386  			if idx&maskVar == 0 {
   387  				panic(errAccessBeforeInit)
   388  			} else {
   389  				v = _undefined
   390  			}
   391  		}
   392  		return v, true
   393  	}
   394  	return nil, false
   395  }
   396  
   397  func (s *stash) getRefByName(name unistring.String, strict bool) ref {
   398  	if obj := s.obj; obj != nil {
   399  		if stashObjHas(obj, name) {
   400  			return &objRef{
   401  				base:    obj,
   402  				name:    name,
   403  				strict:  strict,
   404  				binding: true,
   405  			}
   406  		}
   407  	} else {
   408  		if idx, exists := s.names[name]; exists {
   409  			if idx&maskVar == 0 {
   410  				if idx&maskConst == 0 {
   411  					return &stashRefLex{
   412  						stashRef: stashRef{
   413  							n:   name,
   414  							v:   &s.values,
   415  							idx: int(idx &^ maskTyp),
   416  						},
   417  					}
   418  				} else {
   419  					return &stashRefConst{
   420  						stashRefLex: stashRefLex{
   421  							stashRef: stashRef{
   422  								n:   name,
   423  								v:   &s.values,
   424  								idx: int(idx &^ maskTyp),
   425  							},
   426  						},
   427  						strictConst: strict || (idx&maskStrict != 0),
   428  					}
   429  				}
   430  			} else {
   431  				return &stashRef{
   432  					n:   name,
   433  					v:   &s.values,
   434  					idx: int(idx &^ maskTyp),
   435  				}
   436  			}
   437  		}
   438  	}
   439  	return nil
   440  }
   441  
   442  func (s *stash) createBinding(name unistring.String, deletable bool) {
   443  	if s.names == nil {
   444  		s.names = make(map[unistring.String]uint32)
   445  	}
   446  	if _, exists := s.names[name]; !exists {
   447  		idx := uint32(len(s.names)) | maskVar
   448  		if deletable {
   449  			idx |= maskDeletable
   450  		}
   451  		s.names[name] = idx
   452  		s.values = append(s.values, _undefined)
   453  	}
   454  }
   455  
   456  func (s *stash) createLexBinding(name unistring.String, isConst bool) {
   457  	if s.names == nil {
   458  		s.names = make(map[unistring.String]uint32)
   459  	}
   460  	if _, exists := s.names[name]; !exists {
   461  		idx := uint32(len(s.names))
   462  		if isConst {
   463  			idx |= maskConst | maskStrict
   464  		}
   465  		s.names[name] = idx
   466  		s.values = append(s.values, nil)
   467  	}
   468  }
   469  
   470  func (s *stash) deleteBinding(name unistring.String) {
   471  	delete(s.names, name)
   472  }
   473  
   474  func (vm *vm) newStash() {
   475  	vm.stash = &stash{
   476  		outer: vm.stash,
   477  	}
   478  	vm.stashAllocs++
   479  }
   480  
   481  func (vm *vm) init() {
   482  	vm.sb = -1
   483  	vm.stash = &vm.r.global.stash
   484  	vm.maxCallStackSize = math.MaxInt32
   485  }
   486  
   487  func (vm *vm) run() {
   488  	vm.halt = false
   489  	interrupted := false
   490  	ticks := 0
   491  	for !vm.halt {
   492  		if interrupted = atomic.LoadUint32(&vm.interrupted) != 0; interrupted {
   493  			break
   494  		}
   495  		vm.prg.code[vm.pc].exec(vm)
   496  		ticks++
   497  		if ticks > 10000 {
   498  			runtime.Gosched()
   499  			ticks = 0
   500  		}
   501  	}
   502  
   503  	if interrupted {
   504  		vm.interruptLock.Lock()
   505  		v := &InterruptedError{
   506  			iface: vm.interruptVal,
   507  		}
   508  		v.stack = vm.captureStack(nil, 0)
   509  		vm.interruptLock.Unlock()
   510  		panic(&uncatchableException{
   511  			err: v,
   512  		})
   513  	}
   514  }
   515  
   516  func (vm *vm) Interrupt(v interface{}) {
   517  	vm.interruptLock.Lock()
   518  	vm.interruptVal = v
   519  	atomic.StoreUint32(&vm.interrupted, 1)
   520  	vm.interruptLock.Unlock()
   521  }
   522  
   523  func (vm *vm) ClearInterrupt() {
   524  	atomic.StoreUint32(&vm.interrupted, 0)
   525  }
   526  
   527  func (vm *vm) captureStack(stack []StackFrame, ctxOffset int) []StackFrame {
   528  	// Unroll the context stack
   529  	if vm.pc != -1 {
   530  		var funcName unistring.String
   531  		if vm.prg != nil {
   532  			funcName = vm.prg.funcName
   533  		} else {
   534  			funcName = vm.funcName
   535  		}
   536  		stack = append(stack, StackFrame{prg: vm.prg, pc: vm.pc, funcName: funcName})
   537  	}
   538  	for i := len(vm.callStack) - 1; i > ctxOffset-1; i-- {
   539  		frame := &vm.callStack[i]
   540  		if frame.pc != -1 {
   541  			var funcName unistring.String
   542  			if prg := frame.prg; prg != nil {
   543  				funcName = prg.funcName
   544  			} else {
   545  				funcName = frame.funcName
   546  			}
   547  			stack = append(stack, StackFrame{prg: vm.callStack[i].prg, pc: frame.pc - 1, funcName: funcName})
   548  		}
   549  	}
   550  	return stack
   551  }
   552  
   553  func (vm *vm) try(f func()) (ex *Exception) {
   554  	var ctx context
   555  	vm.saveCtx(&ctx)
   556  
   557  	ctxOffset := len(vm.callStack)
   558  	sp := vm.sp
   559  	iterLen := len(vm.iterStack)
   560  	refLen := len(vm.refStack)
   561  
   562  	defer func() {
   563  		if x := recover(); x != nil {
   564  			defer func() {
   565  				vm.callStack = vm.callStack[:ctxOffset]
   566  				vm.restoreCtx(&ctx)
   567  				vm.sp = sp
   568  
   569  				// Restore other stacks
   570  				iterTail := vm.iterStack[iterLen:]
   571  				for i := range iterTail {
   572  					if iter := iterTail[i].iter; iter != nil {
   573  						_ = vm.try(func() {
   574  							iter.returnIter()
   575  						})
   576  					}
   577  					iterTail[i] = iterStackItem{}
   578  				}
   579  				vm.iterStack = vm.iterStack[:iterLen]
   580  				refTail := vm.refStack[refLen:]
   581  				for i := range refTail {
   582  					refTail[i] = nil
   583  				}
   584  				vm.refStack = vm.refStack[:refLen]
   585  			}()
   586  			switch x1 := x.(type) {
   587  			case *Object:
   588  				ex = &Exception{
   589  					val: x1,
   590  				}
   591  				if er, ok := x1.self.(*errorObject); ok {
   592  					ex.stack = er.stack
   593  				}
   594  			case Value:
   595  				ex = &Exception{
   596  					val: x1,
   597  				}
   598  			case *Exception:
   599  				ex = x1
   600  			case *uncatchableException:
   601  				panic(x1)
   602  			case typeError:
   603  				ex = &Exception{
   604  					val: vm.r.NewTypeError(string(x1)),
   605  				}
   606  			case referenceError:
   607  				ex = &Exception{
   608  					val: vm.r.newError(vm.r.global.ReferenceError, string(x1)),
   609  				}
   610  			case rangeError:
   611  				ex = &Exception{
   612  					val: vm.r.newError(vm.r.global.RangeError, string(x1)),
   613  				}
   614  			case syntaxError:
   615  				ex = &Exception{
   616  					val: vm.r.newError(vm.r.global.SyntaxError, string(x1)),
   617  				}
   618  			default:
   619  				/*
   620  					if vm.prg != nil {
   621  						vm.prg.dumpCode(log.Printf)
   622  					}
   623  					log.Print("Stack: ", string(debug.Stack()))
   624  					panic(fmt.Errorf("Panic at %d: %v", vm.pc, x))
   625  				*/
   626  				panic(x)
   627  			}
   628  			if ex.stack == nil {
   629  				ex.stack = vm.captureStack(make([]StackFrame, 0, len(vm.callStack)+1), 0)
   630  			}
   631  		}
   632  	}()
   633  
   634  	f()
   635  	return
   636  }
   637  
   638  func (vm *vm) runTry() (ex *Exception) {
   639  	return vm.try(vm.run)
   640  }
   641  
   642  func (vm *vm) push(v Value) {
   643  	vm.stack.expand(vm.sp)
   644  	vm.stack[vm.sp] = v
   645  	vm.sp++
   646  }
   647  
   648  func (vm *vm) pop() Value {
   649  	vm.sp--
   650  	return vm.stack[vm.sp]
   651  }
   652  
   653  func (vm *vm) peek() Value {
   654  	return vm.stack[vm.sp-1]
   655  }
   656  
   657  func (vm *vm) saveCtx(ctx *context) {
   658  	ctx.prg, ctx.stash, ctx.privEnv, ctx.newTarget, ctx.result, ctx.pc, ctx.sb, ctx.args, ctx.funcName =
   659  		vm.prg, vm.stash, vm.privEnv, vm.newTarget, vm.result, vm.pc, vm.sb, vm.args, vm.funcName
   660  }
   661  
   662  func (vm *vm) pushCtx() {
   663  	if len(vm.callStack) > vm.maxCallStackSize {
   664  		ex := &StackOverflowError{}
   665  		ex.stack = vm.captureStack(nil, 0)
   666  		panic(&uncatchableException{
   667  			err: ex,
   668  		})
   669  	}
   670  	vm.callStack = append(vm.callStack, context{})
   671  	ctx := &vm.callStack[len(vm.callStack)-1]
   672  	vm.saveCtx(ctx)
   673  }
   674  
   675  func (vm *vm) restoreCtx(ctx *context) {
   676  	vm.prg, vm.funcName, vm.stash, vm.privEnv, vm.newTarget, vm.result, vm.pc, vm.sb, vm.args =
   677  		ctx.prg, ctx.funcName, ctx.stash, ctx.privEnv, ctx.newTarget, ctx.result, ctx.pc, ctx.sb, ctx.args
   678  }
   679  
   680  func (vm *vm) popCtx() {
   681  	l := len(vm.callStack) - 1
   682  	ctx := &vm.callStack[l]
   683  	vm.restoreCtx(ctx)
   684  
   685  	ctx.prg = nil
   686  	ctx.stash = nil
   687  	ctx.privEnv = nil
   688  	ctx.result = nil
   689  	ctx.newTarget = nil
   690  
   691  	vm.callStack = vm.callStack[:l]
   692  }
   693  
   694  func (vm *vm) toCallee(v Value) *Object {
   695  	if obj, ok := v.(*Object); ok {
   696  		return obj
   697  	}
   698  	switch unresolved := v.(type) {
   699  	case valueUnresolved:
   700  		unresolved.throw()
   701  		panic("Unreachable")
   702  	case memberUnresolved:
   703  		panic(vm.r.NewTypeError("Object has no member '%s'", unresolved.ref))
   704  	}
   705  	panic(vm.r.NewTypeError("Value is not an object: %s", v.toString()))
   706  }
   707  
   708  type loadVal uint32
   709  
   710  func (l loadVal) exec(vm *vm) {
   711  	vm.push(vm.prg.values[l])
   712  	vm.pc++
   713  }
   714  
   715  type _loadUndef struct{}
   716  
   717  var loadUndef _loadUndef
   718  
   719  func (_loadUndef) exec(vm *vm) {
   720  	vm.push(_undefined)
   721  	vm.pc++
   722  }
   723  
   724  type _loadNil struct{}
   725  
   726  var loadNil _loadNil
   727  
   728  func (_loadNil) exec(vm *vm) {
   729  	vm.push(nil)
   730  	vm.pc++
   731  }
   732  
   733  type _saveResult struct{}
   734  
   735  var saveResult _saveResult
   736  
   737  func (_saveResult) exec(vm *vm) {
   738  	vm.sp--
   739  	vm.result = vm.stack[vm.sp]
   740  	vm.pc++
   741  }
   742  
   743  type _clearResult struct{}
   744  
   745  var clearResult _clearResult
   746  
   747  func (_clearResult) exec(vm *vm) {
   748  	vm.result = _undefined
   749  	vm.pc++
   750  }
   751  
   752  type _loadGlobalObject struct{}
   753  
   754  var loadGlobalObject _loadGlobalObject
   755  
   756  func (_loadGlobalObject) exec(vm *vm) {
   757  	vm.push(vm.r.globalObject)
   758  	vm.pc++
   759  }
   760  
   761  type loadStack int
   762  
   763  func (l loadStack) exec(vm *vm) {
   764  	// l > 0 -- var<l-1>
   765  	// l == 0 -- this
   766  
   767  	if l > 0 {
   768  		vm.push(nilSafe(vm.stack[vm.sb+vm.args+int(l)]))
   769  	} else {
   770  		vm.push(vm.stack[vm.sb])
   771  	}
   772  	vm.pc++
   773  }
   774  
   775  type loadStack1 int
   776  
   777  func (l loadStack1) exec(vm *vm) {
   778  	// args are in stash
   779  	// l > 0 -- var<l-1>
   780  	// l == 0 -- this
   781  
   782  	if l > 0 {
   783  		vm.push(nilSafe(vm.stack[vm.sb+int(l)]))
   784  	} else {
   785  		vm.push(vm.stack[vm.sb])
   786  	}
   787  	vm.pc++
   788  }
   789  
   790  type loadStackLex int
   791  
   792  func (l loadStackLex) exec(vm *vm) {
   793  	// l < 0 -- arg<-l-1>
   794  	// l > 0 -- var<l-1>
   795  	// l == 0 -- this
   796  	var p *Value
   797  	if l <= 0 {
   798  		arg := int(-l)
   799  		if arg > vm.args {
   800  			vm.push(_undefined)
   801  			vm.pc++
   802  			return
   803  		} else {
   804  			p = &vm.stack[vm.sb+arg]
   805  		}
   806  	} else {
   807  		p = &vm.stack[vm.sb+vm.args+int(l)]
   808  	}
   809  	if *p == nil {
   810  		panic(errAccessBeforeInit)
   811  	}
   812  	vm.push(*p)
   813  	vm.pc++
   814  }
   815  
   816  type loadStack1Lex int
   817  
   818  func (l loadStack1Lex) exec(vm *vm) {
   819  	p := &vm.stack[vm.sb+int(l)]
   820  	if *p == nil {
   821  		panic(errAccessBeforeInit)
   822  	}
   823  	vm.push(*p)
   824  	vm.pc++
   825  }
   826  
   827  type _loadCallee struct{}
   828  
   829  var loadCallee _loadCallee
   830  
   831  func (_loadCallee) exec(vm *vm) {
   832  	vm.push(vm.stack[vm.sb-1])
   833  	vm.pc++
   834  }
   835  
   836  func (vm *vm) storeStack(s int) {
   837  	// l > 0 -- var<l-1>
   838  
   839  	if s > 0 {
   840  		vm.stack[vm.sb+vm.args+s] = vm.stack[vm.sp-1]
   841  	} else {
   842  		panic("Illegal stack var index")
   843  	}
   844  	vm.pc++
   845  }
   846  
   847  func (vm *vm) storeStack1(s int) {
   848  	// args are in stash
   849  	// l > 0 -- var<l-1>
   850  
   851  	if s > 0 {
   852  		vm.stack[vm.sb+s] = vm.stack[vm.sp-1]
   853  	} else {
   854  		panic("Illegal stack var index")
   855  	}
   856  	vm.pc++
   857  }
   858  
   859  func (vm *vm) storeStackLex(s int) {
   860  	// l < 0 -- arg<-l-1>
   861  	// l > 0 -- var<l-1>
   862  	var p *Value
   863  	if s < 0 {
   864  		p = &vm.stack[vm.sb-s]
   865  	} else {
   866  		p = &vm.stack[vm.sb+vm.args+s]
   867  	}
   868  
   869  	if *p != nil {
   870  		*p = vm.stack[vm.sp-1]
   871  	} else {
   872  		panic(errAccessBeforeInit)
   873  	}
   874  	vm.pc++
   875  }
   876  
   877  func (vm *vm) storeStack1Lex(s int) {
   878  	// args are in stash
   879  	// s > 0 -- var<l-1>
   880  	if s <= 0 {
   881  		panic("Illegal stack var index")
   882  	}
   883  	p := &vm.stack[vm.sb+s]
   884  	if *p != nil {
   885  		*p = vm.stack[vm.sp-1]
   886  	} else {
   887  		panic(errAccessBeforeInit)
   888  	}
   889  	vm.pc++
   890  }
   891  
   892  func (vm *vm) initStack(s int) {
   893  	if s <= 0 {
   894  		vm.stack[vm.sb-s] = vm.stack[vm.sp-1]
   895  	} else {
   896  		vm.stack[vm.sb+vm.args+s] = vm.stack[vm.sp-1]
   897  	}
   898  	vm.pc++
   899  }
   900  
   901  func (vm *vm) initStack1(s int) {
   902  	if s <= 0 {
   903  		panic("Illegal stack var index")
   904  	}
   905  	vm.stack[vm.sb+s] = vm.stack[vm.sp-1]
   906  	vm.pc++
   907  }
   908  
   909  type storeStack int
   910  
   911  func (s storeStack) exec(vm *vm) {
   912  	vm.storeStack(int(s))
   913  }
   914  
   915  type storeStack1 int
   916  
   917  func (s storeStack1) exec(vm *vm) {
   918  	vm.storeStack1(int(s))
   919  }
   920  
   921  type storeStackLex int
   922  
   923  func (s storeStackLex) exec(vm *vm) {
   924  	vm.storeStackLex(int(s))
   925  }
   926  
   927  type storeStack1Lex int
   928  
   929  func (s storeStack1Lex) exec(vm *vm) {
   930  	vm.storeStack1Lex(int(s))
   931  }
   932  
   933  type initStack int
   934  
   935  func (s initStack) exec(vm *vm) {
   936  	vm.initStack(int(s))
   937  }
   938  
   939  type initStackP int
   940  
   941  func (s initStackP) exec(vm *vm) {
   942  	vm.initStack(int(s))
   943  	vm.sp--
   944  }
   945  
   946  type initStack1 int
   947  
   948  func (s initStack1) exec(vm *vm) {
   949  	vm.initStack1(int(s))
   950  }
   951  
   952  type initStack1P int
   953  
   954  func (s initStack1P) exec(vm *vm) {
   955  	vm.initStack1(int(s))
   956  	vm.sp--
   957  }
   958  
   959  type storeStackP int
   960  
   961  func (s storeStackP) exec(vm *vm) {
   962  	vm.storeStack(int(s))
   963  	vm.sp--
   964  }
   965  
   966  type storeStack1P int
   967  
   968  func (s storeStack1P) exec(vm *vm) {
   969  	vm.storeStack1(int(s))
   970  	vm.sp--
   971  }
   972  
   973  type storeStackLexP int
   974  
   975  func (s storeStackLexP) exec(vm *vm) {
   976  	vm.storeStackLex(int(s))
   977  	vm.sp--
   978  }
   979  
   980  type storeStack1LexP int
   981  
   982  func (s storeStack1LexP) exec(vm *vm) {
   983  	vm.storeStack1Lex(int(s))
   984  	vm.sp--
   985  }
   986  
   987  type _toNumber struct{}
   988  
   989  var toNumber _toNumber
   990  
   991  func (_toNumber) exec(vm *vm) {
   992  	vm.stack[vm.sp-1] = vm.stack[vm.sp-1].ToNumber()
   993  	vm.pc++
   994  }
   995  
   996  type _add struct{}
   997  
   998  var add _add
   999  
  1000  func (_add) exec(vm *vm) {
  1001  	right := vm.stack[vm.sp-1]
  1002  	left := vm.stack[vm.sp-2]
  1003  
  1004  	if o, ok := left.(*Object); ok {
  1005  		left = o.toPrimitive()
  1006  	}
  1007  
  1008  	if o, ok := right.(*Object); ok {
  1009  		right = o.toPrimitive()
  1010  	}
  1011  
  1012  	var ret Value
  1013  
  1014  	leftString, isLeftString := left.(valueString)
  1015  	rightString, isRightString := right.(valueString)
  1016  
  1017  	if isLeftString || isRightString {
  1018  		if !isLeftString {
  1019  			leftString = left.toString()
  1020  		}
  1021  		if !isRightString {
  1022  			rightString = right.toString()
  1023  		}
  1024  		ret = leftString.concat(rightString)
  1025  	} else {
  1026  		if leftInt, ok := left.(valueInt); ok {
  1027  			if rightInt, ok := right.(valueInt); ok {
  1028  				ret = intToValue(int64(leftInt) + int64(rightInt))
  1029  			} else {
  1030  				ret = floatToValue(float64(leftInt) + right.ToFloat())
  1031  			}
  1032  		} else {
  1033  			ret = floatToValue(left.ToFloat() + right.ToFloat())
  1034  		}
  1035  	}
  1036  
  1037  	vm.stack[vm.sp-2] = ret
  1038  	vm.sp--
  1039  	vm.pc++
  1040  }
  1041  
  1042  type _sub struct{}
  1043  
  1044  var sub _sub
  1045  
  1046  func (_sub) exec(vm *vm) {
  1047  	right := vm.stack[vm.sp-1]
  1048  	left := vm.stack[vm.sp-2]
  1049  
  1050  	var result Value
  1051  
  1052  	if left, ok := left.(valueInt); ok {
  1053  		if right, ok := right.(valueInt); ok {
  1054  			result = intToValue(int64(left) - int64(right))
  1055  			goto end
  1056  		}
  1057  	}
  1058  
  1059  	result = floatToValue(left.ToFloat() - right.ToFloat())
  1060  end:
  1061  	vm.sp--
  1062  	vm.stack[vm.sp-1] = result
  1063  	vm.pc++
  1064  }
  1065  
  1066  type _mul struct{}
  1067  
  1068  var mul _mul
  1069  
  1070  func (_mul) exec(vm *vm) {
  1071  	left := vm.stack[vm.sp-2]
  1072  	right := vm.stack[vm.sp-1]
  1073  
  1074  	var result Value
  1075  
  1076  	if left, ok := assertInt64(left); ok {
  1077  		if right, ok := assertInt64(right); ok {
  1078  			if left == 0 && right == -1 || left == -1 && right == 0 {
  1079  				result = _negativeZero
  1080  				goto end
  1081  			}
  1082  			res := left * right
  1083  			// check for overflow
  1084  			if left == 0 || right == 0 || res/left == right {
  1085  				result = intToValue(res)
  1086  				goto end
  1087  			}
  1088  
  1089  		}
  1090  	}
  1091  
  1092  	result = floatToValue(left.ToFloat() * right.ToFloat())
  1093  
  1094  end:
  1095  	vm.sp--
  1096  	vm.stack[vm.sp-1] = result
  1097  	vm.pc++
  1098  }
  1099  
  1100  type _exp struct{}
  1101  
  1102  var exp _exp
  1103  
  1104  func (_exp) exec(vm *vm) {
  1105  	vm.sp--
  1106  	vm.stack[vm.sp-1] = pow(vm.stack[vm.sp-1], vm.stack[vm.sp])
  1107  	vm.pc++
  1108  }
  1109  
  1110  type _div struct{}
  1111  
  1112  var div _div
  1113  
  1114  func (_div) exec(vm *vm) {
  1115  	left := vm.stack[vm.sp-2].ToFloat()
  1116  	right := vm.stack[vm.sp-1].ToFloat()
  1117  
  1118  	var result Value
  1119  
  1120  	if math.IsNaN(left) || math.IsNaN(right) {
  1121  		result = _NaN
  1122  		goto end
  1123  	}
  1124  	if math.IsInf(left, 0) && math.IsInf(right, 0) {
  1125  		result = _NaN
  1126  		goto end
  1127  	}
  1128  	if left == 0 && right == 0 {
  1129  		result = _NaN
  1130  		goto end
  1131  	}
  1132  
  1133  	if math.IsInf(left, 0) {
  1134  		if math.Signbit(left) == math.Signbit(right) {
  1135  			result = _positiveInf
  1136  			goto end
  1137  		} else {
  1138  			result = _negativeInf
  1139  			goto end
  1140  		}
  1141  	}
  1142  	if math.IsInf(right, 0) {
  1143  		if math.Signbit(left) == math.Signbit(right) {
  1144  			result = _positiveZero
  1145  			goto end
  1146  		} else {
  1147  			result = _negativeZero
  1148  			goto end
  1149  		}
  1150  	}
  1151  	if right == 0 {
  1152  		if math.Signbit(left) == math.Signbit(right) {
  1153  			result = _positiveInf
  1154  			goto end
  1155  		} else {
  1156  			result = _negativeInf
  1157  			goto end
  1158  		}
  1159  	}
  1160  
  1161  	result = floatToValue(left / right)
  1162  
  1163  end:
  1164  	vm.sp--
  1165  	vm.stack[vm.sp-1] = result
  1166  	vm.pc++
  1167  }
  1168  
  1169  type _mod struct{}
  1170  
  1171  var mod _mod
  1172  
  1173  func (_mod) exec(vm *vm) {
  1174  	left := vm.stack[vm.sp-2]
  1175  	right := vm.stack[vm.sp-1]
  1176  
  1177  	var result Value
  1178  
  1179  	if leftInt, ok := assertInt64(left); ok {
  1180  		if rightInt, ok := assertInt64(right); ok {
  1181  			if rightInt == 0 {
  1182  				result = _NaN
  1183  				goto end
  1184  			}
  1185  			r := leftInt % rightInt
  1186  			if r == 0 && leftInt < 0 {
  1187  				result = _negativeZero
  1188  			} else {
  1189  				result = intToValue(leftInt % rightInt)
  1190  			}
  1191  			goto end
  1192  		}
  1193  	}
  1194  
  1195  	result = floatToValue(math.Mod(left.ToFloat(), right.ToFloat()))
  1196  end:
  1197  	vm.sp--
  1198  	vm.stack[vm.sp-1] = result
  1199  	vm.pc++
  1200  }
  1201  
  1202  type _neg struct{}
  1203  
  1204  var neg _neg
  1205  
  1206  func (_neg) exec(vm *vm) {
  1207  	operand := vm.stack[vm.sp-1]
  1208  
  1209  	var result Value
  1210  
  1211  	if i, ok := assertInt64(operand); ok {
  1212  		if i == 0 {
  1213  			result = _negativeZero
  1214  		} else {
  1215  			result = valueInt(-i)
  1216  		}
  1217  	} else {
  1218  		f := operand.ToFloat()
  1219  		if !math.IsNaN(f) {
  1220  			f = -f
  1221  		}
  1222  		result = valueFloat(f)
  1223  	}
  1224  
  1225  	vm.stack[vm.sp-1] = result
  1226  	vm.pc++
  1227  }
  1228  
  1229  type _plus struct{}
  1230  
  1231  var plus _plus
  1232  
  1233  func (_plus) exec(vm *vm) {
  1234  	vm.stack[vm.sp-1] = vm.stack[vm.sp-1].ToNumber()
  1235  	vm.pc++
  1236  }
  1237  
  1238  type _inc struct{}
  1239  
  1240  var inc _inc
  1241  
  1242  func (_inc) exec(vm *vm) {
  1243  	v := vm.stack[vm.sp-1]
  1244  
  1245  	if i, ok := assertInt64(v); ok {
  1246  		v = intToValue(i + 1)
  1247  		goto end
  1248  	}
  1249  
  1250  	v = valueFloat(v.ToFloat() + 1)
  1251  
  1252  end:
  1253  	vm.stack[vm.sp-1] = v
  1254  	vm.pc++
  1255  }
  1256  
  1257  type _dec struct{}
  1258  
  1259  var dec _dec
  1260  
  1261  func (_dec) exec(vm *vm) {
  1262  	v := vm.stack[vm.sp-1]
  1263  
  1264  	if i, ok := assertInt64(v); ok {
  1265  		v = intToValue(i - 1)
  1266  		goto end
  1267  	}
  1268  
  1269  	v = valueFloat(v.ToFloat() - 1)
  1270  
  1271  end:
  1272  	vm.stack[vm.sp-1] = v
  1273  	vm.pc++
  1274  }
  1275  
  1276  type _and struct{}
  1277  
  1278  var and _and
  1279  
  1280  func (_and) exec(vm *vm) {
  1281  	left := toInt32(vm.stack[vm.sp-2])
  1282  	right := toInt32(vm.stack[vm.sp-1])
  1283  	vm.stack[vm.sp-2] = intToValue(int64(left & right))
  1284  	vm.sp--
  1285  	vm.pc++
  1286  }
  1287  
  1288  type _or struct{}
  1289  
  1290  var or _or
  1291  
  1292  func (_or) exec(vm *vm) {
  1293  	left := toInt32(vm.stack[vm.sp-2])
  1294  	right := toInt32(vm.stack[vm.sp-1])
  1295  	vm.stack[vm.sp-2] = intToValue(int64(left | right))
  1296  	vm.sp--
  1297  	vm.pc++
  1298  }
  1299  
  1300  type _xor struct{}
  1301  
  1302  var xor _xor
  1303  
  1304  func (_xor) exec(vm *vm) {
  1305  	left := toInt32(vm.stack[vm.sp-2])
  1306  	right := toInt32(vm.stack[vm.sp-1])
  1307  	vm.stack[vm.sp-2] = intToValue(int64(left ^ right))
  1308  	vm.sp--
  1309  	vm.pc++
  1310  }
  1311  
  1312  type _bnot struct{}
  1313  
  1314  var bnot _bnot
  1315  
  1316  func (_bnot) exec(vm *vm) {
  1317  	op := toInt32(vm.stack[vm.sp-1])
  1318  	vm.stack[vm.sp-1] = intToValue(int64(^op))
  1319  	vm.pc++
  1320  }
  1321  
  1322  type _sal struct{}
  1323  
  1324  var sal _sal
  1325  
  1326  func (_sal) exec(vm *vm) {
  1327  	left := toInt32(vm.stack[vm.sp-2])
  1328  	right := toUint32(vm.stack[vm.sp-1])
  1329  	vm.stack[vm.sp-2] = intToValue(int64(left << (right & 0x1F)))
  1330  	vm.sp--
  1331  	vm.pc++
  1332  }
  1333  
  1334  type _sar struct{}
  1335  
  1336  var sar _sar
  1337  
  1338  func (_sar) exec(vm *vm) {
  1339  	left := toInt32(vm.stack[vm.sp-2])
  1340  	right := toUint32(vm.stack[vm.sp-1])
  1341  	vm.stack[vm.sp-2] = intToValue(int64(left >> (right & 0x1F)))
  1342  	vm.sp--
  1343  	vm.pc++
  1344  }
  1345  
  1346  type _shr struct{}
  1347  
  1348  var shr _shr
  1349  
  1350  func (_shr) exec(vm *vm) {
  1351  	left := toUint32(vm.stack[vm.sp-2])
  1352  	right := toUint32(vm.stack[vm.sp-1])
  1353  	vm.stack[vm.sp-2] = intToValue(int64(left >> (right & 0x1F)))
  1354  	vm.sp--
  1355  	vm.pc++
  1356  }
  1357  
  1358  type _halt struct{}
  1359  
  1360  var halt _halt
  1361  
  1362  func (_halt) exec(vm *vm) {
  1363  	vm.halt = true
  1364  	vm.pc++
  1365  }
  1366  
  1367  type jump int32
  1368  
  1369  func (j jump) exec(vm *vm) {
  1370  	vm.pc += int(j)
  1371  }
  1372  
  1373  type _toPropertyKey struct{}
  1374  
  1375  func (_toPropertyKey) exec(vm *vm) {
  1376  	p := vm.sp - 1
  1377  	vm.stack[p] = toPropertyKey(vm.stack[p])
  1378  	vm.pc++
  1379  }
  1380  
  1381  type _toString struct{}
  1382  
  1383  func (_toString) exec(vm *vm) {
  1384  	p := vm.sp - 1
  1385  	vm.stack[p] = vm.stack[p].toString()
  1386  	vm.pc++
  1387  }
  1388  
  1389  type _getElemRef struct{}
  1390  
  1391  var getElemRef _getElemRef
  1392  
  1393  func (_getElemRef) exec(vm *vm) {
  1394  	obj := vm.stack[vm.sp-2].ToObject(vm.r)
  1395  	propName := toPropertyKey(vm.stack[vm.sp-1])
  1396  	vm.refStack = append(vm.refStack, &objRef{
  1397  		base: obj,
  1398  		name: propName.string(),
  1399  	})
  1400  	vm.sp -= 2
  1401  	vm.pc++
  1402  }
  1403  
  1404  type _getElemRefRecv struct{}
  1405  
  1406  var getElemRefRecv _getElemRefRecv
  1407  
  1408  func (_getElemRefRecv) exec(vm *vm) {
  1409  	obj := vm.stack[vm.sp-1].ToObject(vm.r)
  1410  	propName := toPropertyKey(vm.stack[vm.sp-2])
  1411  	vm.refStack = append(vm.refStack, &objRef{
  1412  		base: obj,
  1413  		name: propName.string(),
  1414  		this: vm.stack[vm.sp-3],
  1415  	})
  1416  	vm.sp -= 3
  1417  	vm.pc++
  1418  }
  1419  
  1420  type _getElemRefStrict struct{}
  1421  
  1422  var getElemRefStrict _getElemRefStrict
  1423  
  1424  func (_getElemRefStrict) exec(vm *vm) {
  1425  	obj := vm.stack[vm.sp-2].ToObject(vm.r)
  1426  	propName := toPropertyKey(vm.stack[vm.sp-1])
  1427  	vm.refStack = append(vm.refStack, &objRef{
  1428  		base:   obj,
  1429  		name:   propName.string(),
  1430  		strict: true,
  1431  	})
  1432  	vm.sp -= 2
  1433  	vm.pc++
  1434  }
  1435  
  1436  type _getElemRefRecvStrict struct{}
  1437  
  1438  var getElemRefRecvStrict _getElemRefRecvStrict
  1439  
  1440  func (_getElemRefRecvStrict) exec(vm *vm) {
  1441  	obj := vm.stack[vm.sp-1].ToObject(vm.r)
  1442  	propName := toPropertyKey(vm.stack[vm.sp-2])
  1443  	vm.refStack = append(vm.refStack, &objRef{
  1444  		base:   obj,
  1445  		name:   propName.string(),
  1446  		this:   vm.stack[vm.sp-3],
  1447  		strict: true,
  1448  	})
  1449  	vm.sp -= 3
  1450  	vm.pc++
  1451  }
  1452  
  1453  type _setElem struct{}
  1454  
  1455  var setElem _setElem
  1456  
  1457  func (_setElem) exec(vm *vm) {
  1458  	obj := vm.stack[vm.sp-3].ToObject(vm.r)
  1459  	propName := toPropertyKey(vm.stack[vm.sp-2])
  1460  	val := vm.stack[vm.sp-1]
  1461  
  1462  	obj.setOwn(propName, val, false)
  1463  
  1464  	vm.sp -= 2
  1465  	vm.stack[vm.sp-1] = val
  1466  	vm.pc++
  1467  }
  1468  
  1469  type _setElem1 struct{}
  1470  
  1471  var setElem1 _setElem1
  1472  
  1473  func (_setElem1) exec(vm *vm) {
  1474  	obj := vm.stack[vm.sp-3].ToObject(vm.r)
  1475  	propName := vm.stack[vm.sp-2]
  1476  	val := vm.stack[vm.sp-1]
  1477  
  1478  	obj.setOwn(propName, val, true)
  1479  
  1480  	vm.sp -= 2
  1481  	vm.pc++
  1482  }
  1483  
  1484  type _setElem1Named struct{}
  1485  
  1486  var setElem1Named _setElem1Named
  1487  
  1488  func (_setElem1Named) exec(vm *vm) {
  1489  	receiver := vm.stack[vm.sp-3]
  1490  	base := receiver.ToObject(vm.r)
  1491  	propName := vm.stack[vm.sp-2]
  1492  	val := vm.stack[vm.sp-1]
  1493  	vm.r.toObject(val).self.defineOwnPropertyStr("name", PropertyDescriptor{
  1494  		Value:        funcName("", propName),
  1495  		Configurable: FLAG_TRUE,
  1496  	}, true)
  1497  	base.set(propName, val, receiver, true)
  1498  
  1499  	vm.sp -= 2
  1500  	vm.pc++
  1501  }
  1502  
  1503  type defineMethod struct {
  1504  	enumerable bool
  1505  }
  1506  
  1507  func (d *defineMethod) exec(vm *vm) {
  1508  	obj := vm.r.toObject(vm.stack[vm.sp-3])
  1509  	propName := vm.stack[vm.sp-2]
  1510  	method := vm.r.toObject(vm.stack[vm.sp-1])
  1511  	method.self.defineOwnPropertyStr("name", PropertyDescriptor{
  1512  		Value:        funcName("", propName),
  1513  		Configurable: FLAG_TRUE,
  1514  	}, true)
  1515  	obj.defineOwnProperty(propName, PropertyDescriptor{
  1516  		Value:        method,
  1517  		Writable:     FLAG_TRUE,
  1518  		Configurable: FLAG_TRUE,
  1519  		Enumerable:   ToFlag(d.enumerable),
  1520  	}, true)
  1521  
  1522  	vm.sp -= 2
  1523  	vm.pc++
  1524  }
  1525  
  1526  type _setElemP struct{}
  1527  
  1528  var setElemP _setElemP
  1529  
  1530  func (_setElemP) exec(vm *vm) {
  1531  	obj := vm.stack[vm.sp-3].ToObject(vm.r)
  1532  	propName := toPropertyKey(vm.stack[vm.sp-2])
  1533  	val := vm.stack[vm.sp-1]
  1534  
  1535  	obj.setOwn(propName, val, false)
  1536  
  1537  	vm.sp -= 3
  1538  	vm.pc++
  1539  }
  1540  
  1541  type _setElemStrict struct{}
  1542  
  1543  var setElemStrict _setElemStrict
  1544  
  1545  func (_setElemStrict) exec(vm *vm) {
  1546  	propName := toPropertyKey(vm.stack[vm.sp-2])
  1547  	receiver := vm.stack[vm.sp-3]
  1548  	val := vm.stack[vm.sp-1]
  1549  	if receiverObj, ok := receiver.(*Object); ok {
  1550  		receiverObj.setOwn(propName, val, true)
  1551  	} else {
  1552  		base := receiver.ToObject(vm.r)
  1553  		base.set(propName, val, receiver, true)
  1554  	}
  1555  
  1556  	vm.sp -= 2
  1557  	vm.stack[vm.sp-1] = val
  1558  	vm.pc++
  1559  }
  1560  
  1561  type _setElemRecv struct{}
  1562  
  1563  var setElemRecv _setElemRecv
  1564  
  1565  func (_setElemRecv) exec(vm *vm) {
  1566  	receiver := vm.stack[vm.sp-4]
  1567  	propName := toPropertyKey(vm.stack[vm.sp-3])
  1568  	o := vm.stack[vm.sp-2]
  1569  	val := vm.stack[vm.sp-1]
  1570  	if obj, ok := o.(*Object); ok {
  1571  		obj.set(propName, val, receiver, false)
  1572  	} else {
  1573  		base := o.ToObject(vm.r)
  1574  		base.set(propName, val, receiver, false)
  1575  	}
  1576  
  1577  	vm.sp -= 3
  1578  	vm.stack[vm.sp-1] = val
  1579  	vm.pc++
  1580  }
  1581  
  1582  type _setElemRecvStrict struct{}
  1583  
  1584  var setElemRecvStrict _setElemRecvStrict
  1585  
  1586  func (_setElemRecvStrict) exec(vm *vm) {
  1587  	receiver := vm.stack[vm.sp-4]
  1588  	propName := toPropertyKey(vm.stack[vm.sp-3])
  1589  	o := vm.stack[vm.sp-2]
  1590  	val := vm.stack[vm.sp-1]
  1591  	if obj, ok := o.(*Object); ok {
  1592  		obj.set(propName, val, receiver, true)
  1593  	} else {
  1594  		base := o.ToObject(vm.r)
  1595  		base.set(propName, val, receiver, true)
  1596  	}
  1597  
  1598  	vm.sp -= 3
  1599  	vm.stack[vm.sp-1] = val
  1600  	vm.pc++
  1601  }
  1602  
  1603  type _setElemStrictP struct{}
  1604  
  1605  var setElemStrictP _setElemStrictP
  1606  
  1607  func (_setElemStrictP) exec(vm *vm) {
  1608  	propName := toPropertyKey(vm.stack[vm.sp-2])
  1609  	receiver := vm.stack[vm.sp-3]
  1610  	val := vm.stack[vm.sp-1]
  1611  	if receiverObj, ok := receiver.(*Object); ok {
  1612  		receiverObj.setOwn(propName, val, true)
  1613  	} else {
  1614  		base := receiver.ToObject(vm.r)
  1615  		base.set(propName, val, receiver, true)
  1616  	}
  1617  
  1618  	vm.sp -= 3
  1619  	vm.pc++
  1620  }
  1621  
  1622  type _setElemRecvP struct{}
  1623  
  1624  var setElemRecvP _setElemRecvP
  1625  
  1626  func (_setElemRecvP) exec(vm *vm) {
  1627  	receiver := vm.stack[vm.sp-4]
  1628  	propName := toPropertyKey(vm.stack[vm.sp-3])
  1629  	o := vm.stack[vm.sp-2]
  1630  	val := vm.stack[vm.sp-1]
  1631  	if obj, ok := o.(*Object); ok {
  1632  		obj.set(propName, val, receiver, false)
  1633  	} else {
  1634  		base := o.ToObject(vm.r)
  1635  		base.set(propName, val, receiver, false)
  1636  	}
  1637  
  1638  	vm.sp -= 4
  1639  	vm.pc++
  1640  }
  1641  
  1642  type _setElemRecvStrictP struct{}
  1643  
  1644  var setElemRecvStrictP _setElemRecvStrictP
  1645  
  1646  func (_setElemRecvStrictP) exec(vm *vm) {
  1647  	receiver := vm.stack[vm.sp-4]
  1648  	propName := toPropertyKey(vm.stack[vm.sp-3])
  1649  	o := vm.stack[vm.sp-2]
  1650  	val := vm.stack[vm.sp-1]
  1651  	if obj, ok := o.(*Object); ok {
  1652  		obj.set(propName, val, receiver, true)
  1653  	} else {
  1654  		base := o.ToObject(vm.r)
  1655  		base.set(propName, val, receiver, true)
  1656  	}
  1657  
  1658  	vm.sp -= 4
  1659  	vm.pc++
  1660  }
  1661  
  1662  type _deleteElem struct{}
  1663  
  1664  var deleteElem _deleteElem
  1665  
  1666  func (_deleteElem) exec(vm *vm) {
  1667  	obj := vm.stack[vm.sp-2].ToObject(vm.r)
  1668  	propName := toPropertyKey(vm.stack[vm.sp-1])
  1669  	if obj.delete(propName, false) {
  1670  		vm.stack[vm.sp-2] = valueTrue
  1671  	} else {
  1672  		vm.stack[vm.sp-2] = valueFalse
  1673  	}
  1674  	vm.sp--
  1675  	vm.pc++
  1676  }
  1677  
  1678  type _deleteElemStrict struct{}
  1679  
  1680  var deleteElemStrict _deleteElemStrict
  1681  
  1682  func (_deleteElemStrict) exec(vm *vm) {
  1683  	obj := vm.stack[vm.sp-2].ToObject(vm.r)
  1684  	propName := toPropertyKey(vm.stack[vm.sp-1])
  1685  	obj.delete(propName, true)
  1686  	vm.stack[vm.sp-2] = valueTrue
  1687  	vm.sp--
  1688  	vm.pc++
  1689  }
  1690  
  1691  type deleteProp unistring.String
  1692  
  1693  func (d deleteProp) exec(vm *vm) {
  1694  	obj := vm.stack[vm.sp-1].ToObject(vm.r)
  1695  	if obj.self.deleteStr(unistring.String(d), false) {
  1696  		vm.stack[vm.sp-1] = valueTrue
  1697  	} else {
  1698  		vm.stack[vm.sp-1] = valueFalse
  1699  	}
  1700  	vm.pc++
  1701  }
  1702  
  1703  type deletePropStrict unistring.String
  1704  
  1705  func (d deletePropStrict) exec(vm *vm) {
  1706  	obj := vm.stack[vm.sp-1].ToObject(vm.r)
  1707  	obj.self.deleteStr(unistring.String(d), true)
  1708  	vm.stack[vm.sp-1] = valueTrue
  1709  	vm.pc++
  1710  }
  1711  
  1712  type getPropRef unistring.String
  1713  
  1714  func (p getPropRef) exec(vm *vm) {
  1715  	vm.refStack = append(vm.refStack, &objRef{
  1716  		base: vm.stack[vm.sp-1].ToObject(vm.r),
  1717  		name: unistring.String(p),
  1718  	})
  1719  	vm.sp--
  1720  	vm.pc++
  1721  }
  1722  
  1723  type getPropRefRecv unistring.String
  1724  
  1725  func (p getPropRefRecv) exec(vm *vm) {
  1726  	vm.refStack = append(vm.refStack, &objRef{
  1727  		this: vm.stack[vm.sp-2],
  1728  		base: vm.stack[vm.sp-1].ToObject(vm.r),
  1729  		name: unistring.String(p),
  1730  	})
  1731  	vm.sp -= 2
  1732  	vm.pc++
  1733  }
  1734  
  1735  type getPropRefStrict unistring.String
  1736  
  1737  func (p getPropRefStrict) exec(vm *vm) {
  1738  	vm.refStack = append(vm.refStack, &objRef{
  1739  		base:   vm.stack[vm.sp-1].ToObject(vm.r),
  1740  		name:   unistring.String(p),
  1741  		strict: true,
  1742  	})
  1743  	vm.sp--
  1744  	vm.pc++
  1745  }
  1746  
  1747  type getPropRefRecvStrict unistring.String
  1748  
  1749  func (p getPropRefRecvStrict) exec(vm *vm) {
  1750  	vm.refStack = append(vm.refStack, &objRef{
  1751  		this:   vm.stack[vm.sp-2],
  1752  		base:   vm.stack[vm.sp-1].ToObject(vm.r),
  1753  		name:   unistring.String(p),
  1754  		strict: true,
  1755  	})
  1756  	vm.sp -= 2
  1757  	vm.pc++
  1758  }
  1759  
  1760  type setProp unistring.String
  1761  
  1762  func (p setProp) exec(vm *vm) {
  1763  	val := vm.stack[vm.sp-1]
  1764  	vm.stack[vm.sp-2].ToObject(vm.r).self.setOwnStr(unistring.String(p), val, false)
  1765  	vm.stack[vm.sp-2] = val
  1766  	vm.sp--
  1767  	vm.pc++
  1768  }
  1769  
  1770  type setPropP unistring.String
  1771  
  1772  func (p setPropP) exec(vm *vm) {
  1773  	val := vm.stack[vm.sp-1]
  1774  	vm.stack[vm.sp-2].ToObject(vm.r).self.setOwnStr(unistring.String(p), val, false)
  1775  	vm.sp -= 2
  1776  	vm.pc++
  1777  }
  1778  
  1779  type setPropStrict unistring.String
  1780  
  1781  func (p setPropStrict) exec(vm *vm) {
  1782  	receiver := vm.stack[vm.sp-2]
  1783  	val := vm.stack[vm.sp-1]
  1784  	propName := unistring.String(p)
  1785  	if receiverObj, ok := receiver.(*Object); ok {
  1786  		receiverObj.self.setOwnStr(propName, val, true)
  1787  	} else {
  1788  		base := receiver.ToObject(vm.r)
  1789  		base.setStr(propName, val, receiver, true)
  1790  	}
  1791  
  1792  	vm.stack[vm.sp-2] = val
  1793  	vm.sp--
  1794  	vm.pc++
  1795  }
  1796  
  1797  type setPropRecv unistring.String
  1798  
  1799  func (p setPropRecv) exec(vm *vm) {
  1800  	receiver := vm.stack[vm.sp-3]
  1801  	o := vm.stack[vm.sp-2]
  1802  	val := vm.stack[vm.sp-1]
  1803  	propName := unistring.String(p)
  1804  	if obj, ok := o.(*Object); ok {
  1805  		obj.setStr(propName, val, receiver, false)
  1806  	} else {
  1807  		base := o.ToObject(vm.r)
  1808  		base.setStr(propName, val, receiver, false)
  1809  	}
  1810  
  1811  	vm.stack[vm.sp-3] = val
  1812  	vm.sp -= 2
  1813  	vm.pc++
  1814  }
  1815  
  1816  type setPropRecvStrict unistring.String
  1817  
  1818  func (p setPropRecvStrict) exec(vm *vm) {
  1819  	receiver := vm.stack[vm.sp-3]
  1820  	o := vm.stack[vm.sp-2]
  1821  	val := vm.stack[vm.sp-1]
  1822  	propName := unistring.String(p)
  1823  	if obj, ok := o.(*Object); ok {
  1824  		obj.setStr(propName, val, receiver, true)
  1825  	} else {
  1826  		base := o.ToObject(vm.r)
  1827  		base.setStr(propName, val, receiver, true)
  1828  	}
  1829  
  1830  	vm.stack[vm.sp-3] = val
  1831  	vm.sp -= 2
  1832  	vm.pc++
  1833  }
  1834  
  1835  type setPropRecvP unistring.String
  1836  
  1837  func (p setPropRecvP) exec(vm *vm) {
  1838  	receiver := vm.stack[vm.sp-3]
  1839  	o := vm.stack[vm.sp-2]
  1840  	val := vm.stack[vm.sp-1]
  1841  	propName := unistring.String(p)
  1842  	if obj, ok := o.(*Object); ok {
  1843  		obj.setStr(propName, val, receiver, false)
  1844  	} else {
  1845  		base := o.ToObject(vm.r)
  1846  		base.setStr(propName, val, receiver, false)
  1847  	}
  1848  
  1849  	vm.sp -= 3
  1850  	vm.pc++
  1851  }
  1852  
  1853  type setPropRecvStrictP unistring.String
  1854  
  1855  func (p setPropRecvStrictP) exec(vm *vm) {
  1856  	receiver := vm.stack[vm.sp-3]
  1857  	o := vm.stack[vm.sp-2]
  1858  	val := vm.stack[vm.sp-1]
  1859  	propName := unistring.String(p)
  1860  	if obj, ok := o.(*Object); ok {
  1861  		obj.setStr(propName, val, receiver, true)
  1862  	} else {
  1863  		base := o.ToObject(vm.r)
  1864  		base.setStr(propName, val, receiver, true)
  1865  	}
  1866  
  1867  	vm.sp -= 3
  1868  	vm.pc++
  1869  }
  1870  
  1871  type setPropStrictP unistring.String
  1872  
  1873  func (p setPropStrictP) exec(vm *vm) {
  1874  	receiver := vm.stack[vm.sp-2]
  1875  	val := vm.stack[vm.sp-1]
  1876  	propName := unistring.String(p)
  1877  	if receiverObj, ok := receiver.(*Object); ok {
  1878  		receiverObj.self.setOwnStr(propName, val, true)
  1879  	} else {
  1880  		base := receiver.ToObject(vm.r)
  1881  		base.setStr(propName, val, receiver, true)
  1882  	}
  1883  
  1884  	vm.sp -= 2
  1885  	vm.pc++
  1886  }
  1887  
  1888  type putProp unistring.String
  1889  
  1890  func (p putProp) exec(vm *vm) {
  1891  	vm.r.toObject(vm.stack[vm.sp-2]).self._putProp(unistring.String(p), vm.stack[vm.sp-1], true, true, true)
  1892  
  1893  	vm.sp--
  1894  	vm.pc++
  1895  }
  1896  
  1897  // used in class declarations instead of putProp because DefineProperty must be observable by Proxy
  1898  type definePropKeyed unistring.String
  1899  
  1900  func (p definePropKeyed) exec(vm *vm) {
  1901  	vm.r.toObject(vm.stack[vm.sp-2]).self.defineOwnPropertyStr(unistring.String(p), PropertyDescriptor{
  1902  		Value:        vm.stack[vm.sp-1],
  1903  		Writable:     FLAG_TRUE,
  1904  		Configurable: FLAG_TRUE,
  1905  		Enumerable:   FLAG_TRUE,
  1906  	}, true)
  1907  
  1908  	vm.sp--
  1909  	vm.pc++
  1910  }
  1911  
  1912  type defineProp struct{}
  1913  
  1914  func (defineProp) exec(vm *vm) {
  1915  	vm.r.toObject(vm.stack[vm.sp-3]).defineOwnProperty(vm.stack[vm.sp-2], PropertyDescriptor{
  1916  		Value:        vm.stack[vm.sp-1],
  1917  		Writable:     FLAG_TRUE,
  1918  		Configurable: FLAG_TRUE,
  1919  		Enumerable:   FLAG_TRUE,
  1920  	}, true)
  1921  
  1922  	vm.sp -= 2
  1923  	vm.pc++
  1924  }
  1925  
  1926  type defineMethodKeyed struct {
  1927  	key        unistring.String
  1928  	enumerable bool
  1929  }
  1930  
  1931  func (d *defineMethodKeyed) exec(vm *vm) {
  1932  	obj := vm.r.toObject(vm.stack[vm.sp-2])
  1933  	method := vm.r.toObject(vm.stack[vm.sp-1])
  1934  
  1935  	obj.self.defineOwnPropertyStr(d.key, PropertyDescriptor{
  1936  		Value:        method,
  1937  		Writable:     FLAG_TRUE,
  1938  		Configurable: FLAG_TRUE,
  1939  		Enumerable:   ToFlag(d.enumerable),
  1940  	}, true)
  1941  
  1942  	vm.sp--
  1943  	vm.pc++
  1944  }
  1945  
  1946  type _setProto struct{}
  1947  
  1948  var setProto _setProto
  1949  
  1950  func (_setProto) exec(vm *vm) {
  1951  	vm.r.setObjectProto(vm.stack[vm.sp-2], vm.stack[vm.sp-1])
  1952  
  1953  	vm.sp--
  1954  	vm.pc++
  1955  }
  1956  
  1957  type defineGetterKeyed struct {
  1958  	key        unistring.String
  1959  	enumerable bool
  1960  }
  1961  
  1962  func (s *defineGetterKeyed) exec(vm *vm) {
  1963  	obj := vm.r.toObject(vm.stack[vm.sp-2])
  1964  	val := vm.stack[vm.sp-1]
  1965  	method := vm.r.toObject(val)
  1966  	method.self.defineOwnPropertyStr("name", PropertyDescriptor{
  1967  		Value:        asciiString("get ").concat(stringValueFromRaw(s.key)),
  1968  		Configurable: FLAG_TRUE,
  1969  	}, true)
  1970  	descr := PropertyDescriptor{
  1971  		Getter:       val,
  1972  		Configurable: FLAG_TRUE,
  1973  		Enumerable:   ToFlag(s.enumerable),
  1974  	}
  1975  
  1976  	obj.self.defineOwnPropertyStr(s.key, descr, true)
  1977  
  1978  	vm.sp--
  1979  	vm.pc++
  1980  }
  1981  
  1982  type defineSetterKeyed struct {
  1983  	key        unistring.String
  1984  	enumerable bool
  1985  }
  1986  
  1987  func (s *defineSetterKeyed) exec(vm *vm) {
  1988  	obj := vm.r.toObject(vm.stack[vm.sp-2])
  1989  	val := vm.stack[vm.sp-1]
  1990  	method := vm.r.toObject(val)
  1991  	method.self.defineOwnPropertyStr("name", PropertyDescriptor{
  1992  		Value:        asciiString("set ").concat(stringValueFromRaw(s.key)),
  1993  		Configurable: FLAG_TRUE,
  1994  	}, true)
  1995  
  1996  	descr := PropertyDescriptor{
  1997  		Setter:       val,
  1998  		Configurable: FLAG_TRUE,
  1999  		Enumerable:   ToFlag(s.enumerable),
  2000  	}
  2001  
  2002  	obj.self.defineOwnPropertyStr(s.key, descr, true)
  2003  
  2004  	vm.sp--
  2005  	vm.pc++
  2006  }
  2007  
  2008  type defineGetter struct {
  2009  	enumerable bool
  2010  }
  2011  
  2012  func (s *defineGetter) exec(vm *vm) {
  2013  	obj := vm.r.toObject(vm.stack[vm.sp-3])
  2014  	propName := vm.stack[vm.sp-2]
  2015  	val := vm.stack[vm.sp-1]
  2016  	method := vm.r.toObject(val)
  2017  	method.self.defineOwnPropertyStr("name", PropertyDescriptor{
  2018  		Value:        funcName("get ", propName),
  2019  		Configurable: FLAG_TRUE,
  2020  	}, true)
  2021  
  2022  	descr := PropertyDescriptor{
  2023  		Getter:       val,
  2024  		Configurable: FLAG_TRUE,
  2025  		Enumerable:   ToFlag(s.enumerable),
  2026  	}
  2027  
  2028  	obj.defineOwnProperty(propName, descr, true)
  2029  
  2030  	vm.sp -= 2
  2031  	vm.pc++
  2032  }
  2033  
  2034  type defineSetter struct {
  2035  	enumerable bool
  2036  }
  2037  
  2038  func (s *defineSetter) exec(vm *vm) {
  2039  	obj := vm.r.toObject(vm.stack[vm.sp-3])
  2040  	propName := vm.stack[vm.sp-2]
  2041  	val := vm.stack[vm.sp-1]
  2042  	method := vm.r.toObject(val)
  2043  
  2044  	method.self.defineOwnPropertyStr("name", PropertyDescriptor{
  2045  		Value:        funcName("set ", propName),
  2046  		Configurable: FLAG_TRUE,
  2047  	}, true)
  2048  
  2049  	descr := PropertyDescriptor{
  2050  		Setter:       val,
  2051  		Configurable: FLAG_TRUE,
  2052  		Enumerable:   FLAG_TRUE,
  2053  	}
  2054  
  2055  	obj.defineOwnProperty(propName, descr, true)
  2056  
  2057  	vm.sp -= 2
  2058  	vm.pc++
  2059  }
  2060  
  2061  type getProp unistring.String
  2062  
  2063  func (g getProp) exec(vm *vm) {
  2064  	v := vm.stack[vm.sp-1]
  2065  	obj := v.baseObject(vm.r)
  2066  	if obj == nil {
  2067  		panic(vm.r.NewTypeError("Cannot read property '%s' of undefined", g))
  2068  	}
  2069  	vm.stack[vm.sp-1] = nilSafe(obj.self.getStr(unistring.String(g), v))
  2070  
  2071  	vm.pc++
  2072  }
  2073  
  2074  type getPropRecv unistring.String
  2075  
  2076  func (g getPropRecv) exec(vm *vm) {
  2077  	recv := vm.stack[vm.sp-2]
  2078  	v := vm.stack[vm.sp-1]
  2079  	obj := v.baseObject(vm.r)
  2080  	if obj == nil {
  2081  		panic(vm.r.NewTypeError("Cannot read property '%s' of undefined", g))
  2082  	}
  2083  	vm.stack[vm.sp-2] = nilSafe(obj.self.getStr(unistring.String(g), recv))
  2084  	vm.sp--
  2085  	vm.pc++
  2086  }
  2087  
  2088  type getPropRecvCallee unistring.String
  2089  
  2090  func (g getPropRecvCallee) exec(vm *vm) {
  2091  	recv := vm.stack[vm.sp-2]
  2092  	v := vm.stack[vm.sp-1]
  2093  	obj := v.baseObject(vm.r)
  2094  	if obj == nil {
  2095  		panic(vm.r.NewTypeError("Cannot read property '%s' of undefined", g))
  2096  	}
  2097  
  2098  	n := unistring.String(g)
  2099  	prop := obj.self.getStr(n, recv)
  2100  	if prop == nil {
  2101  		prop = memberUnresolved{valueUnresolved{r: vm.r, ref: n}}
  2102  	}
  2103  
  2104  	vm.stack[vm.sp-1] = prop
  2105  	vm.pc++
  2106  }
  2107  
  2108  type getPropCallee unistring.String
  2109  
  2110  func (g getPropCallee) exec(vm *vm) {
  2111  	v := vm.stack[vm.sp-1]
  2112  	obj := v.baseObject(vm.r)
  2113  	n := unistring.String(g)
  2114  	if obj == nil {
  2115  		panic(vm.r.NewTypeError("Cannot read property '%s' of undefined or null", n))
  2116  	}
  2117  	prop := obj.self.getStr(n, v)
  2118  	if prop == nil {
  2119  		prop = memberUnresolved{valueUnresolved{r: vm.r, ref: n}}
  2120  	}
  2121  	vm.push(prop)
  2122  
  2123  	vm.pc++
  2124  }
  2125  
  2126  type _getElem struct{}
  2127  
  2128  var getElem _getElem
  2129  
  2130  func (_getElem) exec(vm *vm) {
  2131  	v := vm.stack[vm.sp-2]
  2132  	obj := v.baseObject(vm.r)
  2133  	propName := toPropertyKey(vm.stack[vm.sp-1])
  2134  	if obj == nil {
  2135  		panic(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String()))
  2136  	}
  2137  
  2138  	vm.stack[vm.sp-2] = nilSafe(obj.get(propName, v))
  2139  
  2140  	vm.sp--
  2141  	vm.pc++
  2142  }
  2143  
  2144  type _getElemRecv struct{}
  2145  
  2146  var getElemRecv _getElemRecv
  2147  
  2148  func (_getElemRecv) exec(vm *vm) {
  2149  	recv := vm.stack[vm.sp-3]
  2150  	propName := toPropertyKey(vm.stack[vm.sp-2])
  2151  	v := vm.stack[vm.sp-1]
  2152  	obj := v.baseObject(vm.r)
  2153  	if obj == nil {
  2154  		panic(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String()))
  2155  	}
  2156  
  2157  	vm.stack[vm.sp-3] = nilSafe(obj.get(propName, recv))
  2158  
  2159  	vm.sp -= 2
  2160  	vm.pc++
  2161  }
  2162  
  2163  type _getKey struct{}
  2164  
  2165  var getKey _getKey
  2166  
  2167  func (_getKey) exec(vm *vm) {
  2168  	v := vm.stack[vm.sp-2]
  2169  	obj := v.baseObject(vm.r)
  2170  	propName := vm.stack[vm.sp-1]
  2171  	if obj == nil {
  2172  		panic(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String()))
  2173  	}
  2174  
  2175  	vm.stack[vm.sp-2] = nilSafe(obj.get(propName, v))
  2176  
  2177  	vm.sp--
  2178  	vm.pc++
  2179  }
  2180  
  2181  type _getElemCallee struct{}
  2182  
  2183  var getElemCallee _getElemCallee
  2184  
  2185  func (_getElemCallee) exec(vm *vm) {
  2186  	v := vm.stack[vm.sp-2]
  2187  	obj := v.baseObject(vm.r)
  2188  	propName := toPropertyKey(vm.stack[vm.sp-1])
  2189  	if obj == nil {
  2190  		panic(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String()))
  2191  	}
  2192  
  2193  	prop := obj.get(propName, v)
  2194  	if prop == nil {
  2195  		prop = memberUnresolved{valueUnresolved{r: vm.r, ref: propName.string()}}
  2196  	}
  2197  	vm.stack[vm.sp-1] = prop
  2198  
  2199  	vm.pc++
  2200  }
  2201  
  2202  type _getElemRecvCallee struct{}
  2203  
  2204  var getElemRecvCallee _getElemRecvCallee
  2205  
  2206  func (_getElemRecvCallee) exec(vm *vm) {
  2207  	recv := vm.stack[vm.sp-3]
  2208  	v := vm.stack[vm.sp-2]
  2209  	obj := v.baseObject(vm.r)
  2210  	propName := toPropertyKey(vm.stack[vm.sp-1])
  2211  	if obj == nil {
  2212  		panic(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String()))
  2213  	}
  2214  
  2215  	prop := obj.get(propName, recv)
  2216  	if prop == nil {
  2217  		prop = memberUnresolved{valueUnresolved{r: vm.r, ref: propName.string()}}
  2218  	}
  2219  	vm.stack[vm.sp-2] = prop
  2220  	vm.sp--
  2221  
  2222  	vm.pc++
  2223  }
  2224  
  2225  type _dup struct{}
  2226  
  2227  var dup _dup
  2228  
  2229  func (_dup) exec(vm *vm) {
  2230  	vm.push(vm.stack[vm.sp-1])
  2231  	vm.pc++
  2232  }
  2233  
  2234  type dupN uint32
  2235  
  2236  func (d dupN) exec(vm *vm) {
  2237  	vm.push(vm.stack[vm.sp-1-int(d)])
  2238  	vm.pc++
  2239  }
  2240  
  2241  type rdupN uint32
  2242  
  2243  func (d rdupN) exec(vm *vm) {
  2244  	vm.stack[vm.sp-1-int(d)] = vm.stack[vm.sp-1]
  2245  	vm.pc++
  2246  }
  2247  
  2248  type dupLast uint32
  2249  
  2250  func (d dupLast) exec(vm *vm) {
  2251  	e := vm.sp + int(d)
  2252  	vm.stack.expand(e)
  2253  	copy(vm.stack[vm.sp:e], vm.stack[vm.sp-int(d):])
  2254  	vm.sp = e
  2255  	vm.pc++
  2256  }
  2257  
  2258  type _newObject struct{}
  2259  
  2260  var newObject _newObject
  2261  
  2262  func (_newObject) exec(vm *vm) {
  2263  	vm.push(vm.r.NewObject())
  2264  	vm.pc++
  2265  }
  2266  
  2267  type newArray uint32
  2268  
  2269  func (l newArray) exec(vm *vm) {
  2270  	values := make([]Value, 0, l)
  2271  	vm.push(vm.r.newArrayValues(values))
  2272  	vm.pc++
  2273  }
  2274  
  2275  type _pushArrayItem struct{}
  2276  
  2277  var pushArrayItem _pushArrayItem
  2278  
  2279  func (_pushArrayItem) exec(vm *vm) {
  2280  	arr := vm.stack[vm.sp-2].(*Object).self.(*arrayObject)
  2281  	if arr.length < math.MaxUint32 {
  2282  		arr.length++
  2283  	} else {
  2284  		panic(vm.r.newError(vm.r.global.RangeError, "Invalid array length"))
  2285  	}
  2286  	val := vm.stack[vm.sp-1]
  2287  	arr.values = append(arr.values, val)
  2288  	if val != nil {
  2289  		arr.objCount++
  2290  	}
  2291  	vm.sp--
  2292  	vm.pc++
  2293  }
  2294  
  2295  type _pushArraySpread struct{}
  2296  
  2297  var pushArraySpread _pushArraySpread
  2298  
  2299  func (_pushArraySpread) exec(vm *vm) {
  2300  	arr := vm.stack[vm.sp-2].(*Object).self.(*arrayObject)
  2301  	vm.r.getIterator(vm.stack[vm.sp-1], nil).iterate(func(val Value) {
  2302  		if arr.length < math.MaxUint32 {
  2303  			arr.length++
  2304  		} else {
  2305  			panic(vm.r.newError(vm.r.global.RangeError, "Invalid array length"))
  2306  		}
  2307  		arr.values = append(arr.values, val)
  2308  		arr.objCount++
  2309  	})
  2310  	vm.sp--
  2311  	vm.pc++
  2312  }
  2313  
  2314  type _pushSpread struct{}
  2315  
  2316  var pushSpread _pushSpread
  2317  
  2318  func (_pushSpread) exec(vm *vm) {
  2319  	vm.sp--
  2320  	obj := vm.stack[vm.sp]
  2321  	vm.r.getIterator(obj, nil).iterate(func(val Value) {
  2322  		vm.push(val)
  2323  	})
  2324  	vm.pc++
  2325  }
  2326  
  2327  type _newArrayFromIter struct{}
  2328  
  2329  var newArrayFromIter _newArrayFromIter
  2330  
  2331  func (_newArrayFromIter) exec(vm *vm) {
  2332  	var values []Value
  2333  	l := len(vm.iterStack) - 1
  2334  	iter := vm.iterStack[l].iter
  2335  	vm.iterStack[l] = iterStackItem{}
  2336  	vm.iterStack = vm.iterStack[:l]
  2337  	if iter.iterator != nil {
  2338  		iter.iterate(func(val Value) {
  2339  			values = append(values, val)
  2340  		})
  2341  	}
  2342  	vm.push(vm.r.newArrayValues(values))
  2343  	vm.pc++
  2344  }
  2345  
  2346  type newRegexp struct {
  2347  	pattern *regexpPattern
  2348  	src     valueString
  2349  }
  2350  
  2351  func (n *newRegexp) exec(vm *vm) {
  2352  	vm.push(vm.r.newRegExpp(n.pattern.clone(), n.src, vm.r.global.RegExpPrototype).val)
  2353  	vm.pc++
  2354  }
  2355  
  2356  func (vm *vm) setLocalLex(s int) {
  2357  	v := vm.stack[vm.sp-1]
  2358  	level := s >> 24
  2359  	idx := uint32(s & 0x00FFFFFF)
  2360  	stash := vm.stash
  2361  	for i := 0; i < level; i++ {
  2362  		stash = stash.outer
  2363  	}
  2364  	p := &stash.values[idx]
  2365  	if *p == nil {
  2366  		panic(errAccessBeforeInit)
  2367  	}
  2368  	*p = v
  2369  	vm.pc++
  2370  }
  2371  
  2372  func (vm *vm) initLocal(s int) {
  2373  	v := vm.stack[vm.sp-1]
  2374  	level := s >> 24
  2375  	idx := uint32(s & 0x00FFFFFF)
  2376  	stash := vm.stash
  2377  	for i := 0; i < level; i++ {
  2378  		stash = stash.outer
  2379  	}
  2380  	stash.initByIdx(idx, v)
  2381  	vm.pc++
  2382  }
  2383  
  2384  type storeStash uint32
  2385  
  2386  func (s storeStash) exec(vm *vm) {
  2387  	vm.initLocal(int(s))
  2388  }
  2389  
  2390  type storeStashP uint32
  2391  
  2392  func (s storeStashP) exec(vm *vm) {
  2393  	vm.initLocal(int(s))
  2394  	vm.sp--
  2395  }
  2396  
  2397  type storeStashLex uint32
  2398  
  2399  func (s storeStashLex) exec(vm *vm) {
  2400  	vm.setLocalLex(int(s))
  2401  }
  2402  
  2403  type storeStashLexP uint32
  2404  
  2405  func (s storeStashLexP) exec(vm *vm) {
  2406  	vm.setLocalLex(int(s))
  2407  	vm.sp--
  2408  }
  2409  
  2410  type initStash uint32
  2411  
  2412  func (s initStash) exec(vm *vm) {
  2413  	vm.initLocal(int(s))
  2414  }
  2415  
  2416  type initStashP uint32
  2417  
  2418  func (s initStashP) exec(vm *vm) {
  2419  	vm.initLocal(int(s))
  2420  	vm.sp--
  2421  }
  2422  
  2423  type initGlobalP unistring.String
  2424  
  2425  func (s initGlobalP) exec(vm *vm) {
  2426  	vm.sp--
  2427  	vm.r.global.stash.initByName(unistring.String(s), vm.stack[vm.sp])
  2428  	vm.pc++
  2429  }
  2430  
  2431  type initGlobal unistring.String
  2432  
  2433  func (s initGlobal) exec(vm *vm) {
  2434  	vm.r.global.stash.initByName(unistring.String(s), vm.stack[vm.sp])
  2435  	vm.pc++
  2436  }
  2437  
  2438  type resolveVar1 unistring.String
  2439  
  2440  func (s resolveVar1) exec(vm *vm) {
  2441  	name := unistring.String(s)
  2442  	var ref ref
  2443  	for stash := vm.stash; stash != nil; stash = stash.outer {
  2444  		ref = stash.getRefByName(name, false)
  2445  		if ref != nil {
  2446  			goto end
  2447  		}
  2448  	}
  2449  
  2450  	ref = &objRef{
  2451  		base:    vm.r.globalObject,
  2452  		name:    name,
  2453  		binding: true,
  2454  	}
  2455  
  2456  end:
  2457  	vm.refStack = append(vm.refStack, ref)
  2458  	vm.pc++
  2459  }
  2460  
  2461  type deleteVar unistring.String
  2462  
  2463  func (d deleteVar) exec(vm *vm) {
  2464  	name := unistring.String(d)
  2465  	ret := true
  2466  	for stash := vm.stash; stash != nil; stash = stash.outer {
  2467  		if stash.obj != nil {
  2468  			if stashObjHas(stash.obj, name) {
  2469  				ret = stash.obj.self.deleteStr(name, false)
  2470  				goto end
  2471  			}
  2472  		} else {
  2473  			if idx, exists := stash.names[name]; exists {
  2474  				if idx&(maskVar|maskDeletable) == maskVar|maskDeletable {
  2475  					stash.deleteBinding(name)
  2476  				} else {
  2477  					ret = false
  2478  				}
  2479  				goto end
  2480  			}
  2481  		}
  2482  	}
  2483  
  2484  	if vm.r.globalObject.self.hasPropertyStr(name) {
  2485  		ret = vm.r.globalObject.self.deleteStr(name, false)
  2486  	}
  2487  
  2488  end:
  2489  	if ret {
  2490  		vm.push(valueTrue)
  2491  	} else {
  2492  		vm.push(valueFalse)
  2493  	}
  2494  	vm.pc++
  2495  }
  2496  
  2497  type deleteGlobal unistring.String
  2498  
  2499  func (d deleteGlobal) exec(vm *vm) {
  2500  	name := unistring.String(d)
  2501  	var ret bool
  2502  	if vm.r.globalObject.self.hasPropertyStr(name) {
  2503  		ret = vm.r.globalObject.self.deleteStr(name, false)
  2504  		if ret {
  2505  			delete(vm.r.global.varNames, name)
  2506  		}
  2507  	} else {
  2508  		ret = true
  2509  	}
  2510  	if ret {
  2511  		vm.push(valueTrue)
  2512  	} else {
  2513  		vm.push(valueFalse)
  2514  	}
  2515  	vm.pc++
  2516  }
  2517  
  2518  type resolveVar1Strict unistring.String
  2519  
  2520  func (s resolveVar1Strict) exec(vm *vm) {
  2521  	name := unistring.String(s)
  2522  	var ref ref
  2523  	for stash := vm.stash; stash != nil; stash = stash.outer {
  2524  		ref = stash.getRefByName(name, true)
  2525  		if ref != nil {
  2526  			goto end
  2527  		}
  2528  	}
  2529  
  2530  	if vm.r.globalObject.self.hasPropertyStr(name) {
  2531  		ref = &objRef{
  2532  			base:    vm.r.globalObject,
  2533  			name:    name,
  2534  			binding: true,
  2535  			strict:  true,
  2536  		}
  2537  		goto end
  2538  	}
  2539  
  2540  	ref = &unresolvedRef{
  2541  		runtime: vm.r,
  2542  		name:    name,
  2543  	}
  2544  
  2545  end:
  2546  	vm.refStack = append(vm.refStack, ref)
  2547  	vm.pc++
  2548  }
  2549  
  2550  type setGlobal unistring.String
  2551  
  2552  func (s setGlobal) exec(vm *vm) {
  2553  	vm.r.setGlobal(unistring.String(s), vm.peek(), false)
  2554  	vm.pc++
  2555  }
  2556  
  2557  type setGlobalStrict unistring.String
  2558  
  2559  func (s setGlobalStrict) exec(vm *vm) {
  2560  	vm.r.setGlobal(unistring.String(s), vm.peek(), true)
  2561  	vm.pc++
  2562  }
  2563  
  2564  // Load a var from stash
  2565  type loadStash uint32
  2566  
  2567  func (g loadStash) exec(vm *vm) {
  2568  	level := int(g >> 24)
  2569  	idx := uint32(g & 0x00FFFFFF)
  2570  	stash := vm.stash
  2571  	for i := 0; i < level; i++ {
  2572  		stash = stash.outer
  2573  	}
  2574  
  2575  	vm.push(nilSafe(stash.getByIdx(idx)))
  2576  	vm.pc++
  2577  }
  2578  
  2579  // Load a lexical binding from stash
  2580  type loadStashLex uint32
  2581  
  2582  func (g loadStashLex) exec(vm *vm) {
  2583  	level := int(g >> 24)
  2584  	idx := uint32(g & 0x00FFFFFF)
  2585  	stash := vm.stash
  2586  	for i := 0; i < level; i++ {
  2587  		stash = stash.outer
  2588  	}
  2589  
  2590  	v := stash.getByIdx(idx)
  2591  	if v == nil {
  2592  		panic(errAccessBeforeInit)
  2593  	}
  2594  	vm.push(v)
  2595  	vm.pc++
  2596  }
  2597  
  2598  // scan dynamic stashes up to the given level (encoded as 8 most significant bits of idx), if not found
  2599  // return the indexed var binding value from stash
  2600  type loadMixed struct {
  2601  	name   unistring.String
  2602  	idx    uint32
  2603  	callee bool
  2604  }
  2605  
  2606  func (g *loadMixed) exec(vm *vm) {
  2607  	level := int(g.idx >> 24)
  2608  	idx := g.idx & 0x00FFFFFF
  2609  	stash := vm.stash
  2610  	name := g.name
  2611  	for i := 0; i < level; i++ {
  2612  		if v, found := stash.getByName(name); found {
  2613  			if g.callee {
  2614  				if stash.obj != nil {
  2615  					vm.push(stash.obj)
  2616  				} else {
  2617  					vm.push(_undefined)
  2618  				}
  2619  			}
  2620  			vm.push(v)
  2621  			goto end
  2622  		}
  2623  		stash = stash.outer
  2624  	}
  2625  	if g.callee {
  2626  		vm.push(_undefined)
  2627  	}
  2628  	if stash != nil {
  2629  		vm.push(nilSafe(stash.getByIdx(idx)))
  2630  	}
  2631  end:
  2632  	vm.pc++
  2633  }
  2634  
  2635  // scan dynamic stashes up to the given level (encoded as 8 most significant bits of idx), if not found
  2636  // return the indexed lexical binding value from stash
  2637  type loadMixedLex loadMixed
  2638  
  2639  func (g *loadMixedLex) exec(vm *vm) {
  2640  	level := int(g.idx >> 24)
  2641  	idx := g.idx & 0x00FFFFFF
  2642  	stash := vm.stash
  2643  	name := g.name
  2644  	for i := 0; i < level; i++ {
  2645  		if v, found := stash.getByName(name); found {
  2646  			if g.callee {
  2647  				if stash.obj != nil {
  2648  					vm.push(stash.obj)
  2649  				} else {
  2650  					vm.push(_undefined)
  2651  				}
  2652  			}
  2653  			vm.push(v)
  2654  			goto end
  2655  		}
  2656  		stash = stash.outer
  2657  	}
  2658  	if g.callee {
  2659  		vm.push(_undefined)
  2660  	}
  2661  	if stash != nil {
  2662  		v := stash.getByIdx(idx)
  2663  		if v == nil {
  2664  			panic(errAccessBeforeInit)
  2665  		}
  2666  		vm.push(v)
  2667  	}
  2668  end:
  2669  	vm.pc++
  2670  }
  2671  
  2672  // scan dynamic stashes up to the given level (encoded as 8 most significant bits of idx), if not found
  2673  // return the indexed var binding value from stack
  2674  type loadMixedStack struct {
  2675  	name   unistring.String
  2676  	idx    int
  2677  	level  uint8
  2678  	callee bool
  2679  }
  2680  
  2681  // same as loadMixedStack, but the args have been moved to stash (therefore stack layout is different)
  2682  type loadMixedStack1 loadMixedStack
  2683  
  2684  func (g *loadMixedStack) exec(vm *vm) {
  2685  	stash := vm.stash
  2686  	name := g.name
  2687  	level := int(g.level)
  2688  	for i := 0; i < level; i++ {
  2689  		if v, found := stash.getByName(name); found {
  2690  			if g.callee {
  2691  				if stash.obj != nil {
  2692  					vm.push(stash.obj)
  2693  				} else {
  2694  					vm.push(_undefined)
  2695  				}
  2696  			}
  2697  			vm.push(v)
  2698  			goto end
  2699  		}
  2700  		stash = stash.outer
  2701  	}
  2702  	if g.callee {
  2703  		vm.push(_undefined)
  2704  	}
  2705  	loadStack(g.idx).exec(vm)
  2706  	return
  2707  end:
  2708  	vm.pc++
  2709  }
  2710  
  2711  func (g *loadMixedStack1) exec(vm *vm) {
  2712  	stash := vm.stash
  2713  	name := g.name
  2714  	level := int(g.level)
  2715  	for i := 0; i < level; i++ {
  2716  		if v, found := stash.getByName(name); found {
  2717  			if g.callee {
  2718  				if stash.obj != nil {
  2719  					vm.push(stash.obj)
  2720  				} else {
  2721  					vm.push(_undefined)
  2722  				}
  2723  			}
  2724  			vm.push(v)
  2725  			goto end
  2726  		}
  2727  		stash = stash.outer
  2728  	}
  2729  	if g.callee {
  2730  		vm.push(_undefined)
  2731  	}
  2732  	loadStack1(g.idx).exec(vm)
  2733  	return
  2734  end:
  2735  	vm.pc++
  2736  }
  2737  
  2738  type loadMixedStackLex loadMixedStack
  2739  
  2740  // same as loadMixedStackLex but when the arguments have been moved into stash
  2741  type loadMixedStack1Lex loadMixedStack
  2742  
  2743  func (g *loadMixedStackLex) exec(vm *vm) {
  2744  	stash := vm.stash
  2745  	name := g.name
  2746  	level := int(g.level)
  2747  	for i := 0; i < level; i++ {
  2748  		if v, found := stash.getByName(name); found {
  2749  			if g.callee {
  2750  				if stash.obj != nil {
  2751  					vm.push(stash.obj)
  2752  				} else {
  2753  					vm.push(_undefined)
  2754  				}
  2755  			}
  2756  			vm.push(v)
  2757  			goto end
  2758  		}
  2759  		stash = stash.outer
  2760  	}
  2761  	if g.callee {
  2762  		vm.push(_undefined)
  2763  	}
  2764  	loadStackLex(g.idx).exec(vm)
  2765  	return
  2766  end:
  2767  	vm.pc++
  2768  }
  2769  
  2770  func (g *loadMixedStack1Lex) exec(vm *vm) {
  2771  	stash := vm.stash
  2772  	name := g.name
  2773  	level := int(g.level)
  2774  	for i := 0; i < level; i++ {
  2775  		if v, found := stash.getByName(name); found {
  2776  			if g.callee {
  2777  				if stash.obj != nil {
  2778  					vm.push(stash.obj)
  2779  				} else {
  2780  					vm.push(_undefined)
  2781  				}
  2782  			}
  2783  			vm.push(v)
  2784  			goto end
  2785  		}
  2786  		stash = stash.outer
  2787  	}
  2788  	if g.callee {
  2789  		vm.push(_undefined)
  2790  	}
  2791  	loadStack1Lex(g.idx).exec(vm)
  2792  	return
  2793  end:
  2794  	vm.pc++
  2795  }
  2796  
  2797  type resolveMixed struct {
  2798  	name   unistring.String
  2799  	idx    uint32
  2800  	typ    varType
  2801  	strict bool
  2802  }
  2803  
  2804  func newStashRef(typ varType, name unistring.String, v *[]Value, idx int) ref {
  2805  	switch typ {
  2806  	case varTypeVar:
  2807  		return &stashRef{
  2808  			n:   name,
  2809  			v:   v,
  2810  			idx: idx,
  2811  		}
  2812  	case varTypeLet:
  2813  		return &stashRefLex{
  2814  			stashRef: stashRef{
  2815  				n:   name,
  2816  				v:   v,
  2817  				idx: idx,
  2818  			},
  2819  		}
  2820  	case varTypeConst, varTypeStrictConst:
  2821  		return &stashRefConst{
  2822  			stashRefLex: stashRefLex{
  2823  				stashRef: stashRef{
  2824  					n:   name,
  2825  					v:   v,
  2826  					idx: idx,
  2827  				},
  2828  			},
  2829  			strictConst: typ == varTypeStrictConst,
  2830  		}
  2831  	}
  2832  	panic("unsupported var type")
  2833  }
  2834  
  2835  func (r *resolveMixed) exec(vm *vm) {
  2836  	level := int(r.idx >> 24)
  2837  	idx := r.idx & 0x00FFFFFF
  2838  	stash := vm.stash
  2839  	var ref ref
  2840  	for i := 0; i < level; i++ {
  2841  		ref = stash.getRefByName(r.name, r.strict)
  2842  		if ref != nil {
  2843  			goto end
  2844  		}
  2845  		stash = stash.outer
  2846  	}
  2847  
  2848  	if stash != nil {
  2849  		ref = newStashRef(r.typ, r.name, &stash.values, int(idx))
  2850  		goto end
  2851  	}
  2852  
  2853  	ref = &unresolvedRef{
  2854  		runtime: vm.r,
  2855  		name:    r.name,
  2856  	}
  2857  
  2858  end:
  2859  	vm.refStack = append(vm.refStack, ref)
  2860  	vm.pc++
  2861  }
  2862  
  2863  type resolveMixedStack struct {
  2864  	name   unistring.String
  2865  	idx    int
  2866  	typ    varType
  2867  	level  uint8
  2868  	strict bool
  2869  }
  2870  
  2871  type resolveMixedStack1 resolveMixedStack
  2872  
  2873  func (r *resolveMixedStack) exec(vm *vm) {
  2874  	level := int(r.level)
  2875  	stash := vm.stash
  2876  	var ref ref
  2877  	var idx int
  2878  	for i := 0; i < level; i++ {
  2879  		ref = stash.getRefByName(r.name, r.strict)
  2880  		if ref != nil {
  2881  			goto end
  2882  		}
  2883  		stash = stash.outer
  2884  	}
  2885  
  2886  	if r.idx > 0 {
  2887  		idx = vm.sb + vm.args + r.idx
  2888  	} else {
  2889  		idx = vm.sb - r.idx
  2890  	}
  2891  
  2892  	ref = newStashRef(r.typ, r.name, (*[]Value)(&vm.stack), idx)
  2893  
  2894  end:
  2895  	vm.refStack = append(vm.refStack, ref)
  2896  	vm.pc++
  2897  }
  2898  
  2899  func (r *resolveMixedStack1) exec(vm *vm) {
  2900  	level := int(r.level)
  2901  	stash := vm.stash
  2902  	var ref ref
  2903  	for i := 0; i < level; i++ {
  2904  		ref = stash.getRefByName(r.name, r.strict)
  2905  		if ref != nil {
  2906  			goto end
  2907  		}
  2908  		stash = stash.outer
  2909  	}
  2910  
  2911  	ref = newStashRef(r.typ, r.name, (*[]Value)(&vm.stack), vm.sb+r.idx)
  2912  
  2913  end:
  2914  	vm.refStack = append(vm.refStack, ref)
  2915  	vm.pc++
  2916  }
  2917  
  2918  type _getValue struct{}
  2919  
  2920  var getValue _getValue
  2921  
  2922  func (_getValue) exec(vm *vm) {
  2923  	ref := vm.refStack[len(vm.refStack)-1]
  2924  	if v := ref.get(); v != nil {
  2925  		vm.push(v)
  2926  	} else {
  2927  		vm.r.throwReferenceError(ref.refname())
  2928  		panic("Unreachable")
  2929  	}
  2930  	vm.pc++
  2931  }
  2932  
  2933  type _putValue struct{}
  2934  
  2935  var putValue _putValue
  2936  
  2937  func (_putValue) exec(vm *vm) {
  2938  	l := len(vm.refStack) - 1
  2939  	ref := vm.refStack[l]
  2940  	vm.refStack[l] = nil
  2941  	vm.refStack = vm.refStack[:l]
  2942  	ref.set(vm.stack[vm.sp-1])
  2943  	vm.pc++
  2944  }
  2945  
  2946  type _putValueP struct{}
  2947  
  2948  var putValueP _putValueP
  2949  
  2950  func (_putValueP) exec(vm *vm) {
  2951  	l := len(vm.refStack) - 1
  2952  	ref := vm.refStack[l]
  2953  	vm.refStack[l] = nil
  2954  	vm.refStack = vm.refStack[:l]
  2955  	ref.set(vm.stack[vm.sp-1])
  2956  	vm.sp--
  2957  	vm.pc++
  2958  }
  2959  
  2960  type _initValueP struct{}
  2961  
  2962  var initValueP _initValueP
  2963  
  2964  func (_initValueP) exec(vm *vm) {
  2965  	l := len(vm.refStack) - 1
  2966  	ref := vm.refStack[l]
  2967  	vm.refStack[l] = nil
  2968  	vm.refStack = vm.refStack[:l]
  2969  	ref.init(vm.stack[vm.sp-1])
  2970  	vm.sp--
  2971  	vm.pc++
  2972  }
  2973  
  2974  type loadDynamic unistring.String
  2975  
  2976  func (n loadDynamic) exec(vm *vm) {
  2977  	name := unistring.String(n)
  2978  	var val Value
  2979  	for stash := vm.stash; stash != nil; stash = stash.outer {
  2980  		if v, exists := stash.getByName(name); exists {
  2981  			val = v
  2982  			break
  2983  		}
  2984  	}
  2985  	if val == nil {
  2986  		val = vm.r.globalObject.self.getStr(name, nil)
  2987  		if val == nil {
  2988  			vm.r.throwReferenceError(name)
  2989  		}
  2990  	}
  2991  	vm.push(val)
  2992  	vm.pc++
  2993  }
  2994  
  2995  type loadDynamicRef unistring.String
  2996  
  2997  func (n loadDynamicRef) exec(vm *vm) {
  2998  	name := unistring.String(n)
  2999  	var val Value
  3000  	for stash := vm.stash; stash != nil; stash = stash.outer {
  3001  		if v, exists := stash.getByName(name); exists {
  3002  			val = v
  3003  			break
  3004  		}
  3005  	}
  3006  	if val == nil {
  3007  		val = vm.r.globalObject.self.getStr(name, nil)
  3008  		if val == nil {
  3009  			val = valueUnresolved{r: vm.r, ref: name}
  3010  		}
  3011  	}
  3012  	vm.push(val)
  3013  	vm.pc++
  3014  }
  3015  
  3016  type loadDynamicCallee unistring.String
  3017  
  3018  func (n loadDynamicCallee) exec(vm *vm) {
  3019  	name := unistring.String(n)
  3020  	var val Value
  3021  	var callee *Object
  3022  	for stash := vm.stash; stash != nil; stash = stash.outer {
  3023  		if v, exists := stash.getByName(name); exists {
  3024  			callee = stash.obj
  3025  			val = v
  3026  			break
  3027  		}
  3028  	}
  3029  	if val == nil {
  3030  		val = vm.r.globalObject.self.getStr(name, nil)
  3031  		if val == nil {
  3032  			val = valueUnresolved{r: vm.r, ref: name}
  3033  		}
  3034  	}
  3035  	if callee != nil {
  3036  		vm.push(callee)
  3037  	} else {
  3038  		vm.push(_undefined)
  3039  	}
  3040  	vm.push(val)
  3041  	vm.pc++
  3042  }
  3043  
  3044  type _pop struct{}
  3045  
  3046  var pop _pop
  3047  
  3048  func (_pop) exec(vm *vm) {
  3049  	vm.sp--
  3050  	vm.pc++
  3051  }
  3052  
  3053  func (vm *vm) callEval(n int, strict bool) {
  3054  	if vm.r.toObject(vm.stack[vm.sp-n-1]) == vm.r.global.Eval {
  3055  		if n > 0 {
  3056  			srcVal := vm.stack[vm.sp-n]
  3057  			if src, ok := srcVal.(valueString); ok {
  3058  				ret := vm.r.eval(src, true, strict)
  3059  				vm.stack[vm.sp-n-2] = ret
  3060  			} else {
  3061  				vm.stack[vm.sp-n-2] = srcVal
  3062  			}
  3063  		} else {
  3064  			vm.stack[vm.sp-n-2] = _undefined
  3065  		}
  3066  
  3067  		vm.sp -= n + 1
  3068  		vm.pc++
  3069  	} else {
  3070  		call(n).exec(vm)
  3071  	}
  3072  }
  3073  
  3074  type callEval uint32
  3075  
  3076  func (numargs callEval) exec(vm *vm) {
  3077  	vm.callEval(int(numargs), false)
  3078  }
  3079  
  3080  type callEvalStrict uint32
  3081  
  3082  func (numargs callEvalStrict) exec(vm *vm) {
  3083  	vm.callEval(int(numargs), true)
  3084  }
  3085  
  3086  type _callEvalVariadic struct{}
  3087  
  3088  var callEvalVariadic _callEvalVariadic
  3089  
  3090  func (_callEvalVariadic) exec(vm *vm) {
  3091  	vm.callEval(vm.countVariadicArgs()-2, false)
  3092  }
  3093  
  3094  type _callEvalVariadicStrict struct{}
  3095  
  3096  var callEvalVariadicStrict _callEvalVariadicStrict
  3097  
  3098  func (_callEvalVariadicStrict) exec(vm *vm) {
  3099  	vm.callEval(vm.countVariadicArgs()-2, true)
  3100  }
  3101  
  3102  type _boxThis struct{}
  3103  
  3104  var boxThis _boxThis
  3105  
  3106  func (_boxThis) exec(vm *vm) {
  3107  	v := vm.stack[vm.sb]
  3108  	if v == _undefined || v == _null {
  3109  		vm.stack[vm.sb] = vm.r.globalObject
  3110  	} else {
  3111  		vm.stack[vm.sb] = v.ToObject(vm.r)
  3112  	}
  3113  	vm.pc++
  3114  }
  3115  
  3116  var variadicMarker Value = newSymbol(asciiString("[variadic marker]"))
  3117  
  3118  type _startVariadic struct{}
  3119  
  3120  var startVariadic _startVariadic
  3121  
  3122  func (_startVariadic) exec(vm *vm) {
  3123  	vm.push(variadicMarker)
  3124  	vm.pc++
  3125  }
  3126  
  3127  type _callVariadic struct{}
  3128  
  3129  var callVariadic _callVariadic
  3130  
  3131  func (vm *vm) countVariadicArgs() int {
  3132  	count := 0
  3133  	for i := vm.sp - 1; i >= 0; i-- {
  3134  		if vm.stack[i] == variadicMarker {
  3135  			return count
  3136  		}
  3137  		count++
  3138  	}
  3139  	panic("Variadic marker was not found. Compiler bug.")
  3140  }
  3141  
  3142  func (_callVariadic) exec(vm *vm) {
  3143  	call(vm.countVariadicArgs() - 2).exec(vm)
  3144  }
  3145  
  3146  type _endVariadic struct{}
  3147  
  3148  var endVariadic _endVariadic
  3149  
  3150  func (_endVariadic) exec(vm *vm) {
  3151  	vm.sp--
  3152  	vm.stack[vm.sp-1] = vm.stack[vm.sp]
  3153  	vm.pc++
  3154  }
  3155  
  3156  type call uint32
  3157  
  3158  func (numargs call) exec(vm *vm) {
  3159  	// this
  3160  	// callee
  3161  	// arg0
  3162  	// ...
  3163  	// arg<numargs-1>
  3164  	n := int(numargs)
  3165  	v := vm.stack[vm.sp-n-1] // callee
  3166  	obj := vm.toCallee(v)
  3167  repeat:
  3168  	switch f := obj.self.(type) {
  3169  	case *classFuncObject:
  3170  		f.Call(FunctionCall{}) // throws
  3171  	case *methodFuncObject:
  3172  		vm.pc++
  3173  		vm.pushCtx()
  3174  		vm.args = n
  3175  		vm.prg = f.prg
  3176  		vm.stash = f.stash
  3177  		vm.privEnv = f.privEnv
  3178  		vm.pc = 0
  3179  		vm.stack[vm.sp-n-1], vm.stack[vm.sp-n-2] = vm.stack[vm.sp-n-2], vm.stack[vm.sp-n-1]
  3180  		return
  3181  	case *funcObject:
  3182  		vm.pc++
  3183  		vm.pushCtx()
  3184  		vm.args = n
  3185  		vm.prg = f.prg
  3186  		vm.stash = f.stash
  3187  		vm.privEnv = f.privEnv
  3188  		vm.pc = 0
  3189  		vm.stack[vm.sp-n-1], vm.stack[vm.sp-n-2] = vm.stack[vm.sp-n-2], vm.stack[vm.sp-n-1]
  3190  		return
  3191  	case *arrowFuncObject:
  3192  		vm.pc++
  3193  		vm.pushCtx()
  3194  		vm.args = n
  3195  		vm.prg = f.prg
  3196  		vm.stash = f.stash
  3197  		vm.privEnv = f.privEnv
  3198  		vm.pc = 0
  3199  		vm.stack[vm.sp-n-1], vm.stack[vm.sp-n-2] = nil, vm.stack[vm.sp-n-1]
  3200  		vm.newTarget = f.newTarget
  3201  		return
  3202  	case *nativeFuncObject:
  3203  		vm._nativeCall(f, n)
  3204  	case *boundFuncObject:
  3205  		vm._nativeCall(&f.nativeFuncObject, n)
  3206  	case *proxyObject:
  3207  		vm.pushCtx()
  3208  		vm.prg = nil
  3209  		vm.funcName = "proxy"
  3210  		ret := f.apply(FunctionCall{This: vm.stack[vm.sp-n-2], Arguments: vm.stack[vm.sp-n : vm.sp]})
  3211  		if ret == nil {
  3212  			ret = _undefined
  3213  		}
  3214  		vm.stack[vm.sp-n-2] = ret
  3215  		vm.popCtx()
  3216  		vm.sp -= n + 1
  3217  		vm.pc++
  3218  	case *lazyObject:
  3219  		obj.self = f.create(obj)
  3220  		goto repeat
  3221  	default:
  3222  		vm.r.typeErrorResult(true, "Not a function: %s", obj.toString())
  3223  	}
  3224  }
  3225  
  3226  func (vm *vm) _nativeCall(f *nativeFuncObject, n int) {
  3227  	if f.f != nil {
  3228  		vm.pushCtx()
  3229  		vm.prg = nil
  3230  		vm.funcName = nilSafe(f.getStr("name", nil)).string()
  3231  		ret := f.f(FunctionCall{
  3232  			Arguments: vm.stack[vm.sp-n : vm.sp],
  3233  			This:      vm.stack[vm.sp-n-2],
  3234  		})
  3235  		if ret == nil {
  3236  			ret = _undefined
  3237  		}
  3238  		vm.stack[vm.sp-n-2] = ret
  3239  		vm.popCtx()
  3240  	} else {
  3241  		vm.stack[vm.sp-n-2] = _undefined
  3242  	}
  3243  	vm.sp -= n + 1
  3244  	vm.pc++
  3245  }
  3246  
  3247  func (vm *vm) clearStack() {
  3248  	sp := vm.sp
  3249  	stackTail := vm.stack[sp:]
  3250  	for i := range stackTail {
  3251  		stackTail[i] = nil
  3252  	}
  3253  	vm.stack = vm.stack[:sp]
  3254  }
  3255  
  3256  type enterBlock struct {
  3257  	names     map[unistring.String]uint32
  3258  	stashSize uint32
  3259  	stackSize uint32
  3260  }
  3261  
  3262  func (e *enterBlock) exec(vm *vm) {
  3263  	if e.stashSize > 0 {
  3264  		vm.newStash()
  3265  		vm.stash.values = make([]Value, e.stashSize)
  3266  		if len(e.names) > 0 {
  3267  			vm.stash.names = e.names
  3268  		}
  3269  	}
  3270  	ss := int(e.stackSize)
  3271  	vm.stack.expand(vm.sp + ss - 1)
  3272  	vv := vm.stack[vm.sp : vm.sp+ss]
  3273  	for i := range vv {
  3274  		vv[i] = nil
  3275  	}
  3276  	vm.sp += ss
  3277  	vm.pc++
  3278  }
  3279  
  3280  type enterCatchBlock struct {
  3281  	names     map[unistring.String]uint32
  3282  	stashSize uint32
  3283  	stackSize uint32
  3284  }
  3285  
  3286  func (e *enterCatchBlock) exec(vm *vm) {
  3287  	vm.newStash()
  3288  	vm.stash.values = make([]Value, e.stashSize)
  3289  	if len(e.names) > 0 {
  3290  		vm.stash.names = e.names
  3291  	}
  3292  	vm.sp--
  3293  	vm.stash.values[0] = vm.stack[vm.sp]
  3294  	ss := int(e.stackSize)
  3295  	vm.stack.expand(vm.sp + ss - 1)
  3296  	vv := vm.stack[vm.sp : vm.sp+ss]
  3297  	for i := range vv {
  3298  		vv[i] = nil
  3299  	}
  3300  	vm.sp += ss
  3301  	vm.pc++
  3302  }
  3303  
  3304  type leaveBlock struct {
  3305  	stackSize uint32
  3306  	popStash  bool
  3307  }
  3308  
  3309  func (l *leaveBlock) exec(vm *vm) {
  3310  	if l.popStash {
  3311  		vm.stash = vm.stash.outer
  3312  	}
  3313  	if ss := l.stackSize; ss > 0 {
  3314  		vm.sp -= int(ss)
  3315  	}
  3316  	vm.pc++
  3317  }
  3318  
  3319  type enterFunc struct {
  3320  	names       map[unistring.String]uint32
  3321  	stashSize   uint32
  3322  	stackSize   uint32
  3323  	numArgs     uint32
  3324  	funcType    funcType
  3325  	argsToStash bool
  3326  	extensible  bool
  3327  }
  3328  
  3329  func (e *enterFunc) exec(vm *vm) {
  3330  	// Input stack:
  3331  	//
  3332  	// callee
  3333  	// this
  3334  	// arg0
  3335  	// ...
  3336  	// argN
  3337  	// <- sp
  3338  
  3339  	// Output stack:
  3340  	//
  3341  	// this <- sb
  3342  	// <local stack vars...>
  3343  	// <- sp
  3344  	sp := vm.sp
  3345  	vm.sb = sp - vm.args - 1
  3346  	vm.newStash()
  3347  	stash := vm.stash
  3348  	stash.funcType = e.funcType
  3349  	stash.values = make([]Value, e.stashSize)
  3350  	if len(e.names) > 0 {
  3351  		if e.extensible {
  3352  			m := make(map[unistring.String]uint32, len(e.names))
  3353  			for name, idx := range e.names {
  3354  				m[name] = idx
  3355  			}
  3356  			stash.names = m
  3357  		} else {
  3358  			stash.names = e.names
  3359  		}
  3360  	}
  3361  
  3362  	ss := int(e.stackSize)
  3363  	ea := 0
  3364  	if e.argsToStash {
  3365  		offset := vm.args - int(e.numArgs)
  3366  		copy(stash.values, vm.stack[sp-vm.args:sp])
  3367  		if offset > 0 {
  3368  			vm.stash.extraArgs = make([]Value, offset)
  3369  			copy(stash.extraArgs, vm.stack[sp-offset:])
  3370  		} else {
  3371  			vv := stash.values[vm.args:e.numArgs]
  3372  			for i := range vv {
  3373  				vv[i] = _undefined
  3374  			}
  3375  		}
  3376  		sp -= vm.args
  3377  	} else {
  3378  		d := int(e.numArgs) - vm.args
  3379  		if d > 0 {
  3380  			ss += d
  3381  			ea = d
  3382  			vm.args = int(e.numArgs)
  3383  		}
  3384  	}
  3385  	vm.stack.expand(sp + ss - 1)
  3386  	if ea > 0 {
  3387  		vv := vm.stack[sp : vm.sp+ea]
  3388  		for i := range vv {
  3389  			vv[i] = _undefined
  3390  		}
  3391  	}
  3392  	vv := vm.stack[sp+ea : sp+ss]
  3393  	for i := range vv {
  3394  		vv[i] = nil
  3395  	}
  3396  	vm.sp = sp + ss
  3397  	vm.pc++
  3398  }
  3399  
  3400  // Similar to enterFunc, but for when arguments may be accessed before they are initialised,
  3401  // e.g. by an eval() code or from a closure, or from an earlier initialiser code.
  3402  // In this case the arguments remain on stack, first argsToCopy of them are copied to the stash.
  3403  type enterFunc1 struct {
  3404  	names      map[unistring.String]uint32
  3405  	stashSize  uint32
  3406  	numArgs    uint32
  3407  	argsToCopy uint32
  3408  	funcType   funcType
  3409  	extensible bool
  3410  }
  3411  
  3412  func (e *enterFunc1) exec(vm *vm) {
  3413  	sp := vm.sp
  3414  	vm.sb = sp - vm.args - 1
  3415  	vm.newStash()
  3416  	stash := vm.stash
  3417  	stash.funcType = e.funcType
  3418  	stash.values = make([]Value, e.stashSize)
  3419  	if len(e.names) > 0 {
  3420  		if e.extensible {
  3421  			m := make(map[unistring.String]uint32, len(e.names))
  3422  			for name, idx := range e.names {
  3423  				m[name] = idx
  3424  			}
  3425  			stash.names = m
  3426  		} else {
  3427  			stash.names = e.names
  3428  		}
  3429  	}
  3430  	offset := vm.args - int(e.argsToCopy)
  3431  	if offset > 0 {
  3432  		copy(stash.values, vm.stack[sp-vm.args:sp-offset])
  3433  		if offset := vm.args - int(e.numArgs); offset > 0 {
  3434  			vm.stash.extraArgs = make([]Value, offset)
  3435  			copy(stash.extraArgs, vm.stack[sp-offset:])
  3436  		}
  3437  	} else {
  3438  		copy(stash.values, vm.stack[sp-vm.args:sp])
  3439  		if int(e.argsToCopy) > vm.args {
  3440  			vv := stash.values[vm.args:e.argsToCopy]
  3441  			for i := range vv {
  3442  				vv[i] = _undefined
  3443  			}
  3444  		}
  3445  	}
  3446  
  3447  	vm.pc++
  3448  }
  3449  
  3450  // Finalises the initialisers section and starts the function body which has its own
  3451  // scope. When used in conjunction with enterFunc1 adjustStack is set to true which
  3452  // causes the arguments to be removed from the stack.
  3453  type enterFuncBody struct {
  3454  	enterBlock
  3455  	funcType    funcType
  3456  	extensible  bool
  3457  	adjustStack bool
  3458  }
  3459  
  3460  func (e *enterFuncBody) exec(vm *vm) {
  3461  	if e.stashSize > 0 || e.extensible {
  3462  		vm.newStash()
  3463  		stash := vm.stash
  3464  		stash.funcType = e.funcType
  3465  		stash.values = make([]Value, e.stashSize)
  3466  		if len(e.names) > 0 {
  3467  			if e.extensible {
  3468  				m := make(map[unistring.String]uint32, len(e.names))
  3469  				for name, idx := range e.names {
  3470  					m[name] = idx
  3471  				}
  3472  				stash.names = m
  3473  			} else {
  3474  				stash.names = e.names
  3475  			}
  3476  		}
  3477  	}
  3478  	sp := vm.sp
  3479  	if e.adjustStack {
  3480  		sp -= vm.args
  3481  	}
  3482  	nsp := sp + int(e.stackSize)
  3483  	if e.stackSize > 0 {
  3484  		vm.stack.expand(nsp - 1)
  3485  		vv := vm.stack[sp:nsp]
  3486  		for i := range vv {
  3487  			vv[i] = nil
  3488  		}
  3489  	}
  3490  	vm.sp = nsp
  3491  	vm.pc++
  3492  }
  3493  
  3494  type _ret struct{}
  3495  
  3496  var ret _ret
  3497  
  3498  func (_ret) exec(vm *vm) {
  3499  	// callee -3
  3500  	// this -2 <- sb
  3501  	// retval -1
  3502  
  3503  	vm.stack[vm.sb-1] = vm.stack[vm.sp-1]
  3504  	vm.sp = vm.sb
  3505  	vm.popCtx()
  3506  	if vm.pc < 0 {
  3507  		vm.halt = true
  3508  	}
  3509  }
  3510  
  3511  type cret uint32
  3512  
  3513  func (c cret) exec(vm *vm) {
  3514  	vm.stack[vm.sb] = *vm.getStashPtr(uint32(c))
  3515  	ret.exec(vm)
  3516  }
  3517  
  3518  type enterFuncStashless struct {
  3519  	stackSize uint32
  3520  	args      uint32
  3521  }
  3522  
  3523  func (e *enterFuncStashless) exec(vm *vm) {
  3524  	sp := vm.sp
  3525  	vm.sb = sp - vm.args - 1
  3526  	d := int(e.args) - vm.args
  3527  	if d > 0 {
  3528  		ss := sp + int(e.stackSize) + d
  3529  		vm.stack.expand(ss)
  3530  		vv := vm.stack[sp : sp+d]
  3531  		for i := range vv {
  3532  			vv[i] = _undefined
  3533  		}
  3534  		vv = vm.stack[sp+d : ss]
  3535  		for i := range vv {
  3536  			vv[i] = nil
  3537  		}
  3538  		vm.args = int(e.args)
  3539  		vm.sp = ss
  3540  	} else {
  3541  		if e.stackSize > 0 {
  3542  			ss := sp + int(e.stackSize)
  3543  			vm.stack.expand(ss)
  3544  			vv := vm.stack[sp:ss]
  3545  			for i := range vv {
  3546  				vv[i] = nil
  3547  			}
  3548  			vm.sp = ss
  3549  		}
  3550  	}
  3551  	vm.pc++
  3552  }
  3553  
  3554  type newFunc struct {
  3555  	prg    *Program
  3556  	name   unistring.String
  3557  	source string
  3558  
  3559  	length int
  3560  	strict bool
  3561  }
  3562  
  3563  func (n *newFunc) exec(vm *vm) {
  3564  	obj := vm.r.newFunc(n.name, n.length, n.strict)
  3565  	obj.prg = n.prg
  3566  	obj.stash = vm.stash
  3567  	obj.privEnv = vm.privEnv
  3568  	obj.src = n.source
  3569  	vm.push(obj.val)
  3570  	vm.pc++
  3571  }
  3572  
  3573  type newMethod struct {
  3574  	newFunc
  3575  	homeObjOffset uint32
  3576  }
  3577  
  3578  func (n *newMethod) exec(vm *vm) {
  3579  	obj := vm.r.newMethod(n.name, n.length, n.strict)
  3580  	obj.prg = n.prg
  3581  	obj.stash = vm.stash
  3582  	obj.privEnv = vm.privEnv
  3583  	obj.src = n.source
  3584  	if n.homeObjOffset > 0 {
  3585  		obj.homeObject = vm.r.toObject(vm.stack[vm.sp-int(n.homeObjOffset)])
  3586  	}
  3587  	vm.push(obj.val)
  3588  	vm.pc++
  3589  }
  3590  
  3591  type newArrowFunc struct {
  3592  	newFunc
  3593  }
  3594  
  3595  func getFuncObject(v Value) *Object {
  3596  	if o, ok := v.(*Object); ok {
  3597  		if fn, ok := o.self.(*arrowFuncObject); ok {
  3598  			return fn.funcObj
  3599  		}
  3600  		return o
  3601  	}
  3602  	if v == _undefined {
  3603  		return nil
  3604  	}
  3605  	panic(typeError("Value is not an Object"))
  3606  }
  3607  
  3608  func getHomeObject(v Value) *Object {
  3609  	if o, ok := v.(*Object); ok {
  3610  		switch fn := o.self.(type) {
  3611  		case *methodFuncObject:
  3612  			return fn.homeObject
  3613  		case *classFuncObject:
  3614  			return o.runtime.toObject(fn.getStr("prototype", nil))
  3615  		case *arrowFuncObject:
  3616  			return getHomeObject(fn.funcObj)
  3617  		}
  3618  	}
  3619  	panic(newTypeError("Compiler bug: getHomeObject() on the wrong value: %T", v))
  3620  }
  3621  
  3622  func (n *newArrowFunc) exec(vm *vm) {
  3623  	obj := vm.r.newArrowFunc(n.name, n.length, n.strict)
  3624  	obj.prg = n.prg
  3625  	obj.stash = vm.stash
  3626  	obj.privEnv = vm.privEnv
  3627  	obj.src = n.source
  3628  	if vm.sb > 0 {
  3629  		obj.funcObj = getFuncObject(vm.stack[vm.sb-1])
  3630  	}
  3631  	vm.push(obj.val)
  3632  	vm.pc++
  3633  }
  3634  
  3635  func (vm *vm) alreadyDeclared(name unistring.String) Value {
  3636  	return vm.r.newError(vm.r.global.SyntaxError, "Identifier '%s' has already been declared", name)
  3637  }
  3638  
  3639  func (vm *vm) checkBindVarsGlobal(names []unistring.String) {
  3640  	o := vm.r.globalObject.self
  3641  	sn := vm.r.global.stash.names
  3642  	if bo, ok := o.(*baseObject); ok {
  3643  		// shortcut
  3644  		if bo.extensible {
  3645  			for _, name := range names {
  3646  				if _, exists := sn[name]; exists {
  3647  					panic(vm.alreadyDeclared(name))
  3648  				}
  3649  			}
  3650  		} else {
  3651  			for _, name := range names {
  3652  				if !bo.hasOwnPropertyStr(name) {
  3653  					panic(vm.r.NewTypeError("Cannot define global variable '%s', global object is not extensible", name))
  3654  				}
  3655  				if _, exists := sn[name]; exists {
  3656  					panic(vm.alreadyDeclared(name))
  3657  				}
  3658  			}
  3659  		}
  3660  	} else {
  3661  		for _, name := range names {
  3662  			if !o.hasOwnPropertyStr(name) && !o.isExtensible() {
  3663  				panic(vm.r.NewTypeError("Cannot define global variable '%s', global object is not extensible", name))
  3664  			}
  3665  			if _, exists := sn[name]; exists {
  3666  				panic(vm.alreadyDeclared(name))
  3667  			}
  3668  		}
  3669  	}
  3670  }
  3671  
  3672  func (vm *vm) createGlobalVarBindings(names []unistring.String, d bool) {
  3673  	globalVarNames := vm.r.global.varNames
  3674  	if globalVarNames == nil {
  3675  		globalVarNames = make(map[unistring.String]struct{})
  3676  		vm.r.global.varNames = globalVarNames
  3677  	}
  3678  	o := vm.r.globalObject.self
  3679  	if bo, ok := o.(*baseObject); ok {
  3680  		for _, name := range names {
  3681  			if !bo.hasOwnPropertyStr(name) && bo.extensible {
  3682  				bo._putProp(name, _undefined, true, true, d)
  3683  			}
  3684  			globalVarNames[name] = struct{}{}
  3685  		}
  3686  	} else {
  3687  		var cf Flag
  3688  		if d {
  3689  			cf = FLAG_TRUE
  3690  		} else {
  3691  			cf = FLAG_FALSE
  3692  		}
  3693  		for _, name := range names {
  3694  			if !o.hasOwnPropertyStr(name) && o.isExtensible() {
  3695  				o.defineOwnPropertyStr(name, PropertyDescriptor{
  3696  					Value:        _undefined,
  3697  					Writable:     FLAG_TRUE,
  3698  					Enumerable:   FLAG_TRUE,
  3699  					Configurable: cf,
  3700  				}, true)
  3701  				o.setOwnStr(name, _undefined, false)
  3702  			}
  3703  			globalVarNames[name] = struct{}{}
  3704  		}
  3705  	}
  3706  }
  3707  
  3708  func (vm *vm) createGlobalFuncBindings(names []unistring.String, d bool) {
  3709  	globalVarNames := vm.r.global.varNames
  3710  	if globalVarNames == nil {
  3711  		globalVarNames = make(map[unistring.String]struct{})
  3712  		vm.r.global.varNames = globalVarNames
  3713  	}
  3714  	o := vm.r.globalObject.self
  3715  	b := vm.sp - len(names)
  3716  	var shortcutObj *baseObject
  3717  	if o, ok := o.(*baseObject); ok {
  3718  		shortcutObj = o
  3719  	}
  3720  	for i, name := range names {
  3721  		var desc PropertyDescriptor
  3722  		prop := o.getOwnPropStr(name)
  3723  		desc.Value = vm.stack[b+i]
  3724  		if shortcutObj != nil && prop == nil && shortcutObj.extensible {
  3725  			shortcutObj._putProp(name, desc.Value, true, true, d)
  3726  		} else {
  3727  			if prop, ok := prop.(*valueProperty); ok && !prop.configurable {
  3728  				// no-op
  3729  			} else {
  3730  				desc.Writable = FLAG_TRUE
  3731  				desc.Enumerable = FLAG_TRUE
  3732  				if d {
  3733  					desc.Configurable = FLAG_TRUE
  3734  				} else {
  3735  					desc.Configurable = FLAG_FALSE
  3736  				}
  3737  			}
  3738  			if shortcutObj != nil {
  3739  				shortcutObj.defineOwnPropertyStr(name, desc, true)
  3740  			} else {
  3741  				o.defineOwnPropertyStr(name, desc, true)
  3742  				o.setOwnStr(name, desc.Value, false) // not a bug, see https://262.ecma-international.org/#sec-createglobalfunctionbinding
  3743  			}
  3744  		}
  3745  		globalVarNames[name] = struct{}{}
  3746  	}
  3747  	vm.sp = b
  3748  }
  3749  
  3750  func (vm *vm) checkBindFuncsGlobal(names []unistring.String) {
  3751  	o := vm.r.globalObject.self
  3752  	sn := vm.r.global.stash.names
  3753  	for _, name := range names {
  3754  		if _, exists := sn[name]; exists {
  3755  			panic(vm.alreadyDeclared(name))
  3756  		}
  3757  		prop := o.getOwnPropStr(name)
  3758  		allowed := true
  3759  		switch prop := prop.(type) {
  3760  		case nil:
  3761  			allowed = o.isExtensible()
  3762  		case *valueProperty:
  3763  			allowed = prop.configurable || prop.getterFunc == nil && prop.setterFunc == nil && prop.writable && prop.enumerable
  3764  		}
  3765  		if !allowed {
  3766  			panic(vm.r.NewTypeError("Cannot redefine global function '%s'", name))
  3767  		}
  3768  	}
  3769  }
  3770  
  3771  func (vm *vm) checkBindLexGlobal(names []unistring.String) {
  3772  	o := vm.r.globalObject.self
  3773  	s := &vm.r.global.stash
  3774  	for _, name := range names {
  3775  		if _, exists := vm.r.global.varNames[name]; exists {
  3776  			goto fail
  3777  		}
  3778  		if _, exists := s.names[name]; exists {
  3779  			goto fail
  3780  		}
  3781  		if prop, ok := o.getOwnPropStr(name).(*valueProperty); ok && !prop.configurable {
  3782  			goto fail
  3783  		}
  3784  		continue
  3785  	fail:
  3786  		panic(vm.alreadyDeclared(name))
  3787  	}
  3788  }
  3789  
  3790  type bindVars struct {
  3791  	names     []unistring.String
  3792  	deletable bool
  3793  }
  3794  
  3795  func (d *bindVars) exec(vm *vm) {
  3796  	var target *stash
  3797  	for _, name := range d.names {
  3798  		for s := vm.stash; s != nil; s = s.outer {
  3799  			if idx, exists := s.names[name]; exists && idx&maskVar == 0 {
  3800  				panic(vm.alreadyDeclared(name))
  3801  			}
  3802  			if s.isVariable() {
  3803  				target = s
  3804  				break
  3805  			}
  3806  		}
  3807  	}
  3808  	if target == nil {
  3809  		target = vm.stash
  3810  	}
  3811  	deletable := d.deletable
  3812  	for _, name := range d.names {
  3813  		target.createBinding(name, deletable)
  3814  	}
  3815  	vm.pc++
  3816  }
  3817  
  3818  type bindGlobal struct {
  3819  	vars, funcs, lets, consts []unistring.String
  3820  
  3821  	deletable bool
  3822  }
  3823  
  3824  func (b *bindGlobal) exec(vm *vm) {
  3825  	vm.checkBindFuncsGlobal(b.funcs)
  3826  	vm.checkBindLexGlobal(b.lets)
  3827  	vm.checkBindLexGlobal(b.consts)
  3828  	vm.checkBindVarsGlobal(b.vars)
  3829  
  3830  	s := &vm.r.global.stash
  3831  	for _, name := range b.lets {
  3832  		s.createLexBinding(name, false)
  3833  	}
  3834  	for _, name := range b.consts {
  3835  		s.createLexBinding(name, true)
  3836  	}
  3837  	vm.createGlobalFuncBindings(b.funcs, b.deletable)
  3838  	vm.createGlobalVarBindings(b.vars, b.deletable)
  3839  	vm.pc++
  3840  }
  3841  
  3842  type jne int32
  3843  
  3844  func (j jne) exec(vm *vm) {
  3845  	vm.sp--
  3846  	if !vm.stack[vm.sp].ToBoolean() {
  3847  		vm.pc += int(j)
  3848  	} else {
  3849  		vm.pc++
  3850  	}
  3851  }
  3852  
  3853  type jeq int32
  3854  
  3855  func (j jeq) exec(vm *vm) {
  3856  	vm.sp--
  3857  	if vm.stack[vm.sp].ToBoolean() {
  3858  		vm.pc += int(j)
  3859  	} else {
  3860  		vm.pc++
  3861  	}
  3862  }
  3863  
  3864  type jeq1 int32
  3865  
  3866  func (j jeq1) exec(vm *vm) {
  3867  	if vm.stack[vm.sp-1].ToBoolean() {
  3868  		vm.pc += int(j)
  3869  	} else {
  3870  		vm.sp--
  3871  		vm.pc++
  3872  	}
  3873  }
  3874  
  3875  type jneq1 int32
  3876  
  3877  func (j jneq1) exec(vm *vm) {
  3878  	if !vm.stack[vm.sp-1].ToBoolean() {
  3879  		vm.pc += int(j)
  3880  	} else {
  3881  		vm.sp--
  3882  		vm.pc++
  3883  	}
  3884  }
  3885  
  3886  type jdef int32
  3887  
  3888  func (j jdef) exec(vm *vm) {
  3889  	if vm.stack[vm.sp-1] != _undefined {
  3890  		vm.pc += int(j)
  3891  	} else {
  3892  		vm.sp--
  3893  		vm.pc++
  3894  	}
  3895  }
  3896  
  3897  type jdefP int32
  3898  
  3899  func (j jdefP) exec(vm *vm) {
  3900  	if vm.stack[vm.sp-1] != _undefined {
  3901  		vm.pc += int(j)
  3902  	} else {
  3903  		vm.pc++
  3904  	}
  3905  	vm.sp--
  3906  }
  3907  
  3908  type jopt int32
  3909  
  3910  func (j jopt) exec(vm *vm) {
  3911  	switch vm.stack[vm.sp-1] {
  3912  	case _null:
  3913  		vm.stack[vm.sp-1] = _undefined
  3914  		fallthrough
  3915  	case _undefined:
  3916  		vm.pc += int(j)
  3917  	default:
  3918  		vm.pc++
  3919  	}
  3920  }
  3921  
  3922  type joptc int32
  3923  
  3924  func (j joptc) exec(vm *vm) {
  3925  	switch vm.stack[vm.sp-1].(type) {
  3926  	case valueNull, valueUndefined, memberUnresolved:
  3927  		vm.sp--
  3928  		vm.stack[vm.sp-1] = _undefined
  3929  		vm.pc += int(j)
  3930  	default:
  3931  		vm.pc++
  3932  	}
  3933  }
  3934  
  3935  type jcoalesc int32
  3936  
  3937  func (j jcoalesc) exec(vm *vm) {
  3938  	switch vm.stack[vm.sp-1] {
  3939  	case _undefined, _null:
  3940  		vm.sp--
  3941  		vm.pc++
  3942  	default:
  3943  		vm.pc += int(j)
  3944  	}
  3945  }
  3946  
  3947  type _not struct{}
  3948  
  3949  var not _not
  3950  
  3951  func (_not) exec(vm *vm) {
  3952  	if vm.stack[vm.sp-1].ToBoolean() {
  3953  		vm.stack[vm.sp-1] = valueFalse
  3954  	} else {
  3955  		vm.stack[vm.sp-1] = valueTrue
  3956  	}
  3957  	vm.pc++
  3958  }
  3959  
  3960  func toPrimitiveNumber(v Value) Value {
  3961  	if o, ok := v.(*Object); ok {
  3962  		return o.toPrimitiveNumber()
  3963  	}
  3964  	return v
  3965  }
  3966  
  3967  func toPrimitive(v Value) Value {
  3968  	if o, ok := v.(*Object); ok {
  3969  		return o.toPrimitive()
  3970  	}
  3971  	return v
  3972  }
  3973  
  3974  func cmp(px, py Value) Value {
  3975  	var ret bool
  3976  	var nx, ny float64
  3977  
  3978  	if xs, ok := px.(valueString); ok {
  3979  		if ys, ok := py.(valueString); ok {
  3980  			ret = xs.compareTo(ys) < 0
  3981  			goto end
  3982  		}
  3983  	}
  3984  
  3985  	if xi, ok := px.(valueInt); ok {
  3986  		if yi, ok := py.(valueInt); ok {
  3987  			ret = xi < yi
  3988  			goto end
  3989  		}
  3990  	}
  3991  
  3992  	nx = px.ToFloat()
  3993  	ny = py.ToFloat()
  3994  
  3995  	if math.IsNaN(nx) || math.IsNaN(ny) {
  3996  		return _undefined
  3997  	}
  3998  
  3999  	ret = nx < ny
  4000  
  4001  end:
  4002  	if ret {
  4003  		return valueTrue
  4004  	}
  4005  	return valueFalse
  4006  
  4007  }
  4008  
  4009  type _op_lt struct{}
  4010  
  4011  var op_lt _op_lt
  4012  
  4013  func (_op_lt) exec(vm *vm) {
  4014  	left := toPrimitiveNumber(vm.stack[vm.sp-2])
  4015  	right := toPrimitiveNumber(vm.stack[vm.sp-1])
  4016  
  4017  	r := cmp(left, right)
  4018  	if r == _undefined {
  4019  		vm.stack[vm.sp-2] = valueFalse
  4020  	} else {
  4021  		vm.stack[vm.sp-2] = r
  4022  	}
  4023  	vm.sp--
  4024  	vm.pc++
  4025  }
  4026  
  4027  type _op_lte struct{}
  4028  
  4029  var op_lte _op_lte
  4030  
  4031  func (_op_lte) exec(vm *vm) {
  4032  	left := toPrimitiveNumber(vm.stack[vm.sp-2])
  4033  	right := toPrimitiveNumber(vm.stack[vm.sp-1])
  4034  
  4035  	r := cmp(right, left)
  4036  	if r == _undefined || r == valueTrue {
  4037  		vm.stack[vm.sp-2] = valueFalse
  4038  	} else {
  4039  		vm.stack[vm.sp-2] = valueTrue
  4040  	}
  4041  
  4042  	vm.sp--
  4043  	vm.pc++
  4044  }
  4045  
  4046  type _op_gt struct{}
  4047  
  4048  var op_gt _op_gt
  4049  
  4050  func (_op_gt) exec(vm *vm) {
  4051  	left := toPrimitiveNumber(vm.stack[vm.sp-2])
  4052  	right := toPrimitiveNumber(vm.stack[vm.sp-1])
  4053  
  4054  	r := cmp(right, left)
  4055  	if r == _undefined {
  4056  		vm.stack[vm.sp-2] = valueFalse
  4057  	} else {
  4058  		vm.stack[vm.sp-2] = r
  4059  	}
  4060  	vm.sp--
  4061  	vm.pc++
  4062  }
  4063  
  4064  type _op_gte struct{}
  4065  
  4066  var op_gte _op_gte
  4067  
  4068  func (_op_gte) exec(vm *vm) {
  4069  	left := toPrimitiveNumber(vm.stack[vm.sp-2])
  4070  	right := toPrimitiveNumber(vm.stack[vm.sp-1])
  4071  
  4072  	r := cmp(left, right)
  4073  	if r == _undefined || r == valueTrue {
  4074  		vm.stack[vm.sp-2] = valueFalse
  4075  	} else {
  4076  		vm.stack[vm.sp-2] = valueTrue
  4077  	}
  4078  
  4079  	vm.sp--
  4080  	vm.pc++
  4081  }
  4082  
  4083  type _op_eq struct{}
  4084  
  4085  var op_eq _op_eq
  4086  
  4087  func (_op_eq) exec(vm *vm) {
  4088  	if vm.stack[vm.sp-2].Equals(vm.stack[vm.sp-1]) {
  4089  		vm.stack[vm.sp-2] = valueTrue
  4090  	} else {
  4091  		vm.stack[vm.sp-2] = valueFalse
  4092  	}
  4093  	vm.sp--
  4094  	vm.pc++
  4095  }
  4096  
  4097  type _op_neq struct{}
  4098  
  4099  var op_neq _op_neq
  4100  
  4101  func (_op_neq) exec(vm *vm) {
  4102  	if vm.stack[vm.sp-2].Equals(vm.stack[vm.sp-1]) {
  4103  		vm.stack[vm.sp-2] = valueFalse
  4104  	} else {
  4105  		vm.stack[vm.sp-2] = valueTrue
  4106  	}
  4107  	vm.sp--
  4108  	vm.pc++
  4109  }
  4110  
  4111  type _op_strict_eq struct{}
  4112  
  4113  var op_strict_eq _op_strict_eq
  4114  
  4115  func (_op_strict_eq) exec(vm *vm) {
  4116  	if vm.stack[vm.sp-2].StrictEquals(vm.stack[vm.sp-1]) {
  4117  		vm.stack[vm.sp-2] = valueTrue
  4118  	} else {
  4119  		vm.stack[vm.sp-2] = valueFalse
  4120  	}
  4121  	vm.sp--
  4122  	vm.pc++
  4123  }
  4124  
  4125  type _op_strict_neq struct{}
  4126  
  4127  var op_strict_neq _op_strict_neq
  4128  
  4129  func (_op_strict_neq) exec(vm *vm) {
  4130  	if vm.stack[vm.sp-2].StrictEquals(vm.stack[vm.sp-1]) {
  4131  		vm.stack[vm.sp-2] = valueFalse
  4132  	} else {
  4133  		vm.stack[vm.sp-2] = valueTrue
  4134  	}
  4135  	vm.sp--
  4136  	vm.pc++
  4137  }
  4138  
  4139  type _op_instanceof struct{}
  4140  
  4141  var op_instanceof _op_instanceof
  4142  
  4143  func (_op_instanceof) exec(vm *vm) {
  4144  	left := vm.stack[vm.sp-2]
  4145  	right := vm.r.toObject(vm.stack[vm.sp-1])
  4146  
  4147  	if instanceOfOperator(left, right) {
  4148  		vm.stack[vm.sp-2] = valueTrue
  4149  	} else {
  4150  		vm.stack[vm.sp-2] = valueFalse
  4151  	}
  4152  
  4153  	vm.sp--
  4154  	vm.pc++
  4155  }
  4156  
  4157  type _op_in struct{}
  4158  
  4159  var op_in _op_in
  4160  
  4161  func (_op_in) exec(vm *vm) {
  4162  	left := vm.stack[vm.sp-2]
  4163  	right := vm.r.toObject(vm.stack[vm.sp-1])
  4164  
  4165  	if right.hasProperty(left) {
  4166  		vm.stack[vm.sp-2] = valueTrue
  4167  	} else {
  4168  		vm.stack[vm.sp-2] = valueFalse
  4169  	}
  4170  
  4171  	vm.sp--
  4172  	vm.pc++
  4173  }
  4174  
  4175  type try struct {
  4176  	catchOffset   int32
  4177  	finallyOffset int32
  4178  }
  4179  
  4180  func (t try) exec(vm *vm) {
  4181  	o := vm.pc
  4182  	vm.pc++
  4183  	ex := vm.runTry()
  4184  	if ex != nil && t.catchOffset > 0 {
  4185  		// run the catch block (in try)
  4186  		vm.pc = o + int(t.catchOffset)
  4187  		// TODO: if ex.val is an Error, set the stack property
  4188  		vm.push(ex.val)
  4189  		ex = vm.runTry()
  4190  	}
  4191  
  4192  	if t.finallyOffset > 0 {
  4193  		pc := vm.pc
  4194  		// Run finally
  4195  		vm.pc = o + int(t.finallyOffset)
  4196  		vm.run()
  4197  		if vm.prg.code[vm.pc] == retFinally {
  4198  			vm.pc = pc
  4199  		} else {
  4200  			// break or continue out of finally, dropping exception
  4201  			ex = nil
  4202  		}
  4203  	}
  4204  
  4205  	vm.halt = false
  4206  
  4207  	if ex != nil {
  4208  		vm.pc = -1 // to prevent the current position from being captured in the stacktrace
  4209  		panic(ex)
  4210  	}
  4211  }
  4212  
  4213  type _retFinally struct{}
  4214  
  4215  var retFinally _retFinally
  4216  
  4217  func (_retFinally) exec(vm *vm) {
  4218  	vm.pc++
  4219  }
  4220  
  4221  type _throw struct{}
  4222  
  4223  var throw _throw
  4224  
  4225  func (_throw) exec(vm *vm) {
  4226  	v := vm.stack[vm.sp-1]
  4227  	if o, ok := v.(*Object); ok {
  4228  		if e, ok := o.self.(*errorObject); ok {
  4229  			if len(e.stack) > 0 {
  4230  				frame0 := e.stack[0]
  4231  				// If the Error was created immediately before throwing it (i.e. 'throw new Error(....)')
  4232  				// avoid capturing the stack again by the reusing the stack from the Error.
  4233  				// These stacks would be almost identical and the difference doesn't matter for debugging.
  4234  				if frame0.prg == vm.prg && vm.pc-frame0.pc == 1 {
  4235  					panic(&Exception{
  4236  						val:   v,
  4237  						stack: e.stack,
  4238  					})
  4239  				}
  4240  			}
  4241  		}
  4242  	}
  4243  	panic(&Exception{
  4244  		val:   v,
  4245  		stack: vm.captureStack(make([]StackFrame, 0, len(vm.callStack)+1), 0),
  4246  	})
  4247  }
  4248  
  4249  type _newVariadic struct{}
  4250  
  4251  var newVariadic _newVariadic
  4252  
  4253  func (_newVariadic) exec(vm *vm) {
  4254  	_new(vm.countVariadicArgs() - 1).exec(vm)
  4255  }
  4256  
  4257  type _new uint32
  4258  
  4259  func (n _new) exec(vm *vm) {
  4260  	sp := vm.sp - int(n)
  4261  	obj := vm.stack[sp-1]
  4262  	ctor := vm.r.toConstructor(obj)
  4263  	vm.stack[sp-1] = ctor(vm.stack[sp:vm.sp], nil)
  4264  	vm.sp = sp
  4265  	vm.pc++
  4266  }
  4267  
  4268  type superCall uint32
  4269  
  4270  func (s superCall) exec(vm *vm) {
  4271  	l := len(vm.refStack) - 1
  4272  	thisRef := vm.refStack[l]
  4273  	vm.refStack[l] = nil
  4274  	vm.refStack = vm.refStack[:l]
  4275  
  4276  	obj := vm.r.toObject(vm.stack[vm.sb-1])
  4277  	var cls *classFuncObject
  4278  	switch fn := obj.self.(type) {
  4279  	case *classFuncObject:
  4280  		cls = fn
  4281  	case *arrowFuncObject:
  4282  		cls, _ = fn.funcObj.self.(*classFuncObject)
  4283  	}
  4284  	if cls == nil {
  4285  		panic(vm.r.NewTypeError("wrong callee type for super()"))
  4286  	}
  4287  	sp := vm.sp - int(s)
  4288  	newTarget := vm.r.toObject(vm.newTarget)
  4289  	v := cls.createInstance(vm.stack[sp:vm.sp], newTarget)
  4290  	thisRef.set(v)
  4291  	vm.sp = sp
  4292  	cls._initFields(v)
  4293  	vm.push(v)
  4294  	vm.pc++
  4295  }
  4296  
  4297  type _superCallVariadic struct{}
  4298  
  4299  var superCallVariadic _superCallVariadic
  4300  
  4301  func (_superCallVariadic) exec(vm *vm) {
  4302  	superCall(vm.countVariadicArgs()).exec(vm)
  4303  }
  4304  
  4305  type _loadNewTarget struct{}
  4306  
  4307  var loadNewTarget _loadNewTarget
  4308  
  4309  func (_loadNewTarget) exec(vm *vm) {
  4310  	if t := vm.newTarget; t != nil {
  4311  		vm.push(t)
  4312  	} else {
  4313  		vm.push(_undefined)
  4314  	}
  4315  	vm.pc++
  4316  }
  4317  
  4318  type _typeof struct{}
  4319  
  4320  var typeof _typeof
  4321  
  4322  func (_typeof) exec(vm *vm) {
  4323  	var r Value
  4324  	switch v := vm.stack[vm.sp-1].(type) {
  4325  	case valueUndefined, valueUnresolved:
  4326  		r = stringUndefined
  4327  	case valueNull:
  4328  		r = stringObjectC
  4329  	case *Object:
  4330  	repeat:
  4331  		switch s := v.self.(type) {
  4332  		case *classFuncObject, *methodFuncObject, *funcObject, *nativeFuncObject, *boundFuncObject, *arrowFuncObject:
  4333  			r = stringFunction
  4334  		case *proxyObject:
  4335  			if s.call == nil {
  4336  				r = stringObjectC
  4337  			} else {
  4338  				r = stringFunction
  4339  			}
  4340  		case *lazyObject:
  4341  			v.self = s.create(v)
  4342  			goto repeat
  4343  		default:
  4344  			r = stringObjectC
  4345  		}
  4346  	case valueBool:
  4347  		r = stringBoolean
  4348  	case valueString:
  4349  		r = stringString
  4350  	case valueInt, valueFloat:
  4351  		r = stringNumber
  4352  	case *Symbol:
  4353  		r = stringSymbol
  4354  	default:
  4355  		panic(newTypeError("Compiler bug: unknown type: %T", v))
  4356  	}
  4357  	vm.stack[vm.sp-1] = r
  4358  	vm.pc++
  4359  }
  4360  
  4361  type createArgsMapped uint32
  4362  
  4363  func (formalArgs createArgsMapped) exec(vm *vm) {
  4364  	v := &Object{runtime: vm.r}
  4365  	args := &argumentsObject{}
  4366  	args.extensible = true
  4367  	args.prototype = vm.r.global.ObjectPrototype
  4368  	args.class = "Arguments"
  4369  	v.self = args
  4370  	args.val = v
  4371  	args.length = vm.args
  4372  	args.init()
  4373  	i := 0
  4374  	c := int(formalArgs)
  4375  	if vm.args < c {
  4376  		c = vm.args
  4377  	}
  4378  	for ; i < c; i++ {
  4379  		args._put(unistring.String(strconv.Itoa(i)), &mappedProperty{
  4380  			valueProperty: valueProperty{
  4381  				writable:     true,
  4382  				configurable: true,
  4383  				enumerable:   true,
  4384  			},
  4385  			v: &vm.stash.values[i],
  4386  		})
  4387  	}
  4388  
  4389  	for _, v := range vm.stash.extraArgs {
  4390  		args._put(unistring.String(strconv.Itoa(i)), v)
  4391  		i++
  4392  	}
  4393  
  4394  	args._putProp("callee", vm.stack[vm.sb-1], true, false, true)
  4395  	args._putSym(SymIterator, valueProp(vm.r.global.arrayValues, true, false, true))
  4396  	vm.push(v)
  4397  	vm.pc++
  4398  }
  4399  
  4400  type createArgsUnmapped uint32
  4401  
  4402  func (formalArgs createArgsUnmapped) exec(vm *vm) {
  4403  	args := vm.r.newBaseObject(vm.r.global.ObjectPrototype, "Arguments")
  4404  	i := 0
  4405  	c := int(formalArgs)
  4406  	if vm.args < c {
  4407  		c = vm.args
  4408  	}
  4409  	for _, v := range vm.stash.values[:c] {
  4410  		args._put(unistring.String(strconv.Itoa(i)), v)
  4411  		i++
  4412  	}
  4413  
  4414  	for _, v := range vm.stash.extraArgs {
  4415  		args._put(unistring.String(strconv.Itoa(i)), v)
  4416  		i++
  4417  	}
  4418  
  4419  	args._putProp("length", intToValue(int64(vm.args)), true, false, true)
  4420  	args._put("callee", vm.r.global.throwerProperty)
  4421  	args._putSym(SymIterator, valueProp(vm.r.global.arrayValues, true, false, true))
  4422  	vm.push(args.val)
  4423  	vm.pc++
  4424  }
  4425  
  4426  type _enterWith struct{}
  4427  
  4428  var enterWith _enterWith
  4429  
  4430  func (_enterWith) exec(vm *vm) {
  4431  	vm.newStash()
  4432  	vm.stash.obj = vm.stack[vm.sp-1].ToObject(vm.r)
  4433  	vm.sp--
  4434  	vm.pc++
  4435  }
  4436  
  4437  type _leaveWith struct{}
  4438  
  4439  var leaveWith _leaveWith
  4440  
  4441  func (_leaveWith) exec(vm *vm) {
  4442  	vm.stash = vm.stash.outer
  4443  	vm.pc++
  4444  }
  4445  
  4446  func emptyIter() (propIterItem, iterNextFunc) {
  4447  	return propIterItem{}, nil
  4448  }
  4449  
  4450  type _enumerate struct{}
  4451  
  4452  var enumerate _enumerate
  4453  
  4454  func (_enumerate) exec(vm *vm) {
  4455  	v := vm.stack[vm.sp-1]
  4456  	if v == _undefined || v == _null {
  4457  		vm.iterStack = append(vm.iterStack, iterStackItem{f: emptyIter})
  4458  	} else {
  4459  		vm.iterStack = append(vm.iterStack, iterStackItem{f: enumerateRecursive(v.ToObject(vm.r))})
  4460  	}
  4461  	vm.sp--
  4462  	vm.pc++
  4463  }
  4464  
  4465  type enumNext int32
  4466  
  4467  func (jmp enumNext) exec(vm *vm) {
  4468  	l := len(vm.iterStack) - 1
  4469  	item, n := vm.iterStack[l].f()
  4470  	if n != nil {
  4471  		vm.iterStack[l].val = item.name
  4472  		vm.iterStack[l].f = n
  4473  		vm.pc++
  4474  	} else {
  4475  		vm.pc += int(jmp)
  4476  	}
  4477  }
  4478  
  4479  type _enumGet struct{}
  4480  
  4481  var enumGet _enumGet
  4482  
  4483  func (_enumGet) exec(vm *vm) {
  4484  	l := len(vm.iterStack) - 1
  4485  	vm.push(vm.iterStack[l].val)
  4486  	vm.pc++
  4487  }
  4488  
  4489  type _enumPop struct{}
  4490  
  4491  var enumPop _enumPop
  4492  
  4493  func (_enumPop) exec(vm *vm) {
  4494  	l := len(vm.iterStack) - 1
  4495  	vm.iterStack[l] = iterStackItem{}
  4496  	vm.iterStack = vm.iterStack[:l]
  4497  	vm.pc++
  4498  }
  4499  
  4500  type _enumPopClose struct{}
  4501  
  4502  var enumPopClose _enumPopClose
  4503  
  4504  func (_enumPopClose) exec(vm *vm) {
  4505  	l := len(vm.iterStack) - 1
  4506  	item := vm.iterStack[l]
  4507  	vm.iterStack[l] = iterStackItem{}
  4508  	vm.iterStack = vm.iterStack[:l]
  4509  	if iter := item.iter; iter != nil {
  4510  		iter.returnIter()
  4511  	}
  4512  	vm.pc++
  4513  }
  4514  
  4515  type _iterateP struct{}
  4516  
  4517  var iterateP _iterateP
  4518  
  4519  func (_iterateP) exec(vm *vm) {
  4520  	iter := vm.r.getIterator(vm.stack[vm.sp-1], nil)
  4521  	vm.iterStack = append(vm.iterStack, iterStackItem{iter: iter})
  4522  	vm.sp--
  4523  	vm.pc++
  4524  }
  4525  
  4526  type _iterate struct{}
  4527  
  4528  var iterate _iterate
  4529  
  4530  func (_iterate) exec(vm *vm) {
  4531  	iter := vm.r.getIterator(vm.stack[vm.sp-1], nil)
  4532  	vm.iterStack = append(vm.iterStack, iterStackItem{iter: iter})
  4533  	vm.pc++
  4534  }
  4535  
  4536  type iterNext int32
  4537  
  4538  func (jmp iterNext) exec(vm *vm) {
  4539  	l := len(vm.iterStack) - 1
  4540  	iter := vm.iterStack[l].iter
  4541  	value, ex := iter.step()
  4542  	if ex == nil {
  4543  		if value == nil {
  4544  			vm.pc += int(jmp)
  4545  		} else {
  4546  			vm.iterStack[l].val = value
  4547  			vm.pc++
  4548  		}
  4549  	} else {
  4550  		l := len(vm.iterStack) - 1
  4551  		vm.iterStack[l] = iterStackItem{}
  4552  		vm.iterStack = vm.iterStack[:l]
  4553  		panic(ex.val)
  4554  	}
  4555  }
  4556  
  4557  type iterGetNextOrUndef struct{}
  4558  
  4559  func (iterGetNextOrUndef) exec(vm *vm) {
  4560  	l := len(vm.iterStack) - 1
  4561  	iter := vm.iterStack[l].iter
  4562  	var value Value
  4563  	if iter.iterator != nil {
  4564  		var ex *Exception
  4565  		value, ex = iter.step()
  4566  		if ex != nil {
  4567  			l := len(vm.iterStack) - 1
  4568  			vm.iterStack[l] = iterStackItem{}
  4569  			vm.iterStack = vm.iterStack[:l]
  4570  			panic(ex.val)
  4571  		}
  4572  	}
  4573  	vm.push(nilSafe(value))
  4574  	vm.pc++
  4575  }
  4576  
  4577  type copyStash struct{}
  4578  
  4579  func (copyStash) exec(vm *vm) {
  4580  	oldStash := vm.stash
  4581  	newStash := &stash{
  4582  		outer: oldStash.outer,
  4583  	}
  4584  	vm.stashAllocs++
  4585  	newStash.values = append([]Value(nil), oldStash.values...)
  4586  	newStash.names = oldStash.names
  4587  	vm.stash = newStash
  4588  	vm.pc++
  4589  }
  4590  
  4591  type _throwAssignToConst struct{}
  4592  
  4593  var throwAssignToConst _throwAssignToConst
  4594  
  4595  func (_throwAssignToConst) exec(vm *vm) {
  4596  	panic(errAssignToConst)
  4597  }
  4598  
  4599  func (r *Runtime) copyDataProperties(target, source Value) {
  4600  	targetObj := r.toObject(target)
  4601  	if source == _null || source == _undefined {
  4602  		return
  4603  	}
  4604  	sourceObj := source.ToObject(r)
  4605  	for item, next := iterateEnumerableProperties(sourceObj)(); next != nil; item, next = next() {
  4606  		createDataPropertyOrThrow(targetObj, item.name, item.value)
  4607  	}
  4608  }
  4609  
  4610  type _copySpread struct{}
  4611  
  4612  var copySpread _copySpread
  4613  
  4614  func (_copySpread) exec(vm *vm) {
  4615  	vm.r.copyDataProperties(vm.stack[vm.sp-2], vm.stack[vm.sp-1])
  4616  	vm.sp--
  4617  	vm.pc++
  4618  }
  4619  
  4620  type _copyRest struct{}
  4621  
  4622  var copyRest _copyRest
  4623  
  4624  func (_copyRest) exec(vm *vm) {
  4625  	vm.push(vm.r.NewObject())
  4626  	vm.r.copyDataProperties(vm.stack[vm.sp-1], vm.stack[vm.sp-2])
  4627  	vm.pc++
  4628  }
  4629  
  4630  type _createDestructSrc struct{}
  4631  
  4632  var createDestructSrc _createDestructSrc
  4633  
  4634  func (_createDestructSrc) exec(vm *vm) {
  4635  	v := vm.stack[vm.sp-1]
  4636  	vm.r.checkObjectCoercible(v)
  4637  	vm.push(vm.r.newDestructKeyedSource(v))
  4638  	vm.pc++
  4639  }
  4640  
  4641  type _checkObjectCoercible struct{}
  4642  
  4643  var checkObjectCoercible _checkObjectCoercible
  4644  
  4645  func (_checkObjectCoercible) exec(vm *vm) {
  4646  	vm.r.checkObjectCoercible(vm.stack[vm.sp-1])
  4647  	vm.pc++
  4648  }
  4649  
  4650  type createArgsRestStack int
  4651  
  4652  func (n createArgsRestStack) exec(vm *vm) {
  4653  	var values []Value
  4654  	delta := vm.args - int(n)
  4655  	if delta > 0 {
  4656  		values = make([]Value, delta)
  4657  		copy(values, vm.stack[vm.sb+int(n)+1:])
  4658  	}
  4659  	vm.push(vm.r.newArrayValues(values))
  4660  	vm.pc++
  4661  }
  4662  
  4663  type _createArgsRestStash struct{}
  4664  
  4665  var createArgsRestStash _createArgsRestStash
  4666  
  4667  func (_createArgsRestStash) exec(vm *vm) {
  4668  	vm.push(vm.r.newArrayValues(vm.stash.extraArgs))
  4669  	vm.stash.extraArgs = nil
  4670  	vm.pc++
  4671  }
  4672  
  4673  type concatStrings int
  4674  
  4675  func (n concatStrings) exec(vm *vm) {
  4676  	strs := vm.stack[vm.sp-int(n) : vm.sp]
  4677  	length := 0
  4678  	allAscii := true
  4679  	for i, s := range strs {
  4680  		switch s := s.(type) {
  4681  		case asciiString:
  4682  			length += s.length()
  4683  		case unicodeString:
  4684  			length += s.length()
  4685  			allAscii = false
  4686  		case *importedString:
  4687  			s.ensureScanned()
  4688  			if s.u != nil {
  4689  				strs[i] = s.u
  4690  				length += s.u.length()
  4691  				allAscii = false
  4692  			} else {
  4693  				strs[i] = asciiString(s.s)
  4694  				length += len(s.s)
  4695  			}
  4696  		default:
  4697  			panic(unknownStringTypeErr(s))
  4698  		}
  4699  	}
  4700  
  4701  	vm.sp -= int(n) - 1
  4702  	if allAscii {
  4703  		var buf strings.Builder
  4704  		buf.Grow(length)
  4705  		for _, s := range strs {
  4706  			buf.WriteString(string(s.(asciiString)))
  4707  		}
  4708  		vm.stack[vm.sp-1] = asciiString(buf.String())
  4709  	} else {
  4710  		var buf unicodeStringBuilder
  4711  		buf.Grow(length)
  4712  		for _, s := range strs {
  4713  			buf.WriteString(s.(valueString))
  4714  		}
  4715  		vm.stack[vm.sp-1] = buf.String()
  4716  	}
  4717  	vm.pc++
  4718  }
  4719  
  4720  type getTaggedTmplObject struct {
  4721  	raw, cooked []Value
  4722  }
  4723  
  4724  // As tagged template objects are not cached (because it's hard to ensure the cache is cleaned without using
  4725  // finalizers) this wrapper is needed to override the equality method so that two objects for the same template
  4726  // literal appeared to be equal from the code's point of view.
  4727  type taggedTemplateArray struct {
  4728  	*arrayObject
  4729  	idPtr *[]Value
  4730  }
  4731  
  4732  func (a *taggedTemplateArray) equal(other objectImpl) bool {
  4733  	if o, ok := other.(*taggedTemplateArray); ok {
  4734  		return a.idPtr == o.idPtr
  4735  	}
  4736  	return false
  4737  }
  4738  
  4739  func (c *getTaggedTmplObject) exec(vm *vm) {
  4740  	cooked := vm.r.newArrayObject()
  4741  	setArrayValues(cooked, c.cooked)
  4742  	raw := vm.r.newArrayObject()
  4743  	setArrayValues(raw, c.raw)
  4744  
  4745  	cooked.propValueCount = len(c.cooked)
  4746  	cooked.lengthProp.writable = false
  4747  
  4748  	raw.propValueCount = len(c.raw)
  4749  	raw.lengthProp.writable = false
  4750  
  4751  	raw.preventExtensions(true)
  4752  	raw.val.self = &taggedTemplateArray{
  4753  		arrayObject: raw,
  4754  		idPtr:       &c.raw,
  4755  	}
  4756  
  4757  	cooked._putProp("raw", raw.val, false, false, false)
  4758  	cooked.preventExtensions(true)
  4759  	cooked.val.self = &taggedTemplateArray{
  4760  		arrayObject: cooked,
  4761  		idPtr:       &c.cooked,
  4762  	}
  4763  
  4764  	vm.push(cooked.val)
  4765  	vm.pc++
  4766  }
  4767  
  4768  type _loadSuper struct{}
  4769  
  4770  var loadSuper _loadSuper
  4771  
  4772  func (_loadSuper) exec(vm *vm) {
  4773  	homeObject := getHomeObject(vm.stack[vm.sb-1])
  4774  	if proto := homeObject.Prototype(); proto != nil {
  4775  		vm.push(proto)
  4776  	} else {
  4777  		vm.push(_undefined)
  4778  	}
  4779  	vm.pc++
  4780  }
  4781  
  4782  type newClass struct {
  4783  	ctor       *Program
  4784  	name       unistring.String
  4785  	source     string
  4786  	initFields *Program
  4787  
  4788  	privateFields, privateMethods       []unistring.String // only set when dynamic resolution is needed
  4789  	numPrivateFields, numPrivateMethods uint32
  4790  
  4791  	length        int
  4792  	hasPrivateEnv bool
  4793  }
  4794  
  4795  type newDerivedClass struct {
  4796  	newClass
  4797  }
  4798  
  4799  func (vm *vm) createPrivateType(f *classFuncObject, numFields, numMethods uint32) {
  4800  	typ := &privateEnvType{}
  4801  	typ.numFields = numFields
  4802  	typ.numMethods = numMethods
  4803  	f.privateEnvType = typ
  4804  	f.privateMethods = make([]Value, numMethods)
  4805  }
  4806  
  4807  func (vm *vm) fillPrivateNamesMap(typ *privateEnvType, privateFields, privateMethods []unistring.String) {
  4808  	if len(privateFields) > 0 || len(privateMethods) > 0 {
  4809  		penv := vm.privEnv.names
  4810  		if penv == nil {
  4811  			penv = make(privateNames)
  4812  			vm.privEnv.names = penv
  4813  		}
  4814  		for idx, field := range privateFields {
  4815  			penv[field] = &privateId{
  4816  				typ: typ,
  4817  				idx: uint32(idx),
  4818  			}
  4819  		}
  4820  		for idx, method := range privateMethods {
  4821  			penv[method] = &privateId{
  4822  				typ:      typ,
  4823  				idx:      uint32(idx),
  4824  				isMethod: true,
  4825  			}
  4826  		}
  4827  	}
  4828  }
  4829  
  4830  func (c *newClass) create(protoParent, ctorParent *Object, vm *vm, derived bool) (prototype, cls *Object) {
  4831  	proto := vm.r.newBaseObject(protoParent, classObject)
  4832  	f := vm.r.newClassFunc(c.name, c.length, ctorParent, derived)
  4833  	f._putProp("prototype", proto.val, false, false, false)
  4834  	proto._putProp("constructor", f.val, true, false, true)
  4835  	f.prg = c.ctor
  4836  	f.stash = vm.stash
  4837  	f.src = c.source
  4838  	f.initFields = c.initFields
  4839  	if c.hasPrivateEnv {
  4840  		vm.privEnv = &privateEnv{
  4841  			outer: vm.privEnv,
  4842  		}
  4843  		vm.createPrivateType(f, c.numPrivateFields, c.numPrivateMethods)
  4844  		vm.fillPrivateNamesMap(f.privateEnvType, c.privateFields, c.privateMethods)
  4845  		vm.privEnv.instanceType = f.privateEnvType
  4846  	}
  4847  	f.privEnv = vm.privEnv
  4848  	return proto.val, f.val
  4849  }
  4850  
  4851  func (c *newClass) exec(vm *vm) {
  4852  	proto, cls := c.create(vm.r.global.ObjectPrototype, vm.r.global.FunctionPrototype, vm, false)
  4853  	sp := vm.sp
  4854  	vm.stack.expand(sp + 1)
  4855  	vm.stack[sp] = proto
  4856  	vm.stack[sp+1] = cls
  4857  	vm.sp = sp + 2
  4858  	vm.pc++
  4859  }
  4860  
  4861  func (c *newDerivedClass) exec(vm *vm) {
  4862  	var protoParent *Object
  4863  	var superClass *Object
  4864  	if o := vm.stack[vm.sp-1]; o != _null {
  4865  		if sc, ok := o.(*Object); !ok || sc.self.assertConstructor() == nil {
  4866  			panic(vm.r.NewTypeError("Class extends value is not a constructor or null"))
  4867  		} else {
  4868  			v := sc.self.getStr("prototype", nil)
  4869  			if v != _null {
  4870  				if o, ok := v.(*Object); ok {
  4871  					protoParent = o
  4872  				} else {
  4873  					panic(vm.r.NewTypeError("Class extends value does not have valid prototype property"))
  4874  				}
  4875  			}
  4876  			superClass = sc
  4877  		}
  4878  	} else {
  4879  		superClass = vm.r.global.FunctionPrototype
  4880  	}
  4881  
  4882  	proto, cls := c.create(protoParent, superClass, vm, true)
  4883  	vm.stack[vm.sp-1] = proto
  4884  	vm.push(cls)
  4885  	vm.pc++
  4886  }
  4887  
  4888  // Creates a special instance of *classFuncObject which is only used during evaluation of a class declaration
  4889  // to initialise static fields and instance private methods of another class.
  4890  type newStaticFieldInit struct {
  4891  	initFields                          *Program
  4892  	numPrivateFields, numPrivateMethods uint32
  4893  }
  4894  
  4895  func (c *newStaticFieldInit) exec(vm *vm) {
  4896  	f := vm.r.newClassFunc("", 0, vm.r.global.FunctionPrototype, false)
  4897  	if c.numPrivateFields > 0 || c.numPrivateMethods > 0 {
  4898  		vm.createPrivateType(f, c.numPrivateFields, c.numPrivateMethods)
  4899  	}
  4900  	f.initFields = c.initFields
  4901  	f.stash = vm.stash
  4902  	vm.push(f.val)
  4903  	vm.pc++
  4904  }
  4905  
  4906  func (vm *vm) loadThis(v Value) {
  4907  	if v != nil {
  4908  		vm.push(v)
  4909  	} else {
  4910  		panic(vm.r.newError(vm.r.global.ReferenceError, "Must call super constructor in derived class before accessing 'this'"))
  4911  	}
  4912  	vm.pc++
  4913  }
  4914  
  4915  type loadThisStash uint32
  4916  
  4917  func (l loadThisStash) exec(vm *vm) {
  4918  	vm.loadThis(*vm.getStashPtr(uint32(l)))
  4919  }
  4920  
  4921  type loadThisStack struct{}
  4922  
  4923  func (loadThisStack) exec(vm *vm) {
  4924  	vm.loadThis(vm.stack[vm.sb])
  4925  }
  4926  
  4927  func (vm *vm) getStashPtr(s uint32) *Value {
  4928  	level := int(s) >> 24
  4929  	idx := s & 0x00FFFFFF
  4930  	stash := vm.stash
  4931  	for i := 0; i < level; i++ {
  4932  		stash = stash.outer
  4933  	}
  4934  
  4935  	return &stash.values[idx]
  4936  }
  4937  
  4938  type getThisDynamic struct{}
  4939  
  4940  func (getThisDynamic) exec(vm *vm) {
  4941  	for stash := vm.stash; stash != nil; stash = stash.outer {
  4942  		if stash.obj == nil {
  4943  			if v, exists := stash.getByName(thisBindingName); exists {
  4944  				vm.push(v)
  4945  				vm.pc++
  4946  				return
  4947  			}
  4948  		}
  4949  	}
  4950  	vm.push(vm.r.globalObject)
  4951  	vm.pc++
  4952  }
  4953  
  4954  type throwConst struct {
  4955  	v interface{}
  4956  }
  4957  
  4958  func (t throwConst) exec(vm *vm) {
  4959  	panic(t.v)
  4960  }
  4961  
  4962  type resolveThisStack struct{}
  4963  
  4964  func (r resolveThisStack) exec(vm *vm) {
  4965  	vm.refStack = append(vm.refStack, &thisRef{v: (*[]Value)(&vm.stack), idx: vm.sb})
  4966  	vm.pc++
  4967  }
  4968  
  4969  type resolveThisStash uint32
  4970  
  4971  func (r resolveThisStash) exec(vm *vm) {
  4972  	level := int(r) >> 24
  4973  	idx := r & 0x00FFFFFF
  4974  	stash := vm.stash
  4975  	for i := 0; i < level; i++ {
  4976  		stash = stash.outer
  4977  	}
  4978  	vm.refStack = append(vm.refStack, &thisRef{v: &stash.values, idx: int(idx)})
  4979  	vm.pc++
  4980  }
  4981  
  4982  type resolveThisDynamic struct{}
  4983  
  4984  func (resolveThisDynamic) exec(vm *vm) {
  4985  	for stash := vm.stash; stash != nil; stash = stash.outer {
  4986  		if stash.obj == nil {
  4987  			if idx, exists := stash.names[thisBindingName]; exists {
  4988  				vm.refStack = append(vm.refStack, &thisRef{v: &stash.values, idx: int(idx &^ maskTyp)})
  4989  				vm.pc++
  4990  				return
  4991  			}
  4992  		}
  4993  	}
  4994  	panic(vm.r.newError(vm.r.global.ReferenceError, "Compiler bug: 'this' reference is not found in resolveThisDynamic"))
  4995  }
  4996  
  4997  type defineComputedKey int
  4998  
  4999  func (offset defineComputedKey) exec(vm *vm) {
  5000  	obj := vm.r.toObject(vm.stack[vm.sp-int(offset)])
  5001  	if h, ok := obj.self.(*classFuncObject); ok {
  5002  		key := toPropertyKey(vm.stack[vm.sp-1])
  5003  		h.computedKeys = append(h.computedKeys, key)
  5004  		vm.sp--
  5005  		vm.pc++
  5006  		return
  5007  	}
  5008  	panic(vm.r.NewTypeError("Compiler bug: unexpected target for defineComputedKey: %v", obj))
  5009  }
  5010  
  5011  type loadComputedKey int
  5012  
  5013  func (idx loadComputedKey) exec(vm *vm) {
  5014  	obj := vm.r.toObject(vm.stack[vm.sb-1])
  5015  	if h, ok := obj.self.(*classFuncObject); ok {
  5016  		vm.push(h.computedKeys[idx])
  5017  		vm.pc++
  5018  		return
  5019  	}
  5020  	panic(vm.r.NewTypeError("Compiler bug: unexpected target for loadComputedKey: %v", obj))
  5021  }
  5022  
  5023  type initStaticElements struct {
  5024  	privateFields, privateMethods []unistring.String
  5025  }
  5026  
  5027  func (i *initStaticElements) exec(vm *vm) {
  5028  	cls := vm.stack[vm.sp-1]
  5029  	staticInit := vm.r.toObject(vm.stack[vm.sp-3])
  5030  	vm.sp -= 2
  5031  	if h, ok := staticInit.self.(*classFuncObject); ok {
  5032  		h._putProp("prototype", cls, true, true, true) // so that 'super' resolution work
  5033  		h.privEnv = vm.privEnv
  5034  		if h.privateEnvType != nil {
  5035  			vm.privEnv.staticType = h.privateEnvType
  5036  			vm.fillPrivateNamesMap(h.privateEnvType, i.privateFields, i.privateMethods)
  5037  		}
  5038  		h._initFields(vm.r.toObject(cls))
  5039  		vm.stack[vm.sp-1] = cls
  5040  
  5041  		vm.pc++
  5042  		return
  5043  	}
  5044  	panic(vm.r.NewTypeError("Compiler bug: unexpected target for initStaticElements: %v", staticInit))
  5045  }
  5046  
  5047  type definePrivateMethod struct {
  5048  	idx          int
  5049  	targetOffset int
  5050  }
  5051  
  5052  func (d *definePrivateMethod) getPrivateMethods(vm *vm) []Value {
  5053  	obj := vm.r.toObject(vm.stack[vm.sp-d.targetOffset])
  5054  	if cls, ok := obj.self.(*classFuncObject); ok {
  5055  		return cls.privateMethods
  5056  	} else {
  5057  		panic(vm.r.NewTypeError("Compiler bug: wrong target type for definePrivateMethod: %T", obj.self))
  5058  	}
  5059  }
  5060  
  5061  func (d *definePrivateMethod) exec(vm *vm) {
  5062  	methods := d.getPrivateMethods(vm)
  5063  	methods[d.idx] = vm.stack[vm.sp-1]
  5064  	vm.sp--
  5065  	vm.pc++
  5066  }
  5067  
  5068  type definePrivateGetter struct {
  5069  	definePrivateMethod
  5070  }
  5071  
  5072  func (d *definePrivateGetter) exec(vm *vm) {
  5073  	methods := d.getPrivateMethods(vm)
  5074  	val := vm.stack[vm.sp-1]
  5075  	method := vm.r.toObject(val)
  5076  	p, _ := methods[d.idx].(*valueProperty)
  5077  	if p == nil {
  5078  		p = &valueProperty{
  5079  			accessor: true,
  5080  		}
  5081  		methods[d.idx] = p
  5082  	}
  5083  	if p.getterFunc != nil {
  5084  		panic(vm.r.NewTypeError("Private getter has already been declared"))
  5085  	}
  5086  	p.getterFunc = method
  5087  	vm.sp--
  5088  	vm.pc++
  5089  }
  5090  
  5091  type definePrivateSetter struct {
  5092  	definePrivateMethod
  5093  }
  5094  
  5095  func (d *definePrivateSetter) exec(vm *vm) {
  5096  	methods := d.getPrivateMethods(vm)
  5097  	val := vm.stack[vm.sp-1]
  5098  	method := vm.r.toObject(val)
  5099  	p, _ := methods[d.idx].(*valueProperty)
  5100  	if p == nil {
  5101  		p = &valueProperty{
  5102  			accessor: true,
  5103  		}
  5104  		methods[d.idx] = p
  5105  	}
  5106  	if p.setterFunc != nil {
  5107  		panic(vm.r.NewTypeError("Private setter has already been declared"))
  5108  	}
  5109  	p.setterFunc = method
  5110  	vm.sp--
  5111  	vm.pc++
  5112  }
  5113  
  5114  type definePrivateProp struct {
  5115  	idx int
  5116  }
  5117  
  5118  func (d *definePrivateProp) exec(vm *vm) {
  5119  	f := vm.r.toObject(vm.stack[vm.sb-1]).self.(*classFuncObject)
  5120  	obj := vm.r.toObject(vm.stack[vm.sp-2])
  5121  	penv := obj.self.getPrivateEnv(f.privateEnvType, false)
  5122  	penv.fields[d.idx] = vm.stack[vm.sp-1]
  5123  	vm.sp--
  5124  	vm.pc++
  5125  }
  5126  
  5127  type getPrivatePropRes resolvedPrivateName
  5128  
  5129  func (vm *vm) getPrivateType(level uint8, isStatic bool) *privateEnvType {
  5130  	e := vm.privEnv
  5131  	for i := uint8(0); i < level; i++ {
  5132  		e = e.outer
  5133  	}
  5134  	if isStatic {
  5135  		return e.staticType
  5136  	}
  5137  	return e.instanceType
  5138  }
  5139  
  5140  func (g *getPrivatePropRes) _get(base Value, vm *vm) Value {
  5141  	return vm.getPrivateProp(base, g.name, vm.getPrivateType(g.level, g.isStatic), g.idx, g.isMethod)
  5142  }
  5143  
  5144  func (g *getPrivatePropRes) exec(vm *vm) {
  5145  	vm.stack[vm.sp-1] = g._get(vm.stack[vm.sp-1], vm)
  5146  	vm.pc++
  5147  }
  5148  
  5149  type getPrivatePropId privateId
  5150  
  5151  func (g *getPrivatePropId) exec(vm *vm) {
  5152  	vm.stack[vm.sp-1] = vm.getPrivateProp(vm.stack[vm.sp-1], g.name, g.typ, g.idx, g.isMethod)
  5153  	vm.pc++
  5154  }
  5155  
  5156  type getPrivatePropIdCallee privateId
  5157  
  5158  func (g *getPrivatePropIdCallee) exec(vm *vm) {
  5159  	prop := vm.getPrivateProp(vm.stack[vm.sp-1], g.name, g.typ, g.idx, g.isMethod)
  5160  	if prop == nil {
  5161  		prop = memberUnresolved{valueUnresolved{r: vm.r, ref: (*privateId)(g).string()}}
  5162  	}
  5163  	vm.push(prop)
  5164  
  5165  	vm.pc++
  5166  }
  5167  
  5168  func (vm *vm) getPrivateProp(base Value, name unistring.String, typ *privateEnvType, idx uint32, isMethod bool) Value {
  5169  	obj := vm.r.toObject(base)
  5170  	penv := obj.self.getPrivateEnv(typ, false)
  5171  	var v Value
  5172  	if penv != nil {
  5173  		if isMethod {
  5174  			v = penv.methods[idx]
  5175  		} else {
  5176  			v = penv.fields[idx]
  5177  			if v == nil {
  5178  				panic(vm.r.NewTypeError("Private member #%s is accessed before it is initialized", name))
  5179  			}
  5180  		}
  5181  	} else {
  5182  		panic(vm.r.NewTypeError("Cannot read private member #%s from an object whose class did not declare it", name))
  5183  	}
  5184  	if prop, ok := v.(*valueProperty); ok {
  5185  		if prop.getterFunc == nil {
  5186  			panic(vm.r.NewTypeError("'#%s' was defined without a getter", name))
  5187  		}
  5188  		v = prop.get(obj)
  5189  	}
  5190  	return v
  5191  }
  5192  
  5193  type getPrivatePropResCallee getPrivatePropRes
  5194  
  5195  func (g *getPrivatePropResCallee) exec(vm *vm) {
  5196  	prop := (*getPrivatePropRes)(g)._get(vm.stack[vm.sp-1], vm)
  5197  	if prop == nil {
  5198  		prop = memberUnresolved{valueUnresolved{r: vm.r, ref: (*resolvedPrivateName)(g).string()}}
  5199  	}
  5200  	vm.push(prop)
  5201  
  5202  	vm.pc++
  5203  }
  5204  
  5205  func (vm *vm) setPrivateProp(base Value, name unistring.String, typ *privateEnvType, idx uint32, isMethod bool, val Value) {
  5206  	obj := vm.r.toObject(base)
  5207  	penv := obj.self.getPrivateEnv(typ, false)
  5208  	if penv != nil {
  5209  		if isMethod {
  5210  			v := penv.methods[idx]
  5211  			if prop, ok := v.(*valueProperty); ok {
  5212  				if prop.setterFunc != nil {
  5213  					prop.set(base, val)
  5214  				} else {
  5215  					panic(vm.r.NewTypeError("Cannot assign to read only property '#%s'", name))
  5216  				}
  5217  			} else {
  5218  				panic(vm.r.NewTypeError("Private method '#%s' is not writable", name))
  5219  			}
  5220  		} else {
  5221  			ptr := &penv.fields[idx]
  5222  			if *ptr == nil {
  5223  				panic(vm.r.NewTypeError("Private member #%s is accessed before it is initialized", name))
  5224  			}
  5225  			*ptr = val
  5226  		}
  5227  	} else {
  5228  		panic(vm.r.NewTypeError("Cannot write private member #%s from an object whose class did not declare it", name))
  5229  	}
  5230  }
  5231  
  5232  type setPrivatePropRes resolvedPrivateName
  5233  
  5234  func (p *setPrivatePropRes) _set(base Value, val Value, vm *vm) {
  5235  	vm.setPrivateProp(base, p.name, vm.getPrivateType(p.level, p.isStatic), p.idx, p.isMethod, val)
  5236  }
  5237  
  5238  func (p *setPrivatePropRes) exec(vm *vm) {
  5239  	v := vm.stack[vm.sp-1]
  5240  	p._set(vm.stack[vm.sp-2], v, vm)
  5241  	vm.stack[vm.sp-2] = v
  5242  	vm.sp--
  5243  	vm.pc++
  5244  }
  5245  
  5246  type setPrivatePropResP setPrivatePropRes
  5247  
  5248  func (p *setPrivatePropResP) exec(vm *vm) {
  5249  	v := vm.stack[vm.sp-1]
  5250  	(*setPrivatePropRes)(p)._set(vm.stack[vm.sp-2], v, vm)
  5251  	vm.sp -= 2
  5252  	vm.pc++
  5253  }
  5254  
  5255  type setPrivatePropId privateId
  5256  
  5257  func (p *setPrivatePropId) exec(vm *vm) {
  5258  	v := vm.stack[vm.sp-1]
  5259  	vm.setPrivateProp(vm.stack[vm.sp-2], p.name, p.typ, p.idx, p.isMethod, v)
  5260  	vm.stack[vm.sp-2] = v
  5261  	vm.sp--
  5262  	vm.pc++
  5263  }
  5264  
  5265  type setPrivatePropIdP privateId
  5266  
  5267  func (p *setPrivatePropIdP) exec(vm *vm) {
  5268  	v := vm.stack[vm.sp-1]
  5269  	vm.setPrivateProp(vm.stack[vm.sp-2], p.name, p.typ, p.idx, p.isMethod, v)
  5270  	vm.sp -= 2
  5271  	vm.pc++
  5272  }
  5273  
  5274  type popPrivateEnv struct{}
  5275  
  5276  func (popPrivateEnv) exec(vm *vm) {
  5277  	vm.privEnv = vm.privEnv.outer
  5278  	vm.pc++
  5279  }
  5280  
  5281  type privateInRes resolvedPrivateName
  5282  
  5283  func (i *privateInRes) exec(vm *vm) {
  5284  	obj := vm.r.toObject(vm.stack[vm.sp-1])
  5285  	pe := obj.self.getPrivateEnv(vm.getPrivateType(i.level, i.isStatic), false)
  5286  	if pe != nil && (i.isMethod && pe.methods[i.idx] != nil || !i.isMethod && pe.fields[i.idx] != nil) {
  5287  		vm.stack[vm.sp-1] = valueTrue
  5288  	} else {
  5289  		vm.stack[vm.sp-1] = valueFalse
  5290  	}
  5291  	vm.pc++
  5292  }
  5293  
  5294  type privateInId privateId
  5295  
  5296  func (i *privateInId) exec(vm *vm) {
  5297  	obj := vm.r.toObject(vm.stack[vm.sp-1])
  5298  	pe := obj.self.getPrivateEnv(i.typ, false)
  5299  	if pe != nil && (i.isMethod && pe.methods[i.idx] != nil || !i.isMethod && pe.fields[i.idx] != nil) {
  5300  		vm.stack[vm.sp-1] = valueTrue
  5301  	} else {
  5302  		vm.stack[vm.sp-1] = valueFalse
  5303  	}
  5304  	vm.pc++
  5305  }
  5306  
  5307  type getPrivateRefRes resolvedPrivateName
  5308  
  5309  func (r *getPrivateRefRes) exec(vm *vm) {
  5310  	vm.refStack = append(vm.refStack, &privateRefRes{
  5311  		base: vm.stack[vm.sp-1].ToObject(vm.r),
  5312  		name: (*resolvedPrivateName)(r),
  5313  	})
  5314  	vm.sp--
  5315  	vm.pc++
  5316  }
  5317  
  5318  type getPrivateRefId privateId
  5319  
  5320  func (r *getPrivateRefId) exec(vm *vm) {
  5321  	vm.refStack = append(vm.refStack, &privateRefId{
  5322  		base: vm.stack[vm.sp-1].ToObject(vm.r),
  5323  		id:   (*privateId)(r),
  5324  	})
  5325  	vm.sp--
  5326  	vm.pc++
  5327  }