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// TODO(turbofan): This could be replaced with a fast C-call to 6// CompareCharsUnsigned. 7macro IsSubstringAt<A: type, B: type>( 8 string: ConstSlice<A>, searchStr: ConstSlice<B>, start: intptr): bool { 9 const subslice = 10 Subslice(string, start, searchStr.length) otherwise return false; 11 let stringIterator = subslice.Iterator(); 12 let searchIterator = searchStr.Iterator(); 13 14 while (true) { 15 const searchChar = searchIterator.Next() otherwise return true; 16 const stringChar = stringIterator.Next() otherwise unreachable; 17 if (searchChar != stringChar) { 18 return false; 19 } 20 } 21 VerifiedUnreachable(); 22} 23 24struct IsSubstringAtFunctor { 25 start: intptr; 26} 27// Ideally, this would be a method of IsSubstringAtFunctor, but currently 28// methods don't support templates. 29macro Call<A: type, B: type>( 30 self: IsSubstringAtFunctor, string: ConstSlice<A>, 31 searchStr: ConstSlice<B>): bool { 32 return IsSubstringAt(string, searchStr, self.start); 33} 34 35macro IsSubstringAt(string: String, searchStr: String, start: intptr): bool { 36 return TwoStringsToSlices<bool>( 37 string, searchStr, IsSubstringAtFunctor{start: start}); 38} 39 40// https://tc39.github.io/ecma262/#sec-string.prototype.endswith 41transitioning javascript builtin StringPrototypeEndsWith( 42 js-implicit context: NativeContext, 43 receiver: JSAny)(...arguments): Boolean { 44 const searchString: JSAny = arguments[0]; 45 const endPosition: JSAny = arguments[1]; 46 const kBuiltinName: constexpr string = 'String.prototype.endsWith'; 47 48 // 1. Let O be ? RequireObjectCoercible(this value). 49 // 2. Let S be ? ToString(O). 50 const string: String = ToThisString(receiver, kBuiltinName); 51 52 // 3. Let isRegExp be ? IsRegExp(searchString). 53 // 4. If isRegExp is true, throw a TypeError exception. 54 if (regexp::IsRegExp(searchString)) { 55 ThrowTypeError(MessageTemplate::kFirstArgumentNotRegExp, kBuiltinName); 56 } 57 58 // 5. Let searchStr be ? ToString(searchString). 59 const searchStr: String = ToString_Inline(searchString); 60 61 // 6. Let len be the length of S. 62 const len: uintptr = string.length_uintptr; 63 64 // 7. If endPosition is undefined, let pos be len, 65 // else let pos be ? ToInteger(endPosition). 66 // 8. Let end be min(max(pos, 0), len). 67 const end: uintptr = 68 (endPosition != Undefined) ? ClampToIndexRange(endPosition, len) : len; 69 70 // 9. Let searchLength be the length of searchStr. 71 const searchLength: uintptr = searchStr.length_uintptr; 72 73 // 10. Let start be end - searchLength. 74 const start = Signed(end - searchLength); 75 76 // 11. If start is less than 0, return false. 77 if (start < 0) return False; 78 79 // 12. If the sequence of code units of S starting at start of length 80 // searchLength is the same as the full code unit sequence of searchStr, 81 // return true. 82 // 13. Otherwise, return false. 83 return Convert<Boolean>(IsSubstringAt(string, searchStr, start)); 84} 85