diff --git a/gen/function_source.c b/gen/function_source.c index 642e828..f486ee5 100644 Binary files a/gen/function_source.c and b/gen/function_source.c differ diff --git a/gen/hello.c b/gen/hello.c index f713ed1..8c0f251 100644 Binary files a/gen/hello.c and b/gen/hello.c differ diff --git a/gen/hello_module.c b/gen/hello_module.c index 45e9bc7..65cd2e7 100644 Binary files a/gen/hello_module.c and b/gen/hello_module.c differ diff --git a/gen/repl.c b/gen/repl.c index 80bf563..b79df84 100644 Binary files a/gen/repl.c and b/gen/repl.c differ diff --git a/gen/standalone.c b/gen/standalone.c index 39f0a65..998907a 100644 Binary files a/gen/standalone.c and b/gen/standalone.c differ diff --git a/gen/test_fib.c b/gen/test_fib.c index d33cff2..efa478d 100644 Binary files a/gen/test_fib.c and b/gen/test_fib.c differ diff --git a/quickjs-opcode.h b/quickjs-opcode.h index 09dacb3..fb5394c 100644 --- a/quickjs-opcode.h +++ b/quickjs-opcode.h @@ -111,6 +111,7 @@ DEF( return, 1, 1, 0, none) DEF( return_undef, 1, 0, 0, none) DEF(check_ctor_return, 1, 1, 2, none) DEF( check_ctor, 1, 0, 0, none) +DEF( init_ctor, 1, 0, 1, none) DEF( check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */ DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */ DEF( return_async, 1, 1, 0, none) diff --git a/quickjs.c b/quickjs.c index 9b86e42..c534a26 100644 --- a/quickjs.c +++ b/quickjs.c @@ -15412,10 +15412,27 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValue func_obj, BREAK; CASE(OP_check_ctor): if (JS_IsUndefined(new_target)) { + non_ctor_call: JS_ThrowTypeError(ctx, "class constructors must be invoked with 'new'"); goto exception; } BREAK; + CASE(OP_init_ctor): + { + JSValue super, ret; + sf->cur_pc = pc; + if (JS_IsUndefined(new_target)) + goto non_ctor_call; + super = JS_GetPrototype(ctx, func_obj); + if (JS_IsException(super)) + goto exception; + ret = JS_CallConstructor2(ctx, super, new_target, argc, argv); + JS_FreeValue(ctx, super); + if (JS_IsException(ret)) + goto exception; + *sp++ = ret; + } + BREAK; CASE(OP_check_brand): { int ret = JS_CheckBrand(ctx, sp[-2], sp[-1]); @@ -21896,9 +21913,6 @@ static __exception int js_parse_class_default_ctor(JSParseState *s, fd->has_this_binding = TRUE; fd->new_target_allowed = TRUE; - /* error if not invoked as a constructor */ - emit_op(s, OP_check_ctor); - push_scope(s); /* enter body scope */ fd->body_scope = fd->scope_level; if (has_super) { @@ -21906,43 +21920,17 @@ static __exception int js_parse_class_default_ctor(JSParseState *s, fd->super_call_allowed = TRUE; fd->arguments_allowed = TRUE; fd->has_arguments_binding = TRUE; - func_type = JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR; - /* super */ - emit_op(s, OP_scope_get_var); - emit_atom(s, JS_ATOM_this_active_func); - emit_u16(s, 0); - - emit_op(s, OP_get_super); - - emit_op(s, OP_scope_get_var); - emit_atom(s, JS_ATOM_new_target); - emit_u16(s, 0); - - emit_op(s, OP_array_from); - emit_u16(s, 0); - emit_op(s, OP_push_i32); - emit_u32(s, 0); - - /* arguments */ - emit_op(s, OP_scope_get_var); - emit_atom(s, JS_ATOM_arguments); - emit_u16(s, 0); - - emit_op(s, OP_append); - /* drop the index */ - emit_op(s, OP_drop); - - emit_op(s, OP_apply); - emit_u16(s, 1); - /* set the 'this' value */ - emit_op(s, OP_dup); + emit_op(s, OP_init_ctor); + // TODO(bnoordhuis) roll into OP_init_ctor emit_op(s, OP_scope_put_var_init); emit_atom(s, JS_ATOM_this); emit_u16(s, 0); emit_class_field_init(s); } else { func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR; + /* error if not invoked as a constructor */ + emit_op(s, OP_check_ctor); emit_class_field_init(s); }