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