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