@@ -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. */
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