Browse Source

Adding String.padStart and String.padEnd #429 (#434)

Adam Storr 7 years ago
parent
commit
15807f00bb
2 changed files with 78 additions and 2 deletions
  1. 27 2
      Jint.Tests/Runtime/EngineTests.cs
  2. 51 0
      Jint/Native/String/StringPrototype.cs

+ 27 - 2
Jint.Tests/Runtime/EngineTests.cs

@@ -2,14 +2,12 @@
 using System.Globalization;
 using System.IO;
 using System.Reflection;
-using System.Threading;
 using Jint.Native.Number;
 using Jint.Parser;
 using Jint.Parser.Ast;
 using Jint.Runtime;
 using Jint.Runtime.Debugger;
 using Xunit;
-using System.Net;
 
 namespace Jint.Tests.Runtime
 {
@@ -2153,5 +2151,32 @@ namespace Jint.Tests.Runtime
 
             Assert.Equal(expected, result);
         }
+
+        [Theory]
+        [InlineData("'abc'.padStart(10)", "       abc")]
+        [InlineData("'abc'.padStart(10, \"foo\")", "foofoofabc")]
+        [InlineData("'abc'.padStart(6, \"123456\")", "123abc")]
+        [InlineData("'abc'.padStart(8, \"0\")", "00000abc")]
+        [InlineData("'abc'.padStart(1)", "abc")]
+        public void ShouldPadStart(string source, object expected)
+        {
+            var engine = new Engine();
+            var result = engine.Execute(source).GetCompletionValue().ToObject();
+
+            Assert.Equal(expected, result);
+        }
+
+        [Theory]
+        [InlineData("'abc'.padEnd(10)", "abc       ")]
+        [InlineData("'abc'.padEnd(10, \"foo\")", "abcfoofoof")]
+        [InlineData("'abc'.padEnd(6, \"123456\")", "abc123")]
+        [InlineData("'abc'.padEnd(1)", "abc")]
+        public void ShouldPadEnd(string source, object expected)
+        {
+            var engine = new Engine();
+            var result = engine.Execute(source).GetCompletionValue().ToObject();
+
+            Assert.Equal(expected, result);
+        }
     }
 }

+ 51 - 0
Jint/Native/String/StringPrototype.cs

@@ -58,6 +58,8 @@ namespace Jint.Native.String
             FastAddProperty("toUpperCase", new ClrFunctionInstance(Engine, ToUpperCase), true, false, true);
             FastAddProperty("toLocaleUpperCase", new ClrFunctionInstance(Engine, ToLocaleUpperCase), true, false, true);
             FastAddProperty("trim", new ClrFunctionInstance(Engine, Trim), true, false, true);
+            FastAddProperty("padStart", new ClrFunctionInstance(Engine, PadStart), true, false, true);
+            FastAddProperty("padEnd", new ClrFunctionInstance(Engine, PadEnd), true, false, true);
         }
 
         private JsValue ToStringString(JsValue thisObj, JsValue[] arguments)
@@ -742,5 +744,54 @@ namespace Jint.Native.String
 
             return s.PrimitiveValue;
         }
+
+        /// <summary>
+        /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
+        /// </summary>
+        /// <param name="thisObj">The original string object</param>
+        /// <param name="arguments">
+        ///     argument[0] is the target length of the output string
+        ///     argument[1] is the string to pad with
+        /// </param>
+        /// <returns></returns>
+        private JsValue PadStart(JsValue thisObj, JsValue[] arguments)
+        {
+            return Pad(thisObj, arguments, true);
+        }
+
+        /// <summary>
+        /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
+        /// </summary>
+        /// <param name="thisObj">The original string object</param>
+        /// <param name="arguments">
+        ///     argument[0] is the target length of the output string
+        ///     argument[1] is the string to pad with
+        /// </param>
+        /// <returns></returns>
+        private JsValue PadEnd(JsValue thisObj, JsValue[] arguments)
+        {
+            return Pad(thisObj, arguments, false);
+        }
+
+        private JsValue Pad(JsValue thisObj, JsValue[] arguments, bool padStart)
+        {
+            TypeConverter.CheckObjectCoercible(Engine, thisObj);
+            var targetLength = TypeConverter.ToInt32(arguments.At(0));
+            var padString = TypeConverter.ToString(arguments.At(1, new JsValue(" ")));
+
+            var s = TypeConverter.ToString(thisObj);
+            if (s.Length > targetLength)
+            {
+                return s;
+            }
+
+            targetLength = targetLength - s.Length;
+            if (targetLength > padString.Length)
+            {
+                padString = string.Join("", Enumerable.Repeat(padString, (targetLength / padString.Length) + 1));
+            }
+
+            return padStart ? $"{padString.Substring(0, targetLength)}{s}" : $"{s}{padString.Substring(0, targetLength)}";
+        }
     }
 }