| 1 | #include "jsi.h" | 
|---|
| 2 | #include "jsvalue.h" | 
|---|
| 3 | #include "jsbuiltin.h" | 
|---|
| 4 |  | 
|---|
| 5 | #define QQ(X) #X | 
|---|
| 6 | #define Q(X) QQ(X) | 
|---|
| 7 |  | 
|---|
| 8 | static int jsB_stacktrace(js_State *J, int skip) | 
|---|
| 9 | { | 
|---|
| 10 | char buf[256]; | 
|---|
| 11 | int n = J->tracetop - skip; | 
|---|
| 12 | if (n <= 0) | 
|---|
| 13 | return 0; | 
|---|
| 14 | for (; n > 0; --n) { | 
|---|
| 15 | const char *name = J->trace[n].name; | 
|---|
| 16 | const char *file = J->trace[n].file; | 
|---|
| 17 | int line = J->trace[n].line; | 
|---|
| 18 | if (line > 0) { | 
|---|
| 19 | if (name[0]) | 
|---|
| 20 | snprintf(buf, sizeof buf, "\n\tat %s (%s:%d)", name, file, line); | 
|---|
| 21 | else | 
|---|
| 22 | snprintf(buf, sizeof buf, "\n\tat %s:%d", file, line); | 
|---|
| 23 | } else | 
|---|
| 24 | snprintf(buf, sizeof buf, "\n\tat %s (%s)", name, file); | 
|---|
| 25 | js_pushstring(J, buf); | 
|---|
| 26 | if (n < J->tracetop - skip) | 
|---|
| 27 | js_concat(J); | 
|---|
| 28 | } | 
|---|
| 29 | return 1; | 
|---|
| 30 | } | 
|---|
| 31 |  | 
|---|
| 32 | static void Ep_toString(js_State *J) | 
|---|
| 33 | { | 
|---|
| 34 | const char *name = "Error"; | 
|---|
| 35 | const char *message = ""; | 
|---|
| 36 |  | 
|---|
| 37 | if (!js_isobject(J, -1)) | 
|---|
| 38 | js_typeerror(J, "not an object"); | 
|---|
| 39 |  | 
|---|
| 40 | if (js_hasproperty(J, 0, "name")) | 
|---|
| 41 | name = js_tostring(J, -1); | 
|---|
| 42 | if (js_hasproperty(J, 0, "message")) | 
|---|
| 43 | message = js_tostring(J, -1); | 
|---|
| 44 |  | 
|---|
| 45 | if (name[0] == 0) | 
|---|
| 46 | js_pushstring(J, message); | 
|---|
| 47 | else if (message[0] == 0) | 
|---|
| 48 | js_pushstring(J, name); | 
|---|
| 49 | else { | 
|---|
| 50 | js_pushstring(J, name); | 
|---|
| 51 | js_pushstring(J, ": "); | 
|---|
| 52 | js_concat(J); | 
|---|
| 53 | js_pushstring(J, message); | 
|---|
| 54 | js_concat(J); | 
|---|
| 55 | } | 
|---|
| 56 | } | 
|---|
| 57 |  | 
|---|
| 58 | static int jsB_ErrorX(js_State *J, js_Object *prototype) | 
|---|
| 59 | { | 
|---|
| 60 | int top = js_gettop(J); | 
|---|
| 61 | js_pushobject(J, jsV_newobject(J, JS_CERROR, prototype)); | 
|---|
| 62 | if (top > 1) { | 
|---|
| 63 | js_pushstring(J, js_tostring(J, 1)); | 
|---|
| 64 | js_setproperty(J, -2, "message"); | 
|---|
| 65 | } | 
|---|
| 66 | if (jsB_stacktrace(J, 1)) | 
|---|
| 67 | js_setproperty(J, -2, "stackTrace"); | 
|---|
| 68 | return 1; | 
|---|
| 69 | } | 
|---|
| 70 |  | 
|---|
| 71 | static void js_newerrorx(js_State *J, const char *message, js_Object *prototype) | 
|---|
| 72 | { | 
|---|
| 73 | js_pushobject(J, jsV_newobject(J, JS_CERROR, prototype)); | 
|---|
| 74 | js_pushstring(J, message); | 
|---|
| 75 | js_setproperty(J, -2, "message"); | 
|---|
| 76 | if (jsB_stacktrace(J, 0)) | 
|---|
| 77 | js_setproperty(J, -2, "stackTrace"); | 
|---|
| 78 | } | 
|---|
| 79 |  | 
|---|
| 80 | #define DERROR(name, Name) \ | 
|---|
| 81 | static void jsB_##Name(js_State *J) { \ | 
|---|
| 82 | jsB_ErrorX(J, J->Name##_prototype); \ | 
|---|
| 83 | } \ | 
|---|
| 84 | void js_new##name(js_State *J, const char *s) { \ | 
|---|
| 85 | js_newerrorx(J, s, J->Name##_prototype); \ | 
|---|
| 86 | } \ | 
|---|
| 87 | void js_##name(js_State *J, const char *fmt, ...) { \ | 
|---|
| 88 | va_list ap; \ | 
|---|
| 89 | char buf[256]; \ | 
|---|
| 90 | va_start(ap, fmt); \ | 
|---|
| 91 | vsnprintf(buf, sizeof buf, fmt, ap); \ | 
|---|
| 92 | va_end(ap); \ | 
|---|
| 93 | js_newerrorx(J, buf, J->Name##_prototype); \ | 
|---|
| 94 | js_throw(J); \ | 
|---|
| 95 | } | 
|---|
| 96 |  | 
|---|
| 97 | DERROR(error, Error) | 
|---|
| 98 | DERROR(evalerror, EvalError) | 
|---|
| 99 | DERROR(rangeerror, RangeError) | 
|---|
| 100 | DERROR(referenceerror, ReferenceError) | 
|---|
| 101 | DERROR(syntaxerror, SyntaxError) | 
|---|
| 102 | DERROR(typeerror, TypeError) | 
|---|
| 103 | DERROR(urierror, URIError) | 
|---|
| 104 |  | 
|---|
| 105 | #undef DERROR | 
|---|
| 106 |  | 
|---|
| 107 | void jsB_initerror(js_State *J) | 
|---|
| 108 | { | 
|---|
| 109 | js_pushobject(J, J->Error_prototype); | 
|---|
| 110 | { | 
|---|
| 111 | jsB_props(J, "name", "Error"); | 
|---|
| 112 | jsB_props(J, "message", "an error has occurred"); | 
|---|
| 113 | jsB_propf(J, "Error.prototype.toString", Ep_toString, 0); | 
|---|
| 114 | } | 
|---|
| 115 | js_newcconstructor(J, jsB_Error, jsB_Error, "Error", 1); | 
|---|
| 116 | js_defglobal(J, "Error", JS_DONTENUM); | 
|---|
| 117 |  | 
|---|
| 118 | #define IERROR(NAME) \ | 
|---|
| 119 | js_pushobject(J, J->NAME##_prototype); \ | 
|---|
| 120 | jsB_props(J, "name", Q(NAME)); \ | 
|---|
| 121 | js_newcconstructor(J, jsB_##NAME, jsB_##NAME, Q(NAME), 1); \ | 
|---|
| 122 | js_defglobal(J, Q(NAME), JS_DONTENUM); | 
|---|
| 123 |  | 
|---|
| 124 | IERROR(EvalError); | 
|---|
| 125 | IERROR(RangeError); | 
|---|
| 126 | IERROR(ReferenceError); | 
|---|
| 127 | IERROR(SyntaxError); | 
|---|
| 128 | IERROR(TypeError); | 
|---|
| 129 | IERROR(URIError); | 
|---|
| 130 |  | 
|---|
| 131 | #undef IERROR | 
|---|
| 132 | } | 
|---|
| 133 |  | 
|---|