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
8static 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
32static 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
58static 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
71static 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
97DERROR(error, Error)
98DERROR(evalerror, EvalError)
99DERROR(rangeerror, RangeError)
100DERROR(referenceerror, ReferenceError)
101DERROR(syntaxerror, SyntaxError)
102DERROR(typeerror, TypeError)
103DERROR(urierror, URIError)
104
105#undef DERROR
106
107void 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