• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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