14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/builtins/builtins_string_iterator.h" 174514f5e3Sopenharmony_ci#include "ecmascript/ecma_string_table.h" 184514f5e3Sopenharmony_ci#include "ecmascript/js_iterator.h" 194514f5e3Sopenharmony_ci#include "ecmascript/js_string_iterator.h" 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_cinamespace panda::ecmascript::builtins { 224514f5e3Sopenharmony_ciJSTaggedValue BuiltinsStringIterator::Next(EcmaRuntimeCallInfo *argv) 234514f5e3Sopenharmony_ci{ 244514f5e3Sopenharmony_ci ASSERT(argv); 254514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), StringIterator, Next); 264514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 274514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 284514f5e3Sopenharmony_ci // 1. Let O be the this value. 294514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> thisValue = GetThis(argv); 304514f5e3Sopenharmony_ci return NextInternal(thread, thisValue); 314514f5e3Sopenharmony_ci} 324514f5e3Sopenharmony_ci 334514f5e3Sopenharmony_ciJSTaggedValue BuiltinsStringIterator::NextInternal(JSThread *thread, JSHandle<JSTaggedValue> thisValue) 344514f5e3Sopenharmony_ci{ 354514f5e3Sopenharmony_ci // 2. If Type(O) is not Object, throw a TypeError exception. 364514f5e3Sopenharmony_ci // 3. If O does not have all of the internal slots of an String Iterator Instance (21.1.5.3), 374514f5e3Sopenharmony_ci // throw a TypeError exception. 384514f5e3Sopenharmony_ci if (!thisValue->IsStringIterator()) { 394514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "is not StringIterator", JSTaggedValue::Exception()); 404514f5e3Sopenharmony_ci } 414514f5e3Sopenharmony_ci // 4. Let s be the value of the [[IteratedString]] internal slot of O. 424514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> string(thread, thisValue.GetObject<JSStringIterator>()->GetIteratedString()); 434514f5e3Sopenharmony_ci // 5. If s is undefined, return CreateIterResultObject(undefined, true). 444514f5e3Sopenharmony_ci if (string->IsUndefined()) { 454514f5e3Sopenharmony_ci return JSIterator::CreateIterResultObject(thread, string, true).GetTaggedValue(); 464514f5e3Sopenharmony_ci } 474514f5e3Sopenharmony_ci // 6. Let position be the value of the [[StringIteratorNextIndex]] internal slot of O. 484514f5e3Sopenharmony_ci uint32_t position = thisValue.GetObject<JSStringIterator>()->GetStringIteratorNextIndex(); 494514f5e3Sopenharmony_ci 504514f5e3Sopenharmony_ci // 7. Let len be the number of elements in s. 514514f5e3Sopenharmony_ci uint32_t len = EcmaStringAccessor(string.GetObject<EcmaString>()).GetLength(); 524514f5e3Sopenharmony_ci // If position ≥ len, then 534514f5e3Sopenharmony_ci // a. Set the value of the [[IteratedString]] internal slot of O to 544514f5e3Sopenharmony_ci // b. Return CreateIterResultObject(undefined, true). 554514f5e3Sopenharmony_ci if (position >= len) { 564514f5e3Sopenharmony_ci thisValue.GetObject<JSStringIterator>()->SetIteratedString(thread, JSTaggedValue::Undefined()); 574514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined()); 584514f5e3Sopenharmony_ci return JSIterator::CreateIterResultObject(thread, result, true).GetTaggedValue(); 594514f5e3Sopenharmony_ci } 604514f5e3Sopenharmony_ci 614514f5e3Sopenharmony_ci // 9. Let first be the code unit value at index position in s. 624514f5e3Sopenharmony_ci uint16_t first = EcmaStringAccessor(string.GetObject<EcmaString>()).Get<false>(position); 634514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined()); 644514f5e3Sopenharmony_ci uint32_t resultSize = 1; 654514f5e3Sopenharmony_ci // 10. If first < 0xD800 or first > 0xDBFF or position+1 = len, let resultString be the string consisting of the 664514f5e3Sopenharmony_ci // single code unit first. 674514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 684514f5e3Sopenharmony_ci if (position + 1 == len || first < base::utf_helper::DECODE_LEAD_LOW || 694514f5e3Sopenharmony_ci first > base::utf_helper::DECODE_LEAD_HIGH) { 704514f5e3Sopenharmony_ci if (EcmaStringAccessor::CanBeCompressed(&first, 1)) { 714514f5e3Sopenharmony_ci JSHandle<SingleCharTable> singleCharTable(thread, thread->GetSingleCharTable()); 724514f5e3Sopenharmony_ci result.Update(singleCharTable->GetStringFromSingleCharTable(first)); 734514f5e3Sopenharmony_ci } else { 744514f5e3Sopenharmony_ci std::vector<uint16_t> resultString {first, 0x0}; 754514f5e3Sopenharmony_ci result.Update(factory->NewFromUtf16(resultString.data(), 1).GetTaggedValue()); 764514f5e3Sopenharmony_ci } 774514f5e3Sopenharmony_ci } else { 784514f5e3Sopenharmony_ci // 11. Else, 794514f5e3Sopenharmony_ci // a. Let second be the code unit value at index position+1 in the String S. 804514f5e3Sopenharmony_ci // b. If second < 0xDC00 or second > 0xDFFF, let resultString be the string consisting of the single code unit 814514f5e3Sopenharmony_ci // first. 824514f5e3Sopenharmony_ci // c. Else, let resultString be the string consisting of the code unit first followed by the code unit second. 834514f5e3Sopenharmony_ci uint16_t second = EcmaStringAccessor(string.GetObject<EcmaString>()).Get<false>(position + 1); 844514f5e3Sopenharmony_ci if (second < base::utf_helper::DECODE_TRAIL_LOW || second > base::utf_helper::DECODE_TRAIL_HIGH) { 854514f5e3Sopenharmony_ci std::vector<uint16_t> resultString {first, 0x0}; 864514f5e3Sopenharmony_ci result.Update(factory->NewFromUtf16NotCompress(resultString.data(), 1).GetTaggedValue()); 874514f5e3Sopenharmony_ci } else { 884514f5e3Sopenharmony_ci std::vector<uint16_t> resultString {first, second, 0x0}; 894514f5e3Sopenharmony_ci result.Update( 904514f5e3Sopenharmony_ci factory->NewFromUtf16NotCompress(resultString.data(), 2).GetTaggedValue()); // 2: two bytes 914514f5e3Sopenharmony_ci resultSize = 2; // 2: 2 means that two bytes represent a character string 924514f5e3Sopenharmony_ci } 934514f5e3Sopenharmony_ci } 944514f5e3Sopenharmony_ci // 12. Let resultSize be the number of code units in resultString. 954514f5e3Sopenharmony_ci // 13. Set the value of the [[StringIteratorNextIndex]] internal slot of O to position+ resultSize. 964514f5e3Sopenharmony_ci thisValue.GetObject<JSStringIterator>()->SetStringIteratorNextIndex(position + resultSize); 974514f5e3Sopenharmony_ci 984514f5e3Sopenharmony_ci // 14. Return CreateIterResultObject(resultString, false). 994514f5e3Sopenharmony_ci return JSIterator::CreateIterResultObject(thread, result, false).GetTaggedValue(); 1004514f5e3Sopenharmony_ci} 1014514f5e3Sopenharmony_ci} // namespace panda::ecmascript::builtins 102