Skip to content

Commit 4cc4c6c

Browse files
author
Fabrice Bellard
committed
optimized js_parse_class_default_ctor() (bnoordhuis)
1 parent 9106fa0 commit 4cc4c6c

File tree

2 files changed

+68
-24
lines changed

2 files changed

+68
-24
lines changed

quickjs-opcode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ DEF( return, 1, 1, 0, none)
110110
DEF( return_undef, 1, 0, 0, none)
111111
DEF(check_ctor_return, 1, 1, 2, none)
112112
DEF( check_ctor, 1, 0, 0, none)
113+
DEF( init_ctor, 1, 0, 1, none)
113114
DEF( check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */
114115
DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */
115116
DEF( return_async, 1, 1, 0, none)

quickjs.c

Lines changed: 67 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16677,10 +16677,27 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
1667716677
BREAK;
1667816678
CASE(OP_check_ctor):
1667916679
if (JS_IsUndefined(new_target)) {
16680+
non_ctor_call:
1668016681
JS_ThrowTypeError(ctx, "class constructors must be invoked with 'new'");
1668116682
goto exception;
1668216683
}
1668316684
BREAK;
16685+
CASE(OP_init_ctor):
16686+
{
16687+
JSValue super, ret;
16688+
sf->cur_pc = pc;
16689+
if (JS_IsUndefined(new_target))
16690+
goto non_ctor_call;
16691+
super = JS_GetPrototype(ctx, func_obj);
16692+
if (JS_IsException(super))
16693+
goto exception;
16694+
ret = JS_CallConstructor2(ctx, super, new_target, argc, (JSValueConst *)argv);
16695+
JS_FreeValue(ctx, super);
16696+
if (JS_IsException(ret))
16697+
goto exception;
16698+
*sp++ = ret;
16699+
}
16700+
BREAK;
1668416701
CASE(OP_check_brand):
1668516702
{
1668616703
int ret = JS_CheckBrand(ctx, sp[-2], sp[-1]);
@@ -22714,45 +22731,73 @@ static __exception int js_parse_object_literal(JSParseState *s)
2271422731
#define PF_POW_FORBIDDEN (1 << 3)
2271522732

2271622733
static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags);
22734+
static void emit_class_field_init(JSParseState *s);
22735+
static JSFunctionDef *js_new_function_def(JSContext *ctx,
22736+
JSFunctionDef *parent,
22737+
BOOL is_eval,
22738+
BOOL is_func_expr,
22739+
const char *filename, int line_num);
22740+
static void emit_return(JSParseState *s, BOOL hasval);
2271722741

2271822742
static __exception int js_parse_left_hand_side_expr(JSParseState *s)
2271922743
{
2272022744
return js_parse_postfix_expr(s, PF_POSTFIX_CALL);
2272122745
}
2272222746

22723-
/* XXX: could generate specific bytecode */
2272422747
static __exception int js_parse_class_default_ctor(JSParseState *s,
2272522748
BOOL has_super,
2272622749
JSFunctionDef **pfd)
2272722750
{
22728-
JSParsePos pos;
22729-
const char *str;
22730-
int ret, line_num;
2273122751
JSParseFunctionEnum func_type;
22732-
const uint8_t *saved_buf_end;
22752+
JSFunctionDef *fd = s->cur_func;
22753+
int idx;
2273322754

22734-
js_parse_get_pos(s, &pos);
22755+
fd = js_new_function_def(s->ctx, fd, FALSE, FALSE, s->filename,
22756+
s->token.line_num);
22757+
if (!fd)
22758+
return -1;
22759+
22760+
s->cur_func = fd;
22761+
fd->has_home_object = TRUE;
22762+
fd->super_allowed = TRUE;
22763+
fd->has_prototype = FALSE;
22764+
fd->has_this_binding = TRUE;
22765+
fd->new_target_allowed = TRUE;
22766+
22767+
push_scope(s); /* enter body scope */
22768+
fd->body_scope = fd->scope_level;
2273522769
if (has_super) {
22736-
/* spec change: no argument evaluation */
22737-
str = "(){super(...arguments);}";
22770+
fd->is_derived_class_constructor = TRUE;
22771+
fd->super_call_allowed = TRUE;
22772+
fd->arguments_allowed = TRUE;
22773+
fd->has_arguments_binding = TRUE;
2273822774
func_type = JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR;
22775+
emit_op(s, OP_init_ctor);
22776+
// TODO(bnoordhuis) roll into OP_init_ctor
22777+
emit_op(s, OP_scope_put_var_init);
22778+
emit_atom(s, JS_ATOM_this);
22779+
emit_u16(s, 0);
22780+
emit_class_field_init(s);
2273922781
} else {
22740-
str = "(){}";
2274122782
func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR;
22783+
/* error if not invoked as a constructor */
22784+
emit_op(s, OP_check_ctor);
22785+
emit_class_field_init(s);
2274222786
}
22743-
line_num = s->token.line_num;
22744-
saved_buf_end = s->buf_end;
22745-
s->buf_ptr = (uint8_t *)str;
22746-
s->buf_end = (uint8_t *)(str + strlen(str));
22747-
ret = next_token(s);
22748-
if (!ret) {
22749-
ret = js_parse_function_decl2(s, func_type, JS_FUNC_NORMAL,
22750-
JS_ATOM_NULL, (uint8_t *)str,
22751-
line_num, JS_PARSE_EXPORT_NONE, pfd);
22752-
}
22753-
s->buf_end = saved_buf_end;
22754-
ret |= js_parse_seek_token(s, &pos);
22755-
return ret;
22787+
22788+
fd->func_kind = JS_FUNC_NORMAL;
22789+
fd->func_type = func_type;
22790+
emit_return(s, FALSE);
22791+
22792+
s->cur_func = fd->parent;
22793+
if (pfd)
22794+
*pfd = fd;
22795+
22796+
/* the real object will be set at the end of the compilation */
22797+
idx = cpool_add(s, JS_NULL);
22798+
fd->parent_cpool_idx = idx;
22799+
22800+
return 0;
2275622801
}
2275722802

2275822803
/* find field in the current scope */
@@ -25466,8 +25511,6 @@ static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags)
2546625511
return 0;
2546725512
}
2546825513

25469-
static void emit_return(JSParseState *s, BOOL hasval);
25470-
2547125514
/* allowed parse_flags: PF_IN_ACCEPTED */
2547225515
static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
2547325516
{

0 commit comments

Comments
 (0)