1// Copyright 2019 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include 'src/builtins/builtins-string-gen.h' 6 7namespace string { 8 9extern enum TrimMode extends uint31 constexpr 'String::TrimMode' { 10 kTrim, 11 kTrimStart, 12 kTrimEnd 13} 14 15@export 16macro IsWhiteSpaceOrLineTerminator(charCode: int32): bool { 17 // 0x0020 - SPACE (Intentionally out of order to fast path a commmon case) 18 if (charCode == Int32Constant(0x0020)) { 19 return true; 20 } 21 22 // 0x0009 - HORIZONTAL TAB 23 if (charCode < Int32Constant(0x0009)) { 24 return false; 25 } 26 // 0x000A - LINE FEED OR NEW LINE 27 // 0x000B - VERTICAL TAB 28 // 0x000C - FORMFEED 29 // 0x000D - HORIZONTAL TAB 30 if (charCode <= Int32Constant(0x000D)) { 31 return true; 32 } 33 34 // Common Non-whitespace characters 35 if (charCode < Int32Constant(0x00A0)) { 36 return false; 37 } 38 39 // 0x00A0 - NO-BREAK SPACE 40 if (charCode == Int32Constant(0x00A0)) { 41 return true; 42 } 43 44 // 0x1680 - Ogham Space Mark 45 if (charCode == Int32Constant(0x1680)) { 46 return true; 47 } 48 49 // 0x2000 - EN QUAD 50 if (charCode < Int32Constant(0x2000)) { 51 return false; 52 } 53 // 0x2001 - EM QUAD 54 // 0x2002 - EN SPACE 55 // 0x2003 - EM SPACE 56 // 0x2004 - THREE-PER-EM SPACE 57 // 0x2005 - FOUR-PER-EM SPACE 58 // 0x2006 - SIX-PER-EM SPACE 59 // 0x2007 - FIGURE SPACE 60 // 0x2008 - PUNCTUATION SPACE 61 // 0x2009 - THIN SPACE 62 // 0x200A - HAIR SPACE 63 if (charCode <= Int32Constant(0x200A)) { 64 return true; 65 } 66 67 // 0x2028 - LINE SEPARATOR 68 if (charCode == Int32Constant(0x2028)) { 69 return true; 70 } 71 // 0x2029 - PARAGRAPH SEPARATOR 72 if (charCode == Int32Constant(0x2029)) { 73 return true; 74 } 75 // 0x202F - NARROW NO-BREAK SPACE 76 if (charCode == Int32Constant(0x202F)) { 77 return true; 78 } 79 // 0x205F - MEDIUM MATHEMATICAL SPACE 80 if (charCode == Int32Constant(0x205F)) { 81 return true; 82 } 83 // 0xFEFF - BYTE ORDER MARK 84 if (charCode == Int32Constant(0xFEFF)) { 85 return true; 86 } 87 // 0x3000 - IDEOGRAPHIC SPACE 88 if (charCode == Int32Constant(0x3000)) { 89 return true; 90 } 91 92 return false; 93} 94 95transitioning macro StringTrim(implicit context: Context)( 96 receiver: JSAny, _arguments: Arguments, methodName: constexpr string, 97 variant: constexpr TrimMode): String { 98 const receiverString: String = ToThisString(receiver, methodName); 99 const stringLength: intptr = receiverString.length_intptr; 100 101 const directString = Cast<DirectString>(receiverString) 102 otherwise return runtime::StringTrim( 103 receiverString, SmiTag<TrimMode>(variant)); 104 105 let startIndex: intptr = 0; 106 let endIndex: intptr = stringLength - 1; 107 108 // TODO(duongn): It would probably be more efficient to turn StringTrim into a 109 // tempalate for the different string types and specialize the loop for them. 110 if (variant == TrimMode::kTrim || variant == TrimMode::kTrimStart) { 111 while (true) { 112 if (startIndex == stringLength) { 113 return EmptyStringConstant(); 114 } 115 if (!IsWhiteSpaceOrLineTerminator( 116 StringCharCodeAt(directString, Unsigned(startIndex)))) { 117 break; 118 } 119 startIndex++; 120 } 121 } 122 123 if (variant == TrimMode::kTrim || variant == TrimMode::kTrimEnd) { 124 while (true) { 125 if (endIndex == -1) { 126 return EmptyStringConstant(); 127 } 128 if (!IsWhiteSpaceOrLineTerminator( 129 StringCharCodeAt(directString, Unsigned(endIndex)))) { 130 break; 131 } 132 endIndex--; 133 } 134 } 135 136 return SubString( 137 receiverString, Unsigned(startIndex), Unsigned(endIndex + 1)); 138} 139 140// ES6 #sec-string.prototype.trim 141transitioning javascript builtin 142StringPrototypeTrim( 143 js-implicit context: NativeContext, receiver: JSAny)(...arguments): String { 144 const methodName: constexpr string = 'String.prototype.trim'; 145 return StringTrim(receiver, arguments, methodName, TrimMode::kTrim); 146} 147 148// https://github.com/tc39/proposal-string-left-right-trim 149transitioning javascript builtin 150StringPrototypeTrimStart( 151 js-implicit context: NativeContext, receiver: JSAny)(...arguments): String { 152 const methodName: constexpr string = 'String.prototype.trimLeft'; 153 return StringTrim(receiver, arguments, methodName, TrimMode::kTrimStart); 154} 155 156// https://github.com/tc39/proposal-string-left-right-trim 157transitioning javascript builtin 158StringPrototypeTrimEnd( 159 js-implicit context: NativeContext, receiver: JSAny)(...arguments): String { 160 const methodName: constexpr string = 'String.prototype.trimRight'; 161 return StringTrim(receiver, arguments, methodName, TrimMode::kTrimEnd); 162} 163} 164 165namespace runtime { 166extern runtime StringTrim(implicit context: Context)( 167 String, SmiTagged<string::TrimMode>): String; 168} 169