builtin_error.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. package goja
  2. import "github.com/dop251/goja/unistring"
  3. const propNameStack = "stack"
  4. type errorObject struct {
  5. baseObject
  6. stack []StackFrame
  7. stackPropAdded bool
  8. }
  9. func (e *errorObject) formatStack() valueString {
  10. var b valueStringBuilder
  11. if name := e.getStr("name", nil); name != nil {
  12. b.WriteString(name.toString())
  13. b.WriteRune('\n')
  14. } else {
  15. b.WriteASCII("Error\n")
  16. }
  17. for _, frame := range e.stack {
  18. b.WriteASCII("\tat ")
  19. frame.WriteToValueBuilder(&b)
  20. b.WriteRune('\n')
  21. }
  22. return b.String()
  23. }
  24. func (e *errorObject) addStackProp() Value {
  25. if !e.stackPropAdded {
  26. res := e._putProp(propNameStack, e.formatStack(), true, false, true)
  27. if len(e.propNames) > 1 {
  28. // reorder property names to ensure 'stack' is the first one
  29. copy(e.propNames[1:], e.propNames)
  30. e.propNames[0] = propNameStack
  31. }
  32. e.stackPropAdded = true
  33. return res
  34. }
  35. return nil
  36. }
  37. func (e *errorObject) getStr(p unistring.String, receiver Value) Value {
  38. return e.getStrWithOwnProp(e.getOwnPropStr(p), p, receiver)
  39. }
  40. func (e *errorObject) getOwnPropStr(name unistring.String) Value {
  41. res := e.baseObject.getOwnPropStr(name)
  42. if res == nil && name == propNameStack {
  43. return e.addStackProp()
  44. }
  45. return res
  46. }
  47. func (e *errorObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
  48. if name == propNameStack {
  49. e.addStackProp()
  50. }
  51. return e.baseObject.setOwnStr(name, val, throw)
  52. }
  53. func (e *errorObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
  54. return e._setForeignStr(name, e.getOwnPropStr(name), val, receiver, throw)
  55. }
  56. func (e *errorObject) deleteStr(name unistring.String, throw bool) bool {
  57. if name == propNameStack {
  58. e.addStackProp()
  59. }
  60. return e.baseObject.deleteStr(name, throw)
  61. }
  62. func (e *errorObject) defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool {
  63. if name == propNameStack {
  64. e.addStackProp()
  65. }
  66. return e.baseObject.defineOwnPropertyStr(name, desc, throw)
  67. }
  68. func (e *errorObject) hasOwnPropertyStr(name unistring.String) bool {
  69. if e.baseObject.hasOwnPropertyStr(name) {
  70. return true
  71. }
  72. return name == propNameStack && !e.stackPropAdded
  73. }
  74. func (e *errorObject) stringKeys(all bool, accum []Value) []Value {
  75. if all && !e.stackPropAdded {
  76. accum = append(accum, asciiString(propNameStack))
  77. }
  78. return e.baseObject.stringKeys(all, accum)
  79. }
  80. func (e *errorObject) iterateStringKeys() iterNextFunc {
  81. e.addStackProp()
  82. return e.baseObject.iterateStringKeys()
  83. }
  84. func (e *errorObject) init() {
  85. e.baseObject.init()
  86. vm := e.val.runtime.vm
  87. e.stack = vm.captureStack(make([]StackFrame, 0, len(vm.callStack)+1), 0)
  88. }
  89. func (r *Runtime) newErrorObject(proto *Object, class string) *errorObject {
  90. obj := &Object{runtime: r}
  91. o := &errorObject{
  92. baseObject: baseObject{
  93. class: class,
  94. val: obj,
  95. extensible: true,
  96. prototype: proto,
  97. },
  98. }
  99. obj.self = o
  100. o.init()
  101. return o
  102. }
  103. func (r *Runtime) builtin_Error(args []Value, proto *Object) *Object {
  104. obj := r.newErrorObject(proto, classError)
  105. if len(args) > 0 && args[0] != _undefined {
  106. obj._putProp("message", args[0], true, false, true)
  107. }
  108. return obj.val
  109. }
  110. func (r *Runtime) builtin_AggregateError(args []Value, proto *Object) *Object {
  111. obj := r.newErrorObject(proto, classAggError)
  112. if len(args) > 1 && args[1] != nil && args[1] != _undefined {
  113. obj._putProp("message", args[1].toString(), true, false, true)
  114. }
  115. var errors []Value
  116. if len(args) > 0 {
  117. errors = r.iterableToList(args[0], nil)
  118. }
  119. obj._putProp("errors", r.newArrayValues(errors), true, false, true)
  120. return obj.val
  121. }
  122. func (r *Runtime) createErrorPrototype(name valueString) *Object {
  123. o := r.newBaseObject(r.global.ErrorPrototype, classObject)
  124. o._putProp("message", stringEmpty, true, false, true)
  125. o._putProp("name", name, true, false, true)
  126. return o.val
  127. }
  128. func (r *Runtime) initErrors() {
  129. r.global.ErrorPrototype = r.NewObject()
  130. o := r.global.ErrorPrototype.self
  131. o._putProp("message", stringEmpty, true, false, true)
  132. o._putProp("name", stringError, true, false, true)
  133. o._putProp("toString", r.newNativeFunc(r.error_toString, nil, "toString", nil, 0), true, false, true)
  134. r.global.Error = r.newNativeFuncConstruct(r.builtin_Error, "Error", r.global.ErrorPrototype, 1)
  135. r.addToGlobal("Error", r.global.Error)
  136. r.global.AggregateErrorPrototype = r.createErrorPrototype(stringAggregateError)
  137. r.global.AggregateError = r.newNativeFuncConstructProto(r.builtin_AggregateError, "AggregateError", r.global.AggregateErrorPrototype, r.global.Error, 2)
  138. r.addToGlobal("AggregateError", r.global.AggregateError)
  139. r.global.TypeErrorPrototype = r.createErrorPrototype(stringTypeError)
  140. r.global.TypeError = r.newNativeFuncConstructProto(r.builtin_Error, "TypeError", r.global.TypeErrorPrototype, r.global.Error, 1)
  141. r.addToGlobal("TypeError", r.global.TypeError)
  142. r.global.ReferenceErrorPrototype = r.createErrorPrototype(stringReferenceError)
  143. r.global.ReferenceError = r.newNativeFuncConstructProto(r.builtin_Error, "ReferenceError", r.global.ReferenceErrorPrototype, r.global.Error, 1)
  144. r.addToGlobal("ReferenceError", r.global.ReferenceError)
  145. r.global.SyntaxErrorPrototype = r.createErrorPrototype(stringSyntaxError)
  146. r.global.SyntaxError = r.newNativeFuncConstructProto(r.builtin_Error, "SyntaxError", r.global.SyntaxErrorPrototype, r.global.Error, 1)
  147. r.addToGlobal("SyntaxError", r.global.SyntaxError)
  148. r.global.RangeErrorPrototype = r.createErrorPrototype(stringRangeError)
  149. r.global.RangeError = r.newNativeFuncConstructProto(r.builtin_Error, "RangeError", r.global.RangeErrorPrototype, r.global.Error, 1)
  150. r.addToGlobal("RangeError", r.global.RangeError)
  151. r.global.EvalErrorPrototype = r.createErrorPrototype(stringEvalError)
  152. o = r.global.EvalErrorPrototype.self
  153. o._putProp("name", stringEvalError, true, false, true)
  154. r.global.EvalError = r.newNativeFuncConstructProto(r.builtin_Error, "EvalError", r.global.EvalErrorPrototype, r.global.Error, 1)
  155. r.addToGlobal("EvalError", r.global.EvalError)
  156. r.global.URIErrorPrototype = r.createErrorPrototype(stringURIError)
  157. r.global.URIError = r.newNativeFuncConstructProto(r.builtin_Error, "URIError", r.global.URIErrorPrototype, r.global.Error, 1)
  158. r.addToGlobal("URIError", r.global.URIError)
  159. r.global.GoErrorPrototype = r.createErrorPrototype(stringGoError)
  160. r.global.GoError = r.newNativeFuncConstructProto(r.builtin_Error, "GoError", r.global.GoErrorPrototype, r.global.Error, 1)
  161. r.addToGlobal("GoError", r.global.GoError)
  162. }