瀏覽代碼

LibJS: Add String.prototype.pad{Start,End}()

Linus Groh 5 年之前
父節點
當前提交
31505dde7e

+ 7 - 22
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);

+ 54 - 1
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);
+}
+
 }

+ 2 - 0
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&);
 };

+ 22 - 0
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);
+}

+ 22 - 0
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);
+}