Skip to content

Commit ebf09e6

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 ebf09e6

File tree

1 file changed

+41
-151
lines changed

1 file changed

+41
-151
lines changed

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

Lines changed: 41 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. */
24622465
uint32_t index = 0;
2466+
const uint32_t last_index = len - 1;
24632467

24642468
/* 7.a */
24652469
if (args_number > 1)
@@ -2475,7 +2479,9 @@ ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this arg
24752479
while (!k_present && index < len && ecma_is_value_empty (ret_value))
24762480
{
24772481
/* 8.b.i */
2478-
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index);
2482+
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (start_from_left
2483+
? index
2484+
: last_index - index);
24792485
k_present = true;
24802486

24812487
/* 8.b.ii-iii */
@@ -2507,18 +2513,20 @@ ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this arg
25072513
/* 9. */
25082514
ecma_value_t current_index;
25092515

2510-
for (; index < len && ecma_is_value_empty (ret_value); index++)
2516+
while (index < len && ecma_is_value_empty (ret_value))
25112517
{
2518+
const uint32_t corrected_index = start_from_left ? index : last_index - index;
2519+
25122520
/* 9.a */
2513-
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index);
2521+
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (corrected_index);
25142522

25152523
/* 9.b */
25162524
ECMA_TRY_CATCH (current_value, ecma_op_object_find (obj_p, index_str_p), ret_value);
25172525

25182526
if (ecma_is_value_found (current_value))
25192527
{
25202528
/* 9.c.i, 9.c.ii */
2521-
current_index = ecma_make_uint32_value (index);
2529+
current_index = ecma_make_uint32_value (corrected_index);
25222530
ecma_value_t call_args[] = {accumulator, current_value, current_index, obj_this};
25232531

25242532
ECMA_TRY_CATCH (call_value,
@@ -2537,23 +2545,42 @@ ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this arg
25372545
ECMA_FINALIZE (current_value);
25382546

25392547
ecma_deref_ecma_string (index_str_p);
2540-
/* 9.d in for loop */
2548+
2549+
/* 9.d */
2550+
index++;
25412551
}
25422552

25432553
if (ecma_is_value_empty (ret_value))
25442554
{
25452555
ret_value = ecma_copy_value (accumulator);
25462556
}
2547-
}
25482557

2549-
ecma_free_value (accumulator);
2558+
ecma_free_value (accumulator);
2559+
}
25502560
}
25512561

25522562
ECMA_OP_TO_NUMBER_FINALIZE (len_number);
25532563
ECMA_FINALIZE (len_value);
25542564
ECMA_FINALIZE (obj_this);
25552565

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

25592586
/**
@@ -2570,144 +2597,7 @@ ecma_builtin_array_prototype_object_reduce_right (ecma_value_t this_arg, /**< th
25702597
const ecma_value_t args[], /**< arguments list */
25712598
ecma_length_t args_number) /**< number of arguments */
25722599
{
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;
2600+
return ecma_builtin_array_reduce_from (this_arg, args, args_number, false);
27112601
} /* ecma_builtin_array_prototype_object_reduce_right */
27122602

27132603
/**

0 commit comments

Comments
 (0)