1 /*
2 * Copyright (c) 2021 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/builtins/builtins_typedarray.h"
17
18 #include "ecmascript/base/typed_array_helper-inl.h"
19 #include "ecmascript/base/typed_array_helper.h"
20 #include "ecmascript/builtins/builtins_array.h"
21 #include "ecmascript/builtins/builtins_object.h"
22 #include "ecmascript/ecma_runtime_call_info.h"
23 #include "ecmascript/ecma_string.h"
24 #include "ecmascript/ecma_vm.h"
25 #include "ecmascript/global_env.h"
26 #include "ecmascript/js_array.h"
27 #include "ecmascript/js_array_iterator.h"
28 #include "ecmascript/js_handle.h"
29 #include "ecmascript/js_hclass.h"
30 #include "ecmascript/js_object-inl.h"
31 #include "ecmascript/js_tagged_value-inl.h"
32 #include "ecmascript/js_tagged_value.h"
33 #include "ecmascript/js_thread.h"
34 #include "ecmascript/js_typed_array.h"
35 #include "ecmascript/object_factory.h"
36 #include "ecmascript/object_operator.h"
37 #include "ecmascript/tests/test_helper.h"
38
39 using namespace panda::ecmascript;
40 using namespace panda::ecmascript::builtins;
41 using namespace panda::ecmascript::base;
42
43 namespace panda::test {
44 using Array = ecmascript::builtins::BuiltinsArray;
45 using TypedArray = ecmascript::builtins::BuiltinsTypedArray;
46 using TypedArrayHelper = ecmascript::base::TypedArrayHelper;
47
48 class BuiltinsTypedArrayTest : public testing::Test {
49 public:
SetUpTestCase()50 static void SetUpTestCase()
51 {
52 GTEST_LOG_(INFO) << "SetUpTestCase";
53 }
54
TearDownTestCase()55 static void TearDownTestCase()
56 {
57 GTEST_LOG_(INFO) << "TearDownCase";
58 }
59
SetUp()60 void SetUp() override
61 {
62 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
63 }
64
TearDown()65 void TearDown() override
66 {
67 TestHelper::DestroyEcmaVMWithScope(instance, scope);
68 }
69
70 protected:
71 EcmaVM *instance {nullptr};
72 EcmaHandleScope *scope {nullptr};
73 JSThread *thread {nullptr};
74
75 class TestClass : public base::BuiltinsBase {
76 public:
TestForEachFunc(EcmaRuntimeCallInfo * argv)77 static JSTaggedValue TestForEachFunc(EcmaRuntimeCallInfo *argv)
78 {
79 JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
80 if (key->IsUndefined()) {
81 return JSTaggedValue::Undefined();
82 }
83 JSArray *jsArray = JSArray::Cast(GetThis(argv)->GetTaggedObject());
84 uint32_t length = jsArray->GetArrayLength() + 1U;
85 jsArray->SetArrayLength(argv->GetThread(), length);
86 return JSTaggedValue::Undefined();
87 }
88
TestEveryFunc(EcmaRuntimeCallInfo * argv)89 static JSTaggedValue TestEveryFunc(EcmaRuntimeCallInfo *argv)
90 {
91 uint32_t argc = argv->GetArgsNumber();
92 if (argc > 0) {
93 [[maybe_unused]] int aaa = GetCallArg(argv, 0)->GetInt();
94 // 10 : test case
95 if (GetCallArg(argv, 0)->GetInt() > 10) {
96 return GetTaggedBoolean(true);
97 }
98 }
99 return GetTaggedBoolean(false);
100 }
101
TestFilterFunc(EcmaRuntimeCallInfo * argv)102 static JSTaggedValue TestFilterFunc(EcmaRuntimeCallInfo *argv)
103 {
104 ASSERT(argv);
105 uint32_t argc = argv->GetArgsNumber();
106 if (argc > 0) {
107 // 10 : test case
108 if (GetCallArg(argv, 0)->GetInt() > 10) {
109 return GetTaggedBoolean(true);
110 }
111 }
112 return GetTaggedBoolean(false);
113 }
114
TestMapFunc(EcmaRuntimeCallInfo * argv)115 static JSTaggedValue TestMapFunc(EcmaRuntimeCallInfo *argv)
116 {
117 int accumulator = GetCallArg(argv, 0)->GetInt();
118 accumulator = accumulator * 2; // 2 : mapped to 2 times the original value
119 return BuiltinsBase::GetTaggedInt(accumulator);
120 }
121
TestFindFunc(EcmaRuntimeCallInfo * argv)122 static JSTaggedValue TestFindFunc(EcmaRuntimeCallInfo *argv)
123 {
124 uint32_t argc = argv->GetArgsNumber();
125 if (argc > 0) {
126 // 10 : test case
127 if (GetCallArg(argv, 0)->GetInt() > 10) {
128 return GetTaggedBoolean(true);
129 }
130 }
131 return GetTaggedBoolean(false);
132 }
133
TestFindIndexFunc(EcmaRuntimeCallInfo * argv)134 static JSTaggedValue TestFindIndexFunc(EcmaRuntimeCallInfo *argv)
135 {
136 uint32_t argc = argv->GetArgsNumber();
137 if (argc > 0) {
138 // 10 : test case
139 if (GetCallArg(argv, 0)->GetInt() > 10) {
140 return GetTaggedBoolean(true);
141 }
142 }
143 return GetTaggedBoolean(false);
144 }
145
TestReduceFunc(EcmaRuntimeCallInfo * argv)146 static JSTaggedValue TestReduceFunc(EcmaRuntimeCallInfo *argv)
147 {
148 int accumulator = GetCallArg(argv, 0)->GetInt();
149 accumulator = accumulator + GetCallArg(argv, 1)->GetInt();
150 return BuiltinsBase::GetTaggedInt(accumulator);
151 }
152
TestReduceRightFunc(EcmaRuntimeCallInfo * argv)153 static JSTaggedValue TestReduceRightFunc(EcmaRuntimeCallInfo *argv)
154 {
155 int accumulator = GetCallArg(argv, 0)->GetInt();
156 accumulator = accumulator + GetCallArg(argv, 1)->GetInt();
157 return BuiltinsBase::GetTaggedInt(accumulator);
158 }
159
TestSomeFunc(EcmaRuntimeCallInfo * argv)160 static JSTaggedValue TestSomeFunc(EcmaRuntimeCallInfo *argv)
161 {
162 uint32_t argc = argv->GetArgsNumber();
163 if (argc > 0) {
164 // 10 : test case
165 if (GetCallArg(argv, 0)->GetInt() > 10) {
166 return GetTaggedBoolean(true);
167 }
168 }
169 return GetTaggedBoolean(false);
170 }
171 };
172 };
173
CreateBuiltinsTypeArrayJSObject(JSThread * thread,const CString keyCStr)174 JSTaggedValue CreateBuiltinsTypeArrayJSObject(JSThread *thread, const CString keyCStr)
175 {
176 auto ecmaVM = thread->GetEcmaVM();
177 JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
178 JSHandle<JSTaggedValue> hclass = env->GetObjectFunction();
179 ObjectFactory *factory = ecmaVM->GetFactory();
180
181 JSHandle<JSTaggedValue> obj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass));
182 JSHandle<JSTaggedValue> key(factory->NewFromASCII(&keyCStr[0]));
183 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
184 JSObject::SetProperty(thread, obj, key, value);
185 return obj.GetTaggedValue();
186 }
187
CreateTypedArrayFromList(JSThread * thread,const JSHandle<TaggedArray> & array)188 JSTypedArray *CreateTypedArrayFromList(JSThread *thread, const JSHandle<TaggedArray> &array)
189 {
190 auto ecmaVM = thread->GetEcmaVM();
191 JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
192
193 JSHandle<JSTaggedValue> jsarray(JSArray::CreateArrayFromList(thread, array));
194 JSHandle<JSFunction> int8_array(env->GetInt8ArrayFunction());
195 JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
196 // 6 : test case
197 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*int8_array), 6);
198 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue(*int8_array));
199 ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject));
200 ecmaRuntimeCallInfo1->SetCallArg(0, jsarray.GetTaggedValue());
201
202 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
203 JSTaggedValue result = TypedArray::Int8ArrayConstructor(ecmaRuntimeCallInfo1);
204 TestHelper::TearDownFrame(thread, prev);
205
206 EXPECT_TRUE(result.IsECMAObject());
207 JSTypedArray *int8arr = JSTypedArray::Cast(reinterpret_cast<TaggedObject *>(result.GetRawData()));
208 return int8arr;
209 }
210
211
HWTEST_F_L0(BuiltinsTypedArrayTest,Species)212 HWTEST_F_L0(BuiltinsTypedArrayTest, Species)
213 {
214 auto ecmaVM = thread->GetEcmaVM();
215 JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
216 JSHandle<JSFunction> array(env->GetArrayFunction());
217 JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
218
219 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
220 ecmaRuntimeCallInfo1->SetFunction(array.GetTaggedValue());
221 ecmaRuntimeCallInfo1->SetThis(globalObject.GetTaggedValue());
222
223 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
224 JSTaggedValue result = TypedArray::Species(ecmaRuntimeCallInfo1);
225 ASSERT_TRUE(result.IsECMAObject());
226 }
227
HWTEST_F_L0(BuiltinsTypedArrayTest,Includes)228 HWTEST_F_L0(BuiltinsTypedArrayTest, Includes)
229 {
230 ASSERT_NE(thread, nullptr);
231 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
232 [[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
233 array->Set(thread, 0, JSTaggedValue(2));
234 array->Set(thread, 1, JSTaggedValue(3));
235 array->Set(thread, 2, JSTaggedValue(4));
236
237 [[maybe_unused]] JSHandle<JSTaggedValue> obj =
238 JSHandle<JSTaggedValue>(thread, CreateTypedArrayFromList(thread, array));
239 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
240 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined());
241 ecmaRuntimeCallInfo1->SetThis(obj.GetTaggedValue());
242 ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(2)));
243
244 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
245 [[maybe_unused]] JSTaggedValue result = TypedArray::Includes(ecmaRuntimeCallInfo1);
246 TestHelper::TearDownFrame(thread, prev);
247
248 ASSERT_TRUE(result.JSTaggedValue::ToBoolean()); // new Int8Array[2,3,4].includes(2)
249
250 auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
251 ecmaRuntimeCallInfo2->SetFunction(JSTaggedValue::Undefined());
252 ecmaRuntimeCallInfo2->SetThis(obj.GetTaggedValue());
253 ecmaRuntimeCallInfo2->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(1)));
254
255 prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
256 result = TypedArray::Includes(ecmaRuntimeCallInfo2);
257 TestHelper::TearDownFrame(thread, prev);
258
259 ASSERT_TRUE(!result.JSTaggedValue::ToBoolean()); // new Int8Array[2,3,4].includes(1)
260
261 auto ecmaRuntimeCallInfo3 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
262 ecmaRuntimeCallInfo3->SetFunction(JSTaggedValue::Undefined());
263 ecmaRuntimeCallInfo3->SetThis(obj.GetTaggedValue());
264 ecmaRuntimeCallInfo3->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(3)));
265 ecmaRuntimeCallInfo3->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(1)));
266
267 prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo3);
268 result = TypedArray::Includes(ecmaRuntimeCallInfo3);
269 TestHelper::TearDownFrame(thread, prev);
270
271 ASSERT_TRUE(result.JSTaggedValue::ToBoolean()); // new Int8Array[2,3,4].includes(3, 1)
272
273 auto ecmaRuntimeCallInfo4 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
274 ecmaRuntimeCallInfo4->SetFunction(JSTaggedValue::Undefined());
275 ecmaRuntimeCallInfo4->SetThis(obj.GetTaggedValue());
276 ecmaRuntimeCallInfo4->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(2)));
277 ecmaRuntimeCallInfo4->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(5)));
278
279 prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo4);
280 result = Array::Includes(ecmaRuntimeCallInfo4);
281 TestHelper::TearDownFrame(thread, prev);
282
283 ASSERT_TRUE(!result.JSTaggedValue::ToBoolean()); // new Int8Array[2,3,4].includes(2, 5)
284
285 auto ecmaRuntimeCallInfo5 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
286 ecmaRuntimeCallInfo5->SetFunction(JSTaggedValue::Undefined());
287 ecmaRuntimeCallInfo5->SetThis(obj.GetTaggedValue());
288 ecmaRuntimeCallInfo5->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(2)));
289 ecmaRuntimeCallInfo5->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(-2)));
290
291 prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo5);
292 result = Array::Includes(ecmaRuntimeCallInfo5);
293 TestHelper::TearDownFrame(thread, prev);
294
295 ASSERT_TRUE(!result.JSTaggedValue::ToBoolean()); // new Int8Array[2,3,4].includes(2, -2)
296 }
297 } // namespace panda::test
298