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