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