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