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) \
CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_SETTER, CBC_HAS_LITERAL_ARG, -1, \
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. */ \
CBC_OPCODE (CBC_EXT_PUSH_NAMED_CLASS_ENV, CBC_HAS_LITERAL_ARG, 1, \
+17 -6
View File
@@ -1041,9 +1041,12 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */
default:
{
#if ENABLED (JERRY_ES2015)
if ((context_p->token.lit_location.type == LEXER_IDENT_LITERAL
|| context_p->token.lit_location.type == LEXER_STRING_LITERAL)
&& lexer_compare_literal_to_string (context_p, "__proto__", 9))
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)
&& 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)
{
@@ -1068,7 +1071,7 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */
lexer_next_token (context_p);
#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);
@@ -1078,8 +1081,8 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */
break;
}
if (context_p->token.type == LEXER_RIGHT_BRACE
|| context_p->token.type == LEXER_COMMA)
if ((context_p->token.type == LEXER_RIGHT_BRACE || context_p->token.type == LEXER_COMMA)
&& !is_proto)
{
parser_reparse_as_common_identifier (context_p, start_line, start_column);
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);
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)
{
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))
{
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)
@@ -1367,6 +1358,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
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:
{
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);
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:
{
/* Swap values. */
@@ -1585,14 +1593,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
/* FALLTHRU */
}
#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:
{
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;
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) */
const int index = -1;
#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_REQUIRE_OBJECT_COERCIBLE,/**< RequireObjectCoercible opretaion */
VM_OC_ASSIGN_SUPER, /**< assign super reference */
VM_OC_SET__PROTO__, /**< set prototpe when __proto__: form is used */
#endif /* ENABLED (JERRY_ES2015) */
VM_OC_NONE, /**< a special opcode for unsupported byte codes */
} 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_REQUIRE_OBJECT_COERCIBLE = VM_OC_NONE,/**< RequireObjectCoercible opretaion */
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) */
VM_OC_UNUSED = VM_OC_NONE /**< placeholder if the list is empty */
+33 -2
View File
@@ -26,7 +26,7 @@ var o = {};
o.__proto__ = Array.prototype;
assert(o instanceof Array);
var obj = Object.create(null)
var obj = Object.create(null)
p = {};
obj.__proto__ = p;
assert(Object.getPrototypeOf(obj) !== p);
@@ -54,5 +54,36 @@ try {
assert(e instanceof TypeError);
}
var o2 = { ["__proto__"] : null };
var 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__));