...

Source file src/github.com/dop251/goja/builtin_error.go

Documentation: github.com/dop251/goja

     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  			// reorder property names to ensure 'stack' is the first one
    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