From 2d9d88327486248c7afb06091081acec1d8fde40 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 29 Nov 2020 20:28:10 +0100 Subject: LibJS: Add a basic implementation of String.prototype.substr() --- Libraries/LibJS/Runtime/CommonPropertyNames.h | 3 +- Libraries/LibJS/Runtime/StringPrototype.cpp | 35 ++++++++++++++++++++++ Libraries/LibJS/Runtime/StringPrototype.h | 1 + .../builtins/String/String.prototype.substr.js | 16 ++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 Libraries/LibJS/Tests/builtins/String/String.prototype.substr.js 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(""); +}); -- cgit v1.2.3