Commit 1a272ba2 authored by caitpotter88's avatar caitpotter88 Committed by Commit bot

[esnext] implement String padding proposal

Spec http://tc39.github.io/proposal-string-pad-start-end/

BUG=
LOG=Y
R=adamk@chromium.org, littledan@chromium.org

Review URL: https://codereview.chromium.org/1700003002

Cr-Commit-Position: refs/heads/master@{#35061}
parent fb65527b
......@@ -310,6 +310,7 @@ action("js2c_experimental") {
"src/js/harmony-simd.js",
"src/js/harmony-species.js",
"src/js/harmony-unicode-regexps.js",
"src/js/harmony-string-padding.js",
"src/js/promise-extra.js"
]
......
......@@ -2372,6 +2372,7 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_tailcalls)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_instanceof)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_restrictive_declarations)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_exponentiation_operator)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_string_padding)
void InstallPublicSymbol(Factory* factory, Handle<Context> native_context,
const char* name, Handle<Symbol> value) {
......@@ -2955,6 +2956,8 @@ bool Genesis::InstallExperimentalNatives() {
nullptr};
static const char* harmony_array_prototype_values_natives[] = {nullptr};
static const char* harmony_exponentiation_operator_natives[] = {nullptr};
static const char* harmony_string_padding_natives[] = {
"native harmony-string-padding.js", nullptr};
for (int i = ExperimentalNatives::GetDebuggerCount();
i < ExperimentalNatives::GetBuiltinsCount(); i++) {
......
......@@ -199,7 +199,8 @@ DEFINE_IMPLICATION(es_staging, move_object_start)
V(harmony_sharedarraybuffer, "harmony sharedarraybuffer") \
V(harmony_simd, "harmony simd") \
V(harmony_do_expressions, "harmony do-expressions") \
V(harmony_regexp_property, "harmony unicode regexp property classes")
V(harmony_regexp_property, "harmony unicode regexp property classes") \
V(harmony_string_padding, "harmony String-padding methods")
// Features that are complete (but still behind --harmony/es-staging flag).
#define HARMONY_STAGED(V) \
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function(global, utils) {
%CheckIsBootstrapping();
// -------------------------------------------------------------------
// Imports
var GlobalString = global.String;
var MakeTypeError;
utils.Import(function(from) {
MakeTypeError = from.MakeTypeError;
});
// -------------------------------------------------------------------
// http://tc39.github.io/proposal-string-pad-start-end/
function StringPad(thisString, maxLength, fillString) {
maxLength = TO_LENGTH(maxLength);
var stringLength = thisString.length;
if (maxLength <= stringLength) return "";
if (IS_UNDEFINED(fillString)) {
fillString = " ";
} else {
fillString = TO_STRING(fillString);
if (fillString === "") {
fillString = " ";
}
}
var fillLength = maxLength - stringLength;
var repetitions = (fillLength / fillString.length) | 0;
var remainingChars = (fillLength - fillString.length * repetitions) | 0;
var filler = "";
while (true) {
if (repetitions & 1) filler += fillString;
repetitions >>= 1;
if (repetitions === 0) break;
fillString += fillString;
}
if (remainingChars) {
filler += %_SubString(fillString, 0, remainingChars);
}
return filler;
}
function StringPadStart(maxLength, fillString) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.padStart")
var thisString = TO_STRING(this);
return StringPad(thisString, maxLength, fillString) + thisString;
}
%FunctionSetLength(StringPadStart, 1);
function StringPadEnd(maxLength, fillString) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.padEnd")
var thisString = TO_STRING(this);
return thisString + StringPad(thisString, maxLength, fillString);
}
%FunctionSetLength(StringPadEnd, 1);
utils.InstallFunctions(GlobalString.prototype, DONT_ENUM, [
"padStart", StringPadStart,
"padEnd", StringPadEnd
]);
});
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-string-padding
(function TestMeta() {
assertEquals(1, String.prototype.padEnd.length);
assertEquals("function", typeof String.prototype.padEnd);
assertEquals(Object.getPrototypeOf(Function),
Object.getPrototypeOf(String.prototype.padEnd));
assertEquals("padEnd", String.prototype.padEnd.name);
var desc = Object.getOwnPropertyDescriptor(String.prototype, "padEnd");
assertFalse(desc.enumerable);
assertTrue(desc.configurable);
assertTrue(desc.writable);
assertEquals(undefined, desc.get);
assertEquals(undefined, desc.set);
assertThrows(() => new Function(`${String.prototype.padEnd}`), SyntaxError);
})();
(function TestRequireObjectCoercible() {
var padEnd = String.prototype.padEnd;
assertThrows(() => padEnd.call(null, 4, "test"), TypeError);
assertThrows(() => padEnd.call(undefined, 4, "test"), TypeError);
assertEquals("123 ", padEnd.call({
__proto__: null,
valueOf() { return 123; }
}, 6, " "));
var proxy = new Proxy({}, {
get(t, name) {
if (name === Symbol.toPrimitive || name === "toString") return;
if (name === "valueOf") return () => 6.7;
assertUnreachable();
}
});
assertEquals("6.7 ", padEnd.call(proxy, 6, " "));
proxy = new Proxy({}, {
get(t, name) {
if (name === Symbol.toPrimitive || name === "valueOf") return;
if (name === "toString") return () => 6.7;
assertUnreachable();
}
});
assertEquals("6.7 ", padEnd.call(proxy, 6, " "));
})();
(function TestToLength() {
assertThrows(() => "123".padEnd(Symbol("16")), TypeError);
assertEquals("123", "123".padEnd(-1));
assertEquals("123", "123".padEnd({ toString() { return -1; } }));
assertEquals("123", "123".padEnd(-0));
assertEquals("123", "123".padEnd({ toString() { return -0; } }));
assertEquals("123", "123".padEnd(+0));
assertEquals("123", "123".padEnd({ toString() { return +0; } }));
assertEquals("123", "123".padEnd(NaN));
assertEquals("123", "123".padEnd({ toString() { return NaN; } }));
})();
(function TestFillerToString() {
assertEquals(". ", ".".padEnd(10));
assertEquals(". ", ".".padEnd(10, undefined));
assertEquals(". ", ".".padEnd(10, { toString() { return ""; } }));
assertEquals(".nullnulln", ".".padEnd(10, null));
})();
(function TestFillerRepetition() {
for (var i = 2000; i > 0; --i) {
var expected = "123" + "xoxo".repeat(i / 4).slice(0, i - 3);
var actual = "123".padEnd(i, "xoxo");
assertEquals(expected, actual);
assertEquals(i > "123".length ? i : 3, actual.length);
}
})();
(function TestTruncation() {
assertEquals("ab", "a".padEnd(2, "bc"));
})();
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-string-padding
(function TestMeta() {
assertEquals(1, String.prototype.padStart.length);
assertEquals("function", typeof String.prototype.padStart);
assertEquals(Object.getPrototypeOf(Function),
Object.getPrototypeOf(String.prototype.padStart));
assertEquals("padStart", String.prototype.padStart.name);
var desc = Object.getOwnPropertyDescriptor(String.prototype, "padStart");
assertFalse(desc.enumerable);
assertTrue(desc.configurable);
assertTrue(desc.writable);
assertEquals(undefined, desc.get);
assertEquals(undefined, desc.set);
assertThrows(() => new Function(`${String.prototype.padStart}`), SyntaxError);
})();
(function TestRequireObjectCoercible() {
var padStart = String.prototype.padStart;
assertThrows(() => padStart.call(null, 4, "test"), TypeError);
assertThrows(() => padStart.call(undefined, 4, "test"), TypeError);
assertEquals(" 123", padStart.call({
__proto__: null,
valueOf() { return 123; }
}, 6, " "));
var proxy = new Proxy({}, {
get(t, name) {
if (name === Symbol.toPrimitive || name === "toString") return;
if (name === "valueOf") return () => 6.7;
assertUnreachable();
}
});
assertEquals(" 6.7", padStart.call(proxy, 6, " "));
proxy = new Proxy({}, {
get(t, name) {
if (name === Symbol.toPrimitive || name === "valueOf") return;
if (name === "toString") return () => 6.7;
assertUnreachable();
}
});
assertEquals(" 6.7", padStart.call(proxy, 6, " "));
})();
(function TestToLength() {
assertThrows(() => "123".padStart(Symbol("16")), TypeError);
assertEquals("123", "123".padStart(-1));
assertEquals("123", "123".padStart({ toString() { return -1; } }));
assertEquals("123", "123".padStart(-0));
assertEquals("123", "123".padStart({ toString() { return -0; } }));
assertEquals("123", "123".padStart(+0));
assertEquals("123", "123".padStart({ toString() { return +0; } }));
assertEquals("123", "123".padStart(NaN));
assertEquals("123", "123".padStart({ toString() { return NaN; } }));
})();
(function TestFillerToString() {
assertEquals(" .", ".".padStart(10));
assertEquals(" .", ".".padStart(10, undefined));
assertEquals(" .", ".".padStart(10, { toString() { return ""; } }));
assertEquals("nullnulln.", ".".padStart(10, null));
})();
(function TestFillerRepetition() {
for (var i = 2000; i > 0; --i) {
var expected = "xoxo".repeat(i / 4).slice(0, i - 3) + "123";
var actual = "123".padStart(i, "xoxo");
assertEquals(expected, actual);
assertEquals(i > "123".length ? i : 3, actual.length);
}
})();
(function TestTruncation() {
assertEquals("ba", "a".padStart(2, "bc"));
})();
......@@ -2086,6 +2086,7 @@
'../../src/js/harmony-simd.js',
'../../src/js/harmony-species.js',
'../../src/js/harmony-unicode-regexps.js',
'../../src/js/harmony-string-padding.js',
'../../src/js/promise-extra.js',
],
'libraries_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries.bin',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment