ref: 7c82ec25411d61a9cd70688f729c4b2f3e346e57
parent: b262cc3673965e53ed73606668dedd3acb045881
author: Tor Andersson <tor@ccxvii.net>
date: Mon Jan 20 13:27:52 EST 2014
Clean up error object creation and throwing functions.
--- a/js.h
+++ b/js.h
@@ -18,9 +18,6 @@
const char *js_intern(js_State *J, const char *s);
-/* Push a new Error object with the formatted message and throw it */
-JS_NORETURN void js_error(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
-
/* Property attribute flags */
enum {
JS_READONLY = 1,
@@ -28,6 +25,21 @@
JS_DONTDELETE = 4,
};
+void js_newerror(js_State *J, const char *message);
+void js_newevalerror(js_State *J, const char *message);
+void js_newrangeerror(js_State *J, const char *message);
+void js_newreferenceerror(js_State *J, const char *message);
+void js_newsyntaxerror(js_State *J, const char *message);
+void js_newtypeerror(js_State *J, const char *message);
+void js_newurierror(js_State *J, const char *message);
+
+JS_NORETURN void js_error(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
+JS_NORETURN void js_evalerror(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
+JS_NORETURN void js_rangeerror(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
+JS_NORETURN void js_referenceerror(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
+JS_NORETURN void js_syntaxerror(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
+JS_NORETURN void js_typeerror(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
+JS_NORETURN void js_urierror(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
JS_NORETURN void js_throw(js_State *J);
void js_loadstring(js_State *J, const char *filename, const char *source);
--- a/jsbboolean.c
+++ b/jsbboolean.c
@@ -17,7 +17,7 @@
static int Bp_toString(js_State *J, int n)
{
js_Object *self = js_toobject(J, 0);
- if (self->type != JS_CBOOLEAN) jsR_throwTypeError(J, "not a boolean");
+ if (self->type != JS_CBOOLEAN) js_typeerror(J, "not a boolean");
js_pushliteral(J, self->u.boolean ? "true" : "false");
return 1;
}
@@ -25,7 +25,7 @@
static int Bp_valueOf(js_State *J, int n)
{
js_Object *self = js_toobject(J, 0);
- if (self->type != JS_CBOOLEAN) jsR_throwTypeError(J, "not a boolean");
+ if (self->type != JS_CBOOLEAN) js_typeerror(J, "not a boolean");
js_pushboolean(J, self->u.boolean);
return 1;
}
--- a/jsberror.c
+++ b/jsberror.c
@@ -2,6 +2,9 @@
#include "jsvalue.h"
#include "jsbuiltin.h"
+#define QQ(X) #X
+#define Q(X) QQ(X)
+
static int Ep_toString(js_State *J, int n)
{
js_getproperty(J, 0, "name");
@@ -12,9 +15,6 @@
return 1;
}
-#define STRSTR(X) #X
-#define STR(X) STRSTR(X)
-
#define DECL(NAME) \
static int jsB_new_##NAME(js_State *J, int n) { \
js_pushobject(J, jsV_newobject(J, JS_CERROR, J->NAME##_prototype)); \
@@ -32,22 +32,6 @@
} \
return 1; \
} \
- static void jsB_init##NAME(js_State *J) { \
- js_pushobject(J, J->NAME##_prototype); \
- { \
- jsB_props(J, "name", STR(NAME)); \
- jsB_props(J, "message", "an error has occurred"); \
- jsB_propf(J, "toString", Ep_toString, 0); \
- } \
- js_newcconstructor(J, jsB_##NAME, jsB_new_##NAME); \
- js_setglobal(J, STR(NAME)); \
- } \
- void jsR_throw##NAME(js_State *J, const char *message) { \
- js_pushobject(J, jsV_newobject(J, JS_CERROR, J->NAME##_prototype)); \
- js_pushstring(J, message); \
- js_setproperty(J, -2, "message"); \
- js_throw(J); \
- } \
DECL(Error);
DECL(EvalError);
@@ -59,21 +43,25 @@
void jsB_initerror(js_State *J)
{
- jsB_initError(J);
- jsB_initEvalError(J);
- jsB_initRangeError(J);
- jsB_initReferenceError(J);
- jsB_initSyntaxError(J);
- jsB_initTypeError(J);
- jsB_initURIError(J);
-}
+ js_pushobject(J, J->Error_prototype);
+ {
+ jsB_props(J, "name", "Error");
+ jsB_props(J, "message", "an error has occurred");
+ jsB_propf(J, "toString", Ep_toString, 0);
+ }
+ js_newcconstructor(J, jsB_Error, jsB_new_Error);
+ js_setglobal(J, "Error");
-void js_error(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);
- jsR_throwError(J, buf);
+ #define INIT(NAME) \
+ js_pushobject(J, J->NAME##_prototype); \
+ jsB_props(J, "name", Q(NAME)); \
+ js_newcconstructor(J, jsB_##NAME, jsB_new_##NAME); \
+ js_setglobal(J, Q(NAME));
+
+ INIT(EvalError);
+ INIT(RangeError);
+ INIT(ReferenceError);
+ INIT(SyntaxError);
+ INIT(TypeError);
+ INIT(URIError);
}
--- a/jsbfunction.c
+++ b/jsbfunction.c
@@ -19,7 +19,7 @@
int i, n;
if (!js_iscallable(J, 0))
- jsR_throwTypeError(J, "not a function");
+ js_typeerror(J, "not a function");
if (self->type == JS_CFUNCTION || self->type == JS_CSCRIPT) {
js_Function *F = self->u.f.function;
@@ -51,7 +51,7 @@
char name[20];
if (!js_iscallable(J, 0))
- jsR_throwTypeError(J, "not a function");
+ js_typeerror(J, "not a function");
js_copy(J, 0);
js_copy(J, 1);
@@ -74,7 +74,7 @@
int i;
if (!js_iscallable(J, 0))
- jsR_throwTypeError(J, "not a function");
+ js_typeerror(J, "not a function");
js_copy(J, 0);
js_copy(J, 1);
--- a/jsbnumber.c
+++ b/jsbnumber.c
@@ -17,7 +17,7 @@
static int Np_valueOf(js_State *J, int n)
{
js_Object *self = js_toobject(J, 0);
- if (self->type != JS_CNUMBER) jsR_throwTypeError(J, "not a number");
+ if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
js_pushnumber(J, self->u.number);
return 1;
}
@@ -25,7 +25,7 @@
static int Np_toString(js_State *J, int n)
{
js_Object *self = js_toobject(J, 0);
- if (self->type != JS_CNUMBER) jsR_throwTypeError(J, "not a number");
+ if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
js_pushliteral(J, jsV_numbertostring(J, self->u.number));
return 1;
}
@@ -35,7 +35,7 @@
char buf[40];
js_Object *self = js_toobject(J, 0);
int width = js_tonumber(J, 1);
- if (self->type != JS_CNUMBER) jsR_throwTypeError(J, "not a number");
+ if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
sprintf(buf, "%.*f", width, self->u.number);
js_pushstring(J, buf);
return 1;
@@ -46,7 +46,7 @@
char buf[40];
js_Object *self = js_toobject(J, 0);
int width = js_tonumber(J, 1);
- if (self->type != JS_CNUMBER) jsR_throwTypeError(J, "not a number");
+ if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
sprintf(buf, "%.*e", width, self->u.number);
js_pushstring(J, buf);
return 1;
@@ -57,7 +57,7 @@
char buf[40];
js_Object *self = js_toobject(J, 0);
int width = js_tonumber(J, 1);
- if (self->type != JS_CNUMBER) jsR_throwTypeError(J, "not a number");
+ if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
sprintf(buf, "%.*g", width, self->u.number);
js_pushstring(J, buf);
return 1;
--- a/jsbstring.c
+++ b/jsbstring.c
@@ -18,7 +18,7 @@
static int Sp_toString(js_State *J, int n)
{
js_Object *self = js_toobject(J, 0);
- if (self->type != JS_CSTRING) jsR_throwTypeError(J, "not a string");
+ if (self->type != JS_CSTRING) js_typeerror(J, "not a string");
js_pushliteral(J, self->u.string);
return 1;
}
@@ -26,7 +26,7 @@
static int Sp_valueOf(js_State *J, int n)
{
js_Object *self = js_toobject(J, 0);
- if (self->type != JS_CSTRING) jsR_throwTypeError(J, "not a string");
+ if (self->type != JS_CSTRING) js_typeerror(J, "not a string");
js_pushliteral(J, self->u.string);
return 1;
}
--- a/jscompile.c
+++ b/jscompile.c
@@ -6,12 +6,29 @@
#define JF js_State *J, js_Function *F
-JS_NORETURN int jsC_error(js_State *J, js_Ast *node, const char *fmt, ...);
+JS_NORETURN int jsC_error(js_State *J, js_Ast *node, const char *fmt, ...) JS_PRINTFLIKE(3,4);
static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body);
static void cexp(JF, js_Ast *exp);
static void cstmlist(JF, js_Ast *list);
+int jsC_error(js_State *J, js_Ast *node, const char *fmt, ...)
+{
+ va_list ap;
+ char buf[512];
+ char msgbuf[256];
+
+ va_start(ap, fmt);
+ vsnprintf(msgbuf, 256, fmt, ap);
+ va_end(ap);
+
+ snprintf(buf, 256, "%s:%d: ", J->filename, node->line);
+ strcat(buf, msgbuf);
+
+ js_newsyntaxerror(J, buf);
+ js_throw(J);
+}
+
static js_Function *newfun(js_State *J, js_Ast *name, js_Ast *params, js_Ast *body)
{
js_Function *F = malloc(sizeof *F);
@@ -736,22 +753,6 @@
emit(J, F, OP_UNDEF);
emit(J, F, OP_RETURN);
-}
-
-int jsC_error(js_State *J, js_Ast *node, const char *fmt, ...)
-{
- va_list ap;
- char buf[512];
- char msgbuf[256];
-
- va_start(ap, fmt);
- vsnprintf(msgbuf, 256, fmt, ap);
- va_end(ap);
-
- snprintf(buf, 256, "%s:%d: ", J->filename, node->line);
- strcat(buf, msgbuf);
-
- jsR_throwSyntaxError(J, buf);
}
js_Function *jsC_compile(js_State *J, js_Ast *prog)
--- /dev/null
+++ b/jserror.c
@@ -1,0 +1,34 @@
+#include "jsi.h"
+#include "jsvalue.h"
+
+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");
+}
+
+void js_newerror(js_State *J, const char *s) { js_newerrorx(J, s, J->Error_prototype); }
+void js_newevalerror(js_State *J, const char *s) { js_newerrorx(J, s, J->EvalError_prototype); }
+void js_newrangeerror(js_State *J, const char *s) { js_newerrorx(J, s, J->RangeError_prototype); }
+void js_newreferenceerror(js_State *J, const char *s) { js_newerrorx(J, s, J->ReferenceError_prototype); }
+void js_newsyntaxerror(js_State *J, const char *s) { js_newerrorx(J, s, J->SyntaxError_prototype); }
+void js_newtypeerror(js_State *J, const char *s) { js_newerrorx(J, s, J->TypeError_prototype); }
+void js_newurierror(js_State *J, const char *s) { js_newerrorx(J, s, J->URIError_prototype); }
+
+#define ERR(NAME) \
+ 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)
+
+void js_error(js_State *J, const char *fmt, ...) { ERR(Error); }
+void js_evalerror(js_State *J, const char *fmt, ...) { ERR(EvalError); }
+void js_rangeerror(js_State *J, const char *fmt, ...) { ERR(RangeError); }
+void js_referenceerror(js_State *J, const char *fmt, ...) { ERR(ReferenceError); }
+void js_syntaxerror(js_State *J, const char *fmt, ...) { ERR(SyntaxError); }
+void js_typeerror(js_State *J, const char *fmt, ...) { ERR(TypeError); }
+void js_urierror(js_State *J, const char *fmt, ...) { ERR(URIError); }
--- a/jsi.h
+++ b/jsi.h
@@ -27,14 +27,6 @@
void jsS_dumpstrings(js_State *J);
void jsS_freestrings(js_State *J);
-JS_NORETURN void jsR_throwError(js_State *J, const char *message);
-JS_NORETURN void jsR_throwEvalError(js_State *J, const char *message);
-JS_NORETURN void jsR_throwRangeError(js_State *J, const char *message);
-JS_NORETURN void jsR_throwReferenceError(js_State *J, const char *message);
-JS_NORETURN void jsR_throwSyntaxError(js_State *J, const char *message);
-JS_NORETURN void jsR_throwTypeError(js_State *J, const char *message);
-JS_NORETURN void jsR_throwURIError(js_State *J, const char *message);
-
void js_newfunction(js_State *J, js_Function *function, js_Environment *scope);
void js_newscript(js_State *J, js_Function *function);
--- a/jslex.c
+++ b/jslex.c
@@ -19,7 +19,8 @@
snprintf(buf, 256, "%s:%d: ", J->filename, J->lexline);
strcat(buf, msgbuf);
- jsR_throwSyntaxError(J, buf);
+ js_newsyntaxerror(J, buf);
+ js_throw(J);
}
static const char *tokenstring[] = {
--- a/jsparse.c
+++ b/jsparse.c
@@ -40,7 +40,8 @@
snprintf(buf, 256, "%s:%d: ", J->filename, J->lexline);
strcat(buf, msgbuf);
- jsR_throwSyntaxError(J, buf);
+ js_newsyntaxerror(J, buf);
+ js_throw(J);
}
static void jsP_warning(js_State *J, const char *fmt, ...)
--- a/jsrun.c
+++ b/jsrun.c
@@ -412,7 +412,7 @@
else if (obj->type == JS_CCFUNCTION)
jsR_callcfunction(J, n, obj->u.c.function);
else
- jsR_throwTypeError(J, "not a function");
+ js_typeerror(J, "not a function");
BOT = savebot;
}
@@ -571,7 +571,7 @@
if (ref)
js_pushvalue(J, ref->value);
else
- jsR_throwReferenceError(J, str);
+ js_referenceerror(J, "%s", str);
break;
case OP_SETVAR:
--- a/jsvalue.c
+++ b/jsvalue.c
@@ -64,7 +64,7 @@
return vv;
}
}
- jsR_throwTypeError(J, "cannot convert object to primitive");
+ js_typeerror(J, "cannot convert object to primitive");
}
/* ToBoolean() on a value */
@@ -169,14 +169,14 @@
js_Object *jsV_toobject(js_State *J, const js_Value *v)
{
switch (v->type) {
- case JS_TUNDEFINED: jsR_throwTypeError(J, "cannot convert undefined to object");
- case JS_TNULL: jsR_throwTypeError(J, "cannot convert null to object");
+ case JS_TUNDEFINED: js_typeerror(J, "cannot convert undefined to object");
+ case JS_TNULL: js_typeerror(J, "cannot convert null to object");
case JS_TBOOLEAN: return jsV_newboolean(J, v->u.boolean);
case JS_TNUMBER: return jsV_newnumber(J, v->u.number);
case JS_TSTRING: return jsV_newstring(J, v->u.string);
case JS_TOBJECT: return v->u.object;
}
- jsR_throwTypeError(J, "cannot convert value to object");
+ js_typeerror(J, "cannot convert value to object");
}
void js_newobject(js_State *J)
--
⑨