11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/execution/arguments-inl.h" 61cb0ef41Sopenharmony_ci#include "src/heap/heap-inl.h" 71cb0ef41Sopenharmony_ci#include "src/logging/counters.h" 81cb0ef41Sopenharmony_ci#include "src/numbers/conversions.h" 91cb0ef41Sopenharmony_ci#include "src/objects/js-array-inl.h" 101cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 111cb0ef41Sopenharmony_ci#include "src/objects/slots.h" 121cb0ef41Sopenharmony_ci#include "src/objects/smi.h" 131cb0ef41Sopenharmony_ci#include "src/regexp/regexp-utils.h" 141cb0ef41Sopenharmony_ci#include "src/runtime/runtime-utils.h" 151cb0ef41Sopenharmony_ci#include "src/strings/string-builder-inl.h" 161cb0ef41Sopenharmony_ci#include "src/strings/string-search.h" 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_cinamespace v8 { 191cb0ef41Sopenharmony_cinamespace internal { 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_GetSubstitution) { 221cb0ef41Sopenharmony_ci HandleScope scope(isolate); 231cb0ef41Sopenharmony_ci DCHECK_EQ(5, args.length()); 241cb0ef41Sopenharmony_ci Handle<String> matched = args.at<String>(0); 251cb0ef41Sopenharmony_ci Handle<String> subject = args.at<String>(1); 261cb0ef41Sopenharmony_ci int position = args.smi_value_at(2); 271cb0ef41Sopenharmony_ci Handle<String> replacement = args.at<String>(3); 281cb0ef41Sopenharmony_ci int start_index = args.smi_value_at(4); 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci // A simple match without captures. 311cb0ef41Sopenharmony_ci class SimpleMatch : public String::Match { 321cb0ef41Sopenharmony_ci public: 331cb0ef41Sopenharmony_ci SimpleMatch(Handle<String> match, Handle<String> prefix, 341cb0ef41Sopenharmony_ci Handle<String> suffix) 351cb0ef41Sopenharmony_ci : match_(match), prefix_(prefix), suffix_(suffix) {} 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci Handle<String> GetMatch() override { return match_; } 381cb0ef41Sopenharmony_ci Handle<String> GetPrefix() override { return prefix_; } 391cb0ef41Sopenharmony_ci Handle<String> GetSuffix() override { return suffix_; } 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci int CaptureCount() override { return 0; } 421cb0ef41Sopenharmony_ci bool HasNamedCaptures() override { return false; } 431cb0ef41Sopenharmony_ci MaybeHandle<String> GetCapture(int i, bool* capture_exists) override { 441cb0ef41Sopenharmony_ci *capture_exists = false; 451cb0ef41Sopenharmony_ci return match_; // Return arbitrary string handle. 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci MaybeHandle<String> GetNamedCapture(Handle<String> name, 481cb0ef41Sopenharmony_ci CaptureState* state) override { 491cb0ef41Sopenharmony_ci UNREACHABLE(); 501cb0ef41Sopenharmony_ci } 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci private: 531cb0ef41Sopenharmony_ci Handle<String> match_, prefix_, suffix_; 541cb0ef41Sopenharmony_ci }; 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci Handle<String> prefix = 571cb0ef41Sopenharmony_ci isolate->factory()->NewSubString(subject, 0, position); 581cb0ef41Sopenharmony_ci Handle<String> suffix = isolate->factory()->NewSubString( 591cb0ef41Sopenharmony_ci subject, position + matched->length(), subject->length()); 601cb0ef41Sopenharmony_ci SimpleMatch match(matched, prefix, suffix); 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci RETURN_RESULT_OR_FAILURE( 631cb0ef41Sopenharmony_ci isolate, 641cb0ef41Sopenharmony_ci String::GetSubstitution(isolate, &match, replacement, start_index)); 651cb0ef41Sopenharmony_ci} 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci// This may return an empty MaybeHandle if an exception is thrown or 681cb0ef41Sopenharmony_ci// we abort due to reaching the recursion limit. 691cb0ef41Sopenharmony_ciMaybeHandle<String> StringReplaceOneCharWithString( 701cb0ef41Sopenharmony_ci Isolate* isolate, Handle<String> subject, Handle<String> search, 711cb0ef41Sopenharmony_ci Handle<String> replace, bool* found, int recursion_limit) { 721cb0ef41Sopenharmony_ci StackLimitCheck stackLimitCheck(isolate); 731cb0ef41Sopenharmony_ci if (stackLimitCheck.HasOverflowed() || (recursion_limit == 0)) { 741cb0ef41Sopenharmony_ci return MaybeHandle<String>(); 751cb0ef41Sopenharmony_ci } 761cb0ef41Sopenharmony_ci recursion_limit--; 771cb0ef41Sopenharmony_ci if (subject->IsConsString()) { 781cb0ef41Sopenharmony_ci ConsString cons = ConsString::cast(*subject); 791cb0ef41Sopenharmony_ci Handle<String> first = handle(cons.first(), isolate); 801cb0ef41Sopenharmony_ci Handle<String> second = handle(cons.second(), isolate); 811cb0ef41Sopenharmony_ci Handle<String> new_first; 821cb0ef41Sopenharmony_ci if (!StringReplaceOneCharWithString(isolate, first, search, replace, found, 831cb0ef41Sopenharmony_ci recursion_limit).ToHandle(&new_first)) { 841cb0ef41Sopenharmony_ci return MaybeHandle<String>(); 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci if (*found) return isolate->factory()->NewConsString(new_first, second); 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci Handle<String> new_second; 891cb0ef41Sopenharmony_ci if (!StringReplaceOneCharWithString(isolate, second, search, replace, found, 901cb0ef41Sopenharmony_ci recursion_limit) 911cb0ef41Sopenharmony_ci .ToHandle(&new_second)) { 921cb0ef41Sopenharmony_ci return MaybeHandle<String>(); 931cb0ef41Sopenharmony_ci } 941cb0ef41Sopenharmony_ci if (*found) return isolate->factory()->NewConsString(first, new_second); 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci return subject; 971cb0ef41Sopenharmony_ci } else { 981cb0ef41Sopenharmony_ci int index = String::IndexOf(isolate, subject, search, 0); 991cb0ef41Sopenharmony_ci if (index == -1) return subject; 1001cb0ef41Sopenharmony_ci *found = true; 1011cb0ef41Sopenharmony_ci Handle<String> first = isolate->factory()->NewSubString(subject, 0, index); 1021cb0ef41Sopenharmony_ci Handle<String> cons1; 1031cb0ef41Sopenharmony_ci ASSIGN_RETURN_ON_EXCEPTION( 1041cb0ef41Sopenharmony_ci isolate, cons1, isolate->factory()->NewConsString(first, replace), 1051cb0ef41Sopenharmony_ci String); 1061cb0ef41Sopenharmony_ci Handle<String> second = 1071cb0ef41Sopenharmony_ci isolate->factory()->NewSubString(subject, index + 1, subject->length()); 1081cb0ef41Sopenharmony_ci return isolate->factory()->NewConsString(cons1, second); 1091cb0ef41Sopenharmony_ci } 1101cb0ef41Sopenharmony_ci} 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_StringReplaceOneCharWithString) { 1131cb0ef41Sopenharmony_ci HandleScope scope(isolate); 1141cb0ef41Sopenharmony_ci DCHECK_EQ(3, args.length()); 1151cb0ef41Sopenharmony_ci Handle<String> subject = args.at<String>(0); 1161cb0ef41Sopenharmony_ci Handle<String> search = args.at<String>(1); 1171cb0ef41Sopenharmony_ci Handle<String> replace = args.at<String>(2); 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci // If the cons string tree is too deep, we simply abort the recursion and 1201cb0ef41Sopenharmony_ci // retry with a flattened subject string. 1211cb0ef41Sopenharmony_ci const int kRecursionLimit = 0x1000; 1221cb0ef41Sopenharmony_ci bool found = false; 1231cb0ef41Sopenharmony_ci Handle<String> result; 1241cb0ef41Sopenharmony_ci if (StringReplaceOneCharWithString(isolate, subject, search, replace, &found, 1251cb0ef41Sopenharmony_ci kRecursionLimit).ToHandle(&result)) { 1261cb0ef41Sopenharmony_ci return *result; 1271cb0ef41Sopenharmony_ci } 1281cb0ef41Sopenharmony_ci if (isolate->has_pending_exception()) 1291cb0ef41Sopenharmony_ci return ReadOnlyRoots(isolate).exception(); 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ci subject = String::Flatten(isolate, subject); 1321cb0ef41Sopenharmony_ci if (StringReplaceOneCharWithString(isolate, subject, search, replace, &found, 1331cb0ef41Sopenharmony_ci kRecursionLimit).ToHandle(&result)) { 1341cb0ef41Sopenharmony_ci return *result; 1351cb0ef41Sopenharmony_ci } 1361cb0ef41Sopenharmony_ci if (isolate->has_pending_exception()) 1371cb0ef41Sopenharmony_ci return ReadOnlyRoots(isolate).exception(); 1381cb0ef41Sopenharmony_ci // In case of empty handle and no pending exception we have stack overflow. 1391cb0ef41Sopenharmony_ci return isolate->StackOverflow(); 1401cb0ef41Sopenharmony_ci} 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_StringLastIndexOf) { 1431cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate); 1441cb0ef41Sopenharmony_ci return String::LastIndexOf(isolate, args.at(0), args.at(1), 1451cb0ef41Sopenharmony_ci isolate->factory()->undefined_value()); 1461cb0ef41Sopenharmony_ci} 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_StringSubstring) { 1491cb0ef41Sopenharmony_ci HandleScope scope(isolate); 1501cb0ef41Sopenharmony_ci DCHECK_EQ(3, args.length()); 1511cb0ef41Sopenharmony_ci Handle<String> string = args.at<String>(0); 1521cb0ef41Sopenharmony_ci int start = args.smi_value_at(1); 1531cb0ef41Sopenharmony_ci int end = args.smi_value_at(2); 1541cb0ef41Sopenharmony_ci DCHECK_LE(0, start); 1551cb0ef41Sopenharmony_ci DCHECK_LE(start, end); 1561cb0ef41Sopenharmony_ci DCHECK_LE(end, string->length()); 1571cb0ef41Sopenharmony_ci isolate->counters()->sub_string_runtime()->Increment(); 1581cb0ef41Sopenharmony_ci return *isolate->factory()->NewSubString(string, start, end); 1591cb0ef41Sopenharmony_ci} 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_StringAdd) { 1621cb0ef41Sopenharmony_ci HandleScope scope(isolate); 1631cb0ef41Sopenharmony_ci DCHECK_EQ(2, args.length()); 1641cb0ef41Sopenharmony_ci Handle<String> str1 = args.at<String>(0); 1651cb0ef41Sopenharmony_ci Handle<String> str2 = args.at<String>(1); 1661cb0ef41Sopenharmony_ci isolate->counters()->string_add_runtime()->Increment(); 1671cb0ef41Sopenharmony_ci RETURN_RESULT_OR_FAILURE(isolate, 1681cb0ef41Sopenharmony_ci isolate->factory()->NewConsString(str1, str2)); 1691cb0ef41Sopenharmony_ci} 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_InternalizeString) { 1731cb0ef41Sopenharmony_ci HandleScope handles(isolate); 1741cb0ef41Sopenharmony_ci DCHECK_EQ(1, args.length()); 1751cb0ef41Sopenharmony_ci Handle<String> string = args.at<String>(0); 1761cb0ef41Sopenharmony_ci return *isolate->factory()->InternalizeString(string); 1771cb0ef41Sopenharmony_ci} 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_StringCharCodeAt) { 1801cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate); 1811cb0ef41Sopenharmony_ci DCHECK_EQ(2, args.length()); 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci Handle<String> subject = args.at<String>(0); 1841cb0ef41Sopenharmony_ci uint32_t i = NumberToUint32(args[1]); 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci // Flatten the string. If someone wants to get a char at an index 1871cb0ef41Sopenharmony_ci // in a cons string, it is likely that more indices will be 1881cb0ef41Sopenharmony_ci // accessed. 1891cb0ef41Sopenharmony_ci subject = String::Flatten(isolate, subject); 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_ci if (i >= static_cast<uint32_t>(subject->length())) { 1921cb0ef41Sopenharmony_ci return ReadOnlyRoots(isolate).nan_value(); 1931cb0ef41Sopenharmony_ci } 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_ci return Smi::FromInt(subject->Get(i)); 1961cb0ef41Sopenharmony_ci} 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_StringBuilderConcat) { 1991cb0ef41Sopenharmony_ci HandleScope scope(isolate); 2001cb0ef41Sopenharmony_ci DCHECK_EQ(3, args.length()); 2011cb0ef41Sopenharmony_ci Handle<JSArray> array = args.at<JSArray>(0); 2021cb0ef41Sopenharmony_ci int32_t array_length; 2031cb0ef41Sopenharmony_ci if (!args[1].ToInt32(&array_length)) { 2041cb0ef41Sopenharmony_ci THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError()); 2051cb0ef41Sopenharmony_ci } 2061cb0ef41Sopenharmony_ci Handle<String> special = args.at<String>(2); 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci size_t actual_array_length = 0; 2091cb0ef41Sopenharmony_ci CHECK(TryNumberToSize(array->length(), &actual_array_length)); 2101cb0ef41Sopenharmony_ci CHECK_GE(array_length, 0); 2111cb0ef41Sopenharmony_ci CHECK(static_cast<size_t>(array_length) <= actual_array_length); 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_ci // This assumption is used by the slice encoding in one or two smis. 2141cb0ef41Sopenharmony_ci DCHECK_GE(Smi::kMaxValue, String::kMaxLength); 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_ci CHECK(array->HasFastElements()); 2171cb0ef41Sopenharmony_ci JSObject::EnsureCanContainHeapObjectElements(array); 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci int special_length = special->length(); 2201cb0ef41Sopenharmony_ci if (!array->HasObjectElements()) { 2211cb0ef41Sopenharmony_ci return isolate->Throw(ReadOnlyRoots(isolate).illegal_argument_string()); 2221cb0ef41Sopenharmony_ci } 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ci int length; 2251cb0ef41Sopenharmony_ci bool one_byte = special->IsOneByteRepresentation(); 2261cb0ef41Sopenharmony_ci 2271cb0ef41Sopenharmony_ci { 2281cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 2291cb0ef41Sopenharmony_ci FixedArray fixed_array = FixedArray::cast(array->elements()); 2301cb0ef41Sopenharmony_ci if (fixed_array.length() < array_length) { 2311cb0ef41Sopenharmony_ci array_length = fixed_array.length(); 2321cb0ef41Sopenharmony_ci } 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_ci if (array_length == 0) { 2351cb0ef41Sopenharmony_ci return ReadOnlyRoots(isolate).empty_string(); 2361cb0ef41Sopenharmony_ci } else if (array_length == 1) { 2371cb0ef41Sopenharmony_ci Object first = fixed_array.get(0); 2381cb0ef41Sopenharmony_ci if (first.IsString()) return first; 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci length = StringBuilderConcatLength(special_length, fixed_array, 2411cb0ef41Sopenharmony_ci array_length, &one_byte); 2421cb0ef41Sopenharmony_ci } 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_ci if (length == -1) { 2451cb0ef41Sopenharmony_ci return isolate->Throw(ReadOnlyRoots(isolate).illegal_argument_string()); 2461cb0ef41Sopenharmony_ci } 2471cb0ef41Sopenharmony_ci if (length == 0) { 2481cb0ef41Sopenharmony_ci return ReadOnlyRoots(isolate).empty_string(); 2491cb0ef41Sopenharmony_ci } 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_ci if (one_byte) { 2521cb0ef41Sopenharmony_ci Handle<SeqOneByteString> answer; 2531cb0ef41Sopenharmony_ci ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2541cb0ef41Sopenharmony_ci isolate, answer, isolate->factory()->NewRawOneByteString(length)); 2551cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 2561cb0ef41Sopenharmony_ci StringBuilderConcatHelper(*special, answer->GetChars(no_gc), 2571cb0ef41Sopenharmony_ci FixedArray::cast(array->elements()), 2581cb0ef41Sopenharmony_ci array_length); 2591cb0ef41Sopenharmony_ci return *answer; 2601cb0ef41Sopenharmony_ci } else { 2611cb0ef41Sopenharmony_ci Handle<SeqTwoByteString> answer; 2621cb0ef41Sopenharmony_ci ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2631cb0ef41Sopenharmony_ci isolate, answer, isolate->factory()->NewRawTwoByteString(length)); 2641cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 2651cb0ef41Sopenharmony_ci StringBuilderConcatHelper(*special, answer->GetChars(no_gc), 2661cb0ef41Sopenharmony_ci FixedArray::cast(array->elements()), 2671cb0ef41Sopenharmony_ci array_length); 2681cb0ef41Sopenharmony_ci return *answer; 2691cb0ef41Sopenharmony_ci } 2701cb0ef41Sopenharmony_ci} 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ci// Copies Latin1 characters to the given fixed array looking up 2741cb0ef41Sopenharmony_ci// one-char strings in the cache. Gives up on the first char that is 2751cb0ef41Sopenharmony_ci// not in the cache and fills the remainder with smi zeros. Returns 2761cb0ef41Sopenharmony_ci// the length of the successfully copied prefix. 2771cb0ef41Sopenharmony_cistatic int CopyCachedOneByteCharsToArray(Heap* heap, const uint8_t* chars, 2781cb0ef41Sopenharmony_ci FixedArray elements, int length) { 2791cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 2801cb0ef41Sopenharmony_ci FixedArray one_byte_cache = heap->single_character_string_cache(); 2811cb0ef41Sopenharmony_ci Object undefined = ReadOnlyRoots(heap).undefined_value(); 2821cb0ef41Sopenharmony_ci int i; 2831cb0ef41Sopenharmony_ci WriteBarrierMode mode = elements.GetWriteBarrierMode(no_gc); 2841cb0ef41Sopenharmony_ci for (i = 0; i < length; ++i) { 2851cb0ef41Sopenharmony_ci Object value = one_byte_cache.get(chars[i]); 2861cb0ef41Sopenharmony_ci if (value == undefined) break; 2871cb0ef41Sopenharmony_ci elements.set(i, value, mode); 2881cb0ef41Sopenharmony_ci } 2891cb0ef41Sopenharmony_ci if (i < length) { 2901cb0ef41Sopenharmony_ci MemsetTagged(elements.RawFieldOfElementAt(i), Smi::zero(), length - i); 2911cb0ef41Sopenharmony_ci } 2921cb0ef41Sopenharmony_ci#ifdef DEBUG 2931cb0ef41Sopenharmony_ci for (int j = 0; j < length; ++j) { 2941cb0ef41Sopenharmony_ci Object element = elements.get(j); 2951cb0ef41Sopenharmony_ci DCHECK(element == Smi::zero() || 2961cb0ef41Sopenharmony_ci (element.IsString() && String::cast(element).LooksValid())); 2971cb0ef41Sopenharmony_ci } 2981cb0ef41Sopenharmony_ci#endif 2991cb0ef41Sopenharmony_ci return i; 3001cb0ef41Sopenharmony_ci} 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_ci// Converts a String to JSArray. 3031cb0ef41Sopenharmony_ci// For example, "foo" => ["f", "o", "o"]. 3041cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_StringToArray) { 3051cb0ef41Sopenharmony_ci HandleScope scope(isolate); 3061cb0ef41Sopenharmony_ci DCHECK_EQ(2, args.length()); 3071cb0ef41Sopenharmony_ci Handle<String> s = args.at<String>(0); 3081cb0ef41Sopenharmony_ci uint32_t limit = NumberToUint32(args[1]); 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_ci s = String::Flatten(isolate, s); 3111cb0ef41Sopenharmony_ci const int length = 3121cb0ef41Sopenharmony_ci static_cast<int>(std::min(static_cast<uint32_t>(s->length()), limit)); 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ci Handle<FixedArray> elements; 3151cb0ef41Sopenharmony_ci int position = 0; 3161cb0ef41Sopenharmony_ci if (s->IsFlat() && s->IsOneByteRepresentation()) { 3171cb0ef41Sopenharmony_ci // Try using cached chars where possible. 3181cb0ef41Sopenharmony_ci elements = isolate->factory()->NewFixedArray(length); 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 3211cb0ef41Sopenharmony_ci String::FlatContent content = s->GetFlatContent(no_gc); 3221cb0ef41Sopenharmony_ci if (content.IsOneByte()) { 3231cb0ef41Sopenharmony_ci base::Vector<const uint8_t> chars = content.ToOneByteVector(); 3241cb0ef41Sopenharmony_ci // Note, this will initialize all elements (not only the prefix) 3251cb0ef41Sopenharmony_ci // to prevent GC from seeing partially initialized array. 3261cb0ef41Sopenharmony_ci position = CopyCachedOneByteCharsToArray(isolate->heap(), chars.begin(), 3271cb0ef41Sopenharmony_ci *elements, length); 3281cb0ef41Sopenharmony_ci } else { 3291cb0ef41Sopenharmony_ci MemsetTagged(elements->data_start(), 3301cb0ef41Sopenharmony_ci ReadOnlyRoots(isolate).undefined_value(), length); 3311cb0ef41Sopenharmony_ci } 3321cb0ef41Sopenharmony_ci } else { 3331cb0ef41Sopenharmony_ci elements = isolate->factory()->NewFixedArray(length); 3341cb0ef41Sopenharmony_ci } 3351cb0ef41Sopenharmony_ci for (int i = position; i < length; ++i) { 3361cb0ef41Sopenharmony_ci Handle<Object> str = 3371cb0ef41Sopenharmony_ci isolate->factory()->LookupSingleCharacterStringFromCode(s->Get(i)); 3381cb0ef41Sopenharmony_ci elements->set(i, *str); 3391cb0ef41Sopenharmony_ci } 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ci#ifdef DEBUG 3421cb0ef41Sopenharmony_ci for (int i = 0; i < length; ++i) { 3431cb0ef41Sopenharmony_ci DCHECK_EQ(String::cast(elements->get(i)).length(), 1); 3441cb0ef41Sopenharmony_ci } 3451cb0ef41Sopenharmony_ci#endif 3461cb0ef41Sopenharmony_ci 3471cb0ef41Sopenharmony_ci return *isolate->factory()->NewJSArrayWithElements(elements); 3481cb0ef41Sopenharmony_ci} 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_StringLessThan) { 3511cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate); 3521cb0ef41Sopenharmony_ci DCHECK_EQ(2, args.length()); 3531cb0ef41Sopenharmony_ci Handle<String> x = args.at<String>(0); 3541cb0ef41Sopenharmony_ci Handle<String> y = args.at<String>(1); 3551cb0ef41Sopenharmony_ci ComparisonResult result = String::Compare(isolate, x, y); 3561cb0ef41Sopenharmony_ci DCHECK_NE(result, ComparisonResult::kUndefined); 3571cb0ef41Sopenharmony_ci return isolate->heap()->ToBoolean( 3581cb0ef41Sopenharmony_ci ComparisonResultToBool(Operation::kLessThan, result)); 3591cb0ef41Sopenharmony_ci} 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_StringLessThanOrEqual) { 3621cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate); 3631cb0ef41Sopenharmony_ci DCHECK_EQ(2, args.length()); 3641cb0ef41Sopenharmony_ci Handle<String> x = args.at<String>(0); 3651cb0ef41Sopenharmony_ci Handle<String> y = args.at<String>(1); 3661cb0ef41Sopenharmony_ci ComparisonResult result = String::Compare(isolate, x, y); 3671cb0ef41Sopenharmony_ci DCHECK_NE(result, ComparisonResult::kUndefined); 3681cb0ef41Sopenharmony_ci return isolate->heap()->ToBoolean( 3691cb0ef41Sopenharmony_ci ComparisonResultToBool(Operation::kLessThanOrEqual, result)); 3701cb0ef41Sopenharmony_ci} 3711cb0ef41Sopenharmony_ci 3721cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_StringGreaterThan) { 3731cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate); 3741cb0ef41Sopenharmony_ci DCHECK_EQ(2, args.length()); 3751cb0ef41Sopenharmony_ci Handle<String> x = args.at<String>(0); 3761cb0ef41Sopenharmony_ci Handle<String> y = args.at<String>(1); 3771cb0ef41Sopenharmony_ci ComparisonResult result = String::Compare(isolate, x, y); 3781cb0ef41Sopenharmony_ci DCHECK_NE(result, ComparisonResult::kUndefined); 3791cb0ef41Sopenharmony_ci return isolate->heap()->ToBoolean( 3801cb0ef41Sopenharmony_ci ComparisonResultToBool(Operation::kGreaterThan, result)); 3811cb0ef41Sopenharmony_ci} 3821cb0ef41Sopenharmony_ci 3831cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_StringGreaterThanOrEqual) { 3841cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate); 3851cb0ef41Sopenharmony_ci DCHECK_EQ(2, args.length()); 3861cb0ef41Sopenharmony_ci Handle<String> x = args.at<String>(0); 3871cb0ef41Sopenharmony_ci Handle<String> y = args.at<String>(1); 3881cb0ef41Sopenharmony_ci ComparisonResult result = String::Compare(isolate, x, y); 3891cb0ef41Sopenharmony_ci DCHECK_NE(result, ComparisonResult::kUndefined); 3901cb0ef41Sopenharmony_ci return isolate->heap()->ToBoolean( 3911cb0ef41Sopenharmony_ci ComparisonResultToBool(Operation::kGreaterThanOrEqual, result)); 3921cb0ef41Sopenharmony_ci} 3931cb0ef41Sopenharmony_ci 3941cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_StringEqual) { 3951cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate); 3961cb0ef41Sopenharmony_ci DCHECK_EQ(2, args.length()); 3971cb0ef41Sopenharmony_ci Handle<String> x = args.at<String>(0); 3981cb0ef41Sopenharmony_ci Handle<String> y = args.at<String>(1); 3991cb0ef41Sopenharmony_ci return isolate->heap()->ToBoolean(String::Equals(isolate, x, y)); 4001cb0ef41Sopenharmony_ci} 4011cb0ef41Sopenharmony_ci 4021cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_FlattenString) { 4031cb0ef41Sopenharmony_ci HandleScope scope(isolate); 4041cb0ef41Sopenharmony_ci DCHECK_EQ(1, args.length()); 4051cb0ef41Sopenharmony_ci Handle<String> str = args.at<String>(0); 4061cb0ef41Sopenharmony_ci return *String::Flatten(isolate, str); 4071cb0ef41Sopenharmony_ci} 4081cb0ef41Sopenharmony_ci 4091cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_StringMaxLength) { 4101cb0ef41Sopenharmony_ci SealHandleScope shs(isolate); 4111cb0ef41Sopenharmony_ci return Smi::FromInt(String::kMaxLength); 4121cb0ef41Sopenharmony_ci} 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_StringEscapeQuotes) { 4151cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate); 4161cb0ef41Sopenharmony_ci DCHECK_EQ(1, args.length()); 4171cb0ef41Sopenharmony_ci Handle<String> string = args.at<String>(0); 4181cb0ef41Sopenharmony_ci 4191cb0ef41Sopenharmony_ci // Equivalent to global replacement `string.replace(/"/g, """)`, but this 4201cb0ef41Sopenharmony_ci // does not modify any global state (e.g. the regexp match info). 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ci const int string_length = string->length(); 4231cb0ef41Sopenharmony_ci Handle<String> quotes = 4241cb0ef41Sopenharmony_ci isolate->factory()->LookupSingleCharacterStringFromCode('"'); 4251cb0ef41Sopenharmony_ci 4261cb0ef41Sopenharmony_ci int quote_index = String::IndexOf(isolate, string, quotes, 0); 4271cb0ef41Sopenharmony_ci 4281cb0ef41Sopenharmony_ci // No quotes, nothing to do. 4291cb0ef41Sopenharmony_ci if (quote_index == -1) return *string; 4301cb0ef41Sopenharmony_ci 4311cb0ef41Sopenharmony_ci // Find all quotes. 4321cb0ef41Sopenharmony_ci std::vector<int> indices = {quote_index}; 4331cb0ef41Sopenharmony_ci while (quote_index + 1 < string_length) { 4341cb0ef41Sopenharmony_ci quote_index = String::IndexOf(isolate, string, quotes, quote_index + 1); 4351cb0ef41Sopenharmony_ci if (quote_index == -1) break; 4361cb0ef41Sopenharmony_ci indices.emplace_back(quote_index); 4371cb0ef41Sopenharmony_ci } 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_ci // Build the replacement string. 4401cb0ef41Sopenharmony_ci Handle<String> replacement = 4411cb0ef41Sopenharmony_ci isolate->factory()->NewStringFromAsciiChecked("""); 4421cb0ef41Sopenharmony_ci const int estimated_part_count = static_cast<int>(indices.size()) * 2 + 1; 4431cb0ef41Sopenharmony_ci ReplacementStringBuilder builder(isolate->heap(), string, 4441cb0ef41Sopenharmony_ci estimated_part_count); 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_ci int prev_index = -1; // Start at -1 to avoid special-casing the first match. 4471cb0ef41Sopenharmony_ci for (int index : indices) { 4481cb0ef41Sopenharmony_ci const int slice_start = prev_index + 1; 4491cb0ef41Sopenharmony_ci const int slice_end = index; 4501cb0ef41Sopenharmony_ci if (slice_end > slice_start) { 4511cb0ef41Sopenharmony_ci builder.AddSubjectSlice(slice_start, slice_end); 4521cb0ef41Sopenharmony_ci } 4531cb0ef41Sopenharmony_ci builder.AddString(replacement); 4541cb0ef41Sopenharmony_ci prev_index = index; 4551cb0ef41Sopenharmony_ci } 4561cb0ef41Sopenharmony_ci 4571cb0ef41Sopenharmony_ci if (prev_index < string_length - 1) { 4581cb0ef41Sopenharmony_ci builder.AddSubjectSlice(prev_index + 1, string_length); 4591cb0ef41Sopenharmony_ci } 4601cb0ef41Sopenharmony_ci 4611cb0ef41Sopenharmony_ci return *builder.ToString().ToHandleChecked(); 4621cb0ef41Sopenharmony_ci} 4631cb0ef41Sopenharmony_ci 4641cb0ef41Sopenharmony_ci} // namespace internal 4651cb0ef41Sopenharmony_ci} // namespace v8 466