summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2020-04-10 15:22:58 +0100
committerAndreas Kling <kling@serenityos.org>2020-04-10 16:37:04 +0200
commit31505dde7ec5e8077a5a72e7e50d4e5d7203432d (patch)
tree3c192b7eb1cac3fd1a1b64998535ee759c012d29
parent7636dee2cb64aa81b99df9aa69f0e9b3c19db1b9 (diff)
downloadserenity-31505dde7ec5e8077a5a72e7e50d4e5d7203432d.zip
LibJS: Add String.prototype.pad{Start,End}()
-rw-r--r--Base/home/anon/js/date.js29
-rw-r--r--Libraries/LibJS/Runtime/StringPrototype.cpp55
-rw-r--r--Libraries/LibJS/Runtime/StringPrototype.h2
-rw-r--r--Libraries/LibJS/Tests/String.prototype.padEnd.js22
-rw-r--r--Libraries/LibJS/Tests/String.prototype.padStart.js22
5 files changed, 107 insertions, 23 deletions
diff --git a/Base/home/anon/js/date.js b/Base/home/anon/js/date.js
index 56a40d619c..160786e0bc 100644
--- a/Base/home/anon/js/date.js
+++ b/Base/home/anon/js/date.js
@@ -1,29 +1,14 @@
var now = Date.now();
console.log("Unix timestamp: " + now / 1000);
-// FIXME: We need String.prototype.padStart() :^)
var d = new Date();
var year = d.getFullYear();
-var month = d.getMonth() + 1;
-if (month < 10)
- month = "0" + month;
-var day = d.getDate();
-if (day < 10)
- day = "0" + day;
-var hours = d.getHours();
-if (hours < 10)
- hours = "0" + hours;
-var minutes = d.getMinutes();
-if (minutes < 10)
- minutes = "0" + minutes;
-var seconds = d.getSeconds();
-if (seconds < 10)
- seconds = "0" + seconds;
-var milliseconds = d.getMilliseconds();
-if (milliseconds < 10) {
- milliseconds = "00" + milliseconds;
-} else if (milliseconds < 100) {
- milliseconds = "0" + milliseconds;
-}
+var month = (d.getMonth() + 1).toString().padStart(2, "0");
+var day = d.getDate().toString().padStart(2, "0");
+var hours = d.getHours().toString().padStart(2, "0");
+var minutes = d.getMinutes().toString().padStart(2, "0");
+var seconds = d.getSeconds().toString().padStart(2, "0");
+var milliseconds = d.getMilliseconds().toString().padStart(3, "0");
+
console.log("Date: " + year + "-" + month + "-" + day);
console.log("Time: " + hours + ":" + minutes + ":" + seconds + "." + milliseconds);
diff --git a/Libraries/LibJS/Runtime/StringPrototype.cpp b/Libraries/LibJS/Runtime/StringPrototype.cpp
index 93b0a6739a..5d8f97a909 100644
--- a/Libraries/LibJS/Runtime/StringPrototype.cpp
+++ b/Libraries/LibJS/Runtime/StringPrototype.cpp
@@ -49,6 +49,8 @@ StringPrototype::StringPrototype()
put_native_function("toLowerCase", to_lowercase, 0);
put_native_function("toUpperCase", to_uppercase, 0);
put_native_function("toString", to_string, 0);
+ put_native_function("padStart", pad_start, 1);
+ put_native_function("padEnd", pad_end, 1);
}
StringPrototype::~StringPrototype()
@@ -171,7 +173,7 @@ Value StringPrototype::length_getter(Interpreter& interpreter)
auto* string_object = string_object_from(interpreter);
if (!string_object)
return {};
- return Value((i32) string_object->primitive_string()->string().length());
+ return Value((i32)string_object->primitive_string()->string().length());
}
Value StringPrototype::to_string(Interpreter& interpreter)
@@ -182,4 +184,55 @@ Value StringPrototype::to_string(Interpreter& interpreter)
return js_string(interpreter, string_object->primitive_string()->string());
}
+enum class PadPlacement {
+ Start,
+ End,
+};
+
+static Value pad_string(Interpreter& interpreter, Object* object, PadPlacement placement)
+{
+ auto string = object->to_string().as_string()->string();
+ if (interpreter.argument(0).to_number().is_nan()
+ || interpreter.argument(0).to_number().is_undefined()
+ || interpreter.argument(0).to_number().to_i32() < 0) {
+ return js_string(interpreter, string);
+ }
+ auto max_length = static_cast<size_t>(interpreter.argument(0).to_i32());
+ if (max_length <= string.length())
+ return js_string(interpreter, string);
+
+ String fill_string = " ";
+ if (!interpreter.argument(1).is_undefined())
+ fill_string = interpreter.argument(1).to_string();
+ if (fill_string.is_empty())
+ return js_string(interpreter, string);
+
+ auto fill_length = max_length - string.length();
+
+ StringBuilder filler_builder;
+ while (filler_builder.length() < fill_length)
+ filler_builder.append(fill_string);
+ auto filler = filler_builder.build().substring(0, fill_length);
+
+ if (placement == PadPlacement::Start)
+ return js_string(interpreter, String::format("%s%s", filler.characters(), string.characters()));
+ return js_string(interpreter, String::format("%s%s", string.characters(), filler.characters()));
+}
+
+Value StringPrototype::pad_start(Interpreter& interpreter)
+{
+ auto* this_object = interpreter.this_value().to_object(interpreter.heap());
+ if (!this_object)
+ return {};
+ return pad_string(interpreter, this_object, PadPlacement::Start);
+}
+
+Value StringPrototype::pad_end(Interpreter& interpreter)
+{
+ auto* this_object = interpreter.this_value().to_object(interpreter.heap());
+ if (!this_object)
+ return {};
+ return pad_string(interpreter, this_object, PadPlacement::End);
+}
+
}
diff --git a/Libraries/LibJS/Runtime/StringPrototype.h b/Libraries/LibJS/Runtime/StringPrototype.h
index 06095e3736..b5ee2649e6 100644
--- a/Libraries/LibJS/Runtime/StringPrototype.h
+++ b/Libraries/LibJS/Runtime/StringPrototype.h
@@ -45,6 +45,8 @@ private:
static Value to_lowercase(Interpreter&);
static Value to_uppercase(Interpreter&);
static Value to_string(Interpreter&);
+ static Value pad_start(Interpreter&);
+ static Value pad_end(Interpreter&);
static Value length_getter(Interpreter&);
};
diff --git a/Libraries/LibJS/Tests/String.prototype.padEnd.js b/Libraries/LibJS/Tests/String.prototype.padEnd.js
new file mode 100644
index 0000000000..a654ec8b46
--- /dev/null
+++ b/Libraries/LibJS/Tests/String.prototype.padEnd.js
@@ -0,0 +1,22 @@
+try {
+ assert(String.prototype.padEnd.length === 1);
+
+ var s = "foo";
+ assert(s.padEnd(-1) === "foo");
+ assert(s.padEnd(0) === "foo");
+ assert(s.padEnd(3) === "foo");
+ assert(s.padEnd(5) === "foo ");
+ assert(s.padEnd(10) === "foo ");
+ assert(s.padEnd("5") === "foo ");
+ assert(s.padEnd([[["5"]]]) === "foo ");
+ assert(s.padEnd(2, "+") === "foo");
+ assert(s.padEnd(5, "+") === "foo++");
+ assert(s.padEnd(5, 1) === "foo11");
+ assert(s.padEnd(10, null) === "foonullnul");
+ assert(s.padEnd(10, "bar") === "foobarbarb");
+ assert(s.padEnd(10, "123456789") === "foo1234567");
+
+ console.log("PASS");
+} catch (e) {
+ console.log("FAIL: " + e);
+}
diff --git a/Libraries/LibJS/Tests/String.prototype.padStart.js b/Libraries/LibJS/Tests/String.prototype.padStart.js
new file mode 100644
index 0000000000..322d1c7a35
--- /dev/null
+++ b/Libraries/LibJS/Tests/String.prototype.padStart.js
@@ -0,0 +1,22 @@
+try {
+ assert(String.prototype.padStart.length === 1);
+
+ var s = "foo";
+ assert(s.padStart(-1) === "foo");
+ assert(s.padStart(0) === "foo");
+ assert(s.padStart(3) === "foo");
+ assert(s.padStart(5) === " foo");
+ assert(s.padStart(10) === " foo");
+ assert(s.padStart("5") === " foo");
+ assert(s.padStart([[["5"]]]) === " foo");
+ assert(s.padStart(2, "+") === "foo");
+ assert(s.padStart(5, "+") === "++foo");
+ assert(s.padStart(5, 1) === "11foo");
+ assert(s.padStart(10, null) === "nullnulfoo");
+ assert(s.padStart(10, "bar") === "barbarbfoo");
+ assert(s.padStart(10, "123456789") === "1234567foo");
+
+ console.log("PASS");
+} catch (e) {
+ console.log("FAIL: " + e);
+}