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