1package goja 2 3import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "github.com/dop251/goja/file" 8 "go/ast" 9 "hash/maphash" 10 "math" 11 "math/bits" 12 "math/rand" 13 "reflect" 14 "runtime" 15 "strconv" 16 "time" 17 18 "golang.org/x/text/collate" 19 20 js_ast "github.com/dop251/goja/ast" 21 "github.com/dop251/goja/parser" 22 "github.com/dop251/goja/unistring" 23) 24 25const ( 26 sqrt1_2 float64 = math.Sqrt2 / 2 27 28 deoptimiseRegexp = false 29) 30 31var ( 32 typeCallable = reflect.TypeOf(Callable(nil)) 33 typeValue = reflect.TypeOf((*Value)(nil)).Elem() 34 typeObject = reflect.TypeOf((*Object)(nil)) 35 typeTime = reflect.TypeOf(time.Time{}) 36) 37 38type iterationKind int 39 40const ( 41 iterationKindKey iterationKind = iota 42 iterationKindValue 43 iterationKindKeyValue 44) 45 46type global struct { 47 stash stash 48 varNames map[unistring.String]struct{} 49 50 Object *Object 51 Array *Object 52 Function *Object 53 String *Object 54 Number *Object 55 Boolean *Object 56 RegExp *Object 57 Date *Object 58 Symbol *Object 59 Proxy *Object 60 61 ArrayBuffer *Object 62 DataView *Object 63 TypedArray *Object 64 Uint8Array *Object 65 Uint8ClampedArray *Object 66 Int8Array *Object 67 Uint16Array *Object 68 Int16Array *Object 69 Uint32Array *Object 70 Int32Array *Object 71 Float32Array *Object 72 Float64Array *Object 73 74 WeakSet *Object 75 WeakMap *Object 76 Map *Object 77 Set *Object 78 79 Error *Object 80 TypeError *Object 81 ReferenceError *Object 82 SyntaxError *Object 83 RangeError *Object 84 EvalError *Object 85 URIError *Object 86 87 GoError *Object 88 89 ObjectPrototype *Object 90 ArrayPrototype *Object 91 NumberPrototype *Object 92 StringPrototype *Object 93 BooleanPrototype *Object 94 FunctionPrototype *Object 95 RegExpPrototype *Object 96 DatePrototype *Object 97 SymbolPrototype *Object 98 99 ArrayBufferPrototype *Object 100 DataViewPrototype *Object 101 TypedArrayPrototype *Object 102 WeakSetPrototype *Object 103 WeakMapPrototype *Object 104 MapPrototype *Object 105 SetPrototype *Object 106 107 IteratorPrototype *Object 108 ArrayIteratorPrototype *Object 109 MapIteratorPrototype *Object 110 SetIteratorPrototype *Object 111 StringIteratorPrototype *Object 112 RegExpStringIteratorPrototype *Object 113 114 ErrorPrototype *Object 115 TypeErrorPrototype *Object 116 SyntaxErrorPrototype *Object 117 RangeErrorPrototype *Object 118 ReferenceErrorPrototype *Object 119 EvalErrorPrototype *Object 120 URIErrorPrototype *Object 121 122 GoErrorPrototype *Object 123 124 Eval *Object 125 126 thrower *Object 127 throwerProperty Value 128 129 stdRegexpProto *guardedObject 130 131 weakSetAdder *Object 132 weakMapAdder *Object 133 mapAdder *Object 134 setAdder *Object 135 arrayValues *Object 136 arrayToString *Object 137} 138 139type Flag int 140 141const ( 142 FLAG_NOT_SET Flag = iota 143 FLAG_FALSE 144 FLAG_TRUE 145) 146 147func (f Flag) Bool() bool { 148 return f == FLAG_TRUE 149} 150 151func ToFlag(b bool) Flag { 152 if b { 153 return FLAG_TRUE 154 } 155 return FLAG_FALSE 156} 157 158type RandSource func() float64 159 160type Now func() time.Time 161 162type Runtime struct { 163 global global 164 globalObject *Object 165 stringSingleton *stringObject 166 rand RandSource 167 now Now 168 _collator *collate.Collator 169 parserOptions []parser.Option 170 171 symbolRegistry map[unistring.String]*Symbol 172 173 typeInfoCache map[reflect.Type]*reflectTypeInfo 174 fieldNameMapper FieldNameMapper 175 176 vm *vm 177 hash *maphash.Hash 178 idSeq uint64 179} 180 181type StackFrame struct { 182 prg *Program 183 funcName unistring.String 184 pc int 185} 186 187func (f *StackFrame) SrcName() string { 188 if f.prg == nil { 189 return "<native>" 190 } 191 return f.prg.src.Name() 192} 193 194func (f *StackFrame) FuncName() string { 195 if f.funcName == "" && f.prg == nil { 196 return "<native>" 197 } 198 if f.funcName == "" { 199 return "<anonymous>" 200 } 201 return f.funcName.String() 202} 203 204func (f *StackFrame) Position() file.Position { 205 if f.prg == nil || f.prg.src == nil { 206 return file.Position{} 207 } 208 return f.prg.src.Position(f.prg.sourceOffset(f.pc)) 209} 210 211func (f *StackFrame) Write(b *bytes.Buffer) { 212 if f.prg != nil { 213 if n := f.prg.funcName; n != "" { 214 b.WriteString(n.String()) 215 b.WriteString(" (") 216 } 217 p := f.Position() 218 if p.Filename != "" { 219 b.WriteString(p.Filename) 220 } else { 221 b.WriteString("<eval>") 222 } 223 b.WriteByte(':') 224 b.WriteString(strconv.Itoa(p.Line)) 225 b.WriteByte(':') 226 b.WriteString(strconv.Itoa(p.Column)) 227 b.WriteByte('(') 228 b.WriteString(strconv.Itoa(f.pc)) 229 b.WriteByte(')') 230 if f.prg.funcName != "" { 231 b.WriteByte(')') 232 } 233 } else { 234 if f.funcName != "" { 235 b.WriteString(f.funcName.String()) 236 b.WriteString(" (") 237 } 238 b.WriteString("native") 239 if f.funcName != "" { 240 b.WriteByte(')') 241 } 242 } 243} 244 245type Exception struct { 246 val Value 247 stack []StackFrame 248} 249 250type uncatchableException struct { 251 stack *[]StackFrame 252 err error 253} 254 255type InterruptedError struct { 256 Exception 257 iface interface{} 258} 259 260type StackOverflowError struct { 261 Exception 262} 263 264func (e *InterruptedError) Value() interface{} { 265 return e.iface 266} 267 268func (e *InterruptedError) String() string { 269 if e == nil { 270 return "<nil>" 271 } 272 var b bytes.Buffer 273 if e.iface != nil { 274 b.WriteString(fmt.Sprint(e.iface)) 275 b.WriteByte('\n') 276 } 277 e.writeFullStack(&b) 278 return b.String() 279} 280 281func (e *InterruptedError) Error() string { 282 if e == nil || e.iface == nil { 283 return "<nil>" 284 } 285 var b bytes.Buffer 286 b.WriteString(fmt.Sprint(e.iface)) 287 e.writeShortStack(&b) 288 return b.String() 289} 290 291func (e *Exception) writeFullStack(b *bytes.Buffer) { 292 for _, frame := range e.stack { 293 b.WriteString("\tat ") 294 frame.Write(b) 295 b.WriteByte('\n') 296 } 297} 298 299func (e *Exception) writeShortStack(b *bytes.Buffer) { 300 if len(e.stack) > 0 && (e.stack[0].prg != nil || e.stack[0].funcName != "") { 301 b.WriteString(" at ") 302 e.stack[0].Write(b) 303 } 304} 305 306func (e *Exception) String() string { 307 if e == nil { 308 return "<nil>" 309 } 310 var b bytes.Buffer 311 if e.val != nil { 312 b.WriteString(e.val.String()) 313 b.WriteByte('\n') 314 } 315 e.writeFullStack(&b) 316 return b.String() 317} 318 319func (e *Exception) Error() string { 320 if e == nil || e.val == nil { 321 return "<nil>" 322 } 323 var b bytes.Buffer 324 b.WriteString(e.val.String()) 325 e.writeShortStack(&b) 326 return b.String() 327} 328 329func (e *Exception) Value() Value { 330 return e.val 331} 332 333func (r *Runtime) addToGlobal(name string, value Value) { 334 r.globalObject.self._putProp(unistring.String(name), value, true, false, true) 335} 336 337func (r *Runtime) createIterProto(val *Object) objectImpl { 338 o := newBaseObjectObj(val, r.global.ObjectPrototype, classObject) 339 340 o._putSym(SymIterator, valueProp(r.newNativeFunc(r.returnThis, nil, "[Symbol.iterator]", nil, 0), true, false, true)) 341 return o 342} 343 344func (r *Runtime) init() { 345 r.rand = rand.Float64 346 r.now = time.Now 347 r.global.ObjectPrototype = r.newBaseObject(nil, classObject).val 348 r.globalObject = r.NewObject() 349 350 r.vm = &vm{ 351 r: r, 352 } 353 r.vm.init() 354 355 funcProto := r.newNativeFunc(func(FunctionCall) Value { 356 return _undefined 357 }, nil, " ", nil, 0) 358 r.global.FunctionPrototype = funcProto 359 funcProtoObj := funcProto.self.(*nativeFuncObject) 360 361 r.global.IteratorPrototype = r.newLazyObject(r.createIterProto) 362 363 r.initObject() 364 r.initFunction() 365 r.initArray() 366 r.initString() 367 r.initGlobalObject() 368 r.initNumber() 369 r.initRegExp() 370 r.initDate() 371 r.initBoolean() 372 r.initProxy() 373 r.initReflect() 374 375 r.initErrors() 376 377 r.global.Eval = r.newNativeFunc(r.builtin_eval, nil, "eval", nil, 1) 378 r.addToGlobal("eval", r.global.Eval) 379 380 r.initMath() 381 r.initJSON() 382 383 r.initTypedArrays() 384 r.initSymbol() 385 r.initWeakSet() 386 r.initWeakMap() 387 r.initMap() 388 r.initSet() 389 390 r.global.thrower = r.newNativeFunc(r.builtin_thrower, nil, "thrower", nil, 0) 391 r.global.throwerProperty = &valueProperty{ 392 getterFunc: r.global.thrower, 393 setterFunc: r.global.thrower, 394 accessor: true, 395 } 396 397 funcProtoObj._put("caller", r.global.throwerProperty) 398 funcProtoObj._put("arguments", r.global.throwerProperty) 399} 400 401func (r *Runtime) typeErrorResult(throw bool, args ...interface{}) { 402 if throw { 403 panic(r.NewTypeError(args...)) 404 } 405} 406 407func (r *Runtime) newError(typ *Object, format string, args ...interface{}) Value { 408 msg := fmt.Sprintf(format, args...) 409 return r.builtin_new(typ, []Value{newStringValue(msg)}) 410} 411 412func (r *Runtime) throwReferenceError(name unistring.String) { 413 panic(r.newError(r.global.ReferenceError, "%s is not defined", name)) 414} 415 416func (r *Runtime) newSyntaxError(msg string, offset int) Value { 417 return r.builtin_new(r.global.SyntaxError, []Value{newStringValue(msg)}) 418} 419 420func newBaseObjectObj(obj, proto *Object, class string) *baseObject { 421 o := &baseObject{ 422 class: class, 423 val: obj, 424 extensible: true, 425 prototype: proto, 426 } 427 obj.self = o 428 o.init() 429 return o 430} 431 432func newGuardedObj(proto *Object, class string) *guardedObject { 433 return &guardedObject{ 434 baseObject: baseObject{ 435 class: class, 436 extensible: true, 437 prototype: proto, 438 }, 439 } 440} 441 442func (r *Runtime) newBaseObject(proto *Object, class string) (o *baseObject) { 443 v := &Object{runtime: r} 444 return newBaseObjectObj(v, proto, class) 445} 446 447func (r *Runtime) newGuardedObject(proto *Object, class string) (o *guardedObject) { 448 v := &Object{runtime: r} 449 o = newGuardedObj(proto, class) 450 v.self = o 451 o.val = v 452 o.init() 453 return 454} 455 456func (r *Runtime) NewObject() (v *Object) { 457 return r.newBaseObject(r.global.ObjectPrototype, classObject).val 458} 459 460// CreateObject creates an object with given prototype. Equivalent of Object.create(proto). 461func (r *Runtime) CreateObject(proto *Object) *Object { 462 return r.newBaseObject(proto, classObject).val 463} 464 465func (r *Runtime) NewArray(items ...interface{}) *Object { 466 values := make([]Value, len(items)) 467 for i, item := range items { 468 values[i] = r.ToValue(item) 469 } 470 return r.newArrayValues(values) 471} 472 473func (r *Runtime) NewTypeError(args ...interface{}) *Object { 474 msg := "" 475 if len(args) > 0 { 476 f, _ := args[0].(string) 477 msg = fmt.Sprintf(f, args[1:]...) 478 } 479 return r.builtin_new(r.global.TypeError, []Value{newStringValue(msg)}) 480} 481 482func (r *Runtime) NewGoError(err error) *Object { 483 e := r.newError(r.global.GoError, err.Error()).(*Object) 484 e.Set("value", err) 485 return e 486} 487 488func (r *Runtime) newFunc(name unistring.String, len int, strict bool) (f *funcObject) { 489 v := &Object{runtime: r} 490 491 f = &funcObject{} 492 f.class = classFunction 493 f.val = v 494 f.extensible = true 495 f.strict = strict 496 v.self = f 497 f.prototype = r.global.FunctionPrototype 498 f.init(name, len) 499 return 500} 501 502func (r *Runtime) newArrowFunc(name unistring.String, len int, strict bool) (f *arrowFuncObject) { 503 v := &Object{runtime: r} 504 505 f = &arrowFuncObject{} 506 f.class = classFunction 507 f.val = v 508 f.extensible = true 509 f.strict = strict 510 511 vm := r.vm 512 var this Value 513 if vm.sb >= 0 { 514 this = vm.stack[vm.sb] 515 } else { 516 this = vm.r.globalObject 517 } 518 519 f.this = this 520 f.newTarget = vm.newTarget 521 v.self = f 522 f.prototype = r.global.FunctionPrototype 523 f.init(name, len) 524 return 525} 526 527func (r *Runtime) newNativeFuncObj(v *Object, call func(FunctionCall) Value, construct func(args []Value, proto *Object) *Object, name unistring.String, proto *Object, length int) *nativeFuncObject { 528 f := &nativeFuncObject{ 529 baseFuncObject: baseFuncObject{ 530 baseObject: baseObject{ 531 class: classFunction, 532 val: v, 533 extensible: true, 534 prototype: r.global.FunctionPrototype, 535 }, 536 }, 537 f: call, 538 construct: r.wrapNativeConstruct(construct, proto), 539 } 540 v.self = f 541 f.init(name, length) 542 if proto != nil { 543 f._putProp("prototype", proto, false, false, false) 544 } 545 return f 546} 547 548func (r *Runtime) newNativeConstructor(call func(ConstructorCall) *Object, name unistring.String, length int) *Object { 549 v := &Object{runtime: r} 550 551 f := &nativeFuncObject{ 552 baseFuncObject: baseFuncObject{ 553 baseObject: baseObject{ 554 class: classFunction, 555 val: v, 556 extensible: true, 557 prototype: r.global.FunctionPrototype, 558 }, 559 }, 560 } 561 562 f.f = func(c FunctionCall) Value { 563 thisObj, _ := c.This.(*Object) 564 if thisObj != nil { 565 res := call(ConstructorCall{ 566 This: thisObj, 567 Arguments: c.Arguments, 568 }) 569 if res == nil { 570 return _undefined 571 } 572 return res 573 } 574 return f.defaultConstruct(call, c.Arguments, nil) 575 } 576 577 f.construct = func(args []Value, newTarget *Object) *Object { 578 return f.defaultConstruct(call, args, newTarget) 579 } 580 581 v.self = f 582 f.init(name, length) 583 584 proto := r.NewObject() 585 proto.self._putProp("constructor", v, true, false, true) 586 f._putProp("prototype", proto, true, false, false) 587 588 return v 589} 590 591func (r *Runtime) newNativeConstructOnly(v *Object, ctor func(args []Value, newTarget *Object) *Object, defaultProto *Object, name unistring.String, length int) *nativeFuncObject { 592 if v == nil { 593 v = &Object{runtime: r} 594 } 595 596 f := &nativeFuncObject{ 597 baseFuncObject: baseFuncObject{ 598 baseObject: baseObject{ 599 class: classFunction, 600 val: v, 601 extensible: true, 602 prototype: r.global.FunctionPrototype, 603 }, 604 }, 605 f: func(call FunctionCall) Value { 606 return ctor(call.Arguments, nil) 607 }, 608 construct: func(args []Value, newTarget *Object) *Object { 609 if newTarget == nil { 610 newTarget = v 611 } 612 return ctor(args, newTarget) 613 }, 614 } 615 v.self = f 616 f.init(name, length) 617 if defaultProto != nil { 618 f._putProp("prototype", defaultProto, false, false, false) 619 } 620 621 return f 622} 623 624func (r *Runtime) newNativeFunc(call func(FunctionCall) Value, construct func(args []Value, proto *Object) *Object, name unistring.String, proto *Object, length int) *Object { 625 v := &Object{runtime: r} 626 627 f := &nativeFuncObject{ 628 baseFuncObject: baseFuncObject{ 629 baseObject: baseObject{ 630 class: classFunction, 631 val: v, 632 extensible: true, 633 prototype: r.global.FunctionPrototype, 634 }, 635 }, 636 f: call, 637 construct: r.wrapNativeConstruct(construct, proto), 638 } 639 v.self = f 640 f.init(name, length) 641 if proto != nil { 642 f._putProp("prototype", proto, false, false, false) 643 proto.self._putProp("constructor", v, true, false, true) 644 } 645 return v 646} 647 648func (r *Runtime) newNativeFuncConstructObj(v *Object, construct func(args []Value, proto *Object) *Object, name unistring.String, proto *Object, length int) *nativeFuncObject { 649 f := &nativeFuncObject{ 650 baseFuncObject: baseFuncObject{ 651 baseObject: baseObject{ 652 class: classFunction, 653 val: v, 654 extensible: true, 655 prototype: r.global.FunctionPrototype, 656 }, 657 }, 658 f: r.constructToCall(construct, proto), 659 construct: r.wrapNativeConstruct(construct, proto), 660 } 661 662 f.init(name, length) 663 if proto != nil { 664 f._putProp("prototype", proto, false, false, false) 665 } 666 return f 667} 668 669func (r *Runtime) newNativeFuncConstruct(construct func(args []Value, proto *Object) *Object, name unistring.String, prototype *Object, length int) *Object { 670 return r.newNativeFuncConstructProto(construct, name, prototype, r.global.FunctionPrototype, length) 671} 672 673func (r *Runtime) newNativeFuncConstructProto(construct func(args []Value, proto *Object) *Object, name unistring.String, prototype, proto *Object, length int) *Object { 674 v := &Object{runtime: r} 675 676 f := &nativeFuncObject{} 677 f.class = classFunction 678 f.val = v 679 f.extensible = true 680 v.self = f 681 f.prototype = proto 682 f.f = r.constructToCall(construct, prototype) 683 f.construct = r.wrapNativeConstruct(construct, prototype) 684 f.init(name, length) 685 if prototype != nil { 686 f._putProp("prototype", prototype, false, false, false) 687 prototype.self._putProp("constructor", v, true, false, true) 688 } 689 return v 690} 691 692func (r *Runtime) newPrimitiveObject(value Value, proto *Object, class string) *Object { 693 v := &Object{runtime: r} 694 695 o := &primitiveValueObject{} 696 o.class = class 697 o.val = v 698 o.extensible = true 699 v.self = o 700 o.prototype = proto 701 o.pValue = value 702 o.init() 703 return v 704} 705 706func (r *Runtime) builtin_Number(call FunctionCall) Value { 707 if len(call.Arguments) > 0 { 708 return call.Arguments[0].ToNumber() 709 } else { 710 return valueInt(0) 711 } 712} 713 714func (r *Runtime) builtin_newNumber(args []Value, proto *Object) *Object { 715 var v Value 716 if len(args) > 0 { 717 v = args[0].ToNumber() 718 } else { 719 v = intToValue(0) 720 } 721 return r.newPrimitiveObject(v, proto, classNumber) 722} 723 724func (r *Runtime) builtin_Boolean(call FunctionCall) Value { 725 if len(call.Arguments) > 0 { 726 if call.Arguments[0].ToBoolean() { 727 return valueTrue 728 } else { 729 return valueFalse 730 } 731 } else { 732 return valueFalse 733 } 734} 735 736func (r *Runtime) builtin_newBoolean(args []Value, proto *Object) *Object { 737 var v Value 738 if len(args) > 0 { 739 if args[0].ToBoolean() { 740 v = valueTrue 741 } else { 742 v = valueFalse 743 } 744 } else { 745 v = valueFalse 746 } 747 return r.newPrimitiveObject(v, proto, classBoolean) 748} 749 750func (r *Runtime) error_toString(call FunctionCall) Value { 751 var nameStr, msgStr valueString 752 obj := call.This.ToObject(r).self 753 name := obj.getStr("name", nil) 754 if name == nil || name == _undefined { 755 nameStr = asciiString("Error") 756 } else { 757 nameStr = name.toString() 758 } 759 msg := obj.getStr("message", nil) 760 if msg == nil || msg == _undefined { 761 msgStr = stringEmpty 762 } else { 763 msgStr = msg.toString() 764 } 765 if nameStr.length() == 0 { 766 return msgStr 767 } 768 if msgStr.length() == 0 { 769 return nameStr 770 } 771 var sb valueStringBuilder 772 sb.WriteString(nameStr) 773 sb.WriteString(asciiString(": ")) 774 sb.WriteString(msgStr) 775 return sb.String() 776} 777 778func (r *Runtime) builtin_Error(args []Value, proto *Object) *Object { 779 obj := r.newBaseObject(proto, classError) 780 if len(args) > 0 && args[0] != _undefined { 781 obj._putProp("message", args[0], true, false, true) 782 } 783 return obj.val 784} 785 786func (r *Runtime) builtin_new(construct *Object, args []Value) *Object { 787 return r.toConstructor(construct)(args, nil) 788} 789 790func (r *Runtime) throw(e Value) { 791 panic(e) 792} 793 794func (r *Runtime) builtin_thrower(call FunctionCall) Value { 795 obj := r.toObject(call.This) 796 strict := true 797 switch fn := obj.self.(type) { 798 case *funcObject: 799 strict = fn.strict 800 } 801 r.typeErrorResult(strict, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them") 802 return nil 803} 804 805func (r *Runtime) eval(srcVal valueString, direct, strict bool, this Value) Value { 806 src := escapeInvalidUtf16(srcVal) 807 vm := r.vm 808 inGlobal := true 809 if direct { 810 for s := vm.stash; s != nil; s = s.outer { 811 if s.variable { 812 inGlobal = false 813 break 814 } 815 } 816 } 817 p, err := r.compile("<eval>", src, strict, true, inGlobal) 818 if err != nil { 819 panic(err) 820 } 821 822 vm.pushCtx() 823 vm.prg = p 824 vm.pc = 0 825 vm.args = 0 826 vm.result = _undefined 827 if !direct { 828 vm.stash = &r.global.stash 829 } 830 vm.sb = vm.sp 831 vm.push(this) 832 vm.run() 833 retval := vm.result 834 vm.popCtx() 835 vm.halt = false 836 vm.sp -= 1 837 return retval 838} 839 840func (r *Runtime) builtin_eval(call FunctionCall) Value { 841 if len(call.Arguments) == 0 { 842 return _undefined 843 } 844 if str, ok := call.Arguments[0].(valueString); ok { 845 return r.eval(str, false, false, r.globalObject) 846 } 847 return call.Arguments[0] 848} 849 850func (r *Runtime) constructToCall(construct func(args []Value, proto *Object) *Object, proto *Object) func(call FunctionCall) Value { 851 return func(call FunctionCall) Value { 852 return construct(call.Arguments, proto) 853 } 854} 855 856func (r *Runtime) wrapNativeConstruct(c func(args []Value, proto *Object) *Object, proto *Object) func(args []Value, newTarget *Object) *Object { 857 if c == nil { 858 return nil 859 } 860 return func(args []Value, newTarget *Object) *Object { 861 var p *Object 862 if newTarget != nil { 863 if pp, ok := newTarget.self.getStr("prototype", nil).(*Object); ok { 864 p = pp 865 } 866 } 867 if p == nil { 868 p = proto 869 } 870 return c(args, p) 871 } 872} 873 874func (r *Runtime) toCallable(v Value) func(FunctionCall) Value { 875 if call, ok := r.toObject(v).self.assertCallable(); ok { 876 return call 877 } 878 r.typeErrorResult(true, "Value is not callable: %s", v.toString()) 879 return nil 880} 881 882func (r *Runtime) checkObjectCoercible(v Value) { 883 switch v.(type) { 884 case valueUndefined, valueNull: 885 r.typeErrorResult(true, "Value is not object coercible") 886 } 887} 888 889func toInt8(v Value) int8 { 890 v = v.ToNumber() 891 if i, ok := v.(valueInt); ok { 892 return int8(i) 893 } 894 895 if f, ok := v.(valueFloat); ok { 896 f := float64(f) 897 if !math.IsNaN(f) && !math.IsInf(f, 0) { 898 return int8(int64(f)) 899 } 900 } 901 return 0 902} 903 904func toUint8(v Value) uint8 { 905 v = v.ToNumber() 906 if i, ok := v.(valueInt); ok { 907 return uint8(i) 908 } 909 910 if f, ok := v.(valueFloat); ok { 911 f := float64(f) 912 if !math.IsNaN(f) && !math.IsInf(f, 0) { 913 return uint8(int64(f)) 914 } 915 } 916 return 0 917} 918 919func toUint8Clamp(v Value) uint8 { 920 v = v.ToNumber() 921 if i, ok := v.(valueInt); ok { 922 if i < 0 { 923 return 0 924 } 925 if i <= 255 { 926 return uint8(i) 927 } 928 return 255 929 } 930 931 if num, ok := v.(valueFloat); ok { 932 num := float64(num) 933 if !math.IsNaN(num) { 934 if num < 0 { 935 return 0 936 } 937 if num > 255 { 938 return 255 939 } 940 f := math.Floor(num) 941 f1 := f + 0.5 942 if f1 < num { 943 return uint8(f + 1) 944 } 945 if f1 > num { 946 return uint8(f) 947 } 948 r := uint8(f) 949 if r&1 != 0 { 950 return r + 1 951 } 952 return r 953 } 954 } 955 return 0 956} 957 958func toInt16(v Value) int16 { 959 v = v.ToNumber() 960 if i, ok := v.(valueInt); ok { 961 return int16(i) 962 } 963 964 if f, ok := v.(valueFloat); ok { 965 f := float64(f) 966 if !math.IsNaN(f) && !math.IsInf(f, 0) { 967 return int16(int64(f)) 968 } 969 } 970 return 0 971} 972 973func toUint16(v Value) uint16 { 974 v = v.ToNumber() 975 if i, ok := v.(valueInt); ok { 976 return uint16(i) 977 } 978 979 if f, ok := v.(valueFloat); ok { 980 f := float64(f) 981 if !math.IsNaN(f) && !math.IsInf(f, 0) { 982 return uint16(int64(f)) 983 } 984 } 985 return 0 986} 987 988func toInt32(v Value) int32 { 989 v = v.ToNumber() 990 if i, ok := v.(valueInt); ok { 991 return int32(i) 992 } 993 994 if f, ok := v.(valueFloat); ok { 995 f := float64(f) 996 if !math.IsNaN(f) && !math.IsInf(f, 0) { 997 return int32(int64(f)) 998 } 999 } 1000 return 0 1001} 1002 1003func toUint32(v Value) uint32 { 1004 v = v.ToNumber() 1005 if i, ok := v.(valueInt); ok { 1006 return uint32(i) 1007 } 1008 1009 if f, ok := v.(valueFloat); ok { 1010 f := float64(f) 1011 if !math.IsNaN(f) && !math.IsInf(f, 0) { 1012 return uint32(int64(f)) 1013 } 1014 } 1015 return 0 1016} 1017 1018func toInt64(v Value) int64 { 1019 v = v.ToNumber() 1020 if i, ok := v.(valueInt); ok { 1021 return int64(i) 1022 } 1023 1024 if f, ok := v.(valueFloat); ok { 1025 f := float64(f) 1026 if !math.IsNaN(f) && !math.IsInf(f, 0) { 1027 return int64(f) 1028 } 1029 } 1030 return 0 1031} 1032 1033func toUint64(v Value) uint64 { 1034 v = v.ToNumber() 1035 if i, ok := v.(valueInt); ok { 1036 return uint64(i) 1037 } 1038 1039 if f, ok := v.(valueFloat); ok { 1040 f := float64(f) 1041 if !math.IsNaN(f) && !math.IsInf(f, 0) { 1042 return uint64(int64(f)) 1043 } 1044 } 1045 return 0 1046} 1047 1048func toInt(v Value) int { 1049 v = v.ToNumber() 1050 if i, ok := v.(valueInt); ok { 1051 return int(i) 1052 } 1053 1054 if f, ok := v.(valueFloat); ok { 1055 f := float64(f) 1056 if !math.IsNaN(f) && !math.IsInf(f, 0) { 1057 return int(f) 1058 } 1059 } 1060 return 0 1061} 1062 1063func toUint(v Value) uint { 1064 v = v.ToNumber() 1065 if i, ok := v.(valueInt); ok { 1066 return uint(i) 1067 } 1068 1069 if f, ok := v.(valueFloat); ok { 1070 f := float64(f) 1071 if !math.IsNaN(f) && !math.IsInf(f, 0) { 1072 return uint(int64(f)) 1073 } 1074 } 1075 return 0 1076} 1077 1078func toFloat32(v Value) float32 { 1079 return float32(v.ToFloat()) 1080} 1081 1082func toLength(v Value) int64 { 1083 if v == nil { 1084 return 0 1085 } 1086 i := v.ToInteger() 1087 if i < 0 { 1088 return 0 1089 } 1090 if i >= maxInt { 1091 return maxInt - 1 1092 } 1093 return i 1094} 1095 1096func toIntStrict(i int64) int { 1097 if bits.UintSize == 32 { 1098 if i > math.MaxInt32 || i < math.MinInt32 { 1099 panic(rangeError("Integer value overflows 32-bit int")) 1100 } 1101 } 1102 return int(i) 1103} 1104 1105func toIntClamp(i int64) int { 1106 if bits.UintSize == 32 { 1107 if i > math.MaxInt32 { 1108 return math.MaxInt32 1109 } 1110 if i < math.MinInt32 { 1111 return math.MinInt32 1112 } 1113 } 1114 return int(i) 1115} 1116 1117func (r *Runtime) toIndex(v Value) int { 1118 intIdx := v.ToInteger() 1119 if intIdx >= 0 && intIdx < maxInt { 1120 if bits.UintSize == 32 && intIdx >= math.MaxInt32 { 1121 panic(r.newError(r.global.RangeError, "Index %s overflows int", v.String())) 1122 } 1123 return int(intIdx) 1124 } 1125 panic(r.newError(r.global.RangeError, "Invalid index %s", v.String())) 1126} 1127 1128func (r *Runtime) toBoolean(b bool) Value { 1129 if b { 1130 return valueTrue 1131 } else { 1132 return valueFalse 1133 } 1134} 1135 1136// New creates an instance of a Javascript runtime that can be used to run code. Multiple instances may be created and 1137// used simultaneously, however it is not possible to pass JS values across runtimes. 1138func New() *Runtime { 1139 r := &Runtime{} 1140 r.init() 1141 return r 1142} 1143 1144// Compile creates an internal representation of the JavaScript code that can be later run using the Runtime.RunProgram() 1145// method. This representation is not linked to a runtime in any way and can be run in multiple runtimes (possibly 1146// at the same time). 1147func Compile(name, src string, strict bool) (*Program, error) { 1148 return compile(name, src, strict, false, true) 1149} 1150 1151// CompileAST creates an internal representation of the JavaScript code that can be later run using the Runtime.RunProgram() 1152// method. This representation is not linked to a runtime in any way and can be run in multiple runtimes (possibly 1153// at the same time). 1154func CompileAST(prg *js_ast.Program, strict bool) (*Program, error) { 1155 return compileAST(prg, strict, false, true) 1156} 1157 1158// MustCompile is like Compile but panics if the code cannot be compiled. 1159// It simplifies safe initialization of global variables holding compiled JavaScript code. 1160func MustCompile(name, src string, strict bool) *Program { 1161 prg, err := Compile(name, src, strict) 1162 if err != nil { 1163 panic(err) 1164 } 1165 1166 return prg 1167} 1168 1169// Parse takes a source string and produces a parsed AST. Use this function if you want to pass options 1170// to the parser, e.g.: 1171// 1172// p, err := Parse("test.js", "var a = true", parser.WithDisableSourceMaps) 1173// if err != nil { /* ... */ } 1174// prg, err := CompileAST(p, true) 1175// // ... 1176// 1177// Otherwise use Compile which combines both steps. 1178func Parse(name, src string, options ...parser.Option) (prg *js_ast.Program, err error) { 1179 prg, err1 := parser.ParseFile(nil, name, src, 0, options...) 1180 if err1 != nil { 1181 // FIXME offset 1182 err = &CompilerSyntaxError{ 1183 CompilerError: CompilerError{ 1184 Message: err1.Error(), 1185 }, 1186 } 1187 } 1188 return 1189} 1190 1191func compile(name, src string, strict, eval, inGlobal bool, parserOptions ...parser.Option) (p *Program, err error) { 1192 prg, err := Parse(name, src, parserOptions...) 1193 if err != nil { 1194 return 1195 } 1196 1197 return compileAST(prg, strict, eval, inGlobal) 1198} 1199 1200func compileAST(prg *js_ast.Program, strict, eval, inGlobal bool) (p *Program, err error) { 1201 c := newCompiler() 1202 1203 defer func() { 1204 if x := recover(); x != nil { 1205 p = nil 1206 switch x1 := x.(type) { 1207 case *CompilerSyntaxError: 1208 err = x1 1209 default: 1210 panic(x) 1211 } 1212 } 1213 }() 1214 1215 c.compile(prg, strict, eval, inGlobal) 1216 p = c.p 1217 return 1218} 1219 1220func (r *Runtime) compile(name, src string, strict, eval, inGlobal bool) (p *Program, err error) { 1221 p, err = compile(name, src, strict, eval, inGlobal, r.parserOptions...) 1222 if err != nil { 1223 switch x1 := err.(type) { 1224 case *CompilerSyntaxError: 1225 err = &Exception{ 1226 val: r.builtin_new(r.global.SyntaxError, []Value{newStringValue(x1.Error())}), 1227 } 1228 case *CompilerReferenceError: 1229 err = &Exception{ 1230 val: r.newError(r.global.ReferenceError, x1.Message), 1231 } // TODO proper message 1232 } 1233 } 1234 return 1235} 1236 1237// RunString executes the given string in the global context. 1238func (r *Runtime) RunString(str string) (Value, error) { 1239 return r.RunScript("", str) 1240} 1241 1242// RunScript executes the given string in the global context. 1243func (r *Runtime) RunScript(name, src string) (Value, error) { 1244 p, err := r.compile(name, src, false, false, true) 1245 1246 if err != nil { 1247 return nil, err 1248 } 1249 1250 return r.RunProgram(p) 1251} 1252 1253// RunProgram executes a pre-compiled (see Compile()) code in the global context. 1254func (r *Runtime) RunProgram(p *Program) (result Value, err error) { 1255 defer func() { 1256 if x := recover(); x != nil { 1257 if ex, ok := x.(*uncatchableException); ok { 1258 err = ex.err 1259 } else { 1260 panic(x) 1261 } 1262 } 1263 }() 1264 vm := r.vm 1265 recursive := false 1266 if len(vm.callStack) > 0 { 1267 recursive = true 1268 vm.pushCtx() 1269 vm.stash = &r.global.stash 1270 vm.sb = vm.sp - 1 1271 } 1272 vm.prg = p 1273 vm.pc = 0 1274 vm.result = _undefined 1275 ex := vm.runTry() 1276 if ex == nil { 1277 result = r.vm.result 1278 } else { 1279 err = ex 1280 } 1281 if recursive { 1282 vm.popCtx() 1283 vm.halt = false 1284 vm.clearStack() 1285 } else { 1286 vm.stack = nil 1287 vm.prg = nil 1288 r.leave() 1289 } 1290 return 1291} 1292 1293// CaptureCallStack appends the current call stack frames to the stack slice (which may be nil) up to the specified depth. 1294// The most recent frame will be the first one. 1295// If depth <= 0 or more than the number of available frames, returns the entire stack. 1296// This method is not safe for concurrent use and should only be called by a Go function that is 1297// called from a running script. 1298func (r *Runtime) CaptureCallStack(depth int, stack []StackFrame) []StackFrame { 1299 l := len(r.vm.callStack) 1300 var offset int 1301 if depth > 0 { 1302 offset = l - depth + 1 1303 if offset < 0 { 1304 offset = 0 1305 } 1306 } 1307 if stack == nil { 1308 stack = make([]StackFrame, 0, l-offset+1) 1309 } 1310 return r.vm.captureStack(stack, offset) 1311} 1312 1313// Interrupt a running JavaScript. The corresponding Go call will return an *InterruptedError containing v. 1314// Note, it only works while in JavaScript code, it does not interrupt native Go functions (which includes all built-ins). 1315// If the runtime is currently not running, it will be immediately interrupted on the next Run*() call. 1316// To avoid that use ClearInterrupt() 1317func (r *Runtime) Interrupt(v interface{}) { 1318 r.vm.Interrupt(v) 1319} 1320 1321// ClearInterrupt resets the interrupt flag. Typically this needs to be called before the runtime 1322// is made available for re-use if there is a chance it could have been interrupted with Interrupt(). 1323// Otherwise if Interrupt() was called when runtime was not running (e.g. if it had already finished) 1324// so that Interrupt() didn't actually trigger, an attempt to use the runtime will immediately cause 1325// an interruption. It is up to the user to ensure proper synchronisation so that ClearInterrupt() is 1326// only called when the runtime has finished and there is no chance of a concurrent Interrupt() call. 1327func (r *Runtime) ClearInterrupt() { 1328 r.vm.ClearInterrupt() 1329} 1330 1331/* 1332ToValue converts a Go value into a JavaScript value of a most appropriate type. Structural types (such as structs, maps 1333and slices) are wrapped so that changes are reflected on the original value which can be retrieved using Value.Export(). 1334 1335WARNING! There are two very important caveats to bear in mind when modifying wrapped Go structs, maps and 1336slices. 1337 13381. If a slice is passed by value (not as a pointer), resizing the slice does not reflect on the original 1339value. Moreover, extending the slice may result in the underlying array being re-allocated and copied. 1340For example: 1341 1342 a := []interface{}{1} 1343 vm.Set("a", a) 1344 vm.RunString(`a.push(2); a[0] = 0;`) 1345 fmt.Println(a[0]) // prints "1" 1346 13472. If a regular JavaScript Object is assigned as an element of a wrapped Go struct, map or array, it is 1348Export()'ed and therefore copied. This may result in an unexpected behaviour in JavaScript: 1349 1350 m := map[string]interface{}{} 1351 vm.Set("m", m) 1352 vm.RunString(` 1353 var obj = {test: false}; 1354 m.obj = obj; // obj gets Export()'ed, i.e. copied to a new map[string]interface{} and then this map is set as m["obj"] 1355 obj.test = true; // note, m.obj.test is still false 1356 `) 1357 fmt.Println(m["obj"].(map[string]interface{})["test"]) // prints "false" 1358 1359Notes on individual types: 1360 1361Primitive types 1362 1363Primitive types (numbers, string, bool) are converted to the corresponding JavaScript primitives. 1364 1365Strings 1366 1367Because of the difference in internal string representation between ECMAScript (which uses UTF-16) and Go (which uses 1368UTF-8) conversion from JS to Go may be lossy. In particular, code points that can be part of UTF-16 surrogate pairs 1369(0xD800-0xDFFF) cannot be represented in UTF-8 unless they form a valid surrogate pair and are replaced with 1370utf8.RuneError. 1371 1372Nil 1373 1374Nil is converted to null. 1375 1376Functions 1377 1378func(FunctionCall) Value is treated as a native JavaScript function. This increases performance because there are no 1379automatic argument and return value type conversions (which involves reflect). Attempting to use 1380the function as a constructor will result in a TypeError. 1381 1382func(FunctionCall, *Runtime) Value is treated as above, except the *Runtime is also passed as a parameter. 1383 1384func(ConstructorCall) *Object is treated as a native constructor, allowing to use it with the new 1385operator: 1386 1387 func MyObject(call goja.ConstructorCall) *goja.Object { 1388 // call.This contains the newly created object as per http://www.ecma-international.org/ecma-262/5.1/index.html#sec-13.2.2 1389 // call.Arguments contain arguments passed to the function 1390 1391 call.This.Set("method", method) 1392 1393 //... 1394 1395 // If return value is a non-nil *Object, it will be used instead of call.This 1396 // This way it is possible to return a Go struct or a map converted 1397 // into goja.Value using ToValue(), however in this case 1398 // instanceof will not work as expected. 1399 return nil 1400 } 1401 1402 runtime.Set("MyObject", MyObject) 1403 1404Then it can be used in JS as follows: 1405 1406 var o = new MyObject(arg); 1407 var o1 = MyObject(arg); // same thing 1408 o instanceof MyObject && o1 instanceof MyObject; // true 1409 1410When a native constructor is called directly (without the new operator) its behavior depends on 1411this value: if it's an Object, it is passed through, otherwise a new one is created exactly as 1412if it was called with the new operator. In either case call.NewTarget will be nil. 1413 1414func(ConstructorCall, *Runtime) *Object is treated as above, except the *Runtime is also passed as a parameter. 1415 1416Any other Go function is wrapped so that the arguments are automatically converted into the required Go types and the 1417return value is converted to a JavaScript value (using this method). If conversion is not possible, a TypeError is 1418thrown. 1419 1420Functions with multiple return values return an Array. If the last return value is an `error` it is not returned but 1421converted into a JS exception. If the error is *Exception, it is thrown as is, otherwise it's wrapped in a GoEerror. 1422Note that if there are exactly two return values and the last is an `error`, the function returns the first value as is, 1423not an Array. 1424 1425Structs 1426 1427Structs are converted to Object-like values. Fields and methods are available as properties, their values are 1428results of this method (ToValue()) applied to the corresponding Go value. 1429 1430Field properties are writable (if the struct is addressable) and non-configurable. 1431Method properties are non-writable and non-configurable. 1432 1433Attempt to define a new property or delete an existing property will fail (throw in strict mode) unless it's a Symbol 1434property. Symbol properties only exist in the wrapper and do not affect the underlying Go value. 1435Note that because a wrapper is created every time a property is accessed it may lead to unexpected results such as this: 1436 1437 type Field struct{ 1438 } 1439 type S struct { 1440 Field *Field 1441 } 1442 var s = S{ 1443 Field: &Field{}, 1444 } 1445 vm := New() 1446 vm.Set("s", &s) 1447 res, err := vm.RunString(` 1448 var sym = Symbol(66); 1449 var field1 = s.Field; 1450 field1[sym] = true; 1451 var field2 = s.Field; 1452 field1 === field2; // true, because the equality operation compares the wrapped values, not the wrappers 1453 field1[sym] === true; // true 1454 field2[sym] === undefined; // also true 1455 `) 1456 1457The same applies to values from maps and slices as well. 1458 1459Handling of time.Time 1460 1461time.Time does not get special treatment and therefore is converted just like any other `struct` providing access to 1462all its methods. This is done deliberately instead of converting it to a `Date` because these two types are not fully 1463compatible: `time.Time` includes zone, whereas JS `Date` doesn't. Doing the conversion implicitly therefore would 1464result in a loss of information. 1465 1466If you need to convert it to a `Date`, it can be done either in JS: 1467 1468 var d = new Date(goval.UnixNano()/1e6); 1469 1470... or in Go: 1471 1472 now := time.Now() 1473 vm := New() 1474 val, err := vm.New(vm.Get("Date").ToObject(vm), vm.ToValue(now.UnixNano()/1e6)) 1475 if err != nil { 1476 ... 1477 } 1478 vm.Set("d", val) 1479 1480Note that Value.Export() for a `Date` value returns time.Time in local timezone. 1481 1482Maps 1483 1484Maps with string or integer key type are converted into host objects that largely behave like a JavaScript Object. 1485 1486Maps with methods 1487 1488If a map type has at least one method defined, the properties of the resulting Object represent methods, not map keys. 1489This is because in JavaScript there is no distinction between 'object.key` and `object[key]`, unlike Go. 1490If access to the map values is required, it can be achieved by defining another method or, if it's not possible, by 1491defining an external getter function. 1492 1493Slices 1494 1495Slices are converted into host objects that behave largely like JavaScript Array. It has the appropriate 1496prototype and all the usual methods should work. There is, however, a caveat: converted Arrays may not contain holes 1497(because Go slices cannot). This means that hasOwnProperty(n) always returns `true` if n < length. Deleting an item with 1498an index < length will set it to a zero value (but the property will remain). Nil slice elements are be converted to 1499`null`. Accessing an element beyond `length` returns `undefined`. Also see the warning above about passing slices as 1500values (as opposed to pointers). 1501 1502Any other type is converted to a generic reflect based host object. Depending on the underlying type it behaves similar 1503to a Number, String, Boolean or Object. 1504 1505Note that the underlying type is not lost, calling Export() returns the original Go value. This applies to all 1506reflect based types. 1507*/ 1508func (r *Runtime) ToValue(i interface{}) Value { 1509 switch i := i.(type) { 1510 case nil: 1511 return _null 1512 case *Object: 1513 if i == nil || i.runtime == nil { 1514 return _null 1515 } 1516 if i.runtime != r { 1517 panic(r.NewTypeError("Illegal runtime transition of an Object")) 1518 } 1519 return i 1520 case valueContainer: 1521 return i.toValue(r) 1522 case Value: 1523 return i 1524 case string: 1525 return newStringValue(i) 1526 case bool: 1527 if i { 1528 return valueTrue 1529 } else { 1530 return valueFalse 1531 } 1532 case func(FunctionCall) Value: 1533 name := unistring.NewFromString(runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()) 1534 return r.newNativeFunc(i, nil, name, nil, 0) 1535 case func(FunctionCall, *Runtime) Value: 1536 name := unistring.NewFromString(runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()) 1537 return r.newNativeFunc(func(call FunctionCall) Value { 1538 return i(call, r) 1539 }, nil, name, nil, 0) 1540 case func(ConstructorCall) *Object: 1541 name := unistring.NewFromString(runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()) 1542 return r.newNativeConstructor(i, name, 0) 1543 case func(ConstructorCall, *Runtime) *Object: 1544 name := unistring.NewFromString(runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()) 1545 return r.newNativeConstructor(func(call ConstructorCall) *Object { 1546 return i(call, r) 1547 }, name, 0) 1548 case int: 1549 return intToValue(int64(i)) 1550 case int8: 1551 return intToValue(int64(i)) 1552 case int16: 1553 return intToValue(int64(i)) 1554 case int32: 1555 return intToValue(int64(i)) 1556 case int64: 1557 return intToValue(i) 1558 case uint: 1559 if uint64(i) <= math.MaxInt64 { 1560 return intToValue(int64(i)) 1561 } else { 1562 return floatToValue(float64(i)) 1563 } 1564 case uint8: 1565 return intToValue(int64(i)) 1566 case uint16: 1567 return intToValue(int64(i)) 1568 case uint32: 1569 return intToValue(int64(i)) 1570 case uint64: 1571 if i <= math.MaxInt64 { 1572 return intToValue(int64(i)) 1573 } 1574 return floatToValue(float64(i)) 1575 case float32: 1576 return floatToValue(float64(i)) 1577 case float64: 1578 return floatToValue(i) 1579 case map[string]interface{}: 1580 if i == nil { 1581 return _null 1582 } 1583 obj := &Object{runtime: r} 1584 m := &objectGoMapSimple{ 1585 baseObject: baseObject{ 1586 val: obj, 1587 extensible: true, 1588 }, 1589 data: i, 1590 } 1591 obj.self = m 1592 m.init() 1593 return obj 1594 case []interface{}: 1595 if i == nil { 1596 return _null 1597 } 1598 obj := &Object{runtime: r} 1599 a := &objectGoSlice{ 1600 baseObject: baseObject{ 1601 val: obj, 1602 }, 1603 data: &i, 1604 } 1605 obj.self = a 1606 a.init() 1607 return obj 1608 case *[]interface{}: 1609 if i == nil { 1610 return _null 1611 } 1612 obj := &Object{runtime: r} 1613 a := &objectGoSlice{ 1614 baseObject: baseObject{ 1615 val: obj, 1616 }, 1617 data: i, 1618 } 1619 obj.self = a 1620 a.init() 1621 return obj 1622 } 1623 1624 origValue := reflect.ValueOf(i) 1625 value := origValue 1626 for value.Kind() == reflect.Ptr { 1627 value = reflect.Indirect(value) 1628 } 1629 1630 if !value.IsValid() { 1631 return _null 1632 } 1633 1634 switch value.Kind() { 1635 case reflect.Map: 1636 if value.Type().NumMethod() == 0 { 1637 switch value.Type().Key().Kind() { 1638 case reflect.String, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 1639 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 1640 reflect.Float64, reflect.Float32: 1641 1642 obj := &Object{runtime: r} 1643 m := &objectGoMapReflect{ 1644 objectGoReflect: objectGoReflect{ 1645 baseObject: baseObject{ 1646 val: obj, 1647 extensible: true, 1648 }, 1649 origValue: origValue, 1650 value: value, 1651 }, 1652 } 1653 m.init() 1654 obj.self = m 1655 return obj 1656 } 1657 } 1658 case reflect.Slice: 1659 obj := &Object{runtime: r} 1660 a := &objectGoSliceReflect{ 1661 objectGoReflect: objectGoReflect{ 1662 baseObject: baseObject{ 1663 val: obj, 1664 }, 1665 origValue: origValue, 1666 value: value, 1667 }, 1668 } 1669 a.init() 1670 obj.self = a 1671 return obj 1672 case reflect.Func: 1673 name := unistring.NewFromString(runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()) 1674 return r.newNativeFunc(r.wrapReflectFunc(value), nil, name, nil, value.Type().NumIn()) 1675 } 1676 1677 obj := &Object{runtime: r} 1678 o := &objectGoReflect{ 1679 baseObject: baseObject{ 1680 val: obj, 1681 }, 1682 origValue: origValue, 1683 value: value, 1684 } 1685 obj.self = o 1686 o.init() 1687 return obj 1688} 1689 1690func (r *Runtime) wrapReflectFunc(value reflect.Value) func(FunctionCall) Value { 1691 return func(call FunctionCall) Value { 1692 typ := value.Type() 1693 nargs := typ.NumIn() 1694 var in []reflect.Value 1695 1696 if l := len(call.Arguments); l < nargs { 1697 // fill missing arguments with zero values 1698 n := nargs 1699 if typ.IsVariadic() { 1700 n-- 1701 } 1702 in = make([]reflect.Value, n) 1703 for i := l; i < n; i++ { 1704 in[i] = reflect.Zero(typ.In(i)) 1705 } 1706 } else { 1707 if l > nargs && !typ.IsVariadic() { 1708 l = nargs 1709 } 1710 in = make([]reflect.Value, l) 1711 } 1712 1713 callSlice := false 1714 for i, a := range call.Arguments { 1715 var t reflect.Type 1716 1717 n := i 1718 if n >= nargs-1 && typ.IsVariadic() { 1719 if n > nargs-1 { 1720 n = nargs - 1 1721 } 1722 1723 t = typ.In(n).Elem() 1724 } else if n > nargs-1 { // ignore extra arguments 1725 break 1726 } else { 1727 t = typ.In(n) 1728 } 1729 1730 // if this is a variadic Go function, and the caller has supplied 1731 // exactly the number of JavaScript arguments required, and this 1732 // is the last JavaScript argument, try treating the it as the 1733 // actual set of variadic Go arguments. if that succeeds, break 1734 // out of the loop. 1735 if typ.IsVariadic() && len(call.Arguments) == nargs && i == nargs-1 { 1736 v := reflect.New(typ.In(n)).Elem() 1737 if err := r.toReflectValue(a, v, &objectExportCtx{}); err == nil { 1738 in[i] = v 1739 callSlice = true 1740 break 1741 } 1742 } 1743 v := reflect.New(t).Elem() 1744 err := r.toReflectValue(a, v, &objectExportCtx{}) 1745 if err != nil { 1746 panic(r.newError(r.global.TypeError, "could not convert function call parameter %v to %v", a, t)) 1747 } 1748 in[i] = v 1749 } 1750 1751 var out []reflect.Value 1752 if callSlice { 1753 out = value.CallSlice(in) 1754 } else { 1755 out = value.Call(in) 1756 } 1757 1758 if len(out) == 0 { 1759 return _undefined 1760 } 1761 1762 if last := out[len(out)-1]; last.Type().Name() == "error" { 1763 if !last.IsNil() { 1764 err := last.Interface() 1765 if _, ok := err.(*Exception); ok { 1766 panic(err) 1767 } 1768 panic(r.NewGoError(last.Interface().(error))) 1769 } 1770 out = out[:len(out)-1] 1771 } 1772 1773 switch len(out) { 1774 case 0: 1775 return _undefined 1776 case 1: 1777 return r.ToValue(out[0].Interface()) 1778 default: 1779 s := make([]interface{}, len(out)) 1780 for i, v := range out { 1781 s[i] = v.Interface() 1782 } 1783 1784 return r.ToValue(s) 1785 } 1786 } 1787} 1788 1789func (r *Runtime) toReflectValue(v Value, dst reflect.Value, ctx *objectExportCtx) error { 1790 typ := dst.Type() 1791 switch typ.Kind() { 1792 case reflect.String: 1793 dst.Set(reflect.ValueOf(v.String()).Convert(typ)) 1794 return nil 1795 case reflect.Bool: 1796 dst.Set(reflect.ValueOf(v.ToBoolean()).Convert(typ)) 1797 return nil 1798 case reflect.Int: 1799 dst.Set(reflect.ValueOf(toInt(v)).Convert(typ)) 1800 return nil 1801 case reflect.Int64: 1802 dst.Set(reflect.ValueOf(toInt64(v)).Convert(typ)) 1803 return nil 1804 case reflect.Int32: 1805 dst.Set(reflect.ValueOf(toInt32(v)).Convert(typ)) 1806 return nil 1807 case reflect.Int16: 1808 dst.Set(reflect.ValueOf(toInt16(v)).Convert(typ)) 1809 return nil 1810 case reflect.Int8: 1811 dst.Set(reflect.ValueOf(toInt8(v)).Convert(typ)) 1812 return nil 1813 case reflect.Uint: 1814 dst.Set(reflect.ValueOf(toUint(v)).Convert(typ)) 1815 return nil 1816 case reflect.Uint64: 1817 dst.Set(reflect.ValueOf(toUint64(v)).Convert(typ)) 1818 return nil 1819 case reflect.Uint32: 1820 dst.Set(reflect.ValueOf(toUint32(v)).Convert(typ)) 1821 return nil 1822 case reflect.Uint16: 1823 dst.Set(reflect.ValueOf(toUint16(v)).Convert(typ)) 1824 return nil 1825 case reflect.Uint8: 1826 dst.Set(reflect.ValueOf(toUint8(v)).Convert(typ)) 1827 return nil 1828 case reflect.Float64: 1829 dst.Set(reflect.ValueOf(v.ToFloat()).Convert(typ)) 1830 return nil 1831 case reflect.Float32: 1832 dst.Set(reflect.ValueOf(toFloat32(v)).Convert(typ)) 1833 return nil 1834 } 1835 1836 if typ == typeCallable { 1837 if fn, ok := AssertFunction(v); ok { 1838 dst.Set(reflect.ValueOf(fn)) 1839 return nil 1840 } 1841 } 1842 1843 if typ == typeValue { 1844 dst.Set(reflect.ValueOf(v)) 1845 return nil 1846 } 1847 1848 if typ == typeObject { 1849 if obj, ok := v.(*Object); ok { 1850 dst.Set(reflect.ValueOf(obj)) 1851 return nil 1852 } 1853 } 1854 1855 { 1856 et := v.ExportType() 1857 if et == nil || et == reflectTypeNil { 1858 dst.Set(reflect.Zero(typ)) 1859 return nil 1860 } 1861 1862 for i := 0; ; i++ { 1863 if et.ConvertibleTo(typ) { 1864 ev := reflect.ValueOf(exportValue(v, ctx)) 1865 for ; i > 0; i-- { 1866 ev = ev.Elem() 1867 } 1868 dst.Set(ev.Convert(typ)) 1869 return nil 1870 } 1871 if et.Kind() == reflect.Ptr { 1872 et = et.Elem() 1873 } else { 1874 break 1875 } 1876 } 1877 1878 if typ == typeTime { 1879 if obj, ok := v.(*Object); ok { 1880 if d, ok := obj.self.(*dateObject); ok { 1881 dst.Set(reflect.ValueOf(d.time())) 1882 return nil 1883 } 1884 } 1885 if et.Kind() == reflect.String { 1886 tme, ok := dateParse(v.String()) 1887 if !ok { 1888 return fmt.Errorf("could not convert string %v to %v", v, typ) 1889 } 1890 dst.Set(reflect.ValueOf(tme)) 1891 return nil 1892 } 1893 } 1894 } 1895 1896 switch typ.Kind() { 1897 case reflect.Slice: 1898 if o, ok := v.(*Object); ok { 1899 if o.self.className() == classArray { 1900 if v, exists := ctx.getTyped(o.self, typ); exists { 1901 dst.Set(reflect.ValueOf(v)) 1902 return nil 1903 } 1904 l := int(toLength(o.self.getStr("length", nil))) 1905 if dst.IsNil() || dst.Len() != l { 1906 dst.Set(reflect.MakeSlice(typ, l, l)) 1907 } 1908 s := dst 1909 ctx.putTyped(o.self, typ, s.Interface()) 1910 for i := 0; i < l; i++ { 1911 item := o.self.getIdx(valueInt(int64(i)), nil) 1912 err := r.toReflectValue(item, s.Index(i), ctx) 1913 if err != nil { 1914 return fmt.Errorf("could not convert array element %v to %v at %d: %w", v, typ, i, err) 1915 } 1916 } 1917 return nil 1918 } 1919 } 1920 case reflect.Map: 1921 if o, ok := v.(*Object); ok { 1922 if v, exists := ctx.getTyped(o.self, typ); exists { 1923 dst.Set(reflect.ValueOf(v)) 1924 return nil 1925 } 1926 if dst.IsNil() { 1927 dst.Set(reflect.MakeMap(typ)) 1928 } 1929 m := dst 1930 ctx.putTyped(o.self, typ, m.Interface()) 1931 keyTyp := typ.Key() 1932 elemTyp := typ.Elem() 1933 needConvertKeys := !reflect.ValueOf("").Type().AssignableTo(keyTyp) 1934 iter := &enumerableIter{ 1935 wrapped: o.self.enumerateOwnKeys(), 1936 } 1937 for item, next := iter.next(); next != nil; item, next = next() { 1938 var kv reflect.Value 1939 var err error 1940 if needConvertKeys { 1941 kv = reflect.New(keyTyp).Elem() 1942 err = r.toReflectValue(stringValueFromRaw(item.name), kv, ctx) 1943 if err != nil { 1944 return fmt.Errorf("could not convert map key %s to %v", item.name.String(), typ) 1945 } 1946 } else { 1947 kv = reflect.ValueOf(item.name.String()) 1948 } 1949 1950 ival := o.self.getStr(item.name, nil) 1951 if ival != nil { 1952 vv := reflect.New(elemTyp).Elem() 1953 err := r.toReflectValue(ival, vv, ctx) 1954 if err != nil { 1955 return fmt.Errorf("could not convert map value %v to %v at key %s", ival, typ, item.name.String()) 1956 } 1957 m.SetMapIndex(kv, vv) 1958 } else { 1959 m.SetMapIndex(kv, reflect.Zero(elemTyp)) 1960 } 1961 } 1962 1963 return nil 1964 } 1965 case reflect.Struct: 1966 if o, ok := v.(*Object); ok { 1967 t := reflect.PtrTo(typ) 1968 if v, exists := ctx.getTyped(o.self, t); exists { 1969 dst.Set(reflect.ValueOf(v).Elem()) 1970 return nil 1971 } 1972 s := dst 1973 ctx.putTyped(o.self, t, s.Addr().Interface()) 1974 for i := 0; i < typ.NumField(); i++ { 1975 field := typ.Field(i) 1976 if ast.IsExported(field.Name) { 1977 name := field.Name 1978 if r.fieldNameMapper != nil { 1979 name = r.fieldNameMapper.FieldName(typ, field) 1980 } 1981 var v Value 1982 if field.Anonymous { 1983 v = o 1984 } else { 1985 v = o.self.getStr(unistring.NewFromString(name), nil) 1986 } 1987 1988 if v != nil { 1989 err := r.toReflectValue(v, s.Field(i), ctx) 1990 if err != nil { 1991 return fmt.Errorf("could not convert struct value %v to %v for field %s: %w", v, field.Type, field.Name, err) 1992 } 1993 } 1994 } 1995 } 1996 return nil 1997 } 1998 case reflect.Func: 1999 if fn, ok := AssertFunction(v); ok { 2000 dst.Set(reflect.MakeFunc(typ, r.wrapJSFunc(fn, typ))) 2001 return nil 2002 } 2003 case reflect.Ptr: 2004 if o, ok := v.(*Object); ok { 2005 if v, exists := ctx.getTyped(o.self, typ); exists { 2006 dst.Set(reflect.ValueOf(v)) 2007 return nil 2008 } 2009 } 2010 if dst.IsNil() { 2011 dst.Set(reflect.New(typ.Elem())) 2012 } 2013 return r.toReflectValue(v, dst.Elem(), ctx) 2014 } 2015 2016 return fmt.Errorf("could not convert %v to %v", v, typ) 2017} 2018 2019func (r *Runtime) wrapJSFunc(fn Callable, typ reflect.Type) func(args []reflect.Value) (results []reflect.Value) { 2020 return func(args []reflect.Value) (results []reflect.Value) { 2021 jsArgs := make([]Value, len(args)) 2022 for i, arg := range args { 2023 jsArgs[i] = r.ToValue(arg.Interface()) 2024 } 2025 2026 results = make([]reflect.Value, typ.NumOut()) 2027 res, err := fn(_undefined, jsArgs...) 2028 if err == nil { 2029 if typ.NumOut() > 0 { 2030 v := reflect.New(typ.Out(0)).Elem() 2031 err = r.toReflectValue(res, v, &objectExportCtx{}) 2032 if err == nil { 2033 results[0] = v 2034 } 2035 } 2036 } 2037 2038 if err != nil { 2039 if typ.NumOut() == 2 && typ.Out(1).Name() == "error" { 2040 results[1] = reflect.ValueOf(err).Convert(typ.Out(1)) 2041 } else { 2042 panic(err) 2043 } 2044 } 2045 2046 for i, v := range results { 2047 if !v.IsValid() { 2048 results[i] = reflect.Zero(typ.Out(i)) 2049 } 2050 } 2051 2052 return 2053 } 2054} 2055 2056// ExportTo converts a JavaScript value into the specified Go value. The second parameter must be a non-nil pointer. 2057// Exporting to an interface{} results in a value of the same type as Export() would produce. 2058// Exporting to numeric types uses the standard ECMAScript conversion operations, same as used when assigning 2059// values to non-clamped typed array items, e.g. https://262.ecma-international.org/#sec-toint32 2060// Returns error if conversion is not possible. 2061func (r *Runtime) ExportTo(v Value, target interface{}) error { 2062 tval := reflect.ValueOf(target) 2063 if tval.Kind() != reflect.Ptr || tval.IsNil() { 2064 return errors.New("target must be a non-nil pointer") 2065 } 2066 return r.toReflectValue(v, tval.Elem(), &objectExportCtx{}) 2067} 2068 2069// GlobalObject returns the global object. 2070func (r *Runtime) GlobalObject() *Object { 2071 return r.globalObject 2072} 2073 2074// Set the specified variable in the global context. 2075// Equivalent to running "name = value" in non-strict mode. 2076// The value is first converted using ToValue(). 2077// Note, this is not the same as GlobalObject().Set(name, value), 2078// because if a global lexical binding (let or const) exists, it is set instead. 2079func (r *Runtime) Set(name string, value interface{}) error { 2080 return r.try(func() { 2081 name := unistring.NewFromString(name) 2082 v := r.ToValue(value) 2083 if ref := r.global.stash.getRefByName(name, false); ref != nil { 2084 ref.set(v) 2085 } else { 2086 r.globalObject.self.setOwnStr(name, v, true) 2087 } 2088 }) 2089} 2090 2091// Get the specified variable in the global context. 2092// Equivalent to dereferencing a variable by name in non-strict mode. If variable is not defined returns nil. 2093// Note, this is not the same as GlobalObject().Get(name), 2094// because if a global lexical binding (let or const) exists, it is used instead. 2095// This method will panic with an *Exception if a JavaScript exception is thrown in the process. 2096func (r *Runtime) Get(name string) (ret Value) { 2097 r.tryPanic(func() { 2098 n := unistring.NewFromString(name) 2099 if v, exists := r.global.stash.getByName(n); exists { 2100 ret = v 2101 } else { 2102 ret = r.globalObject.self.getStr(n, nil) 2103 } 2104 }) 2105 return 2106} 2107 2108// SetRandSource sets random source for this Runtime. If not called, the default math/rand is used. 2109func (r *Runtime) SetRandSource(source RandSource) { 2110 r.rand = source 2111} 2112 2113// SetTimeSource sets the current time source for this Runtime. 2114// If not called, the default time.Now() is used. 2115func (r *Runtime) SetTimeSource(now Now) { 2116 r.now = now 2117} 2118 2119// SetParserOptions sets parser options to be used by RunString, RunScript and eval() within the code. 2120func (r *Runtime) SetParserOptions(opts ...parser.Option) { 2121 r.parserOptions = opts 2122} 2123 2124// SetMaxCallStackSize sets the maximum function call depth. When exceeded, a *StackOverflowError is thrown and 2125// returned by RunProgram or by a Callable call. This is useful to prevent memory exhaustion caused by an 2126// infinite recursion. The default value is math.MaxInt32. 2127// This method (as the rest of the Set* methods) is not safe for concurrent use and may only be called 2128// from the vm goroutine or when the vm is not running. 2129func (r *Runtime) SetMaxCallStackSize(size int) { 2130 r.vm.maxCallStackSize = size 2131} 2132 2133// New is an equivalent of the 'new' operator allowing to call it directly from Go. 2134func (r *Runtime) New(construct Value, args ...Value) (o *Object, err error) { 2135 err = r.try(func() { 2136 o = r.builtin_new(r.toObject(construct), args) 2137 }) 2138 return 2139} 2140 2141// Callable represents a JavaScript function that can be called from Go. 2142type Callable func(this Value, args ...Value) (Value, error) 2143 2144// AssertFunction checks if the Value is a function and returns a Callable. 2145func AssertFunction(v Value) (Callable, bool) { 2146 if obj, ok := v.(*Object); ok { 2147 if f, ok := obj.self.assertCallable(); ok { 2148 return func(this Value, args ...Value) (ret Value, err error) { 2149 defer func() { 2150 if x := recover(); x != nil { 2151 if ex, ok := x.(*uncatchableException); ok { 2152 err = ex.err 2153 } else { 2154 panic(x) 2155 } 2156 } 2157 }() 2158 ex := obj.runtime.vm.try(func() { 2159 ret = f(FunctionCall{ 2160 This: this, 2161 Arguments: args, 2162 }) 2163 }) 2164 if ex != nil { 2165 err = ex 2166 } 2167 vm := obj.runtime.vm 2168 vm.clearStack() 2169 if len(vm.callStack) == 0 { 2170 obj.runtime.leave() 2171 } 2172 return 2173 }, true 2174 } 2175 } 2176 return nil, false 2177} 2178 2179// IsUndefined returns true if the supplied Value is undefined. Note, it checks against the real undefined, not 2180// against the global object's 'undefined' property. 2181func IsUndefined(v Value) bool { 2182 return v == _undefined 2183} 2184 2185// IsNull returns true if the supplied Value is null. 2186func IsNull(v Value) bool { 2187 return v == _null 2188} 2189 2190// IsNaN returns true if the supplied value is NaN. 2191func IsNaN(v Value) bool { 2192 f, ok := v.(valueFloat) 2193 return ok && math.IsNaN(float64(f)) 2194} 2195 2196// IsInfinity returns true if the supplied is (+/-)Infinity 2197func IsInfinity(v Value) bool { 2198 return v == _positiveInf || v == _negativeInf 2199} 2200 2201// Undefined returns JS undefined value. Note if global 'undefined' property is changed this still returns the original value. 2202func Undefined() Value { 2203 return _undefined 2204} 2205 2206// Null returns JS null value. 2207func Null() Value { 2208 return _null 2209} 2210 2211// NaN returns a JS NaN value. 2212func NaN() Value { 2213 return _NaN 2214} 2215 2216// PositiveInf returns a JS +Inf value. 2217func PositiveInf() Value { 2218 return _positiveInf 2219} 2220 2221// NegativeInf returns a JS -Inf value. 2222func NegativeInf() Value { 2223 return _negativeInf 2224} 2225 2226func tryFunc(f func()) (ret interface{}) { 2227 defer func() { 2228 ret = recover() 2229 }() 2230 2231 f() 2232 return 2233} 2234 2235func (r *Runtime) try(f func()) error { 2236 if ex := r.vm.try(f); ex != nil { 2237 return ex 2238 } 2239 return nil 2240} 2241 2242func (r *Runtime) tryPanic(f func()) { 2243 if ex := r.vm.try(f); ex != nil { 2244 panic(ex) 2245 } 2246} 2247 2248func (r *Runtime) toObject(v Value, args ...interface{}) *Object { 2249 if obj, ok := v.(*Object); ok { 2250 return obj 2251 } 2252 if len(args) > 0 { 2253 panic(r.NewTypeError(args...)) 2254 } else { 2255 var s string 2256 if v == nil { 2257 s = "undefined" 2258 } else { 2259 s = v.String() 2260 } 2261 panic(r.NewTypeError("Value is not an object: %s", s)) 2262 } 2263} 2264 2265func (r *Runtime) toNumber(v Value) Value { 2266 switch o := v.(type) { 2267 case valueInt, valueFloat: 2268 return v 2269 case *Object: 2270 if pvo, ok := o.self.(*primitiveValueObject); ok { 2271 return r.toNumber(pvo.pValue) 2272 } 2273 } 2274 panic(r.NewTypeError("Value is not a number: %s", v)) 2275} 2276 2277func (r *Runtime) speciesConstructor(o, defaultConstructor *Object) func(args []Value, newTarget *Object) *Object { 2278 c := o.self.getStr("constructor", nil) 2279 if c != nil && c != _undefined { 2280 c = r.toObject(c).self.getSym(SymSpecies, nil) 2281 } 2282 if c == nil || c == _undefined || c == _null { 2283 c = defaultConstructor 2284 } 2285 return r.toConstructor(c) 2286} 2287 2288func (r *Runtime) speciesConstructorObj(o, defaultConstructor *Object) *Object { 2289 c := o.self.getStr("constructor", nil) 2290 if c != nil && c != _undefined { 2291 c = r.toObject(c).self.getSym(SymSpecies, nil) 2292 } 2293 if c == nil || c == _undefined || c == _null { 2294 return defaultConstructor 2295 } 2296 return r.toObject(c) 2297} 2298 2299func (r *Runtime) returnThis(call FunctionCall) Value { 2300 return call.This 2301} 2302 2303func createDataPropertyOrThrow(o *Object, p Value, v Value) { 2304 o.defineOwnProperty(p, PropertyDescriptor{ 2305 Writable: FLAG_TRUE, 2306 Enumerable: FLAG_TRUE, 2307 Configurable: FLAG_TRUE, 2308 Value: v, 2309 }, true) 2310} 2311 2312func toPropertyKey(key Value) Value { 2313 return key.ToString() 2314} 2315 2316func (r *Runtime) getVStr(v Value, p unistring.String) Value { 2317 o := v.ToObject(r) 2318 return o.self.getStr(p, v) 2319} 2320 2321func (r *Runtime) getV(v Value, p Value) Value { 2322 o := v.ToObject(r) 2323 return o.get(p, v) 2324} 2325 2326func (r *Runtime) getIterator(obj Value, method func(FunctionCall) Value) *Object { 2327 if method == nil { 2328 method = toMethod(r.getV(obj, SymIterator)) 2329 if method == nil { 2330 panic(r.NewTypeError("object is not iterable")) 2331 } 2332 } 2333 2334 return r.toObject(method(FunctionCall{ 2335 This: obj, 2336 })) 2337} 2338 2339func returnIter(iter *Object) { 2340 retMethod := toMethod(iter.self.getStr("return", nil)) 2341 if retMethod != nil { 2342 iter.runtime.toObject(retMethod(FunctionCall{This: iter})) 2343 } 2344} 2345 2346func (r *Runtime) iterate(iter *Object, step func(Value)) { 2347 for { 2348 res := r.toObject(toMethod(iter.self.getStr("next", nil))(FunctionCall{This: iter})) 2349 if nilSafe(res.self.getStr("done", nil)).ToBoolean() { 2350 break 2351 } 2352 value := nilSafe(res.self.getStr("value", nil)) 2353 ret := tryFunc(func() { 2354 step(value) 2355 }) 2356 if ret != nil { 2357 _ = tryFunc(func() { 2358 returnIter(iter) 2359 }) 2360 panic(ret) 2361 } 2362 } 2363} 2364 2365func (r *Runtime) createIterResultObject(value Value, done bool) Value { 2366 o := r.NewObject() 2367 o.self.setOwnStr("value", value, false) 2368 o.self.setOwnStr("done", r.toBoolean(done), false) 2369 return o 2370} 2371 2372func (r *Runtime) newLazyObject(create func(*Object) objectImpl) *Object { 2373 val := &Object{runtime: r} 2374 o := &lazyObject{ 2375 val: val, 2376 create: create, 2377 } 2378 val.self = o 2379 return val 2380} 2381 2382func (r *Runtime) getHash() *maphash.Hash { 2383 if r.hash == nil { 2384 r.hash = &maphash.Hash{} 2385 } 2386 return r.hash 2387} 2388 2389// called when the top level function returns (i.e. control is passed outside the Runtime). 2390func (r *Runtime) leave() { 2391 // run jobs, etc... 2392} 2393 2394func nilSafe(v Value) Value { 2395 if v != nil { 2396 return v 2397 } 2398 return _undefined 2399} 2400 2401func isArray(object *Object) bool { 2402 self := object.self 2403 if proxy, ok := self.(*proxyObject); ok { 2404 if proxy.target == nil { 2405 panic(typeError("Cannot perform 'IsArray' on a proxy that has been revoked")) 2406 } 2407 return isArray(proxy.target) 2408 } 2409 switch self.className() { 2410 case classArray: 2411 return true 2412 default: 2413 return false 2414 } 2415} 2416 2417func isRegexp(v Value) bool { 2418 if o, ok := v.(*Object); ok { 2419 matcher := o.self.getSym(SymMatch, nil) 2420 if matcher != nil && matcher != _undefined { 2421 return matcher.ToBoolean() 2422 } 2423 _, reg := o.self.(*regexpObject) 2424 return reg 2425 } 2426 return false 2427} 2428 2429func limitCallArgs(call FunctionCall, n int) FunctionCall { 2430 if len(call.Arguments) > n { 2431 return FunctionCall{This: call.This, Arguments: call.Arguments[:n]} 2432 } else { 2433 return call 2434 } 2435} 2436 2437func shrinkCap(newSize, oldCap int) int { 2438 if oldCap > 8 { 2439 if cap := oldCap / 2; cap >= newSize { 2440 return cap 2441 } 2442 } 2443 return oldCap 2444} 2445 2446func growCap(newSize, oldSize, oldCap int) int { 2447 // Use the same algorithm as in runtime.growSlice 2448 doublecap := oldCap + oldCap 2449 if newSize > doublecap { 2450 return newSize 2451 } else { 2452 if oldSize < 1024 { 2453 return doublecap 2454 } else { 2455 cap := oldCap 2456 // Check 0 < cap to detect overflow 2457 // and prevent an infinite loop. 2458 for 0 < cap && cap < newSize { 2459 cap += cap / 4 2460 } 2461 // Return the requested cap when 2462 // the calculation overflowed. 2463 if cap <= 0 { 2464 return newSize 2465 } 2466 return cap 2467 } 2468 } 2469} 2470 2471func (r *Runtime) genId() (ret uint64) { 2472 if r.hash == nil { 2473 h := r.getHash() 2474 r.idSeq = h.Sum64() 2475 } 2476 if r.idSeq == 0 { 2477 r.idSeq = 1 2478 } 2479 ret = r.idSeq 2480 r.idSeq++ 2481 return 2482} 2483 2484func (r *Runtime) setGlobal(name unistring.String, v Value, strict bool) { 2485 if ref := r.global.stash.getRefByName(name, strict); ref != nil { 2486 ref.set(v) 2487 } else { 2488 o := r.globalObject.self 2489 if strict { 2490 if o.hasOwnPropertyStr(name) { 2491 o.setOwnStr(name, v, true) 2492 } else { 2493 r.throwReferenceError(name) 2494 } 2495 } else { 2496 o.setOwnStr(name, v, false) 2497 } 2498 } 2499} 2500 2501func strToArrayIdx(s unistring.String) uint32 { 2502 if s == "" { 2503 return math.MaxUint32 2504 } 2505 l := len(s) 2506 if s[0] == '0' { 2507 if l == 1 { 2508 return 0 2509 } 2510 return math.MaxUint32 2511 } 2512 var n uint32 2513 if l < 10 { 2514 // guaranteed not to overflow 2515 for i := 0; i < len(s); i++ { 2516 c := s[i] 2517 if c < '0' || c > '9' { 2518 return math.MaxUint32 2519 } 2520 n = n*10 + uint32(c-'0') 2521 } 2522 return n 2523 } 2524 if l > 10 { 2525 // guaranteed to overflow 2526 return math.MaxUint32 2527 } 2528 c9 := s[9] 2529 if c9 < '0' || c9 > '9' { 2530 return math.MaxUint32 2531 } 2532 for i := 0; i < 9; i++ { 2533 c := s[i] 2534 if c < '0' || c > '9' { 2535 return math.MaxUint32 2536 } 2537 n = n*10 + uint32(c-'0') 2538 } 2539 if n >= math.MaxUint32/10+1 { 2540 return math.MaxUint32 2541 } 2542 n *= 10 2543 n1 := n + uint32(c9-'0') 2544 if n1 < n { 2545 return math.MaxUint32 2546 } 2547 2548 return n1 2549} 2550 2551func strToInt32(s unistring.String) (int32, bool) { 2552 if s == "" { 2553 return -1, false 2554 } 2555 neg := s[0] == '-' 2556 if neg { 2557 s = s[1:] 2558 } 2559 l := len(s) 2560 if s[0] == '0' { 2561 if l == 1 { 2562 return 0, !neg 2563 } 2564 return -1, false 2565 } 2566 var n uint32 2567 if l < 10 { 2568 // guaranteed not to overflow 2569 for i := 0; i < len(s); i++ { 2570 c := s[i] 2571 if c < '0' || c > '9' { 2572 return -1, false 2573 } 2574 n = n*10 + uint32(c-'0') 2575 } 2576 } else if l > 10 { 2577 // guaranteed to overflow 2578 return -1, false 2579 } else { 2580 c9 := s[9] 2581 if c9 >= '0' { 2582 if !neg && c9 > '7' || c9 > '8' { 2583 // guaranteed to overflow 2584 return -1, false 2585 } 2586 for i := 0; i < 9; i++ { 2587 c := s[i] 2588 if c < '0' || c > '9' { 2589 return -1, false 2590 } 2591 n = n*10 + uint32(c-'0') 2592 } 2593 if n >= math.MaxInt32/10+1 { 2594 // valid number, but it overflows integer 2595 return 0, false 2596 } 2597 n = n*10 + uint32(c9-'0') 2598 } else { 2599 return -1, false 2600 } 2601 } 2602 if neg { 2603 return int32(-n), true 2604 } 2605 return int32(n), true 2606} 2607 2608func strToInt64(s unistring.String) (int64, bool) { 2609 if s == "" { 2610 return -1, false 2611 } 2612 neg := s[0] == '-' 2613 if neg { 2614 s = s[1:] 2615 } 2616 l := len(s) 2617 if s[0] == '0' { 2618 if l == 1 { 2619 return 0, !neg 2620 } 2621 return -1, false 2622 } 2623 var n uint64 2624 if l < 19 { 2625 // guaranteed not to overflow 2626 for i := 0; i < len(s); i++ { 2627 c := s[i] 2628 if c < '0' || c > '9' { 2629 return -1, false 2630 } 2631 n = n*10 + uint64(c-'0') 2632 } 2633 } else if l > 19 { 2634 // guaranteed to overflow 2635 return -1, false 2636 } else { 2637 c18 := s[18] 2638 if c18 >= '0' { 2639 if !neg && c18 > '7' || c18 > '8' { 2640 // guaranteed to overflow 2641 return -1, false 2642 } 2643 for i := 0; i < 18; i++ { 2644 c := s[i] 2645 if c < '0' || c > '9' { 2646 return -1, false 2647 } 2648 n = n*10 + uint64(c-'0') 2649 } 2650 if n >= math.MaxInt64/10+1 { 2651 // valid number, but it overflows integer 2652 return 0, false 2653 } 2654 n = n*10 + uint64(c18-'0') 2655 } else { 2656 return -1, false 2657 } 2658 } 2659 if neg { 2660 return int64(-n), true 2661 } 2662 return int64(n), true 2663} 2664 2665func strToInt(s unistring.String) (int, bool) { 2666 if bits.UintSize == 32 { 2667 n, ok := strToInt32(s) 2668 return int(n), ok 2669 } 2670 n, ok := strToInt64(s) 2671 return int(n), ok 2672} 2673 2674// Attempts to convert a string into a canonical integer. 2675// On success returns (number, true). 2676// If it was a canonical number, but not an integer returns (0, false). This includes -0 and overflows. 2677// In all other cases returns (-1, false). 2678// See https://262.ecma-international.org/#sec-canonicalnumericindexstring 2679func strToIntNum(s unistring.String) (int, bool) { 2680 n, ok := strToInt64(s) 2681 if n == 0 { 2682 return 0, ok 2683 } 2684 if ok && n >= -maxInt && n <= maxInt { 2685 if bits.UintSize == 32 { 2686 if n > math.MaxInt32 || n < math.MinInt32 { 2687 return 0, false 2688 } 2689 } 2690 return int(n), true 2691 } 2692 str := stringValueFromRaw(s) 2693 if str.ToNumber().toString().SameAs(str) { 2694 return 0, false 2695 } 2696 return -1, false 2697} 2698 2699func strToGoIdx(s unistring.String) int { 2700 if n, ok := strToInt(s); ok { 2701 return n 2702 } 2703 return -1 2704} 2705 2706func strToIdx64(s unistring.String) int64 { 2707 if n, ok := strToInt64(s); ok { 2708 return n 2709 } 2710 return -1 2711} 2712