shithub: libmujs

Download patch

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)
--