diff options
author | Linus Groh <mail@linusgroh.de> | 2020-04-10 15:22:58 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-04-10 16:37:04 +0200 |
commit | 31505dde7ec5e8077a5a72e7e50d4e5d7203432d (patch) | |
tree | 3c192b7eb1cac3fd1a1b64998535ee759c012d29 | |
parent | 7636dee2cb64aa81b99df9aa69f0e9b3c19db1b9 (diff) | |
download | serenity-31505dde7ec5e8077a5a72e7e50d4e5d7203432d.zip |
LibJS: Add String.prototype.pad{Start,End}()
-rw-r--r-- | Base/home/anon/js/date.js | 29 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/StringPrototype.cpp | 55 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/StringPrototype.h | 2 | ||||
-rw-r--r-- | Libraries/LibJS/Tests/String.prototype.padEnd.js | 22 | ||||
-rw-r--r-- | Libraries/LibJS/Tests/String.prototype.padStart.js | 22 |
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); +} |