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