]> git.kaiwu.me - quickjs.git/commitdiff
More informative "not a constructor" error message (initial patch by bnoordhuis)...
authorFabrice Bellard <fabrice@bellard.org>
Mon, 3 Nov 2025 17:52:39 +0000 (18:52 +0100)
committerFabrice Bellard <fabrice@bellard.org>
Mon, 3 Nov 2025 17:53:32 +0000 (18:53 +0100)
quickjs.c
tests/test_language.js

index fcc73683fa9f27105cb4003e8f83f62854b9c1e8..66880f1969892450693dfa2f723d283cab822255 100644 (file)
--- a/quickjs.c
+++ b/quickjs.c
@@ -7326,6 +7326,22 @@ static JSValue JS_ThrowTypeErrorNotAnObject(JSContext *ctx)
     return JS_ThrowTypeError(ctx, "not an object");
 }
 
+static JSValue JS_ThrowTypeErrorNotAConstructor(JSContext *ctx,
+                                                JSValueConst func_obj)
+{
+    const char *name;
+    if (!JS_IsFunction(ctx, func_obj))
+        goto fail;
+    name = get_prop_string(ctx, func_obj, JS_ATOM_name);
+    if (!name) {
+    fail:
+        return JS_ThrowTypeError(ctx, "not a constructor");
+    }
+    JS_ThrowTypeError(ctx, "%s is not a constructor", name);
+    JS_FreeCString(ctx, name);
+    return JS_EXCEPTION;
+}
+
 static JSValue JS_ThrowTypeErrorNotASymbol(JSContext *ctx)
 {
     return JS_ThrowTypeError(ctx, "not a symbol");
@@ -20086,7 +20102,7 @@ static JSValue JS_CallConstructorInternal(JSContext *ctx,
         goto not_a_function;
     p = JS_VALUE_GET_OBJ(func_obj);
     if (unlikely(!p->is_constructor))
-        return JS_ThrowTypeError(ctx, "not a constructor");
+        return JS_ThrowTypeErrorNotAConstructor(ctx, func_obj);
     if (unlikely(p->class_id != JS_CLASS_BYTECODE_FUNCTION)) {
         JSClassCall *call_func;
         call_func = ctx->rt->class_array[p->class_id].call;
@@ -39947,8 +39963,9 @@ static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj,
     if (JS_IsUndefined(species) || JS_IsNull(species))
         return JS_DupValue(ctx, defaultConstructor);
     if (!JS_IsConstructor(ctx, species)) {
+        JS_ThrowTypeErrorNotAConstructor(ctx, species);
         JS_FreeValue(ctx, species);
-        return JS_ThrowTypeError(ctx, "not a constructor");
+        return JS_EXCEPTION;
     }
     return species;
 }
@@ -48791,7 +48808,7 @@ static JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val,
     if (argc > 2) {
         new_target = argv[2];
         if (!JS_IsConstructor(ctx, new_target))
-            return JS_ThrowTypeError(ctx, "not a constructor");
+            return JS_ThrowTypeErrorNotAConstructor(ctx, new_target);
     } else {
         new_target = func;
     }
@@ -49710,7 +49727,7 @@ static JSValue js_proxy_call_constructor(JSContext *ctx, JSValueConst func_obj,
     if (!s)
         return JS_EXCEPTION;
     if (!JS_IsConstructor(ctx, s->target))
-        return JS_ThrowTypeError(ctx, "not a constructor");
+        return JS_ThrowTypeErrorNotAConstructor(ctx, s->target);
     if (JS_IsUndefined(method))
         return JS_CallConstructor2(ctx, s->target, new_target, argc, argv);
     arg_array = js_create_array(ctx, argc, argv);
@@ -49936,7 +49953,7 @@ static JSValue js_symbol_constructor(JSContext *ctx, JSValueConst new_target,
     JSString *p;
 
     if (!JS_IsUndefined(new_target))
-        return JS_ThrowTypeError(ctx, "not a constructor");
+        return JS_ThrowTypeErrorNotAConstructor(ctx, new_target);
     if (argc == 0 || JS_IsUndefined(argv[0])) {
         p = NULL;
     } else {
@@ -54598,7 +54615,7 @@ static JSValue js_bigint_constructor(JSContext *ctx,
                                      int argc, JSValueConst *argv)
 {
     if (!JS_IsUndefined(new_target))
-        return JS_ThrowTypeError(ctx, "not a constructor");
+        return JS_ThrowTypeErrorNotAConstructor(ctx, new_target);
     return JS_ToBigIntCtorFree(ctx, JS_DupValue(ctx, argv[0]));
 }
 
index 2f4578ca576f90980bb732c4c9ab55553f94148b..5c51f0df52c947d1dc35691a4dd09413e34948c9 100644 (file)
@@ -248,6 +248,15 @@ function test_delete()
     assert(err, true, "delete");
 }
 
+function test_constructor()
+{
+    function *G() {}
+    let ex
+    try { new G() } catch (ex_) { ex = ex_ }
+    assert(ex instanceof TypeError)
+    assert(ex.message, "G is not a constructor")
+}
+
 function test_prototype()
 {
     var f = function f() { };
@@ -660,6 +669,7 @@ test_cvt();
 test_eq();
 test_inc_dec();
 test_op2();
+test_constructor();
 test_delete();
 test_prototype();
 test_arguments();