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