From 7c82ec25411d61a9cd70688f729c4b2f3e346e57 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Mon, 20 Jan 2014 18:27:52 +0100 Subject: [PATCH] Clean up error object creation and throwing functions. --- js.h | 18 +++++++++++++--- jsbboolean.c | 4 ++-- jsberror.c | 58 ++++++++++++++++++++------------------------------- jsbfunction.c | 6 +++--- jsbnumber.c | 10 ++++----- jsbstring.c | 4 ++-- jscompile.c | 35 ++++++++++++++++--------------- jserror.c | 34 ++++++++++++++++++++++++++++++ jsi.h | 8 ------- jslex.c | 3 ++- jsparse.c | 3 ++- jsrun.c | 4 ++-- jsvalue.c | 8 +++---- 13 files changed, 112 insertions(+), 83 deletions(-) create mode 100644 jserror.c diff --git a/js.h b/js.h index 533d040..39a8692 100644 --- a/js.h +++ b/js.h @@ -18,9 +18,6 @@ void js_gc(js_State *J, int report); 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 @@ enum { 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); diff --git a/jsbboolean.c b/jsbboolean.c index 5f40836..9731fb5 100644 --- a/jsbboolean.c +++ b/jsbboolean.c @@ -17,7 +17,7 @@ static int jsB_Boolean(js_State *J, int n) 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_toString(js_State *J, int n) 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; } diff --git a/jsberror.c b/jsberror.c index 4240348..29517b2 100644 --- 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 @@ static int Ep_toString(js_State *J, int n) 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 @@ static int Ep_toString(js_State *J, int n) } \ 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 @@ DECL(URIError); 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); } diff --git a/jsbfunction.c b/jsbfunction.c index 13dff7d..0a5e086 100644 --- a/jsbfunction.c +++ b/jsbfunction.c @@ -19,7 +19,7 @@ static int Fp_toString(js_State *J, int nargs) 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 @@ static int Fp_apply(js_State *J, int n) 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 @@ static int Fp_call(js_State *J, int n) 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); diff --git a/jsbnumber.c b/jsbnumber.c index dae559a..ac4469d 100644 --- a/jsbnumber.c +++ b/jsbnumber.c @@ -17,7 +17,7 @@ static int jsB_Number(js_State *J, int n) 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_valueOf(js_State *J, int n) 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 @@ static int Np_toFixed(js_State *J, int n) 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 @@ static int Np_toExponential(js_State *J, int n) 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 @@ static int Np_toPrecision(js_State *J, int n) 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; diff --git a/jsbstring.c b/jsbstring.c index cdde68d..041aa12 100644 --- a/jsbstring.c +++ b/jsbstring.c @@ -18,7 +18,7 @@ static int jsB_String(js_State *J, int n) 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_toString(js_State *J, int n) 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; } diff --git a/jscompile.c b/jscompile.c index a74f076..33f7b11 100644 --- 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); @@ -738,22 +755,6 @@ static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body) 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) { return newfun(J, NULL, NULL, prog); diff --git a/jserror.c b/jserror.c new file mode 100644 index 0000000..00daa9c --- /dev/null +++ b/jserror.c @@ -0,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); } diff --git a/jsi.h b/jsi.h index 1803b95..67799c2 100644 --- a/jsi.h +++ b/jsi.h @@ -27,14 +27,6 @@ typedef struct js_StringNode js_StringNode; 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); diff --git a/jslex.c b/jslex.c index daa0579..1be497d 100644 --- a/jslex.c +++ b/jslex.c @@ -19,7 +19,8 @@ static int jsY_error(js_State *J, const char *fmt, ...) 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[] = { diff --git a/jsparse.c b/jsparse.c index 4f3e59b..f65d367 100644 --- a/jsparse.c +++ b/jsparse.c @@ -40,7 +40,8 @@ static void jsP_error(js_State *J, const char *fmt, ...) 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, ...) diff --git a/jsrun.c b/jsrun.c index a97bfe3..d26b867 100644 --- a/jsrun.c +++ b/jsrun.c @@ -412,7 +412,7 @@ void js_call(js_State *J, int n) 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 @@ static void jsR_run(js_State *J, js_Function *F) if (ref) js_pushvalue(J, ref->value); else - jsR_throwReferenceError(J, str); + js_referenceerror(J, "%s", str); break; case OP_SETVAR: diff --git a/jsvalue.c b/jsvalue.c index 0544b0b..1f0380f 100644 --- a/jsvalue.c +++ b/jsvalue.c @@ -64,7 +64,7 @@ js_Value jsV_toprimitive(js_State *J, const js_Value *v, int preferred) 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 @@ static js_Object *jsV_newstring(js_State *J, const char *v) 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)