class static block (initial patch by bnoordhuis)
This commit is contained in:
parent
a8064b74fb
commit
16057644f3
3 changed files with 78 additions and 19 deletions
2
TODO
2
TODO
|
@ -63,5 +63,5 @@ Optimization ideas:
|
||||||
Test262o: 0/11262 errors, 463 excluded
|
Test262o: 0/11262 errors, 463 excluded
|
||||||
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
|
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
|
||||||
|
|
||||||
Result: 16/76783 errors, 1497 excluded, 8199 skipped
|
Result: 16/76909 errors, 1497 excluded, 8136 skipped
|
||||||
Test262 commit: 6cbb6da9473c56d95358d8e679c5a6d2b4574efb
|
Test262 commit: 6cbb6da9473c56d95358d8e679c5a6d2b4574efb
|
||||||
|
|
93
quickjs.c
93
quickjs.c
|
@ -19688,6 +19688,7 @@ typedef enum JSParseFunctionEnum {
|
||||||
JS_PARSE_FUNC_GETTER,
|
JS_PARSE_FUNC_GETTER,
|
||||||
JS_PARSE_FUNC_SETTER,
|
JS_PARSE_FUNC_SETTER,
|
||||||
JS_PARSE_FUNC_METHOD,
|
JS_PARSE_FUNC_METHOD,
|
||||||
|
JS_PARSE_FUNC_CLASS_STATIC_INIT,
|
||||||
JS_PARSE_FUNC_CLASS_CONSTRUCTOR,
|
JS_PARSE_FUNC_CLASS_CONSTRUCTOR,
|
||||||
JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR,
|
JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR,
|
||||||
} JSParseFunctionEnum;
|
} JSParseFunctionEnum;
|
||||||
|
@ -20574,17 +20575,19 @@ static __exception int next_token(JSParseState *s)
|
||||||
(s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) ||
|
(s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) ||
|
||||||
(s->token.u.ident.atom == JS_ATOM_await &&
|
(s->token.u.ident.atom == JS_ATOM_await &&
|
||||||
(s->is_module ||
|
(s->is_module ||
|
||||||
(((s->cur_func->func_kind & JS_FUNC_ASYNC) ||
|
(s->cur_func->func_kind & JS_FUNC_ASYNC) ||
|
||||||
(s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
|
s->cur_func->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT ||
|
||||||
!s->cur_func->in_function_body && s->cur_func->parent &&
|
(s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
|
||||||
(s->cur_func->parent->func_kind & JS_FUNC_ASYNC))))))) {
|
!s->cur_func->in_function_body && s->cur_func->parent &&
|
||||||
if (ident_has_escape) {
|
((s->cur_func->parent->func_kind & JS_FUNC_ASYNC) ||
|
||||||
s->token.u.ident.is_reserved = TRUE;
|
s->cur_func->parent->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT))))) {
|
||||||
s->token.val = TOK_IDENT;
|
if (ident_has_escape) {
|
||||||
} else {
|
s->token.u.ident.is_reserved = TRUE;
|
||||||
/* The keywords atoms are pre allocated */
|
s->token.val = TOK_IDENT;
|
||||||
s->token.val = s->token.u.ident.atom - 1 + TOK_FIRST_KEYWORD;
|
} else {
|
||||||
}
|
/* The keywords atoms are pre allocated */
|
||||||
|
s->token.val = s->token.u.ident.atom - 1 + TOK_FIRST_KEYWORD;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
s->token.val = TOK_IDENT;
|
s->token.val = TOK_IDENT;
|
||||||
}
|
}
|
||||||
|
@ -22810,6 +22813,49 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
|
||||||
if (is_static) {
|
if (is_static) {
|
||||||
if (next_token(s))
|
if (next_token(s))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
if (s->token.val == '{') {
|
||||||
|
ClassFieldsDef *cf = &class_fields[is_static];
|
||||||
|
JSFunctionDef *init;
|
||||||
|
if (!cf->fields_init_fd) {
|
||||||
|
if (emit_class_init_start(s, cf))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
s->cur_func = cf->fields_init_fd;
|
||||||
|
/* XXX: could try to avoid creating a new function and
|
||||||
|
reuse 'fields_init_fd' with a specific 'var'
|
||||||
|
scope */
|
||||||
|
// stack is now: <empty>
|
||||||
|
if (js_parse_function_decl2(s, JS_PARSE_FUNC_CLASS_STATIC_INIT,
|
||||||
|
JS_FUNC_NORMAL, JS_ATOM_NULL,
|
||||||
|
s->token.ptr, s->token.line_num,
|
||||||
|
JS_PARSE_EXPORT_NONE, &init) < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
// stack is now: fclosure
|
||||||
|
push_scope(s);
|
||||||
|
emit_op(s, OP_scope_get_var);
|
||||||
|
emit_atom(s, JS_ATOM_this);
|
||||||
|
emit_u16(s, 0);
|
||||||
|
// stack is now: fclosure this
|
||||||
|
/* XXX: should do it only once */
|
||||||
|
if (class_name != JS_ATOM_NULL) {
|
||||||
|
// TODO(bnoordhuis) pass as argument to init method?
|
||||||
|
emit_op(s, OP_dup);
|
||||||
|
emit_op(s, OP_scope_put_var_init);
|
||||||
|
emit_atom(s, class_name);
|
||||||
|
emit_u16(s, s->cur_func->scope_level);
|
||||||
|
}
|
||||||
|
emit_op(s, OP_swap);
|
||||||
|
// stack is now: this fclosure
|
||||||
|
emit_op(s, OP_call_method);
|
||||||
|
emit_u16(s, 0);
|
||||||
|
// stack is now: returnvalue
|
||||||
|
emit_op(s, OP_drop);
|
||||||
|
// stack is now: <empty>
|
||||||
|
pop_scope(s);
|
||||||
|
s->cur_func = s->cur_func->parent;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
/* allow "static" field name */
|
/* allow "static" field name */
|
||||||
if (s->token.val == ';' || s->token.val == '=') {
|
if (s->token.val == ';' || s->token.val == '=') {
|
||||||
is_static = FALSE;
|
is_static = FALSE;
|
||||||
|
@ -26127,6 +26173,10 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
|
||||||
js_parse_error(s, "return not in a function");
|
js_parse_error(s, "return not in a function");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
if (s->cur_func->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT) {
|
||||||
|
js_parse_error(s, "return in a static initializer block");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
if (next_token(s))
|
if (next_token(s))
|
||||||
goto fail;
|
goto fail;
|
||||||
if (s->token.val != ';' && s->token.val != '}' && !s->got_lf) {
|
if (s->token.val != ';' && s->token.val != '}' && !s->got_lf) {
|
||||||
|
@ -33278,8 +33328,9 @@ static __exception int js_parse_function_decl2(JSParseState *s,
|
||||||
func_type == JS_PARSE_FUNC_EXPR &&
|
func_type == JS_PARSE_FUNC_EXPR &&
|
||||||
(func_kind & JS_FUNC_GENERATOR)) ||
|
(func_kind & JS_FUNC_GENERATOR)) ||
|
||||||
(s->token.u.ident.atom == JS_ATOM_await &&
|
(s->token.u.ident.atom == JS_ATOM_await &&
|
||||||
func_type == JS_PARSE_FUNC_EXPR &&
|
((func_type == JS_PARSE_FUNC_EXPR &&
|
||||||
(func_kind & JS_FUNC_ASYNC))) {
|
(func_kind & JS_FUNC_ASYNC)) ||
|
||||||
|
func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT))) {
|
||||||
return js_parse_error_reserved_identifier(s);
|
return js_parse_error_reserved_identifier(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33373,7 +33424,8 @@ static __exception int js_parse_function_decl2(JSParseState *s,
|
||||||
func_type == JS_PARSE_FUNC_SETTER ||
|
func_type == JS_PARSE_FUNC_SETTER ||
|
||||||
func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR ||
|
func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR ||
|
||||||
func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR);
|
func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR);
|
||||||
fd->has_arguments_binding = (func_type != JS_PARSE_FUNC_ARROW);
|
fd->has_arguments_binding = (func_type != JS_PARSE_FUNC_ARROW &&
|
||||||
|
func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT);
|
||||||
fd->has_this_binding = fd->has_arguments_binding;
|
fd->has_this_binding = fd->has_arguments_binding;
|
||||||
fd->is_derived_class_constructor = (func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR);
|
fd->is_derived_class_constructor = (func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR);
|
||||||
if (func_type == JS_PARSE_FUNC_ARROW) {
|
if (func_type == JS_PARSE_FUNC_ARROW) {
|
||||||
|
@ -33381,6 +33433,11 @@ static __exception int js_parse_function_decl2(JSParseState *s,
|
||||||
fd->super_call_allowed = fd->parent->super_call_allowed;
|
fd->super_call_allowed = fd->parent->super_call_allowed;
|
||||||
fd->super_allowed = fd->parent->super_allowed;
|
fd->super_allowed = fd->parent->super_allowed;
|
||||||
fd->arguments_allowed = fd->parent->arguments_allowed;
|
fd->arguments_allowed = fd->parent->arguments_allowed;
|
||||||
|
} else if (func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT) {
|
||||||
|
fd->new_target_allowed = TRUE; // although new.target === undefined
|
||||||
|
fd->super_call_allowed = FALSE;
|
||||||
|
fd->super_allowed = TRUE;
|
||||||
|
fd->arguments_allowed = FALSE;
|
||||||
} else {
|
} else {
|
||||||
fd->new_target_allowed = TRUE;
|
fd->new_target_allowed = TRUE;
|
||||||
fd->super_call_allowed = fd->is_derived_class_constructor;
|
fd->super_call_allowed = fd->is_derived_class_constructor;
|
||||||
|
@ -33418,7 +33475,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
|
||||||
if (add_arg(ctx, fd, name) < 0)
|
if (add_arg(ctx, fd, name) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
fd->defined_arg_count = 1;
|
fd->defined_arg_count = 1;
|
||||||
} else {
|
} else if (func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT) {
|
||||||
if (s->token.val == '(') {
|
if (s->token.val == '(') {
|
||||||
int skip_bits;
|
int skip_bits;
|
||||||
/* if there is an '=' inside the parameter list, we
|
/* if there is an '=' inside the parameter list, we
|
||||||
|
@ -33639,8 +33696,10 @@ static __exception int js_parse_function_decl2(JSParseState *s,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (js_parse_expect(s, '{'))
|
if (func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT) {
|
||||||
goto fail;
|
if (js_parse_expect(s, '{'))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
if (js_parse_directives(s))
|
if (js_parse_directives(s))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
@ -79,7 +79,7 @@ class-fields-private
|
||||||
class-fields-private-in=skip
|
class-fields-private-in=skip
|
||||||
class-fields-public
|
class-fields-public
|
||||||
class-methods-private
|
class-methods-private
|
||||||
class-static-block=skip
|
class-static-block
|
||||||
class-static-fields-private
|
class-static-fields-private
|
||||||
class-static-fields-public
|
class-static-fields-public
|
||||||
class-static-methods-private
|
class-static-methods-private
|
||||||
|
|
Loading…
Reference in a new issue