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