diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c index 5e077236a..3e8253ebe 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c @@ -532,73 +532,167 @@ ecma_builtin_helper_string_index_normalize (ecma_number_t index, /**< index */ } /* ecma_builtin_helper_string_index_normalize */ /** - * Helper function for string indexOf and lastIndexOf functions - * - * This function implements string indexOf and lastIndexOf with required checks and conversions. + * Helper function for string indexOf, lastIndexOf, startsWith, includes, endsWith functions * * See also: * ECMA-262 v5, 15.5.4.7 * ECMA-262 v5, 15.5.4.8 + * ECMA-262 v6, 21.1.3.6 + * ECMA-262 v6, 21.1.3.7 + * ECMA-262 v6, 21.1.3.18 * * Used by: * - The String.prototype.indexOf routine. * - The String.prototype.lastIndexOf routine. + * - The String.prototype.startsWith routine. + * - The String.prototype.includes routine. + * - The String.prototype.endsWith routine. * - * @return ecma_value_t - (last) index of search string as an ecma-value + * @return ecma_value_t - Returns index (last index) or a + * boolean value */ ecma_value_t ecma_builtin_helper_string_prototype_object_index_of (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg1, /**< routine's first argument */ ecma_value_t arg2, /**< routine's second argument */ - bool first_index) /**< routine's third argument */ + ecma_string_index_of_mode_t mode) /**< routine's mode */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - /* 1 */ - ECMA_TRY_CATCH (check_coercible_val, - ecma_op_check_object_coercible (this_arg), - ret_value); + if (ECMA_IS_VALUE_ERROR (ecma_op_check_object_coercible (this_arg))) + { + return ECMA_VALUE_ERROR; + } /* 2 */ - ECMA_TRY_CATCH (to_str_val, - ecma_op_to_string (this_arg), - ret_value); + ecma_value_t to_str_val = ecma_op_to_string (this_arg); - /* 3 */ - ECMA_TRY_CATCH (search_str_val, - ecma_op_to_string (arg1), - ret_value); + if (ECMA_IS_VALUE_ERROR (to_str_val)) + { + return to_str_val; + } - /* 4 */ - ECMA_OP_TO_NUMBER_TRY_CATCH (pos_num, - arg2, - ret_value); - - /* 5 (indexOf) -- 6 (lastIndexOf) */ + /* 5 (indexOf), 6 (lastIndexOf), 11 (startsWith, includes) */ ecma_string_t *original_str_p = ecma_get_string_from_value (to_str_val); const ecma_length_t original_len = ecma_string_get_length (original_str_p); - /* 4b, 6 (indexOf) - 4b, 5, 7 (lastIndexOf) */ - ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len, first_index); +#if ENABLED (JERRY_ES2015_BUILTIN) + /* 4, 6 (startsWith, includes, endsWith) */ + if (mode >= ECMA_STRING_STARTS_WITH + && (ecma_is_value_object (arg1) + && ecma_object_class_is (ecma_get_object_from_value (arg1), LIT_MAGIC_STRING_REGEXP_UL))) + { + JERRY_ASSERT (ECMA_STRING_LAST_INDEX_OF < mode && mode <= ECMA_STRING_ENDS_WITH); + ecma_deref_ecma_string (original_str_p); + return ecma_raise_type_error (ECMA_ERR_MSG ("Search string can't be of type: RegExp")); + } +#endif /* ENABLED (JERRY_ES2015_BUILTIN) */ - /* 7 (indexOf) -- 8 (lastIndexOf) */ + /* 3 */ + ecma_value_t search_str_val = ecma_op_to_string (arg1); + + if (ECMA_IS_VALUE_ERROR (search_str_val)) + { + ecma_deref_ecma_string (original_str_p); + return search_str_val; + } + + /* 7, 8 */ ecma_string_t *search_str_p = ecma_get_string_from_value (search_str_val); + /* 4 (indexOf, lastIndexOf), 9 (startsWith, includes), 10 (endsWith) */ + ecma_number_t pos_num; + ecma_value_t ret_value = ecma_get_number (arg2, &pos_num); + + /* 10 (startsWith, includes), 11 (endsWith) */ + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_deref_ecma_string (original_str_p); + ecma_deref_ecma_string (search_str_p); + return ret_value; + } + + bool use_first_index = mode != ECMA_STRING_LAST_INDEX_OF; + + /* 4b, 6 (indexOf) - 4b, 5, 7 (lastIndexOf) */ + ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len, use_first_index); + ecma_number_t ret_num = ECMA_NUMBER_MINUS_ONE; - /* 8 (indexOf) -- 9 (lastIndexOf) */ ecma_length_t index_of = 0; - if (ecma_builtin_helper_string_find_index (original_str_p, search_str_p, first_index, start, &index_of)) + + ret_value = ECMA_VALUE_FALSE; + + switch (mode) { - ret_num = ((ecma_number_t) index_of); +#if ENABLED (JERRY_ES2015_BUILTIN) + case ECMA_STRING_STARTS_WITH: + { + if (pos_num + start > original_len) + { + break; + } + + if (ecma_builtin_helper_string_find_index (original_str_p, search_str_p, true, start, &index_of)) + { + /* 15, 16 (startsWith) */ + ret_value = ecma_make_boolean_value (index_of == start); + } + break; + } + case ECMA_STRING_INCLUDES: + { + if (ecma_builtin_helper_string_find_index (original_str_p, search_str_p, true, start, &index_of)) + { + ret_value = ECMA_VALUE_TRUE; + } + break; + } + case ECMA_STRING_ENDS_WITH: + { + if (start == 0) + { + start = original_len; + } + + ecma_length_t search_str_len = ecma_string_get_length (search_str_p); + + if (search_str_len == 0) + { + ret_value = ECMA_VALUE_TRUE; + break; + } + + int32_t start_ends_with = (int32_t) (start - search_str_len); + + if (start_ends_with < 0) + { + break; + } + if (ecma_builtin_helper_string_find_index (original_str_p, search_str_p, true, + (ecma_length_t) start_ends_with, &index_of)) + { + ret_value = ecma_make_boolean_value (index_of == (ecma_length_t) start_ends_with); + } + break; + } +#endif /* ENABLED (JERRY_ES2015_BUILTIN) */ + + case ECMA_STRING_INDEX_OF: + case ECMA_STRING_LAST_INDEX_OF: + default: + { + /* 8 (indexOf) -- 9 (lastIndexOf) */ + if (ecma_builtin_helper_string_find_index (original_str_p, search_str_p, use_first_index, start, &index_of)) + { + ret_num = ((ecma_number_t) index_of); + } + ret_value = ecma_make_number_value (ret_num); + break; + } } - ret_value = ecma_make_number_value (ret_num); - - ECMA_OP_TO_NUMBER_FINALIZE (pos_num); - ECMA_FINALIZE (search_str_val); - ECMA_FINALIZE (to_str_val); - ECMA_FINALIZE (check_coercible_val); + ecma_deref_ecma_string (search_str_p); + ecma_deref_ecma_string (original_str_p); return ret_value; } /* ecma_builtin_helper_string_prototype_object_index_of */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h index c1d327d5b..de78b721b 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h @@ -26,6 +26,19 @@ * @{ */ +/** + * Mode of string index routine. + */ +typedef enum +{ + /** These routines must be in this order */ + ECMA_STRING_INDEX_OF, /**< String.indexOf: ECMA-262 v5, 15.5.4.7 */ + ECMA_STRING_LAST_INDEX_OF, /**< String.lastIndexOf: ECMA-262 v5, 15.5.4.8 */ + ECMA_STRING_STARTS_WITH, /**< String.startsWith: ECMA-262 v6, 21.1.3.18 */ + ECMA_STRING_INCLUDES, /**< String.includes: ECMA-262 v6, 21.1.3.7 */ + ECMA_STRING_ENDS_WITH /**< String.includes: ECMA-262 v6, 21.1.3.6 */ +} ecma_string_index_of_mode_t; + ecma_value_t ecma_builtin_helper_object_to_string (const ecma_value_t this_arg); ecma_value_t @@ -40,7 +53,7 @@ uint32_t ecma_builtin_helper_string_index_normalize (ecma_number_t index, uint32_t length, bool nan_to_zero); ecma_value_t ecma_builtin_helper_string_prototype_object_index_of (ecma_value_t this_arg, ecma_value_t arg1, - ecma_value_t arg2, bool first_index); + ecma_value_t arg2, ecma_string_index_of_mode_t mode); bool ecma_builtin_helper_string_find_index (ecma_string_t *original_str_p, ecma_string_t *search_str_p, bool first_index, ecma_length_t start_pos, ecma_length_t *ret_index_p); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c index d862e0c7e..6e06aee76 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c @@ -270,6 +270,59 @@ ecma_builtin_string_prototype_object_concat (ecma_value_t this_arg, /**< this ar return ret_value; } /* ecma_builtin_string_prototype_object_concat */ +#if ENABLED (JERRY_ES2015_BUILTIN) +/** + * The String.prototype object's 'startsWith' routine + * + * See also: + * ECMA-262 v6, 21.1.3.18 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_starts_with (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + return ecma_builtin_helper_string_prototype_object_index_of (this_arg, arg1, arg2, ECMA_STRING_STARTS_WITH); +} /* ecma_builtin_string_prototype_object_starts_with */ + +/** + * The String.prototype object's 'includes' routine + * + * See also: + * ECMA-262 v6, 21.1.3.7 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_includes (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + return ecma_builtin_helper_string_prototype_object_index_of (this_arg, arg1, arg2, ECMA_STRING_INCLUDES); +} /* ecma_builtin_string_prototype_object_includes */ + +/** + * The String.prototype object's 'endsWith' routine + * + * See also: + * ECMA-262 v6, 21.1.3.6 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_ends_with (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + return ecma_builtin_helper_string_prototype_object_index_of (this_arg, arg1, arg2, ECMA_STRING_ENDS_WITH); +} /* ecma_builtin_string_prototype_object_ends_with */ +#endif /* ENABLED (JERRY_ES2015_BUILTIN) */ + /** * The String.prototype object's 'indexOf' routine * @@ -284,7 +337,7 @@ ecma_builtin_string_prototype_object_index_of (ecma_value_t this_arg, /**< this ecma_value_t arg1, /**< routine's first argument */ ecma_value_t arg2) /**< routine's second argument */ { - return ecma_builtin_helper_string_prototype_object_index_of (this_arg, arg1, arg2, true); + return ecma_builtin_helper_string_prototype_object_index_of (this_arg, arg1, arg2, ECMA_STRING_INDEX_OF); } /* ecma_builtin_string_prototype_object_index_of */ /** @@ -301,7 +354,7 @@ ecma_builtin_string_prototype_object_last_index_of (ecma_value_t this_arg, /**< ecma_value_t arg1, /**< routine's first argument */ ecma_value_t arg2) /**< routine's second argument */ { - return ecma_builtin_helper_string_prototype_object_index_of (this_arg, arg1, arg2, false); + return ecma_builtin_helper_string_prototype_object_index_of (this_arg, arg1, arg2, ECMA_STRING_LAST_INDEX_OF); } /* ecma_builtin_string_prototype_object_last_index_of */ /** 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 93942e01f..f451d0b6b 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 @@ -49,6 +49,12 @@ ROUTINE (LIT_MAGIC_STRING_CHAR_AT_UL, ecma_builtin_string_prototype_object_char_ ROUTINE (LIT_MAGIC_STRING_CHAR_CODE_AT_UL, ecma_builtin_string_prototype_object_char_code_at, 1, 1) ROUTINE (LIT_MAGIC_STRING_LOCALE_COMPARE_UL, ecma_builtin_string_prototype_object_locale_compare, 1, 1) +#if ENABLED (JERRY_ES2015_BUILTIN) +ROUTINE (LIT_MAGIC_STRING_STARTS_WITH, ecma_builtin_string_prototype_object_starts_with, 2, 1) +ROUTINE (LIT_MAGIC_STRING_INCLUDES, ecma_builtin_string_prototype_object_includes, 2, 1) +ROUTINE (LIT_MAGIC_STRING_ENDS_WITH, ecma_builtin_string_prototype_object_ends_with, 2, 1) +#endif /* ENABLED (JERRY_ES2015_BUILTIN) */ + #if ENABLED (JERRY_BUILTIN_REGEXP) ROUTINE (LIT_MAGIC_STRING_MATCH, ecma_builtin_string_prototype_object_match, 1, 1) ROUTINE (LIT_MAGIC_STRING_REPLACE, ecma_builtin_string_prototype_object_replace, 2, 2) diff --git a/jerry-core/lit/lit-magic-strings.inc.h b/jerry-core/lit/lit-magic-strings.inc.h index 199fb07fa..1c0bdfe9d 100644 --- a/jerry-core/lit/lit-magic-strings.inc.h +++ b/jerry-core/lit/lit-magic-strings.inc.h @@ -422,6 +422,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INFINITY_UL, "Infinity") #if ENABLED (JERRY_BUILTIN_ERRORS) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_URI_ERROR_UL, "URIError") #endif +#if ENABLED (JERRY_BUILTIN_STRING) && ENABLED (JERRY_ES2015_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENDS_WITH, "endsWith") +#endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION, "function") #if ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_HOURS_UL, "getHours") @@ -436,6 +439,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_MONTH_UL, "getMonth") #if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UINT8_UL, "getUint8") #endif +#if ENABLED (JERRY_BUILTIN_STRING) && ENABLED (JERRY_ES2015_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INCLUDES, "includes") +#endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_FINITE, "isFinite") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_FROZEN_UL, "isFrozen") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_SEALED_UL, "isSealed") @@ -557,6 +563,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_MINUTES_UL, "setMinutes") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_SECONDS_UL, "setSeconds") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_DATE_UL, "setUTCDate") #endif +#if ENABLED (JERRY_BUILTIN_STRING) && ENABLED (JERRY_ES2015_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STARTS_WITH, "startsWith") +#endif #if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) \ || ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ARRAY_BUFFER_UL, "ArrayBuffer") diff --git a/jerry-core/lit/lit-magic-strings.ini b/jerry-core/lit/lit-magic-strings.ini index 58afef467..fbf8b37ea 100644 --- a/jerry-core/lit/lit-magic-strings.ini +++ b/jerry-core/lit/lit-magic-strings.ini @@ -180,12 +180,14 @@ LIT_MAGIC_STRING_DATAVIEW_UL = "DataView" LIT_MAGIC_STRING_FUNCTION_UL = "Function" LIT_MAGIC_STRING_INFINITY_UL = "Infinity" LIT_MAGIC_STRING_URI_ERROR_UL = "URIError" +LIT_MAGIC_STRING_ENDS_WITH = "endsWith" LIT_MAGIC_STRING_FUNCTION = "function" LIT_MAGIC_STRING_GET_HOURS_UL = "getHours" LIT_MAGIC_STRING_GET_INT16_UL = "getInt16" LIT_MAGIC_STRING_GET_INT32_UL = "getInt32" LIT_MAGIC_STRING_GET_MONTH_UL = "getMonth" LIT_MAGIC_STRING_GET_UINT8_UL = "getUint8" +LIT_MAGIC_STRING_INCLUDES = "includes" LIT_MAGIC_STRING_IS_FINITE = "isFinite" LIT_MAGIC_STRING_IS_FROZEN_UL = "isFrozen" LIT_MAGIC_STRING_IS_SEALED_UL = "isSealed" @@ -244,6 +246,7 @@ LIT_MAGIC_STRING_SET_FLOAT_64_UL = "setFloat64" LIT_MAGIC_STRING_SET_MINUTES_UL = "setMinutes" LIT_MAGIC_STRING_SET_SECONDS_UL = "setSeconds" LIT_MAGIC_STRING_SET_UTC_DATE_UL = "setUTCDate" +LIT_MAGIC_STRING_STARTS_WITH = "startsWith" LIT_MAGIC_STRING_ARRAY_BUFFER_UL = "ArrayBuffer" LIT_MAGIC_STRING_SYNTAX_ERROR_UL = "SyntaxError" LIT_MAGIC_STRING_UINT16_ARRAY_UL = "Uint16Array" diff --git a/tests/jerry/es2015/string-prototype-endswith.js b/tests/jerry/es2015/string-prototype-endswith.js new file mode 100644 index 000000000..a08e9cfc2 --- /dev/null +++ b/tests/jerry/es2015/string-prototype-endswith.js @@ -0,0 +1,63 @@ +// 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 x = "Dancer of the Boreal Valley"; +assert (x.endsWith ("Valley")); +assert (x.endsWith ("Boreal", 20)); +assert (x.endsWith ("Dancer", 6)); +assert (x.endsWith ("")); +assert (x.endsWith ([])); + +var y = "Lalafell"; +assert (y.endsWith ("Lala") === false); +assert (y.endsWith ("fell", 2) === false); +assert (y.endsWith ("Final", "Fantasy") === false); +assert (y.endsWith ("Hydaelyn", 30) === false); +assert (y.endsWith (undefined) === false); + +assert(String.prototype.endsWith.call (5) === false); + +var test_obj = {toString: function() { return "A realm reborn"; } }; +test_obj.endsWith = String.prototype.endsWith; +assert (test_obj.endsWith ("reborn") === true); +assert (test_obj.endsWith ("realm") === false); + +try { + String.prototype.endsWith.call (Symbol()); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try { + String.prototype.endsWith.call (undefined); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try { + String.prototype.endsWith.call (null); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +var z = /[/]/; +try { + y.endsWith (z); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} diff --git a/tests/jerry/es2015/string-prototype-includes.js b/tests/jerry/es2015/string-prototype-includes.js new file mode 100644 index 000000000..36508b2ca --- /dev/null +++ b/tests/jerry/es2015/string-prototype-includes.js @@ -0,0 +1,62 @@ +// 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 x = "Good King Moggle Mog XII"; +assert (x.includes ("Moggle")); +assert (x.includes ("Moggle Mog", 3)); +assert (x.includes ("")); +assert (x.includes ([])); + +var y = "Nidhogg's Rage"; +assert (y.includes ("Dragon") === false); +assert (y.includes ("Rage", 11) === false); +assert (y.includes ("Final", "Fantasy") === false); +assert (y.includes ("Hydaelyn", 30) === false); +assert (y.includes (undefined) === false); + +assert(String.prototype.includes.call (5) === false); + +var test_obj = {toString: function() { return "The world of Eorzea"; } }; +test_obj.includes = String.prototype.includes; +assert (test_obj.includes ("Eorzea") === true); +assert (test_obj.includes ("Viera") === false); + +try { + String.prototype.includes.call (Symbol()); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try { + String.prototype.includes.call (undefined); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try { + String.prototype.includes.call (null); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +var z = /[/]/; +try { + y.includes (z); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} diff --git a/tests/jerry/es2015/string-prototype-startswith.js b/tests/jerry/es2015/string-prototype-startswith.js new file mode 100644 index 000000000..8926ce671 --- /dev/null +++ b/tests/jerry/es2015/string-prototype-startswith.js @@ -0,0 +1,53 @@ +// 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 x = "My cat is awesome"; +assert (x.startsWith ("My")); +assert (x.startsWith ("cat", 3)); +assert (x.startsWith ("")); +assert (x.startsWith ([])); + +assert (x.startsWith ("doggo") === false); +assert (x.startsWith ("awesome", 2) === false); +assert (x.startsWith ("awesome", "oi") === false); +assert (x.startsWith ("kitten", 30) === false); +assert (x.startsWith (undefined) === false); +assert(String.prototype.startsWith.call (5) === false); + +var test_obj = {toString: function() { return "The world of Eorzea"; } }; +test_obj.startsWith = String.prototype.startsWith; +assert (test_obj.startsWith ("The") === true); +assert (test_obj.startsWith ("Viera") === false); + +try { + String.prototype.startsWith.call (Symbol()); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try { + String.prototype.startsWith.call (undefined); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +y = /[/]/; +try { + x.startsWith (y); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +}