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 }