github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/value.go (about)

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