-
Notifications
You must be signed in to change notification settings - Fork 684
Implement ES2015 class feature (part I.) #2404
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
Conversation
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 worry about as snapshots, what happens if a snapshot has classes and it is executed by a jerry without snapshots.
@@ -690,6 +701,10 @@ ecma_op_function_construct_simple_or_external (ecma_object_t *func_obj_p, /**< F | |||
arguments_list_len), | |||
ret_value); | |||
|
|||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
JERRY_CONTEXT (class_invoked_with_new) = 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.
Who sets this value to false if ecma_op_function_call
throws an error? Using a global value is risky since it always finds way to escape :(
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 can be improved after #2414 lands.
jerry-core/parser/js/byte-code.h
Outdated
@@ -549,6 +549,12 @@ | |||
VM_OC_RESOURCE_NAME) \ | |||
CBC_OPCODE (CBC_EXT_LINE, CBC_NO_FLAG, 0, \ | |||
VM_OC_LINE) \ | |||
CBC_OPCODE (CBC_EXT_SET_UP_PROPERTY, CBC_HAS_LITERAL_ARG, -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.
setup property :)
I would rather use CBC_EXT_SET_STATIC_PROPERTY since it is only used by static functions.
jerry-core/parser/js/byte-code.h
Outdated
@@ -665,6 +671,9 @@ typedef enum | |||
CBC_CODE_FLAGS_ARROW_FUNCTION = (1u << 7), /**< this function is an arrow function */ | |||
CBC_CODE_FLAGS_STATIC_FUNCTION = (1u << 8), /**< this function is a static snapshot function */ | |||
CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 9), /**< this function should be ignored by debugger */ | |||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
CBC_CODE_FLAGS_CLASS_CONSTRUCTOR = (1u << 10), /**< this function 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.
I would just use CBC_CODE_FLAGS_CONSTRUCTOR since we might use it later for other purposes.
jerry-core/parser/js/js-lexer.h
Outdated
*/ | ||
static const lexer_lit_location_t lexer_get_literal = | ||
{ | ||
(const uint8_t *) "get", 3, LEXER_IDENT_LITERAL, 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.
I think get and set are already there.
jerry-core/parser/js/js-lexer.c
Outdated
@@ -2238,6 +2259,8 @@ static const lexer_lit_location_t lexer_set_literal = | |||
(const uint8_t *) "set", 3, LEXER_IDENT_LITERAL, 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.
Just keep these for classes.
jerry-core/parser/js/js-lexer.c
Outdated
@@ -531,7 +541,7 @@ lexer_parse_identifier (parser_context_t *context_p, /**< context */ | |||
{ | |||
if (keyword_p->type >= LEXER_FIRST_FUTURE_STRICT_RESERVED_WORD) | |||
{ | |||
if (context_p->status_flags & PARSER_IS_STRICT) | |||
if (context_p->status_flags & PARSER_IS_STRICT && !LEXER_INSIDE_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 have a feeling we should not require this.
jerry-core/parser/js/js-lexer.c
Outdated
lexer_skip_spaces (context_p); | ||
|
||
if (context_p->source_p < context_p->source_end_p | ||
&& context_p->source_p[0] != LIT_CHAR_COLON) |
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 is the purpose of this check. colons are allowed in classes?
|
||
while (true) | ||
{ | ||
if (!is_static) |
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 function cannot be static?
jerry-core/vm/vm.c
Outdated
@@ -1046,8 +1046,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ | |||
continue; | |||
} | |||
case VM_OC_SET_PROPERTY: | |||
case VM_OC_SET_UP_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.
Add a define around this, so this byte code is not executed when the feature is disabled.
The patch is updated based on your thoughts except the class invoking part. I'm looking for a better solution to handle this problem. |
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 patch, only some minor things remained.
#ifndef CONFIG_DISABLE_ES2015_CLASS | ||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_CONSTRUCTOR) | ||
{ | ||
globals_p->class_found = true; |
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 is not necessary true. However I would not add another flag for classes at the moment, so keep this code.
jerry-core/parser/js/js-lexer.c
Outdated
@@ -2231,6 +2250,15 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */ | |||
{ | |||
lexer_skip_spaces (context_p); | |||
|
|||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
/* Skip empty statements */ | |||
while (context_p->status_flags & PARSER_IS_CLASS && *context_p->source_p == LIT_CHAR_SEMICOLON) |
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 brackets around the and
operation.
jerry-core/parser/js/js-lexer.c
Outdated
if (!must_be_identifier | ||
&& context_p->token.lit_location.length == 6 | ||
&& (context_p->status_flags & PARSER_IS_CLASS) | ||
&& lexer_compare_raw_identifier_to_current (context_p, "static", 6)) |
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.
Check (context_p->status_flags & PARSER_IS_CLASS)
first.
jerry-core/parser/js/js-lexer.c
Outdated
@@ -2297,6 +2335,15 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */ | |||
} | |||
} | |||
|
|||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
if (context_p->status_flags & PARSER_IS_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.
Brackets again.
break; | ||
} | ||
#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.
Cannot we return early form this function? Or not even call it?
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, calling it is unnecessary.
|
||
if (type == LEXER_RIGHT_BRACE && stack_top == SCAN_STACK_HEAD) | ||
{ | ||
mode = SCAN_MODE_STATEMENT; |
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.
Cant be an 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.
True, it can.
} | ||
case PARSER_ERR_CLASS_STATIC_PROPERTY_NAME_PROTOTYPE: | ||
{ | ||
return "Classes may not have a static property named '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.
called prototype
jerry-core/parser/js/js-parser.c
Outdated
} | ||
else | ||
{ | ||
JERRY_DEBUG_MSG ("\n--- Function parsing start ---\n\n"); |
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.
Does it look better with a ?:
or the line is too long?
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 looks better but the lines are too long :/
jerry-core/vm/vm.c
Outdated
JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE); | ||
#ifndef CONFIG_DISABLE_ES2015_CLASS | ||
opfunc_set_accessor (VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_SET_GETTER, | ||
stack_top_p[(byte_code_start_p[1] > CBC_EXT_SET_SETTER) ? -2 : -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.
I would use a const int index
just like above instead of duplicating the code.
jerry-core/vm/vm.c
Outdated
@@ -1047,7 +1047,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ | |||
} | |||
case VM_OC_SET_PROPERTY: | |||
{ | |||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
const int index = (byte_code_start_p[0] == CBC_EXT_OPCODE) ? -2 : -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.
Just create a const int index = - 1
and use the index for accessing the stack top.
b20b452
to
523148c
Compare
jerry-core/parser/js/js-lexer.c
Outdated
&& !is_static_method | ||
&& lexer_compare_raw_identifier_to_current (context_p, "constructor", 11)) | ||
{ | ||
context_p->status_flags |= PARSER_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.
It would be good to introduce a virtual token here.
|
||
while (true) | ||
{ | ||
lexer_expect_object_literal_id (context_p, 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.
Add a skip empty semicolons here (if not static).
@@ -2297,6 +2338,16 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */ | |||
} | |||
} | |||
|
|||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
if ((context_p->status_flags & PARSER_IS_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.
add !must_be_identifier
* Parse class as an object literal. | ||
*/ | ||
void | ||
parser_parse_class_literal (parser_context_t *context_p, /**< 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.
Make this static!
break; | ||
} | ||
|
||
if (type == LEXER_RIGHT_BRACE && stack_top == SCAN_STACK_HEAD) |
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.
switch(1) { default: (class A{} % 1) }
|
||
parser_emit_cbc_literal (context_p, CBC_SET_PROPERTY, context_p->lit_object.index); | ||
|
||
if (is_statement && class_ident_index != PARSER_MAXIMUM_NUMBER_OF_LITERALS) |
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_ident_index != PARSER_MAXIMUM_NUMBER_OF_LITERALS
unnecessary
jerry-core/parser/js/js-parser.c
Outdated
@@ -2596,7 +2646,18 @@ parser_parse_function (parser_context_t *context_p, /**< context */ | |||
#ifdef PARSER_DUMP_BYTE_CODE | |||
if (context_p->is_show_opcodes) | |||
{ | |||
#ifndef CONFIG_DISABLE_ES2015_CLASS | |||
if (context_p->status_flags & PARSER_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.
Bool value
const int index = (byte_code_start_p[0] == CBC_EXT_OPCODE) ? -2 : -1; | ||
#else | ||
const int index = -1; | ||
#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.
Newline after.
const int index = (byte_code_start_p[1] > CBC_EXT_SET_SETTER) ? -2 : -1; | ||
#else | ||
const int index = -1; | ||
#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.
@zherczeg Thanks for the reviews, the PR is updated. |
jerry-core/parser/js/js-parser.c
Outdated
(is_constructor ? JERRY_DEBUG_MSG ("\n--- Class constructor parsing start ---\n\n") | ||
: JERRY_DEBUG_MSG ("\n--- Function parsing start ---\n\n")); | ||
|
||
#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.
JERRY_DEBUG_MSG (is_constructor ? "\n--- Class constructor parsing start ---\n\n"
: "\n--- Function parsing start ---\n\n");
Remove newline after it.
jerry-core/parser/js/js-parser.c
Outdated
bool is_constructor = context_p->status_flags & PARSER_CLASS_CONSTRUCTOR; | ||
(is_constructor ? JERRY_DEBUG_MSG ("\n--- Class constructor parsing end ---\n\n") | ||
: JERRY_DEBUG_MSG ("\n--- Function parsing end ---\n\n")); | ||
#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.
Ditto.
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
/* Class expression may contain an identifier. */ | ||
if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) | ||
{ | ||
//NOTE: If 'Function.name' will be supported, the current literal object must be set to 'name' 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.
/* NOTE: If 'Function.name' will be supported, the current literal object must be set to 'name' 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.
Good catch, I haven't noticed it.
This patch is the first milestone of the implementation of this new language element. Currently supported: - Class statement - Class expression - Static methods JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik [email protected]
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
This includes the following syntax: - Class statement. - Class expression. - Static methods. Author: Robert Fancsik <[email protected]> PR-URL: jerryscript-project/jerryscript#2404
This includes the following syntax: - Class statement. - Class expression. - Static methods. Author: Robert Fancsik <[email protected]> PR-URL: jerryscript-project/jerryscript#2404
This patch is the first milestone of the implementation of this new language element.
Currently supported:
JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik [email protected]