summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-11-29 20:28:10 +0100
committerAndreas Kling <kling@serenityos.org>2020-11-29 20:29:49 +0100
commit2d9d88327486248c7afb06091081acec1d8fde40 (patch)
tree257709592821a9335d9bfaf043ff9e7d367a4703
parent5c911ad4b1fd63c951544de93870d059ec6d1558 (diff)
downloadserenity-2d9d88327486248c7afb06091081acec1d8fde40.zip
LibJS: Add a basic implementation of String.prototype.substr()
-rw-r--r--Libraries/LibJS/Runtime/CommonPropertyNames.h3
-rw-r--r--Libraries/LibJS/Runtime/StringPrototype.cpp35
-rw-r--r--Libraries/LibJS/Runtime/StringPrototype.h1
-rw-r--r--Libraries/LibJS/Tests/builtins/String/String.prototype.substr.js16
4 files changed, 54 insertions, 1 deletions
diff --git a/Libraries/LibJS/Runtime/CommonPropertyNames.h b/Libraries/LibJS/Runtime/CommonPropertyNames.h
index 780a48e757..f2803f3162 100644
--- a/Libraries/LibJS/Runtime/CommonPropertyNames.h
+++ b/Libraries/LibJS/Runtime/CommonPropertyNames.h
@@ -188,8 +188,9 @@ namespace JS {
P(splice) \
P(sqrt) \
P(startsWith) \
- P(stringify) \
P(sticky) \
+ P(stringify) \
+ P(substr) \
P(substring) \
P(tan) \
P(test) \
diff --git a/Libraries/LibJS/Runtime/StringPrototype.cpp b/Libraries/LibJS/Runtime/StringPrototype.cpp
index 46760d7118..bcfcb074cb 100644
--- a/Libraries/LibJS/Runtime/StringPrototype.cpp
+++ b/Libraries/LibJS/Runtime/StringPrototype.cpp
@@ -85,6 +85,7 @@ void StringPrototype::initialize(GlobalObject& global_object)
define_native_function(vm.names.trimStart, trim_start, 0, attr);
define_native_function(vm.names.trimEnd, trim_end, 0, attr);
define_native_function(vm.names.concat, concat, 1, attr);
+ define_native_function(vm.names.substr, substr, 2, attr);
define_native_function(vm.names.substring, substring, 2, attr);
define_native_function(vm.names.includes, includes, 1, attr);
define_native_function(vm.names.slice, slice, 2, attr);
@@ -355,6 +356,40 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substring)
return js_string(vm, string_part);
}
+JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substr)
+{
+ auto string = ak_string_from(vm, global_object);
+ if (string.is_null())
+ return {};
+ if (vm.argument_count() == 0)
+ return js_string(vm, string);
+
+ // FIXME: this should index a UTF-16 code_point view of the string.
+ auto string_length = (i32)string.length();
+
+ auto start_argument = vm.argument(0).to_i32(global_object);
+ if (vm.exception())
+ return {};
+
+ auto start = start_argument < 0 ? (string_length - -start_argument) : start_argument;
+
+ auto length = string_length - start;
+ if (vm.argument_count() >= 2) {
+ auto length_argument = vm.argument(1).to_i32(global_object);
+ if (vm.exception())
+ return {};
+ length = max(0, min(length_argument, length));
+ if (vm.exception())
+ return {};
+ }
+
+ if (length == 0)
+ return js_string(vm, String(""));
+
+ auto string_part = string.substring(start, length);
+ return js_string(vm, string_part);
+}
+
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::includes)
{
auto string = ak_string_from(vm, global_object);
diff --git a/Libraries/LibJS/Runtime/StringPrototype.h b/Libraries/LibJS/Runtime/StringPrototype.h
index bef8bb1aae..e412b713ef 100644
--- a/Libraries/LibJS/Runtime/StringPrototype.h
+++ b/Libraries/LibJS/Runtime/StringPrototype.h
@@ -50,6 +50,7 @@ private:
JS_DECLARE_NATIVE_FUNCTION(pad_start);
JS_DECLARE_NATIVE_FUNCTION(pad_end);
JS_DECLARE_NATIVE_FUNCTION(substring);
+ JS_DECLARE_NATIVE_FUNCTION(substr);
JS_DECLARE_NATIVE_GETTER(length_getter);
diff --git a/Libraries/LibJS/Tests/builtins/String/String.prototype.substr.js b/Libraries/LibJS/Tests/builtins/String/String.prototype.substr.js
new file mode 100644
index 0000000000..ade6c3c60a
--- /dev/null
+++ b/Libraries/LibJS/Tests/builtins/String/String.prototype.substr.js
@@ -0,0 +1,16 @@
+test("basic functionality", () => {
+ expect(String.prototype.substr).toHaveLength(2);
+
+ expect("hello friends".substr()).toBe("hello friends");
+ expect("hello friends".substr(1)).toBe("ello friends");
+ expect("hello friends".substr(0, 5)).toBe("hello");
+ expect("hello friends".substr(5, 6)).toBe(" frien");
+ expect("hello friends".substr("", 5)).toBe("hello");
+ expect("hello friends".substr(3, 3)).toBe("lo ");
+ expect("hello friends".substr(-1, 13)).toBe("s");
+ expect("hello friends".substr(0, 50)).toBe("hello friends");
+ expect("hello friends".substr(0, "5")).toBe("hello");
+ expect("hello friends".substr("2", "2")).toBe("ll");
+ expect("hello friends".substr(-7)).toBe("friends");
+ expect("hello friends".substr(-3, -5)).toBe("");
+});