1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255 |
- package goja
- import (
- "hash/maphash"
- "math"
- "math/big"
- "reflect"
- "strconv"
- "unsafe"
- "github.com/dop251/goja/ftoa"
- "github.com/dop251/goja/unistring"
- )
- var (
- // Not goroutine-safe, do not use for anything other than package level init
- pkgHasher maphash.Hash
- hashFalse = randomHash()
- hashTrue = randomHash()
- hashNull = randomHash()
- hashUndef = randomHash()
- )
- // Not goroutine-safe, do not use for anything other than package level init
- func randomHash() uint64 {
- pkgHasher.WriteByte(0)
- return pkgHasher.Sum64()
- }
- 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 = valueInt(0)
- negativeZero = math.Float64frombits(0 | (1 << 63))
- _negativeZero Value = valueFloat(negativeZero)
- _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))
- reflectTypeBigInt = reflect.TypeOf(big.Int{})
- 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() unistring.String
- ToString() Value
- String() string
- ToFloat() float64
- ToNumber() Value
- ToBigInt() Value
- ToBoolean() bool
- ToObject(*Runtime) *Object
- SameAs(Value) bool
- Equals(Value) bool
- StrictEquals(Value) bool
- Export() interface{}
- ExportType() reflect.Type
- baseObject(r *Runtime) *Object
- hash(hasher *maphash.Hash) uint64
- }
- type valueContainer interface {
- toValue(*Runtime) Value
- }
- type typeError string
- type rangeError string
- type referenceError string
- type valueInt int64
- type valueFloat float64
- type valueBigInt struct {
- *big.Int
- }
- type valueBool bool
- type valueNull struct{}
- type valueUndefined struct {
- valueNull
- }
- // *Symbol is a Value containing ECMAScript Symbol primitive. Symbols must only be created
- // using NewSymbol(). Zero values and copying of values (i.e. *s1 = *s2) are not permitted.
- // Well-known Symbols can be accessed using Sym* package variables (SymIterator, etc...)
- // Symbols can be shared by multiple Runtimes.
- type Symbol struct {
- h uintptr
- desc valueString
- }
- type valueUnresolved struct {
- r *Runtime
- ref unistring.String
- }
- type memberUnresolved struct {
- valueUnresolved
- }
- type valueProperty struct {
- value Value
- writable bool
- configurable bool
- enumerable bool
- accessor bool
- getterFunc *Object
- setterFunc *Object
- }
- var (
- errAccessBeforeInit = referenceError("Cannot access a variable before initialization")
- errAssignToConst = typeError("Assignment to constant variable.")
- )
- 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 fToStr(num float64, mode ftoa.FToStrMode, prec int) string {
- var buf1 [128]byte
- return string(ftoa.FToStr(num, mode, prec, buf1[:0]))
- }
- func (i valueInt) ToInteger() int64 {
- return int64(i)
- }
- func (i valueInt) toString() valueString {
- return asciiString(i.String())
- }
- func (i valueInt) string() unistring.String {
- return unistring.String(i.String())
- }
- func (i valueInt) ToString() Value {
- return i
- }
- func (i valueInt) String() string {
- return strconv.FormatInt(int64(i), 10)
- }
- func (i valueInt) ToFloat() float64 {
- return float64(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) ToBigInt() Value {
- return valueBigInt{big.NewInt(int64(i))}
- }
- func (i valueInt) SameAs(other Value) bool {
- return i == other
- }
- func (i valueInt) Equals(other Value) bool {
- switch o := other.(type) {
- case valueInt:
- return i == o
- case valueFloat:
- return float64(i) == float64(o)
- case valueString:
- return o.ToNumber().Equals(i)
- case valueBool:
- return int64(i) == o.ToInteger()
- case *Object:
- return i.Equals(o.toPrimitive())
- }
- return false
- }
- func (i valueInt) StrictEquals(other Value) bool {
- switch o := other.(type) {
- case valueInt:
- return i == o
- case valueFloat:
- return float64(i) == float64(o)
- }
- return 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 (i valueInt) hash(*maphash.Hash) uint64 {
- return uint64(i)
- }
- func (b valueBool) ToInteger() int64 {
- if b {
- return 1
- }
- return 0
- }
- func (b valueBool) toString() valueString {
- if b {
- return stringTrue
- }
- return stringFalse
- }
- func (b valueBool) ToString() Value {
- return b
- }
- func (b valueBool) String() string {
- if b {
- return "true"
- }
- return "false"
- }
- func (b valueBool) string() unistring.String {
- return unistring.String(b.String())
- }
- func (b valueBool) ToFloat() float64 {
- if b {
- return 1.0
- }
- return 0
- }
- func (b valueBool) ToBoolean() bool {
- return bool(b)
- }
- func (b valueBool) ToObject(r *Runtime) *Object {
- return r.newPrimitiveObject(b, r.global.BooleanPrototype, "Boolean")
- }
- func (b valueBool) ToNumber() Value {
- if b {
- return valueInt(1)
- }
- return valueInt(0)
- }
- func (b valueBool) ToBigInt() Value {
- if b {
- return valueBigInt{big.NewInt(1)}
- }
- return valueBigInt{big.NewInt(0)}
- }
- func (b valueBool) SameAs(other Value) bool {
- if other, ok := other.(valueBool); ok {
- return b == 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 (b valueBool) StrictEquals(other Value) bool {
- if other, ok := other.(valueBool); ok {
- return b == other
- }
- return false
- }
- func (b valueBool) baseObject(r *Runtime) *Object {
- return r.global.BooleanPrototype
- }
- func (b valueBool) Export() interface{} {
- return bool(b)
- }
- func (b valueBool) ExportType() reflect.Type {
- return reflectTypeBool
- }
- func (b valueBool) hash(*maphash.Hash) uint64 {
- if b {
- return hashTrue
- }
- return hashFalse
- }
- func (n valueNull) ToInteger() int64 {
- return 0
- }
- func (n valueNull) toString() valueString {
- return stringNull
- }
- func (n valueNull) string() unistring.String {
- return stringNull.string()
- }
- func (n valueNull) ToString() Value {
- return n
- }
- func (n valueNull) String() string {
- return "null"
- }
- func (u valueUndefined) toString() valueString {
- return stringUndefined
- }
- func (u valueUndefined) ToString() Value {
- return u
- }
- func (u valueUndefined) String() string {
- return "undefined"
- }
- func (u valueUndefined) string() unistring.String {
- return "undefined"
- }
- func (u valueUndefined) ToNumber() Value {
- return _NaN
- }
- func (u valueUndefined) ToBigInt() Value {
- panic("RangeError: not a bigint")
- }
- 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 (u valueUndefined) hash(*maphash.Hash) uint64 {
- return hashUndef
- }
- 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) ToBigInt() Value {
- panic(typeError("Cannot convert null to BigInt"))
- }
- 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) baseObject(*Runtime) *Object {
- return nil
- }
- func (n valueNull) Export() interface{} {
- return nil
- }
- func (n valueNull) ExportType() reflect.Type {
- return reflectTypeNil
- }
- func (n valueNull) hash(*maphash.Hash) uint64 {
- return hashNull
- }
- func (p *valueProperty) ToInteger() int64 {
- return 0
- }
- func (p *valueProperty) toString() valueString {
- return stringEmpty
- }
- func (p *valueProperty) string() unistring.String {
- return ""
- }
- func (p *valueProperty) ToString() Value {
- return _undefined
- }
- 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(*Runtime) *Object {
- return nil
- }
- func (p *valueProperty) ToNumber() Value {
- return nil
- }
- func (p *valueProperty) ToBigInt() Value {
- return nil
- }
- 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(Value) bool {
- return false
- }
- func (p *valueProperty) StrictEquals(Value) bool {
- return false
- }
- func (p *valueProperty) baseObject(r *Runtime) *Object {
- r.typeErrorResult(true, "BUG: baseObject() is called on valueProperty") // TODO error message
- return nil
- }
- func (p *valueProperty) Export() interface{} {
- panic("Cannot export valueProperty")
- }
- func (p *valueProperty) ExportType() reflect.Type {
- panic("Cannot export valueProperty")
- }
- func (p *valueProperty) hash(*maphash.Hash) uint64 {
- panic("valueProperty should never be used in maps or sets")
- }
- func floatToIntClip(n float64) int64 {
- switch {
- case math.IsNaN(n):
- return 0
- case n >= math.MaxInt64:
- return math.MaxInt64
- case n <= math.MinInt64:
- return math.MinInt64
- }
- return int64(n)
- }
- func (f valueFloat) ToInteger() int64 {
- return floatToIntClip(float64(f))
- }
- func (f valueFloat) toString() valueString {
- return asciiString(f.String())
- }
- func (f valueFloat) string() unistring.String {
- return unistring.String(f.String())
- }
- func (f valueFloat) ToString() Value {
- return f
- }
- func (f valueFloat) String() string {
- return fToStr(float64(f), ftoa.ModeStandard, 0)
- }
- 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) ToBigInt() Value {
- i := floatToIntClip(float64(f))
- return valueBigInt{big.NewInt(i)}
- }
- func (f valueFloat) SameAs(other Value) bool {
- switch o := other.(type) {
- case valueFloat:
- this := float64(f)
- o1 := float64(o)
- if math.IsNaN(this) && math.IsNaN(o1) {
- return true
- } else {
- ret := this == o1
- if ret && this == 0 {
- ret = math.Signbit(this) == math.Signbit(o1)
- }
- return ret
- }
- case valueInt:
- 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 {
- switch o := other.(type) {
- case valueFloat:
- return f == o
- case valueInt:
- return float64(f) == float64(o)
- case valueString, valueBool:
- return float64(f) == o.ToFloat()
- case *Object:
- return f.Equals(o.toPrimitive())
- }
- return false
- }
- func (f valueFloat) StrictEquals(other Value) bool {
- switch o := other.(type) {
- case valueFloat:
- return f == o
- case valueInt:
- return float64(f) == float64(o)
- }
- return 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 (f valueFloat) hash(*maphash.Hash) uint64 {
- if f == _negativeZero {
- return 0
- }
- return math.Float64bits(float64(f))
- }
- func (b valueBigInt) ToInteger() int64 {
- return b.Int64()
- }
- func (b valueBigInt) toString() valueString {
- return asciiString(b.String())
- }
- func (b valueBigInt) toPrimitiveNumber() Value {
- return b
- }
- func (b valueBigInt) string() unistring.String {
- return unistring.String(b.String())
- }
- func (b valueBigInt) ToString() Value {
- return b
- }
- func (b valueBigInt) String() string {
- return b.Int.String()
- }
- func (b valueBigInt) ToFloat() float64 {
- return float64(b.Int64())
- }
- func (b valueBigInt) ToBoolean() bool {
- return b.Int64() != 0
- }
- func (b valueBigInt) ToObject(r *Runtime) *Object {
- return r.newPrimitiveObject(b, r.global.BigIntPrototype, "BigInt")
- }
- func (b valueBigInt) ToNumber() Value {
- return b
- }
- func (b valueBigInt) ToBigInt() Value {
- return b
- }
- func (b valueBigInt) SameAs(other Value) bool {
- v, ok := other.(valueBigInt)
- return ok && b.Int.Cmp(v.Int) == 0
- return false
- }
- func (b valueBigInt) Equals(other Value) bool {
- switch o := other.(type) {
- case valueBigInt:
- return b.Cmp(o.Int) == 0
- case valueFloat:
- return float64(b.Int64()) == float64(o)
- case valueInt:
- return b.Int64() == int64(o)
- case valueString, valueBool:
- return b.Int64() == o.ToInteger()
- case *Object:
- return b.Equals(o.toPrimitive())
- }
- return false
- }
- func (b valueBigInt) StrictEquals(other Value) bool {
- switch o := other.(type) {
- case valueBigInt:
- return b.Cmp(o.Int) == 0
- }
- return false
- }
- func (b valueBigInt) baseObject(r *Runtime) *Object {
- return r.global.BigIntPrototype
- }
- func (b valueBigInt) Export() interface{} {
- return (*big.Int)(b.Int)
- }
- func (b valueBigInt) ExportType() reflect.Type {
- return reflectTypeBigInt
- }
- func (b valueBigInt) hash(*maphash.Hash) uint64 {
- return uint64(b.Int64())
- }
- func (o *Object) ToInteger() int64 {
- return o.toPrimitiveNumber().ToNumber().ToInteger()
- }
- func (o *Object) toString() valueString {
- return o.toPrimitiveString().toString()
- }
- func (o *Object) string() unistring.String {
- return o.toPrimitiveString().string()
- }
- func (o *Object) ToString() Value {
- return o.toPrimitiveString().ToString()
- }
- func (o *Object) String() string {
- return o.toPrimitiveString().String()
- }
- func (o *Object) ToFloat() float64 {
- return o.toPrimitiveNumber().ToFloat()
- }
- func (o *Object) ToBoolean() bool {
- return true
- }
- func (o *Object) ToObject(*Runtime) *Object {
- return o
- }
- func (o *Object) ToNumber() Value {
- return o.toPrimitiveNumber().ToNumber()
- }
- func (o *Object) ToBigInt() Value {
- return o.toPrimitiveBigInt().ToBigInt()
- }
- 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)
- }
- switch o1 := other.(type) {
- case valueInt, valueFloat, valueString, *Symbol:
- return o.toPrimitive().Equals(other)
- case valueBool:
- return o.Equals(o1.ToNumber())
- }
- 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) baseObject(*Runtime) *Object {
- return o
- }
- // Export the Object to a plain Go type. The returned value will be map[string]interface{} unless
- // the Object is a wrapped Go value (created using ToValue()).
- // This method will panic with an *Exception if a JavaScript exception is thrown in the process.
- func (o *Object) Export() (ret interface{}) {
- o.runtime.tryPanic(func() {
- ret = o.self.export(&objectExportCtx{})
- })
- return
- }
- func (o *Object) ExportType() reflect.Type {
- return o.self.exportType()
- }
- func (o *Object) hash(*maphash.Hash) uint64 {
- return o.getId()
- }
- // Get an object's property by name.
- // This method will panic with an *Exception if a JavaScript exception is thrown in the process.
- func (o *Object) Get(name string) Value {
- return o.self.getStr(unistring.NewFromString(name), nil)
- }
- // GetSymbol returns the value of a symbol property. Use one of the Sym* values for well-known
- // symbols (such as SymIterator, SymToStringTag, etc...).
- // This method will panic with an *Exception if a JavaScript exception is thrown in the process.
- func (o *Object) GetSymbol(sym *Symbol) Value {
- return o.self.getSym(sym, nil)
- }
- // Keys returns a list of Object's enumerable keys.
- // This method will panic with an *Exception if a JavaScript exception is thrown in the process.
- func (o *Object) Keys() (keys []string) {
- iter := &enumerableIter{
- o: o,
- wrapped: o.self.iterateStringKeys(),
- }
- for item, next := iter.next(); next != nil; item, next = next() {
- keys = append(keys, item.name.String())
- }
- return
- }
- // Symbols returns a list of Object's enumerable symbol properties.
- // This method will panic with an *Exception if a JavaScript exception is thrown in the process.
- func (o *Object) Symbols() []*Symbol {
- symbols := o.self.symbols(false, nil)
- ret := make([]*Symbol, len(symbols))
- for i, sym := range symbols {
- ret[i], _ = sym.(*Symbol)
- }
- return ret
- }
- // 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 o.runtime.try(func() {
- o.self.defineOwnPropertyStr(unistring.NewFromString(name), PropertyDescriptor{
- 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 o.runtime.try(func() {
- o.self.defineOwnPropertyStr(unistring.NewFromString(name), PropertyDescriptor{
- Getter: getter,
- Setter: setter,
- Configurable: configurable,
- Enumerable: enumerable,
- }, true)
- })
- }
- // DefineDataPropertySymbol is a Go equivalent of Object.defineProperty(o, name, {value: value, writable: writable,
- // configurable: configurable, enumerable: enumerable})
- func (o *Object) DefineDataPropertySymbol(name *Symbol, value Value, writable, configurable, enumerable Flag) error {
- return o.runtime.try(func() {
- o.self.defineOwnPropertySym(name, PropertyDescriptor{
- Value: value,
- Writable: writable,
- Configurable: configurable,
- Enumerable: enumerable,
- }, true)
- })
- }
- // DefineAccessorPropertySymbol is a Go equivalent of Object.defineProperty(o, name, {get: getter, set: setter,
- // configurable: configurable, enumerable: enumerable})
- func (o *Object) DefineAccessorPropertySymbol(name *Symbol, getter, setter Value, configurable, enumerable Flag) error {
- return o.runtime.try(func() {
- o.self.defineOwnPropertySym(name, PropertyDescriptor{
- Getter: getter,
- Setter: setter,
- Configurable: configurable,
- Enumerable: enumerable,
- }, true)
- })
- }
- func (o *Object) Set(name string, value interface{}) error {
- return o.runtime.try(func() {
- o.self.setOwnStr(unistring.NewFromString(name), o.runtime.ToValue(value), true)
- })
- }
- func (o *Object) SetSymbol(name *Symbol, value interface{}) error {
- return o.runtime.try(func() {
- o.self.setOwnSym(name, o.runtime.ToValue(value), true)
- })
- }
- func (o *Object) Delete(name string) error {
- return o.runtime.try(func() {
- o.self.deleteStr(unistring.NewFromString(name), true)
- })
- }
- func (o *Object) DeleteSymbol(name *Symbol) error {
- return o.runtime.try(func() {
- o.self.deleteSym(name, true)
- })
- }
- // Prototype returns the Object's prototype, same as Object.getPrototypeOf(). If the prototype is null
- // returns nil.
- func (o *Object) Prototype() *Object {
- return o.self.proto()
- }
- // SetPrototype sets the Object's prototype, same as Object.setPrototypeOf(). Setting proto to nil
- // is an equivalent of Object.setPrototypeOf(null).
- func (o *Object) SetPrototype(proto *Object) error {
- return o.runtime.try(func() {
- o.self.setProto(proto, 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
- }
- // ClassName returns the class name
- func (o *Object) ClassName() string {
- return o.self.className()
- }
- 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() unistring.String {
- o.throw()
- return ""
- }
- func (o valueUnresolved) ToString() Value {
- 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(*Runtime) *Object {
- o.throw()
- return nil
- }
- func (o valueUnresolved) ToNumber() Value {
- o.throw()
- return nil
- }
- func (o valueUnresolved) ToBigInt() Value {
- o.throw()
- return nil
- }
- func (o valueUnresolved) SameAs(Value) bool {
- o.throw()
- return false
- }
- func (o valueUnresolved) Equals(Value) bool {
- o.throw()
- return false
- }
- func (o valueUnresolved) StrictEquals(Value) bool {
- o.throw()
- return false
- }
- func (o valueUnresolved) baseObject(*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 (o valueUnresolved) hash(*maphash.Hash) uint64 {
- o.throw()
- return 0
- }
- func (s *Symbol) ToInteger() int64 {
- panic(typeError("Cannot convert a Symbol value to a number"))
- }
- func (s *Symbol) toString() valueString {
- panic(typeError("Cannot convert a Symbol value to a string"))
- }
- func (s *Symbol) ToString() Value {
- return s
- }
- func (s *Symbol) String() string {
- if s.desc != nil {
- return s.desc.String()
- }
- return ""
- }
- func (s *Symbol) string() unistring.String {
- if s.desc != nil {
- return s.desc.string()
- }
- return ""
- }
- func (s *Symbol) ToFloat() float64 {
- panic(typeError("Cannot convert a Symbol value to a number"))
- }
- func (s *Symbol) ToNumber() Value {
- panic(typeError("Cannot convert a Symbol value to a number"))
- }
- func (s *Symbol) ToBigInt() Value {
- panic(typeError("Cannot convert a Symbol value to a bigint"))
- }
- func (s *Symbol) ToBoolean() bool {
- return true
- }
- func (s *Symbol) ToObject(r *Runtime) *Object {
- return s.baseObject(r)
- }
- func (s *Symbol) SameAs(other Value) bool {
- if s1, ok := other.(*Symbol); ok {
- return s == s1
- }
- return false
- }
- func (s *Symbol) Equals(o Value) bool {
- switch o := o.(type) {
- case *Object:
- return s.Equals(o.toPrimitive())
- }
- return s.SameAs(o)
- }
- func (s *Symbol) StrictEquals(o Value) bool {
- return s.SameAs(o)
- }
- func (s *Symbol) Export() interface{} {
- return s.String()
- }
- func (s *Symbol) ExportType() reflect.Type {
- return reflectTypeString
- }
- func (s *Symbol) baseObject(r *Runtime) *Object {
- return r.newPrimitiveObject(s, r.global.SymbolPrototype, "Symbol")
- }
- func (s *Symbol) hash(*maphash.Hash) uint64 {
- return uint64(s.h)
- }
- func exportValue(v Value, ctx *objectExportCtx) interface{} {
- if obj, ok := v.(*Object); ok {
- return obj.self.export(ctx)
- }
- return v.Export()
- }
- func newSymbol(s valueString) *Symbol {
- r := &Symbol{
- desc: s,
- }
- // This may need to be reconsidered in the future.
- // Depending on changes in Go's allocation policy and/or introduction of a compacting GC
- // this may no longer provide sufficient dispersion. The alternative, however, is a globally
- // synchronised random generator/hasher/sequencer and I don't want to go down that route just yet.
- r.h = uintptr(unsafe.Pointer(r))
- return r
- }
- func NewSymbol(s string) *Symbol {
- return newSymbol(newStringValue(s))
- }
- func (s *Symbol) descriptiveString() valueString {
- desc := s.desc
- if desc == nil {
- desc = stringEmpty
- }
- return asciiString("Symbol(").concat(desc).concat(asciiString(")"))
- }
- func funcName(prefix string, n Value) valueString {
- var b valueStringBuilder
- b.WriteString(asciiString(prefix))
- if sym, ok := n.(*Symbol); ok {
- if sym.desc != nil {
- b.WriteRune('[')
- b.WriteString(sym.desc)
- b.WriteRune(']')
- }
- } else {
- b.WriteString(n.toString())
- }
- return b.String()
- }
- func init() {
- for i := 0; i < 256; i++ {
- intCache[i] = valueInt(i - 128)
- }
- _positiveZero = intToValue(0)
- }
|