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