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 "frameworks/bridge/js_frontend/engine/jsi/ark_js_value.h"
17
18 // NOLINTNEXTLINE(readability-identifier-naming)
19 namespace OHOS::Ace::Framework {
ToInt32(shared_ptr<JsRuntime> runtime)20 int32_t ArkJSValue::ToInt32(shared_ptr<JsRuntime> runtime)
21 {
22 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
23 const EcmaVM* vm = pandaRuntime->GetEcmaVm();
24 LocalScope scope(vm);
25 if (CheckException(pandaRuntime)) {
26 LOGE("ArkJSValue::ToInt32 occurs exception, return 0 directly");
27 return 0;
28 }
29 return value_->Int32Value(vm);
30 }
31
ToDouble(shared_ptr<JsRuntime> runtime)32 double ArkJSValue::ToDouble(shared_ptr<JsRuntime> runtime)
33 {
34 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
35 const EcmaVM* vm = pandaRuntime->GetEcmaVm();
36 LocalScope scope(vm);
37 if (CheckException(pandaRuntime)) {
38 LOGE("ArkJSValue::ToDouble occurs exception, return 0 directly");
39 return 0;
40 }
41 Local<NumberRef> number = value_->ToNumber(vm);
42 if (!CheckException(pandaRuntime, number)) {
43 return number->Value();
44 }
45 LOGE("ArkJSValue::ToDouble occurs exception, return 0 directly");
46 return 0;
47 }
48
ToString(shared_ptr<JsRuntime> runtime)49 std::string ArkJSValue::ToString(shared_ptr<JsRuntime> runtime)
50 {
51 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
52 const EcmaVM* vm = pandaRuntime->GetEcmaVm();
53 LocalScope scope(vm);
54 if (CheckException(pandaRuntime)) {
55 LOGE("ArkJSValue::ToString occurs exception, return empty string directly");
56 return "";
57 }
58 Local<StringRef> string = value_->ToString(vm);
59 if (!CheckException(pandaRuntime, string)) {
60 return string->ToString(vm);
61 }
62 LOGE("ArkJSValue::ToString occurs exception, return empty string directly");
63 return "";
64 }
65
ToBoolean(shared_ptr<JsRuntime> runtime)66 bool ArkJSValue::ToBoolean(shared_ptr<JsRuntime> runtime)
67 {
68 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
69 LocalScope scope(pandaRuntime->GetEcmaVm());
70 if (!CheckException(pandaRuntime)) {
71 return value_->BooleaValue(pandaRuntime->GetEcmaVm());
72 }
73 LOGE("ArkJSValue::ToBoolean occurs exception, return false directly");
74 return false;
75 }
76
77 bool ArkJSValue::IsUndefined([[maybe_unused]] shared_ptr<JsRuntime> runtime)
78 {
79 return !value_.IsEmpty() && value_->IsUndefined();
80 }
81
82 bool ArkJSValue::IsNull([[maybe_unused]] shared_ptr<JsRuntime> runtime)
83 {
84 return !value_.IsEmpty() && value_->IsNull();
85 }
86
87 bool ArkJSValue::IsBoolean([[maybe_unused]] shared_ptr<JsRuntime> runtime)
88 {
89 return !value_.IsEmpty() && value_->IsBoolean();
90 }
91
92 bool ArkJSValue::IsInt32([[maybe_unused]] shared_ptr<JsRuntime> runtime)
93 {
94 return !value_.IsEmpty() && value_->IsInt();
95 }
96
97 bool ArkJSValue::WithinInt32([[maybe_unused]] shared_ptr<JsRuntime> runtime)
98 {
99 return !value_.IsEmpty() && value_->WithinInt32();
100 }
101
102 bool ArkJSValue::IsString([[maybe_unused]] shared_ptr<JsRuntime> runtime)
103 {
104 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
105 return !value_.IsEmpty() && value_->IsString(pandaRuntime->GetEcmaVm());
106 }
107
108 bool ArkJSValue::IsNumber([[maybe_unused]] shared_ptr<JsRuntime> runtime)
109 {
110 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
111 return !value_.IsEmpty() && value_->IsNumber();
112 }
113
114 bool ArkJSValue::IsObject([[maybe_unused]] shared_ptr<JsRuntime> runtime)
115 {
116 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
117 return !value_.IsEmpty() && value_->IsObject(pandaRuntime->GetEcmaVm());
118 }
119
120 bool ArkJSValue::IsArray([[maybe_unused]] shared_ptr<JsRuntime> runtime)
121 {
122 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
123 return !value_.IsEmpty() && value_->IsArray(pandaRuntime->GetEcmaVm());
124 }
125
126 bool ArkJSValue::IsFunction([[maybe_unused]] shared_ptr<JsRuntime> runtime)
127 {
128 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
129 return !value_.IsEmpty() && value_->IsFunction(pandaRuntime->GetEcmaVm());
130 }
131
132 // NOLINTNEXTLINE(performance-unnecessary-value-param)
133 bool ArkJSValue::IsException([[maybe_unused]] shared_ptr<JsRuntime> runtime)
134 {
135 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
136 return value_.IsEmpty() || pandaRuntime->HasPendingException();
137 }
138
Call(shared_ptr<JsRuntime> runtime,shared_ptr<JsValue> thisObj,std::vector<shared_ptr<JsValue>> argv,int32_t argc)139 shared_ptr<JsValue> ArkJSValue::Call(shared_ptr<JsRuntime> runtime, shared_ptr<JsValue> thisObj,
140 std::vector<shared_ptr<JsValue>> argv, int32_t argc)
141 {
142 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
143 const EcmaVM* vm = pandaRuntime->GetEcmaVm();
144 JSExecutionScope executionScope(vm);
145 LocalScope scope(vm);
146 panda::TryCatch trycatch(vm);
147 if (!IsFunction(pandaRuntime)) {
148 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
149 }
150 std::vector<Local<JSValueRef>> arguments;
151 arguments.reserve(argc);
152 for (const shared_ptr<JsValue> &arg : argv) {
153 arguments.emplace_back(std::static_pointer_cast<ArkJSValue>(arg)->GetValue(pandaRuntime));
154 }
155 Local<JSValueRef> thisValue = std::static_pointer_cast<ArkJSValue>(thisObj)->GetValue(pandaRuntime);
156 Local<FunctionRef> function(GetValue(pandaRuntime));
157 Local<JSValueRef> result = function->Call(vm, thisValue, arguments.data(), argc);
158 bool hasCaught = trycatch.HasCaught();
159 pandaRuntime->HandleUncaughtException(trycatch);
160 if (hasCaught) {
161 result = JSValueRef::Undefined(vm);
162 }
163 return std::make_shared<ArkJSValue>(pandaRuntime, result);
164 }
165
GetPropertyNames(shared_ptr<JsRuntime> runtime,shared_ptr<JsValue> & propName,int32_t & len)166 bool ArkJSValue::GetPropertyNames(shared_ptr<JsRuntime> runtime, shared_ptr<JsValue> &propName, int32_t &len)
167 {
168 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
169 const EcmaVM* vm = pandaRuntime->GetEcmaVm();
170 LocalScope scope(vm);
171 if (CheckException(pandaRuntime)) {
172 LOGE("ArkJSValue::GetPropertyNames occurs exception, return false directly");
173 return false;
174 }
175 Local<ObjectRef> obj = value_->ToObject(vm);
176 if (CheckException(pandaRuntime, obj)) {
177 LOGE("ArkJSValue::GetPropertyNames occurs exception, return false directly");
178 return false;
179 }
180 Local<ArrayRef> names = obj->GetOwnPropertyNames(vm);
181 len = static_cast<int32_t>(names->Length(vm));
182 if (!propName) {
183 propName = std::make_shared<ArkJSValue>(pandaRuntime, names);
184 } else {
185 std::static_pointer_cast<ArkJSValue>(propName)->SetValue(pandaRuntime, names);
186 }
187 return true;
188 }
189
GetEnumerablePropertyNames(shared_ptr<JsRuntime> runtime,shared_ptr<JsValue> & propName,int32_t & len)190 bool ArkJSValue::GetEnumerablePropertyNames(shared_ptr<JsRuntime> runtime, shared_ptr<JsValue> &propName, int32_t &len)
191 {
192 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
193 const EcmaVM* vm = pandaRuntime->GetEcmaVm();
194 LocalScope scope(vm);
195 if (CheckException(pandaRuntime)) {
196 LOGE("ArkJSValue::GetEnumerablePropertyNames occurs exception, return false directly");
197 return false;
198 }
199 Local<ObjectRef> obj = value_->ToObject(vm);
200 if (CheckException(pandaRuntime, obj)) {
201 LOGE("ArkJSValue::GetEnumerablePropertyNames occurs exception, return false directly");
202 return false;
203 }
204 Local<ArrayRef> names = obj->GetOwnEnumerablePropertyNames(vm);
205 len = static_cast<int32_t>(names->Length(vm));
206 if (!propName) {
207 propName = std::make_shared<ArkJSValue>(pandaRuntime, names);
208 } else {
209 std::static_pointer_cast<ArkJSValue>(propName)->SetValue(pandaRuntime, names);
210 }
211 return true;
212 }
213
GetProperty(shared_ptr<JsRuntime> runtime,int32_t idx)214 shared_ptr<JsValue> ArkJSValue::GetProperty(shared_ptr<JsRuntime> runtime, int32_t idx)
215 {
216 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
217 const EcmaVM* vm = pandaRuntime->GetEcmaVm();
218 LocalScope scope(vm);
219 if (CheckException(pandaRuntime)) {
220 LOGE("ArkJSValue::GetProperty occurs exception, return undefined directly");
221 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
222 }
223 Local<ObjectRef> obj = value_->ToObject(vm);
224 if (CheckException(pandaRuntime, obj)) {
225 LOGE("ArkJSValue::GetProperty occurs exception, return undefined directly");
226 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
227 }
228 Local<JSValueRef> property = obj->Get(vm, idx);
229 if (CheckException(pandaRuntime, property)) {
230 LOGE("ArkJSValue::GetProperty occurs exception, return undefined directly");
231 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
232 }
233 return std::make_shared<ArkJSValue>(pandaRuntime, property);
234 }
235
GetProperty(shared_ptr<JsRuntime> runtime,const std::string & name)236 shared_ptr<JsValue> ArkJSValue::GetProperty(shared_ptr<JsRuntime> runtime, const std::string &name)
237 {
238 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
239 LocalScope scope(pandaRuntime->GetEcmaVm());
240 shared_ptr<JsValue> key = pandaRuntime->NewString(name);
241 return GetProperty(runtime, key);
242 }
243
GetProperty(shared_ptr<JsRuntime> runtime,const shared_ptr<JsValue> & name)244 shared_ptr<JsValue> ArkJSValue::GetProperty(shared_ptr<JsRuntime> runtime, const shared_ptr<JsValue> &name)
245 {
246 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
247 const EcmaVM* vm = pandaRuntime->GetEcmaVm();
248 LocalScope scope(vm);
249 if (CheckException(pandaRuntime)) {
250 LOGE("ArkJSValue::GetProperty occurs exception, return undefined directly");
251 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
252 }
253 Local<ObjectRef> obj = value_->ToObject(vm);
254 if (CheckException(pandaRuntime, obj)) {
255 LOGE("ArkJSValue::GetProperty occurs exception, return undefined directly");
256 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
257 }
258 Local<JSValueRef> key = std::static_pointer_cast<ArkJSValue>(name)->GetValue(pandaRuntime);
259 Local<JSValueRef> property = obj->Get(vm, key);
260 if (CheckException(pandaRuntime, property)) {
261 LOGE("ArkJSValue::GetProperty occurs exception, return undefined directly");
262 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
263 }
264 return std::make_shared<ArkJSValue>(pandaRuntime, property);
265 }
266
SetProperty(shared_ptr<JsRuntime> runtime,const std::string & name,const shared_ptr<JsValue> & value)267 bool ArkJSValue::SetProperty(shared_ptr<JsRuntime> runtime, const std::string &name, const shared_ptr<JsValue> &value)
268 {
269 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
270 LocalScope scope(pandaRuntime->GetEcmaVm());
271 shared_ptr<JsValue> key = pandaRuntime->NewString(name);
272 return SetProperty(runtime, key, value);
273 }
274
SetProperty(shared_ptr<JsRuntime> runtime,const shared_ptr<JsValue> & name,const shared_ptr<JsValue> & value)275 bool ArkJSValue::SetProperty(shared_ptr<JsRuntime> runtime, const shared_ptr<JsValue> &name,
276 const shared_ptr<JsValue> &value)
277 {
278 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
279 const EcmaVM* vm = pandaRuntime->GetEcmaVm();
280 LocalScope scope(vm);
281 if (CheckException(pandaRuntime)) {
282 LOGE("ArkJSValue::SetProperty occurs exception, return false directly");
283 return false;
284 }
285 Local<ObjectRef> obj = value_->ToObject(vm);
286 if (CheckException(pandaRuntime, obj)) {
287 LOGE("ArkJSValue::SetProperty occurs exception, return false directly");
288 return false;
289 }
290 Local<JSValueRef> key = std::static_pointer_cast<ArkJSValue>(name)->GetValue(pandaRuntime);
291 Local<JSValueRef> value_ref = std::static_pointer_cast<ArkJSValue>(value)->GetValue(pandaRuntime);
292 return obj->Set(vm, key, value_ref);
293 }
294
SetAccessorProperty(shared_ptr<JsRuntime> runtime,const std::string & name,const shared_ptr<JsValue> & getter,const shared_ptr<JsValue> & setter)295 bool ArkJSValue::SetAccessorProperty(shared_ptr<JsRuntime> runtime, const std::string &name,
296 const shared_ptr<JsValue> &getter, const shared_ptr<JsValue> &setter)
297 {
298 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
299 LocalScope scope(pandaRuntime->GetEcmaVm());
300 shared_ptr<JsValue> key = pandaRuntime->NewString(name);
301 return SetAccessorProperty(runtime, key, getter, setter);
302 }
303
SetAccessorProperty(shared_ptr<JsRuntime> runtime,const shared_ptr<JsValue> & name,const shared_ptr<JsValue> & getter,const shared_ptr<JsValue> & setter)304 bool ArkJSValue::SetAccessorProperty(shared_ptr<JsRuntime> runtime, const shared_ptr<JsValue> &name,
305 const shared_ptr<JsValue> &getter, const shared_ptr<JsValue> &setter)
306 {
307 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
308 const EcmaVM* vm = pandaRuntime->GetEcmaVm();
309 LocalScope scope(vm);
310 if (CheckException(pandaRuntime)) {
311 LOGE("ArkJSValue::SetAccessorProperty occurs exception, return false directly");
312 return false;
313 }
314 Local<ObjectRef> obj = value_->ToObject(vm);
315 if (CheckException(pandaRuntime, obj)) {
316 LOGE("ArkJSValue::SetAccessorProperty occurs exception, return false directly");
317 return false;
318 }
319 Local<JSValueRef> key = std::static_pointer_cast<ArkJSValue>(name)->GetValue(pandaRuntime);
320 Local<JSValueRef> getterValue = std::static_pointer_cast<ArkJSValue>(getter)->GetValue(pandaRuntime);
321 Local<JSValueRef> setterValue = std::static_pointer_cast<ArkJSValue>(setter)->GetValue(pandaRuntime);
322 return obj->SetAccessorProperty(vm, key, getterValue, setterValue);
323 }
324
HasProperty(shared_ptr<JsRuntime> runtime,const std::string & name)325 bool ArkJSValue::HasProperty(shared_ptr<JsRuntime> runtime, const std::string &name)
326 {
327 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
328 LocalScope scope(pandaRuntime->GetEcmaVm());
329 shared_ptr<JsValue> key = pandaRuntime->NewString(name);
330 return HasProperty(runtime, key);
331 }
332
HasProperty(shared_ptr<JsRuntime> runtime,const shared_ptr<JsValue> & name)333 bool ArkJSValue::HasProperty(shared_ptr<JsRuntime> runtime, const shared_ptr<JsValue> &name)
334 {
335 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
336 const EcmaVM* vm = pandaRuntime->GetEcmaVm();
337 LocalScope scope(vm);
338 if (CheckException(pandaRuntime)) {
339 LOGE("ArkJSValue::HasProperty occurs exception, return false directly");
340 return false;
341 }
342 Local<ObjectRef> obj = value_->ToObject(vm);
343 if (CheckException(pandaRuntime, obj)) {
344 LOGE("ArkJSValue::HasProperty occurs exception, return false directly");
345 return false;
346 }
347 Local<JSValueRef> key = std::static_pointer_cast<ArkJSValue>(name)->GetValue(pandaRuntime);
348 bool hasProperty = obj->Has(vm, key);
349 if (CheckException(pandaRuntime)) {
350 LOGE("ArkJSValue::HasProperty occurs exception, return false directly");
351 return false;
352 }
353 return hasProperty;
354 }
355
GetArrayLength(shared_ptr<JsRuntime> runtime)356 int32_t ArkJSValue::GetArrayLength(shared_ptr<JsRuntime> runtime)
357 {
358 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
359 const EcmaVM* vm = pandaRuntime->GetEcmaVm();
360 LocalScope scope(vm);
361 if (CheckException(pandaRuntime)) {
362 LOGE("ArkJSValue::GetArrayLength occurs exception, return -1 directly");
363 return -1;
364 }
365 Local<ArrayRef> array(GetValue(pandaRuntime));
366 return array->Length(vm);
367 }
368
GetElement(shared_ptr<JsRuntime> runtime,int32_t idx)369 shared_ptr<JsValue> ArkJSValue::GetElement(shared_ptr<JsRuntime> runtime, int32_t idx)
370 {
371 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
372 const EcmaVM* vm = pandaRuntime->GetEcmaVm();
373 LocalScope scope(vm);
374 if (CheckException(pandaRuntime)) {
375 LOGE("ArkJSValue::GetElement occurs exception, return undefined directly");
376 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
377 }
378 Local<ArrayRef> obj(GetValue(pandaRuntime));
379 if (CheckException(pandaRuntime, obj)) {
380 LOGE("ArkJSValue::GetElement occurs exception, return undefined directly");
381 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
382 }
383 Local<JSValueRef> property = obj->Get(vm, idx);
384 if (CheckException(pandaRuntime, property)) {
385 LOGE("ArkJSValue::GetElement occurs exception, return undefined directly");
386 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
387 }
388 return std::make_shared<ArkJSValue>(pandaRuntime, property);
389 }
390
GetJsonString(const shared_ptr<JsRuntime> & runtime)391 std::string ArkJSValue::GetJsonString(const shared_ptr<JsRuntime>& runtime)
392 {
393 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
394 const EcmaVM* vm = pandaRuntime->GetEcmaVm();
395 LocalScope scope(vm);
396 auto stringify = panda::JSON::Stringify(vm, GetValue(pandaRuntime));
397 if (CheckException(pandaRuntime, stringify)) {
398 LOGE("ArkJSValue::GetJsonString occurs exception, return empty string directly");
399 return "";
400 }
401 auto valueStr = panda::Local<panda::StringRef>(stringify);
402 if (CheckException(pandaRuntime, valueStr)) {
403 LOGE("ArkJSValue::GetJsonString occurs exception, return empty string directly");
404 return "";
405 }
406 return valueStr->ToString(pandaRuntime->GetEcmaVm());
407 }
408
CheckException(const shared_ptr<ArkJSRuntime> & runtime) const409 bool ArkJSValue::CheckException(const shared_ptr<ArkJSRuntime> &runtime) const
410 {
411 return value_.IsEmpty() || runtime->HasPendingException();
412 }
413
CheckException(const shared_ptr<ArkJSRuntime> & runtime,const Local<JSValueRef> & value) const414 bool ArkJSValue::CheckException(const shared_ptr<ArkJSRuntime> &runtime, const Local<JSValueRef> &value) const
415 {
416 return value.IsEmpty() || runtime->HasPendingException();
417 }
418 } // namespace OHOS::Ace::Framework
419