123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857 |
- package goja
- import (
- "math"
- "reflect"
- "regexp"
- "strconv"
- )
- var (
- valueFalse Value = valueBool(false)
- valueTrue Value = valueBool(true)
- _null Value = valueNull{}
- _NaN Value = valueFloat(math.NaN())
- _positiveInf Value = valueFloat(math.Inf(+1))
- _negativeInf Value = valueFloat(math.Inf(-1))
- _positiveZero Value
- _negativeZero Value = valueFloat(math.Float64frombits(0 | (1 << 63)))
- _epsilon = valueFloat(2.2204460492503130808472633361816e-16)
- _undefined Value = valueUndefined{}
- )
- var (
- reflectTypeInt = reflect.TypeOf(int64(0))
- reflectTypeBool = reflect.TypeOf(false)
- reflectTypeNil = reflect.TypeOf(nil)
- reflectTypeFloat = reflect.TypeOf(float64(0))
- reflectTypeMap = reflect.TypeOf(map[string]interface{}{})
- reflectTypeArray = reflect.TypeOf([]interface{}{})
- reflectTypeString = reflect.TypeOf("")
- )
- var intCache [256]Value
- type Value interface {
- ToInteger() int64
- ToString() valueString
- String() string
- ToFloat() float64
- ToNumber() Value
- ToBoolean() bool
- ToObject(*Runtime) *Object
- SameAs(Value) bool
- Equals(Value) bool
- StrictEquals(Value) bool
- Export() interface{}
- ExportType() reflect.Type
- assertInt() (int64, bool)
- assertString() (valueString, bool)
- assertFloat() (float64, bool)
- baseObject(r *Runtime) *Object
- }
- type valueInt int64
- type valueFloat float64
- type valueBool bool
- type valueNull struct{}
- type valueUndefined struct {
- valueNull
- }
- type valueUnresolved struct {
- r *Runtime
- ref string
- }
- type memberUnresolved struct {
- valueUnresolved
- }
- type valueProperty struct {
- value Value
- writable bool
- configurable bool
- enumerable bool
- accessor bool
- getterFunc *Object
- setterFunc *Object
- }
- func propGetter(o Value, v Value, r *Runtime) *Object {
- if v == _undefined {
- return nil
- }
- if obj, ok := v.(*Object); ok {
- if _, ok := obj.self.assertCallable(); ok {
- return obj
- }
- }
- r.typeErrorResult(true, "Getter must be a function: %s", v.ToString())
- return nil
- }
- func propSetter(o Value, v Value, r *Runtime) *Object {
- if v == _undefined {
- return nil
- }
- if obj, ok := v.(*Object); ok {
- if _, ok := obj.self.assertCallable(); ok {
- return obj
- }
- }
- r.typeErrorResult(true, "Setter must be a function: %s", v.ToString())
- return nil
- }
- func (i valueInt) ToInteger() int64 {
- return int64(i)
- }
- func (i valueInt) ToString() valueString {
- return asciiString(i.String())
- }
- func (i valueInt) String() string {
- return strconv.FormatInt(int64(i), 10)
- }
- func (i valueInt) ToFloat() float64 {
- return float64(int64(i))
- }
- func (i valueInt) ToBoolean() bool {
- return i != 0
- }
- func (i valueInt) ToObject(r *Runtime) *Object {
- return r.newPrimitiveObject(i, r.global.NumberPrototype, classNumber)
- }
- func (i valueInt) ToNumber() Value {
- return i
- }
- func (i valueInt) SameAs(other Value) bool {
- if otherInt, ok := other.assertInt(); ok {
- return int64(i) == otherInt
- }
- return false
- }
- func (i valueInt) Equals(other Value) bool {
- if o, ok := other.assertInt(); ok {
- return int64(i) == o
- }
- if o, ok := other.assertFloat(); ok {
- return float64(i) == o
- }
- if o, ok := other.assertString(); ok {
- return o.ToNumber().Equals(i)
- }
- if o, ok := other.(valueBool); ok {
- return int64(i) == o.ToInteger()
- }
- if o, ok := other.(*Object); ok {
- return i.Equals(o.self.toPrimitiveNumber())
- }
- return false
- }
- func (i valueInt) StrictEquals(other Value) bool {
- if otherInt, ok := other.assertInt(); ok {
- return int64(i) == otherInt
- } else if otherFloat, ok := other.assertFloat(); ok {
- return float64(i) == otherFloat
- }
- return false
- }
- func (i valueInt) assertInt() (int64, bool) {
- return int64(i), true
- }
- func (i valueInt) assertFloat() (float64, bool) {
- return 0, false
- }
- func (i valueInt) assertString() (valueString, bool) {
- return nil, false
- }
- func (i valueInt) baseObject(r *Runtime) *Object {
- return r.global.NumberPrototype
- }
- func (i valueInt) Export() interface{} {
- return int64(i)
- }
- func (i valueInt) ExportType() reflect.Type {
- return reflectTypeInt
- }
- func (o valueBool) ToInteger() int64 {
- if o {
- return 1
- }
- return 0
- }
- func (o valueBool) ToString() valueString {
- if o {
- return stringTrue
- }
- return stringFalse
- }
- func (o valueBool) String() string {
- if o {
- return "true"
- }
- return "false"
- }
- func (o valueBool) ToFloat() float64 {
- if o {
- return 1.0
- }
- return 0
- }
- func (o valueBool) ToBoolean() bool {
- return bool(o)
- }
- func (o valueBool) ToObject(r *Runtime) *Object {
- return r.newPrimitiveObject(o, r.global.BooleanPrototype, "Boolean")
- }
- func (o valueBool) ToNumber() Value {
- if o {
- return valueInt(1)
- }
- return valueInt(0)
- }
- func (o valueBool) SameAs(other Value) bool {
- if other, ok := other.(valueBool); ok {
- return o == other
- }
- return false
- }
- func (b valueBool) Equals(other Value) bool {
- if o, ok := other.(valueBool); ok {
- return b == o
- }
- if b {
- return other.Equals(intToValue(1))
- } else {
- return other.Equals(intToValue(0))
- }
- }
- func (o valueBool) StrictEquals(other Value) bool {
- if other, ok := other.(valueBool); ok {
- return o == other
- }
- return false
- }
- func (o valueBool) assertInt() (int64, bool) {
- return 0, false
- }
- func (o valueBool) assertFloat() (float64, bool) {
- return 0, false
- }
- func (o valueBool) assertString() (valueString, bool) {
- return nil, false
- }
- func (o valueBool) baseObject(r *Runtime) *Object {
- return r.global.BooleanPrototype
- }
- func (o valueBool) Export() interface{} {
- return bool(o)
- }
- func (o valueBool) ExportType() reflect.Type {
- return reflectTypeBool
- }
- func (n valueNull) ToInteger() int64 {
- return 0
- }
- func (n valueNull) ToString() valueString {
- return stringNull
- }
- func (n valueNull) String() string {
- return "null"
- }
- func (u valueUndefined) ToString() valueString {
- return stringUndefined
- }
- func (u valueUndefined) String() string {
- return "undefined"
- }
- func (u valueUndefined) ToNumber() Value {
- return _NaN
- }
- func (u valueUndefined) SameAs(other Value) bool {
- _, same := other.(valueUndefined)
- return same
- }
- func (u valueUndefined) StrictEquals(other Value) bool {
- _, same := other.(valueUndefined)
- return same
- }
- func (u valueUndefined) ToFloat() float64 {
- return math.NaN()
- }
- func (n valueNull) ToFloat() float64 {
- return 0
- }
- func (n valueNull) ToBoolean() bool {
- return false
- }
- func (n valueNull) ToObject(r *Runtime) *Object {
- r.typeErrorResult(true, "Cannot convert undefined or null to object")
- return nil
- //return r.newObject()
- }
- func (n valueNull) ToNumber() Value {
- return intToValue(0)
- }
- func (n valueNull) SameAs(other Value) bool {
- _, same := other.(valueNull)
- return same
- }
- func (n valueNull) Equals(other Value) bool {
- switch other.(type) {
- case valueUndefined, valueNull:
- return true
- }
- return false
- }
- func (n valueNull) StrictEquals(other Value) bool {
- _, same := other.(valueNull)
- return same
- }
- func (n valueNull) assertInt() (int64, bool) {
- return 0, false
- }
- func (n valueNull) assertFloat() (float64, bool) {
- return 0, false
- }
- func (n valueNull) assertString() (valueString, bool) {
- return nil, false
- }
- func (n valueNull) baseObject(r *Runtime) *Object {
- return nil
- }
- func (n valueNull) Export() interface{} {
- return nil
- }
- func (n valueNull) ExportType() reflect.Type {
- return reflectTypeNil
- }
- func (p *valueProperty) ToInteger() int64 {
- return 0
- }
- func (p *valueProperty) ToString() valueString {
- return stringEmpty
- }
- func (p *valueProperty) String() string {
- return ""
- }
- func (p *valueProperty) ToFloat() float64 {
- return math.NaN()
- }
- func (p *valueProperty) ToBoolean() bool {
- return false
- }
- func (p *valueProperty) ToObject(r *Runtime) *Object {
- return nil
- }
- func (p *valueProperty) ToNumber() Value {
- return nil
- }
- func (p *valueProperty) assertInt() (int64, bool) {
- return 0, false
- }
- func (p *valueProperty) assertFloat() (float64, bool) {
- return 0, false
- }
- func (p *valueProperty) assertString() (valueString, bool) {
- return nil, false
- }
- func (p *valueProperty) isWritable() bool {
- return p.writable || p.setterFunc != nil
- }
- func (p *valueProperty) get(this Value) Value {
- if p.getterFunc == nil {
- if p.value != nil {
- return p.value
- }
- return _undefined
- }
- call, _ := p.getterFunc.self.assertCallable()
- return call(FunctionCall{
- This: this,
- })
- }
- func (p *valueProperty) set(this, v Value) {
- if p.setterFunc == nil {
- p.value = v
- return
- }
- call, _ := p.setterFunc.self.assertCallable()
- call(FunctionCall{
- This: this,
- Arguments: []Value{v},
- })
- }
- func (p *valueProperty) SameAs(other Value) bool {
- if otherProp, ok := other.(*valueProperty); ok {
- return p == otherProp
- }
- return false
- }
- func (p *valueProperty) Equals(other Value) bool {
- return false
- }
- func (p *valueProperty) StrictEquals(other Value) bool {
- return false
- }
- func (n *valueProperty) baseObject(r *Runtime) *Object {
- r.typeErrorResult(true, "BUG: baseObject() is called on valueProperty") // TODO error message
- return nil
- }
- func (n *valueProperty) Export() interface{} {
- panic("Cannot export valueProperty")
- }
- func (n *valueProperty) ExportType() reflect.Type {
- panic("Cannot export valueProperty")
- }
- func (f valueFloat) ToInteger() int64 {
- switch {
- case math.IsNaN(float64(f)):
- return 0
- case math.IsInf(float64(f), 1):
- return int64(math.MaxInt64)
- case math.IsInf(float64(f), -1):
- return int64(math.MinInt64)
- }
- return int64(f)
- }
- func (f valueFloat) ToString() valueString {
- return asciiString(f.String())
- }
- var matchLeading0Exponent = regexp.MustCompile(`([eE][\+\-])0+([1-9])`) // 1e-07 => 1e-7
- func (f valueFloat) String() string {
- value := float64(f)
- if math.IsNaN(value) {
- return "NaN"
- } else if math.IsInf(value, 0) {
- if math.Signbit(value) {
- return "-Infinity"
- }
- return "Infinity"
- } else if f == _negativeZero {
- return "0"
- }
- exponent := math.Log10(math.Abs(value))
- if exponent >= 21 || exponent < -6 {
- return matchLeading0Exponent.ReplaceAllString(strconv.FormatFloat(value, 'g', -1, 64), "$1$2")
- }
- return strconv.FormatFloat(value, 'f', -1, 64)
- }
- func (f valueFloat) ToFloat() float64 {
- return float64(f)
- }
- func (f valueFloat) ToBoolean() bool {
- return float64(f) != 0.0 && !math.IsNaN(float64(f))
- }
- func (f valueFloat) ToObject(r *Runtime) *Object {
- return r.newPrimitiveObject(f, r.global.NumberPrototype, "Number")
- }
- func (f valueFloat) ToNumber() Value {
- return f
- }
- func (f valueFloat) SameAs(other Value) bool {
- if o, ok := other.assertFloat(); ok {
- this := float64(f)
- if math.IsNaN(this) && math.IsNaN(o) {
- return true
- } else {
- ret := this == o
- if ret && this == 0 {
- ret = math.Signbit(this) == math.Signbit(o)
- }
- return ret
- }
- } else if o, ok := other.assertInt(); ok {
- this := float64(f)
- ret := this == float64(o)
- if ret && this == 0 {
- ret = !math.Signbit(this)
- }
- return ret
- }
- return false
- }
- func (f valueFloat) Equals(other Value) bool {
- if o, ok := other.assertFloat(); ok {
- return float64(f) == o
- }
- if o, ok := other.assertInt(); ok {
- return float64(f) == float64(o)
- }
- if _, ok := other.assertString(); ok {
- return float64(f) == other.ToFloat()
- }
- if o, ok := other.(valueBool); ok {
- return float64(f) == o.ToFloat()
- }
- if o, ok := other.(*Object); ok {
- return f.Equals(o.self.toPrimitiveNumber())
- }
- return false
- }
- func (f valueFloat) StrictEquals(other Value) bool {
- if o, ok := other.assertFloat(); ok {
- return float64(f) == o
- } else if o, ok := other.assertInt(); ok {
- return float64(f) == float64(o)
- }
- return false
- }
- func (f valueFloat) assertInt() (int64, bool) {
- return 0, false
- }
- func (f valueFloat) assertFloat() (float64, bool) {
- return float64(f), true
- }
- func (f valueFloat) assertString() (valueString, bool) {
- return nil, false
- }
- func (f valueFloat) baseObject(r *Runtime) *Object {
- return r.global.NumberPrototype
- }
- func (f valueFloat) Export() interface{} {
- return float64(f)
- }
- func (f valueFloat) ExportType() reflect.Type {
- return reflectTypeFloat
- }
- func (o *Object) ToInteger() int64 {
- return o.self.toPrimitiveNumber().ToNumber().ToInteger()
- }
- func (o *Object) ToString() valueString {
- return o.self.toPrimitiveString().ToString()
- }
- func (o *Object) String() string {
- return o.self.toPrimitiveString().String()
- }
- func (o *Object) ToFloat() float64 {
- return o.self.toPrimitiveNumber().ToFloat()
- }
- func (o *Object) ToBoolean() bool {
- return true
- }
- func (o *Object) ToObject(r *Runtime) *Object {
- return o
- }
- func (o *Object) ToNumber() Value {
- return o.self.toPrimitiveNumber().ToNumber()
- }
- func (o *Object) SameAs(other Value) bool {
- if other, ok := other.(*Object); ok {
- return o == other
- }
- return false
- }
- func (o *Object) Equals(other Value) bool {
- if other, ok := other.(*Object); ok {
- return o == other || o.self.equal(other.self)
- }
- if _, ok := other.assertInt(); ok {
- return o.self.toPrimitive().Equals(other)
- }
- if _, ok := other.assertFloat(); ok {
- return o.self.toPrimitive().Equals(other)
- }
- if other, ok := other.(valueBool); ok {
- return o.Equals(other.ToNumber())
- }
- if _, ok := other.assertString(); ok {
- return o.self.toPrimitive().Equals(other)
- }
- return false
- }
- func (o *Object) StrictEquals(other Value) bool {
- if other, ok := other.(*Object); ok {
- return o == other || o.self.equal(other.self)
- }
- return false
- }
- func (o *Object) assertInt() (int64, bool) {
- return 0, false
- }
- func (o *Object) assertFloat() (float64, bool) {
- return 0, false
- }
- func (o *Object) assertString() (valueString, bool) {
- return nil, false
- }
- func (o *Object) baseObject(r *Runtime) *Object {
- return o
- }
- func (o *Object) Export() interface{} {
- return o.self.export()
- }
- func (o *Object) ExportType() reflect.Type {
- return o.self.exportType()
- }
- func (o *Object) Get(name string) Value {
- return o.self.getStr(name)
- }
- func (o *Object) Keys() (keys []string) {
- for item, f := o.self.enumerate(false, false)(); f != nil; item, f = f() {
- keys = append(keys, item.name)
- }
- return
- }
- // DefineDataProperty is a Go equivalent of Object.defineProperty(o, name, {value: value, writable: writable,
- // configurable: configurable, enumerable: enumerable})
- func (o *Object) DefineDataProperty(name string, value Value, writable, configurable, enumerable Flag) error {
- return tryFunc(func() {
- o.self.defineOwnProperty(newStringValue(name), propertyDescr{
- Value: value,
- Writable: writable,
- Configurable: configurable,
- Enumerable: enumerable,
- }, true)
- })
- }
- // DefineAccessorProperty is a Go equivalent of Object.defineProperty(o, name, {get: getter, set: setter,
- // configurable: configurable, enumerable: enumerable})
- func (o *Object) DefineAccessorProperty(name string, getter, setter Value, configurable, enumerable Flag) error {
- return tryFunc(func() {
- o.self.defineOwnProperty(newStringValue(name), propertyDescr{
- Getter: getter,
- Setter: setter,
- Configurable: configurable,
- Enumerable: enumerable,
- }, true)
- })
- }
- func (o *Object) Set(name string, value interface{}) error {
- return tryFunc(func() {
- o.self.putStr(name, o.runtime.ToValue(value), true)
- })
- }
- // MarshalJSON returns JSON representation of the Object. It is equivalent to JSON.stringify(o).
- // Note, this implements json.Marshaler so that json.Marshal() can be used without the need to Export().
- func (o *Object) MarshalJSON() ([]byte, error) {
- ctx := _builtinJSON_stringifyContext{
- r: o.runtime,
- }
- ex := o.runtime.vm.try(func() {
- if !ctx.do(o) {
- ctx.buf.WriteString("null")
- }
- })
- if ex != nil {
- return nil, ex
- }
- return ctx.buf.Bytes(), nil
- }
- func (o valueUnresolved) throw() {
- o.r.throwReferenceError(o.ref)
- }
- func (o valueUnresolved) ToInteger() int64 {
- o.throw()
- return 0
- }
- func (o valueUnresolved) ToString() valueString {
- o.throw()
- return nil
- }
- func (o valueUnresolved) String() string {
- o.throw()
- return ""
- }
- func (o valueUnresolved) ToFloat() float64 {
- o.throw()
- return 0
- }
- func (o valueUnresolved) ToBoolean() bool {
- o.throw()
- return false
- }
- func (o valueUnresolved) ToObject(r *Runtime) *Object {
- o.throw()
- return nil
- }
- func (o valueUnresolved) ToNumber() Value {
- o.throw()
- return nil
- }
- func (o valueUnresolved) SameAs(other Value) bool {
- o.throw()
- return false
- }
- func (o valueUnresolved) Equals(other Value) bool {
- o.throw()
- return false
- }
- func (o valueUnresolved) StrictEquals(other Value) bool {
- o.throw()
- return false
- }
- func (o valueUnresolved) assertInt() (int64, bool) {
- o.throw()
- return 0, false
- }
- func (o valueUnresolved) assertFloat() (float64, bool) {
- o.throw()
- return 0, false
- }
- func (o valueUnresolved) assertString() (valueString, bool) {
- o.throw()
- return nil, false
- }
- func (o valueUnresolved) baseObject(r *Runtime) *Object {
- o.throw()
- return nil
- }
- func (o valueUnresolved) Export() interface{} {
- o.throw()
- return nil
- }
- func (o valueUnresolved) ExportType() reflect.Type {
- o.throw()
- return nil
- }
- func init() {
- for i := 0; i < 256; i++ {
- intCache[i] = valueInt(i - 128)
- }
- _positiveZero = intToValue(0)
- }
|