diff --git a/jerry-core/ecma/base/ecma-helpers-number.c b/jerry-core/ecma/base/ecma-helpers-number.c index 010bb8d00..9c9cc114a 100644 --- a/jerry-core/ecma/base/ecma-helpers-number.c +++ b/jerry-core/ecma/base/ecma-helpers-number.c @@ -729,13 +729,11 @@ ecma_number_parse_int (const lit_utf8_byte_t *string_buff, /**< routine's first return ecma_make_nan_value (); } - const lit_utf8_byte_t *string_curr_p = string_buff; + /* 2. Remove leading whitespace. */ - /* 2. Remove leading whitespace. */ - ecma_string_trim_helper (&string_curr_p, &string_buff_size); - - const lit_utf8_byte_t *string_end_p = string_curr_p + string_buff_size; - const lit_utf8_byte_t *start_p = string_curr_p; + const lit_utf8_byte_t *string_end_p = string_buff + string_buff_size; + const lit_utf8_byte_t *start_p = ecma_string_trim_front (string_buff, string_end_p); + const lit_utf8_byte_t *string_curr_p = start_p; const lit_utf8_byte_t *end_p = string_end_p; if (string_curr_p >= string_end_p) @@ -906,13 +904,11 @@ ecma_number_parse_float (const lit_utf8_byte_t *string_buff, /**< routine's firs return ecma_make_nan_value (); } - const lit_utf8_byte_t *str_curr_p = string_buff; - /* 2. Remove leading whitespace. */ - ecma_string_trim_helper (&str_curr_p, &string_buff_size); - const lit_utf8_byte_t *str_end_p = str_curr_p + string_buff_size; - const lit_utf8_byte_t *start_p = str_curr_p; + const lit_utf8_byte_t *str_end_p = string_buff + string_buff_size; + const lit_utf8_byte_t *start_p = ecma_string_trim_front (string_buff, str_end_p); + const lit_utf8_byte_t *str_curr_p = start_p; const lit_utf8_byte_t *end_p = str_end_p; bool sign = false; diff --git a/jerry-core/ecma/base/ecma-helpers-string.c b/jerry-core/ecma/base/ecma-helpers-string.c index 7f82c2d9c..9a69a42d1 100644 --- a/jerry-core/ecma/base/ecma-helpers-string.c +++ b/jerry-core/ecma/base/ecma-helpers-string.c @@ -2426,49 +2426,81 @@ ecma_string_substr (const ecma_string_t *string_p, /**< pointer to an ecma strin * Helper function for trimming. * * Used by: - * - ecma_string_trim - * - ecma_utf8_string_to_number + * - ecma_string_trim_helper * - ecma_builtin_global_object_parse_int * - ecma_builtin_global_object_parse_float + * + * @return position of the first non whitespace character. */ -void -ecma_string_trim_helper (const lit_utf8_byte_t **utf8_str_p, /**< [in, out] current string position */ - lit_utf8_size_t *utf8_str_size) /**< [in, out] size of the given string */ +const lit_utf8_byte_t * +ecma_string_trim_front (const lit_utf8_byte_t *start_p, /**< current string's start position */ + const lit_utf8_byte_t *end_p) /**< current string's end position */ { ecma_char_t ch; - lit_utf8_size_t read_size; - const lit_utf8_byte_t *nonws_start_p = *utf8_str_p + *utf8_str_size; - const lit_utf8_byte_t *current_p = *utf8_str_p; - while (current_p < nonws_start_p) + while (start_p < end_p) { - read_size = lit_read_code_unit_from_utf8 (current_p, &ch); - - if (!lit_char_is_white_space (ch)) - { - nonws_start_p = current_p; - break; - } - - current_p += read_size; - } - - current_p = *utf8_str_p + *utf8_str_size; - - while (current_p > nonws_start_p) - { - read_size = lit_read_prev_code_unit_from_utf8 (current_p, &ch); + lit_utf8_size_t read_size = lit_read_code_unit_from_utf8 (start_p, &ch); if (!lit_char_is_white_space (ch)) { break; } - current_p -= read_size; + start_p += read_size; } - *utf8_str_p = nonws_start_p; - *utf8_str_size = (lit_utf8_size_t) (current_p - nonws_start_p); + return start_p; +} /* ecma_string_trim_front */ + +/** + * Helper function for trimming. + * + * Used by: + * - ecma_string_trim_helper + * + * @return position of the last non whitespace character. + */ +const lit_utf8_byte_t * +ecma_string_trim_back (const lit_utf8_byte_t *start_p, /**< current string's start position */ + const lit_utf8_byte_t *end_p) /**< current string's end position */ +{ + ecma_char_t ch; + + while (end_p > start_p) + { + lit_utf8_size_t read_size = lit_read_prev_code_unit_from_utf8 (end_p, &ch); + + if (!lit_char_is_white_space (ch)) + { + break; + } + + end_p -= read_size; + } + + return end_p; +} /* ecma_string_trim_back */ + +/** + * Helper function for trimming. + * + * Used by: + * - ecma_string_trim + * - ecma_utf8_string_to_number + */ +inline void JERRY_ATTR_ALWAYS_INLINE +ecma_string_trim_helper (const lit_utf8_byte_t **utf8_str_p, /**< [in, out] current string position */ + lit_utf8_size_t *utf8_str_size) /**< [in, out] size of the given string */ +{ + const lit_utf8_byte_t *end_p = *utf8_str_p + *utf8_str_size; + const lit_utf8_byte_t *start_p = *utf8_str_p; + + const lit_utf8_byte_t *new_start_p = ecma_string_trim_front (start_p, end_p); + const lit_utf8_byte_t *new_end_p = ecma_string_trim_back (new_start_p, end_p); + + *utf8_str_size = (lit_utf8_size_t) (new_end_p - new_start_p); + *utf8_str_p = new_start_p; } /* ecma_string_trim_helper */ /** diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 55e08807b..cdb350e42 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -397,6 +397,8 @@ lit_magic_string_id_t ecma_get_string_magic (const ecma_string_t *string_p); lit_string_hash_t ecma_string_hash (const ecma_string_t *string_p); ecma_string_t *ecma_string_substr (const ecma_string_t *string_p, lit_utf8_size_t start_pos, lit_utf8_size_t end_pos); +const lit_utf8_byte_t *ecma_string_trim_front (const lit_utf8_byte_t *start_p, const lit_utf8_byte_t *end_p); +const lit_utf8_byte_t *ecma_string_trim_back (const lit_utf8_byte_t *start_p, const lit_utf8_byte_t *end_p); void ecma_string_trim_helper (const lit_utf8_byte_t **utf8_str_p, lit_utf8_size_t *utf8_str_size); ecma_string_t *ecma_string_trim (const ecma_string_t *string_p); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.c b/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.c index c87f2259b..a2474b57e 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.c @@ -18,7 +18,9 @@ #include "ecma-container-object.h" #include "ecma-array-object.h" #include "ecma-typedarray-object.h" +#include "ecma-string-object.h" #include "ecma-gc.h" +#include "ecma-helpers.h" #include "lit-char-helpers.h" #if ENABLED (JERRY_ESNEXT) @@ -44,7 +46,9 @@ enum ECMA_INTRINSIC_ARRAY_TO_STRING, ECMA_INTRINSIC_DATE_TO_UTC_STRING, ECMA_INTRINSIC_PARSE_FLOAT, - ECMA_INTRINSIC_PARSE_INT + ECMA_INTRINSIC_PARSE_INT, + ECMA_INTRINSIC_STRING_TRIM_START, + ECMA_INTRINSIC_STRING_TRIM_END, }; #define BUILTIN_INC_HEADER_NAME "ecma-builtin-intrinsic.inc.h" @@ -206,6 +210,48 @@ ecma_builtin_intrinsic_dispatch_routine (uint16_t builtin_routine_id, /**< built return ecma_date_value_to_utc_string (*prim_value_p); } + case ECMA_INTRINSIC_STRING_TRIM_START: + case ECMA_INTRINSIC_STRING_TRIM_END: + { + ecma_value_t coercible = ecma_op_check_object_coercible (this_arg); + + if (ECMA_IS_VALUE_ERROR (coercible)) + { + return coercible; + } + + ecma_string_t *to_str_p = ecma_op_to_string (this_arg); + if (to_str_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ECMA_STRING_TO_UTF8_STRING (to_str_p, start_p, input_start_size); + + lit_utf8_size_t size; + const lit_utf8_byte_t *input_start_p = start_p; + const lit_utf8_byte_t *input_str_end_p = start_p + input_start_size; + + ecma_string_t *ret_str_p; + if (builtin_routine_id == ECMA_INTRINSIC_STRING_TRIM_START) + { + const lit_utf8_byte_t *new_start_p = ecma_string_trim_front (input_start_p, input_str_end_p); + size = (lit_utf8_size_t) (input_str_end_p - new_start_p); + ret_str_p = ecma_new_ecma_string_from_utf8 (new_start_p, size); + } + else + { + const lit_utf8_byte_t *new_end_p = ecma_string_trim_back (input_start_p, input_str_end_p); + size = (lit_utf8_size_t) (new_end_p - input_start_p); + ret_str_p = ecma_new_ecma_string_from_utf8 (input_start_p, size); + } + + ECMA_FINALIZE_UTF8_STRING (start_p, input_start_size); + ecma_value_t result = ecma_make_string_value (ret_str_p); + ecma_deref_ecma_string (to_str_p); + return result; + + } default: { JERRY_ASSERT (builtin_routine_id == ECMA_INTRINSIC_PARSE_INT @@ -236,7 +282,6 @@ ecma_builtin_intrinsic_dispatch_routine (uint16_t builtin_routine_id, /**< built ECMA_FINALIZE_UTF8_STRING (string_buff, string_buff_size); ecma_deref_ecma_string (str_p); - return result; } } diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h index 89ae67c8b..d0063f7c9 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h @@ -74,6 +74,8 @@ ROUTINE (LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES, ECMA_INTRINSIC_ARRAY_ ROUTINE (LIT_INTERNAL_MAGIC_STRING_TYPEDARRAY_PROTOTYPE_VALUES, ECMA_INTRINSIC_TYPEDARRAY_PROTOTYPE_VALUES, 0, 0) ROUTINE (LIT_INTERNAL_MAGIC_STRING_SET_PROTOTYPE_VALUES, ECMA_INTRINSIC_SET_PROTOTYPE_VALUES, 0, 0) ROUTINE (LIT_INTERNAL_MAGIC_STRING_MAP_PROTOTYPE_ENTRIES, ECMA_INTRINSIC_MAP_PROTOTYPE_ENTRIES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TRIM_START, ECMA_INTRINSIC_STRING_TRIM_START, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TRIM_END, ECMA_INTRINSIC_STRING_TRIM_END, 0, 0) ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_INTRINSIC_ARRAY_TO_STRING, 0, 0) ROUTINE (LIT_MAGIC_STRING_TO_UTC_STRING_UL, ECMA_INTRINSIC_DATE_TO_UTC_STRING, 0, 0) ROUTINE (LIT_MAGIC_STRING_PARSE_FLOAT, ECMA_INTRINSIC_PARSE_FLOAT, 1, 1) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h index f3e685b4d..17663d3f1 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h @@ -76,6 +76,15 @@ ROUTINE (LIT_MAGIC_STRING_CODE_POINT_AT, ECMA_STRING_PROTOTYPE_CODE_POINT_AT, 1, ROUTINE (LIT_MAGIC_STRING_PAD_START, ECMA_STRING_PROTOTYPE_PAD_START, 2, 1) ROUTINE (LIT_MAGIC_STRING_PAD_END, ECMA_STRING_PROTOTYPE_PAD_END, 2, 1) ROUTINE (LIT_GLOBAL_SYMBOL_ITERATOR, ECMA_STRING_PROTOTYPE_ITERATOR, 0, 0) + +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TRIM_START, LIT_MAGIC_STRING_TRIM_START, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TRIM_LEFT, LIT_MAGIC_STRING_TRIM_START, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TRIM_END, LIT_MAGIC_STRING_TRIM_END, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TRIM_RIGHT, LIT_MAGIC_STRING_TRIM_END, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) #endif /* ENABLED (JERRY_ESNEXT) */ #endif /* ENABLED (JERRY_BUILTIN_STRING) */ diff --git a/jerry-core/lit/lit-magic-strings.inc.h b/jerry-core/lit/lit-magic-strings.inc.h index 62410e425..36e59c7ff 100644 --- a/jerry-core/lit/lit-magic-strings.inc.h +++ b/jerry-core/lit/lit-magic-strings.inc.h @@ -531,6 +531,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPECIES, "species") #if ENABLED (JERRY_BUILTIN_NUMBER) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_FIXED_UL, "toFixed") #endif +#if ENABLED (JERRY_ESNEXT) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM_END, "trimEnd") +#endif #if ENABLED (JERRY_BUILTIN_REGEXP) && ENABLED (JERRY_ESNEXT) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNICODE, "unicode") #endif @@ -598,6 +601,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UINT8_UL, "setUint8") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SUBARRAY, "subarray") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_STRING_UL, "toString") +#if ENABLED (JERRY_BUILTIN_STRING) && ENABLED (JERRY_ESNEXT) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM_LEFT, "trimLeft") +#endif #if ENABLED (JERRY_BUILTIN_ANNEXB) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNESCAPE, "unescape") #endif @@ -668,6 +674,12 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STRINGIFY, "stringify") #if ENABLED (JERRY_BUILTIN_STRING) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SUBSTRING, "substring") #endif +#if ENABLED (JERRY_BUILTIN_STRING) && ENABLED (JERRY_ESNEXT) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM_RIGHT, "trimRight") +#endif +#if ENABLED (JERRY_ESNEXT) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM_START, "trimStart") +#endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNDEFINED, "undefined") #if ENABLED (JERRY_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INT16_ARRAY_UL, "Int16Array") diff --git a/jerry-core/lit/lit-magic-strings.ini b/jerry-core/lit/lit-magic-strings.ini index a54ea5596..50f22c9e2 100644 --- a/jerry-core/lit/lit-magic-strings.ini +++ b/jerry-core/lit/lit-magic-strings.ini @@ -206,6 +206,7 @@ LIT_MAGIC_STRING_SET_INT8_UL = "setInt8" LIT_MAGIC_STRING_SET_YEAR_UL = "setYear" LIT_MAGIC_STRING_SPECIES = "species" LIT_MAGIC_STRING_TO_FIXED_UL = "toFixed" +LIT_MAGIC_STRING_TRIM_END = "trimEnd" LIT_MAGIC_STRING_UNICODE = "unicode" LIT_MAGIC_STRING_UNSHIFT = "unshift" LIT_MAGIC_STRING_VALUE_OF_UL = "valueOf" @@ -236,6 +237,7 @@ LIT_MAGIC_STRING_SET_MONTH_UL = "setMonth" LIT_MAGIC_STRING_SET_UINT8_UL = "setUint8" LIT_MAGIC_STRING_SUBARRAY = "subarray" LIT_MAGIC_STRING_TO_STRING_UL = "toString" +LIT_MAGIC_STRING_TRIM_LEFT = "trimLeft" LIT_MAGIC_STRING_UNESCAPE = "unescape" LIT_MAGIC_STRING_WRITABLE = "writable" LIT_MAGIC_STRING_OBJECT_TO_STRING_UL = "[object " @@ -267,6 +269,8 @@ LIT_MAGIC_STRING_STRINGIFY = "stringify" LIT_MAGIC_STRING_SET_UINT16_UL = "setUint16" LIT_MAGIC_STRING_SET_UINT32_UL = "setUint32" LIT_MAGIC_STRING_SUBSTRING = "substring" +LIT_MAGIC_STRING_TRIM_RIGHT = "trimRight" +LIT_MAGIC_STRING_TRIM_START = "trimStart" LIT_MAGIC_STRING_UNDEFINED = "undefined" LIT_MAGIC_STRING_INT16_ARRAY_UL = "Int16Array" LIT_MAGIC_STRING_INT32_ARRAY_UL = "Int32Array" diff --git a/tests/jerry/es.next/string-prototype-trim.js b/tests/jerry/es.next/string-prototype-trim.js new file mode 100644 index 000000000..7aaf2fea4 --- /dev/null +++ b/tests/jerry/es.next/string-prototype-trim.js @@ -0,0 +1,29 @@ +// 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 test = " asd "; +assert(test.trimStart() === "asd ") +assert(test.trimStart().length === 5) +assert(test.trimLeft() === "asd ") +assert(test.trimLeft().length === 5) +assert(String.prototype.trimStart === String.prototype.trimLeft) + +assert(test.trimEnd() === " asd") +assert(test.trimEnd().length === 5) +assert(test.trimRight() === " asd") +assert(test.trimRight().length === 5) +assert(String.prototype.trimEnd === String.prototype.trimRight) + +assert(test.trim() === "asd") +assert(test.trim().length === 3) diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml index eb9e46b68..04d54a78e 100644 --- a/tests/test262-esnext-excludelist.xml +++ b/tests/test262-esnext-excludelist.xml @@ -92,12 +92,6 @@ - - - - - - @@ -1947,50 +1941,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -