github.com/dop251/goja@v0.0.0-20240220182346-e401ed450204/func.go (about) 1 package goja 2 3 import ( 4 "fmt" 5 "reflect" 6 7 "github.com/dop251/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.getReferenceError(), "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 hasInstance(val *Object, v Value) bool { 513 if v, ok := v.(*Object); ok { 514 o := 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 panic(val.runtime.NewTypeError("prototype is not an object")) 527 } 528 } 529 530 return false 531 } 532 533 func (f *baseFuncObject) hasInstance(v Value) bool { 534 return hasInstance(f.val, v) 535 } 536 537 func (f *nativeFuncObject) defaultConstruct(ccall func(ConstructorCall) *Object, args []Value, newTarget *Object) *Object { 538 obj := f.createInstance(newTarget) 539 ret := ccall(ConstructorCall{ 540 This: obj, 541 Arguments: args, 542 NewTarget: newTarget, 543 }) 544 545 if ret != nil { 546 return ret 547 } 548 return obj 549 } 550 551 func (f *nativeFuncObject) assertCallable() (func(FunctionCall) Value, bool) { 552 if f.f != nil { 553 return f.f, true 554 } 555 return nil, false 556 } 557 558 func (f *nativeFuncObject) vmCall(vm *vm, n int) { 559 if f.f != nil { 560 vm.pushCtx() 561 vm.prg = nil 562 vm.sb = vm.sp - n // so that [sb-1] points to the callee 563 ret := f.f(FunctionCall{ 564 Arguments: vm.stack[vm.sp-n : vm.sp], 565 This: vm.stack[vm.sp-n-2], 566 }) 567 if ret == nil { 568 ret = _undefined 569 } 570 vm.stack[vm.sp-n-2] = ret 571 vm.popCtx() 572 } else { 573 vm.stack[vm.sp-n-2] = _undefined 574 } 575 vm.sp -= n + 1 576 vm.pc++ 577 } 578 579 func (f *nativeFuncObject) assertConstructor() func(args []Value, newTarget *Object) *Object { 580 return f.construct 581 } 582 583 func (f *boundFuncObject) hasInstance(v Value) bool { 584 return instanceOfOperator(v, f.wrapped) 585 } 586 587 func (f *baseJsFuncObject) prepareForVmCall(call FunctionCall) { 588 vm := f.val.runtime.vm 589 args := call.Arguments 590 vm.stack.expand(vm.sp + len(args) + 1) 591 vm.stack[vm.sp] = call.This 592 vm.sp++ 593 vm.stack[vm.sp] = f.val 594 vm.sp++ 595 for _, arg := range args { 596 if arg != nil { 597 vm.stack[vm.sp] = arg 598 } else { 599 vm.stack[vm.sp] = _undefined 600 } 601 vm.sp++ 602 } 603 } 604 605 func (f *baseJsFuncObject) asyncCall(call FunctionCall, vmCall func(*vm, int)) Value { 606 f.prepareForVmCall(call) 607 ar := &asyncRunner{ 608 f: f.val, 609 vmCall: vmCall, 610 } 611 ar.start(len(call.Arguments)) 612 return ar.promiseCap.promise 613 } 614 615 func (f *asyncFuncObject) Call(call FunctionCall) Value { 616 return f.asyncCall(call, f.baseJsFuncObject.vmCall) 617 } 618 619 func (f *asyncFuncObject) assertCallable() (func(FunctionCall) Value, bool) { 620 return f.Call, true 621 } 622 623 func (f *asyncFuncObject) export(*objectExportCtx) interface{} { 624 return f.Call 625 } 626 627 func (f *asyncArrowFuncObject) Call(call FunctionCall) Value { 628 return f.asyncCall(call, f.arrowFuncObject.vmCall) 629 } 630 631 func (f *asyncArrowFuncObject) assertCallable() (func(FunctionCall) Value, bool) { 632 return f.Call, true 633 } 634 635 func (f *asyncArrowFuncObject) export(*objectExportCtx) interface{} { 636 return f.Call 637 } 638 639 func (f *asyncArrowFuncObject) vmCall(vm *vm, n int) { 640 f.asyncVmCall(vm, n, f.arrowFuncObject.vmCall) 641 } 642 643 func (f *asyncMethodFuncObject) Call(call FunctionCall) Value { 644 return f.asyncCall(call, f.methodFuncObject.vmCall) 645 } 646 647 func (f *asyncMethodFuncObject) assertCallable() (func(FunctionCall) Value, bool) { 648 return f.Call, true 649 } 650 651 func (f *asyncMethodFuncObject) export(ctx *objectExportCtx) interface{} { 652 return f.Call 653 } 654 655 func (f *asyncMethodFuncObject) vmCall(vm *vm, n int) { 656 f.asyncVmCall(vm, n, f.methodFuncObject.vmCall) 657 } 658 659 func (f *baseJsFuncObject) asyncVmCall(vm *vm, n int, vmCall func(*vm, int)) { 660 ar := &asyncRunner{ 661 f: f.val, 662 vmCall: vmCall, 663 } 664 ar.start(n) 665 vm.push(ar.promiseCap.promise) 666 vm.pc++ 667 } 668 669 func (f *asyncFuncObject) vmCall(vm *vm, n int) { 670 f.asyncVmCall(vm, n, f.baseJsFuncObject.vmCall) 671 } 672 673 type asyncRunner struct { 674 gen generator 675 promiseCap *promiseCapability 676 f *Object 677 vmCall func(*vm, int) 678 } 679 680 func (ar *asyncRunner) onFulfilled(call FunctionCall) Value { 681 ar.gen.vm.curAsyncRunner = ar 682 defer func() { 683 ar.gen.vm.curAsyncRunner = nil 684 }() 685 arg := call.Argument(0) 686 res, resType, ex := ar.gen.next(arg) 687 ar.step(res, resType == resultNormal, ex) 688 return _undefined 689 } 690 691 func (ar *asyncRunner) onRejected(call FunctionCall) Value { 692 ar.gen.vm.curAsyncRunner = ar 693 defer func() { 694 ar.gen.vm.curAsyncRunner = nil 695 }() 696 reason := call.Argument(0) 697 res, resType, ex := ar.gen.nextThrow(reason) 698 ar.step(res, resType == resultNormal, ex) 699 return _undefined 700 } 701 702 func (ar *asyncRunner) step(res Value, done bool, ex *Exception) { 703 r := ar.f.runtime 704 if done || ex != nil { 705 if ex == nil { 706 ar.promiseCap.resolve(res) 707 } else { 708 ar.promiseCap.reject(ex.val) 709 } 710 return 711 } 712 713 // await 714 promise := r.promiseResolve(r.getPromise(), res) 715 promise.self.(*Promise).addReactions(&promiseReaction{ 716 typ: promiseReactionFulfill, 717 handler: &jobCallback{callback: ar.onFulfilled}, 718 asyncRunner: ar, 719 }, &promiseReaction{ 720 typ: promiseReactionReject, 721 handler: &jobCallback{callback: ar.onRejected}, 722 asyncRunner: ar, 723 }) 724 } 725 726 func (ar *asyncRunner) start(nArgs int) { 727 r := ar.f.runtime 728 ar.gen.vm = r.vm 729 ar.promiseCap = r.newPromiseCapability(r.getPromise()) 730 sp := r.vm.sp 731 ar.gen.enter() 732 ar.vmCall(r.vm, nArgs) 733 res, resType, ex := ar.gen.step() 734 ar.step(res, resType == resultNormal, ex) 735 if ex != nil { 736 r.vm.sp = sp - nArgs - 2 737 } 738 r.vm.popTryFrame() 739 r.vm.popCtx() 740 } 741 742 type generator struct { 743 ctx execCtx 744 vm *vm 745 746 tryStackLen, iterStackLen, refStackLen uint32 747 } 748 749 func (g *generator) storeLengths() { 750 g.tryStackLen, g.iterStackLen, g.refStackLen = uint32(len(g.vm.tryStack)), uint32(len(g.vm.iterStack)), uint32(len(g.vm.refStack)) 751 } 752 753 func (g *generator) enter() { 754 g.vm.pushCtx() 755 g.vm.pushTryFrame(tryPanicMarker, -1) 756 g.vm.prg, g.vm.sb, g.vm.pc = nil, -1, -2 // so that vm.run() halts after ret 757 g.storeLengths() 758 } 759 760 func (g *generator) step() (res Value, resultType resultType, ex *Exception) { 761 for { 762 ex = g.vm.runTryInner() 763 if ex != nil { 764 return 765 } 766 if g.vm.halted() { 767 break 768 } 769 } 770 res = g.vm.pop() 771 if ym, ok := res.(*yieldMarker); ok { 772 resultType = ym.resultType 773 g.ctx = execCtx{} 774 g.vm.pc = -g.vm.pc + 1 775 if res != yieldEmpty { 776 res = g.vm.pop() 777 } else { 778 res = nil 779 } 780 g.vm.suspend(&g.ctx, g.tryStackLen, g.iterStackLen, g.refStackLen) 781 g.vm.sp = g.vm.sb - 1 782 g.vm.callStack = g.vm.callStack[:len(g.vm.callStack)-1] // remove the frame with pc == -2, as ret would do 783 } 784 return 785 } 786 787 func (g *generator) enterNext() { 788 g.vm.pushCtx() 789 g.vm.pushTryFrame(tryPanicMarker, -1) 790 g.vm.callStack = append(g.vm.callStack, context{pc: -2}) // extra frame so that vm.run() halts after ret 791 g.storeLengths() 792 g.vm.resume(&g.ctx) 793 } 794 795 func (g *generator) next(v Value) (Value, resultType, *Exception) { 796 g.enterNext() 797 if v != nil { 798 g.vm.push(v) 799 } 800 res, done, ex := g.step() 801 g.vm.popTryFrame() 802 g.vm.popCtx() 803 return res, done, ex 804 } 805 806 func (g *generator) nextThrow(v interface{}) (Value, resultType, *Exception) { 807 g.enterNext() 808 ex := g.vm.handleThrow(v) 809 if ex != nil { 810 g.vm.popTryFrame() 811 g.vm.popCtx() 812 return nil, resultNormal, ex 813 } 814 815 res, resType, ex := g.step() 816 g.vm.popTryFrame() 817 g.vm.popCtx() 818 return res, resType, ex 819 } 820 821 func (g *generatorObject) init(vmCall func(*vm, int), nArgs int) { 822 g.baseObject.init() 823 vm := g.val.runtime.vm 824 g.gen.vm = vm 825 826 g.gen.enter() 827 vmCall(vm, nArgs) 828 829 _, _, ex := g.gen.step() 830 831 vm.popTryFrame() 832 if ex != nil { 833 panic(ex) 834 } 835 836 g.state = genStateSuspendedStart 837 vm.popCtx() 838 } 839 840 func (g *generatorObject) validate() { 841 if g.state == genStateExecuting { 842 panic(g.val.runtime.NewTypeError("Illegal generator state")) 843 } 844 } 845 846 func (g *generatorObject) step(res Value, resType resultType, ex *Exception) Value { 847 if ex != nil { 848 g.delegated = nil 849 g.state = genStateCompleted 850 panic(ex) 851 } 852 switch resType { 853 case resultYield: 854 g.state = genStateSuspendedYield 855 return g.val.runtime.createIterResultObject(res, false) 856 case resultYieldDelegate: 857 g.state = genStateSuspendedYield 858 return g.delegate(res) 859 case resultYieldRes: 860 g.state = genStateSuspendedYieldRes 861 return g.val.runtime.createIterResultObject(res, false) 862 case resultYieldDelegateRes: 863 g.state = genStateSuspendedYieldRes 864 return g.delegate(res) 865 case resultNormal: 866 g.state = genStateCompleted 867 return g.val.runtime.createIterResultObject(res, true) 868 default: 869 panic(g.val.runtime.NewTypeError("Runtime bug: unexpected result type: %v", resType)) 870 } 871 } 872 873 func (g *generatorObject) delegate(v Value) Value { 874 ex := g.val.runtime.try(func() { 875 g.delegated = g.val.runtime.getIterator(v, nil) 876 }) 877 if ex != nil { 878 g.delegated = nil 879 g.state = genStateCompleted 880 return g.step(g.gen.nextThrow(ex)) 881 } 882 return g.next(_undefined) 883 } 884 885 func (g *generatorObject) tryCallDelegated(fn func() (Value, bool)) (ret Value, done bool) { 886 ex := g.val.runtime.try(func() { 887 ret, done = fn() 888 }) 889 if ex != nil { 890 g.delegated = nil 891 g.state = genStateExecuting 892 return g.step(g.gen.nextThrow(ex)), false 893 } 894 return 895 } 896 897 func (g *generatorObject) callDelegated(method func(FunctionCall) Value, v Value) (Value, bool) { 898 res := g.val.runtime.toObject(method(FunctionCall{This: g.delegated.iterator, Arguments: []Value{v}})) 899 if iteratorComplete(res) { 900 g.delegated = nil 901 return iteratorValue(res), true 902 } 903 return res, false 904 } 905 906 func (g *generatorObject) next(v Value) Value { 907 g.validate() 908 if g.state == genStateCompleted { 909 return g.val.runtime.createIterResultObject(_undefined, true) 910 } 911 if g.delegated != nil { 912 res, done := g.tryCallDelegated(func() (Value, bool) { 913 return g.callDelegated(g.delegated.next, v) 914 }) 915 if !done { 916 return res 917 } else { 918 v = res 919 } 920 } 921 if g.state != genStateSuspendedYieldRes { 922 v = nil 923 } 924 g.state = genStateExecuting 925 return g.step(g.gen.next(v)) 926 } 927 928 func (g *generatorObject) throw(v Value) Value { 929 g.validate() 930 if g.state == genStateSuspendedStart { 931 g.state = genStateCompleted 932 } 933 if g.state == genStateCompleted { 934 panic(v) 935 } 936 if d := g.delegated; d != nil { 937 res, done := g.tryCallDelegated(func() (Value, bool) { 938 method := toMethod(g.delegated.iterator.self.getStr("throw", nil)) 939 if method != nil { 940 return g.callDelegated(method, v) 941 } 942 g.delegated = nil 943 d.returnIter() 944 panic(g.val.runtime.NewTypeError("The iterator does not provide a 'throw' method")) 945 }) 946 if !done { 947 return res 948 } 949 if g.state != genStateSuspendedYieldRes { 950 res = nil 951 } 952 g.state = genStateExecuting 953 return g.step(g.gen.next(res)) 954 } 955 g.state = genStateExecuting 956 return g.step(g.gen.nextThrow(v)) 957 } 958 959 func (g *generatorObject) _return(v Value) Value { 960 g.validate() 961 if g.state == genStateSuspendedStart { 962 g.state = genStateCompleted 963 } 964 965 if g.state == genStateCompleted { 966 return g.val.runtime.createIterResultObject(v, true) 967 } 968 969 if d := g.delegated; d != nil { 970 res, done := g.tryCallDelegated(func() (Value, bool) { 971 method := toMethod(g.delegated.iterator.self.getStr("return", nil)) 972 if method != nil { 973 return g.callDelegated(method, v) 974 } 975 g.delegated = nil 976 return v, true 977 }) 978 if !done { 979 return res 980 } else { 981 v = res 982 } 983 } 984 985 g.state = genStateExecuting 986 987 g.gen.enterNext() 988 989 vm := g.gen.vm 990 var ex *Exception 991 for len(vm.tryStack) > 0 { 992 tf := &vm.tryStack[len(vm.tryStack)-1] 993 if int(tf.callStackLen) != len(vm.callStack) { 994 break 995 } 996 997 if tf.finallyPos >= 0 { 998 vm.sp = int(tf.sp) 999 vm.stash = tf.stash 1000 vm.privEnv = tf.privEnv 1001 ex1 := vm.restoreStacks(tf.iterLen, tf.refLen) 1002 if ex1 != nil { 1003 ex = ex1 1004 vm.popTryFrame() 1005 continue 1006 } 1007 1008 vm.pc = int(tf.finallyPos) 1009 tf.catchPos = tryPanicMarker 1010 tf.finallyPos = -1 1011 tf.finallyRet = -2 // -1 would cause it to continue after leaveFinally 1012 for { 1013 ex1 := vm.runTryInner() 1014 if ex1 != nil { 1015 ex = ex1 1016 vm.popTryFrame() 1017 break 1018 } 1019 if vm.halted() { 1020 break 1021 } 1022 } 1023 } else { 1024 vm.popTryFrame() 1025 } 1026 } 1027 1028 g.state = genStateCompleted 1029 1030 vm.popTryFrame() 1031 1032 if ex == nil { 1033 ex = vm.restoreStacks(g.gen.iterStackLen, g.gen.refStackLen) 1034 } 1035 1036 if ex != nil { 1037 panic(ex) 1038 } 1039 1040 vm.callStack = vm.callStack[:len(vm.callStack)-1] 1041 vm.sp = vm.sb - 1 1042 vm.popCtx() 1043 1044 return g.val.runtime.createIterResultObject(v, true) 1045 } 1046 1047 func (f *baseJsFuncObject) generatorCall(vmCall func(*vm, int), nArgs int) Value { 1048 o := &Object{runtime: f.val.runtime} 1049 1050 genObj := &generatorObject{ 1051 baseObject: baseObject{ 1052 class: classObject, 1053 val: o, 1054 extensible: true, 1055 }, 1056 } 1057 o.self = genObj 1058 genObj.init(vmCall, nArgs) 1059 genObj.prototype = o.runtime.getPrototypeFromCtor(f.val, nil, o.runtime.getGeneratorPrototype()) 1060 return o 1061 } 1062 1063 func (f *baseJsFuncObject) generatorVmCall(vmCall func(*vm, int), nArgs int) { 1064 vm := f.val.runtime.vm 1065 vm.push(f.generatorCall(vmCall, nArgs)) 1066 vm.pc++ 1067 } 1068 1069 func (f *generatorFuncObject) vmCall(_ *vm, nArgs int) { 1070 f.generatorVmCall(f.baseJsFuncObject.vmCall, nArgs) 1071 } 1072 1073 func (f *generatorFuncObject) Call(call FunctionCall) Value { 1074 f.prepareForVmCall(call) 1075 return f.generatorCall(f.baseJsFuncObject.vmCall, len(call.Arguments)) 1076 } 1077 1078 func (f *generatorFuncObject) assertCallable() (func(FunctionCall) Value, bool) { 1079 return f.Call, true 1080 } 1081 1082 func (f *generatorFuncObject) export(*objectExportCtx) interface{} { 1083 return f.Call 1084 } 1085 1086 func (f *generatorFuncObject) assertConstructor() func(args []Value, newTarget *Object) *Object { 1087 return nil 1088 } 1089 1090 func (f *generatorMethodFuncObject) vmCall(_ *vm, nArgs int) { 1091 f.generatorVmCall(f.methodFuncObject.vmCall, nArgs) 1092 } 1093 1094 func (f *generatorMethodFuncObject) Call(call FunctionCall) Value { 1095 f.prepareForVmCall(call) 1096 return f.generatorCall(f.methodFuncObject.vmCall, len(call.Arguments)) 1097 } 1098 1099 func (f *generatorMethodFuncObject) assertCallable() (func(FunctionCall) Value, bool) { 1100 return f.Call, true 1101 } 1102 1103 func (f *generatorMethodFuncObject) export(*objectExportCtx) interface{} { 1104 return f.Call 1105 }