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:
@@ -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, \
|
||||||
|
|||||||
@@ -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
@@ -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) */
|
||||||
|
|||||||
@@ -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__));
|
||||||
|
|||||||
Reference in New Issue
Block a user