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