object_gomap.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package goja
  2. import (
  3. "reflect"
  4. "github.com/dop251/goja/unistring"
  5. )
  6. type objectGoMapSimple struct {
  7. baseObject
  8. data map[string]interface{}
  9. }
  10. func (o *objectGoMapSimple) init() {
  11. o.baseObject.init()
  12. o.prototype = o.val.runtime.global.ObjectPrototype
  13. o.class = classObject
  14. o.extensible = true
  15. }
  16. func (o *objectGoMapSimple) _getStr(name string) Value {
  17. v, exists := o.data[name]
  18. if !exists {
  19. return nil
  20. }
  21. return o.val.runtime.ToValue(v)
  22. }
  23. func (o *objectGoMapSimple) getStr(name unistring.String, receiver Value) Value {
  24. if v := o._getStr(name.String()); v != nil {
  25. return v
  26. }
  27. return o.baseObject.getStr(name, receiver)
  28. }
  29. func (o *objectGoMapSimple) getOwnPropStr(name unistring.String) Value {
  30. if v := o._getStr(name.String()); v != nil {
  31. return v
  32. }
  33. return nil
  34. }
  35. func (o *objectGoMapSimple) setOwnStr(name unistring.String, val Value, throw bool) bool {
  36. n := name.String()
  37. if _, exists := o.data[n]; exists {
  38. o.data[n] = val.Export()
  39. return true
  40. }
  41. if proto := o.prototype; proto != nil {
  42. // we know it's foreign because prototype loops are not allowed
  43. if res, ok := proto.self.setForeignStr(name, val, o.val, throw); ok {
  44. return res
  45. }
  46. }
  47. // new property
  48. if !o.extensible {
  49. o.val.runtime.typeErrorResult(throw, "Cannot add property %s, object is not extensible", name)
  50. return false
  51. } else {
  52. o.data[n] = val.Export()
  53. }
  54. return true
  55. }
  56. func trueValIfPresent(present bool) Value {
  57. if present {
  58. return valueTrue
  59. }
  60. return nil
  61. }
  62. func (o *objectGoMapSimple) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
  63. return o._setForeignStr(name, trueValIfPresent(o._hasStr(name.String())), val, receiver, throw)
  64. }
  65. func (o *objectGoMapSimple) _hasStr(name string) bool {
  66. _, exists := o.data[name]
  67. return exists
  68. }
  69. func (o *objectGoMapSimple) hasOwnPropertyStr(name unistring.String) bool {
  70. return o._hasStr(name.String())
  71. }
  72. func (o *objectGoMapSimple) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
  73. if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) {
  74. return false
  75. }
  76. n := name.String()
  77. if o.extensible || o._hasStr(n) {
  78. o.data[n] = descr.Value.Export()
  79. return true
  80. }
  81. o.val.runtime.typeErrorResult(throw, "Cannot define property %s, object is not extensible", n)
  82. return false
  83. }
  84. /*
  85. func (o *objectGoMapSimple) toPrimitiveNumber() Value {
  86. return o.toPrimitiveString()
  87. }
  88. func (o *objectGoMapSimple) toPrimitiveString() Value {
  89. return stringObjectObject
  90. }
  91. func (o *objectGoMapSimple) toPrimitive() Value {
  92. return o.toPrimitiveString()
  93. }
  94. func (o *objectGoMapSimple) assertCallable() (call func(FunctionCall) Value, ok bool) {
  95. return nil, false
  96. }
  97. */
  98. func (o *objectGoMapSimple) deleteStr(name unistring.String, _ bool) bool {
  99. delete(o.data, name.String())
  100. return true
  101. }
  102. type gomapPropIter struct {
  103. o *objectGoMapSimple
  104. propNames []string
  105. idx int
  106. }
  107. func (i *gomapPropIter) next() (propIterItem, iterNextFunc) {
  108. for i.idx < len(i.propNames) {
  109. name := i.propNames[i.idx]
  110. i.idx++
  111. if _, exists := i.o.data[name]; exists {
  112. return propIterItem{name: newStringValue(name), enumerable: _ENUM_TRUE}, i.next
  113. }
  114. }
  115. return propIterItem{}, nil
  116. }
  117. func (o *objectGoMapSimple) iterateStringKeys() iterNextFunc {
  118. propNames := make([]string, len(o.data))
  119. i := 0
  120. for key := range o.data {
  121. propNames[i] = key
  122. i++
  123. }
  124. return (&gomapPropIter{
  125. o: o,
  126. propNames: propNames,
  127. }).next
  128. }
  129. func (o *objectGoMapSimple) stringKeys(_ bool, accum []Value) []Value {
  130. // all own keys are enumerable
  131. for key := range o.data {
  132. accum = append(accum, newStringValue(key))
  133. }
  134. return accum
  135. }
  136. func (o *objectGoMapSimple) export(*objectExportCtx) interface{} {
  137. return o.data
  138. }
  139. func (o *objectGoMapSimple) exportType() reflect.Type {
  140. return reflectTypeMap
  141. }
  142. func (o *objectGoMapSimple) equal(other objectImpl) bool {
  143. if other, ok := other.(*objectGoMapSimple); ok {
  144. return o == other
  145. }
  146. return false
  147. }