1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "ecmascript/js_api/js_api_deque_iterator.h" 17 18 #include "ecmascript/base/builtins_base.h" 19 #include "ecmascript/containers/containers_errors.h" 20 #include "ecmascript/global_env_constants-inl.h" 21 #include "ecmascript/js_api/js_api_deque.h" 22 #include "ecmascript/js_handle.h" 23 #include "ecmascript/js_iterator.h" 24 #include "ecmascript/js_handle.h" 25 #include "ecmascript/js_tagged_value-inl.h" 26 #include "ecmascript/js_thread.h" 27 #include "ecmascript/tagged_array.h" 28 29 namespace panda::ecmascript { 30 using BuiltinsBase = base::BuiltinsBase; 31 using ContainerError = containers::ContainerError; 32 using ErrorFlag = containers::ErrorFlag; 33 // DequeIteratorPrototype%.next ( ) Next(EcmaRuntimeCallInfo * argv)34 JSTaggedValue JSAPIDequeIterator::Next(EcmaRuntimeCallInfo *argv) 35 { 36 ASSERT(argv); 37 JSThread *thread = argv->GetThread(); 38 [[maybe_unused]] EcmaHandleScope handleScope(thread); 39 JSHandle<JSTaggedValue> input(BuiltinsBase::GetThis(argv)); 40 41 if (!input->IsJSAPIDequeIterator()) { 42 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 43 "The Symbol.iterator method cannot be bound"); 44 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 45 } 46 JSHandle<JSAPIDequeIterator> iter(input); 47 JSHandle<JSTaggedValue> iteratorDeque(thread, iter->GetIteratedDeque()); 48 const GlobalEnvConstants *globalConst = thread->GlobalConstants(); 49 if (iteratorDeque->IsUndefined()) { 50 return globalConst->GetUndefinedIterResult(); 51 } 52 JSHandle<JSAPIDeque> deque = JSHandle<JSAPIDeque>::Cast(iteratorDeque); 53 uint32_t index = iter->GetNextIndex(); 54 55 JSHandle<TaggedArray> elements(thread, deque->GetElements()); 56 uint32_t capacity = elements->GetLength(); 57 uint32_t first = deque->GetFirst(); 58 uint32_t last = deque->GetLast(); 59 if (index == last) { 60 JSHandle<JSTaggedValue> undefinedHandle = globalConst->GetHandledUndefined(); 61 iter->SetIteratedDeque(thread, undefinedHandle); 62 return globalConst->GetUndefinedIterResult(); 63 } 64 ASSERT(capacity != 0); 65 iter->SetNextIndex((index + 1) % capacity); 66 uint32_t elementIndex = (index + capacity - first) % capacity; 67 JSHandle<JSTaggedValue> value(thread, JSHandle<JSAPIDeque>::Cast(iteratorDeque)->Get(elementIndex)); 68 69 return JSIterator::CreateIterResultObject(thread, value, false).GetTaggedValue(); 70 } 71 } // namespace panda::ecmascript 72