object.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package otto
  2. type object struct {
  3. value interface{}
  4. runtime *runtime
  5. objectClass *objectClass
  6. prototype *object
  7. property map[string]property
  8. class string
  9. propertyOrder []string
  10. extensible bool
  11. }
  12. func newObject(rt *runtime, class string) *object {
  13. o := &object{
  14. runtime: rt,
  15. class: class,
  16. objectClass: classObject,
  17. property: make(map[string]property),
  18. extensible: true,
  19. }
  20. return o
  21. }
  22. // 8.12
  23. // 8.12.1.
  24. func (o *object) getOwnProperty(name string) *property {
  25. return o.objectClass.getOwnProperty(o, name)
  26. }
  27. // 8.12.2.
  28. func (o *object) getProperty(name string) *property {
  29. return o.objectClass.getProperty(o, name)
  30. }
  31. // 8.12.3.
  32. func (o *object) get(name string) Value {
  33. return o.objectClass.get(o, name)
  34. }
  35. // 8.12.4.
  36. func (o *object) canPut(name string) bool {
  37. return o.objectClass.canPut(o, name)
  38. }
  39. // 8.12.5.
  40. func (o *object) put(name string, value Value, throw bool) {
  41. o.objectClass.put(o, name, value, throw)
  42. }
  43. // 8.12.6.
  44. func (o *object) hasProperty(name string) bool {
  45. return o.objectClass.hasProperty(o, name)
  46. }
  47. func (o *object) hasOwnProperty(name string) bool {
  48. return o.objectClass.hasOwnProperty(o, name)
  49. }
  50. type defaultValueHint int
  51. const (
  52. defaultValueNoHint defaultValueHint = iota
  53. defaultValueHintString
  54. defaultValueHintNumber
  55. )
  56. // 8.12.8.
  57. func (o *object) DefaultValue(hint defaultValueHint) Value {
  58. if hint == defaultValueNoHint {
  59. if o.class == classDateName {
  60. // Date exception
  61. hint = defaultValueHintString
  62. } else {
  63. hint = defaultValueHintNumber
  64. }
  65. }
  66. methodSequence := []string{"valueOf", "toString"}
  67. if hint == defaultValueHintString {
  68. methodSequence = []string{"toString", "valueOf"}
  69. }
  70. for _, methodName := range methodSequence {
  71. method := o.get(methodName)
  72. // FIXME This is redundant...
  73. if method.isCallable() {
  74. result := method.object().call(objectValue(o), nil, false, nativeFrame)
  75. if result.IsPrimitive() {
  76. return result
  77. }
  78. }
  79. }
  80. panic(o.runtime.panicTypeError("Object.DefaultValue unknown"))
  81. }
  82. func (o *object) String() string {
  83. return o.DefaultValue(defaultValueHintString).string()
  84. }
  85. func (o *object) defineProperty(name string, value Value, mode propertyMode, throw bool) bool { //nolint:unparam
  86. return o.defineOwnProperty(name, property{value, mode}, throw)
  87. }
  88. // 8.12.9.
  89. func (o *object) defineOwnProperty(name string, descriptor property, throw bool) bool {
  90. return o.objectClass.defineOwnProperty(o, name, descriptor, throw)
  91. }
  92. func (o *object) delete(name string, throw bool) bool {
  93. return o.objectClass.delete(o, name, throw)
  94. }
  95. func (o *object) enumerate(all bool, each func(string) bool) {
  96. o.objectClass.enumerate(o, all, each)
  97. }
  98. func (o *object) readProperty(name string) (property, bool) {
  99. prop, exists := o.property[name]
  100. return prop, exists
  101. }
  102. func (o *object) writeProperty(name string, value interface{}, mode propertyMode) {
  103. if value == nil {
  104. value = Value{}
  105. }
  106. if _, exists := o.property[name]; !exists {
  107. o.propertyOrder = append(o.propertyOrder, name)
  108. }
  109. o.property[name] = property{value, mode}
  110. }
  111. func (o *object) deleteProperty(name string) {
  112. if _, exists := o.property[name]; !exists {
  113. return
  114. }
  115. delete(o.property, name)
  116. for index, prop := range o.propertyOrder {
  117. if name == prop {
  118. if index == len(o.propertyOrder)-1 {
  119. o.propertyOrder = o.propertyOrder[:index]
  120. } else {
  121. o.propertyOrder = append(o.propertyOrder[:index], o.propertyOrder[index+1:]...)
  122. }
  123. }
  124. }
  125. }