Clean up error object creation and throwing functions.

This commit is contained in:
Tor Andersson
2014-01-20 18:27:52 +01:00
parent b262cc3673
commit 7c82ec2541
13 changed files with 112 additions and 83 deletions
+15 -3
View File
@@ -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);
+2 -2
View File
@@ -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;
}
+23 -35
View File
@@ -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);
}
+3 -3
View File
@@ -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);
+5 -5
View File
@@ -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;
+2 -2
View File
@@ -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;
}
+18 -17
View File
@@ -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);
+34
View File
@@ -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); }
-8
View File
@@ -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);
+2 -1
View File
@@ -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[] = {
+2 -1
View File
@@ -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, ...)
+2 -2
View File
@@ -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:
+4 -4
View File
@@ -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)