object_class.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. package otto
  2. import (
  3. "encoding/json"
  4. )
  5. type _objectClass struct {
  6. getOwnProperty func(*_object, string) *_property
  7. getProperty func(*_object, string) *_property
  8. get func(*_object, string) Value
  9. canPut func(*_object, string) bool
  10. put func(*_object, string, Value, bool)
  11. hasProperty func(*_object, string) bool
  12. hasOwnProperty func(*_object, string) bool
  13. defineOwnProperty func(*_object, string, _property, bool) bool
  14. delete func(*_object, string, bool) bool
  15. enumerate func(*_object, bool, func(string) bool)
  16. clone func(*_object, *_object, *_clone) *_object
  17. marshalJSON func(*_object) json.Marshaler
  18. }
  19. func objectEnumerate(self *_object, all bool, each func(string) bool) {
  20. for _, name := range self.propertyOrder {
  21. if all || self.property[name].enumerable() {
  22. if !each(name) {
  23. return
  24. }
  25. }
  26. }
  27. }
  28. var (
  29. _classObject,
  30. _classArray,
  31. _classString,
  32. _classArguments,
  33. _classGoStruct,
  34. _classGoMap,
  35. _classGoArray,
  36. _classGoSlice,
  37. _ *_objectClass
  38. )
  39. func init() {
  40. _classObject = &_objectClass{
  41. objectGetOwnProperty,
  42. objectGetProperty,
  43. objectGet,
  44. objectCanPut,
  45. objectPut,
  46. objectHasProperty,
  47. objectHasOwnProperty,
  48. objectDefineOwnProperty,
  49. objectDelete,
  50. objectEnumerate,
  51. objectClone,
  52. nil,
  53. }
  54. _classArray = &_objectClass{
  55. objectGetOwnProperty,
  56. objectGetProperty,
  57. objectGet,
  58. objectCanPut,
  59. objectPut,
  60. objectHasProperty,
  61. objectHasOwnProperty,
  62. arrayDefineOwnProperty,
  63. objectDelete,
  64. objectEnumerate,
  65. objectClone,
  66. nil,
  67. }
  68. _classString = &_objectClass{
  69. stringGetOwnProperty,
  70. objectGetProperty,
  71. objectGet,
  72. objectCanPut,
  73. objectPut,
  74. objectHasProperty,
  75. objectHasOwnProperty,
  76. objectDefineOwnProperty,
  77. objectDelete,
  78. stringEnumerate,
  79. objectClone,
  80. nil,
  81. }
  82. _classArguments = &_objectClass{
  83. argumentsGetOwnProperty,
  84. objectGetProperty,
  85. argumentsGet,
  86. objectCanPut,
  87. objectPut,
  88. objectHasProperty,
  89. objectHasOwnProperty,
  90. argumentsDefineOwnProperty,
  91. argumentsDelete,
  92. objectEnumerate,
  93. objectClone,
  94. nil,
  95. }
  96. _classGoStruct = &_objectClass{
  97. goStructGetOwnProperty,
  98. objectGetProperty,
  99. objectGet,
  100. goStructCanPut,
  101. goStructPut,
  102. objectHasProperty,
  103. objectHasOwnProperty,
  104. objectDefineOwnProperty,
  105. objectDelete,
  106. goStructEnumerate,
  107. objectClone,
  108. goStructMarshalJSON,
  109. }
  110. _classGoMap = &_objectClass{
  111. goMapGetOwnProperty,
  112. objectGetProperty,
  113. objectGet,
  114. objectCanPut,
  115. objectPut,
  116. objectHasProperty,
  117. objectHasOwnProperty,
  118. goMapDefineOwnProperty,
  119. goMapDelete,
  120. goMapEnumerate,
  121. objectClone,
  122. nil,
  123. }
  124. _classGoArray = &_objectClass{
  125. goArrayGetOwnProperty,
  126. objectGetProperty,
  127. objectGet,
  128. objectCanPut,
  129. objectPut,
  130. objectHasProperty,
  131. objectHasOwnProperty,
  132. goArrayDefineOwnProperty,
  133. goArrayDelete,
  134. goArrayEnumerate,
  135. objectClone,
  136. nil,
  137. }
  138. _classGoSlice = &_objectClass{
  139. goSliceGetOwnProperty,
  140. objectGetProperty,
  141. objectGet,
  142. objectCanPut,
  143. objectPut,
  144. objectHasProperty,
  145. objectHasOwnProperty,
  146. goSliceDefineOwnProperty,
  147. goSliceDelete,
  148. goSliceEnumerate,
  149. objectClone,
  150. nil,
  151. }
  152. }
  153. // Allons-y
  154. // 8.12.1
  155. func objectGetOwnProperty(self *_object, name string) *_property {
  156. // Return a _copy_ of the property
  157. property, exists := self._read(name)
  158. if !exists {
  159. return nil
  160. }
  161. return &property
  162. }
  163. // 8.12.2
  164. func objectGetProperty(self *_object, name string) *_property {
  165. property := self.getOwnProperty(name)
  166. if property != nil {
  167. return property
  168. }
  169. if self.prototype != nil {
  170. return self.prototype.getProperty(name)
  171. }
  172. return nil
  173. }
  174. // 8.12.3
  175. func objectGet(self *_object, name string) Value {
  176. property := self.getProperty(name)
  177. if property != nil {
  178. return property.get(self)
  179. }
  180. return Value{}
  181. }
  182. // 8.12.4
  183. func objectCanPut(self *_object, name string) bool {
  184. canPut, _, _ := _objectCanPut(self, name)
  185. return canPut
  186. }
  187. func _objectCanPut(self *_object, name string) (canPut bool, property *_property, setter *_object) {
  188. property = self.getOwnProperty(name)
  189. if property != nil {
  190. switch propertyValue := property.value.(type) {
  191. case Value:
  192. canPut = property.writable()
  193. return
  194. case _propertyGetSet:
  195. setter = propertyValue[1]
  196. canPut = setter != nil
  197. return
  198. default:
  199. panic(self.runtime.panicTypeError())
  200. }
  201. }
  202. if self.prototype == nil {
  203. return self.extensible, nil, nil
  204. }
  205. property = self.prototype.getProperty(name)
  206. if property == nil {
  207. return self.extensible, nil, nil
  208. }
  209. switch propertyValue := property.value.(type) {
  210. case Value:
  211. if !self.extensible {
  212. return false, nil, nil
  213. }
  214. return property.writable(), nil, nil
  215. case _propertyGetSet:
  216. setter = propertyValue[1]
  217. canPut = setter != nil
  218. return
  219. default:
  220. panic(self.runtime.panicTypeError())
  221. }
  222. }
  223. // 8.12.5
  224. func objectPut(self *_object, name string, value Value, throw bool) {
  225. if true {
  226. // Shortcut...
  227. //
  228. // So, right now, every class is using objectCanPut and every class
  229. // is using objectPut.
  230. //
  231. // If that were to no longer be the case, we would have to have
  232. // something to detect that here, so that we do not use an
  233. // incompatible canPut routine
  234. canPut, property, setter := _objectCanPut(self, name)
  235. if !canPut {
  236. self.runtime.typeErrorResult(throw)
  237. } else if setter != nil {
  238. setter.call(toValue(self), []Value{value}, false, nativeFrame)
  239. } else if property != nil {
  240. property.value = value
  241. self.defineOwnProperty(name, *property, throw)
  242. } else {
  243. self.defineProperty(name, value, 0111, throw)
  244. }
  245. return
  246. }
  247. // The long way...
  248. //
  249. // Right now, code should never get here, see above
  250. if !self.canPut(name) {
  251. self.runtime.typeErrorResult(throw)
  252. return
  253. }
  254. property := self.getOwnProperty(name)
  255. if property == nil {
  256. property = self.getProperty(name)
  257. if property != nil {
  258. if getSet, isAccessor := property.value.(_propertyGetSet); isAccessor {
  259. getSet[1].call(toValue(self), []Value{value}, false, nativeFrame)
  260. return
  261. }
  262. }
  263. self.defineProperty(name, value, 0111, throw)
  264. } else {
  265. switch propertyValue := property.value.(type) {
  266. case Value:
  267. property.value = value
  268. self.defineOwnProperty(name, *property, throw)
  269. case _propertyGetSet:
  270. if propertyValue[1] != nil {
  271. propertyValue[1].call(toValue(self), []Value{value}, false, nativeFrame)
  272. return
  273. }
  274. if throw {
  275. panic(self.runtime.panicTypeError())
  276. }
  277. default:
  278. panic(self.runtime.panicTypeError())
  279. }
  280. }
  281. }
  282. // 8.12.6
  283. func objectHasProperty(self *_object, name string) bool {
  284. return self.getProperty(name) != nil
  285. }
  286. func objectHasOwnProperty(self *_object, name string) bool {
  287. return self.getOwnProperty(name) != nil
  288. }
  289. // 8.12.9
  290. func objectDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool {
  291. property, exists := self._read(name)
  292. {
  293. if !exists {
  294. if !self.extensible {
  295. goto Reject
  296. }
  297. if newGetSet, isAccessor := descriptor.value.(_propertyGetSet); isAccessor {
  298. if newGetSet[0] == &_nilGetSetObject {
  299. newGetSet[0] = nil
  300. }
  301. if newGetSet[1] == &_nilGetSetObject {
  302. newGetSet[1] = nil
  303. }
  304. descriptor.value = newGetSet
  305. }
  306. self._write(name, descriptor.value, descriptor.mode)
  307. return true
  308. }
  309. if descriptor.isEmpty() {
  310. return true
  311. }
  312. // TODO Per 8.12.9.6 - We should shortcut here (returning true) if
  313. // the current and new (define) properties are the same
  314. configurable := property.configurable()
  315. if !configurable {
  316. if descriptor.configurable() {
  317. goto Reject
  318. }
  319. // Test that, if enumerable is set on the property descriptor, then it should
  320. // be the same as the existing property
  321. if descriptor.enumerateSet() && descriptor.enumerable() != property.enumerable() {
  322. goto Reject
  323. }
  324. }
  325. value, isDataDescriptor := property.value.(Value)
  326. getSet, _ := property.value.(_propertyGetSet)
  327. if descriptor.isGenericDescriptor() {
  328. // GenericDescriptor
  329. } else if isDataDescriptor != descriptor.isDataDescriptor() {
  330. // DataDescriptor <=> AccessorDescriptor
  331. if !configurable {
  332. goto Reject
  333. }
  334. } else if isDataDescriptor && descriptor.isDataDescriptor() {
  335. // DataDescriptor <=> DataDescriptor
  336. if !configurable {
  337. if !property.writable() && descriptor.writable() {
  338. goto Reject
  339. }
  340. if !property.writable() {
  341. if descriptor.value != nil && !sameValue(value, descriptor.value.(Value)) {
  342. goto Reject
  343. }
  344. }
  345. }
  346. } else {
  347. // AccessorDescriptor <=> AccessorDescriptor
  348. newGetSet, _ := descriptor.value.(_propertyGetSet)
  349. presentGet, presentSet := true, true
  350. if newGetSet[0] == &_nilGetSetObject {
  351. // Present, but nil
  352. newGetSet[0] = nil
  353. } else if newGetSet[0] == nil {
  354. // Missing, not even nil
  355. newGetSet[0] = getSet[0]
  356. presentGet = false
  357. }
  358. if newGetSet[1] == &_nilGetSetObject {
  359. // Present, but nil
  360. newGetSet[1] = nil
  361. } else if newGetSet[1] == nil {
  362. // Missing, not even nil
  363. newGetSet[1] = getSet[1]
  364. presentSet = false
  365. }
  366. if !configurable {
  367. if (presentGet && (getSet[0] != newGetSet[0])) || (presentSet && (getSet[1] != newGetSet[1])) {
  368. goto Reject
  369. }
  370. }
  371. descriptor.value = newGetSet
  372. }
  373. {
  374. // This section will preserve attributes of
  375. // the original property, if necessary
  376. value1 := descriptor.value
  377. if value1 == nil {
  378. value1 = property.value
  379. } else if newGetSet, isAccessor := descriptor.value.(_propertyGetSet); isAccessor {
  380. if newGetSet[0] == &_nilGetSetObject {
  381. newGetSet[0] = nil
  382. }
  383. if newGetSet[1] == &_nilGetSetObject {
  384. newGetSet[1] = nil
  385. }
  386. value1 = newGetSet
  387. }
  388. mode1 := descriptor.mode
  389. if mode1&0222 != 0 {
  390. // TODO Factor this out into somewhere testable
  391. // (Maybe put into switch ...)
  392. mode0 := property.mode
  393. if mode1&0200 != 0 {
  394. if descriptor.isDataDescriptor() {
  395. mode1 &= ^0200 // Turn off "writable" missing
  396. mode1 |= (mode0 & 0100)
  397. }
  398. }
  399. if mode1&020 != 0 {
  400. mode1 |= (mode0 & 010)
  401. }
  402. if mode1&02 != 0 {
  403. mode1 |= (mode0 & 01)
  404. }
  405. mode1 &= 0311 // 0311 to preserve the non-setting on "writable"
  406. }
  407. self._write(name, value1, mode1)
  408. }
  409. return true
  410. }
  411. Reject:
  412. if throw {
  413. panic(self.runtime.panicTypeError())
  414. }
  415. return false
  416. }
  417. func objectDelete(self *_object, name string, throw bool) bool {
  418. property_ := self.getOwnProperty(name)
  419. if property_ == nil {
  420. return true
  421. }
  422. if property_.configurable() {
  423. self._delete(name)
  424. return true
  425. }
  426. return self.runtime.typeErrorResult(throw)
  427. }
  428. func objectClone(in *_object, out *_object, clone *_clone) *_object {
  429. *out = *in
  430. out.runtime = clone.runtime
  431. if out.prototype != nil {
  432. out.prototype = clone.object(in.prototype)
  433. }
  434. out.property = make(map[string]_property, len(in.property))
  435. out.propertyOrder = make([]string, len(in.propertyOrder))
  436. copy(out.propertyOrder, in.propertyOrder)
  437. for index, property := range in.property {
  438. out.property[index] = clone.property(property)
  439. }
  440. switch value := in.value.(type) {
  441. case _nativeFunctionObject:
  442. out.value = value
  443. case _bindFunctionObject:
  444. out.value = _bindFunctionObject{
  445. target: clone.object(value.target),
  446. this: clone.value(value.this),
  447. argumentList: clone.valueArray(value.argumentList),
  448. }
  449. case _nodeFunctionObject:
  450. out.value = _nodeFunctionObject{
  451. node: value.node,
  452. stash: clone.stash(value.stash),
  453. }
  454. case _argumentsObject:
  455. out.value = value.clone(clone)
  456. }
  457. return out
  458. }