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