From 0a94661c148a17f455875bd29f977eed2e080d25 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sun, 29 Mar 2020 17:15:00 +0100 Subject: LibJS: Implement String.prototype.startsWith() --- Libraries/LibJS/Runtime/StringPrototype.cpp | 27 +++++++++++++++ Libraries/LibJS/Runtime/StringPrototype.h | 1 + .../LibJS/Tests/String.prototype.startsWith.js | 40 ++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 Libraries/LibJS/Tests/String.prototype.startsWith.js (limited to 'Libraries/LibJS') diff --git a/Libraries/LibJS/Runtime/StringPrototype.cpp b/Libraries/LibJS/Runtime/StringPrototype.cpp index 5d05545d05..6e871db061 100644 --- a/Libraries/LibJS/Runtime/StringPrototype.cpp +++ b/Libraries/LibJS/Runtime/StringPrototype.cpp @@ -41,6 +41,7 @@ StringPrototype::StringPrototype() put_native_property("length", length_getter, nullptr); put_native_function("charAt", char_at); put_native_function("repeat", repeat); + put_native_function("startsWith", starts_with); } StringPrototype::~StringPrototype() @@ -83,6 +84,32 @@ Value StringPrototype::repeat(Interpreter& interpreter) return js_string(interpreter.heap(), builder.to_string()); } +Value StringPrototype::starts_with(Interpreter& interpreter) +{ + auto* this_object = interpreter.this_value().to_object(interpreter.heap()); + if (!this_object) + return {}; + if (interpreter.call_frame().arguments.is_empty()) + return Value(false); + auto search_string = interpreter.call_frame().arguments[0].to_string(); + auto search_string_length = static_cast(search_string.length()); + i32 position = 0; + if (interpreter.call_frame().arguments.size() > 1) { + auto number = interpreter.call_frame().arguments[1].to_number(); + if (!number.is_nan()) + position = number.to_i32(); + } + ASSERT(this_object->is_string_object()); + auto underlying_string = static_cast(this_object)->primitive_string()->string(); + auto underlying_string_length = static_cast(underlying_string.length()); + auto start = min(max(position, 0), underlying_string_length); + if (start + search_string_length > underlying_string_length) + return Value(false); + if (search_string_length == 0) + return Value(true); + return Value(underlying_string.substring(start, search_string_length) == search_string); +} + Value StringPrototype::length_getter(Interpreter& interpreter) { auto* this_object = interpreter.this_value().to_object(interpreter.heap()); diff --git a/Libraries/LibJS/Runtime/StringPrototype.h b/Libraries/LibJS/Runtime/StringPrototype.h index b12c674584..000f373fb6 100644 --- a/Libraries/LibJS/Runtime/StringPrototype.h +++ b/Libraries/LibJS/Runtime/StringPrototype.h @@ -40,6 +40,7 @@ private: static Value char_at(Interpreter&); static Value repeat(Interpreter&); + static Value starts_with(Interpreter&); static Value length_getter(Interpreter&); }; diff --git a/Libraries/LibJS/Tests/String.prototype.startsWith.js b/Libraries/LibJS/Tests/String.prototype.startsWith.js new file mode 100644 index 0000000000..b194816e43 --- /dev/null +++ b/Libraries/LibJS/Tests/String.prototype.startsWith.js @@ -0,0 +1,40 @@ +function assert(x) { if (!x) throw 1; } + +try { + var s = "foobar"; + assert(s.startsWith("f") === true); + assert(s.startsWith("fo") === true); + assert(s.startsWith("foo") === true); + assert(s.startsWith("foob") === true); + assert(s.startsWith("fooba") === true); + assert(s.startsWith("foobar") === true); + assert(s.startsWith("foobar1") === false); + assert(s.startsWith("f", 0) === true); + assert(s.startsWith("fo", 0) === true); + assert(s.startsWith("foo", 0) === true); + assert(s.startsWith("foob", 0) === true); + assert(s.startsWith("fooba", 0) === true); + assert(s.startsWith("foobar", 0) === true); + assert(s.startsWith("foobar1", 0) === false); + assert(s.startsWith("foo", []) === true); + assert(s.startsWith("foo", null) === true); + assert(s.startsWith("foo", undefined) === true); + assert(s.startsWith("foo", false) === true); + assert(s.startsWith("foo", true) === false); + assert(s.startsWith("foo", "foo") === true); + assert(s.startsWith("foo", 0 - 1) === true); + assert(s.startsWith("foo", 42) === false); + assert(s.startsWith("bar", 3) === true); + assert(s.startsWith("bar", "3") === true); + assert(s.startsWith("bar1", 3) === false); + assert(s.startsWith() === false); + assert(s.startsWith("") === true); + assert(s.startsWith("", 0) === true); + assert(s.startsWith("", 1) === true); + assert(s.startsWith("", 0 - 1) === true); + assert(s.startsWith("", 42) === true); + + console.log("PASS"); +} catch (e) { + console.log("FAIL: " + e); +} -- cgit v1.2.3