Implement computed properties for object literals. (#2481)

Also disable ES5.1 property name dumplication checks
when ES2015 object literals are enabled.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2018-08-28 15:28:16 +02:00
committed by GitHub
parent 300e40ba9d
commit bd42403600
19 changed files with 493 additions and 163 deletions
+1 -5
View File
@@ -101,12 +101,10 @@ opfunc_typeof (ecma_value_t left_value) /**< left value */
void
opfunc_set_accessor (bool is_getter, /**< is getter accessor */
ecma_value_t object, /**< object value */
ecma_value_t accessor_name, /**< accessor name value */
ecma_string_t *accessor_name_p, /**< accessor name */
ecma_value_t accessor) /**< accessor value */
{
ecma_object_t *object_p = ecma_get_object_from_value (object);
JERRY_ASSERT (ecma_is_value_string (accessor_name) || ecma_is_value_number (accessor_name));
ecma_string_t *accessor_name_p = ecma_get_string_from_value (ecma_op_to_string (accessor_name));
ecma_property_t *property_p = ecma_find_named_property (object_p, accessor_name_p);
if (property_p != NULL
@@ -153,8 +151,6 @@ opfunc_set_accessor (bool is_getter, /**< is getter accessor */
ECMA_PROPERTY_VALUE_PTR (property_p),
setter_func_p);
}
ecma_deref_ecma_string (accessor_name_p);
} /* opfunc_set_accessor */
/**
+1 -1
View File
@@ -85,7 +85,7 @@ ecma_value_t
opfunc_typeof (ecma_value_t left_value);
void
opfunc_set_accessor (bool is_getter, ecma_value_t object, ecma_value_t accessor_name, ecma_value_t accessor);
opfunc_set_accessor (bool is_getter, ecma_value_t object, ecma_string_t *accessor_name_p, ecma_value_t accessor);
ecma_value_t
vm_op_delete_prop (ecma_value_t object, ecma_value_t property, bool is_strict);
+79 -29
View File
@@ -927,11 +927,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
switch (VM_OC_GROUP_GET_INDEX (opcode_data))
{
case VM_OC_NONE:
{
JERRY_ASSERT (opcode == CBC_EXT_DEBUGGER);
continue;
}
case VM_OC_POP:
{
JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end);
@@ -1045,23 +1040,26 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
*stack_top_p++ = ecma_make_object_value (obj_p);
continue;
}
#ifndef CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER
case VM_OC_SET_COMPUTED_PROPERTY:
{
/* Swap values. */
left_value ^= right_value;
right_value ^= left_value;
left_value ^= right_value;
/* FALLTHRU */
}
#endif /* !CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER */
case VM_OC_SET_PROPERTY:
{
#ifndef CONFIG_DISABLE_ES2015_CLASS
const int index = (byte_code_start_p[0] == CBC_EXT_OPCODE) ? -2 : -1;
#else
const int index = -1;
#endif /* !CONFIG_DISABLE_ES2015_CLASS */
JERRY_STATIC_ASSERT (VM_OC_NON_STATIC_FLAG == VM_OC_BACKWARD_BRANCH,
vm_oc_non_static_flag_must_be_equal_to_vm_oc_backward_branch);
ecma_object_t *object_p = ecma_get_object_from_value (stack_top_p[index]);
ecma_string_t *prop_name_p;
ecma_property_t *property_p;
JERRY_ASSERT ((opcode_data >> VM_OC_NON_STATIC_SHIFT) <= 0x1);
if (ecma_is_value_string (right_value))
{
prop_name_p = ecma_get_string_from_value (right_value);
}
else
result = right_value;
if (JERRY_UNLIKELY (!ecma_is_value_string (right_value)))
{
result = ecma_op_to_string (right_value);
@@ -1069,11 +1067,30 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
prop_name_p = ecma_get_string_from_value (result);
}
property_p = ecma_find_named_property (object_p, prop_name_p);
ecma_string_t *prop_name_p = ecma_get_string_from_value (result);
#ifndef CONFIG_DISABLE_ES2015_CLASS
if (JERRY_UNLIKELY (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING_PROTOTYPE))
&& !(opcode_data & VM_OC_NON_STATIC_FLAG))
{
if (!ecma_is_value_string (right_value))
{
ecma_deref_ecma_string (prop_name_p);
}
result = ecma_raise_type_error (ECMA_ERR_MSG ("prototype property of a class is non-configurable"));
goto error;
}
const int index = (int) (opcode_data >> VM_OC_NON_STATIC_SHIFT) - 2;
#else /* CONFIG_DISABLE_ES2015_CLASS */
const int index = -1;
#endif /* !CONFIG_DISABLE_ES2015_CLASS */
ecma_object_t *object_p = ecma_get_object_from_value (stack_top_p[index]);
ecma_property_t *property_p = ecma_find_named_property (object_p, prop_name_p);
if (property_p != NULL
&& ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDDATA)
@@ -1108,18 +1125,50 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
case VM_OC_SET_GETTER:
case VM_OC_SET_SETTER:
{
JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE);
JERRY_ASSERT ((opcode_data >> VM_OC_NON_STATIC_SHIFT) <= 0x1);
result = left_value;
if (JERRY_UNLIKELY (!ecma_is_value_string (left_value)))
{
result = ecma_op_to_string (left_value);
if (ECMA_IS_VALUE_ERROR (result))
{
goto error;
}
}
ecma_string_t *prop_name_p = ecma_get_string_from_value (result);
#ifndef CONFIG_DISABLE_ES2015_CLASS
const int index = (byte_code_start_p[1] > CBC_EXT_SET_SETTER) ? -2 : -1;
#else
if (JERRY_UNLIKELY (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING_PROTOTYPE))
&& !(opcode_data & VM_OC_NON_STATIC_FLAG))
{
if (!ecma_is_value_string (left_value))
{
ecma_deref_ecma_string (prop_name_p);
}
result = ecma_raise_type_error (ECMA_ERR_MSG ("prototype property of a class is non-configurable"));
goto error;
}
const int index = (int) (opcode_data >> VM_OC_NON_STATIC_SHIFT) - 2;
#else /* CONFIG_DISABLE_ES2015_CLASS */
const int index = -1;
#endif /* !CONFIG_DISABLE_ES2015_CLASS */
opfunc_set_accessor (VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_SET_GETTER,
stack_top_p[index],
left_value,
prop_name_p,
right_value);
if (!ecma_is_value_string (left_value))
{
ecma_deref_ecma_string (prop_name_p);
}
goto free_both_values;
}
case VM_OC_PUSH_ARRAY:
@@ -2560,9 +2609,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p);
continue;
}
#ifdef JERRY_DEBUGGER
case VM_OC_BREAKPOINT_ENABLED:
{
#ifdef JERRY_DEBUGGER
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_IGNORE)
{
continue;
@@ -2580,12 +2629,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
result = ECMA_VALUE_ERROR;
goto error;
}
#endif /* JERRY_DEBUGGER */
continue;
}
case VM_OC_BREAKPOINT_DISABLED:
{
#ifdef JERRY_DEBUGGER
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_IGNORE)
{
continue;
@@ -2634,9 +2681,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
goto error;
}
}
#endif /* JERRY_DEBUGGER */
continue;
}
#endif /* JERRY_DEBUGGER */
#ifdef JERRY_ENABLE_LINE_INFO
case VM_OC_RESOURCE_NAME:
{
@@ -2685,6 +2732,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
#endif /* JERRY_ENABLE_LINE_INFO */
default:
{
JERRY_ASSERT (VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_NONE);
jerry_fatal (ERR_DISABLED_BYTE_CODE);
JERRY_UNREACHABLE ();
}
}
+39 -2
View File
@@ -41,7 +41,8 @@
*/
/**
* Branch argument is a backward branch
* If VM_OC_GET_ARGS_INDEX(opcode) == VM_OC_GET_BRANCH,
* this flag signals that the branch is a backward branch.
*/
#define VM_OC_BACKWARD_BRANCH 0x4000
@@ -102,7 +103,6 @@ typedef enum
*/
typedef enum
{
VM_OC_NONE, /**< do nothing */
VM_OC_POP, /**< pop from stack */
VM_OC_POP_BLOCK, /**< pop block */
VM_OC_PUSH, /**< push one literal */
@@ -121,6 +121,9 @@ typedef enum
VM_OC_PUSH_LIT_NEG_BYTE, /**< push literal and number between -1 and -256 */
VM_OC_PUSH_OBJECT, /**< push object */
VM_OC_SET_PROPERTY, /**< set property */
#ifndef CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER
VM_OC_SET_COMPUTED_PROPERTY, /**< set computed property */
#endif /* !CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER */
VM_OC_SET_GETTER, /**< set getter */
VM_OC_SET_SETTER, /**< set setter */
VM_OC_PUSH_UNDEFINED_BASE, /**< push undefined base */
@@ -206,12 +209,36 @@ typedef enum
VM_OC_FINALLY, /**< finally */
VM_OC_CONTEXT_END, /**< context end */
VM_OC_JUMP_AND_EXIT_CONTEXT, /**< jump and exit context */
#ifdef JERRY_DEBUGGER
VM_OC_BREAKPOINT_ENABLED, /**< enabled breakpoint for debugger */
VM_OC_BREAKPOINT_DISABLED, /**< disabled breakpoint for debugger */
#endif /* JERRY_DEBUGGER */
#ifdef JERRY_ENABLE_LINE_INFO
VM_OC_RESOURCE_NAME, /**< resource name of the current function */
VM_OC_LINE, /**< line number of the next statement */
#endif /* JERRY_ENABLE_LINE_INFO */
VM_OC_NONE, /**< a special opcode for */
} vm_oc_types;
/**
* Unused opcodes, but required by byte-code types.
*/
typedef enum
{
#ifdef CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER
VM_OC_SET_COMPUTED_PROPERTY = VM_OC_NONE, /**< set computed property is unused */
#endif /* CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER */
#ifndef JERRY_DEBUGGER
VM_OC_BREAKPOINT_ENABLED = VM_OC_NONE, /**< enabled breakpoint for debugger is unused */
VM_OC_BREAKPOINT_DISABLED = VM_OC_NONE, /**< disabled breakpoint for debugger is unused */
#endif /* !JERRY_DEBUGGER */
#ifndef JERRY_ENABLE_LINE_INFO
VM_OC_RESOURCE_NAME = VM_OC_NONE, /**< resource name of the current function is unused */
VM_OC_LINE = VM_OC_NONE, /**< line number of the next statement is unused */
#endif /* !JERRY_ENABLE_LINE_INFO */
VM_OC_UNUSED = VM_OC_NONE /**< placeholder if the list is empty */
} vm_oc_unused_types;
/**
* Decrement operator.
*/
@@ -237,6 +264,16 @@ typedef enum
*/
#define VM_OC_LOGICAL_BRANCH_FLAG 0x2
/**
* Bit index shift for non-static property initializers.
*/
#define VM_OC_NON_STATIC_SHIFT 14
/**
* This flag is set for static property initializers.
*/
#define VM_OC_NON_STATIC_FLAG (0x1 << VM_OC_NON_STATIC_SHIFT)
/**
* Position of "put result" opcode.
*/