builtin_object.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. package otto
  2. import (
  3. "fmt"
  4. )
  5. // Object
  6. func builtinObject(call FunctionCall) Value {
  7. value := call.Argument(0)
  8. switch value.kind {
  9. case valueUndefined, valueNull:
  10. return toValue_object(call.runtime.newObject())
  11. }
  12. return toValue_object(call.runtime.toObject(value))
  13. }
  14. func builtinNewObject(self *_object, argumentList []Value) Value {
  15. value := valueOfArrayIndex(argumentList, 0)
  16. switch value.kind {
  17. case valueNull, valueUndefined:
  18. case valueNumber, valueString, valueBoolean:
  19. return toValue_object(self.runtime.toObject(value))
  20. case valueObject:
  21. return value
  22. default:
  23. }
  24. return toValue_object(self.runtime.newObject())
  25. }
  26. func builtinObject_valueOf(call FunctionCall) Value {
  27. return toValue_object(call.thisObject())
  28. }
  29. func builtinObject_hasOwnProperty(call FunctionCall) Value {
  30. propertyName := call.Argument(0).string()
  31. thisObject := call.thisObject()
  32. return toValue_bool(thisObject.hasOwnProperty(propertyName))
  33. }
  34. func builtinObject_isPrototypeOf(call FunctionCall) Value {
  35. value := call.Argument(0)
  36. if !value.IsObject() {
  37. return falseValue
  38. }
  39. prototype := call.toObject(value).prototype
  40. thisObject := call.thisObject()
  41. for prototype != nil {
  42. if thisObject == prototype {
  43. return trueValue
  44. }
  45. prototype = prototype.prototype
  46. }
  47. return falseValue
  48. }
  49. func builtinObject_propertyIsEnumerable(call FunctionCall) Value {
  50. propertyName := call.Argument(0).string()
  51. thisObject := call.thisObject()
  52. property := thisObject.getOwnProperty(propertyName)
  53. if property != nil && property.enumerable() {
  54. return trueValue
  55. }
  56. return falseValue
  57. }
  58. func builtinObject_toString(call FunctionCall) Value {
  59. var result string
  60. if call.This.IsUndefined() {
  61. result = "[object Undefined]"
  62. } else if call.This.IsNull() {
  63. result = "[object Null]"
  64. } else {
  65. result = fmt.Sprintf("[object %s]", call.thisObject().class)
  66. }
  67. return toValue_string(result)
  68. }
  69. func builtinObject_toLocaleString(call FunctionCall) Value {
  70. toString := call.thisObject().get("toString")
  71. if !toString.isCallable() {
  72. panic(call.runtime.panicTypeError())
  73. }
  74. return toString.call(call.runtime, call.This)
  75. }
  76. func builtinObject_getPrototypeOf(call FunctionCall) Value {
  77. objectValue := call.Argument(0)
  78. object := objectValue._object()
  79. if object == nil {
  80. panic(call.runtime.panicTypeError())
  81. }
  82. if object.prototype == nil {
  83. return nullValue
  84. }
  85. return toValue_object(object.prototype)
  86. }
  87. func builtinObject_getOwnPropertyDescriptor(call FunctionCall) Value {
  88. objectValue := call.Argument(0)
  89. object := objectValue._object()
  90. if object == nil {
  91. panic(call.runtime.panicTypeError())
  92. }
  93. name := call.Argument(1).string()
  94. descriptor := object.getOwnProperty(name)
  95. if descriptor == nil {
  96. return Value{}
  97. }
  98. return toValue_object(call.runtime.fromPropertyDescriptor(*descriptor))
  99. }
  100. func builtinObject_defineProperty(call FunctionCall) Value {
  101. objectValue := call.Argument(0)
  102. object := objectValue._object()
  103. if object == nil {
  104. panic(call.runtime.panicTypeError())
  105. }
  106. name := call.Argument(1).string()
  107. descriptor := toPropertyDescriptor(call.runtime, call.Argument(2))
  108. object.defineOwnProperty(name, descriptor, true)
  109. return objectValue
  110. }
  111. func builtinObject_defineProperties(call FunctionCall) Value {
  112. objectValue := call.Argument(0)
  113. object := objectValue._object()
  114. if object == nil {
  115. panic(call.runtime.panicTypeError())
  116. }
  117. properties := call.runtime.toObject(call.Argument(1))
  118. properties.enumerate(false, func(name string) bool {
  119. descriptor := toPropertyDescriptor(call.runtime, properties.get(name))
  120. object.defineOwnProperty(name, descriptor, true)
  121. return true
  122. })
  123. return objectValue
  124. }
  125. func builtinObject_create(call FunctionCall) Value {
  126. prototypeValue := call.Argument(0)
  127. if !prototypeValue.IsNull() && !prototypeValue.IsObject() {
  128. panic(call.runtime.panicTypeError())
  129. }
  130. object := call.runtime.newObject()
  131. object.prototype = prototypeValue._object()
  132. propertiesValue := call.Argument(1)
  133. if propertiesValue.IsDefined() {
  134. properties := call.runtime.toObject(propertiesValue)
  135. properties.enumerate(false, func(name string) bool {
  136. descriptor := toPropertyDescriptor(call.runtime, properties.get(name))
  137. object.defineOwnProperty(name, descriptor, true)
  138. return true
  139. })
  140. }
  141. return toValue_object(object)
  142. }
  143. func builtinObject_isExtensible(call FunctionCall) Value {
  144. object := call.Argument(0)
  145. if object := object._object(); object != nil {
  146. return toValue_bool(object.extensible)
  147. }
  148. panic(call.runtime.panicTypeError())
  149. }
  150. func builtinObject_preventExtensions(call FunctionCall) Value {
  151. object := call.Argument(0)
  152. if object := object._object(); object != nil {
  153. object.extensible = false
  154. } else {
  155. panic(call.runtime.panicTypeError())
  156. }
  157. return object
  158. }
  159. func builtinObject_isSealed(call FunctionCall) Value {
  160. object := call.Argument(0)
  161. if object := object._object(); object != nil {
  162. if object.extensible {
  163. return toValue_bool(false)
  164. }
  165. result := true
  166. object.enumerate(true, func(name string) bool {
  167. property := object.getProperty(name)
  168. if property.configurable() {
  169. result = false
  170. }
  171. return true
  172. })
  173. return toValue_bool(result)
  174. }
  175. panic(call.runtime.panicTypeError())
  176. }
  177. func builtinObject_seal(call FunctionCall) Value {
  178. object := call.Argument(0)
  179. if object := object._object(); object != nil {
  180. object.enumerate(true, func(name string) bool {
  181. if property := object.getOwnProperty(name); nil != property && property.configurable() {
  182. property.configureOff()
  183. object.defineOwnProperty(name, *property, true)
  184. }
  185. return true
  186. })
  187. object.extensible = false
  188. } else {
  189. panic(call.runtime.panicTypeError())
  190. }
  191. return object
  192. }
  193. func builtinObject_isFrozen(call FunctionCall) Value {
  194. object := call.Argument(0)
  195. if object := object._object(); object != nil {
  196. if object.extensible {
  197. return toValue_bool(false)
  198. }
  199. result := true
  200. object.enumerate(true, func(name string) bool {
  201. property := object.getProperty(name)
  202. if property.configurable() || property.writable() {
  203. result = false
  204. }
  205. return true
  206. })
  207. return toValue_bool(result)
  208. }
  209. panic(call.runtime.panicTypeError())
  210. }
  211. func builtinObject_freeze(call FunctionCall) Value {
  212. object := call.Argument(0)
  213. if object := object._object(); object != nil {
  214. object.enumerate(true, func(name string) bool {
  215. if property, update := object.getOwnProperty(name), false; nil != property {
  216. if property.isDataDescriptor() && property.writable() {
  217. property.writeOff()
  218. update = true
  219. }
  220. if property.configurable() {
  221. property.configureOff()
  222. update = true
  223. }
  224. if update {
  225. object.defineOwnProperty(name, *property, true)
  226. }
  227. }
  228. return true
  229. })
  230. object.extensible = false
  231. } else {
  232. panic(call.runtime.panicTypeError())
  233. }
  234. return object
  235. }
  236. func builtinObject_keys(call FunctionCall) Value {
  237. if object, keys := call.Argument(0)._object(), []Value(nil); nil != object {
  238. object.enumerate(false, func(name string) bool {
  239. keys = append(keys, toValue_string(name))
  240. return true
  241. })
  242. return toValue_object(call.runtime.newArrayOf(keys))
  243. }
  244. panic(call.runtime.panicTypeError())
  245. }
  246. func builtinObject_getOwnPropertyNames(call FunctionCall) Value {
  247. if object, propertyNames := call.Argument(0)._object(), []Value(nil); nil != object {
  248. object.enumerate(true, func(name string) bool {
  249. if object.hasOwnProperty(name) {
  250. propertyNames = append(propertyNames, toValue_string(name))
  251. }
  252. return true
  253. })
  254. return toValue_object(call.runtime.newArrayOf(propertyNames))
  255. }
  256. panic(call.runtime.panicTypeError())
  257. }