Implement Array.prototoype.toLocaleString()

JerryScript-DCO-1.0-Signed-off-by: Peter Gal pgal.u-szeged@partner.samsung.com
This commit is contained in:
Peter Gal
2015-05-22 18:41:49 +02:00
parent cf70fc2500
commit aaeec7fb09
5 changed files with 220 additions and 0 deletions
@@ -469,6 +469,105 @@ ecma_builtin_array_prototype_object_to_string (ecma_value_t this_arg) /**< this
return return_value;
} /* ecma_builtin_array_prototype_object_to_string */
/**
* The Array.prototype object's 'toLocaleString' routine
*
* See also:
* ECMA-262 v5, 15.4.4.3
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value.
*/
static ecma_completion_value_t
ecma_builtin_array_prototype_object_to_locale_string (const ecma_value_t this_arg) /**< this argument */
{
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
/* 1. */
ECMA_TRY_CATCH (obj_value,
ecma_op_to_object (this_arg),
ret_value);
ecma_object_t *obj_p = ecma_get_object_from_completion_value (obj_value);
ecma_string_t *length_magic_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH);
/* 2. */
ECMA_TRY_CATCH (length_value,
ecma_op_object_get (obj_p, length_magic_string_p),
ret_value);
/* 3. */
ECMA_OP_TO_NUMBER_TRY_CATCH (length_number,
length_value,
ret_value);
uint32_t length = ecma_number_to_uint32 (length_number);
/* 4. Implementation-defined: set the separator to a single comma character */
ecma_string_t *separator_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_COMMA_CHAR);
/* 5. */
if (length == 0)
{
ecma_string_t *empty_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING__EMPTY);
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (empty_string_p));
}
else
{
/* 7-8. */
ECMA_TRY_CATCH (first_value,
ecma_builtin_helper_get_to_locale_string_at_index (obj_p, 0),
ret_value);
ecma_string_t *return_string_p = ecma_copy_or_ref_ecma_string (ecma_get_string_from_value (first_value));
/* 9-10. */
for (uint32_t k = 1; ecma_is_completion_value_empty (ret_value) && (k < length); ++k)
{
ecma_string_t *part_string_p = ecma_concat_ecma_strings (return_string_p, separator_string_p);
ECMA_TRY_CATCH (next_string_value,
ecma_builtin_helper_get_to_locale_string_at_index (obj_p, k),
ret_value);
ecma_string_t *next_string_p = ecma_get_string_from_completion_value (next_string_value);
ecma_deref_ecma_string (return_string_p);
return_string_p = ecma_concat_ecma_strings (part_string_p, next_string_p);
ECMA_FINALIZE (next_string_value);
ecma_deref_ecma_string (part_string_p);
}
if (ecma_is_completion_value_empty (ret_value))
{
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (return_string_p));
}
else
{
ecma_deref_ecma_string (return_string_p);
}
ECMA_FINALIZE (first_value);
}
ecma_deref_ecma_string (separator_string_p);
ECMA_OP_TO_NUMBER_FINALIZE (length_number);
ECMA_FINALIZE (length_value);
ecma_deref_ecma_string (length_magic_string_p);
ECMA_FINALIZE (obj_value);
return ret_value;
} /* ecma_builtin_array_prototype_object_to_locale_string */
/**
* The Array.prototype object's 'pop' routine
*
@@ -62,6 +62,7 @@ ROUTINE (ECMA_MAGIC_STRING_FOR_EACH_UL, ecma_builtin_array_prototype_object_for_
ROUTINE (ECMA_MAGIC_STRING_CONCAT, ecma_builtin_array_prototype_object_concat, NON_FIXED, 1)
ROUTINE (ECMA_MAGIC_STRING_JOIN, ecma_builtin_array_prototype_join, 1, 1)
ROUTINE (ECMA_MAGIC_STRING_TO_STRING_UL, ecma_builtin_array_prototype_object_to_string, 0, 0)
ROUTINE (ECMA_MAGIC_STRING_TO_LOCALE_STRING_UL, ecma_builtin_array_prototype_object_to_locale_string, 0, 0)
ROUTINE (ECMA_MAGIC_STRING_POP, ecma_builtin_array_prototype_object_pop, 0, 0)
ROUTINE (ECMA_MAGIC_STRING_PUSH, ecma_builtin_array_prototype_object_push, NON_FIXED, 1)
ROUTINE (ECMA_MAGIC_STRING_REVERSE, ecma_builtin_array_prototype_object_reverse, 0, 0)
@@ -18,9 +18,11 @@
#include "ecma-builtins.h"
#include "ecma-conversion.h"
#include "ecma-function-object.h"
#include "ecma-exceptions.h"
#include "ecma-helpers.h"
#include "ecma-objects.h"
#include "ecma-try-catch-macro.h"
/** \addtogroup ecma ECMA
* @{
@@ -122,6 +124,71 @@ ecma_builtin_helper_object_to_string (const ecma_value_t this_arg) /**< this arg
return ecma_make_normal_completion_value (ecma_make_string_value (ret_string_p));
} /* ecma_builtin_helper_object_to_string */
/**
* The Array.prototype's 'toLocaleString' single element operation routine
*
* See also:
* ECMA-262 v5, 15.4.4.3 steps 6-8 and 10.b-d
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value.
*/
ecma_completion_value_t
ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, /** < this object */
uint32_t index) /** < array index */
{
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
ECMA_TRY_CATCH (index_value,
ecma_op_object_get (obj_p, index_string_p),
ret_value);
if (ecma_is_value_undefined (index_value) || ecma_is_value_null (index_value))
{
ecma_string_t *return_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING__EMPTY);
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (return_string_p));
}
else
{
ECMA_TRY_CATCH (index_obj_value,
ecma_op_to_object (index_value),
ret_value);
ecma_object_t *index_obj_p = ecma_get_object_from_value (index_obj_value);
ecma_string_t *locale_string_magic_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_TO_LOCALE_STRING_UL);
ECMA_TRY_CATCH (to_locale_value,
ecma_op_object_get (index_obj_p, locale_string_magic_string_p),
ret_value);
if (ecma_op_is_callable (to_locale_value))
{
ecma_object_t *locale_func_obj_p = ecma_get_object_from_value (to_locale_value);
ret_value = ecma_op_function_call (locale_func_obj_p,
ecma_make_object_value (index_obj_p),
NULL,
0);
}
else
{
ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
}
ECMA_FINALIZE (to_locale_value);
ecma_deref_ecma_string (locale_string_magic_string_p);
ECMA_FINALIZE (index_obj_value);
}
ECMA_FINALIZE (index_value);
ecma_deref_ecma_string (index_string_p);
return ret_value;
} /* ecma_builtin_helper_get_to_locale_string_at_index */
/**
* @}
* @}
@@ -27,6 +27,7 @@
*/
extern ecma_completion_value_t ecma_builtin_helper_object_to_string (const ecma_value_t this_arg);
extern ecma_completion_value_t ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, uint32_t index);
/**
* @}
@@ -0,0 +1,52 @@
// Copyright 2015 Samsung Electronics Co., Ltd.
// Copyright 2015 University of Szeged.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
assert ([].toLocaleString() === "");
assert ([1].toLocaleString() === "1");
assert ([1,2].toLocaleString() === "1,2");
assert ([1,2,3].toLocaleString() === "1,2,3");
var test_ok = {
length: 1,
toLocaleString: function() { return "1"; }
};
assert ([3, test_ok, 4, test_ok].toLocaleString() === "3,1,4,1");
var test_fail = {
toLocaleString: "FAIL"
};
try {
[test_fail].toLocaleString();
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}
var test_fail_call = {
toLocaleString: function() { throw new ReferenceError("foo"); }
};
try {
[1, 2, test_fail_call].toLocaleString();
assert (false);
} catch (e) {
assert (e.message === "foo");
assert (e instanceof ReferenceError);
}