object_args.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package goja
  2. import "github.com/dop251/goja/unistring"
  3. type argumentsObject struct {
  4. baseObject
  5. length int
  6. }
  7. type mappedProperty struct {
  8. valueProperty
  9. v *Value
  10. }
  11. func (a *argumentsObject) getStr(name unistring.String, receiver Value) Value {
  12. return a.getStrWithOwnProp(a.getOwnPropStr(name), name, receiver)
  13. }
  14. func (a *argumentsObject) getOwnPropStr(name unistring.String) Value {
  15. if mapped, ok := a.values[name].(*mappedProperty); ok {
  16. if mapped.writable && mapped.enumerable && mapped.configurable {
  17. return *mapped.v
  18. }
  19. return &valueProperty{
  20. value: *mapped.v,
  21. writable: mapped.writable,
  22. configurable: mapped.configurable,
  23. enumerable: mapped.enumerable,
  24. }
  25. }
  26. return a.baseObject.getOwnPropStr(name)
  27. }
  28. func (a *argumentsObject) init() {
  29. a.baseObject.init()
  30. a._putProp("length", intToValue(int64(a.length)), true, false, true)
  31. }
  32. func (a *argumentsObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
  33. if prop, ok := a.values[name].(*mappedProperty); ok {
  34. if !prop.writable {
  35. a.val.runtime.typeErrorResult(throw, "Property is not writable: %s", name)
  36. return false
  37. }
  38. *prop.v = val
  39. return true
  40. }
  41. return a.baseObject.setOwnStr(name, val, throw)
  42. }
  43. func (a *argumentsObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
  44. return a._setForeignStr(name, a.getOwnPropStr(name), val, receiver, throw)
  45. }
  46. func (a *argumentsObject) deleteStr(name unistring.String, throw bool) bool {
  47. if prop, ok := a.values[name].(*mappedProperty); ok {
  48. if !a.checkDeleteProp(name, &prop.valueProperty, throw) {
  49. return false
  50. }
  51. a._delete(name)
  52. return true
  53. }
  54. return a.baseObject.deleteStr(name, throw)
  55. }
  56. type argumentsPropIter struct {
  57. wrapped iterNextFunc
  58. }
  59. func (i *argumentsPropIter) next() (propIterItem, iterNextFunc) {
  60. var item propIterItem
  61. item, i.wrapped = i.wrapped()
  62. if i.wrapped == nil {
  63. return propIterItem{}, nil
  64. }
  65. if prop, ok := item.value.(*mappedProperty); ok {
  66. item.value = *prop.v
  67. }
  68. return item, i.next
  69. }
  70. func (a *argumentsObject) iterateStringKeys() iterNextFunc {
  71. return (&argumentsPropIter{
  72. wrapped: a.baseObject.iterateStringKeys(),
  73. }).next
  74. }
  75. func (a *argumentsObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
  76. if mapped, ok := a.values[name].(*mappedProperty); ok {
  77. existing := &valueProperty{
  78. configurable: mapped.configurable,
  79. writable: true,
  80. enumerable: mapped.enumerable,
  81. value: *mapped.v,
  82. }
  83. val, ok := a.baseObject._defineOwnProperty(name, existing, descr, throw)
  84. if !ok {
  85. return false
  86. }
  87. if prop, ok := val.(*valueProperty); ok {
  88. if !prop.accessor {
  89. *mapped.v = prop.value
  90. }
  91. if prop.accessor || !prop.writable {
  92. a._put(name, prop)
  93. return true
  94. }
  95. mapped.configurable = prop.configurable
  96. mapped.enumerable = prop.enumerable
  97. } else {
  98. *mapped.v = val
  99. mapped.configurable = true
  100. mapped.enumerable = true
  101. }
  102. return true
  103. }
  104. return a.baseObject.defineOwnPropertyStr(name, descr, throw)
  105. }
  106. func (a *argumentsObject) export(ctx *objectExportCtx) interface{} {
  107. if v, exists := ctx.get(a.val); exists {
  108. return v
  109. }
  110. arr := make([]interface{}, a.length)
  111. ctx.put(a.val, arr)
  112. for i := range arr {
  113. v := a.getIdx(valueInt(int64(i)), nil)
  114. if v != nil {
  115. arr[i] = exportValue(v, ctx)
  116. }
  117. }
  118. return arr
  119. }