Fix __proto__ parsing in object literals (#3704)

Co-authored-by: Rafal Walczyna r.walczyna@samsung.com
JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
Robert Fancsik
2020-05-04 14:49:15 +02:00
committed by GitHub
parent 14cea9c1ec
commit 40a9f27314
5 changed files with 71 additions and 32 deletions
+2
View File
@@ -604,6 +604,8 @@
VM_OC_SET_GETTER | VM_OC_GET_STACK_LITERAL) \ VM_OC_SET_GETTER | VM_OC_GET_STACK_LITERAL) \
CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_SETTER, CBC_HAS_LITERAL_ARG, -1, \ CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_SETTER, CBC_HAS_LITERAL_ARG, -1, \
VM_OC_SET_SETTER | VM_OC_GET_STACK_LITERAL) \ VM_OC_SET_SETTER | VM_OC_GET_STACK_LITERAL) \
CBC_OPCODE (CBC_EXT_SET__PROTO__, CBC_NO_FLAG, -1, \
VM_OC_SET__PROTO__ | VM_OC_GET_STACK) \
\ \
/* Class related opcodes. */ \ /* Class related opcodes. */ \
CBC_OPCODE (CBC_EXT_PUSH_NAMED_CLASS_ENV, CBC_HAS_LITERAL_ARG, 1, \ CBC_OPCODE (CBC_EXT_PUSH_NAMED_CLASS_ENV, CBC_HAS_LITERAL_ARG, 1, \
+16 -5
View File
@@ -1041,9 +1041,12 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */
default: default:
{ {
#if ENABLED (JERRY_ES2015) #if ENABLED (JERRY_ES2015)
if ((context_p->token.lit_location.type == LEXER_IDENT_LITERAL const lexer_lit_location_t *literal_p = (const lexer_lit_location_t *) context_p->lit_object.literal_p;
bool is_proto = ((context_p->token.lit_location.type == LEXER_IDENT_LITERAL
|| context_p->token.lit_location.type == LEXER_STRING_LITERAL) || context_p->token.lit_location.type == LEXER_STRING_LITERAL)
&& lexer_compare_literal_to_string (context_p, "__proto__", 9)) && lexer_compare_identifier_to_string (literal_p, (uint8_t *) "__proto__", 9)
&& lexer_check_next_character (context_p, LIT_CHAR_COLON));
if (is_proto)
{ {
if (proto_seen) if (proto_seen)
{ {
@@ -1068,7 +1071,7 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */
lexer_next_token (context_p); lexer_next_token (context_p);
#if ENABLED (JERRY_ES2015) #if ENABLED (JERRY_ES2015)
if (context_p->token.type == LEXER_LEFT_PAREN) if (context_p->token.type == LEXER_LEFT_PAREN && !is_proto)
{ {
parser_parse_object_method (context_p); parser_parse_object_method (context_p);
@@ -1078,8 +1081,8 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */
break; break;
} }
if (context_p->token.type == LEXER_RIGHT_BRACE if ((context_p->token.type == LEXER_RIGHT_BRACE || context_p->token.type == LEXER_COMMA)
|| context_p->token.type == LEXER_COMMA) && !is_proto)
{ {
parser_reparse_as_common_identifier (context_p, start_line, start_column); parser_reparse_as_common_identifier (context_p, start_line, start_column);
parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
@@ -1100,6 +1103,14 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */
lexer_next_token (context_p); lexer_next_token (context_p);
parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
#if ENABLED (JERRY_ES2015)
if (is_proto)
{
parser_emit_cbc_ext (context_p, CBC_EXT_SET__PROTO__);
break;
}
#endif /* ENABLED (JERRY_ES2015) */
if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
{ {
context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY; context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY;
+17 -24
View File
@@ -92,15 +92,6 @@ vm_op_get_value (ecma_value_t object, /**< base object */
else if (ecma_is_value_string (property)) else if (ecma_is_value_string (property))
{ {
property_name_p = ecma_get_string_from_value (property); property_name_p = ecma_get_string_from_value (property);
#if ENABLED (JERRY_ES2015)
if (JERRY_UNLIKELY (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING__PROTO__)))
{
ecma_object_t *obj_p = ecma_get_object_from_value (object);
return ecma_builtin_object_object_get_prototype_of (obj_p);
}
#endif /* ENABLED (JERRY_ES2015) */
} }
#if ENABLED (JERRY_ES2015) #if ENABLED (JERRY_ES2015)
@@ -1367,6 +1358,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
continue; continue;
} }
#if ENABLED (JERRY_SNAPSHOT_EXEC)
case VM_OC_SET_BYTECODE_PTR:
{
memcpy (&byte_code_p, byte_code_p++, sizeof (uint8_t *));
frame_ctx_p->byte_code_start_p = byte_code_p;
continue;
}
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
case VM_OC_INIT_LOCAL: case VM_OC_INIT_LOCAL:
{ {
uint32_t literal_index, value_index; uint32_t literal_index, value_index;
@@ -1576,6 +1575,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
frame_ctx_p->lex_env_p = ecma_clone_decl_lexical_environment (frame_ctx_p->lex_env_p, copy_values); frame_ctx_p->lex_env_p = ecma_clone_decl_lexical_environment (frame_ctx_p->lex_env_p, copy_values);
continue; continue;
} }
case VM_OC_SET__PROTO__:
{
result = ecma_builtin_object_object_set_proto (stack_top_p[-1], left_value);
if (ECMA_IS_VALUE_ERROR (result))
{
goto error;
}
goto free_left_value;
}
case VM_OC_SET_COMPUTED_PROPERTY: case VM_OC_SET_COMPUTED_PROPERTY:
{ {
/* Swap values. */ /* Swap values. */
@@ -1585,14 +1593,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
/* FALLTHRU */ /* FALLTHRU */
} }
#endif /* ENABLED (JERRY_ES2015) */ #endif /* ENABLED (JERRY_ES2015) */
#if ENABLED (JERRY_SNAPSHOT_EXEC)
case VM_OC_SET_BYTECODE_PTR:
{
memcpy (&byte_code_p, byte_code_p++, sizeof (uint8_t *));
frame_ctx_p->byte_code_start_p = byte_code_p;
continue;
}
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
case VM_OC_SET_PROPERTY: case VM_OC_SET_PROPERTY:
{ {
JERRY_STATIC_ASSERT (VM_OC_NON_STATIC_FLAG == VM_OC_BACKWARD_BRANCH, JERRY_STATIC_ASSERT (VM_OC_NON_STATIC_FLAG == VM_OC_BACKWARD_BRANCH,
@@ -1617,13 +1617,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
} }
const int index = (int) (opcode_data >> VM_OC_NON_STATIC_SHIFT) - 2; const int index = (int) (opcode_data >> VM_OC_NON_STATIC_SHIFT) - 2;
if (JERRY_UNLIKELY (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING__PROTO__)))
{
result = ecma_builtin_object_object_set_proto (stack_top_p[index], left_value);
ecma_deref_ecma_string (prop_name_p);
goto free_both_values;
}
#else /* !ENABLED (JERRY_ES2015) */ #else /* !ENABLED (JERRY_ES2015) */
const int index = -1; const int index = -1;
#endif /* ENABLED (JERRY_ES2015) */ #endif /* ENABLED (JERRY_ES2015) */
+2
View File
@@ -271,6 +271,7 @@ typedef enum
VM_OC_PUSH_NEW_TARGET, /**< push new.target onto the stack */ VM_OC_PUSH_NEW_TARGET, /**< push new.target onto the stack */
VM_OC_REQUIRE_OBJECT_COERCIBLE,/**< RequireObjectCoercible opretaion */ VM_OC_REQUIRE_OBJECT_COERCIBLE,/**< RequireObjectCoercible opretaion */
VM_OC_ASSIGN_SUPER, /**< assign super reference */ VM_OC_ASSIGN_SUPER, /**< assign super reference */
VM_OC_SET__PROTO__, /**< set prototpe when __proto__: form is used */
#endif /* ENABLED (JERRY_ES2015) */ #endif /* ENABLED (JERRY_ES2015) */
VM_OC_NONE, /**< a special opcode for unsupported byte codes */ VM_OC_NONE, /**< a special opcode for unsupported byte codes */
} vm_oc_types; } vm_oc_types;
@@ -333,6 +334,7 @@ typedef enum
VM_OC_PUSH_NEW_TARGET = VM_OC_NONE, /**< push new.target onto the stack */ VM_OC_PUSH_NEW_TARGET = VM_OC_NONE, /**< push new.target onto the stack */
VM_OC_REQUIRE_OBJECT_COERCIBLE = VM_OC_NONE,/**< RequireObjectCoercible opretaion */ VM_OC_REQUIRE_OBJECT_COERCIBLE = VM_OC_NONE,/**< RequireObjectCoercible opretaion */
VM_OC_ASSIGN_SUPER = VM_OC_NONE, /**< assign super reference */ VM_OC_ASSIGN_SUPER = VM_OC_NONE, /**< assign super reference */
VM_OC_SET__PROTO__ = VM_OC_NONE, /**< set prototpe when __proto__: form is used */
#endif /* !ENABLED (JERRY_ES2015) */ #endif /* !ENABLED (JERRY_ES2015) */
VM_OC_UNUSED = VM_OC_NONE /**< placeholder if the list is empty */ VM_OC_UNUSED = VM_OC_NONE /**< placeholder if the list is empty */
@@ -56,3 +56,34 @@ try {
var o2 = { ["__proto__"] : null }; var o2 = { ["__proto__"] : null };
assert(o2.__proto__ === null); assert(o2.__proto__ === null);
assert(Object.getPrototypeOf(o2) === Object.prototype);
var o3 = { __proto__ : null };
assert(o3.__proto__ === undefined);
assert(Object.getPrototypeOf(o3) === null);
var o4 = { "__proto__" : null };
assert(o4.__proto__ === undefined);
assert(Object.getPrototypeOf(o4) === null);
var __proto__ = [];
var o5 = { __proto__ };
assert(o5.__proto__ === __proto__);
assert(Object.getPrototypeOf(o5) === Object.prototype);
var o6 = { __proto__() { return "42" } };
assert(o6.__proto__() === "42");
assert(Object.getPrototypeOf(o6) === Object.prototype);
var o7 = { __\u0070r\u006ft\u006f__: null };
assert(o7.__proto__ === undefined);
assert(Object.getPrototypeOf(o7) === null);
var o8 = { };
o8.__proto__ = Array.prototype;
assert(Object.getPrototypeOf(o8) === Array.prototype);
var str1 = '{"__proto__": [] }';
var obj1 = JSON.parse(str1);
assert(Object.getPrototypeOf(obj1) === Object.prototype);
assert(Array.isArray(obj1.__proto__));