blob: eef0ccd84f95652ccb01433d9200b76e361c81c8 [file] [log] [blame]
Kaido Kertf309f9a2021-04-30 12:09:15 -07001// 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}