Skip to content

Commit aaeec7f

Browse files
committed
Implement Array.prototoype.toLocaleString()
JerryScript-DCO-1.0-Signed-off-by: Peter Gal [email protected]
1 parent cf70fc2 commit aaeec7f

File tree

5 files changed

+220
-0
lines changed

5 files changed

+220
-0
lines changed

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

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,105 @@ ecma_builtin_array_prototype_object_to_string (ecma_value_t this_arg) /**< this
469469
return return_value;
470470
} /* ecma_builtin_array_prototype_object_to_string */
471471

472+
473+
/**
474+
* The Array.prototype object's 'toLocaleString' routine
475+
*
476+
* See also:
477+
* ECMA-262 v5, 15.4.4.3
478+
*
479+
* @return completion value
480+
* Returned value must be freed with ecma_free_completion_value.
481+
*/
482+
static ecma_completion_value_t
483+
ecma_builtin_array_prototype_object_to_locale_string (const ecma_value_t this_arg) /**< this argument */
484+
{
485+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
486+
487+
/* 1. */
488+
ECMA_TRY_CATCH (obj_value,
489+
ecma_op_to_object (this_arg),
490+
ret_value);
491+
492+
ecma_object_t *obj_p = ecma_get_object_from_completion_value (obj_value);
493+
494+
ecma_string_t *length_magic_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH);
495+
496+
/* 2. */
497+
ECMA_TRY_CATCH (length_value,
498+
ecma_op_object_get (obj_p, length_magic_string_p),
499+
ret_value);
500+
501+
/* 3. */
502+
ECMA_OP_TO_NUMBER_TRY_CATCH (length_number,
503+
length_value,
504+
ret_value);
505+
506+
uint32_t length = ecma_number_to_uint32 (length_number);
507+
508+
/* 4. Implementation-defined: set the separator to a single comma character */
509+
ecma_string_t *separator_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_COMMA_CHAR);
510+
511+
/* 5. */
512+
if (length == 0)
513+
{
514+
ecma_string_t *empty_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING__EMPTY);
515+
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (empty_string_p));
516+
}
517+
else
518+
{
519+
/* 7-8. */
520+
ECMA_TRY_CATCH (first_value,
521+
ecma_builtin_helper_get_to_locale_string_at_index (obj_p, 0),
522+
ret_value);
523+
524+
ecma_string_t *return_string_p = ecma_copy_or_ref_ecma_string (ecma_get_string_from_value (first_value));
525+
526+
/* 9-10. */
527+
for (uint32_t k = 1; ecma_is_completion_value_empty (ret_value) && (k < length); ++k)
528+
{
529+
ecma_string_t *part_string_p = ecma_concat_ecma_strings (return_string_p, separator_string_p);
530+
531+
ECMA_TRY_CATCH (next_string_value,
532+
ecma_builtin_helper_get_to_locale_string_at_index (obj_p, k),
533+
ret_value);
534+
535+
ecma_string_t *next_string_p = ecma_get_string_from_completion_value (next_string_value);
536+
537+
ecma_deref_ecma_string (return_string_p);
538+
539+
return_string_p = ecma_concat_ecma_strings (part_string_p, next_string_p);
540+
541+
ECMA_FINALIZE (next_string_value);
542+
543+
ecma_deref_ecma_string (part_string_p);
544+
}
545+
546+
if (ecma_is_completion_value_empty (ret_value))
547+
{
548+
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (return_string_p));
549+
}
550+
else
551+
{
552+
ecma_deref_ecma_string (return_string_p);
553+
}
554+
555+
ECMA_FINALIZE (first_value);
556+
}
557+
558+
ecma_deref_ecma_string (separator_string_p);
559+
560+
ECMA_OP_TO_NUMBER_FINALIZE (length_number);
561+
562+
ECMA_FINALIZE (length_value);
563+
564+
ecma_deref_ecma_string (length_magic_string_p);
565+
566+
ECMA_FINALIZE (obj_value);
567+
568+
return ret_value;
569+
} /* ecma_builtin_array_prototype_object_to_locale_string */
570+
472571
/**
473572
* The Array.prototype object's 'pop' routine
474573
*

jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ ROUTINE (ECMA_MAGIC_STRING_FOR_EACH_UL, ecma_builtin_array_prototype_object_for_
6262
ROUTINE (ECMA_MAGIC_STRING_CONCAT, ecma_builtin_array_prototype_object_concat, NON_FIXED, 1)
6363
ROUTINE (ECMA_MAGIC_STRING_JOIN, ecma_builtin_array_prototype_join, 1, 1)
6464
ROUTINE (ECMA_MAGIC_STRING_TO_STRING_UL, ecma_builtin_array_prototype_object_to_string, 0, 0)
65+
ROUTINE (ECMA_MAGIC_STRING_TO_LOCALE_STRING_UL, ecma_builtin_array_prototype_object_to_locale_string, 0, 0)
6566
ROUTINE (ECMA_MAGIC_STRING_POP, ecma_builtin_array_prototype_object_pop, 0, 0)
6667
ROUTINE (ECMA_MAGIC_STRING_PUSH, ecma_builtin_array_prototype_object_push, NON_FIXED, 1)
6768
ROUTINE (ECMA_MAGIC_STRING_REVERSE, ecma_builtin_array_prototype_object_reverse, 0, 0)

jerry-core/ecma/builtin-objects/ecma-builtin-helpers.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818

1919
#include "ecma-builtins.h"
2020
#include "ecma-conversion.h"
21+
#include "ecma-function-object.h"
2122
#include "ecma-exceptions.h"
2223
#include "ecma-helpers.h"
2324
#include "ecma-objects.h"
25+
#include "ecma-try-catch-macro.h"
2426

2527
/** \addtogroup ecma ECMA
2628
* @{
@@ -122,6 +124,71 @@ ecma_builtin_helper_object_to_string (const ecma_value_t this_arg) /**< this arg
122124
return ecma_make_normal_completion_value (ecma_make_string_value (ret_string_p));
123125
} /* ecma_builtin_helper_object_to_string */
124126

127+
/**
128+
* The Array.prototype's 'toLocaleString' single element operation routine
129+
*
130+
* See also:
131+
* ECMA-262 v5, 15.4.4.3 steps 6-8 and 10.b-d
132+
*
133+
* @return completion value
134+
* Returned value must be freed with ecma_free_completion_value.
135+
*/
136+
ecma_completion_value_t
137+
ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, /** < this object */
138+
uint32_t index) /** < array index */
139+
{
140+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
141+
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
142+
143+
ECMA_TRY_CATCH (index_value,
144+
ecma_op_object_get (obj_p, index_string_p),
145+
ret_value);
146+
147+
if (ecma_is_value_undefined (index_value) || ecma_is_value_null (index_value))
148+
{
149+
ecma_string_t *return_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING__EMPTY);
150+
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (return_string_p));
151+
}
152+
else
153+
{
154+
ECMA_TRY_CATCH (index_obj_value,
155+
ecma_op_to_object (index_value),
156+
ret_value);
157+
158+
ecma_object_t *index_obj_p = ecma_get_object_from_value (index_obj_value);
159+
ecma_string_t *locale_string_magic_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_TO_LOCALE_STRING_UL);
160+
161+
ECMA_TRY_CATCH (to_locale_value,
162+
ecma_op_object_get (index_obj_p, locale_string_magic_string_p),
163+
ret_value);
164+
165+
if (ecma_op_is_callable (to_locale_value))
166+
{
167+
ecma_object_t *locale_func_obj_p = ecma_get_object_from_value (to_locale_value);
168+
ret_value = ecma_op_function_call (locale_func_obj_p,
169+
ecma_make_object_value (index_obj_p),
170+
NULL,
171+
0);
172+
}
173+
else
174+
{
175+
ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
176+
}
177+
178+
ECMA_FINALIZE (to_locale_value);
179+
180+
ecma_deref_ecma_string (locale_string_magic_string_p);
181+
182+
ECMA_FINALIZE (index_obj_value);
183+
}
184+
185+
ECMA_FINALIZE (index_value);
186+
187+
ecma_deref_ecma_string (index_string_p);
188+
189+
return ret_value;
190+
} /* ecma_builtin_helper_get_to_locale_string_at_index */
191+
125192
/**
126193
* @}
127194
* @}

jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
*/
2828

2929
extern ecma_completion_value_t ecma_builtin_helper_object_to_string (const ecma_value_t this_arg);
30+
extern ecma_completion_value_t ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, uint32_t index);
3031

3132
/**
3233
* @}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2015 Samsung Electronics Co., Ltd.
2+
// Copyright 2015 University of Szeged.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
assert ([].toLocaleString() === "");
17+
assert ([1].toLocaleString() === "1");
18+
assert ([1,2].toLocaleString() === "1,2");
19+
assert ([1,2,3].toLocaleString() === "1,2,3");
20+
21+
var test_ok = {
22+
length: 1,
23+
toLocaleString: function() { return "1"; }
24+
};
25+
26+
assert ([3, test_ok, 4, test_ok].toLocaleString() === "3,1,4,1");
27+
28+
29+
var test_fail = {
30+
toLocaleString: "FAIL"
31+
};
32+
33+
try {
34+
[test_fail].toLocaleString();
35+
assert (false);
36+
} catch (e) {
37+
assert (e instanceof TypeError);
38+
}
39+
40+
41+
var test_fail_call = {
42+
toLocaleString: function() { throw new ReferenceError("foo"); }
43+
};
44+
45+
46+
try {
47+
[1, 2, test_fail_call].toLocaleString();
48+
assert (false);
49+
} catch (e) {
50+
assert (e.message === "foo");
51+
assert (e instanceof ReferenceError);
52+
}

0 commit comments

Comments
 (0)