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