diff --git a/api-test.c b/api-test.c index 6ae8f6f47..950b4156c 100644 --- a/api-test.c +++ b/api-test.c @@ -5,6 +5,7 @@ #include #include #include "quickjs.h" +#include "cutils.h" #define MAX_TIME 10 @@ -506,6 +507,44 @@ static void dump_memory_usage(void) JS_FreeRuntime(rt); } +static void new_errors(void) +{ + typedef struct { + const char name[16]; + JSValue (*func)(JSContext *, const char *, ...); + } Entry; + static const Entry entries[] = { + {"Error", JS_NewPlainError}, + {"InternalError", JS_NewInternalError}, + {"RangeError", JS_NewRangeError}, + {"ReferenceError", JS_NewReferenceError}, + {"SyntaxError", JS_NewSyntaxError}, + {"TypeError", JS_NewTypeError}, + }; + const Entry *e; + + JSRuntime *rt = JS_NewRuntime(); + JSContext *ctx = JS_NewContext(rt); + for (e = entries; e < endof(entries); e++) { + JSValue obj = (*e->func)(ctx, "the %s", "needle"); + assert(!JS_IsException(obj)); + assert(JS_IsObject(obj)); + assert(JS_IsError(ctx, obj)); + const char *haystack = JS_ToCString(ctx, obj); + char needle[256]; + snprintf(needle, sizeof(needle), "%s: the needle", e->name); + assert(strstr(haystack, needle)); + JS_FreeCString(ctx, haystack); + JSValue stack = JS_GetPropertyStr(ctx, obj, "stack"); + assert(!JS_IsException(stack)); + assert(JS_IsString(stack)); + JS_FreeValue(ctx, stack); + JS_FreeValue(ctx, obj); + } + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + int main(void) { sync_call(); @@ -518,5 +557,6 @@ int main(void) weak_map_gc_check(); promise_hook(); dump_memory_usage(); + new_errors(); return 0; } diff --git a/quickjs.c b/quickjs.c index fb42ff8da..0b8cefeed 100644 --- a/quickjs.c +++ b/quickjs.c @@ -6947,8 +6947,8 @@ JSValue JS_NewError(JSContext *ctx) return obj; } -static JSValue JS_MakeError(JSContext *ctx, JSErrorEnum error_num, - const char *message, bool add_backtrace) +static JSValue JS_MakeError2(JSContext *ctx, JSErrorEnum error_num, + bool add_backtrace, const char *message) { JSValue obj, msg; @@ -6972,16 +6972,24 @@ static JSValue JS_MakeError(JSContext *ctx, JSErrorEnum error_num, return obj; } -/* fmt and arguments may be pure ASCII or UTF-8 encoded contents */ static JSValue JS_PRINTF_FORMAT_ATTR(4, 0) -JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num, - bool add_backtrace, JS_PRINTF_FORMAT const char *fmt, va_list ap) +JS_MakeError(JSContext *ctx, JSErrorEnum error_num, bool add_backtrace, + JS_PRINTF_FORMAT const char *fmt, va_list ap) { char buf[256]; - JSValue obj; vsnprintf(buf, sizeof(buf), fmt, ap); - obj = JS_MakeError(ctx, error_num, buf, add_backtrace); + return JS_MakeError2(ctx, error_num, add_backtrace, buf); +} + +/* fmt and arguments may be pure ASCII or UTF-8 encoded contents */ +static JSValue JS_PRINTF_FORMAT_ATTR(4, 0) +JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num, bool add_backtrace, + JS_PRINTF_FORMAT const char *fmt, va_list ap) +{ + JSValue obj; + + obj = JS_MakeError(ctx, error_num, add_backtrace, fmt, ap); if (unlikely(JS_IsException(obj))) { /* out of memory: throw JS_NULL to avoid recursing */ obj = JS_NULL; @@ -7004,38 +7012,45 @@ JS_ThrowError(JSContext *ctx, JSErrorEnum error_num, return JS_ThrowError2(ctx, error_num, add_backtrace, fmt, ap); } -JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowPlainError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...) -{ - JSValue val; - va_list ap; - - va_start(ap, fmt); - val = JS_ThrowError(ctx, JS_PLAIN_ERROR, fmt, ap); - va_end(ap); - return val; -} - -JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowSyntaxError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...) -{ - JSValue val; - va_list ap; - - va_start(ap, fmt); - val = JS_ThrowError(ctx, JS_SYNTAX_ERROR, fmt, ap); - va_end(ap); - return val; -} - -JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowTypeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...) -{ - JSValue val; - va_list ap; - - va_start(ap, fmt); - val = JS_ThrowError(ctx, JS_TYPE_ERROR, fmt, ap); - va_end(ap); - return val; -} +#define JS_ERROR_MAP(X) \ + X(Internal, INTERNAL) \ + X(Plain, PLAIN) \ + X(Range, RANGE) \ + X(Reference, REFERENCE) \ + X(Syntax, SYNTAX) \ + X(Type, TYPE) \ + +#define X(lc, uc) \ + JSValue JS_PRINTF_FORMAT_ATTR(2, 3) \ + JS_New##lc##Error(JSContext *ctx, \ + JS_PRINTF_FORMAT const char *fmt, ...) \ + { \ + JSValue val; \ + va_list ap; \ + \ + va_start(ap, fmt); \ + val = JS_MakeError(ctx, JS_##uc##_ERROR, \ + /*add_backtrace*/true, fmt, ap); \ + va_end(ap); \ + return val; \ + } \ + JSValue JS_PRINTF_FORMAT_ATTR(2, 3) \ + JS_Throw##lc##Error(JSContext *ctx, \ + JS_PRINTF_FORMAT const char *fmt, ...) \ + { \ + JSValue val; \ + va_list ap; \ + \ + va_start(ap, fmt); \ + val = JS_ThrowError(ctx, JS_##uc##_ERROR, fmt, ap); \ + va_end(ap); \ + return val; \ + } \ + +JS_ERROR_MAP(X) + +#undef X +#undef JS_ERROR_MAP static int JS_PRINTF_FORMAT_ATTR(3, 4) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, JS_PRINTF_FORMAT const char *fmt, ...) { @@ -7084,39 +7099,6 @@ static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom) } } -JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowReferenceError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...) -{ - JSValue val; - va_list ap; - - va_start(ap, fmt); - val = JS_ThrowError(ctx, JS_REFERENCE_ERROR, fmt, ap); - va_end(ap); - return val; -} - -JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowRangeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...) -{ - JSValue val; - va_list ap; - - va_start(ap, fmt); - val = JS_ThrowError(ctx, JS_RANGE_ERROR, fmt, ap); - va_end(ap); - return val; -} - -JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowInternalError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...) -{ - JSValue val; - va_list ap; - - va_start(ap, fmt); - val = JS_ThrowError(ctx, JS_INTERNAL_ERROR, fmt, ap); - va_end(ap); - return val; -} - JSValue JS_ThrowOutOfMemory(JSContext *ctx) { JSRuntime *rt = ctx->rt; @@ -51457,8 +51439,8 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi err = JS_GetException(ctx); is_reject = 1; } else { - err = JS_MakeError(ctx, JS_TYPE_ERROR, "throw is not a method", - true); + err = JS_MakeError2(ctx, JS_TYPE_ERROR, /*add_backtrace*/true, + "throw is not a method"); is_reject = 1; } goto done_resolve; diff --git a/quickjs.h b/quickjs.h index d8d161944..a20360532 100644 --- a/quickjs.h +++ b/quickjs.h @@ -756,12 +756,18 @@ JS_EXTERN void JS_ClearUncatchableError(JSContext *ctx, JSValueConst val); // JS_Throw(ctx, exc); JS_EXTERN void JS_ResetUncatchableError(JSContext *ctx); JS_EXTERN JSValue JS_NewError(JSContext *ctx); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_NewInternalError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_NewPlainError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_NewRangeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_NewReferenceError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_NewSyntaxError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_NewTypeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowInternalError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowPlainError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowRangeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowReferenceError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowSyntaxError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowTypeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowReferenceError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowRangeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowInternalError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); JS_EXTERN JSValue JS_ThrowOutOfMemory(JSContext *ctx); JS_EXTERN void JS_FreeValue(JSContext *ctx, JSValue v); JS_EXTERN void JS_FreeValueRT(JSRuntime *rt, JSValue v);