Skip to content

Commit c288cda

Browse files
mmatyasyichoi
authored andcommitted
Reduce code duplication between Array.reduce and reduceRight (#2280)
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 5e097dc commit c288cda

File tree

1 file changed

+37
-149
lines changed

1 file changed

+37
-149
lines changed

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

Lines changed: 37 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -2296,18 +2296,20 @@ ecma_builtin_array_prototype_object_filter (ecma_value_t this_arg, /**< this arg
22962296
} /* ecma_builtin_array_prototype_object_filter */
22972297

22982298
/**
2299-
* The Array.prototype object's 'reduce' routine
2299+
* Reduces the Array starting from left or right
23002300
*
23012301
* See also:
2302-
* ECMA-262 v5, 15.4.4.21
2302+
* Array.prototype.reduce
2303+
* Array.prototype.reduceRight
23032304
*
23042305
* @return ecma value
23052306
* Returned value must be freed with ecma_free_value.
23062307
*/
23072308
static ecma_value_t
2308-
ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this argument */
2309-
const ecma_value_t args[], /**< arguments list */
2310-
ecma_length_t args_number) /**< number of arguments */
2309+
ecma_builtin_array_reduce_from (ecma_value_t this_arg, /**< this argument */
2310+
const ecma_value_t args[], /**< arguments list */
2311+
ecma_length_t args_number, /**< number of arguments */
2312+
bool start_from_left) /**< whether the reduce starts from left or right */
23112313
{
23122314
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
23132315
ecma_value_t callbackfn = (args_number > 0) ? args[0] : ECMA_VALUE_UNDEFINED;
@@ -2341,7 +2343,6 @@ ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this arg
23412343

23422344
JERRY_ASSERT (ecma_is_value_object (callbackfn));
23432345
func_object_p = ecma_get_object_from_value (callbackfn);
2344-
ecma_value_t accumulator = ECMA_VALUE_UNDEFINED;
23452346

23462347
/* 5. */
23472348
if (len_number == ECMA_NUMBER_ZERO && ecma_is_value_undefined (initial_value))
@@ -2350,8 +2351,11 @@ ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this arg
23502351
}
23512352
else
23522353
{
2354+
ecma_value_t accumulator = ECMA_VALUE_UNDEFINED;
2355+
23532356
/* 6. */
23542357
uint32_t index = 0;
2358+
const uint32_t last_index = len - 1;
23552359

23562360
/* 7.a */
23572361
if (args_number > 1)
@@ -2367,7 +2371,8 @@ ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this arg
23672371
while (!k_present && index < len && ecma_is_value_empty (ret_value))
23682372
{
23692373
/* 8.b.i */
2370-
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index);
2374+
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (start_from_left ? index
2375+
: last_index - index);
23712376
k_present = true;
23722377

23732378
/* 8.b.ii-iii */
@@ -2401,16 +2406,18 @@ ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this arg
24012406

24022407
for (; index < len && ecma_is_value_empty (ret_value); index++)
24032408
{
2409+
const uint32_t corrected_index = start_from_left ? index : last_index - index;
2410+
24042411
/* 9.a */
2405-
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index);
2412+
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (corrected_index);
24062413

24072414
/* 9.b */
24082415
ECMA_TRY_CATCH (current_value, ecma_op_object_find (obj_p, index_str_p), ret_value);
24092416

24102417
if (ecma_is_value_found (current_value))
24112418
{
24122419
/* 9.c.i, 9.c.ii */
2413-
current_index = ecma_make_uint32_value (index);
2420+
current_index = ecma_make_uint32_value (corrected_index);
24142421
ecma_value_t call_args[] = {accumulator, current_value, current_index, obj_this};
24152422

24162423
ECMA_TRY_CATCH (call_value,
@@ -2429,23 +2436,41 @@ ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this arg
24292436
ECMA_FINALIZE (current_value);
24302437

24312438
ecma_deref_ecma_string (index_str_p);
2439+
24322440
/* 9.d in for loop */
24332441
}
24342442

24352443
if (ecma_is_value_empty (ret_value))
24362444
{
24372445
ret_value = ecma_copy_value (accumulator);
24382446
}
2439-
}
24402447

2441-
ecma_free_value (accumulator);
2448+
ecma_free_value (accumulator);
2449+
}
24422450
}
24432451

24442452
ECMA_OP_TO_NUMBER_FINALIZE (len_number);
24452453
ECMA_FINALIZE (len_value);
24462454
ECMA_FINALIZE (obj_this);
24472455

24482456
return ret_value;
2457+
} /* ecma_builtin_array_reduce_from */
2458+
2459+
/**
2460+
* The Array.prototype object's 'reduce' routine
2461+
*
2462+
* See also:
2463+
* ECMA-262 v5, 15.4.4.21
2464+
*
2465+
* @return ecma value
2466+
* Returned value must be freed with ecma_free_value.
2467+
*/
2468+
static ecma_value_t
2469+
ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this argument */
2470+
const ecma_value_t args[], /**< arguments list */
2471+
ecma_length_t args_number) /**< number of arguments */
2472+
{
2473+
return ecma_builtin_array_reduce_from (this_arg, args, args_number, true);
24492474
} /* ecma_builtin_array_prototype_object_reduce */
24502475

24512476
/**
@@ -2462,144 +2487,7 @@ ecma_builtin_array_prototype_object_reduce_right (ecma_value_t this_arg, /**< th
24622487
const ecma_value_t args[], /**< arguments list */
24632488
ecma_length_t args_number) /**< number of arguments */
24642489
{
2465-
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
2466-
ecma_value_t callbackfn = (args_number > 0) ? args[0] : ECMA_VALUE_UNDEFINED;
2467-
ecma_value_t initial_value = (args_number > 1) ? args[1] : ECMA_VALUE_UNDEFINED;
2468-
2469-
/* 1. */
2470-
ECMA_TRY_CATCH (obj_this,
2471-
ecma_op_to_object (this_arg),
2472-
ret_value);
2473-
2474-
ecma_object_t *obj_p = ecma_get_object_from_value (obj_this);
2475-
2476-
/* 2. */
2477-
ECMA_TRY_CATCH (len_value,
2478-
ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH),
2479-
ret_value);
2480-
2481-
ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value);
2482-
2483-
/* 3. */
2484-
uint32_t len = ecma_number_to_uint32 (len_number);
2485-
2486-
/* 4. */
2487-
if (!ecma_op_is_callable (callbackfn))
2488-
{
2489-
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Callback function is not callable."));
2490-
}
2491-
else
2492-
{
2493-
ecma_object_t *func_object_p;
2494-
2495-
JERRY_ASSERT (ecma_is_value_object (callbackfn));
2496-
func_object_p = ecma_get_object_from_value (callbackfn);
2497-
2498-
/* 5. */
2499-
if (len_number == ECMA_NUMBER_ZERO && ecma_is_value_undefined (initial_value))
2500-
{
2501-
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Initial value cannot be undefined."));
2502-
}
2503-
else
2504-
{
2505-
ecma_value_t accumulator = ECMA_VALUE_UNDEFINED;
2506-
2507-
/* 6. */
2508-
int64_t index = (int64_t) len - 1;
2509-
2510-
/* 7.a */
2511-
if (args_number > 1)
2512-
{
2513-
accumulator = ecma_copy_value (initial_value);
2514-
}
2515-
else
2516-
{
2517-
/* 8.a */
2518-
bool k_present = false;
2519-
2520-
/* 8.b */
2521-
while (!k_present && index >= 0 && ecma_is_value_empty (ret_value))
2522-
{
2523-
/* 8.b.i */
2524-
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 ((uint32_t) index);
2525-
k_present = true;
2526-
2527-
/* 8.b.ii-iii */
2528-
ECMA_TRY_CATCH (current_value, ecma_op_object_find (obj_p, index_str_p), ret_value);
2529-
2530-
if (ecma_is_value_found (current_value))
2531-
{
2532-
accumulator = ecma_copy_value (current_value);
2533-
}
2534-
else
2535-
{
2536-
k_present = false;
2537-
}
2538-
2539-
ECMA_FINALIZE (current_value);
2540-
2541-
/* 8.b.iv */
2542-
index--;
2543-
2544-
ecma_deref_ecma_string (index_str_p);
2545-
}
2546-
2547-
/* 8.c */
2548-
if (!k_present)
2549-
{
2550-
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Missing array element."));
2551-
}
2552-
}
2553-
/* 9. */
2554-
ecma_value_t current_index;
2555-
2556-
for (; index >= 0 && ecma_is_value_empty (ret_value); index--)
2557-
{
2558-
/* 9.a */
2559-
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 ((uint32_t) index);
2560-
2561-
/* 9.b */
2562-
ECMA_TRY_CATCH (current_value, ecma_op_object_find (obj_p, index_str_p), ret_value);
2563-
2564-
if (ecma_is_value_found (current_value))
2565-
{
2566-
/* 9.c.i, 9.c.ii */
2567-
current_index = ecma_make_uint32_value ((uint32_t) index);
2568-
ecma_value_t call_args[] = {accumulator, current_value, current_index, obj_this};
2569-
2570-
ECMA_TRY_CATCH (call_value,
2571-
ecma_op_function_call (func_object_p,
2572-
ECMA_VALUE_UNDEFINED,
2573-
call_args,
2574-
4),
2575-
ret_value);
2576-
2577-
ecma_free_value (accumulator);
2578-
accumulator = ecma_copy_value (call_value);
2579-
2580-
ECMA_FINALIZE (call_value);
2581-
}
2582-
2583-
ECMA_FINALIZE (current_value);
2584-
2585-
ecma_deref_ecma_string (index_str_p);
2586-
/* 9.d in for loop */
2587-
}
2588-
2589-
if (ecma_is_value_empty (ret_value))
2590-
{
2591-
ret_value = ecma_copy_value (accumulator);
2592-
}
2593-
2594-
ecma_free_value (accumulator);
2595-
}
2596-
}
2597-
2598-
ECMA_OP_TO_NUMBER_FINALIZE (len_number);
2599-
ECMA_FINALIZE (len_value);
2600-
ECMA_FINALIZE (obj_this);
2601-
2602-
return ret_value;
2490+
return ecma_builtin_array_reduce_from (this_arg, args, args_number, false);
26032491
} /* ecma_builtin_array_prototype_object_reduce_right */
26042492

26052493
/**

0 commit comments

Comments
 (0)