Implement rest parameter support for destructuring object patterns. (#4318)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
+134
-12
@@ -601,10 +601,7 @@ opfunc_append_array (ecma_value_t *stack_top_p, /**< current stack top */
|
||||
{
|
||||
filled_holes++;
|
||||
|
||||
if (ecma_is_value_object (stack_top_p[i]))
|
||||
{
|
||||
ecma_deref_object (ecma_get_object_from_value (stack_top_p[i]));
|
||||
}
|
||||
ecma_deref_if_object (stack_top_p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -632,16 +629,10 @@ opfunc_append_array (ecma_value_t *stack_top_p, /**< current stack top */
|
||||
|
||||
ecma_deref_ecma_string (index_str_p);
|
||||
prop_value_p->value = stack_top_p[i];
|
||||
|
||||
if (ecma_is_value_object (stack_top_p[i]))
|
||||
{
|
||||
ecma_free_value (stack_top_p[i]);
|
||||
}
|
||||
|
||||
ecma_deref_if_object (stack_top_p[i]);
|
||||
}
|
||||
|
||||
ext_array_obj_p->u.array.length = old_length + values_length;
|
||||
}
|
||||
ext_array_obj_p->u.array.length = old_length + values_length;
|
||||
}
|
||||
|
||||
return ECMA_VALUE_EMPTY;
|
||||
@@ -1687,6 +1678,137 @@ opfunc_assign_super_reference (ecma_value_t **vm_stack_top_p, /**< vm stack top
|
||||
|
||||
return result;
|
||||
} /* opfunc_assign_super_reference */
|
||||
|
||||
/**
|
||||
* Copy data properties of an object
|
||||
*
|
||||
* @return ECMA_VALUE_ERROR - if the operation fails
|
||||
* ECMA_VALUE_EMPTY - otherwise
|
||||
*/
|
||||
ecma_value_t
|
||||
opfunc_copy_data_properties (ecma_value_t target_object, /**< target object */
|
||||
ecma_value_t source_object, /**< source object */
|
||||
ecma_value_t filter_array) /**< filter array */
|
||||
{
|
||||
bool source_to_object = false;
|
||||
|
||||
if (!ecma_is_value_object (source_object))
|
||||
{
|
||||
source_object = ecma_op_to_object (source_object);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (source_object))
|
||||
{
|
||||
return source_object;
|
||||
}
|
||||
|
||||
source_to_object = true;
|
||||
}
|
||||
|
||||
ecma_object_t *source_object_p = ecma_get_object_from_value (source_object);
|
||||
ecma_collection_t *names_p = ecma_op_object_own_property_keys (source_object_p);
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_PROXY)
|
||||
if (names_p == NULL)
|
||||
{
|
||||
JERRY_ASSERT (!source_to_object);
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
|
||||
|
||||
ecma_object_t *target_object_p = ecma_get_object_from_value (target_object);
|
||||
ecma_value_t *buffer_p = names_p->buffer_p;
|
||||
ecma_value_t *buffer_end_p = buffer_p + names_p->item_count;
|
||||
ecma_value_t *filter_start_p = NULL;
|
||||
ecma_value_t *filter_end_p = NULL;
|
||||
ecma_value_t result = ECMA_VALUE_EMPTY;
|
||||
|
||||
if (filter_array != ECMA_VALUE_UNDEFINED)
|
||||
{
|
||||
ecma_object_t *filter_array_p = ecma_get_object_from_value (filter_array);
|
||||
|
||||
JERRY_ASSERT (ecma_get_object_type (filter_array_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
JERRY_ASSERT (ecma_op_object_is_fast_array (filter_array_p));
|
||||
|
||||
if (filter_array_p->u1.property_list_cp != JMEM_CP_NULL)
|
||||
{
|
||||
filter_start_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, filter_array_p->u1.property_list_cp);
|
||||
filter_end_p = filter_start_p + ((ecma_extended_object_t *) filter_array_p)->u.array.length;
|
||||
}
|
||||
}
|
||||
|
||||
while (buffer_p < buffer_end_p)
|
||||
{
|
||||
ecma_string_t *property_name_p = ecma_get_prop_name_from_value (*buffer_p++);
|
||||
|
||||
if (filter_start_p != NULL)
|
||||
{
|
||||
ecma_value_t *filter_p = filter_start_p;
|
||||
|
||||
do
|
||||
{
|
||||
if (ecma_compare_ecma_strings (property_name_p, ecma_get_prop_name_from_value (*filter_p)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (++filter_p < filter_end_p);
|
||||
|
||||
if (filter_p != filter_end_p)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_property_descriptor_t descriptor;
|
||||
result = ecma_op_object_get_own_property_descriptor (source_object_p, property_name_p, &descriptor);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == ECMA_VALUE_FALSE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(descriptor.flags & ECMA_PROP_IS_ENUMERABLE))
|
||||
{
|
||||
ecma_free_property_descriptor (&descriptor);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((descriptor.flags & ECMA_PROP_IS_VALUE_DEFINED) && !ECMA_OBJECT_IS_PROXY (source_object_p))
|
||||
{
|
||||
result = descriptor.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_free_property_descriptor (&descriptor);
|
||||
|
||||
result = ecma_op_object_get (source_object_p, property_name_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
opfunc_set_data_property (target_object_p, property_name_p, result);
|
||||
ecma_free_value (result);
|
||||
|
||||
result = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (source_to_object))
|
||||
{
|
||||
ecma_deref_object (source_object_p);
|
||||
}
|
||||
|
||||
ecma_collection_free (names_p);
|
||||
return result;
|
||||
} /* opfunc_copy_data_properties */
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/**
|
||||
|
||||
@@ -131,6 +131,7 @@ ecma_value_t
|
||||
opfunc_append_array (ecma_value_t *stack_top_p, uint16_t values_length);
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
vm_executable_object_t *
|
||||
opfunc_create_executable_object (vm_frame_ctx_t *frame_ctx_p, vm_create_executable_object_type_t type);
|
||||
|
||||
@@ -179,6 +180,10 @@ opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, vm_frame_ctx_t *fram
|
||||
|
||||
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);
|
||||
|
||||
ecma_value_t
|
||||
opfunc_copy_data_properties (ecma_value_t target_object, ecma_value_t source_object, ecma_value_t filter_array);
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/**
|
||||
|
||||
+60
-46
@@ -1887,61 +1887,21 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
}
|
||||
case VM_OC_COPY_DATA_PROPERTIES:
|
||||
{
|
||||
result = *(--stack_top_p);
|
||||
left_value = *(--stack_top_p);
|
||||
|
||||
if (ecma_is_value_undefined (result) || ecma_is_value_null (result))
|
||||
if (ecma_is_value_undefined (left_value) || ecma_is_value_null (left_value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ecma_is_value_object (result))
|
||||
result = opfunc_copy_data_properties (stack_top_p[-1], left_value, ECMA_VALUE_UNDEFINED);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
ecma_value_t value = result;
|
||||
result = ecma_op_to_object (value);
|
||||
ecma_free_value (value);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (result);
|
||||
ecma_collection_t *names_p = ecma_op_object_get_enumerable_property_names (object_p,
|
||||
ECMA_ENUMERABLE_PROPERTY_KEYS);
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_PROXY)
|
||||
if (names_p == NULL)
|
||||
{
|
||||
ecma_deref_object (object_p);
|
||||
result = ECMA_VALUE_ERROR;
|
||||
goto error;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
|
||||
|
||||
ecma_object_t *target_object_p = ecma_get_object_from_value (stack_top_p[-1]);
|
||||
ecma_value_t *buffer_p = names_p->buffer_p;
|
||||
ecma_value_t *buffer_end_p = buffer_p + names_p->item_count;
|
||||
|
||||
while (buffer_p < buffer_end_p)
|
||||
{
|
||||
ecma_string_t *property_name_p = ecma_get_string_from_value (*buffer_p++);
|
||||
result = ecma_op_object_get (object_p, property_name_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
ecma_collection_free (names_p);
|
||||
ecma_deref_object (object_p);
|
||||
goto error;
|
||||
}
|
||||
|
||||
opfunc_set_data_property (target_object_p, property_name_p, result);
|
||||
ecma_free_value (result);
|
||||
}
|
||||
|
||||
ecma_collection_free (names_p);
|
||||
ecma_deref_object (object_p);
|
||||
continue;
|
||||
goto free_left_value;
|
||||
}
|
||||
case VM_OC_SET_COMPUTED_PROPERTY:
|
||||
{
|
||||
@@ -2438,6 +2398,60 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
*stack_top_p++ = ecma_make_object_value (array_p);
|
||||
continue;
|
||||
}
|
||||
case VM_OC_INITIALIZER_PUSH_LIST:
|
||||
{
|
||||
stack_top_p++;
|
||||
stack_top_p[-1] = stack_top_p[-2];
|
||||
stack_top_p[-2] = ecma_make_object_value (ecma_op_new_array_object (0));
|
||||
continue;
|
||||
}
|
||||
case VM_OC_INITIALIZER_PUSH_REST:
|
||||
{
|
||||
if (!ecma_op_require_object_coercible (stack_top_p[-1]))
|
||||
{
|
||||
result = ECMA_VALUE_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ecma_object_t *prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
|
||||
ecma_object_t *result_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL);
|
||||
|
||||
left_value = ecma_make_object_value (result_object_p);
|
||||
result = opfunc_copy_data_properties (left_value, stack_top_p[-1], stack_top_p[-2]);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
ecma_free_value (stack_top_p[-2]);
|
||||
stack_top_p[-2] = stack_top_p[-1];
|
||||
stack_top_p[-1] = left_value;
|
||||
continue;
|
||||
}
|
||||
case VM_OC_INITIALIZER_PUSH_NAME:
|
||||
{
|
||||
if (JERRY_UNLIKELY (!ecma_is_value_prop_name (left_value)))
|
||||
{
|
||||
ecma_string_t *property_key = ecma_op_to_property_key (left_value);
|
||||
|
||||
if (property_key == NULL)
|
||||
{
|
||||
result = ECMA_VALUE_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ecma_free_value (left_value);
|
||||
left_value = ecma_make_string_value (property_key);
|
||||
}
|
||||
|
||||
ecma_object_t *array_obj_p = ecma_get_object_from_value (stack_top_p[-2]);
|
||||
JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
|
||||
ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p;
|
||||
ecma_fast_array_set_property (array_obj_p, ext_array_obj_p->u.array.length, left_value);
|
||||
/* FALLTHRU */
|
||||
}
|
||||
case VM_OC_INITIALIZER_PUSH_PROP:
|
||||
{
|
||||
result = vm_op_get_value (stack_top_p[-1], left_value);
|
||||
|
||||
@@ -278,6 +278,9 @@ typedef enum
|
||||
VM_OC_GET_ITERATOR, /**< GetIterator abstract operation */
|
||||
VM_OC_ITERATOR_STEP, /**< IteratorStep abstract operation */
|
||||
VM_OC_ITERATOR_CLOSE, /**< IteratorClose abstract operation */
|
||||
VM_OC_INITIALIZER_PUSH_LIST, /**< push name list array */
|
||||
VM_OC_INITIALIZER_PUSH_REST, /**< push the object with the rest properties */
|
||||
VM_OC_INITIALIZER_PUSH_NAME, /**< append string to name list array and push the string */
|
||||
VM_OC_DEFAULT_INITIALIZER, /**< default initializer inside a pattern */
|
||||
VM_OC_REST_INITIALIZER, /**< create rest object inside an array pattern */
|
||||
VM_OC_INITIALIZER_PUSH_PROP, /**< push property for object initializer */
|
||||
@@ -363,6 +366,9 @@ typedef enum
|
||||
VM_OC_GET_ITERATOR = VM_OC_NONE, /**< GetIterator abstract operation */
|
||||
VM_OC_ITERATOR_STEP = VM_OC_NONE, /**< IteratorStep abstract operation */
|
||||
VM_OC_ITERATOR_CLOSE = VM_OC_NONE, /**< IteratorClose abstract operation */
|
||||
VM_OC_INITIALIZER_PUSH_LIST = VM_OC_NONE, /**< push name list array */
|
||||
VM_OC_INITIALIZER_PUSH_REST = VM_OC_NONE, /**< push the object with the rest properties */
|
||||
VM_OC_INITIALIZER_PUSH_NAME = VM_OC_NONE, /**< append string to name list array and push the string */
|
||||
VM_OC_DEFAULT_INITIALIZER = VM_OC_NONE, /**< default initializer inside a pattern */
|
||||
VM_OC_REST_INITIALIZER = VM_OC_NONE, /**< create rest object inside an array pattern */
|
||||
VM_OC_INITIALIZER_PUSH_PROP = VM_OC_NONE, /**< push property for object initializer */
|
||||
|
||||
Reference in New Issue
Block a user