1 package goja
2
3 import "github.com/dop251/goja/unistring"
4
5 const propNameStack = "stack"
6
7 type errorObject struct {
8 baseObject
9 stack []StackFrame
10 stackPropAdded bool
11 }
12
13 func (e *errorObject) formatStack() String {
14 var b StringBuilder
15 val := writeErrorString(&b, e.val)
16 if val != nil {
17 b.WriteString(val)
18 }
19 b.WriteRune('\n')
20
21 for _, frame := range e.stack {
22 b.writeASCII("\tat ")
23 frame.WriteToValueBuilder(&b)
24 b.WriteRune('\n')
25 }
26 return b.String()
27 }
28
29 func (e *errorObject) addStackProp() Value {
30 if !e.stackPropAdded {
31 res := e._putProp(propNameStack, e.formatStack(), true, false, true)
32 if len(e.propNames) > 1 {
33
34 copy(e.propNames[1:], e.propNames)
35 e.propNames[0] = propNameStack
36 }
37 e.stackPropAdded = true
38 return res
39 }
40 return nil
41 }
42
43 func (e *errorObject) getStr(p unistring.String, receiver Value) Value {
44 return e.getStrWithOwnProp(e.getOwnPropStr(p), p, receiver)
45 }
46
47 func (e *errorObject) getOwnPropStr(name unistring.String) Value {
48 res := e.baseObject.getOwnPropStr(name)
49 if res == nil && name == propNameStack {
50 return e.addStackProp()
51 }
52
53 return res
54 }
55
56 func (e *errorObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
57 if name == propNameStack {
58 e.addStackProp()
59 }
60 return e.baseObject.setOwnStr(name, val, throw)
61 }
62
63 func (e *errorObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
64 return e._setForeignStr(name, e.getOwnPropStr(name), val, receiver, throw)
65 }
66
67 func (e *errorObject) deleteStr(name unistring.String, throw bool) bool {
68 if name == propNameStack {
69 e.addStackProp()
70 }
71 return e.baseObject.deleteStr(name, throw)
72 }
73
74 func (e *errorObject) defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool {
75 if name == propNameStack {
76 e.addStackProp()
77 }
78 return e.baseObject.defineOwnPropertyStr(name, desc, throw)
79 }
80
81 func (e *errorObject) hasOwnPropertyStr(name unistring.String) bool {
82 if e.baseObject.hasOwnPropertyStr(name) {
83 return true
84 }
85
86 return name == propNameStack && !e.stackPropAdded
87 }
88
89 func (e *errorObject) stringKeys(all bool, accum []Value) []Value {
90 if all && !e.stackPropAdded {
91 accum = append(accum, asciiString(propNameStack))
92 }
93 return e.baseObject.stringKeys(all, accum)
94 }
95
96 func (e *errorObject) iterateStringKeys() iterNextFunc {
97 e.addStackProp()
98 return e.baseObject.iterateStringKeys()
99 }
100
101 func (e *errorObject) init() {
102 e.baseObject.init()
103 vm := e.val.runtime.vm
104 e.stack = vm.captureStack(make([]StackFrame, 0, len(vm.callStack)+1), 0)
105 }
106
107 func (r *Runtime) newErrorObject(proto *Object, class string) *errorObject {
108 obj := &Object{runtime: r}
109 o := &errorObject{
110 baseObject: baseObject{
111 class: class,
112 val: obj,
113 extensible: true,
114 prototype: proto,
115 },
116 }
117 obj.self = o
118 o.init()
119 return o
120 }
121
122 func (r *Runtime) builtin_Error(args []Value, proto *Object) *Object {
123 obj := r.newErrorObject(proto, classError)
124 if len(args) > 0 && args[0] != _undefined {
125 obj._putProp("message", args[0], true, false, true)
126 }
127 return obj.val
128 }
129
130 func (r *Runtime) builtin_AggregateError(args []Value, proto *Object) *Object {
131 obj := r.newErrorObject(proto, classError)
132 if len(args) > 1 && args[1] != nil && args[1] != _undefined {
133 obj._putProp("message", args[1].toString(), true, false, true)
134 }
135 var errors []Value
136 if len(args) > 0 {
137 errors = r.iterableToList(args[0], nil)
138 }
139 obj._putProp("errors", r.newArrayValues(errors), true, false, true)
140
141 return obj.val
142 }
143
144 func writeErrorString(sb *StringBuilder, obj *Object) String {
145 var nameStr, msgStr String
146 name := obj.self.getStr("name", nil)
147 if name == nil || name == _undefined {
148 nameStr = asciiString("Error")
149 } else {
150 nameStr = name.toString()
151 }
152 msg := obj.self.getStr("message", nil)
153 if msg == nil || msg == _undefined {
154 msgStr = stringEmpty
155 } else {
156 msgStr = msg.toString()
157 }
158 if nameStr.Length() == 0 {
159 return msgStr
160 }
161 if msgStr.Length() == 0 {
162 return nameStr
163 }
164 sb.WriteString(nameStr)
165 sb.WriteString(asciiString(": "))
166 sb.WriteString(msgStr)
167 return nil
168 }
169
170 func (r *Runtime) error_toString(call FunctionCall) Value {
171 var sb StringBuilder
172 val := writeErrorString(&sb, r.toObject(call.This))
173 if val != nil {
174 return val
175 }
176 return sb.String()
177 }
178
179 func (r *Runtime) createErrorPrototype(name String, ctor *Object) *Object {
180 o := r.newBaseObject(r.getErrorPrototype(), classObject)
181 o._putProp("message", stringEmpty, true, false, true)
182 o._putProp("name", name, true, false, true)
183 o._putProp("constructor", ctor, true, false, true)
184 return o.val
185 }
186
187 func (r *Runtime) getErrorPrototype() *Object {
188 ret := r.global.ErrorPrototype
189 if ret == nil {
190 ret = r.NewObject()
191 r.global.ErrorPrototype = ret
192 o := ret.self
193 o._putProp("message", stringEmpty, true, false, true)
194 o._putProp("name", stringError, true, false, true)
195 o._putProp("toString", r.newNativeFunc(r.error_toString, "toString", 0), true, false, true)
196 o._putProp("constructor", r.getError(), true, false, true)
197 }
198 return ret
199 }
200
201 func (r *Runtime) getError() *Object {
202 ret := r.global.Error
203 if ret == nil {
204 ret = &Object{runtime: r}
205 r.global.Error = ret
206 r.newNativeFuncConstruct(ret, r.builtin_Error, "Error", r.getErrorPrototype(), 1)
207 }
208 return ret
209 }
210
211 func (r *Runtime) getAggregateError() *Object {
212 ret := r.global.AggregateError
213 if ret == nil {
214 ret = &Object{runtime: r}
215 r.global.AggregateError = ret
216 r.newNativeFuncConstructProto(ret, r.builtin_AggregateError, "AggregateError", r.createErrorPrototype(stringAggregateError, ret), r.getError(), 2)
217 }
218 return ret
219 }
220
221 func (r *Runtime) getTypeError() *Object {
222 ret := r.global.TypeError
223 if ret == nil {
224 ret = &Object{runtime: r}
225 r.global.TypeError = ret
226 r.newNativeFuncConstructProto(ret, r.builtin_Error, "TypeError", r.createErrorPrototype(stringTypeError, ret), r.getError(), 1)
227 }
228 return ret
229 }
230
231 func (r *Runtime) getReferenceError() *Object {
232 ret := r.global.ReferenceError
233 if ret == nil {
234 ret = &Object{runtime: r}
235 r.global.ReferenceError = ret
236 r.newNativeFuncConstructProto(ret, r.builtin_Error, "ReferenceError", r.createErrorPrototype(stringReferenceError, ret), r.getError(), 1)
237 }
238 return ret
239 }
240
241 func (r *Runtime) getSyntaxError() *Object {
242 ret := r.global.SyntaxError
243 if ret == nil {
244 ret = &Object{runtime: r}
245 r.global.SyntaxError = ret
246 r.newNativeFuncConstructProto(ret, r.builtin_Error, "SyntaxError", r.createErrorPrototype(stringSyntaxError, ret), r.getError(), 1)
247 }
248 return ret
249 }
250
251 func (r *Runtime) getRangeError() *Object {
252 ret := r.global.RangeError
253 if ret == nil {
254 ret = &Object{runtime: r}
255 r.global.RangeError = ret
256 r.newNativeFuncConstructProto(ret, r.builtin_Error, "RangeError", r.createErrorPrototype(stringRangeError, ret), r.getError(), 1)
257 }
258 return ret
259 }
260
261 func (r *Runtime) getEvalError() *Object {
262 ret := r.global.EvalError
263 if ret == nil {
264 ret = &Object{runtime: r}
265 r.global.EvalError = ret
266 r.newNativeFuncConstructProto(ret, r.builtin_Error, "EvalError", r.createErrorPrototype(stringEvalError, ret), r.getError(), 1)
267 }
268 return ret
269 }
270
271 func (r *Runtime) getURIError() *Object {
272 ret := r.global.URIError
273 if ret == nil {
274 ret = &Object{runtime: r}
275 r.global.URIError = ret
276 r.newNativeFuncConstructProto(ret, r.builtin_Error, "URIError", r.createErrorPrototype(stringURIError, ret), r.getError(), 1)
277 }
278 return ret
279 }
280
281 func (r *Runtime) getGoError() *Object {
282 ret := r.global.GoError
283 if ret == nil {
284 ret = &Object{runtime: r}
285 r.global.GoError = ret
286 r.newNativeFuncConstructProto(ret, r.builtin_Error, "GoError", r.createErrorPrototype(stringGoError, ret), r.getError(), 1)
287 }
288 return ret
289 }
290
View as plain text