• 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
5namespace string {
6macro TryFastStringCompareSequence(
7    string: String, searchStr: String, start: uintptr,
8    searchLength: uintptr): Boolean labels Slow {
9  const directString = Cast<DirectString>(string) otherwise Slow;
10  const directSearchStr = Cast<DirectString>(searchStr) otherwise Slow;
11
12  let searchIndex: uintptr = 0;
13  let stringIndex: uintptr = start;
14
15  while (searchIndex < searchLength) {
16    if (StringCharCodeAt(directSearchStr, searchIndex) !=
17        StringCharCodeAt(directString, stringIndex)) {
18      return False;
19    }
20
21    searchIndex++;
22    stringIndex++;
23  }
24  return True;
25}
26
27// https://tc39.github.io/ecma262/#sec-string.prototype.endswith
28transitioning javascript builtin StringPrototypeEndsWith(
29    js-implicit context: NativeContext,
30    receiver: JSAny)(...arguments): Boolean {
31  const searchString: JSAny = arguments[0];
32  const endPosition: JSAny = arguments[1];
33  const kBuiltinName: constexpr string = 'String.prototype.endsWith';
34
35  // 1. Let O be ? RequireObjectCoercible(this value).
36  // 2. Let S be ? ToString(O).
37  const string: String = ToThisString(receiver, kBuiltinName);
38
39  // 3. Let isRegExp be ? IsRegExp(searchString).
40  // 4. If isRegExp is true, throw a TypeError exception.
41  if (regexp::IsRegExp(searchString)) {
42    ThrowTypeError(MessageTemplate::kFirstArgumentNotRegExp, kBuiltinName);
43  }
44
45  // 5. Let searchStr be ? ToString(searchString).
46  const searchStr: String = ToString_Inline(searchString);
47
48  // 6. Let len be the length of S.
49  const len: uintptr = string.length_uintptr;
50
51  // 7. If endPosition is undefined, let pos be len,
52  // else let pos be ? ToInteger(endPosition).
53  // 8. Let end be min(max(pos, 0), len).
54  const end: uintptr =
55      (endPosition != Undefined) ? ClampToIndexRange(endPosition, len) : len;
56
57  // 9. Let searchLength be the length of searchStr.
58  const searchLength: uintptr = searchStr.length_uintptr;
59
60  // 10. Let start be end - searchLength.
61  const start: uintptr = end - searchLength;
62
63  // 11. If start is less than 0, return false.
64  if (Signed(start) < 0) return False;
65
66  // 12. If the sequence of code units of S starting at start of length
67  // searchLength is the same as the full code unit sequence of searchStr,
68  // return true.
69  // 13. Otherwise, return false.
70  try {
71    // Fast Path: If both strings are direct and relevant indices are Smis.
72    return TryFastStringCompareSequence(string, searchStr, start, searchLength)
73        otherwise Slow;
74  } label Slow {
75    // Slow Path: If either of the string is indirect, bail into runtime.
76    return StringCompareSequence(
77        context, string, searchStr, Convert<Number>(start));
78  }
79}
80}
81