go.ketch.com/lib/goja@v0.0.1/value.go (about)

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