Skip to content

Commit 9e3ceb6

Browse files
committed
Fix inner classes in class heritage environment
This patch is the proper fix for #2667, since #2269 did not fix the problem entirely. JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik [email protected]
1 parent e8502fa commit 9e3ceb6

File tree

7 files changed

+113
-26
lines changed

7 files changed

+113
-26
lines changed

jerry-core/ecma/base/ecma-globals.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,12 @@ typedef enum
9898
ECMA_PARSE_NO_OPTS = 0, /**< no options passed */
9999
ECMA_PARSE_STRICT_MODE = (1u << 0), /**< enable strict mode */
100100
ECMA_PARSE_DIRECT_EVAL = (1u << 1), /**< eval is called directly (ECMA-262 v5, 15.1.2.1.1) */
101-
/* These three status flags must be in this order. See PARSER_CLASS_PARSE_OPTS_OFFSET. */
101+
/* These four status flags must be in this order. See PARSER_CLASS_PARSE_OPTS_OFFSET. */
102102
ECMA_PARSE_CLASS_CONSTRUCTOR = (1u << 2), /**< a class constructor is being parsed (this value must be kept in
103103
* in sync with PARSER_CLASS_CONSTRUCTOR) */
104104
ECMA_PARSE_HAS_SUPER = (1u << 3), /**< the current context has super reference */
105-
ECMA_PARSE_HAS_STATIC_SUPER = (1u << 4), /**< the current context is a static class method */
105+
ECMA_PARSE_HAS_IMPL_SUPER = (1u << 4), /**< the current context has super implicit super reference */
106+
ECMA_PARSE_HAS_STATIC_SUPER = (1u << 5), /**< the current context is a static class method */
106107
} ecma_parse_opts_t;
107108

108109
/**

jerry-core/ecma/operations/ecma-function-object.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1053,7 +1053,10 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */
10531053
/* Catch the special case when a the class extends value in null
10541054
and the class has no explicit constructor to raise TypeError.*/
10551055
JERRY_ASSERT (!ecma_op_function_has_construct_flag (arguments_list_p));
1056-
JERRY_ASSERT (ecma_get_object_prototype (func_obj_p) == NULL);
1056+
#ifndef JERRY_NDEBUG
1057+
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
1058+
JERRY_ASSERT (ecma_get_object_prototype (func_obj_p) == prototype_obj_p);
1059+
#endif /* !JERRY_NDEBUG */
10571060

10581061
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Super constructor null is not a constructor."));
10591062
break;

jerry-core/parser/js/js-parser-expr.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,8 @@ parser_parse_class_literal (parser_context_t *context_p) /**< context */
369369
parser_emit_cbc (context_p, CBC_CREATE_OBJECT);
370370

371371
bool super_called = false;
372-
uint32_t status_flags = PARSER_IS_FUNCTION | PARSER_IS_CLOSURE | (context_p->status_flags & PARSER_CLASS_HAS_SUPER);
372+
uint32_t status_flags = PARSER_IS_FUNCTION | PARSER_IS_CLOSURE;
373+
status_flags |= (context_p->status_flags & (PARSER_CLASS_HAS_SUPER | PARSER_CLASS_IMPLICIT_SUPER));
373374

374375
while (true)
375376
{
@@ -480,9 +481,10 @@ parser_parse_class_literal (parser_context_t *context_p) /**< context */
480481
lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
481482
literal_p->type = LEXER_UNUSED_LITERAL;
482483
literal_p->status_flags = 0;
484+
uint16_t result_index = context_p->literal_count;
483485
literal_p->u.bytecode_p = parser_parse_function (context_p, constructor_status_flags);
484486
literal_p->type = LEXER_FUNCTION_LITERAL;
485-
parser_emit_cbc_literal (context_p, PARSER_TO_EXT_OPCODE (CBC_EXT_SET_CLASS_LITERAL), context_p->literal_count);
487+
parser_emit_cbc_literal (context_p, PARSER_TO_EXT_OPCODE (CBC_EXT_SET_CLASS_LITERAL), result_index);
486488
context_p->literal_count++;
487489
continue;
488490
}
@@ -560,8 +562,6 @@ parser_parse_class (parser_context_t *context_p, /**< context */
560562
{
561563
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_CLASS);
562564

563-
context_p->status_flags &= (uint32_t) ~PARSER_CLASS_HAS_SUPER;
564-
565565
uint16_t class_ident_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS;
566566

567567
if (is_statement)
@@ -587,7 +587,10 @@ parser_parse_class (parser_context_t *context_p, /**< context */
587587
}
588588
}
589589

590-
if (context_p->token.type == LEXER_KEYW_EXTENDS)
590+
bool create_class_env = (bool) (context_p->token.type == LEXER_KEYW_EXTENDS
591+
|| context_p->status_flags & PARSER_CLASS_HAS_SUPER);
592+
593+
if (create_class_env)
591594
{
592595
parser_parse_super_class_context_start (context_p);
593596
}
@@ -620,10 +623,10 @@ parser_parse_class (parser_context_t *context_p, /**< context */
620623
parser_emit_cbc_literal (context_p, CBC_ASSIGN_SET_IDENT, class_ident_index);
621624
}
622625

623-
if (context_p->status_flags & PARSER_CLASS_HAS_SUPER)
626+
if (create_class_env)
624627
{
625628
parser_parse_super_class_context_end (context_p, is_statement);
626-
context_p->status_flags &= (uint32_t) ~PARSER_CLASS_HAS_SUPER;
629+
context_p->status_flags &= (uint32_t) ~(PARSER_CLASS_HAS_SUPER | PARSER_CLASS_IMPLICIT_SUPER);
627630
}
628631

629632
parser_flush_cbc (context_p);
@@ -1371,7 +1374,14 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
13711374
#ifndef CONFIG_DISABLE_ES2015_CLASS
13721375
if (PARSER_IS_CLASS_CONSTRUCTOR_SUPER (context_p->status_flags))
13731376
{
1374-
parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_CONSTRUCTOR_THIS);
1377+
if (context_p->status_flags & PARSER_CLASS_IMPLICIT_SUPER)
1378+
{
1379+
parser_emit_cbc (context_p, CBC_PUSH_THIS);
1380+
}
1381+
else
1382+
{
1383+
parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_CONSTRUCTOR_THIS);
1384+
}
13751385
}
13761386
else
13771387
{
@@ -1420,13 +1430,20 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
14201430
break;
14211431
}
14221432

1433+
if (context_p->status_flags & PARSER_CLASS_IMPLICIT_SUPER)
1434+
{
1435+
parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_STATIC_SUPER);
1436+
break;
1437+
}
1438+
14231439
bool is_static = (context_p->status_flags & PARSER_CLASS_STATIC_FUNCTION) != 0;
14241440
parser_emit_cbc_ext (context_p, is_static ? CBC_EXT_PUSH_STATIC_SUPER : CBC_EXT_PUSH_SUPER);
14251441
break;
14261442
}
14271443

14281444
if (lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN)
14291445
&& (context_p->status_flags & PARSER_CLASS_HAS_SUPER)
1446+
&& !(context_p->status_flags & PARSER_CLASS_IMPLICIT_SUPER)
14301447
&& (context_p->status_flags & (PARSER_IS_ARROW_FUNCTION | PARSER_CLASS_CONSTRUCTOR)))
14311448
{
14321449
parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_CONSTRUCTOR_SUPER);

jerry-core/parser/js/js-parser-internal.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,13 @@ typedef enum
6767
PARSER_ARROW_PARSE_ARGS = (1u << 19), /**< parse the argument list of an arrow function */
6868
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
6969
#ifndef CONFIG_DISABLE_ES2015_CLASS
70-
/* These three status flags must be in this order. See PARSER_CLASS_PARSE_OPTS_OFFSET. */
70+
/* These four status flags must be in this order. See PARSER_CLASS_PARSE_OPTS_OFFSET. */
7171
PARSER_CLASS_CONSTRUCTOR = (1u << 20), /**< a class constructor is parsed (this value must be kept in
7272
* in sync with ECMA_PARSE_CLASS_CONSTRUCTOR) */
7373
PARSER_CLASS_HAS_SUPER = (1u << 21), /**< class has super reference */
74-
PARSER_CLASS_STATIC_FUNCTION = (1u << 22), /**< this function is a static class method */
75-
PARSER_CLASS_SUPER_PROP_REFERENCE = (1u << 23), /**< super property call or assignment */
74+
PARSER_CLASS_IMPLICIT_SUPER = (1u << 22), /**< super property call or assignment */
75+
PARSER_CLASS_STATIC_FUNCTION = (1u << 23), /**< this function is a static class method */
76+
PARSER_CLASS_SUPER_PROP_REFERENCE = (1u << 24), /**< super property call or assignment */
7677
#endif /* !CONFIG_DISABLE_ES2015_CLASS */
7778
} parser_general_flags_t;
7879

jerry-core/parser/js/js-parser-statm.c

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -606,16 +606,25 @@ parser_parse_with_statement_end (parser_context_t *context_p) /**< context */
606606
void
607607
parser_parse_super_class_context_start (parser_context_t *context_p) /**< context */
608608
{
609-
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_EXTENDS);
610-
609+
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_EXTENDS
610+
|| (context_p->status_flags & PARSER_CLASS_HAS_SUPER));
611611
parser_with_statement_t with_statement;
612612

613-
lexer_next_token (context_p);
613+
if (context_p->token.type == LEXER_KEYW_EXTENDS)
614+
{
615+
lexer_next_token (context_p);
614616

615-
/* NOTE: Currently there is no proper way to check whether the currently parsed expression
616-
is a valid lefthand-side expression or not, so we do not throw syntax error and parse
617-
the class extending value as an expression. */
618-
parser_parse_expression (context_p, PARSE_EXPR | PARSE_EXPR_NO_COMMA);
617+
/* NOTE: Currently there is no proper way to check whether the currently parsed expression
618+
is a valid lefthand-side expression or not, so we do not throw syntax error and parse
619+
the class extending value as an expression. */
620+
parser_parse_expression (context_p, PARSE_EXPR | PARSE_EXPR_NO_COMMA);
621+
}
622+
else
623+
{
624+
JERRY_ASSERT (context_p->status_flags & PARSER_CLASS_HAS_SUPER);
625+
parser_emit_cbc (context_p, CBC_PUSH_NULL);
626+
context_p->status_flags |= PARSER_CLASS_IMPLICIT_SUPER;
627+
}
619628

620629
#ifndef JERRY_NDEBUG
621630
PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_SUPER_CLASS_CONTEXT_STACK_ALLOCATION);
@@ -2022,7 +2031,14 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
20222031
#ifndef CONFIG_DISABLE_ES2015_CLASS
20232032
if (JERRY_UNLIKELY (PARSER_IS_CLASS_CONSTRUCTOR_SUPER (context_p->status_flags)))
20242033
{
2025-
parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_CONSTRUCTOR_THIS);
2034+
if (context_p->status_flags & PARSER_CLASS_IMPLICIT_SUPER)
2035+
{
2036+
parser_emit_cbc (context_p, CBC_PUSH_THIS);
2037+
}
2038+
else
2039+
{
2040+
parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_CONSTRUCTOR_THIS);
2041+
}
20262042
parser_emit_cbc (context_p, CBC_RETURN);
20272043
}
20282044
else
@@ -2164,7 +2180,14 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
21642180
#ifndef CONFIG_DISABLE_ES2015_CLASS
21652181
if (JERRY_UNLIKELY (PARSER_IS_CLASS_CONSTRUCTOR_SUPER (context_p->status_flags)))
21662182
{
2167-
parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_CONSTRUCTOR_THIS);
2183+
if (context_p->status_flags & PARSER_CLASS_IMPLICIT_SUPER)
2184+
{
2185+
parser_emit_cbc (context_p, CBC_PUSH_THIS);
2186+
}
2187+
else
2188+
{
2189+
parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_CONSTRUCTOR_THIS);
2190+
}
21682191
parser_emit_cbc (context_p, CBC_RETURN);
21692192
parser_flush_cbc (context_p);
21702193
}

jerry-core/vm/vm.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,7 +1328,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
13281328

13291329
if (ecma_is_value_null (super_value))
13301330
{
1331-
super_class_p = ecma_create_object (NULL, 0, ECMA_OBJECT_TYPE_GENERAL);
1331+
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
1332+
super_class_p = ecma_create_object (prototype_obj_p, 0, ECMA_OBJECT_TYPE_GENERAL);
13321333
}
13331334
else
13341335
{
@@ -1404,7 +1405,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
14041405

14051406
ECMA_SET_POINTER (child_prototype_class_p->prototype_or_outer_reference_cp, super_prototype_class_p);
14061407
ECMA_SET_POINTER (child_class_p->prototype_or_outer_reference_cp, super_class_p);
1407-
14081408
}
14091409
ecma_free_value (super_prototype_value);
14101410
}
@@ -1533,7 +1533,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
15331533
else
15341534
{
15351535
ecma_object_t *super_class_p = ecma_op_resolve_super_reference_value (frame_ctx_p->lex_env_p);
1536-
*stack_top_p++ = ecma_fast_copy_value (ecma_make_object_value (super_class_p));
1536+
ecma_ref_object (super_class_p);
1537+
*stack_top_p++ = ecma_make_object_value (super_class_p);
15371538
}
15381539

15391540
continue;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
class C1 {
2+
f() {
3+
return 5;
4+
}
5+
}
6+
7+
class C2 extends C1 {
8+
f() {
9+
assert (super.f () === 5);
10+
11+
class G {
12+
g() {
13+
assert (super.f === undefined)
14+
assert (super.toString () === "[object Object]");
15+
var a = super.valueOf ();
16+
try {
17+
a ();
18+
assert (false);
19+
} catch (e) {
20+
assert (e instanceof TypeError);
21+
}
22+
}
23+
24+
constructor (){
25+
assert (Object.getPrototypeOf (this) === G.prototype);
26+
27+
try {
28+
eval ("super ()");
29+
assert (false);
30+
} catch (e) {
31+
assert (e instanceof SyntaxError);
32+
}
33+
}
34+
}
35+
36+
var g = new G ();
37+
g.g ();
38+
}
39+
}
40+
41+
(new C2).f ();

0 commit comments

Comments
 (0)