Commit e0e8431d authored by Mathias Bynens's avatar Mathias Bynens Committed by Commit Bot

[esnext] Implement String.prototype.{trimStart,trimEnd}

Until now, String.prototype.{trimLeft,trimRight} were non-standard
language extensions, required for Web compatibility.

The proposal at https://github.com/tc39/proposal-string-left-right-trim
standardizes this functionality as String.prototype.{trimStart,trimEnd},
and defines String.prototype.{trimLeft,trimRight} as aliases for
backwards compatibility.

This patch implements that proposal behind the --harmony-string-trimming
flag.

Bug: v8:6530
Change-Id: Id21e624c12a79e6b782efb049a48901b9da7db71
Reviewed-on: https://chromium-review.googlesource.com/867044
Commit-Queue: Mathias Bynens <mathias@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50717}
parent 20ed6786
......@@ -2104,9 +2104,9 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(prototype, "trim", Builtins::kStringPrototypeTrim, 0,
false);
SimpleInstallFunction(prototype, "trimLeft",
Builtins::kStringPrototypeTrimLeft, 0, false);
Builtins::kStringPrototypeTrimStart, 0, false);
SimpleInstallFunction(prototype, "trimRight",
Builtins::kStringPrototypeTrimRight, 0, false);
Builtins::kStringPrototypeTrimEnd, 0, false);
#ifdef V8_INTL_SUPPORT
SimpleInstallFunction(prototype, "toLowerCase",
Builtins::kStringPrototypeToLowerCaseIntl, 0, true);
......@@ -4404,6 +4404,41 @@ void Genesis::InitializeGlobal_harmony_sharedarraybuffer() {
}
}
void Genesis::InitializeGlobal_harmony_string_trimming() {
if (!FLAG_harmony_string_trimming) return;
Handle<JSGlobalObject> global(native_context()->global_object());
Isolate* isolate = global->GetIsolate();
Factory* factory = isolate->factory();
Handle<JSObject> string_prototype(
native_context()->initial_string_prototype());
{
Handle<String> trim_left_name = factory->InternalizeUtf8String("trimLeft");
Handle<String> trim_start_name =
factory->InternalizeUtf8String("trimStart");
Handle<JSFunction> trim_left_fun = Handle<JSFunction>::cast(
JSObject::GetProperty(string_prototype, trim_left_name)
.ToHandleChecked());
JSObject::AddProperty(string_prototype, trim_start_name, trim_left_fun,
DONT_ENUM);
trim_left_fun->shared()->set_name(*trim_start_name);
}
{
Handle<String> trim_right_name =
factory->InternalizeUtf8String("trimRight");
Handle<String> trim_end_name = factory->InternalizeUtf8String("trimEnd");
Handle<JSFunction> trim_right_fun = Handle<JSFunction>::cast(
JSObject::GetProperty(string_prototype, trim_right_name)
.ToHandleChecked());
JSObject::AddProperty(string_prototype, trim_end_name, trim_right_fun,
DONT_ENUM);
trim_right_fun->shared()->set_name(*trim_end_name);
}
}
void Genesis::InitializeGlobal_harmony_array_prototype_values() {
if (!FLAG_harmony_array_prototype_values) return;
Handle<JSFunction> array_constructor(native_context()->array_function());
......
......@@ -1034,9 +1034,8 @@ namespace internal {
/* ES6 #sec-string.prototype.tostring */ \
TFJ(StringPrototypeToString, 0) \
TFJ(StringPrototypeTrim, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
TFJ(StringPrototypeTrimLeft, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
TFJ(StringPrototypeTrimRight, \
TFJ(StringPrototypeTrimEnd, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
TFJ(StringPrototypeTrimStart, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.valueof */ \
TFJ(StringPrototypeValueOf, 0) \
......
......@@ -2072,14 +2072,14 @@ TF_BUILTIN(StringPrototypeTrim, StringTrimAssembler) {
Generate(String::kTrim, "String.prototype.trim");
}
// Non-standard WebKit extension
TF_BUILTIN(StringPrototypeTrimLeft, StringTrimAssembler) {
Generate(String::kTrimLeft, "String.prototype.trimLeft");
// https://github.com/tc39/proposal-string-left-right-trim
TF_BUILTIN(StringPrototypeTrimStart, StringTrimAssembler) {
Generate(String::kTrimStart, "String.prototype.trimLeft");
}
// Non-standard WebKit extension
TF_BUILTIN(StringPrototypeTrimRight, StringTrimAssembler) {
Generate(String::kTrimRight, "String.prototype.trimRight");
// https://github.com/tc39/proposal-string-left-right-trim
TF_BUILTIN(StringPrototypeTrimEnd, StringTrimAssembler) {
Generate(String::kTrimEnd, "String.prototype.trimRight");
}
void StringTrimAssembler::Generate(String::TrimMode mode,
......@@ -2105,12 +2105,12 @@ void StringTrimAssembler::Generate(String::TrimMode mode,
TVARIABLE(IntPtrT, var_start, IntPtrConstant(0));
TVARIABLE(IntPtrT, var_end, IntPtrSub(string_length, IntPtrConstant(1)));
if (mode == String::kTrimLeft || mode == String::kTrim) {
if (mode == String::kTrimStart || mode == String::kTrim) {
ScanForNonWhiteSpaceOrLineTerminator(string_data, string_data_offset,
is_stringonebyte, &var_start,
string_length, 1, &return_emptystring);
}
if (mode == String::kTrimRight || mode == String::kTrim) {
if (mode == String::kTrimEnd || mode == String::kTrim) {
ScanForNonWhiteSpaceOrLineTerminator(
string_data, string_data_offset, is_stringonebyte, &var_end,
IntPtrConstant(-1), -1, &return_emptystring);
......
......@@ -1576,8 +1576,8 @@ Type* Typer::Visitor::JSCallTyper(Type* fun, Typer* t) {
case kStringToString:
case kStringToUpperCase:
case kStringTrim:
case kStringTrimLeft:
case kStringTrimRight:
case kStringTrimEnd:
case kStringTrimStart:
case kStringValueOf:
return Type::String();
......
......@@ -663,8 +663,8 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) {
case Builtins::kStringPrototypeToUpperCase:
#endif
case Builtins::kStringPrototypeTrim:
case Builtins::kStringPrototypeTrimLeft:
case Builtins::kStringPrototypeTrimRight:
case Builtins::kStringPrototypeTrimEnd:
case Builtins::kStringPrototypeTrimStart:
case Builtins::kStringPrototypeValueOf:
case Builtins::kStringToNumber:
case Builtins::kSubString:
......
......@@ -202,14 +202,15 @@ DEFINE_IMPLICATION(harmony_class_fields, harmony_static_fields)
DEFINE_IMPLICATION(harmony_class_fields, harmony_private_fields)
// Features that are still work in progress (behind individual flags).
#define HARMONY_INPROGRESS(V) \
V(harmony_import_meta, "harmony import.meta property") \
V(harmony_array_prototype_values, "harmony Array.prototype.values") \
V(harmony_function_sent, "harmony function.sent") \
V(harmony_do_expressions, "harmony do-expressions") \
V(harmony_class_fields, "harmony fields in class literals") \
V(harmony_static_fields, "harmony static fields in class literals") \
V(harmony_bigint, "harmony arbitrary precision integers") \
#define HARMONY_INPROGRESS(V) \
V(harmony_string_trimming, "harmony String.prototype.trim{Start,End}") \
V(harmony_import_meta, "harmony import.meta property") \
V(harmony_array_prototype_values, "harmony Array.prototype.values") \
V(harmony_function_sent, "harmony function.sent") \
V(harmony_do_expressions, "harmony do-expressions") \
V(harmony_class_fields, "harmony fields in class literals") \
V(harmony_static_fields, "harmony static fields in class literals") \
V(harmony_bigint, "harmony arbitrary precision integers") \
V(harmony_private_fields, "harmony private fields in class literals")
// Features that are complete (but still behind --harmony/es-staging flag).
......
......@@ -10565,7 +10565,7 @@ Handle<String> String::Trim(Handle<String> string, TrimMode mode) {
// Perform left trimming if requested.
int left = 0;
UnicodeCache* unicode_cache = isolate->unicode_cache();
if (mode == kTrim || mode == kTrimLeft) {
if (mode == kTrim || mode == kTrimStart) {
while (left < length &&
unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) {
left++;
......@@ -10574,7 +10574,7 @@ Handle<String> String::Trim(Handle<String> string, TrimMode mode) {
// Perform right trimming if requested.
int right = length;
if (mode == kTrim || mode == kTrimRight) {
if (mode == kTrim || mode == kTrimEnd) {
while (
right > left &&
unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) {
......
......@@ -3124,8 +3124,8 @@ class ContextExtension : public Struct {
V(String.prototype, toString, StringToString) \
V(String.prototype, toUpperCase, StringToUpperCase) \
V(String.prototype, trim, StringTrim) \
V(String.prototype, trimLeft, StringTrimLeft) \
V(String.prototype, trimRight, StringTrimRight) \
V(String.prototype, trimLeft, StringTrimStart) \
V(String.prototype, trimRight, StringTrimEnd) \
V(String.prototype, valueOf, StringValueOf) \
V(String, fromCharCode, StringFromCharCode) \
V(String, fromCodePoint, StringFromCodePoint) \
......
......@@ -314,7 +314,7 @@ class String : public Name {
uint32_t inline ToValidIndex(Object* number);
// Trimming.
enum TrimMode { kTrim, kTrimLeft, kTrimRight };
enum TrimMode { kTrim, kTrimStart, kTrimEnd };
static Handle<String> Trim(Handle<String> string, TrimMode mode);
DECL_CAST(String)
......
// Copyright 2018 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-trimming
assertEquals('trim', String.prototype.trim.name);
assertEquals('trimStart', String.prototype.trimStart.name);
assertEquals('trimStart', String.prototype.trimLeft.name);
assertEquals('trimEnd', String.prototype.trimEnd.name);
assertEquals('trimEnd', String.prototype.trimRight.name);
......@@ -21,130 +21,212 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This test checks String.trim(), String.trimLeft() and String.trimRight() methods.
This test checks the `trim`, `trimStart`/`trimLeft`, and `trimEnd`/`trimRight` methods on `String.prototype`.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS whitespace[0].s.trim() is ''
PASS whitespace[0].s.trimStart() is ''
PASS whitespace[0].s.trimLeft() is ''
PASS whitespace[0].s.trimEnd() is ''
PASS whitespace[0].s.trimRight() is ''
PASS whitespace[1].s.trim() is ''
PASS whitespace[1].s.trimStart() is ''
PASS whitespace[1].s.trimLeft() is ''
PASS whitespace[1].s.trimEnd() is ''
PASS whitespace[1].s.trimRight() is ''
PASS whitespace[2].s.trim() is ''
PASS whitespace[2].s.trimStart() is ''
PASS whitespace[2].s.trimLeft() is ''
PASS whitespace[2].s.trimEnd() is ''
PASS whitespace[2].s.trimRight() is ''
PASS whitespace[3].s.trim() is ''
PASS whitespace[3].s.trimStart() is ''
PASS whitespace[3].s.trimLeft() is ''
PASS whitespace[3].s.trimEnd() is ''
PASS whitespace[3].s.trimRight() is ''
PASS whitespace[4].s.trim() is ''
PASS whitespace[4].s.trimStart() is ''
PASS whitespace[4].s.trimLeft() is ''
PASS whitespace[4].s.trimEnd() is ''
PASS whitespace[4].s.trimRight() is ''
PASS whitespace[5].s.trim() is ''
PASS whitespace[5].s.trimStart() is ''
PASS whitespace[5].s.trimLeft() is ''
PASS whitespace[5].s.trimEnd() is ''
PASS whitespace[5].s.trimRight() is ''
PASS whitespace[6].s.trim() is ''
PASS whitespace[6].s.trimStart() is ''
PASS whitespace[6].s.trimLeft() is ''
PASS whitespace[6].s.trimEnd() is ''
PASS whitespace[6].s.trimRight() is ''
PASS whitespace[7].s.trim() is ''
PASS whitespace[7].s.trimStart() is ''
PASS whitespace[7].s.trimLeft() is ''
PASS whitespace[7].s.trimEnd() is ''
PASS whitespace[7].s.trimRight() is ''
PASS whitespace[8].s.trim() is ''
PASS whitespace[8].s.trimStart() is ''
PASS whitespace[8].s.trimLeft() is ''
PASS whitespace[8].s.trimEnd() is ''
PASS whitespace[8].s.trimRight() is ''
PASS whitespace[9].s.trim() is ''
PASS whitespace[9].s.trimStart() is ''
PASS whitespace[9].s.trimLeft() is ''
PASS whitespace[9].s.trimEnd() is ''
PASS whitespace[9].s.trimRight() is ''
PASS whitespace[10].s.trim() is ''
PASS whitespace[10].s.trimStart() is ''
PASS whitespace[10].s.trimLeft() is ''
PASS whitespace[10].s.trimEnd() is ''
PASS whitespace[10].s.trimRight() is ''
PASS whitespace[11].s.trim() is ''
PASS whitespace[11].s.trimStart() is ''
PASS whitespace[11].s.trimLeft() is ''
PASS whitespace[11].s.trimEnd() is ''
PASS whitespace[11].s.trimRight() is ''
PASS whitespace[12].s.trim() is ''
PASS whitespace[12].s.trimStart() is ''
PASS whitespace[12].s.trimLeft() is ''
PASS whitespace[12].s.trimEnd() is ''
PASS whitespace[12].s.trimRight() is ''
PASS whitespace[13].s.trim() is ''
PASS whitespace[13].s.trimStart() is ''
PASS whitespace[13].s.trimLeft() is ''
PASS whitespace[13].s.trimEnd() is ''
PASS whitespace[13].s.trimRight() is ''
PASS whitespace[14].s.trim() is ''
PASS whitespace[14].s.trimStart() is ''
PASS whitespace[14].s.trimLeft() is ''
PASS whitespace[14].s.trimEnd() is ''
PASS whitespace[14].s.trimRight() is ''
PASS whitespace[15].s.trim() is ''
PASS whitespace[15].s.trimStart() is ''
PASS whitespace[15].s.trimLeft() is ''
PASS whitespace[15].s.trimEnd() is ''
PASS whitespace[15].s.trimRight() is ''
PASS whitespace[16].s.trim() is ''
PASS whitespace[16].s.trimStart() is ''
PASS whitespace[16].s.trimLeft() is ''
PASS whitespace[16].s.trimEnd() is ''
PASS whitespace[16].s.trimRight() is ''
PASS whitespace[17].s.trim() is ''
PASS whitespace[17].s.trimStart() is ''
PASS whitespace[17].s.trimLeft() is ''
PASS whitespace[17].s.trimEnd() is ''
PASS whitespace[17].s.trimRight() is ''
PASS whitespace[18].s.trim() is ''
PASS whitespace[18].s.trimStart() is ''
PASS whitespace[18].s.trimLeft() is ''
PASS whitespace[18].s.trimEnd() is ''
PASS whitespace[18].s.trimRight() is ''
PASS whitespace[19].s.trim() is ''
PASS whitespace[19].s.trimStart() is ''
PASS whitespace[19].s.trimLeft() is ''
PASS whitespace[19].s.trimEnd() is ''
PASS whitespace[19].s.trimRight() is ''
PASS whitespace[20].s.trim() is ''
PASS whitespace[20].s.trimStart() is ''
PASS whitespace[20].s.trimLeft() is ''
PASS whitespace[20].s.trimEnd() is ''
PASS whitespace[20].s.trimRight() is ''
FAIL whitespace[21].s.trim() should be . Was ​.
FAIL whitespace[21].s.trimStart() should be . Was ​.
FAIL whitespace[21].s.trimLeft() should be . Was ​.
FAIL whitespace[21].s.trimEnd() should be . Was ​.
FAIL whitespace[21].s.trimRight() should be . Was ​.
FAIL wsString.trim() should be . Was ​.
FAIL wsString.trimStart() should be . Was ​.
FAIL wsString.trimLeft() should be . Was ​.
FAIL wsString.trimRight() should be . Was
FAIL wsString.trimEnd() should be . Was
             

​.
FAIL trimString.trim() should be foo bar. Was ​foo bar
FAIL wsString.trimRight() should be . Was
             

​.
FAIL trimString.trimLeft() should be foo bar
FAIL trimString.trim() should be foo bar. Was ​foo bar
             

​. Was ​foo bar
             

​.
FAIL trimString.trimStart() should be foo bar
             

​. Was ​foo bar
             

​.
FAIL trimString.trimLeft() should be foo bar
             

​. Was ​foo bar
             

​.
FAIL trimString.trimRight() should be
FAIL trimString.trimEnd() should be
             

​foo bar. Was
             

​foo bar. Was
             

​foo bar
             

​foo bar
             

​.
FAIL leftTrimString.trim() should be foo bar. Was foo bar
FAIL trimString.trimRight() should be
             

​foo bar. Was
             

​foo bar
             

​.
FAIL leftTrimString.trim() should be foo bar. Was foo bar
             

​.
PASS leftTrimString.trimStart() is leftTrimString
PASS leftTrimString.trimLeft() is leftTrimString
FAIL leftTrimString.trimRight() should be foo bar. Was foo bar
FAIL leftTrimString.trimEnd() should be foo bar. Was foo bar
             

​.
FAIL leftTrimString.trimRight() should be foo bar. Was foo bar
             

​.
FAIL rightTrimString.trim() should be foo bar. Was ​foo bar.
FAIL rightTrimString.trimStart() should be foo bar. Was ​foo bar.
FAIL rightTrimString.trimLeft() should be foo bar. Was ​foo bar.
PASS rightTrimString.trimEnd() is rightTrimString
PASS rightTrimString.trimRight() is rightTrimString
PASS trim.call(0) is '0'
PASS trimStart.call(0) is '0'
PASS trimLeft.call(0) is '0'
PASS trimEnd.call(0) is '0'
PASS trimRight.call(0) is '0'
PASS trim.call(Infinity) is 'Infinity'
PASS trimStart.call(Infinity) is 'Infinity'
PASS trimLeft.call(Infinity) is 'Infinity'
PASS trimEnd.call(Infinity) is 'Infinity'
PASS trimRight.call(Infinity) is 'Infinity'
PASS trim.call(NaN) is 'NaN'
PASS trimStart.call(NaN) is 'NaN'
PASS trimLeft.call(NaN) is 'NaN'
PASS trimEnd.call(NaN) is 'NaN'
PASS trimRight.call(NaN) is 'NaN'
PASS trim.call(true) is 'true'
PASS trimStart.call(true) is 'true'
PASS trimLeft.call(true) is 'true'
PASS trimEnd.call(true) is 'true'
PASS trimRight.call(true) is 'true'
PASS trim.call(false) is 'false'
PASS trimStart.call(false) is 'false'
PASS trimLeft.call(false) is 'false'
PASS trimEnd.call(false) is 'false'
PASS trimRight.call(false) is 'false'
PASS trim.call(({})) is '[object Object]'
PASS trimStart.call(({})) is '[object Object]'
PASS trimLeft.call(({})) is '[object Object]'
PASS trimEnd.call(({})) is '[object Object]'
PASS trimRight.call(({})) is '[object Object]'
PASS trim.call(({toString:function(){return 'wibble'}})) is 'wibble'
PASS trimStart.call(({toString:function(){return 'wibble'}})) is 'wibble'
PASS trimLeft.call(({toString:function(){return 'wibble'}})) is 'wibble'
PASS trimEnd.call(({toString:function(){return 'wibble'}})) is 'wibble'
PASS trimRight.call(({toString:function(){return 'wibble'}})) is 'wibble'
PASS trim.call(['an','array']) is 'an,array'
PASS trimStart.call(['an','array']) is 'an,array'
PASS trimLeft.call(['an','array']) is 'an,array'
PASS trimEnd.call(['an','array']) is 'an,array'
PASS trimRight.call(['an','array']) is 'an,array'
PASS successfullyParsed is true
......
......@@ -21,74 +21,95 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
description("This test checks String.trim(), String.trimLeft() and String.trimRight() methods.");
// Flags: --harmony-string-trimming
//references to trim(), trimLeft() and trimRight() functions for testing Function's *.call() and *.apply() methods
var trim = String.prototype.trim;
var trimLeft = String.prototype.trimLeft;
var trimRight = String.prototype.trimRight;
description("This test checks the `trim`, `trimStart`/`trimLeft`, and `trimEnd`/`trimRight` methods on `String.prototype`.");
var testString = 'foo bar';
var trimString = '';
var leftTrimString = '';
var rightTrimString = '';
var wsString = '';
// References to trim(), trimLeft() and trimRight() functions for testing Function's *.call() and *.apply() methods
const trim = String.prototype.trim;
const trimStart = String.prototype.trimStart;
const trimLeft = String.prototype.trimLeft;
const trimEnd = String.prototype.trimEnd;
const trimRight = String.prototype.trimRight;
var whitespace = [
{s : '\u0009', t : 'HORIZONTAL TAB'},
{s : '\u000A', t : 'LINE FEED OR NEW LINE'},
{s : '\u000B', t : 'VERTICAL TAB'},
{s : '\u000C', t : 'FORMFEED'},
{s : '\u000D', t : 'CARRIAGE RETURN'},
{s : '\u0020', t : 'SPACE'},
{s : '\u00A0', t : 'NO-BREAK SPACE'},
{s : '\u2000', t : 'EN QUAD'},
{s : '\u2001', t : 'EM QUAD'},
{s : '\u2002', t : 'EN SPACE'},
{s : '\u2003', t : 'EM SPACE'},
{s : '\u2004', t : 'THREE-PER-EM SPACE'},
{s : '\u2005', t : 'FOUR-PER-EM SPACE'},
{s : '\u2006', t : 'SIX-PER-EM SPACE'},
{s : '\u2007', t : 'FIGURE SPACE'},
{s : '\u2008', t : 'PUNCTUATION SPACE'},
{s : '\u2009', t : 'THIN SPACE'},
{s : '\u200A', t : 'HAIR SPACE'},
{s : '\u3000', t : 'IDEOGRAPHIC SPACE'},
{s : '\u2028', t : 'LINE SEPARATOR'},
{s : '\u2029', t : 'PARAGRAPH SEPARATOR'},
{s : '\u200B', t : 'ZERO WIDTH SPACE (category Cf)'}
const whitespace = [
{s: '\u0009', t: 'HORIZONTAL TAB'},
{s: '\u000A', t: 'LINE FEED OR NEW LINE'},
{s: '\u000B', t: 'VERTICAL TAB'},
{s: '\u000C', t: 'FORMFEED'},
{s: '\u000D', t: 'CARRIAGE RETURN'},
{s: '\u0020', t: 'SPACE'},
{s: '\u00A0', t: 'NO-BREAK SPACE'},
{s: '\u2000', t: 'EN QUAD'},
{s: '\u2001', t: 'EM QUAD'},
{s: '\u2002', t: 'EN SPACE'},
{s: '\u2003', t: 'EM SPACE'},
{s: '\u2004', t: 'THREE-PER-EM SPACE'},
{s: '\u2005', t: 'FOUR-PER-EM SPACE'},
{s: '\u2006', t: 'SIX-PER-EM SPACE'},
{s: '\u2007', t: 'FIGURE SPACE'},
{s: '\u2008', t: 'PUNCTUATION SPACE'},
{s: '\u2009', t: 'THIN SPACE'},
{s: '\u200A', t: 'HAIR SPACE'},
{s: '\u3000', t: 'IDEOGRAPHIC SPACE'},
{s: '\u2028', t: 'LINE SEPARATOR'},
{s: '\u2029', t: 'PARAGRAPH SEPARATOR'},
{s: '\u200B', t: 'ZERO WIDTH SPACE (category Cf)'},
];
for (var i = 0; i < whitespace.length; i++) {
shouldBe("whitespace["+i+"].s.trim()", "''");
shouldBe("whitespace["+i+"].s.trimLeft()", "''");
shouldBe("whitespace["+i+"].s.trimRight()", "''");
wsString += whitespace[i].s;
let wsString = '';
for (let i = 0; i < whitespace.length; i++) {
shouldBe("whitespace["+i+"].s.trim()", "''");
shouldBe("whitespace["+i+"].s.trimStart()", "''");
shouldBe("whitespace["+i+"].s.trimLeft()", "''");
shouldBe("whitespace["+i+"].s.trimEnd()", "''");
shouldBe("whitespace["+i+"].s.trimRight()", "''");
wsString += whitespace[i].s;
}
trimString = wsString + testString + wsString;
leftTrimString = testString + wsString; //trimmed from the left
rightTrimString = wsString + testString; //trimmed from the right
const testString = 'foo bar';
const trimString = wsString + testString + wsString;
const leftTrimString = testString + wsString; //trimmed from the left
const rightTrimString = wsString + testString; //trimmed from the right
shouldBe("wsString.trim()", "''");
shouldBe("wsString.trimStart()", "''");
shouldBe("wsString.trimLeft()", "''");
shouldBe("wsString.trimEnd()", "''");
shouldBe("wsString.trimRight()", "''");
shouldBe("trimString.trim()", "testString");
shouldBe("trimString.trimStart()", "leftTrimString");
shouldBe("trimString.trimLeft()", "leftTrimString");
shouldBe("trimString.trimEnd()", "rightTrimString");
shouldBe("trimString.trimRight()", "rightTrimString");
shouldBe("leftTrimString.trim()", "testString");
shouldBe("leftTrimString.trimStart()", "leftTrimString");
shouldBe("leftTrimString.trimLeft()", "leftTrimString");
shouldBe("leftTrimString.trimEnd()", "testString");
shouldBe("leftTrimString.trimRight()", "testString");
shouldBe("rightTrimString.trim()", "testString");
shouldBe("rightTrimString.trimStart()", "testString");
shouldBe("rightTrimString.trimLeft()", "testString");
shouldBe("rightTrimString.trimEnd()", "rightTrimString");
shouldBe("rightTrimString.trimRight()", "rightTrimString");
var testValues = ["0", "Infinity", "NaN", "true", "false", "({})", "({toString:function(){return 'wibble'}})", "['an','array']"];
for (var i = 0; i < testValues.length; i++) {
shouldBe("trim.call("+testValues[i]+")", "'"+eval(testValues[i])+"'");
shouldBe("trimLeft.call("+testValues[i]+")", "'"+eval(testValues[i])+"'");
shouldBe("trimRight.call("+testValues[i]+")", "'"+eval(testValues[i])+"'");
const testValues = [
"0",
"Infinity",
"NaN",
"true",
"false",
"({})",
"({toString:function(){return 'wibble'}})",
"['an','array']",
];
for (const testValue of testValues) {
shouldBe("trim.call("+testValue+")", "'"+eval(testValue)+"'");
shouldBe("trimStart.call("+testValue+")", "'"+eval(testValue)+"'");
shouldBe("trimLeft.call("+testValue+")", "'"+eval(testValue)+"'");
shouldBe("trimEnd.call("+testValue+")", "'"+eval(testValue)+"'");
shouldBe("trimRight.call("+testValue+")", "'"+eval(testValue)+"'");
}
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