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, ...@@ -2104,9 +2104,9 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(prototype, "trim", Builtins::kStringPrototypeTrim, 0, SimpleInstallFunction(prototype, "trim", Builtins::kStringPrototypeTrim, 0,
false); false);
SimpleInstallFunction(prototype, "trimLeft", SimpleInstallFunction(prototype, "trimLeft",
Builtins::kStringPrototypeTrimLeft, 0, false); Builtins::kStringPrototypeTrimStart, 0, false);
SimpleInstallFunction(prototype, "trimRight", SimpleInstallFunction(prototype, "trimRight",
Builtins::kStringPrototypeTrimRight, 0, false); Builtins::kStringPrototypeTrimEnd, 0, false);
#ifdef V8_INTL_SUPPORT #ifdef V8_INTL_SUPPORT
SimpleInstallFunction(prototype, "toLowerCase", SimpleInstallFunction(prototype, "toLowerCase",
Builtins::kStringPrototypeToLowerCaseIntl, 0, true); Builtins::kStringPrototypeToLowerCaseIntl, 0, true);
...@@ -4404,6 +4404,41 @@ void Genesis::InitializeGlobal_harmony_sharedarraybuffer() { ...@@ -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() { void Genesis::InitializeGlobal_harmony_array_prototype_values() {
if (!FLAG_harmony_array_prototype_values) return; if (!FLAG_harmony_array_prototype_values) return;
Handle<JSFunction> array_constructor(native_context()->array_function()); Handle<JSFunction> array_constructor(native_context()->array_function());
......
...@@ -1034,9 +1034,8 @@ namespace internal { ...@@ -1034,9 +1034,8 @@ namespace internal {
/* ES6 #sec-string.prototype.tostring */ \ /* ES6 #sec-string.prototype.tostring */ \
TFJ(StringPrototypeToString, 0) \ TFJ(StringPrototypeToString, 0) \
TFJ(StringPrototypeTrim, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ TFJ(StringPrototypeTrim, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
TFJ(StringPrototypeTrimLeft, \ TFJ(StringPrototypeTrimEnd, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ TFJ(StringPrototypeTrimStart, \
TFJ(StringPrototypeTrimRight, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.valueof */ \ /* ES6 #sec-string.prototype.valueof */ \
TFJ(StringPrototypeValueOf, 0) \ TFJ(StringPrototypeValueOf, 0) \
......
...@@ -2072,14 +2072,14 @@ TF_BUILTIN(StringPrototypeTrim, StringTrimAssembler) { ...@@ -2072,14 +2072,14 @@ TF_BUILTIN(StringPrototypeTrim, StringTrimAssembler) {
Generate(String::kTrim, "String.prototype.trim"); Generate(String::kTrim, "String.prototype.trim");
} }
// Non-standard WebKit extension // https://github.com/tc39/proposal-string-left-right-trim
TF_BUILTIN(StringPrototypeTrimLeft, StringTrimAssembler) { TF_BUILTIN(StringPrototypeTrimStart, StringTrimAssembler) {
Generate(String::kTrimLeft, "String.prototype.trimLeft"); Generate(String::kTrimStart, "String.prototype.trimLeft");
} }
// Non-standard WebKit extension // https://github.com/tc39/proposal-string-left-right-trim
TF_BUILTIN(StringPrototypeTrimRight, StringTrimAssembler) { TF_BUILTIN(StringPrototypeTrimEnd, StringTrimAssembler) {
Generate(String::kTrimRight, "String.prototype.trimRight"); Generate(String::kTrimEnd, "String.prototype.trimRight");
} }
void StringTrimAssembler::Generate(String::TrimMode mode, void StringTrimAssembler::Generate(String::TrimMode mode,
...@@ -2105,12 +2105,12 @@ 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_start, IntPtrConstant(0));
TVARIABLE(IntPtrT, var_end, IntPtrSub(string_length, IntPtrConstant(1))); 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, ScanForNonWhiteSpaceOrLineTerminator(string_data, string_data_offset,
is_stringonebyte, &var_start, is_stringonebyte, &var_start,
string_length, 1, &return_emptystring); string_length, 1, &return_emptystring);
} }
if (mode == String::kTrimRight || mode == String::kTrim) { if (mode == String::kTrimEnd || mode == String::kTrim) {
ScanForNonWhiteSpaceOrLineTerminator( ScanForNonWhiteSpaceOrLineTerminator(
string_data, string_data_offset, is_stringonebyte, &var_end, string_data, string_data_offset, is_stringonebyte, &var_end,
IntPtrConstant(-1), -1, &return_emptystring); IntPtrConstant(-1), -1, &return_emptystring);
......
...@@ -1576,8 +1576,8 @@ Type* Typer::Visitor::JSCallTyper(Type* fun, Typer* t) { ...@@ -1576,8 +1576,8 @@ Type* Typer::Visitor::JSCallTyper(Type* fun, Typer* t) {
case kStringToString: case kStringToString:
case kStringToUpperCase: case kStringToUpperCase:
case kStringTrim: case kStringTrim:
case kStringTrimLeft: case kStringTrimEnd:
case kStringTrimRight: case kStringTrimStart:
case kStringValueOf: case kStringValueOf:
return Type::String(); return Type::String();
......
...@@ -663,8 +663,8 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) { ...@@ -663,8 +663,8 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) {
case Builtins::kStringPrototypeToUpperCase: case Builtins::kStringPrototypeToUpperCase:
#endif #endif
case Builtins::kStringPrototypeTrim: case Builtins::kStringPrototypeTrim:
case Builtins::kStringPrototypeTrimLeft: case Builtins::kStringPrototypeTrimEnd:
case Builtins::kStringPrototypeTrimRight: case Builtins::kStringPrototypeTrimStart:
case Builtins::kStringPrototypeValueOf: case Builtins::kStringPrototypeValueOf:
case Builtins::kStringToNumber: case Builtins::kStringToNumber:
case Builtins::kSubString: case Builtins::kSubString:
......
...@@ -202,14 +202,15 @@ DEFINE_IMPLICATION(harmony_class_fields, harmony_static_fields) ...@@ -202,14 +202,15 @@ DEFINE_IMPLICATION(harmony_class_fields, harmony_static_fields)
DEFINE_IMPLICATION(harmony_class_fields, harmony_private_fields) DEFINE_IMPLICATION(harmony_class_fields, harmony_private_fields)
// Features that are still work in progress (behind individual flags). // Features that are still work in progress (behind individual flags).
#define HARMONY_INPROGRESS(V) \ #define HARMONY_INPROGRESS(V) \
V(harmony_import_meta, "harmony import.meta property") \ V(harmony_string_trimming, "harmony String.prototype.trim{Start,End}") \
V(harmony_array_prototype_values, "harmony Array.prototype.values") \ V(harmony_import_meta, "harmony import.meta property") \
V(harmony_function_sent, "harmony function.sent") \ V(harmony_array_prototype_values, "harmony Array.prototype.values") \
V(harmony_do_expressions, "harmony do-expressions") \ V(harmony_function_sent, "harmony function.sent") \
V(harmony_class_fields, "harmony fields in class literals") \ V(harmony_do_expressions, "harmony do-expressions") \
V(harmony_static_fields, "harmony static fields in class literals") \ V(harmony_class_fields, "harmony fields in class literals") \
V(harmony_bigint, "harmony arbitrary precision integers") \ 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") V(harmony_private_fields, "harmony private fields in class literals")
// Features that are complete (but still behind --harmony/es-staging flag). // Features that are complete (but still behind --harmony/es-staging flag).
......
...@@ -10565,7 +10565,7 @@ Handle<String> String::Trim(Handle<String> string, TrimMode mode) { ...@@ -10565,7 +10565,7 @@ Handle<String> String::Trim(Handle<String> string, TrimMode mode) {
// Perform left trimming if requested. // Perform left trimming if requested.
int left = 0; int left = 0;
UnicodeCache* unicode_cache = isolate->unicode_cache(); UnicodeCache* unicode_cache = isolate->unicode_cache();
if (mode == kTrim || mode == kTrimLeft) { if (mode == kTrim || mode == kTrimStart) {
while (left < length && while (left < length &&
unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) { unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) {
left++; left++;
...@@ -10574,7 +10574,7 @@ Handle<String> String::Trim(Handle<String> string, TrimMode mode) { ...@@ -10574,7 +10574,7 @@ Handle<String> String::Trim(Handle<String> string, TrimMode mode) {
// Perform right trimming if requested. // Perform right trimming if requested.
int right = length; int right = length;
if (mode == kTrim || mode == kTrimRight) { if (mode == kTrim || mode == kTrimEnd) {
while ( while (
right > left && right > left &&
unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) { unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) {
......
...@@ -3124,8 +3124,8 @@ class ContextExtension : public Struct { ...@@ -3124,8 +3124,8 @@ class ContextExtension : public Struct {
V(String.prototype, toString, StringToString) \ V(String.prototype, toString, StringToString) \
V(String.prototype, toUpperCase, StringToUpperCase) \ V(String.prototype, toUpperCase, StringToUpperCase) \
V(String.prototype, trim, StringTrim) \ V(String.prototype, trim, StringTrim) \
V(String.prototype, trimLeft, StringTrimLeft) \ V(String.prototype, trimLeft, StringTrimStart) \
V(String.prototype, trimRight, StringTrimRight) \ V(String.prototype, trimRight, StringTrimEnd) \
V(String.prototype, valueOf, StringValueOf) \ V(String.prototype, valueOf, StringValueOf) \
V(String, fromCharCode, StringFromCharCode) \ V(String, fromCharCode, StringFromCharCode) \
V(String, fromCodePoint, StringFromCodePoint) \ V(String, fromCodePoint, StringFromCodePoint) \
......
...@@ -314,7 +314,7 @@ class String : public Name { ...@@ -314,7 +314,7 @@ class String : public Name {
uint32_t inline ToValidIndex(Object* number); uint32_t inline ToValidIndex(Object* number);
// Trimming. // Trimming.
enum TrimMode { kTrim, kTrimLeft, kTrimRight }; enum TrimMode { kTrim, kTrimStart, kTrimEnd };
static Handle<String> Trim(Handle<String> string, TrimMode mode); static Handle<String> Trim(Handle<String> string, TrimMode mode);
DECL_CAST(String) 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 @@ ...@@ -21,130 +21,212 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # 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". On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS whitespace[0].s.trim() is '' PASS whitespace[0].s.trim() is ''
PASS whitespace[0].s.trimStart() is ''
PASS whitespace[0].s.trimLeft() is '' PASS whitespace[0].s.trimLeft() is ''
PASS whitespace[0].s.trimEnd() is ''
PASS whitespace[0].s.trimRight() is '' PASS whitespace[0].s.trimRight() is ''
PASS whitespace[1].s.trim() is '' PASS whitespace[1].s.trim() is ''
PASS whitespace[1].s.trimStart() is ''
PASS whitespace[1].s.trimLeft() is '' PASS whitespace[1].s.trimLeft() is ''
PASS whitespace[1].s.trimEnd() is ''
PASS whitespace[1].s.trimRight() is '' PASS whitespace[1].s.trimRight() is ''
PASS whitespace[2].s.trim() is '' PASS whitespace[2].s.trim() is ''
PASS whitespace[2].s.trimStart() is ''
PASS whitespace[2].s.trimLeft() is '' PASS whitespace[2].s.trimLeft() is ''
PASS whitespace[2].s.trimEnd() is ''
PASS whitespace[2].s.trimRight() is '' PASS whitespace[2].s.trimRight() is ''
PASS whitespace[3].s.trim() is '' PASS whitespace[3].s.trim() is ''
PASS whitespace[3].s.trimStart() is ''
PASS whitespace[3].s.trimLeft() is '' PASS whitespace[3].s.trimLeft() is ''
PASS whitespace[3].s.trimEnd() is ''
PASS whitespace[3].s.trimRight() is '' PASS whitespace[3].s.trimRight() is ''
PASS whitespace[4].s.trim() is '' PASS whitespace[4].s.trim() is ''
PASS whitespace[4].s.trimStart() is ''
PASS whitespace[4].s.trimLeft() is '' PASS whitespace[4].s.trimLeft() is ''
PASS whitespace[4].s.trimEnd() is ''
PASS whitespace[4].s.trimRight() is '' PASS whitespace[4].s.trimRight() is ''
PASS whitespace[5].s.trim() is '' PASS whitespace[5].s.trim() is ''
PASS whitespace[5].s.trimStart() is ''
PASS whitespace[5].s.trimLeft() is '' PASS whitespace[5].s.trimLeft() is ''
PASS whitespace[5].s.trimEnd() is ''
PASS whitespace[5].s.trimRight() is '' PASS whitespace[5].s.trimRight() is ''
PASS whitespace[6].s.trim() is '' PASS whitespace[6].s.trim() is ''
PASS whitespace[6].s.trimStart() is ''
PASS whitespace[6].s.trimLeft() is '' PASS whitespace[6].s.trimLeft() is ''
PASS whitespace[6].s.trimEnd() is ''
PASS whitespace[6].s.trimRight() is '' PASS whitespace[6].s.trimRight() is ''
PASS whitespace[7].s.trim() is '' PASS whitespace[7].s.trim() is ''
PASS whitespace[7].s.trimStart() is ''
PASS whitespace[7].s.trimLeft() is '' PASS whitespace[7].s.trimLeft() is ''
PASS whitespace[7].s.trimEnd() is ''
PASS whitespace[7].s.trimRight() is '' PASS whitespace[7].s.trimRight() is ''
PASS whitespace[8].s.trim() is '' PASS whitespace[8].s.trim() is ''
PASS whitespace[8].s.trimStart() is ''
PASS whitespace[8].s.trimLeft() is '' PASS whitespace[8].s.trimLeft() is ''
PASS whitespace[8].s.trimEnd() is ''
PASS whitespace[8].s.trimRight() is '' PASS whitespace[8].s.trimRight() is ''
PASS whitespace[9].s.trim() is '' PASS whitespace[9].s.trim() is ''
PASS whitespace[9].s.trimStart() is ''
PASS whitespace[9].s.trimLeft() is '' PASS whitespace[9].s.trimLeft() is ''
PASS whitespace[9].s.trimEnd() is ''
PASS whitespace[9].s.trimRight() is '' PASS whitespace[9].s.trimRight() is ''
PASS whitespace[10].s.trim() is '' PASS whitespace[10].s.trim() is ''
PASS whitespace[10].s.trimStart() is ''
PASS whitespace[10].s.trimLeft() is '' PASS whitespace[10].s.trimLeft() is ''
PASS whitespace[10].s.trimEnd() is ''
PASS whitespace[10].s.trimRight() is '' PASS whitespace[10].s.trimRight() is ''
PASS whitespace[11].s.trim() is '' PASS whitespace[11].s.trim() is ''
PASS whitespace[11].s.trimStart() is ''
PASS whitespace[11].s.trimLeft() is '' PASS whitespace[11].s.trimLeft() is ''
PASS whitespace[11].s.trimEnd() is ''
PASS whitespace[11].s.trimRight() is '' PASS whitespace[11].s.trimRight() is ''
PASS whitespace[12].s.trim() is '' PASS whitespace[12].s.trim() is ''
PASS whitespace[12].s.trimStart() is ''
PASS whitespace[12].s.trimLeft() is '' PASS whitespace[12].s.trimLeft() is ''
PASS whitespace[12].s.trimEnd() is ''
PASS whitespace[12].s.trimRight() is '' PASS whitespace[12].s.trimRight() is ''
PASS whitespace[13].s.trim() is '' PASS whitespace[13].s.trim() is ''
PASS whitespace[13].s.trimStart() is ''
PASS whitespace[13].s.trimLeft() is '' PASS whitespace[13].s.trimLeft() is ''
PASS whitespace[13].s.trimEnd() is ''
PASS whitespace[13].s.trimRight() is '' PASS whitespace[13].s.trimRight() is ''
PASS whitespace[14].s.trim() is '' PASS whitespace[14].s.trim() is ''
PASS whitespace[14].s.trimStart() is ''
PASS whitespace[14].s.trimLeft() is '' PASS whitespace[14].s.trimLeft() is ''
PASS whitespace[14].s.trimEnd() is ''
PASS whitespace[14].s.trimRight() is '' PASS whitespace[14].s.trimRight() is ''
PASS whitespace[15].s.trim() is '' PASS whitespace[15].s.trim() is ''
PASS whitespace[15].s.trimStart() is ''
PASS whitespace[15].s.trimLeft() is '' PASS whitespace[15].s.trimLeft() is ''
PASS whitespace[15].s.trimEnd() is ''
PASS whitespace[15].s.trimRight() is '' PASS whitespace[15].s.trimRight() is ''
PASS whitespace[16].s.trim() is '' PASS whitespace[16].s.trim() is ''
PASS whitespace[16].s.trimStart() is ''
PASS whitespace[16].s.trimLeft() is '' PASS whitespace[16].s.trimLeft() is ''
PASS whitespace[16].s.trimEnd() is ''
PASS whitespace[16].s.trimRight() is '' PASS whitespace[16].s.trimRight() is ''
PASS whitespace[17].s.trim() is '' PASS whitespace[17].s.trim() is ''
PASS whitespace[17].s.trimStart() is ''
PASS whitespace[17].s.trimLeft() is '' PASS whitespace[17].s.trimLeft() is ''
PASS whitespace[17].s.trimEnd() is ''
PASS whitespace[17].s.trimRight() is '' PASS whitespace[17].s.trimRight() is ''
PASS whitespace[18].s.trim() is '' PASS whitespace[18].s.trim() is ''
PASS whitespace[18].s.trimStart() is ''
PASS whitespace[18].s.trimLeft() is '' PASS whitespace[18].s.trimLeft() is ''
PASS whitespace[18].s.trimEnd() is ''
PASS whitespace[18].s.trimRight() is '' PASS whitespace[18].s.trimRight() is ''
PASS whitespace[19].s.trim() is '' PASS whitespace[19].s.trim() is ''
PASS whitespace[19].s.trimStart() is ''
PASS whitespace[19].s.trimLeft() is '' PASS whitespace[19].s.trimLeft() is ''
PASS whitespace[19].s.trimEnd() is ''
PASS whitespace[19].s.trimRight() is '' PASS whitespace[19].s.trimRight() is ''
PASS whitespace[20].s.trim() is '' PASS whitespace[20].s.trim() is ''
PASS whitespace[20].s.trimStart() is ''
PASS whitespace[20].s.trimLeft() is '' PASS whitespace[20].s.trimLeft() is ''
PASS whitespace[20].s.trimEnd() is ''
PASS whitespace[20].s.trimRight() is '' PASS whitespace[20].s.trimRight() is ''
FAIL whitespace[21].s.trim() should be . Was ​. 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.trimLeft() should be . Was ​.
FAIL whitespace[21].s.trimEnd() should be . Was ​.
FAIL whitespace[21].s.trimRight() should be . Was ​. FAIL whitespace[21].s.trimRight() should be . Was ​.
FAIL wsString.trim() should be . Was ​. FAIL wsString.trim() should be . Was ​.
FAIL wsString.trimStart() should be . Was ​.
FAIL wsString.trimLeft() 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 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.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. FAIL rightTrimString.trimLeft() should be foo bar. Was ​foo bar.
PASS rightTrimString.trimEnd() is rightTrimString
PASS rightTrimString.trimRight() is rightTrimString PASS rightTrimString.trimRight() is rightTrimString
PASS trim.call(0) is '0' PASS trim.call(0) is '0'
PASS trimStart.call(0) is '0'
PASS trimLeft.call(0) is '0' PASS trimLeft.call(0) is '0'
PASS trimEnd.call(0) is '0'
PASS trimRight.call(0) is '0' PASS trimRight.call(0) is '0'
PASS trim.call(Infinity) is 'Infinity' PASS trim.call(Infinity) is 'Infinity'
PASS trimStart.call(Infinity) is 'Infinity'
PASS trimLeft.call(Infinity) is 'Infinity' PASS trimLeft.call(Infinity) is 'Infinity'
PASS trimEnd.call(Infinity) is 'Infinity'
PASS trimRight.call(Infinity) is 'Infinity' PASS trimRight.call(Infinity) is 'Infinity'
PASS trim.call(NaN) is 'NaN' PASS trim.call(NaN) is 'NaN'
PASS trimStart.call(NaN) is 'NaN'
PASS trimLeft.call(NaN) is 'NaN' PASS trimLeft.call(NaN) is 'NaN'
PASS trimEnd.call(NaN) is 'NaN'
PASS trimRight.call(NaN) is 'NaN' PASS trimRight.call(NaN) is 'NaN'
PASS trim.call(true) is 'true' PASS trim.call(true) is 'true'
PASS trimStart.call(true) is 'true'
PASS trimLeft.call(true) is 'true' PASS trimLeft.call(true) is 'true'
PASS trimEnd.call(true) is 'true'
PASS trimRight.call(true) is 'true' PASS trimRight.call(true) is 'true'
PASS trim.call(false) is 'false' PASS trim.call(false) is 'false'
PASS trimStart.call(false) is 'false'
PASS trimLeft.call(false) is 'false' PASS trimLeft.call(false) is 'false'
PASS trimEnd.call(false) is 'false'
PASS trimRight.call(false) is 'false' PASS trimRight.call(false) is 'false'
PASS trim.call(({})) is '[object Object]' PASS trim.call(({})) is '[object Object]'
PASS trimStart.call(({})) is '[object Object]'
PASS trimLeft.call(({})) is '[object Object]' PASS trimLeft.call(({})) is '[object Object]'
PASS trimEnd.call(({})) is '[object Object]'
PASS trimRight.call(({})) is '[object Object]' PASS trimRight.call(({})) is '[object Object]'
PASS trim.call(({toString:function(){return 'wibble'}})) is 'wibble' 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 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 trimRight.call(({toString:function(){return 'wibble'}})) is 'wibble'
PASS trim.call(['an','array']) is 'an,array' 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 trimLeft.call(['an','array']) is 'an,array'
PASS trimEnd.call(['an','array']) is 'an,array'
PASS trimRight.call(['an','array']) is 'an,array' PASS trimRight.call(['an','array']) is 'an,array'
PASS successfullyParsed is true PASS successfullyParsed is true
......
...@@ -21,74 +21,95 @@ ...@@ -21,74 +21,95 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // 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 description("This test checks the `trim`, `trimStart`/`trimLeft`, and `trimEnd`/`trimRight` methods on `String.prototype`.");
var trim = String.prototype.trim;
var trimLeft = String.prototype.trimLeft;
var trimRight = String.prototype.trimRight;
var testString = 'foo bar'; // References to trim(), trimLeft() and trimRight() functions for testing Function's *.call() and *.apply() methods
var trimString = ''; const trim = String.prototype.trim;
var leftTrimString = ''; const trimStart = String.prototype.trimStart;
var rightTrimString = ''; const trimLeft = String.prototype.trimLeft;
var wsString = ''; const trimEnd = String.prototype.trimEnd;
const trimRight = String.prototype.trimRight;
var whitespace = [ const whitespace = [
{s : '\u0009', t : 'HORIZONTAL TAB'}, {s: '\u0009', t: 'HORIZONTAL TAB'},
{s : '\u000A', t : 'LINE FEED OR NEW LINE'}, {s: '\u000A', t: 'LINE FEED OR NEW LINE'},
{s : '\u000B', t : 'VERTICAL TAB'}, {s: '\u000B', t: 'VERTICAL TAB'},
{s : '\u000C', t : 'FORMFEED'}, {s: '\u000C', t: 'FORMFEED'},
{s : '\u000D', t : 'CARRIAGE RETURN'}, {s: '\u000D', t: 'CARRIAGE RETURN'},
{s : '\u0020', t : 'SPACE'}, {s: '\u0020', t: 'SPACE'},
{s : '\u00A0', t : 'NO-BREAK SPACE'}, {s: '\u00A0', t: 'NO-BREAK SPACE'},
{s : '\u2000', t : 'EN QUAD'}, {s: '\u2000', t: 'EN QUAD'},
{s : '\u2001', t : 'EM QUAD'}, {s: '\u2001', t: 'EM QUAD'},
{s : '\u2002', t : 'EN SPACE'}, {s: '\u2002', t: 'EN SPACE'},
{s : '\u2003', t : 'EM SPACE'}, {s: '\u2003', t: 'EM SPACE'},
{s : '\u2004', t : 'THREE-PER-EM SPACE'}, {s: '\u2004', t: 'THREE-PER-EM SPACE'},
{s : '\u2005', t : 'FOUR-PER-EM SPACE'}, {s: '\u2005', t: 'FOUR-PER-EM SPACE'},
{s : '\u2006', t : 'SIX-PER-EM SPACE'}, {s: '\u2006', t: 'SIX-PER-EM SPACE'},
{s : '\u2007', t : 'FIGURE SPACE'}, {s: '\u2007', t: 'FIGURE SPACE'},
{s : '\u2008', t : 'PUNCTUATION SPACE'}, {s: '\u2008', t: 'PUNCTUATION SPACE'},
{s : '\u2009', t : 'THIN SPACE'}, {s: '\u2009', t: 'THIN SPACE'},
{s : '\u200A', t : 'HAIR SPACE'}, {s: '\u200A', t: 'HAIR SPACE'},
{s : '\u3000', t : 'IDEOGRAPHIC SPACE'}, {s: '\u3000', t: 'IDEOGRAPHIC SPACE'},
{s : '\u2028', t : 'LINE SEPARATOR'}, {s: '\u2028', t: 'LINE SEPARATOR'},
{s : '\u2029', t : 'PARAGRAPH SEPARATOR'}, {s: '\u2029', t: 'PARAGRAPH SEPARATOR'},
{s : '\u200B', t : 'ZERO WIDTH SPACE (category Cf)'} {s: '\u200B', t: 'ZERO WIDTH SPACE (category Cf)'},
]; ];
for (var i = 0; i < whitespace.length; i++) { let wsString = '';
shouldBe("whitespace["+i+"].s.trim()", "''"); for (let i = 0; i < whitespace.length; i++) {
shouldBe("whitespace["+i+"].s.trimLeft()", "''"); shouldBe("whitespace["+i+"].s.trim()", "''");
shouldBe("whitespace["+i+"].s.trimRight()", "''"); shouldBe("whitespace["+i+"].s.trimStart()", "''");
wsString += whitespace[i].s; shouldBe("whitespace["+i+"].s.trimLeft()", "''");
shouldBe("whitespace["+i+"].s.trimEnd()", "''");
shouldBe("whitespace["+i+"].s.trimRight()", "''");
wsString += whitespace[i].s;
} }
trimString = wsString + testString + wsString; const testString = 'foo bar';
leftTrimString = testString + wsString; //trimmed from the left const trimString = wsString + testString + wsString;
rightTrimString = wsString + testString; //trimmed from the right const leftTrimString = testString + wsString; //trimmed from the left
const rightTrimString = wsString + testString; //trimmed from the right
shouldBe("wsString.trim()", "''"); shouldBe("wsString.trim()", "''");
shouldBe("wsString.trimStart()", "''");
shouldBe("wsString.trimLeft()", "''"); shouldBe("wsString.trimLeft()", "''");
shouldBe("wsString.trimEnd()", "''");
shouldBe("wsString.trimRight()", "''"); shouldBe("wsString.trimRight()", "''");
shouldBe("trimString.trim()", "testString"); shouldBe("trimString.trim()", "testString");
shouldBe("trimString.trimStart()", "leftTrimString");
shouldBe("trimString.trimLeft()", "leftTrimString"); shouldBe("trimString.trimLeft()", "leftTrimString");
shouldBe("trimString.trimEnd()", "rightTrimString");
shouldBe("trimString.trimRight()", "rightTrimString"); shouldBe("trimString.trimRight()", "rightTrimString");
shouldBe("leftTrimString.trim()", "testString"); shouldBe("leftTrimString.trim()", "testString");
shouldBe("leftTrimString.trimStart()", "leftTrimString");
shouldBe("leftTrimString.trimLeft()", "leftTrimString"); shouldBe("leftTrimString.trimLeft()", "leftTrimString");
shouldBe("leftTrimString.trimEnd()", "testString");
shouldBe("leftTrimString.trimRight()", "testString"); shouldBe("leftTrimString.trimRight()", "testString");
shouldBe("rightTrimString.trim()", "testString"); shouldBe("rightTrimString.trim()", "testString");
shouldBe("rightTrimString.trimStart()", "testString");
shouldBe("rightTrimString.trimLeft()", "testString"); shouldBe("rightTrimString.trimLeft()", "testString");
shouldBe("rightTrimString.trimEnd()", "rightTrimString");
shouldBe("rightTrimString.trimRight()", "rightTrimString"); shouldBe("rightTrimString.trimRight()", "rightTrimString");
var testValues = ["0", "Infinity", "NaN", "true", "false", "({})", "({toString:function(){return 'wibble'}})", "['an','array']"]; const testValues = [
for (var i = 0; i < testValues.length; i++) { "0",
shouldBe("trim.call("+testValues[i]+")", "'"+eval(testValues[i])+"'"); "Infinity",
shouldBe("trimLeft.call("+testValues[i]+")", "'"+eval(testValues[i])+"'"); "NaN",
shouldBe("trimRight.call("+testValues[i]+")", "'"+eval(testValues[i])+"'"); "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