github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/value.go (about) 1 package goja 2 3 import ( 4 "fmt" 5 "hash/maphash" 6 "math" 7 "reflect" 8 "strconv" 9 "unsafe" 10 11 "github.com/nuvolaris/goja/ftoa" 12 "github.com/nuvolaris/goja/unistring" 13 ) 14 15 var ( 16 // Not goroutine-safe, do not use for anything other than package level init 17 pkgHasher maphash.Hash 18 19 hashFalse = randomHash() 20 hashTrue = randomHash() 21 hashNull = randomHash() 22 hashUndef = randomHash() 23 ) 24 25 // Not goroutine-safe, do not use for anything other than package level init 26 func randomHash() uint64 { 27 pkgHasher.WriteByte(0) 28 return pkgHasher.Sum64() 29 } 30 31 var ( 32 valueFalse Value = valueBool(false) 33 valueTrue Value = valueBool(true) 34 _null Value = valueNull{} 35 _NaN Value = valueFloat(math.NaN()) 36 _positiveInf Value = valueFloat(math.Inf(+1)) 37 _negativeInf Value = valueFloat(math.Inf(-1)) 38 _positiveZero Value = valueInt(0) 39 negativeZero = math.Float64frombits(0 | (1 << 63)) 40 _negativeZero Value = valueFloat(negativeZero) 41 _epsilon = valueFloat(2.2204460492503130808472633361816e-16) 42 _undefined Value = valueUndefined{} 43 ) 44 45 var ( 46 reflectTypeInt = reflect.TypeOf(int64(0)) 47 reflectTypeBool = reflect.TypeOf(false) 48 reflectTypeNil = reflect.TypeOf(nil) 49 reflectTypeFloat = reflect.TypeOf(float64(0)) 50 reflectTypeMap = reflect.TypeOf(map[string]interface{}{}) 51 reflectTypeArray = reflect.TypeOf([]interface{}{}) 52 reflectTypeArrayPtr = reflect.TypeOf((*[]interface{})(nil)) 53 reflectTypeString = reflect.TypeOf("") 54 reflectTypeFunc = reflect.TypeOf((func(FunctionCall) Value)(nil)) 55 reflectTypeError = reflect.TypeOf((*error)(nil)).Elem() 56 ) 57 58 var intCache [256]Value 59 60 // Value represents an ECMAScript value. 61 // 62 // Export returns a "plain" Go value which type depends on the type of the Value. 63 // 64 // For integer numbers it's int64. 65 // 66 // For any other numbers (including Infinities, NaN and negative zero) it's float64. 67 // 68 // For string it's a string. Note that unicode strings are converted into UTF-8 with invalid code points replaced with utf8.RuneError. 69 // 70 // For boolean it's bool. 71 // 72 // For null and undefined it's nil. 73 // 74 // For Object it depends on the Object type, see Object.Export() for more details. 75 type Value interface { 76 ToInteger() int64 77 toString() String 78 string() unistring.String 79 ToString() Value 80 String() string 81 ToFloat() float64 82 ToNumber() Value 83 ToBoolean() bool 84 ToObject(*Runtime) *Object 85 SameAs(Value) bool 86 Equals(Value) bool 87 StrictEquals(Value) bool 88 Export() interface{} 89 ExportType() reflect.Type 90 91 baseObject(r *Runtime) *Object 92 93 hash(hasher *maphash.Hash) uint64 94 } 95 96 type valueContainer interface { 97 toValue(*Runtime) Value 98 } 99 100 type typeError string 101 type rangeError string 102 type referenceError string 103 type syntaxError string 104 105 type valueInt int64 106 type valueFloat float64 107 type valueBool bool 108 type valueNull struct{} 109 type valueUndefined struct { 110 valueNull 111 } 112 113 // *Symbol is a Value containing ECMAScript Symbol primitive. Symbols must only be created 114 // using NewSymbol(). Zero values and copying of values (i.e. *s1 = *s2) are not permitted. 115 // Well-known Symbols can be accessed using Sym* package variables (SymIterator, etc...) 116 // Symbols can be shared by multiple Runtimes. 117 type Symbol struct { 118 h uintptr 119 desc String 120 } 121 122 type valueUnresolved struct { 123 r *Runtime 124 ref unistring.String 125 } 126 127 type memberUnresolved struct { 128 valueUnresolved 129 } 130 131 type valueProperty struct { 132 value Value 133 writable bool 134 configurable bool 135 enumerable bool 136 accessor bool 137 getterFunc *Object 138 setterFunc *Object 139 } 140 141 var ( 142 errAccessBeforeInit = referenceError("Cannot access a variable before initialization") 143 errAssignToConst = typeError("Assignment to constant variable.") 144 ) 145 146 func propGetter(o Value, v Value, r *Runtime) *Object { 147 if v == _undefined { 148 return nil 149 } 150 if obj, ok := v.(*Object); ok { 151 if _, ok := obj.self.assertCallable(); ok { 152 return obj 153 } 154 } 155 r.typeErrorResult(true, "Getter must be a function: %s", v.toString()) 156 return nil 157 } 158 159 func propSetter(o Value, v Value, r *Runtime) *Object { 160 if v == _undefined { 161 return nil 162 } 163 if obj, ok := v.(*Object); ok { 164 if _, ok := obj.self.assertCallable(); ok { 165 return obj 166 } 167 } 168 r.typeErrorResult(true, "Setter must be a function: %s", v.toString()) 169 return nil 170 } 171 172 func fToStr(num float64, mode ftoa.FToStrMode, prec int) string { 173 var buf1 [128]byte 174 return string(ftoa.FToStr(num, mode, prec, buf1[:0])) 175 } 176 177 func (i valueInt) ToInteger() int64 { 178 return int64(i) 179 } 180 181 func (i valueInt) toString() String { 182 return asciiString(i.String()) 183 } 184 185 func (i valueInt) string() unistring.String { 186 return unistring.String(i.String()) 187 } 188 189 func (i valueInt) ToString() Value { 190 return i 191 } 192 193 func (i valueInt) String() string { 194 return strconv.FormatInt(int64(i), 10) 195 } 196 197 func (i valueInt) ToFloat() float64 { 198 return float64(i) 199 } 200 201 func (i valueInt) ToBoolean() bool { 202 return i != 0 203 } 204 205 func (i valueInt) ToObject(r *Runtime) *Object { 206 return r.newPrimitiveObject(i, r.global.NumberPrototype, classNumber) 207 } 208 209 func (i valueInt) ToNumber() Value { 210 return i 211 } 212 213 func (i valueInt) SameAs(other Value) bool { 214 return i == other 215 } 216 217 func (i valueInt) Equals(other Value) bool { 218 switch o := other.(type) { 219 case valueInt: 220 return i == o 221 case valueFloat: 222 return float64(i) == float64(o) 223 case String: 224 return o.ToNumber().Equals(i) 225 case valueBool: 226 return int64(i) == o.ToInteger() 227 case *Object: 228 return i.Equals(o.toPrimitive()) 229 } 230 231 return false 232 } 233 234 func (i valueInt) StrictEquals(other Value) bool { 235 switch o := other.(type) { 236 case valueInt: 237 return i == o 238 case valueFloat: 239 return float64(i) == float64(o) 240 } 241 242 return false 243 } 244 245 func (i valueInt) baseObject(r *Runtime) *Object { 246 return r.global.NumberPrototype 247 } 248 249 func (i valueInt) Export() interface{} { 250 return int64(i) 251 } 252 253 func (i valueInt) ExportType() reflect.Type { 254 return reflectTypeInt 255 } 256 257 func (i valueInt) hash(*maphash.Hash) uint64 { 258 return uint64(i) 259 } 260 261 func (b valueBool) ToInteger() int64 { 262 if b { 263 return 1 264 } 265 return 0 266 } 267 268 func (b valueBool) toString() String { 269 if b { 270 return stringTrue 271 } 272 return stringFalse 273 } 274 275 func (b valueBool) ToString() Value { 276 return b 277 } 278 279 func (b valueBool) String() string { 280 if b { 281 return "true" 282 } 283 return "false" 284 } 285 286 func (b valueBool) string() unistring.String { 287 return unistring.String(b.String()) 288 } 289 290 func (b valueBool) ToFloat() float64 { 291 if b { 292 return 1.0 293 } 294 return 0 295 } 296 297 func (b valueBool) ToBoolean() bool { 298 return bool(b) 299 } 300 301 func (b valueBool) ToObject(r *Runtime) *Object { 302 return r.newPrimitiveObject(b, r.global.BooleanPrototype, "Boolean") 303 } 304 305 func (b valueBool) ToNumber() Value { 306 if b { 307 return valueInt(1) 308 } 309 return valueInt(0) 310 } 311 312 func (b valueBool) SameAs(other Value) bool { 313 if other, ok := other.(valueBool); ok { 314 return b == other 315 } 316 return false 317 } 318 319 func (b valueBool) Equals(other Value) bool { 320 if o, ok := other.(valueBool); ok { 321 return b == o 322 } 323 324 if b { 325 return other.Equals(intToValue(1)) 326 } else { 327 return other.Equals(intToValue(0)) 328 } 329 330 } 331 332 func (b valueBool) StrictEquals(other Value) bool { 333 if other, ok := other.(valueBool); ok { 334 return b == other 335 } 336 return false 337 } 338 339 func (b valueBool) baseObject(r *Runtime) *Object { 340 return r.global.BooleanPrototype 341 } 342 343 func (b valueBool) Export() interface{} { 344 return bool(b) 345 } 346 347 func (b valueBool) ExportType() reflect.Type { 348 return reflectTypeBool 349 } 350 351 func (b valueBool) hash(*maphash.Hash) uint64 { 352 if b { 353 return hashTrue 354 } 355 356 return hashFalse 357 } 358 359 func (n valueNull) ToInteger() int64 { 360 return 0 361 } 362 363 func (n valueNull) toString() String { 364 return stringNull 365 } 366 367 func (n valueNull) string() unistring.String { 368 return stringNull.string() 369 } 370 371 func (n valueNull) ToString() Value { 372 return n 373 } 374 375 func (n valueNull) String() string { 376 return "null" 377 } 378 379 func (u valueUndefined) toString() String { 380 return stringUndefined 381 } 382 383 func (u valueUndefined) ToString() Value { 384 return u 385 } 386 387 func (u valueUndefined) String() string { 388 return "undefined" 389 } 390 391 func (u valueUndefined) string() unistring.String { 392 return "undefined" 393 } 394 395 func (u valueUndefined) ToNumber() Value { 396 return _NaN 397 } 398 399 func (u valueUndefined) SameAs(other Value) bool { 400 _, same := other.(valueUndefined) 401 return same 402 } 403 404 func (u valueUndefined) StrictEquals(other Value) bool { 405 _, same := other.(valueUndefined) 406 return same 407 } 408 409 func (u valueUndefined) ToFloat() float64 { 410 return math.NaN() 411 } 412 413 func (u valueUndefined) hash(*maphash.Hash) uint64 { 414 return hashUndef 415 } 416 417 func (n valueNull) ToFloat() float64 { 418 return 0 419 } 420 421 func (n valueNull) ToBoolean() bool { 422 return false 423 } 424 425 func (n valueNull) ToObject(r *Runtime) *Object { 426 r.typeErrorResult(true, "Cannot convert undefined or null to object") 427 return nil 428 //return r.newObject() 429 } 430 431 func (n valueNull) ToNumber() Value { 432 return intToValue(0) 433 } 434 435 func (n valueNull) SameAs(other Value) bool { 436 _, same := other.(valueNull) 437 return same 438 } 439 440 func (n valueNull) Equals(other Value) bool { 441 switch other.(type) { 442 case valueUndefined, valueNull: 443 return true 444 } 445 return false 446 } 447 448 func (n valueNull) StrictEquals(other Value) bool { 449 _, same := other.(valueNull) 450 return same 451 } 452 453 func (n valueNull) baseObject(*Runtime) *Object { 454 return nil 455 } 456 457 func (n valueNull) Export() interface{} { 458 return nil 459 } 460 461 func (n valueNull) ExportType() reflect.Type { 462 return reflectTypeNil 463 } 464 465 func (n valueNull) hash(*maphash.Hash) uint64 { 466 return hashNull 467 } 468 469 func (p *valueProperty) ToInteger() int64 { 470 return 0 471 } 472 473 func (p *valueProperty) toString() String { 474 return stringEmpty 475 } 476 477 func (p *valueProperty) string() unistring.String { 478 return "" 479 } 480 481 func (p *valueProperty) ToString() Value { 482 return _undefined 483 } 484 485 func (p *valueProperty) String() string { 486 return "" 487 } 488 489 func (p *valueProperty) ToFloat() float64 { 490 return math.NaN() 491 } 492 493 func (p *valueProperty) ToBoolean() bool { 494 return false 495 } 496 497 func (p *valueProperty) ToObject(*Runtime) *Object { 498 return nil 499 } 500 501 func (p *valueProperty) ToNumber() Value { 502 return nil 503 } 504 505 func (p *valueProperty) isWritable() bool { 506 return p.writable || p.setterFunc != nil 507 } 508 509 func (p *valueProperty) get(this Value) Value { 510 if p.getterFunc == nil { 511 if p.value != nil { 512 return p.value 513 } 514 return _undefined 515 } 516 call, _ := p.getterFunc.self.assertCallable() 517 return call(FunctionCall{ 518 This: this, 519 }) 520 } 521 522 func (p *valueProperty) set(this, v Value) { 523 if p.setterFunc == nil { 524 p.value = v 525 return 526 } 527 call, _ := p.setterFunc.self.assertCallable() 528 call(FunctionCall{ 529 This: this, 530 Arguments: []Value{v}, 531 }) 532 } 533 534 func (p *valueProperty) SameAs(other Value) bool { 535 if otherProp, ok := other.(*valueProperty); ok { 536 return p == otherProp 537 } 538 return false 539 } 540 541 func (p *valueProperty) Equals(Value) bool { 542 return false 543 } 544 545 func (p *valueProperty) StrictEquals(Value) bool { 546 return false 547 } 548 549 func (p *valueProperty) baseObject(r *Runtime) *Object { 550 r.typeErrorResult(true, "BUG: baseObject() is called on valueProperty") // TODO error message 551 return nil 552 } 553 554 func (p *valueProperty) Export() interface{} { 555 panic("Cannot export valueProperty") 556 } 557 558 func (p *valueProperty) ExportType() reflect.Type { 559 panic("Cannot export valueProperty") 560 } 561 562 func (p *valueProperty) hash(*maphash.Hash) uint64 { 563 panic("valueProperty should never be used in maps or sets") 564 } 565 566 func floatToIntClip(n float64) int64 { 567 switch { 568 case math.IsNaN(n): 569 return 0 570 case n >= math.MaxInt64: 571 return math.MaxInt64 572 case n <= math.MinInt64: 573 return math.MinInt64 574 } 575 return int64(n) 576 } 577 578 func (f valueFloat) ToInteger() int64 { 579 return floatToIntClip(float64(f)) 580 } 581 582 func (f valueFloat) toString() String { 583 return asciiString(f.String()) 584 } 585 586 func (f valueFloat) string() unistring.String { 587 return unistring.String(f.String()) 588 } 589 590 func (f valueFloat) ToString() Value { 591 return f 592 } 593 594 func (f valueFloat) String() string { 595 return fToStr(float64(f), ftoa.ModeStandard, 0) 596 } 597 598 func (f valueFloat) ToFloat() float64 { 599 return float64(f) 600 } 601 602 func (f valueFloat) ToBoolean() bool { 603 return float64(f) != 0.0 && !math.IsNaN(float64(f)) 604 } 605 606 func (f valueFloat) ToObject(r *Runtime) *Object { 607 return r.newPrimitiveObject(f, r.global.NumberPrototype, "Number") 608 } 609 610 func (f valueFloat) ToNumber() Value { 611 return f 612 } 613 614 func (f valueFloat) SameAs(other Value) bool { 615 switch o := other.(type) { 616 case valueFloat: 617 this := float64(f) 618 o1 := float64(o) 619 if math.IsNaN(this) && math.IsNaN(o1) { 620 return true 621 } else { 622 ret := this == o1 623 if ret && this == 0 { 624 ret = math.Signbit(this) == math.Signbit(o1) 625 } 626 return ret 627 } 628 case valueInt: 629 this := float64(f) 630 ret := this == float64(o) 631 if ret && this == 0 { 632 ret = !math.Signbit(this) 633 } 634 return ret 635 } 636 637 return false 638 } 639 640 func (f valueFloat) Equals(other Value) bool { 641 switch o := other.(type) { 642 case valueFloat: 643 return f == o 644 case valueInt: 645 return float64(f) == float64(o) 646 case String, valueBool: 647 return float64(f) == o.ToFloat() 648 case *Object: 649 return f.Equals(o.toPrimitive()) 650 } 651 652 return false 653 } 654 655 func (f valueFloat) StrictEquals(other Value) bool { 656 switch o := other.(type) { 657 case valueFloat: 658 return f == o 659 case valueInt: 660 return float64(f) == float64(o) 661 } 662 663 return false 664 } 665 666 func (f valueFloat) baseObject(r *Runtime) *Object { 667 return r.global.NumberPrototype 668 } 669 670 func (f valueFloat) Export() interface{} { 671 return float64(f) 672 } 673 674 func (f valueFloat) ExportType() reflect.Type { 675 return reflectTypeFloat 676 } 677 678 func (f valueFloat) hash(*maphash.Hash) uint64 { 679 if f == _negativeZero { 680 return 0 681 } 682 return math.Float64bits(float64(f)) 683 } 684 685 func (o *Object) ToInteger() int64 { 686 return o.toPrimitiveNumber().ToNumber().ToInteger() 687 } 688 689 func (o *Object) toString() String { 690 return o.toPrimitiveString().toString() 691 } 692 693 func (o *Object) string() unistring.String { 694 return o.toPrimitiveString().string() 695 } 696 697 func (o *Object) ToString() Value { 698 return o.toPrimitiveString().ToString() 699 } 700 701 func (o *Object) String() string { 702 return o.toPrimitiveString().String() 703 } 704 705 func (o *Object) ToFloat() float64 { 706 return o.toPrimitiveNumber().ToFloat() 707 } 708 709 func (o *Object) ToBoolean() bool { 710 return true 711 } 712 713 func (o *Object) ToObject(*Runtime) *Object { 714 return o 715 } 716 717 func (o *Object) ToNumber() Value { 718 return o.toPrimitiveNumber().ToNumber() 719 } 720 721 func (o *Object) SameAs(other Value) bool { 722 return o.StrictEquals(other) 723 } 724 725 func (o *Object) Equals(other Value) bool { 726 if other, ok := other.(*Object); ok { 727 return o == other || o.self.equal(other.self) 728 } 729 730 switch o1 := other.(type) { 731 case valueInt, valueFloat, String, *Symbol: 732 return o.toPrimitive().Equals(other) 733 case valueBool: 734 return o.Equals(o1.ToNumber()) 735 } 736 737 return false 738 } 739 740 func (o *Object) StrictEquals(other Value) bool { 741 if other, ok := other.(*Object); ok { 742 return o == other || o != nil && other != nil && o.self.equal(other.self) 743 } 744 return false 745 } 746 747 func (o *Object) baseObject(*Runtime) *Object { 748 return o 749 } 750 751 // Export the Object to a plain Go type. 752 // If the Object is a wrapped Go value (created using ToValue()) returns the original value. 753 // 754 // If the Object is a function, returns func(FunctionCall) Value. Note that exceptions thrown inside the function 755 // result in panics, which can also leave the Runtime in an unusable state. Therefore, these values should only 756 // be used inside another ES function implemented in Go. For calling a function from Go, use AssertFunction() or 757 // Runtime.ExportTo() as described in the README. 758 // 759 // For a Map, returns the list of entries as [][2]interface{}. 760 // 761 // For a Set, returns the list of elements as []interface{}. 762 // 763 // For a Proxy, returns Proxy. 764 // 765 // For a Promise, returns Promise. 766 // 767 // For a DynamicObject or a DynamicArray, returns the underlying handler. 768 // 769 // For typed arrays it returns a slice of the corresponding type backed by the original data (i.e. it does not copy). 770 // 771 // For an untyped array, returns its items exported into a newly created []interface{}. 772 // 773 // In all other cases returns own enumerable non-symbol properties as map[string]interface{}. 774 // 775 // This method will panic with an *Exception if a JavaScript exception is thrown in the process. 776 func (o *Object) Export() interface{} { 777 return o.self.export(&objectExportCtx{}) 778 } 779 780 // ExportType returns the type of the value that is returned by Export(). 781 func (o *Object) ExportType() reflect.Type { 782 return o.self.exportType() 783 } 784 785 func (o *Object) hash(*maphash.Hash) uint64 { 786 return o.getId() 787 } 788 789 // Get an object's property by name. 790 // This method will panic with an *Exception if a JavaScript exception is thrown in the process. 791 func (o *Object) Get(name string) Value { 792 return o.self.getStr(unistring.NewFromString(name), nil) 793 } 794 795 // GetSymbol returns the value of a symbol property. Use one of the Sym* values for well-known 796 // symbols (such as SymIterator, SymToStringTag, etc...). 797 // This method will panic with an *Exception if a JavaScript exception is thrown in the process. 798 func (o *Object) GetSymbol(sym *Symbol) Value { 799 return o.self.getSym(sym, nil) 800 } 801 802 // Keys returns a list of Object's enumerable keys. 803 // This method will panic with an *Exception if a JavaScript exception is thrown in the process. 804 func (o *Object) Keys() (keys []string) { 805 iter := &enumerableIter{ 806 o: o, 807 wrapped: o.self.iterateStringKeys(), 808 } 809 for item, next := iter.next(); next != nil; item, next = next() { 810 keys = append(keys, item.name.String()) 811 } 812 813 return 814 } 815 816 // Symbols returns a list of Object's enumerable symbol properties. 817 // This method will panic with an *Exception if a JavaScript exception is thrown in the process. 818 func (o *Object) Symbols() []*Symbol { 819 symbols := o.self.symbols(false, nil) 820 ret := make([]*Symbol, len(symbols)) 821 for i, sym := range symbols { 822 ret[i], _ = sym.(*Symbol) 823 } 824 return ret 825 } 826 827 // DefineDataProperty is a Go equivalent of Object.defineProperty(o, name, {value: value, writable: writable, 828 // configurable: configurable, enumerable: enumerable}) 829 func (o *Object) DefineDataProperty(name string, value Value, writable, configurable, enumerable Flag) error { 830 return o.runtime.try(func() { 831 o.self.defineOwnPropertyStr(unistring.NewFromString(name), PropertyDescriptor{ 832 Value: value, 833 Writable: writable, 834 Configurable: configurable, 835 Enumerable: enumerable, 836 }, true) 837 }) 838 } 839 840 // DefineAccessorProperty is a Go equivalent of Object.defineProperty(o, name, {get: getter, set: setter, 841 // configurable: configurable, enumerable: enumerable}) 842 func (o *Object) DefineAccessorProperty(name string, getter, setter Value, configurable, enumerable Flag) error { 843 return o.runtime.try(func() { 844 o.self.defineOwnPropertyStr(unistring.NewFromString(name), PropertyDescriptor{ 845 Getter: getter, 846 Setter: setter, 847 Configurable: configurable, 848 Enumerable: enumerable, 849 }, true) 850 }) 851 } 852 853 // DefineDataPropertySymbol is a Go equivalent of Object.defineProperty(o, name, {value: value, writable: writable, 854 // configurable: configurable, enumerable: enumerable}) 855 func (o *Object) DefineDataPropertySymbol(name *Symbol, value Value, writable, configurable, enumerable Flag) error { 856 return o.runtime.try(func() { 857 o.self.defineOwnPropertySym(name, PropertyDescriptor{ 858 Value: value, 859 Writable: writable, 860 Configurable: configurable, 861 Enumerable: enumerable, 862 }, true) 863 }) 864 } 865 866 // DefineAccessorPropertySymbol is a Go equivalent of Object.defineProperty(o, name, {get: getter, set: setter, 867 // configurable: configurable, enumerable: enumerable}) 868 func (o *Object) DefineAccessorPropertySymbol(name *Symbol, getter, setter Value, configurable, enumerable Flag) error { 869 return o.runtime.try(func() { 870 o.self.defineOwnPropertySym(name, PropertyDescriptor{ 871 Getter: getter, 872 Setter: setter, 873 Configurable: configurable, 874 Enumerable: enumerable, 875 }, true) 876 }) 877 } 878 879 func (o *Object) Set(name string, value interface{}) error { 880 return o.runtime.try(func() { 881 o.self.setOwnStr(unistring.NewFromString(name), o.runtime.ToValue(value), true) 882 }) 883 } 884 885 func (o *Object) SetSymbol(name *Symbol, value interface{}) error { 886 return o.runtime.try(func() { 887 o.self.setOwnSym(name, o.runtime.ToValue(value), true) 888 }) 889 } 890 891 func (o *Object) Delete(name string) error { 892 return o.runtime.try(func() { 893 o.self.deleteStr(unistring.NewFromString(name), true) 894 }) 895 } 896 897 func (o *Object) DeleteSymbol(name *Symbol) error { 898 return o.runtime.try(func() { 899 o.self.deleteSym(name, true) 900 }) 901 } 902 903 // Prototype returns the Object's prototype, same as Object.getPrototypeOf(). If the prototype is null 904 // returns nil. 905 func (o *Object) Prototype() *Object { 906 return o.self.proto() 907 } 908 909 // SetPrototype sets the Object's prototype, same as Object.setPrototypeOf(). Setting proto to nil 910 // is an equivalent of Object.setPrototypeOf(null). 911 func (o *Object) SetPrototype(proto *Object) error { 912 return o.runtime.try(func() { 913 o.self.setProto(proto, true) 914 }) 915 } 916 917 // MarshalJSON returns JSON representation of the Object. It is equivalent to JSON.stringify(o). 918 // Note, this implements json.Marshaler so that json.Marshal() can be used without the need to Export(). 919 func (o *Object) MarshalJSON() ([]byte, error) { 920 ctx := _builtinJSON_stringifyContext{ 921 r: o.runtime, 922 } 923 ex := o.runtime.vm.try(func() { 924 if !ctx.do(o) { 925 ctx.buf.WriteString("null") 926 } 927 }) 928 if ex != nil { 929 return nil, ex 930 } 931 return ctx.buf.Bytes(), nil 932 } 933 934 // UnmarshalJSON implements the json.Unmarshaler interface. It is added to compliment MarshalJSON, because 935 // some alternative JSON encoders refuse to use MarshalJSON unless UnmarshalJSON is also present. 936 // It is a no-op and always returns nil. 937 func (o *Object) UnmarshalJSON([]byte) error { 938 return nil 939 } 940 941 // ClassName returns the class name 942 func (o *Object) ClassName() string { 943 return o.self.className() 944 } 945 946 func (o valueUnresolved) throw() { 947 o.r.throwReferenceError(o.ref) 948 } 949 950 func (o valueUnresolved) ToInteger() int64 { 951 o.throw() 952 return 0 953 } 954 955 func (o valueUnresolved) toString() String { 956 o.throw() 957 return nil 958 } 959 960 func (o valueUnresolved) string() unistring.String { 961 o.throw() 962 return "" 963 } 964 965 func (o valueUnresolved) ToString() Value { 966 o.throw() 967 return nil 968 } 969 970 func (o valueUnresolved) String() string { 971 o.throw() 972 return "" 973 } 974 975 func (o valueUnresolved) ToFloat() float64 { 976 o.throw() 977 return 0 978 } 979 980 func (o valueUnresolved) ToBoolean() bool { 981 o.throw() 982 return false 983 } 984 985 func (o valueUnresolved) ToObject(*Runtime) *Object { 986 o.throw() 987 return nil 988 } 989 990 func (o valueUnresolved) ToNumber() Value { 991 o.throw() 992 return nil 993 } 994 995 func (o valueUnresolved) SameAs(Value) bool { 996 o.throw() 997 return false 998 } 999 1000 func (o valueUnresolved) Equals(Value) bool { 1001 o.throw() 1002 return false 1003 } 1004 1005 func (o valueUnresolved) StrictEquals(Value) bool { 1006 o.throw() 1007 return false 1008 } 1009 1010 func (o valueUnresolved) baseObject(*Runtime) *Object { 1011 o.throw() 1012 return nil 1013 } 1014 1015 func (o valueUnresolved) Export() interface{} { 1016 o.throw() 1017 return nil 1018 } 1019 1020 func (o valueUnresolved) ExportType() reflect.Type { 1021 o.throw() 1022 return nil 1023 } 1024 1025 func (o valueUnresolved) hash(*maphash.Hash) uint64 { 1026 o.throw() 1027 return 0 1028 } 1029 1030 func (s *Symbol) ToInteger() int64 { 1031 panic(typeError("Cannot convert a Symbol value to a number")) 1032 } 1033 1034 func (s *Symbol) toString() String { 1035 panic(typeError("Cannot convert a Symbol value to a string")) 1036 } 1037 1038 func (s *Symbol) ToString() Value { 1039 return s 1040 } 1041 1042 func (s *Symbol) String() string { 1043 if s.desc != nil { 1044 return s.desc.String() 1045 } 1046 return "" 1047 } 1048 1049 func (s *Symbol) string() unistring.String { 1050 if s.desc != nil { 1051 return s.desc.string() 1052 } 1053 return "" 1054 } 1055 1056 func (s *Symbol) ToFloat() float64 { 1057 panic(typeError("Cannot convert a Symbol value to a number")) 1058 } 1059 1060 func (s *Symbol) ToNumber() Value { 1061 panic(typeError("Cannot convert a Symbol value to a number")) 1062 } 1063 1064 func (s *Symbol) ToBoolean() bool { 1065 return true 1066 } 1067 1068 func (s *Symbol) ToObject(r *Runtime) *Object { 1069 return s.baseObject(r) 1070 } 1071 1072 func (s *Symbol) SameAs(other Value) bool { 1073 if s1, ok := other.(*Symbol); ok { 1074 return s == s1 1075 } 1076 return false 1077 } 1078 1079 func (s *Symbol) Equals(o Value) bool { 1080 switch o := o.(type) { 1081 case *Object: 1082 return s.Equals(o.toPrimitive()) 1083 } 1084 return s.SameAs(o) 1085 } 1086 1087 func (s *Symbol) StrictEquals(o Value) bool { 1088 return s.SameAs(o) 1089 } 1090 1091 func (s *Symbol) Export() interface{} { 1092 return s.String() 1093 } 1094 1095 func (s *Symbol) ExportType() reflect.Type { 1096 return reflectTypeString 1097 } 1098 1099 func (s *Symbol) baseObject(r *Runtime) *Object { 1100 return r.newPrimitiveObject(s, r.global.SymbolPrototype, classObject) 1101 } 1102 1103 func (s *Symbol) hash(*maphash.Hash) uint64 { 1104 return uint64(s.h) 1105 } 1106 1107 func exportValue(v Value, ctx *objectExportCtx) interface{} { 1108 if obj, ok := v.(*Object); ok { 1109 return obj.self.export(ctx) 1110 } 1111 return v.Export() 1112 } 1113 1114 func newSymbol(s String) *Symbol { 1115 r := &Symbol{ 1116 desc: s, 1117 } 1118 // This may need to be reconsidered in the future. 1119 // Depending on changes in Go's allocation policy and/or introduction of a compacting GC 1120 // this may no longer provide sufficient dispersion. The alternative, however, is a globally 1121 // synchronised random generator/hasher/sequencer and I don't want to go down that route just yet. 1122 r.h = uintptr(unsafe.Pointer(r)) 1123 return r 1124 } 1125 1126 func NewSymbol(s string) *Symbol { 1127 return newSymbol(newStringValue(s)) 1128 } 1129 1130 func (s *Symbol) descriptiveString() String { 1131 desc := s.desc 1132 if desc == nil { 1133 desc = stringEmpty 1134 } 1135 return asciiString("Symbol(").Concat(desc).Concat(asciiString(")")) 1136 } 1137 1138 func funcName(prefix string, n Value) String { 1139 var b StringBuilder 1140 b.WriteString(asciiString(prefix)) 1141 if sym, ok := n.(*Symbol); ok { 1142 if sym.desc != nil { 1143 b.WriteRune('[') 1144 b.WriteString(sym.desc) 1145 b.WriteRune(']') 1146 } 1147 } else { 1148 b.WriteString(n.toString()) 1149 } 1150 return b.String() 1151 } 1152 1153 func newTypeError(args ...interface{}) typeError { 1154 msg := "" 1155 if len(args) > 0 { 1156 f, _ := args[0].(string) 1157 msg = fmt.Sprintf(f, args[1:]...) 1158 } 1159 return typeError(msg) 1160 } 1161 1162 func typeErrorResult(throw bool, args ...interface{}) { 1163 if throw { 1164 panic(newTypeError(args...)) 1165 } 1166 1167 } 1168 1169 func init() { 1170 for i := 0; i < 256; i++ { 1171 intCache[i] = valueInt(i - 256) 1172 } 1173 }