1package goja 2 3import ( 4 "math" 5 "reflect" 6 "regexp" 7 "strconv" 8) 9 10var ( 11 valueFalse Value = valueBool(false) 12 valueTrue Value = valueBool(true) 13 _null Value = valueNull{} 14 _NaN Value = valueFloat(math.NaN()) 15 _positiveInf Value = valueFloat(math.Inf(+1)) 16 _negativeInf Value = valueFloat(math.Inf(-1)) 17 _positiveZero Value 18 _negativeZero Value = valueFloat(math.Float64frombits(0 | (1 << 63))) 19 _epsilon = valueFloat(2.2204460492503130808472633361816e-16) 20 _undefined Value = valueUndefined{} 21) 22 23var ( 24 reflectTypeInt = reflect.TypeOf(int64(0)) 25 reflectTypeBool = reflect.TypeOf(false) 26 reflectTypeNil = reflect.TypeOf(nil) 27 reflectTypeFloat = reflect.TypeOf(float64(0)) 28 reflectTypeMap = reflect.TypeOf(map[string]interface{}{}) 29 reflectTypeArray = reflect.TypeOf([]interface{}{}) 30 reflectTypeString = reflect.TypeOf("") 31) 32 33var intCache [256]Value 34 35type Value interface { 36 ToInteger() int64 37 ToString() valueString 38 String() string 39 ToFloat() float64 40 ToNumber() Value 41 ToBoolean() bool 42 ToObject(*Runtime) *Object 43 SameAs(Value) bool 44 Equals(Value) bool 45 StrictEquals(Value) bool 46 Export() interface{} 47 ExportType() reflect.Type 48 49 assertInt() (int64, bool) 50 assertString() (valueString, bool) 51 assertFloat() (float64, bool) 52 53 baseObject(r *Runtime) *Object 54} 55 56type valueInt int64 57type valueFloat float64 58type valueBool bool 59type valueNull struct{} 60type valueUndefined struct { 61 valueNull 62} 63 64type valueUnresolved struct { 65 r *Runtime 66 ref string 67} 68 69type memberUnresolved struct { 70 valueUnresolved 71} 72 73type valueProperty struct { 74 value Value 75 writable bool 76 configurable bool 77 enumerable bool 78 accessor bool 79 getterFunc *Object 80 setterFunc *Object 81} 82 83func propGetter(o Value, v Value, r *Runtime) *Object { 84 if v == _undefined { 85 return nil 86 } 87 if obj, ok := v.(*Object); ok { 88 if _, ok := obj.self.assertCallable(); ok { 89 return obj 90 } 91 } 92 r.typeErrorResult(true, "Getter must be a function: %s", v.ToString()) 93 return nil 94} 95 96func propSetter(o Value, v Value, r *Runtime) *Object { 97 if v == _undefined { 98 return nil 99 } 100 if obj, ok := v.(*Object); ok { 101 if _, ok := obj.self.assertCallable(); ok { 102 return obj 103 } 104 } 105 r.typeErrorResult(true, "Setter must be a function: %s", v.ToString()) 106 return nil 107} 108 109func (i valueInt) ToInteger() int64 { 110 return int64(i) 111} 112 113func (i valueInt) ToString() valueString { 114 return asciiString(i.String()) 115} 116 117func (i valueInt) String() string { 118 return strconv.FormatInt(int64(i), 10) 119} 120 121func (i valueInt) ToFloat() float64 { 122 return float64(int64(i)) 123} 124 125func (i valueInt) ToBoolean() bool { 126 return i != 0 127} 128 129func (i valueInt) ToObject(r *Runtime) *Object { 130 return r.newPrimitiveObject(i, r.global.NumberPrototype, classNumber) 131} 132 133func (i valueInt) ToNumber() Value { 134 return i 135} 136 137func (i valueInt) SameAs(other Value) bool { 138 if otherInt, ok := other.assertInt(); ok { 139 return int64(i) == otherInt 140 } 141 return false 142} 143 144func (i valueInt) Equals(other Value) bool { 145 if o, ok := other.assertInt(); ok { 146 return int64(i) == o 147 } 148 if o, ok := other.assertFloat(); ok { 149 return float64(i) == o 150 } 151 if o, ok := other.assertString(); ok { 152 return o.ToNumber().Equals(i) 153 } 154 if o, ok := other.(valueBool); ok { 155 return int64(i) == o.ToInteger() 156 } 157 if o, ok := other.(*Object); ok { 158 return i.Equals(o.self.toPrimitiveNumber()) 159 } 160 return false 161} 162 163func (i valueInt) StrictEquals(other Value) bool { 164 if otherInt, ok := other.assertInt(); ok { 165 return int64(i) == otherInt 166 } else if otherFloat, ok := other.assertFloat(); ok { 167 return float64(i) == otherFloat 168 } 169 return false 170} 171 172func (i valueInt) assertInt() (int64, bool) { 173 return int64(i), true 174} 175 176func (i valueInt) assertFloat() (float64, bool) { 177 return 0, false 178} 179 180func (i valueInt) assertString() (valueString, bool) { 181 return nil, false 182} 183 184func (i valueInt) baseObject(r *Runtime) *Object { 185 return r.global.NumberPrototype 186} 187 188func (i valueInt) Export() interface{} { 189 return int64(i) 190} 191 192func (i valueInt) ExportType() reflect.Type { 193 return reflectTypeInt 194} 195 196func (o valueBool) ToInteger() int64 { 197 if o { 198 return 1 199 } 200 return 0 201} 202 203func (o valueBool) ToString() valueString { 204 if o { 205 return stringTrue 206 } 207 return stringFalse 208} 209 210func (o valueBool) String() string { 211 if o { 212 return "true" 213 } 214 return "false" 215} 216 217func (o valueBool) ToFloat() float64 { 218 if o { 219 return 1.0 220 } 221 return 0 222} 223 224func (o valueBool) ToBoolean() bool { 225 return bool(o) 226} 227 228func (o valueBool) ToObject(r *Runtime) *Object { 229 return r.newPrimitiveObject(o, r.global.BooleanPrototype, "Boolean") 230} 231 232func (o valueBool) ToNumber() Value { 233 if o { 234 return valueInt(1) 235 } 236 return valueInt(0) 237} 238 239func (o valueBool) SameAs(other Value) bool { 240 if other, ok := other.(valueBool); ok { 241 return o == other 242 } 243 return false 244} 245 246func (b valueBool) Equals(other Value) bool { 247 if o, ok := other.(valueBool); ok { 248 return b == o 249 } 250 251 if b { 252 return other.Equals(intToValue(1)) 253 } else { 254 return other.Equals(intToValue(0)) 255 } 256 257} 258 259func (o valueBool) StrictEquals(other Value) bool { 260 if other, ok := other.(valueBool); ok { 261 return o == other 262 } 263 return false 264} 265 266func (o valueBool) assertInt() (int64, bool) { 267 return 0, false 268} 269 270func (o valueBool) assertFloat() (float64, bool) { 271 return 0, false 272} 273 274func (o valueBool) assertString() (valueString, bool) { 275 return nil, false 276} 277 278func (o valueBool) baseObject(r *Runtime) *Object { 279 return r.global.BooleanPrototype 280} 281 282func (o valueBool) Export() interface{} { 283 return bool(o) 284} 285 286func (o valueBool) ExportType() reflect.Type { 287 return reflectTypeBool 288} 289 290func (n valueNull) ToInteger() int64 { 291 return 0 292} 293 294func (n valueNull) ToString() valueString { 295 return stringNull 296} 297 298func (n valueNull) String() string { 299 return "null" 300} 301 302func (u valueUndefined) ToString() valueString { 303 return stringUndefined 304} 305 306func (u valueUndefined) String() string { 307 return "undefined" 308} 309 310func (u valueUndefined) ToNumber() Value { 311 return _NaN 312} 313 314func (u valueUndefined) SameAs(other Value) bool { 315 _, same := other.(valueUndefined) 316 return same 317} 318 319func (u valueUndefined) StrictEquals(other Value) bool { 320 _, same := other.(valueUndefined) 321 return same 322} 323 324func (u valueUndefined) ToFloat() float64 { 325 return math.NaN() 326} 327 328func (n valueNull) ToFloat() float64 { 329 return 0 330} 331 332func (n valueNull) ToBoolean() bool { 333 return false 334} 335 336func (n valueNull) ToObject(r *Runtime) *Object { 337 r.typeErrorResult(true, "Cannot convert undefined or null to object") 338 return nil 339 //return r.newObject() 340} 341 342func (n valueNull) ToNumber() Value { 343 return intToValue(0) 344} 345 346func (n valueNull) SameAs(other Value) bool { 347 _, same := other.(valueNull) 348 return same 349} 350 351func (n valueNull) Equals(other Value) bool { 352 switch other.(type) { 353 case valueUndefined, valueNull: 354 return true 355 } 356 return false 357} 358 359func (n valueNull) StrictEquals(other Value) bool { 360 _, same := other.(valueNull) 361 return same 362} 363 364func (n valueNull) assertInt() (int64, bool) { 365 return 0, false 366} 367 368func (n valueNull) assertFloat() (float64, bool) { 369 return 0, false 370} 371 372func (n valueNull) assertString() (valueString, bool) { 373 return nil, false 374} 375 376func (n valueNull) baseObject(r *Runtime) *Object { 377 return nil 378} 379 380func (n valueNull) Export() interface{} { 381 return nil 382} 383 384func (n valueNull) ExportType() reflect.Type { 385 return reflectTypeNil 386} 387 388func (p *valueProperty) ToInteger() int64 { 389 return 0 390} 391 392func (p *valueProperty) ToString() valueString { 393 return stringEmpty 394} 395 396func (p *valueProperty) String() string { 397 return "" 398} 399 400func (p *valueProperty) ToFloat() float64 { 401 return math.NaN() 402} 403 404func (p *valueProperty) ToBoolean() bool { 405 return false 406} 407 408func (p *valueProperty) ToObject(r *Runtime) *Object { 409 return nil 410} 411 412func (p *valueProperty) ToNumber() Value { 413 return nil 414} 415 416func (p *valueProperty) assertInt() (int64, bool) { 417 return 0, false 418} 419 420func (p *valueProperty) assertFloat() (float64, bool) { 421 return 0, false 422} 423 424func (p *valueProperty) assertString() (valueString, bool) { 425 return nil, false 426} 427 428func (p *valueProperty) isWritable() bool { 429 return p.writable || p.setterFunc != nil 430} 431 432func (p *valueProperty) get(this Value) Value { 433 if p.getterFunc == nil { 434 if p.value != nil { 435 return p.value 436 } 437 return _undefined 438 } 439 call, _ := p.getterFunc.self.assertCallable() 440 return call(FunctionCall{ 441 This: this, 442 }) 443} 444 445func (p *valueProperty) set(this, v Value) { 446 if p.setterFunc == nil { 447 p.value = v 448 return 449 } 450 call, _ := p.setterFunc.self.assertCallable() 451 call(FunctionCall{ 452 This: this, 453 Arguments: []Value{v}, 454 }) 455} 456 457func (p *valueProperty) SameAs(other Value) bool { 458 if otherProp, ok := other.(*valueProperty); ok { 459 return p == otherProp 460 } 461 return false 462} 463 464func (p *valueProperty) Equals(other Value) bool { 465 return false 466} 467 468func (p *valueProperty) StrictEquals(other Value) bool { 469 return false 470} 471 472func (n *valueProperty) baseObject(r *Runtime) *Object { 473 r.typeErrorResult(true, "BUG: baseObject() is called on valueProperty") // TODO error message 474 return nil 475} 476 477func (n *valueProperty) Export() interface{} { 478 panic("Cannot export valueProperty") 479} 480 481func (n *valueProperty) ExportType() reflect.Type { 482 panic("Cannot export valueProperty") 483} 484 485func (f valueFloat) ToInteger() int64 { 486 switch { 487 case math.IsNaN(float64(f)): 488 return 0 489 case math.IsInf(float64(f), 1): 490 return int64(math.MaxInt64) 491 case math.IsInf(float64(f), -1): 492 return int64(math.MinInt64) 493 } 494 return int64(f) 495} 496 497func (f valueFloat) ToString() valueString { 498 return asciiString(f.String()) 499} 500 501var matchLeading0Exponent = regexp.MustCompile(`([eE][\+\-])0+([1-9])`) // 1e-07 => 1e-7 502 503func (f valueFloat) String() string { 504 value := float64(f) 505 if math.IsNaN(value) { 506 return "NaN" 507 } else if math.IsInf(value, 0) { 508 if math.Signbit(value) { 509 return "-Infinity" 510 } 511 return "Infinity" 512 } else if f == _negativeZero { 513 return "0" 514 } 515 exponent := math.Log10(math.Abs(value)) 516 if exponent >= 21 || exponent < -6 { 517 return matchLeading0Exponent.ReplaceAllString(strconv.FormatFloat(value, 'g', -1, 64), "$1$2") 518 } 519 return strconv.FormatFloat(value, 'f', -1, 64) 520} 521 522func (f valueFloat) ToFloat() float64 { 523 return float64(f) 524} 525 526func (f valueFloat) ToBoolean() bool { 527 return float64(f) != 0.0 && !math.IsNaN(float64(f)) 528} 529 530func (f valueFloat) ToObject(r *Runtime) *Object { 531 return r.newPrimitiveObject(f, r.global.NumberPrototype, "Number") 532} 533 534func (f valueFloat) ToNumber() Value { 535 return f 536} 537 538func (f valueFloat) SameAs(other Value) bool { 539 if o, ok := other.assertFloat(); ok { 540 this := float64(f) 541 if math.IsNaN(this) && math.IsNaN(o) { 542 return true 543 } else { 544 ret := this == o 545 if ret && this == 0 { 546 ret = math.Signbit(this) == math.Signbit(o) 547 } 548 return ret 549 } 550 } else if o, ok := other.assertInt(); ok { 551 this := float64(f) 552 ret := this == float64(o) 553 if ret && this == 0 { 554 ret = !math.Signbit(this) 555 } 556 return ret 557 } 558 return false 559} 560 561func (f valueFloat) Equals(other Value) bool { 562 if o, ok := other.assertFloat(); ok { 563 return float64(f) == o 564 } 565 566 if o, ok := other.assertInt(); ok { 567 return float64(f) == float64(o) 568 } 569 570 if _, ok := other.assertString(); ok { 571 return float64(f) == other.ToFloat() 572 } 573 574 if o, ok := other.(valueBool); ok { 575 return float64(f) == o.ToFloat() 576 } 577 578 if o, ok := other.(*Object); ok { 579 return f.Equals(o.self.toPrimitiveNumber()) 580 } 581 582 return false 583} 584 585func (f valueFloat) StrictEquals(other Value) bool { 586 if o, ok := other.assertFloat(); ok { 587 return float64(f) == o 588 } else if o, ok := other.assertInt(); ok { 589 return float64(f) == float64(o) 590 } 591 return false 592} 593 594func (f valueFloat) assertInt() (int64, bool) { 595 return 0, false 596} 597 598func (f valueFloat) assertFloat() (float64, bool) { 599 return float64(f), true 600} 601 602func (f valueFloat) assertString() (valueString, bool) { 603 return nil, false 604} 605 606func (f valueFloat) baseObject(r *Runtime) *Object { 607 return r.global.NumberPrototype 608} 609 610func (f valueFloat) Export() interface{} { 611 return float64(f) 612} 613 614func (f valueFloat) ExportType() reflect.Type { 615 return reflectTypeFloat 616} 617 618func (o *Object) ToInteger() int64 { 619 return o.self.toPrimitiveNumber().ToNumber().ToInteger() 620} 621 622func (o *Object) ToString() valueString { 623 return o.self.toPrimitiveString().ToString() 624} 625 626func (o *Object) String() string { 627 return o.self.toPrimitiveString().String() 628} 629 630func (o *Object) ToFloat() float64 { 631 return o.self.toPrimitiveNumber().ToFloat() 632} 633 634func (o *Object) ToBoolean() bool { 635 return true 636} 637 638func (o *Object) ToObject(r *Runtime) *Object { 639 return o 640} 641 642func (o *Object) ToNumber() Value { 643 return o.self.toPrimitiveNumber().ToNumber() 644} 645 646func (o *Object) SameAs(other Value) bool { 647 if other, ok := other.(*Object); ok { 648 return o == other 649 } 650 return false 651} 652 653func (o *Object) Equals(other Value) bool { 654 if other, ok := other.(*Object); ok { 655 return o == other || o.self.equal(other.self) 656 } 657 658 if _, ok := other.assertInt(); ok { 659 return o.self.toPrimitive().Equals(other) 660 } 661 662 if _, ok := other.assertFloat(); ok { 663 return o.self.toPrimitive().Equals(other) 664 } 665 666 if other, ok := other.(valueBool); ok { 667 return o.Equals(other.ToNumber()) 668 } 669 670 if _, ok := other.assertString(); ok { 671 return o.self.toPrimitive().Equals(other) 672 } 673 return false 674} 675 676func (o *Object) StrictEquals(other Value) bool { 677 if other, ok := other.(*Object); ok { 678 return o == other || o.self.equal(other.self) 679 } 680 return false 681} 682 683func (o *Object) assertInt() (int64, bool) { 684 return 0, false 685} 686 687func (o *Object) assertFloat() (float64, bool) { 688 return 0, false 689} 690 691func (o *Object) assertString() (valueString, bool) { 692 return nil, false 693} 694 695func (o *Object) baseObject(r *Runtime) *Object { 696 return o 697} 698 699func (o *Object) Export() interface{} { 700 return o.self.export() 701} 702 703func (o *Object) ExportType() reflect.Type { 704 return o.self.exportType() 705} 706 707func (o *Object) Get(name string) Value { 708 return o.self.getStr(name) 709} 710 711func (o *Object) Keys() (keys []string) { 712 for item, f := o.self.enumerate(false, false)(); f != nil; item, f = f() { 713 keys = append(keys, item.name) 714 } 715 716 return 717} 718 719// DefineDataProperty is a Go equivalent of Object.defineProperty(o, name, {value: value, writable: writable, 720// configurable: configurable, enumerable: enumerable}) 721func (o *Object) DefineDataProperty(name string, value Value, writable, configurable, enumerable Flag) error { 722 return tryFunc(func() { 723 o.self.defineOwnProperty(newStringValue(name), propertyDescr{ 724 Value: value, 725 Writable: writable, 726 Configurable: configurable, 727 Enumerable: enumerable, 728 }, true) 729 }) 730} 731 732// DefineAccessorProperty is a Go equivalent of Object.defineProperty(o, name, {get: getter, set: setter, 733// configurable: configurable, enumerable: enumerable}) 734func (o *Object) DefineAccessorProperty(name string, getter, setter Value, configurable, enumerable Flag) error { 735 return tryFunc(func() { 736 o.self.defineOwnProperty(newStringValue(name), propertyDescr{ 737 Getter: getter, 738 Setter: setter, 739 Configurable: configurable, 740 Enumerable: enumerable, 741 }, true) 742 }) 743} 744 745func (o *Object) Set(name string, value interface{}) error { 746 return tryFunc(func() { 747 o.self.putStr(name, o.runtime.ToValue(value), true) 748 }) 749} 750 751// MarshalJSON returns JSON representation of the Object. It is equivalent to JSON.stringify(o). 752// Note, this implements json.Marshaler so that json.Marshal() can be used without the need to Export(). 753func (o *Object) MarshalJSON() ([]byte, error) { 754 ctx := _builtinJSON_stringifyContext{ 755 r: o.runtime, 756 } 757 ex := o.runtime.vm.try(func() { 758 if !ctx.do(o) { 759 ctx.buf.WriteString("null") 760 } 761 }) 762 if ex != nil { 763 return nil, ex 764 } 765 return ctx.buf.Bytes(), nil 766} 767 768func (o valueUnresolved) throw() { 769 o.r.throwReferenceError(o.ref) 770} 771 772func (o valueUnresolved) ToInteger() int64 { 773 o.throw() 774 return 0 775} 776 777func (o valueUnresolved) ToString() valueString { 778 o.throw() 779 return nil 780} 781 782func (o valueUnresolved) String() string { 783 o.throw() 784 return "" 785} 786 787func (o valueUnresolved) ToFloat() float64 { 788 o.throw() 789 return 0 790} 791 792func (o valueUnresolved) ToBoolean() bool { 793 o.throw() 794 return false 795} 796 797func (o valueUnresolved) ToObject(r *Runtime) *Object { 798 o.throw() 799 return nil 800} 801 802func (o valueUnresolved) ToNumber() Value { 803 o.throw() 804 return nil 805} 806 807func (o valueUnresolved) SameAs(other Value) bool { 808 o.throw() 809 return false 810} 811 812func (o valueUnresolved) Equals(other Value) bool { 813 o.throw() 814 return false 815} 816 817func (o valueUnresolved) StrictEquals(other Value) bool { 818 o.throw() 819 return false 820} 821 822func (o valueUnresolved) assertInt() (int64, bool) { 823 o.throw() 824 return 0, false 825} 826 827func (o valueUnresolved) assertFloat() (float64, bool) { 828 o.throw() 829 return 0, false 830} 831 832func (o valueUnresolved) assertString() (valueString, bool) { 833 o.throw() 834 return nil, false 835} 836 837func (o valueUnresolved) baseObject(r *Runtime) *Object { 838 o.throw() 839 return nil 840} 841 842func (o valueUnresolved) Export() interface{} { 843 o.throw() 844 return nil 845} 846 847func (o valueUnresolved) ExportType() reflect.Type { 848 o.throw() 849 return nil 850} 851 852func init() { 853 for i := 0; i < 256; i++ { 854 intCache[i] = valueInt(i - 128) 855 } 856 _positiveZero = intToValue(0) 857} 858