• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_hashmap_iterator.h"
17 
18 #include "ecmascript/containers/containers_errors.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/js_api/js_api_hasharray_iterator.h"
21 
22 namespace panda::ecmascript {
23 using BuiltinsBase = base::BuiltinsBase;
24 using ContainerError = containers::ContainerError;
25 using ErrorFlag = containers::ErrorFlag;
Next(EcmaRuntimeCallInfo * argv)26 JSTaggedValue JSAPIHashMapIterator::Next(EcmaRuntimeCallInfo *argv)
27 {
28     ASSERT(argv);
29     JSThread *thread = argv->GetThread();
30     [[maybe_unused]] EcmaHandleScope handleScope(thread);
31     JSHandle<JSTaggedValue> input(BuiltinsBase::GetThis(argv));
32 
33     if (!input->IsJSAPIHashMapIterator()) {
34         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
35                                                             "The Symbol.iterator method cannot be bound");
36         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
37     }
38     JSHandle<JSAPIHashMapIterator> iter = JSHandle<JSAPIHashMapIterator>::Cast(input);
39     JSHandle<JSTaggedValue> iteratedHashMap(thread, iter->GetIteratedHashMap(thread));
40     // If m is undefined, return undefinedIteratorResult.
41     if (iteratedHashMap->IsUndefined()) {
42         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
43         return env->GetUndefinedIteratorResult().GetTaggedValue();
44     }
45     JSHandle<TaggedHashArray> tableArr(thread, JSHandle<JSAPIHashMap>::Cast(iteratedHashMap)->GetTable(thread));
46     uint32_t tableLength = tableArr->GetLength();
47     uint32_t index = iter->GetNextIndex();
48 
49     JSMutableHandle<TaggedQueue> queue(thread, iter->GetTaggedQueue(thread));
50     JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined());
51     JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
52     JSMutableHandle<TaggedNode> currentNode(thread, JSTaggedValue::Undefined());
53 
54     IterationKind itemKind = iter->GetIterationKind();
55     while (index < tableLength) {
56         currentNode.Update(JSAPIHashArrayIterator::GetCurrentNode<JSAPIHashMapIterator>(thread, iter, queue, tableArr));
57         if (currentNode.GetTaggedValue().IsHole()) {
58             iter->SetNextIndex(++index);
59             continue;
60         }
61         JSTaggedValue key = currentNode->GetKey(thread);
62         keyHandle.Update(key);
63         if (itemKind == IterationKind::KEY) {
64             return JSIterator::CreateIterResultObject(thread, keyHandle, false).GetTaggedValue();
65         }
66         valueHandle.Update(currentNode->GetValue(thread));
67         if (itemKind == IterationKind::VALUE) {
68             return JSIterator::CreateIterResultObject(thread, valueHandle, false).GetTaggedValue();
69         }
70         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
71         JSHandle<TaggedArray> array = factory->NewTaggedArray(2); // 2 means the length of array
72         array->Set(thread, 0, keyHandle);
73         array->Set(thread, 1, valueHandle);
74         JSHandle<JSTaggedValue> keyAndValue(JSArray::CreateArrayFromList(thread, array));
75         return JSIterator::CreateIterResultObject(thread, keyAndValue, false).GetTaggedValue();
76     }
77     // Set [[IteratedMap]] to undefined.
78     iter->SetIteratedHashMap(thread, JSTaggedValue::Undefined());
79     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
80     return env->GetUndefinedIteratorResult().GetTaggedValue();
81 }
82 
CreateHashMapIterator(JSThread * thread,const JSHandle<JSTaggedValue> & obj,IterationKind kind)83 JSHandle<JSTaggedValue> JSAPIHashMapIterator::CreateHashMapIterator(JSThread *thread,
84                                                                     const JSHandle<JSTaggedValue> &obj,
85                                                                     IterationKind kind)
86 {
87     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
88     if (!obj->IsJSAPIHashMap()) {
89         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
90                                                             "The Symbol.iterator method cannot be bound");
91         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception()));
92     }
93     JSHandle<JSTaggedValue> iter(factory->NewJSAPIHashMapIterator(JSHandle<JSAPIHashMap>(obj), kind));
94     return iter;
95 }
96 }  // namespace panda::ecmascript