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