Fix super property assignment for namedaccessor properties (#3654)
Tha patch also updates the [[Put]] internal method with the new steps from the ES6 standard. JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
@@ -1132,12 +1132,87 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */
|
|||||||
is_throw);
|
is_throw);
|
||||||
} /* ecma_op_object_put */
|
} /* ecma_op_object_put */
|
||||||
|
|
||||||
|
#if ENABLED (JERRY_ES2015)
|
||||||
|
/**
|
||||||
|
* [[Set]] ( P, V, Receiver) operation part for ordinary objects
|
||||||
|
*
|
||||||
|
* See also: ECMAScript v6, 9.19.9
|
||||||
|
*
|
||||||
|
* @return ecma value
|
||||||
|
* The returned value must be freed with ecma_free_value.
|
||||||
|
*/
|
||||||
|
static ecma_value_t
|
||||||
|
ecma_op_object_put_apply_receiver (ecma_value_t receiver, /**< receiver */
|
||||||
|
ecma_string_t *property_name_p, /**< property name */
|
||||||
|
ecma_value_t value, /**< value to set */
|
||||||
|
bool is_throw) /**< flag that controls failure handling */
|
||||||
|
{
|
||||||
|
/* 5.b */
|
||||||
|
if (!ecma_is_value_object (receiver))
|
||||||
|
{
|
||||||
|
return ecma_reject (is_throw);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_object_t *receiver_obj_p = ecma_get_object_from_value (receiver);
|
||||||
|
|
||||||
|
ecma_property_descriptor_t prop_desc;
|
||||||
|
/* 5.c */
|
||||||
|
ecma_value_t status = ecma_op_object_get_own_property_descriptor (receiver_obj_p,
|
||||||
|
property_name_p,
|
||||||
|
&prop_desc);
|
||||||
|
|
||||||
|
/* 5.d */
|
||||||
|
if (ECMA_IS_VALUE_ERROR (status))
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 5.e */
|
||||||
|
if (ecma_is_value_true (status))
|
||||||
|
{
|
||||||
|
ecma_value_t result;
|
||||||
|
|
||||||
|
/* 5.e.i - 5.e.ii */
|
||||||
|
if (prop_desc.flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED)
|
||||||
|
|| !(prop_desc.flags & ECMA_PROP_IS_WRITABLE))
|
||||||
|
{
|
||||||
|
result = ecma_reject (is_throw);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* 5.e.iii */
|
||||||
|
JERRY_ASSERT (prop_desc.flags & ECMA_PROP_IS_VALUE_DEFINED);
|
||||||
|
ecma_free_value (prop_desc.value);
|
||||||
|
prop_desc.value = ecma_copy_value (value);
|
||||||
|
|
||||||
|
/* 5.e.iv */
|
||||||
|
result = ecma_op_object_define_own_property (receiver_obj_p, property_name_p, &prop_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_free_property_descriptor (&prop_desc);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/* 5.f.i */
|
||||||
|
ecma_property_value_t *new_prop_value_p;
|
||||||
|
new_prop_value_p = ecma_create_named_data_property (receiver_obj_p,
|
||||||
|
property_name_p,
|
||||||
|
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
|
||||||
|
NULL);
|
||||||
|
JERRY_ASSERT (ecma_is_value_undefined (new_prop_value_p->value));
|
||||||
|
new_prop_value_p->value = ecma_copy_value_if_not_object (value);
|
||||||
|
|
||||||
|
return ECMA_VALUE_TRUE;
|
||||||
|
} /* ecma_op_object_put_apply_receiver */
|
||||||
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [[Put]] ecma general object's operation with given receiver
|
* [[Put]] ecma general object's operation with given receiver
|
||||||
*
|
*
|
||||||
* See also:
|
* See also:
|
||||||
* ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
|
* ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
|
||||||
* ECMA-262 v5, 8.12.5
|
* ECMA-262 v5, 8.12.5
|
||||||
|
* ECMA-262 v6, 9.1.9
|
||||||
* Also incorporates [[CanPut]] ECMA-262 v5, 8.12.4
|
* Also incorporates [[CanPut]] ECMA-262 v5, 8.12.4
|
||||||
*
|
*
|
||||||
* @return ecma value
|
* @return ecma value
|
||||||
@@ -1361,6 +1436,13 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */
|
|||||||
{
|
{
|
||||||
if (ecma_is_property_writable (*property_p))
|
if (ecma_is_property_writable (*property_p))
|
||||||
{
|
{
|
||||||
|
#if ENABLED (JERRY_ES2015)
|
||||||
|
if (ecma_make_object_value (object_p) != receiver)
|
||||||
|
{
|
||||||
|
return ecma_op_object_put_apply_receiver (receiver, property_name_p, value, is_throw);
|
||||||
|
}
|
||||||
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
|
|
||||||
/* There is no need for special casing arrays here because changing the
|
/* There is no need for special casing arrays here because changing the
|
||||||
* value of an existing property never changes the length of an array. */
|
* value of an existing property never changes the length of an array. */
|
||||||
ecma_named_data_property_assign_value (object_p,
|
ecma_named_data_property_assign_value (object_p,
|
||||||
@@ -1389,6 +1471,17 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */
|
|||||||
ecma_property_ref_t property_ref = { NULL };
|
ecma_property_ref_t property_ref = { NULL };
|
||||||
ecma_object_t *proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp);
|
ecma_object_t *proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp);
|
||||||
|
|
||||||
|
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
|
||||||
|
if (ECMA_OBJECT_IS_PROXY (proto_p))
|
||||||
|
{
|
||||||
|
return ecma_op_object_put_with_receiver (proto_p,
|
||||||
|
property_name_p,
|
||||||
|
value,
|
||||||
|
receiver,
|
||||||
|
is_throw);
|
||||||
|
}
|
||||||
|
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
|
||||||
|
|
||||||
ecma_property_t inherited_property = ecma_op_object_get_property (proto_p,
|
ecma_property_t inherited_property = ecma_op_object_get_property (proto_p,
|
||||||
property_name_p,
|
property_name_p,
|
||||||
&property_ref,
|
&property_ref,
|
||||||
@@ -1445,6 +1538,10 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLED (JERRY_ES2015)
|
||||||
|
return ecma_op_object_put_apply_receiver (receiver, property_name_p, value, is_throw);
|
||||||
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
|
|
||||||
ecma_property_value_t *new_prop_value_p;
|
ecma_property_value_t *new_prop_value_p;
|
||||||
new_prop_value_p = ecma_create_named_data_property (object_p,
|
new_prop_value_p = ecma_create_named_data_property (object_p,
|
||||||
property_name_p,
|
property_name_p,
|
||||||
|
|||||||
@@ -496,6 +496,12 @@
|
|||||||
VM_OC_MOV_IDENT | VM_OC_GET_STACK | VM_OC_PUT_IDENT) \
|
VM_OC_MOV_IDENT | VM_OC_GET_STACK | VM_OC_PUT_IDENT) \
|
||||||
CBC_OPCODE (CBC_ASSIGN_LET_CONST, CBC_HAS_LITERAL_ARG, -1, \
|
CBC_OPCODE (CBC_ASSIGN_LET_CONST, CBC_HAS_LITERAL_ARG, -1, \
|
||||||
VM_OC_ASSIGN_LET_CONST | VM_OC_GET_STACK) \
|
VM_OC_ASSIGN_LET_CONST | VM_OC_GET_STACK) \
|
||||||
|
CBC_OPCODE (CBC_ASSIGN_SUPER, CBC_NO_FLAG, -3, \
|
||||||
|
VM_OC_ASSIGN_SUPER) \
|
||||||
|
CBC_OPCODE (CBC_ASSIGN_SUPER_PUSH_RESULT, CBC_NO_FLAG, -2, \
|
||||||
|
VM_OC_ASSIGN_SUPER | VM_OC_PUT_STACK) \
|
||||||
|
CBC_OPCODE (CBC_ASSIGN_SUPER_BLOCK, CBC_NO_FLAG, -3, \
|
||||||
|
VM_OC_ASSIGN_SUPER | VM_OC_PUT_BLOCK) \
|
||||||
\
|
\
|
||||||
/* Last opcode (not a real opcode). */ \
|
/* Last opcode (not a real opcode). */ \
|
||||||
CBC_OPCODE (CBC_END, CBC_NO_FLAG, 0, \
|
CBC_OPCODE (CBC_END, CBC_NO_FLAG, 0, \
|
||||||
@@ -616,11 +622,15 @@
|
|||||||
VM_OC_PUSH_SUPER_CONSTRUCTOR) \
|
VM_OC_PUSH_SUPER_CONSTRUCTOR) \
|
||||||
CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP, CBC_NO_FLAG, 0, \
|
CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP, CBC_NO_FLAG, 0, \
|
||||||
VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \
|
VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \
|
||||||
CBC_OPCODE (CBC_EXT_SUPER_PROP_CALL_REFERENCE, CBC_NO_FLAG, 2, \
|
CBC_OPCODE (CBC_EXT_SUPER_PROP_REFERENCE, CBC_NO_FLAG, 2, \
|
||||||
VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \
|
VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \
|
||||||
CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 1, \
|
CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 1, \
|
||||||
VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \
|
VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \
|
||||||
CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_CALL_REFERENCE, CBC_HAS_LITERAL_ARG, 3, \
|
CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 3, \
|
||||||
|
VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \
|
||||||
|
CBC_OPCODE (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE, CBC_NO_FLAG, 1, \
|
||||||
|
VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \
|
||||||
|
CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE, CBC_HAS_LITERAL_ARG, 2, \
|
||||||
VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \
|
VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \
|
||||||
CBC_OPCODE (CBC_EXT_RESOLVE_LEXICAL_THIS, CBC_NO_FLAG, 1, \
|
CBC_OPCODE (CBC_EXT_RESOLVE_LEXICAL_THIS, CBC_NO_FLAG, 1, \
|
||||||
VM_OC_RESOLVE_LEXICAL_THIS | VM_OC_PUT_STACK) \
|
VM_OC_RESOLVE_LEXICAL_THIS | VM_OC_PUT_STACK) \
|
||||||
|
|||||||
@@ -221,6 +221,15 @@ parser_emit_unary_lvalue_opcode (parser_context_t *context_p, /**< context */
|
|||||||
/* Invalid LeftHandSide expression. */
|
/* Invalid LeftHandSide expression. */
|
||||||
if (opcode == CBC_DELETE_PUSH_RESULT)
|
if (opcode == CBC_DELETE_PUSH_RESULT)
|
||||||
{
|
{
|
||||||
|
#if ENABLED (JERRY_ES2015)
|
||||||
|
if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL)
|
||||||
|
|| context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP))
|
||||||
|
{
|
||||||
|
parser_emit_cbc_ext (context_p, CBC_EXT_THROW_REFERENCE_ERROR);
|
||||||
|
parser_emit_cbc (context_p, CBC_POP);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
parser_emit_cbc (context_p, CBC_POP);
|
parser_emit_cbc (context_p, CBC_POP);
|
||||||
parser_emit_cbc (context_p, CBC_PUSH_TRUE);
|
parser_emit_cbc (context_p, CBC_PUSH_TRUE);
|
||||||
return;
|
return;
|
||||||
@@ -1904,12 +1913,12 @@ parser_process_unary_expression (parser_context_t *context_p, /**< context */
|
|||||||
}
|
}
|
||||||
else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL))
|
else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL))
|
||||||
{
|
{
|
||||||
context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_CALL_REFERENCE);
|
context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_REFERENCE);
|
||||||
opcode = CBC_CALL_PROP;
|
opcode = CBC_CALL_PROP;
|
||||||
}
|
}
|
||||||
else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP))
|
else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP))
|
||||||
{
|
{
|
||||||
context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_CALL_REFERENCE);
|
context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_REFERENCE);
|
||||||
opcode = CBC_CALL_PROP;
|
opcode = CBC_CALL_PROP;
|
||||||
}
|
}
|
||||||
#endif /* ENABLED (JERRY_ES2015) */
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
@@ -2180,13 +2189,6 @@ parser_append_binary_single_assignment_token (parser_context_t *context_p, /**<
|
|||||||
* assignment, since it has multiple forms depending on the
|
* assignment, since it has multiple forms depending on the
|
||||||
* previous instruction. */
|
* previous instruction. */
|
||||||
|
|
||||||
#if ENABLED (JERRY_ES2015)
|
|
||||||
if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL))
|
|
||||||
{
|
|
||||||
context_p->last_cbc_opcode = CBC_PUSH_PROP_THIS_LITERAL;
|
|
||||||
}
|
|
||||||
#endif /* ENABLED (JERRY_ES2015) */
|
|
||||||
|
|
||||||
if (PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode)
|
if (PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode)
|
||||||
&& context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)
|
&& context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)
|
||||||
{
|
{
|
||||||
@@ -2265,6 +2267,18 @@ parser_append_binary_single_assignment_token (parser_context_t *context_p, /**<
|
|||||||
parser_stack_push_uint8 (context_p, CBC_ASSIGN);
|
parser_stack_push_uint8 (context_p, CBC_ASSIGN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if ENABLED (JERRY_ES2015)
|
||||||
|
else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL))
|
||||||
|
{
|
||||||
|
context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE);
|
||||||
|
parser_stack_push_uint8 (context_p, CBC_ASSIGN_SUPER);
|
||||||
|
}
|
||||||
|
else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP))
|
||||||
|
{
|
||||||
|
context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE);
|
||||||
|
parser_stack_push_uint8 (context_p, CBC_ASSIGN_SUPER);
|
||||||
|
}
|
||||||
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Invalid LeftHandSide expression. */
|
/* Invalid LeftHandSide expression. */
|
||||||
|
|||||||
+81
-3
@@ -1184,6 +1184,19 @@ opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, /**< current vm stac
|
|||||||
return ECMA_VALUE_ERROR;
|
return ECMA_VALUE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ecma_value_t *stack_top_p = *vm_stack_top_p;
|
||||||
|
|
||||||
|
if (opcode >= CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE)
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (opcode == CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE
|
||||||
|
|| opcode == CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE);
|
||||||
|
*stack_top_p++ = parent;
|
||||||
|
*stack_top_p++ = ecma_copy_value (prop_name);
|
||||||
|
*vm_stack_top_p = stack_top_p;
|
||||||
|
|
||||||
|
return ECMA_VALUE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
ecma_object_t *parent_p = ecma_get_object_from_value (parent);
|
ecma_object_t *parent_p = ecma_get_object_from_value (parent);
|
||||||
ecma_string_t *prop_name_p = ecma_op_to_prop_name (prop_name);
|
ecma_string_t *prop_name_p = ecma_op_to_prop_name (prop_name);
|
||||||
|
|
||||||
@@ -1202,9 +1215,7 @@ opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, /**< current vm stac
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ecma_value_t *stack_top_p = *vm_stack_top_p;
|
if (opcode == CBC_EXT_SUPER_PROP_LITERAL_REFERENCE || opcode == CBC_EXT_SUPER_PROP_REFERENCE)
|
||||||
|
|
||||||
if (opcode == CBC_EXT_SUPER_PROP_LITERAL_CALL_REFERENCE || opcode == CBC_EXT_SUPER_PROP_CALL_REFERENCE)
|
|
||||||
{
|
{
|
||||||
*stack_top_p++ = ecma_copy_value (frame_ctx_p->this_binding);
|
*stack_top_p++ = ecma_copy_value (frame_ctx_p->this_binding);
|
||||||
*stack_top_p++ = ECMA_VALUE_UNDEFINED;
|
*stack_top_p++ = ECMA_VALUE_UNDEFINED;
|
||||||
@@ -1215,6 +1226,73 @@ opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, /**< current vm stac
|
|||||||
|
|
||||||
return ECMA_VALUE_EMPTY;
|
return ECMA_VALUE_EMPTY;
|
||||||
} /* opfunc_form_super_reference */
|
} /* opfunc_form_super_reference */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assignment operation for SuperRefence base
|
||||||
|
*
|
||||||
|
* @return ECMA_VALUE_ERROR - if the operation fails
|
||||||
|
* ECMA_VALUE_EMPTY - otherwise
|
||||||
|
*/
|
||||||
|
ecma_value_t
|
||||||
|
opfunc_assign_super_reference (ecma_value_t **vm_stack_top_p, /**< vm stack top */
|
||||||
|
vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||||
|
uint32_t opcode_data) /**< opcode data to store the result */
|
||||||
|
{
|
||||||
|
ecma_value_t *stack_top_p = *vm_stack_top_p;
|
||||||
|
|
||||||
|
ecma_value_t base_obj = ecma_op_to_object (stack_top_p[-3]);
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (base_obj))
|
||||||
|
{
|
||||||
|
return base_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_object_t *base_obj_p = ecma_get_object_from_value (base_obj);
|
||||||
|
ecma_string_t *prop_name_p = ecma_op_to_prop_name (stack_top_p[-2]);
|
||||||
|
|
||||||
|
if (prop_name_p == NULL)
|
||||||
|
{
|
||||||
|
ecma_deref_object (base_obj_p);
|
||||||
|
return ECMA_VALUE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_strict = (frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0;
|
||||||
|
|
||||||
|
ecma_value_t result = ecma_op_object_put_with_receiver (base_obj_p,
|
||||||
|
prop_name_p,
|
||||||
|
stack_top_p[-1],
|
||||||
|
frame_ctx_p->this_binding,
|
||||||
|
is_strict);
|
||||||
|
|
||||||
|
ecma_deref_ecma_string (prop_name_p);
|
||||||
|
ecma_deref_object (base_obj_p);
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32_t i = 1; i <= 3; i++)
|
||||||
|
{
|
||||||
|
ecma_free_value (stack_top_p[-i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
stack_top_p -= 3;
|
||||||
|
|
||||||
|
if (opcode_data & VM_OC_PUT_STACK)
|
||||||
|
{
|
||||||
|
*stack_top_p++ = result;
|
||||||
|
}
|
||||||
|
else if (opcode_data & VM_OC_PUT_BLOCK)
|
||||||
|
{
|
||||||
|
ecma_fast_free_value (frame_ctx_p->block_result);
|
||||||
|
frame_ctx_p->block_result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
*vm_stack_top_p = stack_top_p;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} /* opfunc_assign_super_reference */
|
||||||
#endif /* ENABLED (JERRY_ES2015) */
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -137,6 +137,9 @@ opfunc_finalize_class (vm_frame_ctx_t *frame_ctx_p, ecma_value_t **vm_stack_top_
|
|||||||
ecma_value_t
|
ecma_value_t
|
||||||
opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, vm_frame_ctx_t *frame_ctx_p, ecma_value_t prop_name,
|
opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, vm_frame_ctx_t *frame_ctx_p, ecma_value_t prop_name,
|
||||||
uint8_t opcode);
|
uint8_t opcode);
|
||||||
|
|
||||||
|
ecma_value_t
|
||||||
|
opfunc_assign_super_reference (ecma_value_t **vm_stack_top_p, vm_frame_ctx_t *frame_ctx_p, uint32_t opcode_data);
|
||||||
#endif /* ENABLED (JERRY_ES2015) */
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2012,6 +2012,16 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
|||||||
{
|
{
|
||||||
result = ecma_op_check_object_coercible (stack_top_p[-1]);
|
result = ecma_op_check_object_coercible (stack_top_p[-1]);
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (result))
|
||||||
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case VM_OC_ASSIGN_SUPER:
|
||||||
|
{
|
||||||
|
result = opfunc_assign_super_reference (&stack_top_p, frame_ctx_p, opcode_data);
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (result))
|
if (ECMA_IS_VALUE_ERROR (result))
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
|
|||||||
@@ -266,6 +266,7 @@ typedef enum
|
|||||||
VM_OC_GET_TEMPLATE_OBJECT, /**< GetTemplateObject operation */
|
VM_OC_GET_TEMPLATE_OBJECT, /**< GetTemplateObject operation */
|
||||||
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 */
|
||||||
#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;
|
||||||
@@ -323,6 +324,7 @@ typedef enum
|
|||||||
VM_OC_GET_TEMPLATE_OBJECT = VM_OC_NONE, /**< GetTemplateObject operation */
|
VM_OC_GET_TEMPLATE_OBJECT = VM_OC_NONE, /**< GetTemplateObject operation */
|
||||||
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 */
|
||||||
#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 */
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ assert(monster.foo === "foo");
|
|||||||
var target = { foo: "foo"};
|
var target = { foo: "foo"};
|
||||||
var handler = {
|
var handler = {
|
||||||
set: function(obj, prop, value) {
|
set: function(obj, prop, value) {
|
||||||
obj[prop] = "";
|
obj[prop] = "";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var proxy = new Proxy(target, handler);
|
var proxy = new Proxy(target, handler);
|
||||||
@@ -58,6 +58,7 @@ var handler = {};
|
|||||||
var proxy = new Proxy(target, handler);
|
var proxy = new Proxy(target, handler);
|
||||||
|
|
||||||
// test when property does not exist on target
|
// test when property does not exist on target
|
||||||
|
/* TODO: Enable these tests when Proxy.[[GetOwnProperty]] has been implemented
|
||||||
for (var p of properties) {
|
for (var p of properties) {
|
||||||
proxy.p = 42;
|
proxy.p = 42;
|
||||||
assert(target.p === 42);
|
assert(target.p === 42);
|
||||||
@@ -73,7 +74,7 @@ for (var p of properties) {
|
|||||||
proxy.p = 42;
|
proxy.p = 42;
|
||||||
assert(target.p === 42);
|
assert(target.p === 42);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// test when target is a proxy
|
// test when target is a proxy
|
||||||
var target = {};
|
var target = {};
|
||||||
var handler = {
|
var handler = {
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
// Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
var setterCalled = false;
|
||||||
|
|
||||||
|
class Base {
|
||||||
|
func () {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
funcArrow () {
|
||||||
|
return () => 5;
|
||||||
|
}
|
||||||
|
["com" + "puted"] () {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
get getter () {
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
set setter (a) {
|
||||||
|
setterCalled = true;
|
||||||
|
}
|
||||||
|
getSuperValueOf() {
|
||||||
|
return super.valueOf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Derived extends Base {
|
||||||
|
func () {
|
||||||
|
return super.func();
|
||||||
|
}
|
||||||
|
funcArrow () {
|
||||||
|
return () => super.func();
|
||||||
|
}
|
||||||
|
["com" + "puted"] () {
|
||||||
|
return super["com" + "puted"]();
|
||||||
|
}
|
||||||
|
get getter () {
|
||||||
|
return super.getter;
|
||||||
|
}
|
||||||
|
set setter (a) {
|
||||||
|
super.setter = a;
|
||||||
|
}
|
||||||
|
deleteSuperReference () {
|
||||||
|
delete super.a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var derived = new Derived;
|
||||||
|
var base = new Base;
|
||||||
|
|
||||||
|
assert (derived.func() === 5);
|
||||||
|
assert (derived.funcArrow()() === 5);
|
||||||
|
assert (derived.computed() === 10);
|
||||||
|
assert (derived.getter === 6);
|
||||||
|
derived.setter = 7;
|
||||||
|
assert (setterCalled === true);
|
||||||
|
assert (base.getSuperValueOf() === Object.prototype.valueOf);
|
||||||
|
|
||||||
|
try {
|
||||||
|
derived.deleteSuperReference();
|
||||||
|
assert (false);
|
||||||
|
} catch (e) {
|
||||||
|
assert (e instanceof ReferenceError);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user