Skip to content

Commit 6aa16f6

Browse files
committed
Reduce code duplication between Array.reduce and reduceRight
Their code differs only in handling the array index. JerryScript-DCO-1.0-Signed-off-by: Mátyás Mustoha mmatyas@inf.u-szeged.hu
1 parent 2bfd3b7 commit 6aa16f6

File tree

1 file changed

+39
-151
lines changed

1 file changed

+39
-151
lines changed

jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c

Lines changed: 39 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -2404,18 +2404,20 @@ ecma_builtin_array_prototype_object_filter (ecma_value_t this_arg, /**< this arg
24042404
} /* ecma_builtin_array_prototype_object_filter */
24052405

24062406
/**
2407-
* The Array.prototype object's 'reduce' routine
2407+
* Reduces the Array starting from left or right
24082408
*
24092409
* See also:
2410-
* ECMA-262 v5, 15.4.4.21
2410+
* Array.prototype.reduce
2411+
* Array.prototype.reduceRight
24112412
*
24122413
* @return ecma value
24132414
* Returned value must be freed with ecma_free_value.
24142415
*/
24152416
static ecma_value_t
2416-
ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this argument */
2417-
const ecma_value_t args[], /**< arguments list */
2418-
ecma_length_t args_number) /**< number of arguments */
2417+
ecma_builtin_array_reduce_from (ecma_value_t this_arg, /**< this argument */
2418+
const ecma_value_t args[], /**< arguments list */
2419+
ecma_length_t args_number, /**< number of arguments */
2420+
bool start_from_left) /**< whether the reduce starts from left or right */
24192421
{
24202422
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
24212423
ecma_value_t callbackfn = (args_number > 0) ? args[0] : ECMA_VALUE_UNDEFINED;
@@ -2449,7 +2451,6 @@ ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this arg
24492451

24502452
JERRY_ASSERT (ecma_is_value_object (callbackfn));
24512453
func_object_p = ecma_get_object_from_value (callbackfn);
2452-
ecma_value_t accumulator = ECMA_VALUE_UNDEFINED;
24532454

24542455
/* 5. */
24552456
if (len_number == ECMA_NUMBER_ZERO && ecma_is_value_undefined (initial_value))
@@ -2458,8 +2459,11 @@ ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this arg
24582459
}
24592460
else
24602461
{
2462+
ecma_value_t accumulator = ECMA_VALUE_UNDEFINED;
2463+
24612464
/* 6. */
2462-
uint32_t index = 0;
2465+
uint32_t index = start_from_left ? 0 : (len - 1);
2466+
uint32_t items_visited = 0;
24632467

24642468
/* 7.a */
24652469
if (args_number > 1)
@@ -2472,7 +2476,7 @@ ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this arg
24722476
bool k_present = false;
24732477

24742478
/* 8.b */
2475-
while (!k_present && index < len && ecma_is_value_empty (ret_value))
2479+
while (!k_present && items_visited < len && ecma_is_value_empty (ret_value))
24762480
{
24772481
/* 8.b.i */
24782482
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index);
@@ -2493,7 +2497,8 @@ ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this arg
24932497
ECMA_FINALIZE (current_value);
24942498

24952499
/* 8.b.iv */
2496-
index++;
2500+
index = start_from_left ? (index + 1) : (index - 1);
2501+
items_visited++;
24972502

24982503
ecma_deref_ecma_string (index_str_p);
24992504
}
@@ -2507,7 +2512,7 @@ ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this arg
25072512
/* 9. */
25082513
ecma_value_t current_index;
25092514

2510-
for (; index < len && ecma_is_value_empty (ret_value); index++)
2515+
while (items_visited < len && ecma_is_value_empty (ret_value))
25112516
{
25122517
/* 9.a */
25132518
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index);
@@ -2537,23 +2542,43 @@ ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this arg
25372542
ECMA_FINALIZE (current_value);
25382543

25392544
ecma_deref_ecma_string (index_str_p);
2540-
/* 9.d in for loop */
2545+
2546+
/* 9.d */
2547+
index = start_from_left ? (index + 1) : (index - 1);
2548+
items_visited++;
25412549
}
25422550

25432551
if (ecma_is_value_empty (ret_value))
25442552
{
25452553
ret_value = ecma_copy_value (accumulator);
25462554
}
2547-
}
25482555

2549-
ecma_free_value (accumulator);
2556+
ecma_free_value (accumulator);
2557+
}
25502558
}
25512559

25522560
ECMA_OP_TO_NUMBER_FINALIZE (len_number);
25532561
ECMA_FINALIZE (len_value);
25542562
ECMA_FINALIZE (obj_this);
25552563

25562564
return ret_value;
2565+
} /* ecma_builtin_array_reduce_from */
2566+
2567+
/**
2568+
* The Array.prototype object's 'reduce' routine
2569+
*
2570+
* See also:
2571+
* ECMA-262 v5, 15.4.4.21
2572+
*
2573+
* @return ecma value
2574+
* Returned value must be freed with ecma_free_value.
2575+
*/
2576+
static ecma_value_t
2577+
ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this argument */
2578+
const ecma_value_t args[], /**< arguments list */
2579+
ecma_length_t args_number) /**< number of arguments */
2580+
{
2581+
return ecma_builtin_array_reduce_from (this_arg, args, args_number, true);
25572582
} /* ecma_builtin_array_prototype_object_reduce */
25582583

25592584
/**
@@ -2570,144 +2595,7 @@ ecma_builtin_array_prototype_object_reduce_right (ecma_value_t this_arg, /**< th
25702595
const ecma_value_t args[], /**< arguments list */
25712596
ecma_length_t args_number) /**< number of arguments */
25722597
{
2573-
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
2574-
ecma_value_t callbackfn = (args_number > 0) ? args[0] : ECMA_VALUE_UNDEFINED;
2575-
ecma_value_t initial_value = (args_number > 1) ? args[1] : ECMA_VALUE_UNDEFINED;
2576-
2577-
/* 1. */
2578-
ECMA_TRY_CATCH (obj_this,
2579-
ecma_op_to_object (this_arg),
2580-
ret_value);
2581-
2582-
ecma_object_t *obj_p = ecma_get_object_from_value (obj_this);
2583-
2584-
/* 2. */
2585-
ECMA_TRY_CATCH (len_value,
2586-
ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH),
2587-
ret_value);
2588-
2589-
ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value);
2590-
2591-
/* 3. */
2592-
uint32_t len = ecma_number_to_uint32 (len_number);
2593-
2594-
/* 4. */
2595-
if (!ecma_op_is_callable (callbackfn))
2596-
{
2597-
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Callback function is not callable."));
2598-
}
2599-
else
2600-
{
2601-
ecma_object_t *func_object_p;
2602-
2603-
JERRY_ASSERT (ecma_is_value_object (callbackfn));
2604-
func_object_p = ecma_get_object_from_value (callbackfn);
2605-
2606-
/* 5. */
2607-
if (len_number == ECMA_NUMBER_ZERO && ecma_is_value_undefined (initial_value))
2608-
{
2609-
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Initial value cannot be undefined."));
2610-
}
2611-
else
2612-
{
2613-
ecma_value_t accumulator = ECMA_VALUE_UNDEFINED;
2614-
2615-
/* 6. */
2616-
int64_t index = (int64_t) len - 1;
2617-
2618-
/* 7.a */
2619-
if (args_number > 1)
2620-
{
2621-
accumulator = ecma_copy_value (initial_value);
2622-
}
2623-
else
2624-
{
2625-
/* 8.a */
2626-
bool k_present = false;
2627-
2628-
/* 8.b */
2629-
while (!k_present && index >= 0 && ecma_is_value_empty (ret_value))
2630-
{
2631-
/* 8.b.i */
2632-
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 ((uint32_t) index);
2633-
k_present = true;
2634-
2635-
/* 8.b.ii-iii */
2636-
ECMA_TRY_CATCH (current_value, ecma_op_object_find (obj_p, index_str_p), ret_value);
2637-
2638-
if (ecma_is_value_found (current_value))
2639-
{
2640-
accumulator = ecma_copy_value (current_value);
2641-
}
2642-
else
2643-
{
2644-
k_present = false;
2645-
}
2646-
2647-
ECMA_FINALIZE (current_value);
2648-
2649-
/* 8.b.iv */
2650-
index--;
2651-
2652-
ecma_deref_ecma_string (index_str_p);
2653-
}
2654-
2655-
/* 8.c */
2656-
if (!k_present)
2657-
{
2658-
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Missing array element."));
2659-
}
2660-
}
2661-
/* 9. */
2662-
ecma_value_t current_index;
2663-
2664-
for (; index >= 0 && ecma_is_value_empty (ret_value); index--)
2665-
{
2666-
/* 9.a */
2667-
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 ((uint32_t) index);
2668-
2669-
/* 9.b */
2670-
ECMA_TRY_CATCH (current_value, ecma_op_object_find (obj_p, index_str_p), ret_value);
2671-
2672-
if (ecma_is_value_found (current_value))
2673-
{
2674-
/* 9.c.i, 9.c.ii */
2675-
current_index = ecma_make_uint32_value ((uint32_t) index);
2676-
ecma_value_t call_args[] = {accumulator, current_value, current_index, obj_this};
2677-
2678-
ECMA_TRY_CATCH (call_value,
2679-
ecma_op_function_call (func_object_p,
2680-
ECMA_VALUE_UNDEFINED,
2681-
call_args,
2682-
4),
2683-
ret_value);
2684-
2685-
ecma_free_value (accumulator);
2686-
accumulator = ecma_copy_value (call_value);
2687-
2688-
ECMA_FINALIZE (call_value);
2689-
}
2690-
2691-
ECMA_FINALIZE (current_value);
2692-
2693-
ecma_deref_ecma_string (index_str_p);
2694-
/* 9.d in for loop */
2695-
}
2696-
2697-
if (ecma_is_value_empty (ret_value))
2698-
{
2699-
ret_value = ecma_copy_value (accumulator);
2700-
}
2701-
2702-
ecma_free_value (accumulator);
2703-
}
2704-
}
2705-
2706-
ECMA_OP_TO_NUMBER_FINALIZE (len_number);
2707-
ECMA_FINALIZE (len_value);
2708-
ECMA_FINALIZE (obj_this);
2709-
2710-
return ret_value;
2598+
return ecma_builtin_array_reduce_from (this_arg, args, args_number, false);
27112599
} /* ecma_builtin_array_prototype_object_reduce_right */
27122600

27132601
/**

0 commit comments

Comments
 (0)