LibJS: Implement String.prototype.endsWith()

This commit is contained in:
Xavier Cooney 2020-12-25 12:58:34 +11:00 committed by Andreas Kling
parent 43f948b357
commit 1cf92d39eb
Notes: sideshowbarker 2024-07-19 00:36:17 +09:00
5 changed files with 88 additions and 0 deletions

View file

@ -93,6 +93,7 @@ namespace JS {
P(description) \
P(done) \
P(dotAll) \
P(endsWith) \
P(entries) \
P(enumerable) \
P(error) \

View file

@ -75,6 +75,7 @@ void StringPrototype::initialize(GlobalObject& global_object)
define_native_function(vm.names.charCodeAt, char_code_at, 1, attr);
define_native_function(vm.names.repeat, repeat, 1, attr);
define_native_function(vm.names.startsWith, starts_with, 1, attr);
define_native_function(vm.names.endsWith, ends_with, 1, attr);
define_native_function(vm.names.indexOf, index_of, 1, attr);
define_native_function(vm.names.toLowerCase, to_lowercase, 0, attr);
define_native_function(vm.names.toUpperCase, to_uppercase, 0, attr);
@ -185,6 +186,51 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::starts_with)
return Value(string.substring(start, search_string_length) == search_string);
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::ends_with)
{
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
auto search_string_value = vm.argument(0);
bool search_is_regexp = search_string_value.is_regexp(global_object);
if (vm.exception())
return {};
if (search_is_regexp) {
vm.throw_exception<TypeError>(global_object, ErrorType::IsNotA, "searchString", "string, but a regular expression");
return {};
}
auto search_string = search_string_value.to_string(global_object);
if (vm.exception())
return {};
auto string_length = string.length();
auto search_string_length = search_string.length();
size_t pos = string_length;
auto end_position_value = vm.argument(1);
if (!end_position_value.is_undefined()) {
auto number = end_position_value.to_number(global_object);
if (vm.exception())
return {};
double pos_as_double = number.to_integer_or_infinity(global_object);
if (vm.exception())
return {};
pos = clamp(pos_as_double, static_cast<double>(0), static_cast<double>(string_length));
}
if (search_string_length == 0)
return Value(true);
if (pos < search_string_length)
return Value(false);
auto start = pos - search_string_length;
return Value(string.substring(start, search_string_length) == search_string);
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::index_of)
{
auto string = ak_string_from(vm, global_object);

View file

@ -43,6 +43,7 @@ private:
JS_DECLARE_NATIVE_FUNCTION(char_code_at);
JS_DECLARE_NATIVE_FUNCTION(repeat);
JS_DECLARE_NATIVE_FUNCTION(starts_with);
JS_DECLARE_NATIVE_FUNCTION(ends_with);
JS_DECLARE_NATIVE_FUNCTION(index_of);
JS_DECLARE_NATIVE_FUNCTION(to_lowercase);
JS_DECLARE_NATIVE_FUNCTION(to_uppercase);

View file

@ -4,6 +4,7 @@ test("basic functionality", () => {
"charCodeAt",
"repeat",
"startsWith",
"endsWith",
"indexOf",
"toLowerCase",
"toUpperCase",

View file

@ -0,0 +1,39 @@
test("basic functionality", () => {
expect(String.prototype.endsWith).toHaveLength(1);
var s = "foobar";
expect(s.endsWith("r")).toBeTrue();
expect(s.endsWith("ar")).toBeTrue();
expect(s.endsWith("bar")).toBeTrue();
expect(s.endsWith("obar")).toBeTrue();
expect(s.endsWith("oobar")).toBeTrue();
expect(s.endsWith("foobar")).toBeTrue();
expect(s.endsWith("1foobar")).toBeFalse();
expect(s.endsWith("r", 6)).toBeTrue();
expect(s.endsWith("ar", 6)).toBeTrue();
expect(s.endsWith("bar", 6)).toBeTrue();
expect(s.endsWith("obar", 6)).toBeTrue();
expect(s.endsWith("oobar", 6)).toBeTrue();
expect(s.endsWith("foobar", 6)).toBeTrue();
expect(s.endsWith("1foobar", 6)).toBeFalse();
expect(s.endsWith("bar", [])).toBeFalse();
expect(s.endsWith("bar", null)).toBeFalse();
expect(s.endsWith("bar", false)).toBeFalse();
expect(s.endsWith("bar", true)).toBeFalse();
expect(s.endsWith("f", true)).toBeTrue();
expect(s.endsWith("bar", -1)).toBeFalse();
expect(s.endsWith("bar", 42)).toBeTrue();
expect(s.endsWith("foo", 3)).toBeTrue();
expect(s.endsWith("foo", "3")).toBeTrue();
expect(s.endsWith("foo1", 3)).toBeFalse();
expect(s.endsWith("foo", 3.7)).toBeTrue();
expect(s.endsWith()).toBeFalse();
expect(s.endsWith("")).toBeTrue();
expect(s.endsWith("", 0)).toBeTrue();
expect(s.endsWith("", 1)).toBeTrue();
expect(s.endsWith("", -1)).toBeTrue();
expect(s.endsWith("", 42)).toBeTrue();
expect("12undefined".endsWith()).toBeTrue();
expect(() => s.endsWith(/foobar/)).toThrowWithMessage(TypeError, "searchString is not a string, but a regular expression");
expect(s.endsWith("bar", undefined)).toBeTrue();
});