-
Notifications
You must be signed in to change notification settings - Fork 684
Implement ES2015 class feature (part II.) #2439
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement ES2015 class feature (part II.) #2439
Conversation
3d8f738
to
9900717
Compare
jerry-core/ecma/base/ecma-helpers.h
Outdated
@@ -297,7 +297,9 @@ ecma_collection_iterator_next (ecma_value_t *iterator_p); | |||
/* ecma-helpers.c */ | |||
ecma_object_t *ecma_create_object (ecma_object_t *prototype_object_p, size_t ext_object_size, ecma_object_type_t type); | |||
ecma_object_t *ecma_create_decl_lex_env (ecma_object_t *outer_lexical_environment_p); | |||
ecma_object_t *ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, ecma_object_t *binding_obj_p); | |||
ecma_object_t *ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, | |||
ecma_object_t *binding_obj_p, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can keep this in the previous line.
@@ -72,6 +75,27 @@ ecma_builtin_global_object_eval (ecma_value_t this_arg, /**< this argument */ | |||
parse_opts |= ECMA_PARSE_STRICT_MODE; | |||
} | |||
|
|||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
uint32_t super_call_opts = JERRY_CONTEXT (vm_top_context_p)->super_call_opts; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be a simple global variable. Maybe combined with a direct_eval flag.
jerry-core/vm/vm.c
Outdated
#ifndef CONFIG_DISABLE_ES2015_CLASS | ||
if (JERRY_UNLIKELY (frame_ctx_p->super_call_opts & ECMA_SUPER_CALL_CONSTRUCTOR)) | ||
{ | ||
stack_top_p = (ecma_value_t *) ecma_op_function_set_construct_flag (stack_top_p); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would store these in local variables rather than manipulating globals. Just like is_direct_eval
above.
{ | ||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); | ||
|
||
return (property_p != NULL); | ||
} | ||
else | ||
{ | ||
JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); | ||
#ifndef CONFIG_DISABLE_ES2015_CLASS | ||
JERRY_ASSERT (lex_env_type != ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is an assert, use ==
twice.
jerry-core/parser/js/js-lexer.h
Outdated
@@ -16,6 +16,8 @@ | |||
#ifndef JS_LEXER_H | |||
#define JS_LEXER_H | |||
|
|||
#include "lit-char-helpers.h" | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather not include this here.
if (context_p->status_flags & PARSER_IS_ARROW_FUNCTION) | ||
{ | ||
status_flags |= PARSER_IS_ARROW_FUNCTION; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, you can do this in a less complicated way:
const uint32_t inherited_flags = PARSER_CLASS_HAS_SUPER | PARSER_IS_ARROW_FUNCTION;
status_flags |= (context_p->status_flags & inherited_flags);
Why arrow function is inherited?
{ | ||
parser_parse_super_class_context_start (context_p); | ||
} | ||
|
||
/* Currently heritage is not supported so the next token must be left brace. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this comment still valid?
parser_emit_cbc (context_p, CBC_PUSH_THIS); | ||
#endif /* !CONFIG_DISABLE_ES2015_CLASS */ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need this newline.
|| context_p->last_cbc_opcode == CBC_PUSH_PROP_THIS_LITERAL)) | ||
{ | ||
/* Invalid LeftHandSide expression. */ | ||
parser_raise_error (context_p, PARSER_ERR_INVALID_LEFT_HAND_SIDE_EXPRESSION); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ES6 standard is confusing for me. It allows f() = 5
lefthandside expressions, but says it is a ReferenceError during runtime.
For classes it has meaning: class A extends f() {}
is ok.
@zherczeg Thanks for the review, I'm going to apply your suggestions. |
3d9f3fc
to
d985517
Compare
@zherczeg The patch is updated and ready for the review. |
jerry-core/ecma/base/ecma-globals.h
Outdated
@@ -633,12 +637,56 @@ typedef enum | |||
ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE = 13, /**< declarative lexical environment */ | |||
ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND = 14, /**< object-bound lexical environment | |||
* with provideThis flag */ | |||
ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND = 15, /**< object-bound lexical environment | |||
* with provided super reference */ | |||
|
|||
ECMA_LEXICAL_ENVIRONMENT_TYPE_START = ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE, /**< first lexical | |||
* environment type */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete one space before comment.
jerry-core/ecma/base/ecma-helpers.c
Outdated
@@ -355,7 +354,7 @@ ecma_get_lex_env_binding_object (const ecma_object_t *object_p) /**< object-boun | |||
{ | |||
JERRY_ASSERT (object_p != NULL); | |||
JERRY_ASSERT (ecma_is_lexical_environment (object_p)); | |||
JERRY_ASSERT (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); | |||
JERRY_ASSERT (ecma_get_lex_env_type (object_p) != ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use != in assert.
ecma_object_t *constructor_object_p = ecma_get_object_from_value (constructor_value); | ||
|
||
ecma_value_t result = ecma_op_create_array_object (arguments_list_p, | ||
arguments_list_len, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a space.
* @return the bytecode of the most general 'super'. | ||
*/ | ||
static const ecma_compiled_code_t * | ||
ecma_resolve_implicit_constructor_call (const ecma_compiled_code_t *bytecode_data_p, /**< byte-code data header */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets try to use bound functions.
@@ -59,6 +59,30 @@ ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, /**< starting lexical | |||
return NULL; | |||
} /* ecma_op_resolve_reference_base */ | |||
|
|||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this newline.
eval_parse_opts |= ECMA_PARSE_ARROW_FUNCTION; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One newline.
jerry-core/vm/vm.c
Outdated
{ | ||
this_value = frame_ctx_p->this_binding; | ||
frame_ctx_p->super_call_opts &= (uint8_t) ~ECMA_HERITAGE_SUPER_PROP_CALL; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do this in the parser.
7c69ea4
to
8788c2a
Compare
jerry-core/ecma/base/ecma-globals.h
Outdated
@@ -170,6 +174,7 @@ enum | |||
* ecma_op_object_find */ | |||
ECMA_VALUE_REGISTER_REF = ECMA_MAKE_VALUE (8), /**< register reference, | |||
* a special "base" value for vm */ | |||
ECMA_VALUE_IMPLICIT_CALL = ECMA_MAKE_VALUE (9), /**< TODO */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
todo
jerry-core/ecma/base/ecma-globals.h
Outdated
ECMA_PARSE_DIRECT_EVAL = (1 << 1), /**< is eval called directly (ECMA-262 v5, 15.1.2.1.1) */ | ||
ECMA_PARSE_HAS_SUPER = (1 << 2), /**< the current context has super reference */ | ||
ECMA_PARSE_CLASS_CONSTRUCTOR = (1 << 3), /**< the current context is a class constructor */ | ||
ECMA_PARSE_ARROW_FUNCTION = (1 << 4), /**< the current context is an arrow function */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need this flag?
jerry-core/ecma/base/ecma-globals.h
Outdated
typedef enum | ||
{ | ||
ECMA_HERITAGE_NO_OPTS = 0, /**< no speficied options are provided */ | ||
ECMA_HERITAGE_SUPER_CALLED = (1 << 1), /**< 'super ()' has been called in the current context */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about using ECMA_OBJECT_FLAG_EXTENSIBLE?
is_treat_single_arg_as_length); | ||
|
||
ecma_object_t *result_object_p = ecma_get_object_from_value (result); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Less newline please.
jerry-core/vm/vm.c
Outdated
JERRY_ASSERT (frame_ctx_p->call_operation == VM_EXEC_SUPER_CALL); | ||
|
||
/* This flag is only used to force the call operation to VM_EXEC_SUPER_CALL | ||
so it is no longer needed. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this comment.
jerry-core/vm/vm.c
Outdated
goto error; | ||
} | ||
|
||
*stack_top_p++ = ecma_copy_value (ecma_op_get_super_this_binding (frame_ctx_p->lex_env_p)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
class this binding
jerry-core/vm/vm.c
Outdated
ecma_extended_object_t *current_ext_func_obj_p = (ecma_extended_object_t *) current_constructor_obj_p; | ||
|
||
current_constructor_obj_p->type_flags_refs &= (uint16_t) ~ECMA_OBJECT_TYPE_MASK; | ||
current_constructor_obj_p->type_flags_refs |= ECMA_OBJECT_TYPE_FUNCTION; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+= ECMA_OBJECT_TYPE_FUNCTION - ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION
jerry-core/vm/vm.c
Outdated
} | ||
case VM_OC_SUPER_PROP_REFERENCE: | ||
{ | ||
JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this.
ff1b5b2
to
0ea5c73
Compare
jerry-core/ecma/base/ecma-globals.h
Outdated
@@ -82,12 +82,16 @@ typedef enum | |||
|
|||
/** | |||
* Option flags for script parsing. | |||
* NOTE: The enum members must be kept int sync with parser_general_flags_t |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"kept in"
jerry-core/ecma/base/ecma-globals.h
Outdated
ECMA_PARSE_DIRECT_EVAL = (1u << 1), /**< is eval called directly (ECMA-262 v5, 15.1.2.1.1) */ | ||
ECMA_PARSE_CLASS_CONSTRUCTOR = (1u << 2), /**< the current context is a class constructor */ | ||
ECMA_PARSE_HAS_SUPER = (1u << 3), /**< the current context has super reference */ | ||
ECMA_PARSE_CLASS_STATIC_FUNCTION = (1u << 4), /**< the current context is a static class method */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ECMA_PARSE_HAS_STATIC_SUPER
jerry-core/ecma/base/ecma-globals.h
Outdated
ECMA_PARSE_DIRECT_EVAL = (1 << 1) /**< is eval called directly (ECMA-262 v5, 15.1.2.1.1) */ | ||
ECMA_PARSE_STRICT_MODE = (1u << 0), /**< enable strict mode */ | ||
ECMA_PARSE_DIRECT_EVAL = (1u << 1), /**< is eval called directly (ECMA-262 v5, 15.1.2.1.1) */ | ||
ECMA_PARSE_CLASS_CONSTRUCTOR = (1u << 2), /**< the current context is a class constructor */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a class constructor is being parsed.
jerry-core/ecma/base/ecma-globals.h
Outdated
/** | ||
* Set JERRY_CONTEXT (status_flags) top 8 bits to the specified 'opts'. | ||
*/ | ||
#define ECMA_SET_SUPER_EVAL_PARSER_OPTS(base, opts) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think "base" is unnecessary.
*/ | ||
ecma_value_t | ||
ecma_op_create_array_object_by_constructor (const ecma_value_t *arguments_list_p, /**< list of arguments that | ||
* are passed to Array constructor */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indentation is missing.
ecma_op_set_class_context (ecma_object_t *local_env_p, /**< local lexical enviroment */ | ||
ecma_value_t this_binding) /**< 'this' argument's value */ | ||
{ | ||
ecma_string_t *super_this_binding_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_THIS_BINDING); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
class_this_binding
jerry-core/parser/js/byte-code.h
Outdated
/* Class opcodes */ \ | ||
CBC_OPCODE (CBC_EXT_INHERIT_AND_SET_CONSTRUCTOR, CBC_NO_FLAG, 0, \ | ||
VM_OC_CLASS_HERITAGE) \ | ||
CBC_OPCODE (CBC_EXT_SUPER_EVAL, CBC_HAS_BYTE_ARG, 0, \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CBC_EXT_CLASS_EVAL
jerry-core/parser/js/byte-code.h
Outdated
VM_OC_SUPER_CALL | VM_OC_PUT_STACK) \ | ||
CBC_OPCODE (CBC_EXT_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, \ | ||
VM_OC_SUPER_CALL | VM_OC_PUT_BLOCK) \ | ||
CBC_OPCODE (CBC_EXT_PUSH_CLASS_CONSTRUCTOR, CBC_NO_FLAG, 1, \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move after CBC_EXT_INHERIT_AND_SET_CONSTRUCTOR
jerry-core/vm/vm.c
Outdated
ecma_value_t super_prototype_value = ecma_op_object_get_by_magic_id (super_class_p, | ||
LIT_MAGIC_STRING_PROTOTYPE); | ||
|
||
if (!ECMA_IS_VALUE_ERROR (super_prototype_value) && !ecma_is_value_undefined (super_prototype_value)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If not object or null, throw an error.
0ea5c73
to
44729d4
Compare
The patch is updated, depends on #2547. |
3f86596
to
61be3d8
Compare
jerry-core/ecma/base/ecma-globals.h
Outdated
@@ -76,18 +76,25 @@ typedef enum | |||
ECMA_TYPE_DIRECT_STRING = 5, /**< directly encoded string values */ | |||
ECMA_TYPE_ERROR = 7, /**< pointer to description of an error reference (only supported by C API) */ | |||
ECMA_TYPE_POINTER = ECMA_TYPE_ERROR, /**< a generic aligned pointer */ | |||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
ECMA_TYPE_CLASS = ECMA_TYPE_ERROR, /**< special type for class contextes */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ECMA_TYPE_INACCESSIBLE_THIS
jerry-core/ecma/base/ecma-globals.h
Outdated
@@ -170,6 +177,7 @@ enum | |||
* ecma_op_object_find */ | |||
ECMA_VALUE_REGISTER_REF = ECMA_MAKE_VALUE (8), /**< register reference, | |||
* a special "base" value for vm */ | |||
ECMA_VALUE_IMPLICIT_CALL = ECMA_MAKE_VALUE (9), /**< special value for implicit constructor call */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment: bound class constructors
ECMA_VALUE_IMPLICIT_CONSTRUCTOR
|
||
if (ecma_is_value_class (this_binding)) | ||
{ | ||
this_binding -= ECMA_TYPE_CLASS - ECMA_TYPE_OBJECT;; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Double semicolon.
@@ -829,7 +1050,7 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */ | |||
} | |||
|
|||
/* 8. */ | |||
ecma_value_t ret_value; | |||
ecma_value_t ret_value = ECMA_VALUE_UNDEFINED; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this before the break statement.
jerry-core/lit/lit-magic-strings.h
Outdated
@@ -46,6 +46,7 @@ typedef enum | |||
LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_INDEX, /**< [[Index]] property */ | |||
LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_VALUE, /**< [[Values]] property */ | |||
LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REMAINING_ELEMENT, /**< [[RemainingElement]] property */ | |||
LIT_INTERNAL_MAGIC_STRING_CLASS_THIS_BINDING, /**< the this binding of the class constructor */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use internal properties.
/** | ||
* Offset between PARSER_CLASS_CONSTRUCTOR and ECMA_PARSE_CLASS_CONSTRUCTOR | ||
*/ | ||
#define PARSER_CLASS_PARSE_OPTS_OFFSET 18 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(20-2)
@@ -69,6 +69,9 @@ typedef enum | |||
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ | |||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
PARSER_CLASS_CONSTRUCTOR = (1u << 20), /**< a class constructor is parsed */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment about PARSER_CLASS_PARSE_OPTS_OFFSET
b94cce4
to
b1bdb21
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getting very close.
jerry-core/ecma/base/ecma-globals.h
Outdated
ECMA_PARSE_STRICT_MODE = (1 << 0), /**< enable strict mode */ | ||
ECMA_PARSE_DIRECT_EVAL = (1 << 1) /**< is eval called directly (ECMA-262 v5, 15.1.2.1.1) */ | ||
ECMA_PARSE_STRICT_MODE = (1u << 0), /**< enable strict mode */ | ||
ECMA_PARSE_DIRECT_EVAL = (1u << 1), /**< is eval called directly (ECMA-262 v5, 15.1.2.1.1) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment: eval is called directly
@@ -131,6 +134,67 @@ ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of | |||
return ecma_make_object_value (object_p); | |||
} /* ecma_op_create_array_object */ | |||
|
|||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
/** | |||
* Array object creation operation according to the 'constructor' property. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment: Array object creation with custom prototype.
case ECMA_OBJECT_TYPE_BOUND_FUNCTION: | ||
{ | ||
JERRY_ASSERT (!ecma_op_function_has_construct_flag (arguments_list_p)); | ||
ret_value = ecma_op_function_construct (func_obj_p, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would pass the target_function
here. Requires one less check after the recursive call.
uint32_t constructor_super = PARSER_CLASS_CONSTRUCTOR | PARSER_CLASS_HAS_SUPER; | ||
bool is_constructor_super = (context_p->status_flags & constructor_super) == constructor_super; | ||
#else /* CONFIG_DISABLE_ES2015_CLASS */ | ||
bool is_constructor_super = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we do this nicely without introducing a variable?
jerry-core/parser/js/js-parser.c
Outdated
JERRY_ASSERT ((status_flags & PARSER_IS_FUNCTION) | ||
&& (status_flags & PARSER_IS_ARROW_FUNCTION)); | ||
parser_save_context (context_p, &saved_context); | ||
#ifndef CONFIG_DISABLE_ES2015_CLASS | ||
context_p->status_flags |= status_flags | PARSER_ARGUMENTS_NOT_NEEDED | class_has_super; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the uint32_t class_has_super = context_p->status_flags & PARSER_CLASS_HAS_SUPER;
above.
Add context_p->status_flags |= context_p->status_flags & PARSER_CLASS_HAS_SUPER
here if the line above is too long with this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you save the context you lose all of your status flags except the PARSER_IS_STRICT
, so
context_p->status_flags |= context_p->status_flags & PARSER_CLASS_HAS_SUPER
will never add the PARSER_CLASS_HAS_SUPER
flag to the new context.
But we can combine our solutions like:
context_p->status_flags |= saved_context.status_flags & PARSER_CLASS_HAS_SUPER
jerry-core/vm/vm.c
Outdated
|
||
ecma_free_value (result); | ||
|
||
result = ecma_raise_type_error ("Class extends value is not a constructor or null."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Value provided by class extends is not an object or null.
jerry-core/vm/vm.c
Outdated
|
||
frame_ctx_p->lex_env_p = super_env_p; | ||
} | ||
else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems the two code paths do not share code. Would it be a good idea to introduce two vm opcodes for them?
jerry-core/vm/vm.c
Outdated
@@ -1573,6 +1937,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ | |||
ecma_fast_free_value (block_result); | |||
block_result = result; | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this space is needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First set of comments. More may come, I couldn't review all parts of the change yet.
jerry-core/ecma/base/ecma-globals.h
Outdated
@@ -82,12 +82,16 @@ typedef enum | |||
|
|||
/** | |||
* Option flags for script parsing. | |||
* NOTE: The enum members must be kept in sync with parser_general_flags_t |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK, notes are written in a slightly different way in the rest of the code base:
*
* Note:
* text here
jerry-core/jcontext/jcontext.h
Outdated
@@ -109,7 +109,7 @@ struct jerry_context_t | |||
ecma_value_t error_value; /**< currently thrown error value */ | |||
uint32_t lit_magic_string_ex_count; /**< external magic strings count */ | |||
uint32_t jerry_init_flags; /**< run-time configuration flags */ | |||
uint32_t status_flags; /**< run-time flags */ | |||
uint32_t status_flags; /**< run-time flags. NOTE: the top 8 bits are used for passing class parsing options */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That all-caps note is very 'loud'. I'd suggest simply "run-time flags (the top 8 bits are used for passing class parsing options)"
jerry-core/lit/lit-magic-strings.h
Outdated
* Check whether the current magic string is internal magic string | ||
*/ | ||
#define LIT_IS_INTERNAL_MAGIC_STRING(id) ((id) >= LIT_GC_MARK_REQUIRED_MAGIC_STRING__COUNT \ | ||
&& (id) < LIT_MAGIC_STRING__COUNT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This second part of the predicate seems to be a safety check that usually goes into an assert to prevent being a performance hit. Cannot LIT_IS_INTERNAL_MAGIC_STRING
only check for (id) >= LIT_GC_MARK_REQUIRED_MAGIC_STRING__COUNT
? Callers of LIT_IS_INTERNAL_MAGIC_STRING
can have a separate assert for (id) < LIT_MAGIC_STRING__COUNT
, which will then be a no-op for release builds (or LIT_IS_INTERNAL_MAGIC_STRING
can have a different version for debug/release builds, but I think there is no precedent for that in the code base).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is not used by asserts. Live code should be fast.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@akosthekiss Your insight is right about the safety check. The reason of this plus check is that this macro is only used in asserts.
case ECMA_PROPERTY_TYPE_INTERNAL:
{
JERRY_ASSERT (ECMA_PROPERTY_GET_NAME_TYPE (property) == ECMA_DIRECT_STRING_MAGIC
&& LIT_IS_INTERNAL_MAGIC_STRING (property_pair_p->names_cp[index]));
break;
}
default:
{
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_INTERNAL);
/* Must be a native pointer. */
JERRY_ASSERT (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC
&& LIT_IS_INTERNAL_MAGIC_STRING (name_cp));
break;
}
Anyway the property's type is the most significant attribute during the property processing we can not rely on this macro, it's only for safety check.
Therefore I think it's not necessary to modify this macro to support release builds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is only used twice and both times in an assert, is a macro (that can be misused by mistake and thus become a performance hit) justified for this? Can't this check simply be incorporated into the two asserts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, you convinced me.
@@ -25,6 +25,10 @@ | |||
#include "jcontext.h" | |||
#endif /* !CONFIG_DISABLE_ES2015_CLASS && (JERRY_DEBUGGER || JERRY_ENABLE_LINE_INFO) */ | |||
|
|||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
#include "lit-char-helpers.h" | |||
#endif /* !CONFIG_DISABLE_ES2015_CLASS */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note 1: lit-char-helpers.h
is already included some lines above, guarded by CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS
. These could be merged.
Note 2: But what's the point of conditional includes? What harm can the unconditional includes do? I see that other header inclusions are guarded, too, but don't really see why. I'd just write
#include "jcontext.h"
#include "lit-char-helpers.h"
If this causes any problems in this compilation unit in some configuration, then that signals quite a problem somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I followed the #ifdef
guard terminology, but +1 for removing them.
@@ -68,7 +68,11 @@ typedef enum | |||
PARSER_ARROW_PARSE_ARGS = (1u << 19), /**< parse the argument list of an arrow function */ | |||
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ | |||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
PARSER_CLASS_CONSTRUCTOR = (1u << 20), /**< a class constructor is parsed */ | |||
PARSER_CLASS_CONSTRUCTOR = (1u << 20), /**< a class constructor is parsed. NOTE: this value must be kept in | |||
* in sync with ECMA_PARSE_CLASS_CONSTRUCTOR */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it only this enumerator that must be kept in sync with another enumerator? The newly added note at ecma_parse_opts_t
mentions all enumerators in this enum. BTW, what does "in sync" mean in this case? See:
ECMA_PARSE_CLASS_CONSTRUCTOR = (1u << 2), /**< a class constructor is being parsed */
ECMA_PARSE_HAS_SUPER = (1u << 3), /**< the current context has super reference */
ECMA_PARSE_HAS_STATIC_SUPER = (1u << 4), /**< the current context is a static class method */
vs
PARSER_CLASS_CONSTRUCTOR = (1u << 20), /**< a class constructor is parsed */
PARSER_CLASS_HAS_SUPER = (1u << 21) /**< class has super reference */
PARSER_CLASS_STATIC_FUNCTION = (1u << 22), /**< this function is a static class method */
The values are definitely not the same, and the enumerator names are also a bit 'out-of-sync'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just found PARSER_CLASS_PARSE_OPTS_OFFSET
. It should be referenced in the comment (or perhaps in a comment inserted before PARSER_CLASS_CONSTRUCTOR
to emphasise that the following enumerators form a group and have to be treated together).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Static asserts could be used to check this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reference in the comment is a good idea, static assert for the check is already available.
@@ -21,6 +21,8 @@ | |||
#include "jcontext.h" | |||
#endif /* JERRY_DEBUGGER || JERRY_ENABLE_LINE_INFO */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Also a conditional include. Not part of this PR but still not sure why.)
jerry-core/vm/vm-stack.c
Outdated
{ | ||
ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; | ||
frame_ctx_p->lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p); | ||
ecma_deref_object (lex_env_p); | ||
|
||
#ifndef CONFIG_DISABLE_ES2015_CLASS | ||
JERRY_ASSERT (PARSER_WITH_CONTEXT_STACK_ALLOCATION == PARSER_SUPER_CLASS_CONTEXT_STACK_ALLOCATION); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this rather be a static assert? Both PARSER_WITH_CONTEXT_STACK_ALLOCATION
and PARSER_SUPER_CLASS_CONTEXT_STACK_ALLOCATION
are macro-defined constants in byte-code.h
. (And PARSER_SUPER_CLASS_CONTEXT_STACK_ALLOCATION
is not even macro-guarded. So either the (static?) assert should not be guarded or PARSER_SUPER_CLASS_CONTEXT_STACK_ALLOCATION
should be macro-guarded.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I can agree with that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second set of comments. I got 20 of the 30 files covered now.
jerry-core/ecma/base/ecma-helpers.h
Outdated
@@ -148,6 +148,9 @@ bool JERRY_ATTR_CONST ecma_is_value_true (ecma_value_t value); | |||
bool JERRY_ATTR_CONST ecma_is_value_false (ecma_value_t value); | |||
bool JERRY_ATTR_CONST ecma_is_value_found (ecma_value_t value); | |||
bool JERRY_ATTR_CONST ecma_is_value_array_hole (ecma_value_t value); | |||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
bool JERRY_ATTR_CONST ecma_is_value_class (ecma_value_t value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cannot find this function either implemented or used anywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, it's a leftover code!
#include "jcontext.h" | ||
#endif /* JERRY_ENABLE_LINE_INFO */ | ||
#endif /* defined (JERRY_ENABLE_LINE_INFO) || !defined (CONFIG_DISABLE_ES2015_CLASS) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yet another conditional include. I still suggest dropping the guards.
jerry-core/parser/js/js-parser.c
Outdated
@@ -22,6 +22,14 @@ | |||
|
|||
#ifndef JERRY_DISABLE_JS_PARSER | |||
|
|||
JERRY_STATIC_ASSERT ((int) ECMA_PARSE_STRICT_MODE == (int) PARSER_IS_STRICT, | |||
ecma_parse_strict_mode_and_parser_is_strict_are_equal); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK the wording of the static assert 'messages' should contain "must", "must be", "should be", "must not", etc. That's because "xxx_and_yyy_are_equal" is somewhat misleading. If the assert is triggered and this text is printed, it's not really clear what the cause of the error is. (The message could suggest that they are equal, while the real problem is that they aren't.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, I'll rename it.
jerry-core/parser/js/js-parser.c
Outdated
|
||
#ifndef CONFIG_DISABLE_ES2015_CLASS | ||
JERRY_STATIC_ASSERT ((ECMA_PARSE_CLASS_CONSTRUCTOR << PARSER_CLASS_PARSE_OPTS_OFFSET) == PARSER_CLASS_CONSTRUCTOR, | ||
ecma_class_parse_options_can_be_shifted_to_ecma_general_flags); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same static assert message problem here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto.
must_throw ("class B extends A { constructor (a, b) { this.b = b} } \ | ||
var b = new B (1,2);"); | ||
|
||
must_throw ("class B extends A { constructor (a,b) { super.f() } } \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Args should be comma+space-separated. That one extra space is not a big price for readability. Also when calling a function (above, new B (1,2)
). Throughout this file.
} | ||
|
||
class B extends A { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this empty line needed?
} | ||
|
||
var d = new D; | ||
assert (Object.getPrototypeOf(d) == D.prototype); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, this test file is huge. The problem with that is that it's full with asserts and if this test fails, it becomes hard to find which part is problematic. I think it should be possible to split up this file into smaller ones that test fewer functionalities.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about splitting the tests file into:
class-inheritance-early-semantics.js
(must throw part)class-inheritance-main.js
(core functionalities)class-inheritance-builtin-extends.js
(specific behaviour withArray / %Typedarray%
)class-inheritance-mixins.js
(Mix-ins + bound functions)
(Also with the unified style)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good as a start.
@@ -68,7 +68,11 @@ typedef enum | |||
PARSER_ARROW_PARSE_ARGS = (1u << 19), /**< parse the argument list of an arrow function */ | |||
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ | |||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
PARSER_CLASS_CONSTRUCTOR = (1u << 20), /**< a class constructor is parsed */ | |||
PARSER_CLASS_CONSTRUCTOR = (1u << 20), /**< a class constructor is parsed. NOTE: this value must be kept in | |||
* in sync with ECMA_PARSE_CLASS_CONSTRUCTOR */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just found PARSER_CLASS_PARSE_OPTS_OFFSET
. It should be referenced in the comment (or perhaps in a comment inserted before PARSER_CLASS_CONSTRUCTOR
to emphasise that the following enumerators form a group and have to be treated together).
/** | ||
* Mask for get class option bits from ecma_parse_opts_t | ||
*/ | ||
#define PARSER_CLASS_ECMA_PARSE_OPTS_TO_PARSER_OPTS_MASK 0x1C |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be a way to specify a static assert for this, otherwise this will become a fragile hard-coded constant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still thinking on a proper static assert for this...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Third set of comments. Got through all files now.
@@ -24,6 +24,9 @@ | |||
#include "ecma-number-arithmetic.h" | |||
#include "ecma-objects.h" | |||
#include "ecma-objects-general.h" | |||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
#include "ecma-function-object.h" | |||
#endif /* !CONFIG_DISABLE_ES2015_CLASS */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Conditional include, guards to be dropped.
|
||
ecma_deref_object (proto_p); | ||
|
||
ecma_object_t *constructor_prototpye_object_p = ecma_get_object_from_value (constructor_prototype); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: constructor_prototpye_object_p
-> constructor_prototype_object_p
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I didn't notice it.
ecma_free_value (obj_this); | ||
return new_array; | ||
} | ||
#else /* CONFIG_DISABLE_ES2015_CLASS */ | ||
ecma_value_t new_array = ecma_op_create_array_object (0, 0, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's interesting that the old code never checks for error although ecma_op_create_array_object
may raise errors. But only if length was invalid, which is known not to happen for the hard-coded params. A JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array));
might still have its place here to signal that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, an assert never hurts.
@@ -223,7 +223,18 @@ ecma_builtin_array_prototype_object_concat (ecma_value_t this_arg, /**< this arg | |||
ret_value); | |||
|
|||
/* 2. */ | |||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); | |||
ecma_value_t new_array = ecma_op_create_array_object_by_constructor (0, 0, false, obj_p); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First argument is of type ecma_value_t *arguments_list_p
, so NULL
would be a better fit here instead of the 0
. (The old code might also be improved.)
if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) | ||
{ | ||
context_p->last_cbc_opcode = CBC_RETURN_WITH_LITERAL; | ||
} | ||
#endif /* !CONFIG_DISABLE_ES2015_CLASS */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as
#ifndef CONFIG_DISABLE_ES2015_CLASS
if ((context_p->status_flags & constructor_super) != constructor_super)
{
#endif /* !CONFIG_DISABLE_ES2015_CLASS */
if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
{
context_p->last_cbc_opcode = CBC_RETURN_WITH_LITERAL;
}
#ifndef CONFIG_DISABLE_ES2015_CLASS
}
#endif /* !CONFIG_DISABLE_ES2015_CLASS */
or
if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
{
#ifndef CONFIG_DISABLE_ES2015_CLASS
if ((context_p->status_flags & constructor_super) != constructor_super)
{
#endif /* !CONFIG_DISABLE_ES2015_CLASS */
context_p->last_cbc_opcode = CBC_RETURN_WITH_LITERAL;
#ifndef CONFIG_DISABLE_ES2015_CLASS
}
#endif /* !CONFIG_DISABLE_ES2015_CLASS */
}
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really don't like such constructs. So hard to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I don't like copy-paste cloning. And the above pattern makes the code more future-proof in the sense that should we ever change the config macro infrastructure from #ifdef ENABLE
/#ifndef DISABLE
to #if 1
(i.e., making decisions not based on whether a macro is defined but based on its value) then the above pattern can be easily recognized and simplified into and if
with a simple predicate:
if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL
&& (!CONFIG_ES2015_CLASS || (context_p->status_flags & constructor_super) != constructor_super))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the advantages/disadvantages of both styles. How about summoning @LaszloLango and @robertsipka to ask their opinions?
The question is:
#ifndef CONFIG_DISABLE_ES2015_XXX
if (// New condition)
{
// New code path
}
else
{
// Old code path
}
#else /* CONFIG_DISABLE_ES2015_XXX */
// Old code path
#endif /* !CONFIG_DISABLE_ES2015_XXX */
vs.
#ifndef CONFIG_DISABLE_ES2015_XXX
if (// New condition)
{
// New code path
}
else
{
#endif /* !CONFIG_DISABLE_ES2015_XXX */
// Old code path
#ifndef CONFIG_DISABLE_ES2015_XXX
}
#endif /* !CONFIG_DISABLE_ES2015_XXX */
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer the second one without code duplication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first one is easier to read, but eliminate the code duplication has priority (+1 for the second).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the answers, I'll use the 2nd style.
@@ -1970,22 +2036,59 @@ parser_parse_statements (parser_context_t *context_p) /**< context */ | |||
} | |||
|
|||
lexer_next_token (context_p); | |||
|
|||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
uint32_t constructor_super = PARSER_CLASS_CONSTRUCTOR | PARSER_CLASS_HAS_SUPER; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make this const
so that it doesn't get modified by mistake, and move it before the switch so that it doesn't have to be defined multiple times (as around line 2194). Or make this something like a #define PARSER_CLASS_CONSTRUCTOR_SUPER (PARSER_CLASS_CONSTRUCTOR | PARSER_CLASS_HAS_SUPER)
if the value is used multiple times, as in js-parser.c
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#define PARSER_CLASS_CONSTRUCTOR_SUPER (PARSER_CLASS_CONSTRUCTOR | PARSER_CLASS_HAS_SUPER)
is a good idea.
@akosthekiss Thanks for the deep review. Let me apply a part of your suggestions first (I mean the trivial ones) then talk about the rest. |
8b6584b
to
c54f440
Compare
Patch is updated to see what have been resolved. Still working on it. |
f72e2f8
to
61b4070
Compare
@akosthekiss The patch has been updated! |
ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false); | ||
#endif /* !CONFIG_DISABLE_ES2015_CLASS */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This addition is not consistent with the previous approaches: there is no assertion check for no error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The diff does not show it but there was an already existing assert for it in the next line. Anyway, I move it up to the else/endif block
.
ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false); | ||
#endif /* !CONFIG_DISABLE_ES2015_CLASS */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
this.g = super.f; | ||
this.h = this.f; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it intentional that A
and B
are redefined over and over again in the same test file with slightly different content? All redefinitions seem to be potential test file splitting points.
must_throw ("class A extends { constructor () { super () } }"); | ||
|
||
class B extends A { | ||
constructor (a,b) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add space after comma
} | ||
} | ||
var b = new B (1, 2); | ||
assert (b.g ()()() === 5); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to me that these two checks could be merged. Constructors are the same (assert can be kept), object is instantiated the same way in both cases. Only the second g ()
has to be renamed (e.g., to h ()
), and then this assert has to be rewritten as b.h ()()() === 5
. If I get it right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, let's merge them.
|
||
var b = new B (); | ||
assert (b.f () === 1) | ||
assert (b.g () === 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
potential splitting point? (independent tests before and after)
} | ||
} | ||
|
||
new C ().foo () |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
potential splitting point?
61b4070
to
fcebdfc
Compare
@akosthekiss Your suggestions have been applied! |
class A { | ||
constructor () { | ||
this.a = 5; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
strange indentation
assert (b.f === 5); | ||
assert (b.length === 3); | ||
|
||
class A extends Array { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the redefinition of A intentional here?
|
||
var b = new B (); | ||
assert (b.f () === 1) | ||
assert (b.g () === 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
splitting point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let it be.
fcebdfc
to
a5d4211
Compare
|
||
assert (D.a () === 6); | ||
|
||
class A extends Array { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like a leftover in this test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Thanks.
* limitations under the License. | ||
*/ | ||
|
||
var g = Array.bind (0, 1, 2, 3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicking: why is this test file named "bounds"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason is that implicit class constructors are really similar to bound functions. But let's rename it only to -bound.js
, hence it only includes one test case.
a5d4211
to
481f83b
Compare
This patch is the second milestone of the implementation of this new language element. Supported: - Single class inheritance - Functionality of 'super' keyword - Implicit constructor in class heritage - Specific behaviour while extending with the built-in 'Array' or '%TypedArray%' object - Abstract subclasses (Mix-ins) JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik [email protected]
481f83b
to
7eac228
Compare
@akosthekiss The PR is updated as you suggested. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. That was quite some work.
This patch is the second milestone of the implementation of this new language element. Supported: - Single class inheritance - Functionality of 'super' keyword - Implicit constructor in class heritage - Specific behaviour while extending with the built-in 'Array' or '%TypedArray%' object - Abstract subclasses (Mix-ins) JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik [email protected]
This patch is the second milestone of the implementation of this new language element. Supported: - Single class inheritance - Functionality of 'super' keyword - Implicit constructor in class heritage - Specific behaviour while extending with the built-in 'Array' or '%TypedArray%' object - Abstract subclasses (Mix-ins) JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik [email protected]
This patch is the second milestone of the implementation of this new language element. Supported: - Single class inheritance - Functionality of 'super' keyword - Implicit constructor in class heritage - Specific behaviour while extending with the built-in 'Array' or '%TypedArray%' object - Abstract subclasses (Mix-ins) JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik [email protected]
Picked from upstream jerryscript-project/jerryscript#2439
Refs: jerryscript-project/jerryscript#2431 Refs: jerryscript-project/jerryscript#2496 Refs: jerryscript-project/jerryscript#2485 Refs: jerryscript-project/jerryscript#2530 Refs: jerryscript-project/jerryscript#2547 Refs: jerryscript-project/jerryscript#2436 Refs: jerryscript-project/jerryscript#2467 Refs: jerryscript-project/jerryscript#2481 Refs: jerryscript-project/jerryscript#2408 Refs: jerryscript-project/jerryscript#2430 Refs: jerryscript-project/jerryscript#2439 Refs: jerryscript-project/jerryscript#2588
This patch is the second milestone of the implementation of this new language element.
Supported:
JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik [email protected]