Skip to content

Commit

Permalink
Implement String.prototype.padStart and .padEnd in JS
Browse files Browse the repository at this point in the history
Summary: Implement `String.prototype.padStart` and `String.prototype.padEnd` in JS

Reviewed By: dulinriley

Differential Revision: D18063296

fbshipit-source-id: a65587648755bd97886e887dbb8d5446a9da42b3
  • Loading branch information
Kiwi137 authored and facebook-github-bot committed Nov 6, 2019
1 parent fb156d2 commit 65d0d2c
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 123 deletions.
2 changes: 1 addition & 1 deletion include/hermes/VM/NativeFunctions.def
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,6 @@ NATIVE_FUNCTION(stringPrototypeCodePointAt)
NATIVE_FUNCTION(stringPrototypeConcat)
NATIVE_FUNCTION(stringPrototypeLocaleCompare)
NATIVE_FUNCTION(stringPrototypeNormalize)
NATIVE_FUNCTION(stringPrototypePad)
NATIVE_FUNCTION(stringPrototypeRepeat)
NATIVE_FUNCTION(stringPrototypeReplace)
NATIVE_FUNCTION(stringPrototypeSubstr)
Expand All @@ -309,6 +308,7 @@ NATIVE_FUNCTION(stringPrototypeIncludesOrStartsWith)
NATIVE_FUNCTION(stringPrototypeIndexOf)
NATIVE_FUNCTION(stringPrototypeLastIndexOf)
NATIVE_FUNCTION(stringPrototypeMatch)
NATIVE_FUNCTION(stringPrototypePad)
NATIVE_FUNCTION(stringPrototypeSearch)
NATIVE_FUNCTION(stringPrototypeSlice)
NATIVE_FUNCTION(stringPrototypeSplit)
Expand Down
100 changes: 100 additions & 0 deletions lib/InternalBytecode/String.js
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,102 @@ String.prototype.slice = function slice(start, end) {
return HermesInternal.executeCall(_StringPrototypeSubstring, S, from, to);
};

/**
* Helper function for String.prototype.padStart and String.prototype.padEnd,
* see their docuemntations for more details.
* @param str a value that's coercible to string.
* @param maxLength maximum length of the resulting string.
* @param fillString string used for padding, defaults to ' ' if it's
* undefined.
* @param padStart boolean flag for whether the caller function is
* padStart or padEnd.
* @return the resulting string after padding fillString to `this` string.
*/
function stringPrototypePadHelper(str, maxLength, fillString, padStart) {
if (new.target)
throw _TypeError('This function cannot be used as a constructor.');

// 1. Let O be ? RequireObjectCoercible(this value).
if (str === undefined || str === null) {
throw _TypeError('Value not coercible to object');
}
// 2. Let S be ? ToString(O).
var S = HermesInternal.toString(str);

// 3. Let intMaxLength be ? ToLength(maxLength).
var intMaxLength = HermesInternal.toLength(maxLength);
// 4. Let stringLength be the length of S.
var stringLength = S.length;

// 5. If intMaxLength is not greater than stringLength, return S.
if (intMaxLength <= stringLength) return S;
// 6. If fillString is undefined, let filler be the String value consisting solely
// of the code unit 0x0020 (SPACE).
// 7. Else, let filler be ? ToString(fillString).
var filler =
fillString === undefined ? ' ' : HermesInternal.toString(fillString);
var fillerLen = filler.length;
// 8. If filler is the empty String, return S.
if (fillerLen === 0) return S;
// 9. Let fillLen be intMaxLength - stringLength.
var fillLen = intMaxLength - stringLength;

// 10. Let truncatedStringFiller be the String value consisting of repeated
// concatenations of filler truncated to length fillLen.
var truncatedLen = fillLen % fillerLen;
var repeatTimes = fillLen / fillerLen;
var truncatedStringFiller =
HermesInternal.executeCall(_StringPrototypeRepeat, filler, repeatTimes) +
HermesInternal.executeCall(
_StringPrototypeSubstring,
filler,
0,
truncatedLen,
);

// 11. Return the string-concatenation of truncatedStringFiller and S.
return padStart ? truncatedStringFiller + S : S + truncatedStringFiller;
}

/**
* ES10.0 21.1.3.14
* Pads repeated copies of fillString in front of `this` string
* until the length achieves maxLength.
* Will coerce both values to strings if they aren't already.
* @this a value that's coercible to string.
* @param maxLength maximum length of the resulting string.
* @param [fillString] string used for padding, defaults to ' '
* if it's undefined.
* @return the resulting string after padding fillString in front
* of `this` string.
*/
String.prototype.padStart = function padStart(
maxLength,
fillString = undefined,
) {
if (new.target)
throw _TypeError('This function cannot be used as a constructor.');
return stringPrototypePadHelper(this, maxLength, fillString, true);
};

/**
* ES10.0 21.1.3.14
* Pads repeated copies of fillString to the end of `this` string
* until the length achieves maxLength.
* Will coerce both values to strings if they aren't already.
* @this a value that's coercible to string.
* @param maxLength maximum length of the resulting string.
* @param [fillString] string used for padding, defaults to ' '
* if it's undefined.
* @return the resulting string after padding fillString to the end
* of `this` string.
*/
String.prototype.padEnd = function padEnd(maxLength, fillString = undefined) {
if (new.target)
throw _TypeError('This function cannot be used as a constructor.');
return stringPrototypePadHelper(this, maxLength, fillString, false);
};

Object.defineProperty(String.prototype, 'charAt', builtinFuncDescriptor);
Object.defineProperty(String.prototype, 'match', builtinFuncDescriptor);
Object.defineProperty(String.prototype, 'search', builtinFuncDescriptor);
Expand All @@ -560,6 +656,8 @@ Object.defineProperty(String.prototype, 'indexOf', builtinFuncDescriptor);
Object.defineProperty(String.prototype, 'lastIndexOf', builtinFuncDescriptor);
Object.defineProperty(String.prototype, 'split', builtinFuncDescriptor);
Object.defineProperty(String.prototype, 'slice', builtinFuncDescriptor);
Object.defineProperty(String.prototype, 'padStart', builtinFuncDescriptor);
Object.defineProperty(String.prototype, 'padEnd', builtinFuncDescriptor);

String.prototype.charAt.prototype = undefined;
String.prototype.match.prototype = undefined;
Expand All @@ -571,3 +669,5 @@ String.prototype.indexOf.prototype = undefined;
String.prototype.lastIndexOf.prototype = undefined;
String.prototype.split.prototype = undefined;
String.prototype.slice.prototype = undefined;
String.prototype.padStart.prototype = undefined;
String.prototype.padEnd.prototype = undefined;
1 change: 1 addition & 0 deletions lib/InternalBytecode/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
var _MathMax = Math.max;
var _MathMin = Math.min;
var _ObjectDefineProperty = Object.defineProperty;
var _StringPrototypeRepeat = String.prototype.repeat;
var _StringPrototypeSubstring = String.prototype.substring;
var _SymbolIterator = Symbol.iterator;
var _SymbolMatch = Symbol.match;
Expand Down
Loading

0 comments on commit 65d0d2c

Please sign in to comment.