From b257545b6f4799c0a0301ca577a67e24559f0bc9 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Mon, 19 Feb 2024 16:31:17 +0100 Subject: [PATCH] Better output from JS_ToCString() on exception (#274) `ToString(object)` can fail when there is a pending exception. Add a special case for exception objects to help debugging. Getting an empty string when the real error was "InternalError: stack overflow" is rage inducing. Fixes: https://github.com/quickjs-ng/quickjs/issues/273 --- quickjs.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/quickjs.c b/quickjs.c index e6166ee..3feacd9 100644 --- a/quickjs.c +++ b/quickjs.c @@ -3938,16 +3938,36 @@ const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValue val1, BOOL ce JSValue val; JSString *str, *str_new; int pos, len, c, c1; + JSObject *p; uint8_t *q; - if (JS_VALUE_GET_TAG(val1) != JS_TAG_STRING) { - val = JS_ToString(ctx, val1); - if (JS_IsException(val)) - goto fail; - } else { + if (JS_VALUE_GET_TAG(val1) == JS_TAG_STRING) { val = js_dup(val1); + goto go; } + val = JS_ToString(ctx, val1); + if (!JS_IsException(val)) + goto go; + + // Stringification can fail when there is an exception pending, + // e.g. a stack overflow InternalError. Special-case exception + // objects to make debugging easier, look up the .message property + // and stringify that. + if (JS_VALUE_GET_TAG(val1) != JS_TAG_OBJECT) + goto fail; + + p = JS_VALUE_GET_OBJ(val1); + if (p->class_id != JS_CLASS_ERROR) + goto fail; + + val = JS_GetProperty(ctx, val1, JS_ATOM_message); + if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING) { + JS_FreeValue(ctx, val); + goto fail; + } + +go: str = JS_VALUE_GET_STRING(val); len = str->len; if (!str->is_wide_char) {