Implement String.prototype.codePointAt method (#3291)

The algorithm is based on ECMA-262 v6, 21.1.3.3

JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu
This commit is contained in:
Szilagyi Adam 2019-11-11 15:54:49 +01:00 committed by Robert Fancsik
parent da69589f05
commit 452c78182d
5 changed files with 114 additions and 0 deletions

View File

@ -30,6 +30,7 @@
#include "jrt.h"
#include "jrt-libc-includes.h"
#include "lit-char-helpers.h"
#include "lit-strings.h"
#if ENABLED (JERRY_BUILTIN_REGEXP)
#include "ecma-regexp-object.h"
@ -77,6 +78,7 @@ enum
ECMA_STRING_PROTOTYPE_SUBSTR,
ECMA_STRING_PROTOTYPE_REPEAT,
ECMA_STRING_PROTOTYPE_CODE_POINT_AT,
/* Note: These 5 routines MUST be in this order */
ECMA_STRING_PROTOTYPE_INDEX_OF,
ECMA_STRING_PROTOTYPE_LAST_INDEX_OF,
@ -1401,6 +1403,54 @@ ecma_builtin_string_prototype_object_repeat (ecma_string_t *original_string_p, /
return ecma_make_string_value (ret_string_p);
} /* ecma_builtin_string_prototype_object_repeat */
/**
* The String.prototype object's 'codePointAt' routine
*
* See also:
* ECMA-262 v6, 21.1.3.3
*
* @return lit_code_point_t
*/
static ecma_value_t
ecma_builtin_string_prototype_object_code_point_at (ecma_string_t *this_string_p, /**< this argument */
ecma_value_t pos) /**< given position */
{
ecma_number_t pos_num;
ecma_value_t error = ecma_op_to_integer (pos, &pos_num);
if (ECMA_IS_VALUE_ERROR (error))
{
return error;
}
ecma_length_t size = ecma_string_get_length (this_string_p);
if (pos_num < 0 || pos_num >= size)
{
return ECMA_VALUE_UNDEFINED;
}
uint32_t index = (uint32_t) pos_num;
ecma_char_t first = ecma_string_get_char_at_pos (this_string_p, index);
if (first < LIT_UTF16_HIGH_SURROGATE_MIN
|| first > LIT_UTF16_HIGH_SURROGATE_MAX
|| index + 1 == size)
{
return ecma_make_uint32_value (first);
}
ecma_char_t second = ecma_string_get_char_at_pos (this_string_p, index + 1);
if (second < LIT_UTF16_LOW_SURROGATE_MARKER
|| second > LIT_UTF16_LOW_SURROGATE_MAX)
{
return ecma_make_uint32_value (first);
}
return ecma_make_uint32_value (lit_convert_surrogate_pair_to_code_point (first, second));
} /* ecma_builtin_string_prototype_object_code_point_at */
#endif /* ENABLED (JERRY_ES2015_BUILTIN) */
#if ENABLED (JERRY_BUILTIN_ANNEXB)
@ -1615,6 +1665,11 @@ ecma_builtin_string_prototype_dispatch_routine (uint16_t builtin_routine_id, /**
ret_value = ecma_builtin_string_prototype_object_repeat (string_p, arg1);
break;
}
case ECMA_STRING_PROTOTYPE_CODE_POINT_AT:
{
ret_value = ecma_builtin_string_prototype_object_code_point_at (string_p, arg1);
break;
}
#endif /* ENABLED (JERRY_ES2015_BUILTIN) */
#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR)
case ECMA_STRING_PROTOTYPE_ITERATOR:

View File

@ -72,6 +72,7 @@ ROUTINE (LIT_MAGIC_STRING_REPEAT, ECMA_STRING_PROTOTYPE_REPEAT, 1, 1)
ROUTINE (LIT_MAGIC_STRING_STARTS_WITH, ECMA_STRING_PROTOTYPE_STARTS_WITH, 2, 1)
ROUTINE (LIT_MAGIC_STRING_INCLUDES, ECMA_STRING_PROTOTYPE_INCLUDES, 2, 1)
ROUTINE (LIT_MAGIC_STRING_ENDS_WITH, ECMA_STRING_PROTOTYPE_ENDS_WITH, 2, 1)
ROUTINE (LIT_MAGIC_STRING_CODE_POINT_AT, ECMA_STRING_PROTOTYPE_CODE_POINT_AT, 1, 1)
#endif /* ENABLED (JERRY_ES2015_BUILTIN) */
#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR)

View File

@ -612,6 +612,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYNTAX_ERROR_UL, "SyntaxError")
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UINT16_ARRAY_UL, "Uint16Array")
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UINT32_ARRAY_UL, "Uint32Array")
#endif
#if ENABLED (JERRY_BUILTIN_STRING) && ENABLED (JERRY_ES2015_BUILTIN)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CODE_POINT_AT, "codePointAt")
#endif
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CONSTRUCTOR, "constructor")
#if ENABLED (JERRY_BUILTIN_DATE)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_FULL_YEAR_UL, "getFullYear")

View File

@ -261,6 +261,7 @@ LIT_MAGIC_STRING_SYNTAX_ERROR_UL = "SyntaxError"
LIT_MAGIC_STRING_UINT16_ARRAY_UL = "Uint16Array"
LIT_MAGIC_STRING_UINT32_ARRAY_UL = "Uint32Array"
LIT_MAGIC_STRING_CONSTRUCTOR = "constructor"
LIT_MAGIC_STRING_CODE_POINT_AT = "codePointAt"
LIT_MAGIC_STRING_GET_FULL_YEAR_UL = "getFullYear"
LIT_MAGIC_STRING_GET_UTC_HOURS_UL = "getUTCHours"
LIT_MAGIC_STRING_GET_UTC_MONTH_UL = "getUTCMonth"

View File

@ -0,0 +1,54 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// 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.
var str = "A🌃B\uD800";
var obj = {};
// Test with normal inputs
assert(str.codePointAt(0) === 65);
assert(str.codePointAt(1) === 127747);
assert(str.codePointAt(2) === 57091);
assert(str.codePointAt(3) === 66);
assert(str.codePointAt(4) === 55296);
// Test with string
assert(str.codePointAt("a") === 65);
assert(str.codePointAt("B") === 65);
// Test with object
assert(str.codePointAt(obj) === 65);
// Test with NaN
assert(str.codePointAt(NaN) === 65);
// Test when the input >= length
assert(str.codePointAt(5) === undefined);
assert(str.codePointAt(10) === undefined);
// Test witn negative
assert(str.codePointAt(-1) === undefined);
assert(str.codePointAt(-5) === undefined);
assert(str.codePointAt(-0) === 65);
// Test with undefined and +/- Infinity
assert(str.codePointAt(undefined) === 65);
assert(str.codePointAt(Infinity) === undefined);
assert(str.codePointAt(-Infinity) === undefined);
// Test with boolean
assert(str.codePointAt(true) === 127747);
assert(str.codePointAt(false) === 65);
// Test when input > UINT32_MAX
assert(str.codePointAt(4294967299) === undefined);