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

     1  package goja
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  
     7  	"github.com/nuvolaris/goja/unistring"
     8  )
     9  
    10  type resultType uint8
    11  
    12  const (
    13  	resultNormal resultType = iota
    14  	resultYield
    15  	resultYieldRes      // a yield that expects a value in return
    16  	resultYieldDelegate // yield*
    17  	resultYieldDelegateRes
    18  	resultAwait
    19  )
    20  
    21  // used both as an instruction and as a Value
    22  type yieldMarker struct {
    23  	valueNull
    24  	resultType resultType
    25  }
    26  
    27  var (
    28  	await = &yieldMarker{resultType: resultAwait}
    29  
    30  	yield            = &yieldMarker{resultType: resultYield}
    31  	yieldRes         = &yieldMarker{resultType: resultYieldRes}
    32  	yieldDelegate    = &yieldMarker{resultType: resultYieldDelegate}
    33  	yieldDelegateRes = &yieldMarker{resultType: resultYieldDelegateRes}
    34  	yieldEmpty       = &yieldMarker{resultType: resultYield}
    35  )
    36  
    37  // AsyncContextTracker is a handler that allows to track an async execution context to ensure it remains
    38  // consistent across all callback invocations.
    39  // Whenever a Promise reaction job is scheduled the Grab method is called. It is supposed to return the
    40  // current context. The same context will be supplied to the Resumed method before the reaction job is
    41  // executed. The Exited method is called after the reaction job is finished.
    42  // This means that for each invocation of the Grab method there will be exactly one subsequent invocation
    43  // of Resumed and then Exited methods (assuming the Promise is fulfilled or rejected). Also, the Resumed/Exited
    44  // calls cannot be nested, so Exited can simply clear the current context instead of popping from a stack.
    45  // Note, this works for both async functions and regular Promise.then()/Promise.catch() callbacks.
    46  // See TestAsyncContextTracker for more insight.
    47  //
    48  // To register it call Runtime.SetAsyncContextTracker().
    49  type AsyncContextTracker interface {
    50  	Grab() (trackingObject interface{})
    51  	Resumed(trackingObject interface{})
    52  	Exited()
    53  }
    54  
    55  type funcObjectImpl interface {
    56  	source() String
    57  }
    58  
    59  type baseFuncObject struct {
    60  	baseObject
    61  
    62  	lenProp valueProperty
    63  }
    64  
    65  type baseJsFuncObject struct {
    66  	baseFuncObject
    67  
    68  	stash   *stash
    69  	privEnv *privateEnv
    70  
    71  	prg    *Program
    72  	src    string
    73  	strict bool
    74  }
    75  
    76  type funcObject struct {
    77  	baseJsFuncObject
    78  }
    79  
    80  type generatorFuncObject struct {
    81  	baseJsFuncObject
    82  }
    83  
    84  type asyncFuncObject struct {
    85  	baseJsFuncObject
    86  }
    87  
    88  type classFuncObject struct {
    89  	baseJsFuncObject
    90  	initFields   *Program
    91  	computedKeys []Value
    92  
    93  	privateEnvType *privateEnvType
    94  	privateMethods []Value
    95  
    96  	derived bool
    97  }
    98  
    99  type methodFuncObject struct {
   100  	baseJsFuncObject
   101  	homeObject *Object
   102  }
   103  
   104  type generatorMethodFuncObject struct {
   105  	methodFuncObject
   106  }
   107  
   108  type asyncMethodFuncObject struct {
   109  	methodFuncObject
   110  }
   111  
   112  type arrowFuncObject struct {
   113  	baseJsFuncObject
   114  	funcObj   *Object
   115  	newTarget Value
   116  }
   117  
   118  type asyncArrowFuncObject struct {
   119  	arrowFuncObject
   120  }
   121  
   122  type nativeFuncObject struct {
   123  	baseFuncObject
   124  
   125  	f         func(FunctionCall) Value
   126  	construct func(args []Value, newTarget *Object) *Object
   127  }
   128  
   129  type wrappedFuncObject struct {
   130  	nativeFuncObject
   131  	wrapped reflect.Value
   132  }
   133  
   134  type boundFuncObject struct {
   135  	nativeFuncObject
   136  	wrapped *Object
   137  }
   138  
   139  type generatorState uint8
   140  
   141  const (
   142  	genStateUndefined generatorState = iota
   143  	genStateSuspendedStart
   144  	genStateExecuting
   145  	genStateSuspendedYield
   146  	genStateSuspendedYieldRes
   147  	genStateCompleted
   148  )
   149  
   150  type generatorObject struct {
   151  	baseObject
   152  	gen       generator
   153  	delegated *iteratorRecord
   154  	state     generatorState
   155  }
   156  
   157  func (f *nativeFuncObject) source() String {
   158  	return newStringValue(fmt.Sprintf("function %s() { [native code] }", nilSafe(f.getStr("name", nil)).toString()))
   159  }
   160  
   161  func (f *nativeFuncObject) export(*objectExportCtx) interface{} {
   162  	return f.f
   163  }
   164  
   165  func (f *wrappedFuncObject) exportType() reflect.Type {
   166  	return f.wrapped.Type()
   167  }
   168  
   169  func (f *wrappedFuncObject) export(*objectExportCtx) interface{} {
   170  	return f.wrapped.Interface()
   171  }
   172  
   173  func (f *funcObject) _addProto(n unistring.String) Value {
   174  	if n == "prototype" {
   175  		if _, exists := f.values[n]; !exists {
   176  			return f.addPrototype()
   177  		}
   178  	}
   179  	return nil
   180  }
   181  
   182  func (f *funcObject) getStr(p unistring.String, receiver Value) Value {
   183  	return f.getStrWithOwnProp(f.getOwnPropStr(p), p, receiver)
   184  }
   185  
   186  func (f *funcObject) getOwnPropStr(name unistring.String) Value {
   187  	if v := f._addProto(name); v != nil {
   188  		return v
   189  	}
   190  
   191  	return f.baseObject.getOwnPropStr(name)
   192  }
   193  
   194  func (f *funcObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
   195  	f._addProto(name)
   196  	return f.baseObject.setOwnStr(name, val, throw)
   197  }
   198  
   199  func (f *funcObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
   200  	return f._setForeignStr(name, f.getOwnPropStr(name), val, receiver, throw)
   201  }
   202  
   203  func (f *funcObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
   204  	f._addProto(name)
   205  	return f.baseObject.defineOwnPropertyStr(name, descr, throw)
   206  }
   207  
   208  func (f *funcObject) deleteStr(name unistring.String, throw bool) bool {
   209  	f._addProto(name)
   210  	return f.baseObject.deleteStr(name, throw)
   211  }
   212  
   213  func (f *funcObject) addPrototype() Value {
   214  	proto := f.val.runtime.NewObject()
   215  	proto.self._putProp("constructor", f.val, true, false, true)
   216  	return f._putProp("prototype", proto, true, false, false)
   217  }
   218  
   219  func (f *funcObject) hasOwnPropertyStr(name unistring.String) bool {
   220  	if f.baseObject.hasOwnPropertyStr(name) {
   221  		return true
   222  	}
   223  
   224  	if name == "prototype" {
   225  		return true
   226  	}
   227  	return false
   228  }
   229  
   230  func (f *funcObject) stringKeys(all bool, accum []Value) []Value {
   231  	if all {
   232  		if _, exists := f.values["prototype"]; !exists {
   233  			accum = append(accum, asciiString("prototype"))
   234  		}
   235  	}
   236  	return f.baseFuncObject.stringKeys(all, accum)
   237  }
   238  
   239  func (f *funcObject) iterateStringKeys() iterNextFunc {
   240  	if _, exists := f.values["prototype"]; !exists {
   241  		f.addPrototype()
   242  	}
   243  	return f.baseFuncObject.iterateStringKeys()
   244  }
   245  
   246  func (f *baseFuncObject) createInstance(newTarget *Object) *Object {
   247  	r := f.val.runtime
   248  	if newTarget == nil {
   249  		newTarget = f.val
   250  	}
   251  	proto := r.getPrototypeFromCtor(newTarget, nil, r.global.ObjectPrototype)
   252  
   253  	return f.val.runtime.newBaseObject(proto, classObject).val
   254  }
   255  
   256  func (f *baseJsFuncObject) source() String {
   257  	return newStringValue(f.src)
   258  }
   259  
   260  func (f *baseJsFuncObject) construct(args []Value, newTarget *Object) *Object {
   261  	if newTarget == nil {
   262  		newTarget = f.val
   263  	}
   264  	proto := newTarget.self.getStr("prototype", nil)
   265  	var protoObj *Object
   266  	if p, ok := proto.(*Object); ok {
   267  		protoObj = p
   268  	} else {
   269  		protoObj = f.val.runtime.global.ObjectPrototype
   270  	}
   271  
   272  	obj := f.val.runtime.newBaseObject(protoObj, classObject).val
   273  	ret := f.call(FunctionCall{
   274  		This:      obj,
   275  		Arguments: args,
   276  	}, newTarget)
   277  
   278  	if ret, ok := ret.(*Object); ok {
   279  		return ret
   280  	}
   281  	return obj
   282  }
   283  
   284  func (f *classFuncObject) Call(FunctionCall) Value {
   285  	panic(f.val.runtime.NewTypeError("Class constructor cannot be invoked without 'new'"))
   286  }
   287  
   288  func (f *classFuncObject) assertCallable() (func(FunctionCall) Value, bool) {
   289  	return f.Call, true
   290  }
   291  
   292  func (f *classFuncObject) vmCall(vm *vm, n int) {
   293  	f.Call(FunctionCall{})
   294  }
   295  
   296  func (f *classFuncObject) export(*objectExportCtx) interface{} {
   297  	return f.Call
   298  }
   299  
   300  func (f *classFuncObject) createInstance(args []Value, newTarget *Object) (instance *Object) {
   301  	if f.derived {
   302  		if ctor := f.prototype.self.assertConstructor(); ctor != nil {
   303  			instance = ctor(args, newTarget)
   304  		} else {
   305  			panic(f.val.runtime.NewTypeError("Super constructor is not a constructor"))
   306  		}
   307  	} else {
   308  		instance = f.baseFuncObject.createInstance(newTarget)
   309  	}
   310  	return
   311  }
   312  
   313  func (f *classFuncObject) _initFields(instance *Object) {
   314  	if f.privateEnvType != nil {
   315  		penv := instance.self.getPrivateEnv(f.privateEnvType, true)
   316  		penv.methods = f.privateMethods
   317  	}
   318  	if f.initFields != nil {
   319  		vm := f.val.runtime.vm
   320  		vm.pushCtx()
   321  		vm.prg = f.initFields
   322  		vm.stash = f.stash
   323  		vm.privEnv = f.privEnv
   324  		vm.newTarget = nil
   325  
   326  		// so that 'super' base could be correctly resolved (including from direct eval())
   327  		vm.push(f.val)
   328  
   329  		vm.sb = vm.sp
   330  		vm.push(instance)
   331  		vm.pc = 0
   332  		ex := vm.runTry()
   333  		vm.popCtx()
   334  		if ex != nil {
   335  			panic(ex)
   336  		}
   337  		vm.sp -= 2
   338  	}
   339  }
   340  
   341  func (f *classFuncObject) construct(args []Value, newTarget *Object) *Object {
   342  	if newTarget == nil {
   343  		newTarget = f.val
   344  	}
   345  	if f.prg == nil {
   346  		instance := f.createInstance(args, newTarget)
   347  		f._initFields(instance)
   348  		return instance
   349  	} else {
   350  		var instance *Object
   351  		var thisVal Value
   352  		if !f.derived {
   353  			instance = f.createInstance(args, newTarget)
   354  			f._initFields(instance)
   355  			thisVal = instance
   356  		}
   357  		ret := f._call(args, newTarget, thisVal)
   358  
   359  		if ret, ok := ret.(*Object); ok {
   360  			return ret
   361  		}
   362  		if f.derived {
   363  			r := f.val.runtime
   364  			if ret != _undefined {
   365  				panic(r.NewTypeError("Derived constructors may only return object or undefined"))
   366  			}
   367  			if v := r.vm.stack[r.vm.sp+1]; v != nil { // using residual 'this' value (a bit hacky)
   368  				instance = r.toObject(v)
   369  			} else {
   370  				panic(r.newError(r.global.ReferenceError, "Must call super constructor in derived class before returning from derived constructor"))
   371  			}
   372  		}
   373  		return instance
   374  	}
   375  }
   376  
   377  func (f *classFuncObject) assertConstructor() func(args []Value, newTarget *Object) *Object {
   378  	return f.construct
   379  }
   380  
   381  func (f *baseJsFuncObject) Call(call FunctionCall) Value {
   382  	return f.call(call, nil)
   383  }
   384  
   385  func (f *arrowFuncObject) Call(call FunctionCall) Value {
   386  	return f._call(call.Arguments, f.newTarget, nil)
   387  }
   388  
   389  func (f *baseJsFuncObject) __call(args []Value, newTarget, this Value) (Value, *Exception) {
   390  	vm := f.val.runtime.vm
   391  
   392  	vm.stack.expand(vm.sp + len(args) + 1)
   393  	vm.stack[vm.sp] = f.val
   394  	vm.sp++
   395  	vm.stack[vm.sp] = this
   396  	vm.sp++
   397  	for _, arg := range args {
   398  		if arg != nil {
   399  			vm.stack[vm.sp] = arg
   400  		} else {
   401  			vm.stack[vm.sp] = _undefined
   402  		}
   403  		vm.sp++
   404  	}
   405  
   406  	vm.pushTryFrame(tryPanicMarker, -1)
   407  	defer vm.popTryFrame()
   408  
   409  	var needPop bool
   410  	if vm.prg != nil {
   411  		vm.pushCtx()
   412  		vm.callStack = append(vm.callStack, context{pc: -2}) // extra frame so that run() halts after ret
   413  		needPop = true
   414  	} else {
   415  		vm.pc = -2
   416  		vm.pushCtx()
   417  	}
   418  
   419  	vm.args = len(args)
   420  	vm.prg = f.prg
   421  	vm.stash = f.stash
   422  	vm.privEnv = f.privEnv
   423  	vm.newTarget = newTarget
   424  	vm.pc = 0
   425  	for {
   426  		ex := vm.runTryInner()
   427  		if ex != nil {
   428  			return nil, ex
   429  		}
   430  		if vm.halted() {
   431  			break
   432  		}
   433  	}
   434  	if needPop {
   435  		vm.popCtx()
   436  	}
   437  
   438  	return vm.pop(), nil
   439  }
   440  
   441  func (f *baseJsFuncObject) _call(args []Value, newTarget, this Value) Value {
   442  	res, ex := f.__call(args, newTarget, this)
   443  	if ex != nil {
   444  		panic(ex)
   445  	}
   446  	return res
   447  }
   448  
   449  func (f *baseJsFuncObject) call(call FunctionCall, newTarget Value) Value {
   450  	return f._call(call.Arguments, newTarget, nilSafe(call.This))
   451  }
   452  
   453  func (f *baseJsFuncObject) export(*objectExportCtx) interface{} {
   454  	return f.Call
   455  }
   456  
   457  func (f *baseFuncObject) exportType() reflect.Type {
   458  	return reflectTypeFunc
   459  }
   460  
   461  func (f *baseFuncObject) typeOf() String {
   462  	return stringFunction
   463  }
   464  
   465  func (f *baseJsFuncObject) assertCallable() (func(FunctionCall) Value, bool) {
   466  	return f.Call, true
   467  }
   468  
   469  func (f *funcObject) assertConstructor() func(args []Value, newTarget *Object) *Object {
   470  	return f.construct
   471  }
   472  
   473  func (f *baseJsFuncObject) vmCall(vm *vm, n int) {
   474  	vm.pushCtx()
   475  	vm.args = n
   476  	vm.prg = f.prg
   477  	vm.stash = f.stash
   478  	vm.privEnv = f.privEnv
   479  	vm.pc = 0
   480  	vm.stack[vm.sp-n-1], vm.stack[vm.sp-n-2] = vm.stack[vm.sp-n-2], vm.stack[vm.sp-n-1]
   481  }
   482  
   483  func (f *arrowFuncObject) assertCallable() (func(FunctionCall) Value, bool) {
   484  	return f.Call, true
   485  }
   486  
   487  func (f *arrowFuncObject) vmCall(vm *vm, n int) {
   488  	vm.pushCtx()
   489  	vm.args = n
   490  	vm.prg = f.prg
   491  	vm.stash = f.stash
   492  	vm.privEnv = f.privEnv
   493  	vm.pc = 0
   494  	vm.stack[vm.sp-n-1], vm.stack[vm.sp-n-2] = nil, vm.stack[vm.sp-n-1]
   495  	vm.newTarget = f.newTarget
   496  }
   497  
   498  func (f *arrowFuncObject) export(*objectExportCtx) interface{} {
   499  	return f.Call
   500  }
   501  
   502  func (f *baseFuncObject) init(name unistring.String, length Value) {
   503  	f.baseObject.init()
   504  
   505  	f.lenProp.configurable = true
   506  	f.lenProp.value = length
   507  	f._put("length", &f.lenProp)
   508  
   509  	f._putProp("name", stringValueFromRaw(name), false, false, true)
   510  }
   511  
   512  func (f *baseFuncObject) hasInstance(v Value) bool {
   513  	if v, ok := v.(*Object); ok {
   514  		o := f.val.self.getStr("prototype", nil)
   515  		if o1, ok := o.(*Object); ok {
   516  			for {
   517  				v = v.self.proto()
   518  				if v == nil {
   519  					return false
   520  				}
   521  				if o1 == v {
   522  					return true
   523  				}
   524  			}
   525  		} else {
   526  			f.val.runtime.typeErrorResult(true, "prototype is not an object")
   527  		}
   528  	}
   529  
   530  	return false
   531  }
   532  
   533  func (f *nativeFuncObject) defaultConstruct(ccall func(ConstructorCall) *Object, args []Value, newTarget *Object) *Object {
   534  	obj := f.createInstance(newTarget)
   535  	ret := ccall(ConstructorCall{
   536  		This:      obj,
   537  		Arguments: args,
   538  		NewTarget: newTarget,
   539  	})
   540  
   541  	if ret != nil {
   542  		return ret
   543  	}
   544  	return obj
   545  }
   546  
   547  func (f *nativeFuncObject) assertCallable() (func(FunctionCall) Value, bool) {
   548  	if f.f != nil {
   549  		return f.f, true
   550  	}
   551  	return nil, false
   552  }
   553  
   554  func (f *nativeFuncObject) vmCall(vm *vm, n int) {
   555  	if f.f != nil {
   556  		vm.pushCtx()
   557  		vm.prg = nil
   558  		vm.sb = vm.sp - n // so that [sb-1] points to the callee
   559  		ret := f.f(FunctionCall{
   560  			Arguments: vm.stack[vm.sp-n : vm.sp],
   561  			This:      vm.stack[vm.sp-n-2],
   562  		})
   563  		if ret == nil {
   564  			ret = _undefined
   565  		}
   566  		vm.stack[vm.sp-n-2] = ret
   567  		vm.popCtx()
   568  	} else {
   569  		vm.stack[vm.sp-n-2] = _undefined
   570  	}
   571  	vm.sp -= n + 1
   572  	vm.pc++
   573  }
   574  
   575  func (f *nativeFuncObject) assertConstructor() func(args []Value, newTarget *Object) *Object {
   576  	return f.construct
   577  }
   578  
   579  func (f *boundFuncObject) hasInstance(v Value) bool {
   580  	return instanceOfOperator(v, f.wrapped)
   581  }
   582  
   583  func (f *baseJsFuncObject) prepareForVmCall(call FunctionCall) {
   584  	vm := f.val.runtime.vm
   585  	args := call.Arguments
   586  	vm.stack.expand(vm.sp + len(args) + 1)
   587  	vm.stack[vm.sp] = call.This
   588  	vm.sp++
   589  	vm.stack[vm.sp] = f.val
   590  	vm.sp++
   591  	for _, arg := range args {
   592  		if arg != nil {
   593  			vm.stack[vm.sp] = arg
   594  		} else {
   595  			vm.stack[vm.sp] = _undefined
   596  		}
   597  		vm.sp++
   598  	}
   599  }
   600  
   601  func (f *baseJsFuncObject) asyncCall(call FunctionCall, vmCall func(*vm, int)) Value {
   602  	f.prepareForVmCall(call)
   603  	ar := &asyncRunner{
   604  		f:      f.val,
   605  		vmCall: vmCall,
   606  	}
   607  	ar.start(len(call.Arguments))
   608  	return ar.promiseCap.promise
   609  }
   610  
   611  func (f *asyncFuncObject) Call(call FunctionCall) Value {
   612  	return f.asyncCall(call, f.baseJsFuncObject.vmCall)
   613  }
   614  
   615  func (f *asyncFuncObject) assertCallable() (func(FunctionCall) Value, bool) {
   616  	return f.Call, true
   617  }
   618  
   619  func (f *asyncFuncObject) export(*objectExportCtx) interface{} {
   620  	return f.Call
   621  }
   622  
   623  func (f *asyncArrowFuncObject) Call(call FunctionCall) Value {
   624  	return f.asyncCall(call, f.arrowFuncObject.vmCall)
   625  }
   626  
   627  func (f *asyncArrowFuncObject) assertCallable() (func(FunctionCall) Value, bool) {
   628  	return f.Call, true
   629  }
   630  
   631  func (f *asyncArrowFuncObject) export(*objectExportCtx) interface{} {
   632  	return f.Call
   633  }
   634  
   635  func (f *asyncArrowFuncObject) vmCall(vm *vm, n int) {
   636  	f.asyncVmCall(vm, n, f.arrowFuncObject.vmCall)
   637  }
   638  
   639  func (f *asyncMethodFuncObject) Call(call FunctionCall) Value {
   640  	return f.asyncCall(call, f.methodFuncObject.vmCall)
   641  }
   642  
   643  func (f *asyncMethodFuncObject) assertCallable() (func(FunctionCall) Value, bool) {
   644  	return f.Call, true
   645  }
   646  
   647  func (f *asyncMethodFuncObject) export(ctx *objectExportCtx) interface{} {
   648  	return f.Call
   649  }
   650  
   651  func (f *asyncMethodFuncObject) vmCall(vm *vm, n int) {
   652  	f.asyncVmCall(vm, n, f.methodFuncObject.vmCall)
   653  }
   654  
   655  func (f *baseJsFuncObject) asyncVmCall(vm *vm, n int, vmCall func(*vm, int)) {
   656  	ar := &asyncRunner{
   657  		f:      f.val,
   658  		vmCall: vmCall,
   659  	}
   660  	ar.start(n)
   661  	vm.push(ar.promiseCap.promise)
   662  	vm.pc++
   663  }
   664  
   665  func (f *asyncFuncObject) vmCall(vm *vm, n int) {
   666  	f.asyncVmCall(vm, n, f.baseJsFuncObject.vmCall)
   667  }
   668  
   669  type asyncRunner struct {
   670  	gen        generator
   671  	promiseCap *promiseCapability
   672  	f          *Object
   673  	vmCall     func(*vm, int)
   674  }
   675  
   676  func (ar *asyncRunner) onFulfilled(call FunctionCall) Value {
   677  	ar.gen.vm.curAsyncRunner = ar
   678  	defer func() {
   679  		ar.gen.vm.curAsyncRunner = nil
   680  	}()
   681  	arg := call.Argument(0)
   682  	res, resType, ex := ar.gen.next(arg)
   683  	ar.step(res, resType == resultNormal, ex)
   684  	return _undefined
   685  }
   686  
   687  func (ar *asyncRunner) onRejected(call FunctionCall) Value {
   688  	ar.gen.vm.curAsyncRunner = ar
   689  	defer func() {
   690  		ar.gen.vm.curAsyncRunner = nil
   691  	}()
   692  	reason := call.Argument(0)
   693  	res, resType, ex := ar.gen.nextThrow(reason)
   694  	ar.step(res, resType == resultNormal, ex)
   695  	return _undefined
   696  }
   697  
   698  func (ar *asyncRunner) step(res Value, done bool, ex *Exception) {
   699  	r := ar.f.runtime
   700  	if done || ex != nil {
   701  		if ex == nil {
   702  			ar.promiseCap.resolve(res)
   703  		} else {
   704  			ar.promiseCap.reject(ex.val)
   705  		}
   706  		return
   707  	}
   708  
   709  	// await
   710  	promise := r.promiseResolve(r.global.Promise, res)
   711  	promise.self.(*Promise).addReactions(&promiseReaction{
   712  		typ:         promiseReactionFulfill,
   713  		handler:     &jobCallback{callback: ar.onFulfilled},
   714  		asyncRunner: ar,
   715  	}, &promiseReaction{
   716  		typ:         promiseReactionReject,
   717  		handler:     &jobCallback{callback: ar.onRejected},
   718  		asyncRunner: ar,
   719  	})
   720  }
   721  
   722  func (ar *asyncRunner) start(nArgs int) {
   723  	r := ar.f.runtime
   724  	ar.gen.vm = r.vm
   725  	ar.promiseCap = r.newPromiseCapability(r.global.Promise)
   726  	sp := r.vm.sp
   727  	ar.gen.enter()
   728  	ar.vmCall(r.vm, nArgs)
   729  	res, resType, ex := ar.gen.step()
   730  	ar.step(res, resType == resultNormal, ex)
   731  	if ex != nil {
   732  		r.vm.sp = sp - nArgs - 2
   733  	}
   734  	r.vm.popTryFrame()
   735  	r.vm.popCtx()
   736  }
   737  
   738  type generator struct {
   739  	ctx execCtx
   740  	vm  *vm
   741  
   742  	tryStackLen, iterStackLen, refStackLen uint32
   743  }
   744  
   745  func (g *generator) storeLengths() {
   746  	g.tryStackLen, g.iterStackLen, g.refStackLen = uint32(len(g.vm.tryStack)), uint32(len(g.vm.iterStack)), uint32(len(g.vm.refStack))
   747  }
   748  
   749  func (g *generator) enter() {
   750  	g.vm.pushCtx()
   751  	g.vm.pushTryFrame(tryPanicMarker, -1)
   752  	g.vm.prg, g.vm.sb, g.vm.pc = nil, -1, -2 // so that vm.run() halts after ret
   753  	g.storeLengths()
   754  }
   755  
   756  func (g *generator) step() (res Value, resultType resultType, ex *Exception) {
   757  	for {
   758  		ex = g.vm.runTryInner()
   759  		if ex != nil {
   760  			return
   761  		}
   762  		if g.vm.halted() {
   763  			break
   764  		}
   765  	}
   766  	res = g.vm.pop()
   767  	if ym, ok := res.(*yieldMarker); ok {
   768  		resultType = ym.resultType
   769  		g.ctx = execCtx{}
   770  		g.vm.pc = -g.vm.pc + 1
   771  		if res != yieldEmpty {
   772  			res = g.vm.pop()
   773  		} else {
   774  			res = nil
   775  		}
   776  		g.vm.suspend(&g.ctx, g.tryStackLen, g.iterStackLen, g.refStackLen)
   777  		g.vm.sp = g.vm.sb - 1
   778  		g.vm.callStack = g.vm.callStack[:len(g.vm.callStack)-1] // remove the frame with pc == -2, as ret would do
   779  	}
   780  	return
   781  }
   782  
   783  func (g *generator) enterNext() {
   784  	g.vm.pushCtx()
   785  	g.vm.pushTryFrame(tryPanicMarker, -1)
   786  	g.vm.callStack = append(g.vm.callStack, context{pc: -2}) // extra frame so that vm.run() halts after ret
   787  	g.storeLengths()
   788  	g.vm.resume(&g.ctx)
   789  }
   790  
   791  func (g *generator) next(v Value) (Value, resultType, *Exception) {
   792  	g.enterNext()
   793  	if v != nil {
   794  		g.vm.push(v)
   795  	}
   796  	res, done, ex := g.step()
   797  	g.vm.popTryFrame()
   798  	g.vm.popCtx()
   799  	return res, done, ex
   800  }
   801  
   802  func (g *generator) nextThrow(v interface{}) (Value, resultType, *Exception) {
   803  	g.enterNext()
   804  	ex := g.vm.handleThrow(v)
   805  	if ex != nil {
   806  		g.vm.popTryFrame()
   807  		g.vm.popCtx()
   808  		return nil, resultNormal, ex
   809  	}
   810  
   811  	res, resType, ex := g.step()
   812  	g.vm.popTryFrame()
   813  	g.vm.popCtx()
   814  	return res, resType, ex
   815  }
   816  
   817  func (g *generatorObject) init(vmCall func(*vm, int), nArgs int) {
   818  	g.baseObject.init()
   819  	vm := g.val.runtime.vm
   820  	g.gen.vm = vm
   821  
   822  	g.gen.enter()
   823  	vmCall(vm, nArgs)
   824  
   825  	_, _, ex := g.gen.step()
   826  
   827  	vm.popTryFrame()
   828  	if ex != nil {
   829  		panic(ex)
   830  	}
   831  
   832  	g.state = genStateSuspendedStart
   833  	vm.popCtx()
   834  }
   835  
   836  func (g *generatorObject) validate() {
   837  	if g.state == genStateExecuting {
   838  		panic(g.val.runtime.NewTypeError("Illegal generator state"))
   839  	}
   840  }
   841  
   842  func (g *generatorObject) step(res Value, resType resultType, ex *Exception) Value {
   843  	if ex != nil {
   844  		g.delegated = nil
   845  		g.state = genStateCompleted
   846  		panic(ex)
   847  	}
   848  	switch resType {
   849  	case resultYield:
   850  		g.state = genStateSuspendedYield
   851  		return g.val.runtime.createIterResultObject(res, false)
   852  	case resultYieldDelegate:
   853  		g.state = genStateSuspendedYield
   854  		return g.delegate(res)
   855  	case resultYieldRes:
   856  		g.state = genStateSuspendedYieldRes
   857  		return g.val.runtime.createIterResultObject(res, false)
   858  	case resultYieldDelegateRes:
   859  		g.state = genStateSuspendedYieldRes
   860  		return g.delegate(res)
   861  	case resultNormal:
   862  		g.state = genStateCompleted
   863  		return g.val.runtime.createIterResultObject(res, true)
   864  	default:
   865  		panic(g.val.runtime.NewTypeError("Runtime bug: unexpected result type: %v", resType))
   866  	}
   867  }
   868  
   869  func (g *generatorObject) delegate(v Value) Value {
   870  	ex := g.val.runtime.try(func() {
   871  		g.delegated = g.val.runtime.getIterator(v, nil)
   872  	})
   873  	if ex != nil {
   874  		g.delegated = nil
   875  		g.state = genStateCompleted
   876  		return g.step(g.gen.nextThrow(ex))
   877  	}
   878  	return g.next(_undefined)
   879  }
   880  
   881  func (g *generatorObject) tryCallDelegated(fn func() (Value, bool)) (ret Value, done bool) {
   882  	ex := g.val.runtime.try(func() {
   883  		ret, done = fn()
   884  	})
   885  	if ex != nil {
   886  		g.delegated = nil
   887  		g.state = genStateExecuting
   888  		return g.step(g.gen.nextThrow(ex)), false
   889  	}
   890  	return
   891  }
   892  
   893  func (g *generatorObject) callDelegated(method func(FunctionCall) Value, v Value) (Value, bool) {
   894  	res := g.val.runtime.toObject(method(FunctionCall{This: g.delegated.iterator, Arguments: []Value{v}}))
   895  	if iteratorComplete(res) {
   896  		g.delegated = nil
   897  		return iteratorValue(res), true
   898  	}
   899  	return res, false
   900  }
   901  
   902  func (g *generatorObject) next(v Value) Value {
   903  	g.validate()
   904  	if g.state == genStateCompleted {
   905  		return g.val.runtime.createIterResultObject(_undefined, true)
   906  	}
   907  	if g.delegated != nil {
   908  		res, done := g.tryCallDelegated(func() (Value, bool) {
   909  			return g.callDelegated(g.delegated.next, v)
   910  		})
   911  		if !done {
   912  			return res
   913  		} else {
   914  			v = res
   915  		}
   916  	}
   917  	if g.state != genStateSuspendedYieldRes {
   918  		v = nil
   919  	}
   920  	g.state = genStateExecuting
   921  	return g.step(g.gen.next(v))
   922  }
   923  
   924  func (g *generatorObject) throw(v Value) Value {
   925  	g.validate()
   926  	if g.state == genStateSuspendedStart {
   927  		g.state = genStateCompleted
   928  	}
   929  	if g.state == genStateCompleted {
   930  		panic(v)
   931  	}
   932  	if d := g.delegated; d != nil {
   933  		res, done := g.tryCallDelegated(func() (Value, bool) {
   934  			method := toMethod(g.delegated.iterator.self.getStr("throw", nil))
   935  			if method != nil {
   936  				return g.callDelegated(method, v)
   937  			}
   938  			g.delegated = nil
   939  			d.returnIter()
   940  			panic(g.val.runtime.NewTypeError("The iterator does not provide a 'throw' method"))
   941  		})
   942  		if !done {
   943  			return res
   944  		}
   945  		if g.state != genStateSuspendedYieldRes {
   946  			res = nil
   947  		}
   948  		g.state = genStateExecuting
   949  		return g.step(g.gen.next(res))
   950  	}
   951  	g.state = genStateExecuting
   952  	return g.step(g.gen.nextThrow(v))
   953  }
   954  
   955  func (g *generatorObject) _return(v Value) Value {
   956  	g.validate()
   957  	if g.state == genStateSuspendedStart {
   958  		g.state = genStateCompleted
   959  	}
   960  
   961  	if g.state == genStateCompleted {
   962  		return g.val.runtime.createIterResultObject(v, true)
   963  	}
   964  
   965  	if d := g.delegated; d != nil {
   966  		res, done := g.tryCallDelegated(func() (Value, bool) {
   967  			method := toMethod(g.delegated.iterator.self.getStr("return", nil))
   968  			if method != nil {
   969  				return g.callDelegated(method, v)
   970  			}
   971  			g.delegated = nil
   972  			return v, true
   973  		})
   974  		if !done {
   975  			return res
   976  		} else {
   977  			v = res
   978  		}
   979  	}
   980  
   981  	g.state = genStateExecuting
   982  
   983  	g.gen.enterNext()
   984  
   985  	vm := g.gen.vm
   986  	var ex *Exception
   987  	for len(vm.tryStack) > 0 {
   988  		tf := &vm.tryStack[len(vm.tryStack)-1]
   989  		if int(tf.callStackLen) != len(vm.callStack) {
   990  			break
   991  		}
   992  
   993  		if tf.finallyPos >= 0 {
   994  			vm.sp = int(tf.sp)
   995  			vm.stash = tf.stash
   996  			vm.privEnv = tf.privEnv
   997  			ex1 := vm.restoreStacks(tf.iterLen, tf.refLen)
   998  			if ex1 != nil {
   999  				ex = ex1
  1000  				vm.popTryFrame()
  1001  				continue
  1002  			}
  1003  
  1004  			vm.pc = int(tf.finallyPos)
  1005  			tf.catchPos = tryPanicMarker
  1006  			tf.finallyPos = -1
  1007  			tf.finallyRet = -2 // -1 would cause it to continue after leaveFinally
  1008  			for {
  1009  				ex1 := vm.runTryInner()
  1010  				if ex1 != nil {
  1011  					ex = ex1
  1012  					vm.popTryFrame()
  1013  					break
  1014  				}
  1015  				if vm.halted() {
  1016  					break
  1017  				}
  1018  			}
  1019  		} else {
  1020  			vm.popTryFrame()
  1021  		}
  1022  	}
  1023  
  1024  	g.state = genStateCompleted
  1025  
  1026  	vm.popTryFrame()
  1027  
  1028  	if ex == nil {
  1029  		ex = vm.restoreStacks(g.gen.iterStackLen, g.gen.refStackLen)
  1030  	}
  1031  
  1032  	if ex != nil {
  1033  		panic(ex)
  1034  	}
  1035  
  1036  	vm.callStack = vm.callStack[:len(vm.callStack)-1]
  1037  	vm.sp = vm.sb - 1
  1038  	vm.popCtx()
  1039  
  1040  	return g.val.runtime.createIterResultObject(v, true)
  1041  }
  1042  
  1043  func (f *baseJsFuncObject) generatorCall(vmCall func(*vm, int), nArgs int) Value {
  1044  	o := &Object{runtime: f.val.runtime}
  1045  
  1046  	genObj := &generatorObject{
  1047  		baseObject: baseObject{
  1048  			class:      classObject,
  1049  			val:        o,
  1050  			extensible: true,
  1051  		},
  1052  	}
  1053  	o.self = genObj
  1054  	genObj.init(vmCall, nArgs)
  1055  	genObj.prototype = o.runtime.getPrototypeFromCtor(f.val, nil, o.runtime.getGeneratorPrototype())
  1056  	return o
  1057  }
  1058  
  1059  func (f *baseJsFuncObject) generatorVmCall(vmCall func(*vm, int), nArgs int) {
  1060  	vm := f.val.runtime.vm
  1061  	vm.push(f.generatorCall(vmCall, nArgs))
  1062  	vm.pc++
  1063  }
  1064  
  1065  func (f *generatorFuncObject) vmCall(_ *vm, nArgs int) {
  1066  	f.generatorVmCall(f.baseJsFuncObject.vmCall, nArgs)
  1067  }
  1068  
  1069  func (f *generatorFuncObject) Call(call FunctionCall) Value {
  1070  	f.prepareForVmCall(call)
  1071  	return f.generatorCall(f.baseJsFuncObject.vmCall, len(call.Arguments))
  1072  }
  1073  
  1074  func (f *generatorFuncObject) assertCallable() (func(FunctionCall) Value, bool) {
  1075  	return f.Call, true
  1076  }
  1077  
  1078  func (f *generatorFuncObject) export(*objectExportCtx) interface{} {
  1079  	return f.Call
  1080  }
  1081  
  1082  func (f *generatorFuncObject) assertConstructor() func(args []Value, newTarget *Object) *Object {
  1083  	return nil
  1084  }
  1085  
  1086  func (f *generatorMethodFuncObject) vmCall(_ *vm, nArgs int) {
  1087  	f.generatorVmCall(f.methodFuncObject.vmCall, nArgs)
  1088  }
  1089  
  1090  func (f *generatorMethodFuncObject) Call(call FunctionCall) Value {
  1091  	f.prepareForVmCall(call)
  1092  	return f.generatorCall(f.methodFuncObject.vmCall, len(call.Arguments))
  1093  }
  1094  
  1095  func (f *generatorMethodFuncObject) assertCallable() (func(FunctionCall) Value, bool) {
  1096  	return f.Call, true
  1097  }
  1098  
  1099  func (f *generatorMethodFuncObject) export(*objectExportCtx) interface{} {
  1100  	return f.Call
  1101  }