@@ -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 */
24152416static 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