Skip to content

Commit e1713ea

Browse files
authored
Add function name to "not a constructor" errors (#1207)
Include the function name (if known) in the error message, to make debugging easier. Not a complete fix but still an improvement. Refs: #991
1 parent c85fd87 commit e1713ea

File tree

2 files changed

+36
-6
lines changed

2 files changed

+36
-6
lines changed

quickjs.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7232,6 +7232,25 @@ static JSValue JS_ThrowStackOverflow(JSContext *ctx)
72327232
return JS_ThrowRangeError(ctx, "Maximum call stack size exceeded");
72337233
}
72347234

7235+
static JSValue JS_ThrowTypeErrorNotAConstructor(JSContext *ctx,
7236+
JSValueConst func_obj)
7237+
{
7238+
JSObject *p;
7239+
JSAtom name;
7240+
7241+
if (JS_TAG_OBJECT != JS_VALUE_GET_TAG(func_obj))
7242+
goto fini;
7243+
p = JS_VALUE_GET_OBJ(func_obj);
7244+
if (!js_class_has_bytecode(p->class_id))
7245+
goto fini;
7246+
name = p->u.func.function_bytecode->func_name;
7247+
if (name == JS_ATOM_NULL)
7248+
goto fini;
7249+
return JS_ThrowTypeErrorAtom(ctx, "%s is not a constructor", name);
7250+
fini:
7251+
return JS_ThrowTypeError(ctx, "not a constructor");
7252+
}
7253+
72357254
static JSValue JS_ThrowTypeErrorNotAFunction(JSContext *ctx)
72367255
{
72377256
return JS_ThrowTypeError(ctx, "not a function");
@@ -18822,7 +18841,7 @@ static JSValue JS_CallConstructorInternal(JSContext *ctx,
1882218841
goto not_a_function;
1882318842
p = JS_VALUE_GET_OBJ(func_obj);
1882418843
if (unlikely(!p->is_constructor))
18825-
return JS_ThrowTypeError(ctx, "not a constructor");
18844+
return JS_ThrowTypeErrorNotAConstructor(ctx, func_obj);
1882618845
if (unlikely(p->class_id != JS_CLASS_BYTECODE_FUNCTION)) {
1882718846
JSClassCall *call_func;
1882818847
call_func = ctx->rt->class_array[p->class_id].call;
@@ -38668,8 +38687,9 @@ static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj,
3866838687
if (JS_IsUndefined(species) || JS_IsNull(species))
3866938688
return js_dup(defaultConstructor);
3867038689
if (!JS_IsConstructor(ctx, species)) {
38690+
JS_ThrowTypeErrorNotAConstructor(ctx, species);
3867138691
JS_FreeValue(ctx, species);
38672-
return JS_ThrowTypeError(ctx, "not a constructor");
38692+
return JS_EXCEPTION;
3867338693
}
3867438694
return species;
3867538695
}
@@ -47555,7 +47575,7 @@ static JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val,
4755547575
if (argc > 2) {
4755647576
new_target = argv[2];
4755747577
if (!JS_IsConstructor(ctx, new_target))
47558-
return JS_ThrowTypeError(ctx, "not a constructor");
47578+
return JS_ThrowTypeErrorNotAConstructor(ctx, new_target);
4755947579
} else {
4756047580
new_target = func;
4756147581
}
@@ -48475,7 +48495,7 @@ static JSValue js_proxy_call_constructor(JSContext *ctx, JSValueConst func_obj,
4847548495
if (!s)
4847648496
return JS_EXCEPTION;
4847748497
if (!JS_IsConstructor(ctx, s->target))
48478-
return JS_ThrowTypeError(ctx, "not a constructor");
48498+
return JS_ThrowTypeErrorNotAConstructor(ctx, s->target);
4847948499
if (JS_IsUndefined(method))
4848048500
return JS_CallConstructor2(ctx, s->target, new_target, argc, argv);
4848148501
arg_array = js_create_array(ctx, argc, argv);
@@ -48707,7 +48727,7 @@ static JSValue js_symbol_constructor(JSContext *ctx, JSValueConst new_target,
4870748727
JSString *p;
4870848728

4870948729
if (!JS_IsUndefined(new_target))
48710-
return JS_ThrowTypeError(ctx, "not a constructor");
48730+
return JS_ThrowTypeErrorNotAConstructor(ctx, new_target);
4871148731
if (argc == 0 || JS_IsUndefined(argv[0])) {
4871248732
p = NULL;
4871348733
} else {
@@ -53317,7 +53337,7 @@ static JSValue js_bigint_constructor(JSContext *ctx,
5331753337
int argc, JSValueConst *argv)
5331853338
{
5331953339
if (!JS_IsUndefined(new_target))
53320-
return JS_ThrowTypeError(ctx, "not a constructor");
53340+
return JS_ThrowTypeErrorNotAConstructor(ctx, new_target);
5332153341
return JS_ToBigIntCtorFree(ctx, js_dup(argv[0]));
5332253342
}
5332353343

tests/test_language.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,15 @@ function test_delete()
259259
assert(err, true, "delete");
260260
}
261261

262+
function test_constructor()
263+
{
264+
function *G() {}
265+
let ex
266+
try { new G() } catch (ex_) { ex = ex_ }
267+
assert(ex instanceof TypeError)
268+
assert(ex.message, "G is not a constructor")
269+
}
270+
262271
function test_prototype()
263272
{
264273
var f = function f() { };
@@ -718,6 +727,7 @@ test_eq();
718727
test_inc_dec();
719728
test_op2();
720729
test_delete();
730+
test_constructor();
721731
test_prototype();
722732
test_arguments();
723733
test_class();

0 commit comments

Comments
 (0)