• 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     panda::TryCatch trycatch(vm);
146     if (!IsFunction(pandaRuntime)) {
147         return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
148     }
149     std::vector<Local<JSValueRef>> arguments;
150     arguments.reserve(argc);
151     for (const shared_ptr<JsValue> &arg : argv) {
152         arguments.emplace_back(std::static_pointer_cast<ArkJSValue>(arg)->GetValue(pandaRuntime));
153     }
154     Local<JSValueRef> thisValue = std::static_pointer_cast<ArkJSValue>(thisObj)->GetValue(pandaRuntime);
155     Local<FunctionRef> function(GetValue(pandaRuntime));
156     Local<JSValueRef> result = function->Call(vm, thisValue, arguments.data(), argc);
157     bool hasCaught = trycatch.HasCaught();
158     pandaRuntime->HandleUncaughtException(trycatch);
159     if (hasCaught) {
160         result = JSValueRef::Undefined(vm);
161     }
162     return std::make_shared<ArkJSValue>(pandaRuntime, result);
163 }
164 
GetPropertyNames(shared_ptr<JsRuntime> runtime,shared_ptr<JsValue> & propName,int32_t & len)165 bool ArkJSValue::GetPropertyNames(shared_ptr<JsRuntime> runtime, shared_ptr<JsValue> &propName, int32_t &len)
166 {
167     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
168     const EcmaVM* vm = pandaRuntime->GetEcmaVm();
169     LocalScope scope(vm);
170     if (CheckException(pandaRuntime)) {
171         LOGE("ArkJSValue::GetPropertyNames occurs exception, return false directly");
172         return false;
173     }
174     Local<ObjectRef> obj = value_->ToObject(vm);
175     if (CheckException(pandaRuntime, obj)) {
176         LOGE("ArkJSValue::GetPropertyNames occurs exception, return false directly");
177         return false;
178     }
179     Local<ArrayRef> names = obj->GetOwnPropertyNames(vm);
180     len = names->Length(vm);
181     if (!propName) {
182         propName = std::make_shared<ArkJSValue>(pandaRuntime, names);
183     } else {
184         std::static_pointer_cast<ArkJSValue>(propName)->SetValue(pandaRuntime, names);
185     }
186     return true;
187 }
188 
GetEnumerablePropertyNames(shared_ptr<JsRuntime> runtime,shared_ptr<JsValue> & propName,int32_t & len)189 bool ArkJSValue::GetEnumerablePropertyNames(shared_ptr<JsRuntime> runtime, shared_ptr<JsValue> &propName, int32_t &len)
190 {
191     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
192     const EcmaVM* vm = pandaRuntime->GetEcmaVm();
193     LocalScope scope(vm);
194     if (CheckException(pandaRuntime)) {
195         LOGE("ArkJSValue::GetEnumerablePropertyNames occurs exception, return false directly");
196         return false;
197     }
198     Local<ObjectRef> obj = value_->ToObject(vm);
199     if (CheckException(pandaRuntime, obj)) {
200         LOGE("ArkJSValue::GetEnumerablePropertyNames occurs exception, return false directly");
201         return false;
202     }
203     Local<ArrayRef> names = obj->GetOwnEnumerablePropertyNames(vm);
204     len = names->Length(vm);
205     if (!propName) {
206         propName = std::make_shared<ArkJSValue>(pandaRuntime, names);
207     } else {
208         std::static_pointer_cast<ArkJSValue>(propName)->SetValue(pandaRuntime, names);
209     }
210     return true;
211 }
212 
GetProperty(shared_ptr<JsRuntime> runtime,int32_t idx)213 shared_ptr<JsValue> ArkJSValue::GetProperty(shared_ptr<JsRuntime> runtime, int32_t idx)
214 {
215     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
216     const EcmaVM* vm = pandaRuntime->GetEcmaVm();
217     LocalScope scope(vm);
218     if (CheckException(pandaRuntime)) {
219         LOGE("ArkJSValue::GetProperty occurs exception, return undefined directly");
220         return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
221     }
222     Local<ObjectRef> obj = value_->ToObject(vm);
223     if (CheckException(pandaRuntime, obj)) {
224         LOGE("ArkJSValue::GetProperty occurs exception, return undefined directly");
225         return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
226     }
227     Local<JSValueRef> property = obj->Get(vm, idx);
228     if (CheckException(pandaRuntime, property)) {
229         LOGE("ArkJSValue::GetProperty occurs exception, return undefined directly");
230         return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
231     }
232     return std::make_shared<ArkJSValue>(pandaRuntime, property);
233 }
234 
GetProperty(shared_ptr<JsRuntime> runtime,const std::string & name)235 shared_ptr<JsValue> ArkJSValue::GetProperty(shared_ptr<JsRuntime> runtime, const std::string &name)
236 {
237     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
238     LocalScope scope(pandaRuntime->GetEcmaVm());
239     shared_ptr<JsValue> key = pandaRuntime->NewString(name);
240     return GetProperty(runtime, key);
241 }
242 
GetProperty(shared_ptr<JsRuntime> runtime,const shared_ptr<JsValue> & name)243 shared_ptr<JsValue> ArkJSValue::GetProperty(shared_ptr<JsRuntime> runtime, const shared_ptr<JsValue> &name)
244 {
245     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
246     const EcmaVM* vm = pandaRuntime->GetEcmaVm();
247     LocalScope scope(vm);
248     if (CheckException(pandaRuntime)) {
249         LOGE("ArkJSValue::GetProperty occurs exception, return undefined directly");
250         return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
251     }
252     Local<ObjectRef> obj = value_->ToObject(vm);
253     if (CheckException(pandaRuntime, obj)) {
254         LOGE("ArkJSValue::GetProperty occurs exception, return undefined directly");
255         return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
256     }
257     Local<JSValueRef> key = std::static_pointer_cast<ArkJSValue>(name)->GetValue(pandaRuntime);
258     Local<JSValueRef> property = obj->Get(vm, key);
259     if (CheckException(pandaRuntime, property)) {
260         LOGE("ArkJSValue::GetProperty occurs exception, return undefined directly");
261         return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
262     }
263     return std::make_shared<ArkJSValue>(pandaRuntime, property);
264 }
265 
SetProperty(shared_ptr<JsRuntime> runtime,const std::string & name,const shared_ptr<JsValue> & value)266 bool ArkJSValue::SetProperty(shared_ptr<JsRuntime> runtime, const std::string &name, const shared_ptr<JsValue> &value)
267 {
268     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
269     LocalScope scope(pandaRuntime->GetEcmaVm());
270     shared_ptr<JsValue> key = pandaRuntime->NewString(name);
271     return SetProperty(runtime, key, value);
272 }
273 
SetProperty(shared_ptr<JsRuntime> runtime,const shared_ptr<JsValue> & name,const shared_ptr<JsValue> & value)274 bool ArkJSValue::SetProperty(shared_ptr<JsRuntime> runtime, const shared_ptr<JsValue> &name,
275                              const shared_ptr<JsValue> &value)
276 {
277     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
278     const EcmaVM* vm = pandaRuntime->GetEcmaVm();
279     LocalScope scope(vm);
280     if (CheckException(pandaRuntime)) {
281         LOGE("ArkJSValue::SetProperty occurs exception, return false directly");
282         return false;
283     }
284     Local<ObjectRef> obj = value_->ToObject(vm);
285     if (CheckException(pandaRuntime, obj)) {
286         LOGE("ArkJSValue::SetProperty occurs exception, return false directly");
287         return false;
288     }
289     Local<JSValueRef> key = std::static_pointer_cast<ArkJSValue>(name)->GetValue(pandaRuntime);
290     Local<JSValueRef> value_ref = std::static_pointer_cast<ArkJSValue>(value)->GetValue(pandaRuntime);
291     return obj->Set(vm, key, value_ref);
292 }
293 
SetAccessorProperty(shared_ptr<JsRuntime> runtime,const std::string & name,const shared_ptr<JsValue> & getter,const shared_ptr<JsValue> & setter)294 bool ArkJSValue::SetAccessorProperty(shared_ptr<JsRuntime> runtime, const std::string &name,
295                                      const shared_ptr<JsValue> &getter, const shared_ptr<JsValue> &setter)
296 {
297     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
298     LocalScope scope(pandaRuntime->GetEcmaVm());
299     shared_ptr<JsValue> key = pandaRuntime->NewString(name);
300     return SetAccessorProperty(runtime, key, getter, setter);
301 }
302 
SetAccessorProperty(shared_ptr<JsRuntime> runtime,const shared_ptr<JsValue> & name,const shared_ptr<JsValue> & getter,const shared_ptr<JsValue> & setter)303 bool ArkJSValue::SetAccessorProperty(shared_ptr<JsRuntime> runtime, const shared_ptr<JsValue> &name,
304                                      const shared_ptr<JsValue> &getter, const shared_ptr<JsValue> &setter)
305 {
306     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
307     const EcmaVM* vm = pandaRuntime->GetEcmaVm();
308     LocalScope scope(vm);
309     if (CheckException(pandaRuntime)) {
310         LOGE("ArkJSValue::SetAccessorProperty occurs exception, return false directly");
311         return false;
312     }
313     Local<ObjectRef> obj = value_->ToObject(vm);
314     if (CheckException(pandaRuntime, obj)) {
315         LOGE("ArkJSValue::SetAccessorProperty occurs exception, return false directly");
316         return false;
317     }
318     Local<JSValueRef> key = std::static_pointer_cast<ArkJSValue>(name)->GetValue(pandaRuntime);
319     Local<JSValueRef> getterValue = std::static_pointer_cast<ArkJSValue>(getter)->GetValue(pandaRuntime);
320     Local<JSValueRef> setterValue = std::static_pointer_cast<ArkJSValue>(setter)->GetValue(pandaRuntime);
321     return obj->SetAccessorProperty(vm, key, getterValue, setterValue);
322 }
323 
HasProperty(shared_ptr<JsRuntime> runtime,const std::string & name)324 bool ArkJSValue::HasProperty(shared_ptr<JsRuntime> runtime, const std::string &name)
325 {
326     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
327     LocalScope scope(pandaRuntime->GetEcmaVm());
328     shared_ptr<JsValue> key = pandaRuntime->NewString(name);
329     return HasProperty(runtime, key);
330 }
331 
HasProperty(shared_ptr<JsRuntime> runtime,const shared_ptr<JsValue> & name)332 bool ArkJSValue::HasProperty(shared_ptr<JsRuntime> runtime, const shared_ptr<JsValue> &name)
333 {
334     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
335     const EcmaVM* vm = pandaRuntime->GetEcmaVm();
336     LocalScope scope(vm);
337     if (CheckException(pandaRuntime)) {
338         LOGE("ArkJSValue::HasProperty occurs exception, return false directly");
339         return false;
340     }
341     Local<ObjectRef> obj = value_->ToObject(vm);
342     if (CheckException(pandaRuntime, obj)) {
343         LOGE("ArkJSValue::HasProperty occurs exception, return false directly");
344         return false;
345     }
346     Local<JSValueRef> key = std::static_pointer_cast<ArkJSValue>(name)->GetValue(pandaRuntime);
347     bool hasProperty = obj->Has(vm, key);
348     if (CheckException(pandaRuntime)) {
349         LOGE("ArkJSValue::HasProperty occurs exception, return false directly");
350         return false;
351     }
352     return hasProperty;
353 }
354 
GetArrayLength(shared_ptr<JsRuntime> runtime)355 int32_t ArkJSValue::GetArrayLength(shared_ptr<JsRuntime> runtime)
356 {
357     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
358     const EcmaVM* vm = pandaRuntime->GetEcmaVm();
359     LocalScope scope(vm);
360     if (CheckException(pandaRuntime)) {
361         LOGE("ArkJSValue::GetArrayLength occurs exception, return -1 directly");
362         return -1;
363     }
364     Local<ArrayRef> array(GetValue(pandaRuntime));
365     return array->Length(vm);
366 }
367 
GetElement(shared_ptr<JsRuntime> runtime,int32_t idx)368 shared_ptr<JsValue> ArkJSValue::GetElement(shared_ptr<JsRuntime> runtime, int32_t idx)
369 {
370     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
371     const EcmaVM* vm = pandaRuntime->GetEcmaVm();
372     LocalScope scope(vm);
373     if (CheckException(pandaRuntime)) {
374         LOGE("ArkJSValue::GetElement occurs exception, return undefined directly");
375         return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
376     }
377     Local<ArrayRef> obj(GetValue(pandaRuntime));
378     if (CheckException(pandaRuntime, obj)) {
379         LOGE("ArkJSValue::GetElement occurs exception, return undefined directly");
380         return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
381     }
382     Local<JSValueRef> property = obj->Get(vm, idx);
383     if (CheckException(pandaRuntime, property)) {
384         LOGE("ArkJSValue::GetElement occurs exception, return undefined directly");
385         return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(vm));
386     }
387     return std::make_shared<ArkJSValue>(pandaRuntime, property);
388 }
389 
GetJsonString(const shared_ptr<JsRuntime> & runtime)390 std::string ArkJSValue::GetJsonString(const shared_ptr<JsRuntime>& runtime)
391 {
392     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
393     const EcmaVM* vm = pandaRuntime->GetEcmaVm();
394     LocalScope scope(vm);
395     auto stringify = panda::JSON::Stringify(vm, GetValue(pandaRuntime));
396     if (CheckException(pandaRuntime, stringify)) {
397         LOGE("ArkJSValue::GetJsonString occurs exception, return empty string directly");
398         return "";
399     }
400     auto valueStr = panda::Local<panda::StringRef>(stringify);
401     if (CheckException(pandaRuntime, valueStr)) {
402         LOGE("ArkJSValue::GetJsonString occurs exception, return empty string directly");
403         return "";
404     }
405     return valueStr->ToString();
406 }
407 
CheckException(const shared_ptr<ArkJSRuntime> & runtime) const408 bool ArkJSValue::CheckException(const shared_ptr<ArkJSRuntime> &runtime) const
409 {
410     return value_.IsEmpty() || runtime->HasPendingException();
411 }
412 
CheckException(const shared_ptr<ArkJSRuntime> & runtime,const Local<JSValueRef> & value) const413 bool ArkJSValue::CheckException(const shared_ptr<ArkJSRuntime> &runtime, const Local<JSValueRef> &value) const
414 {
415     return value.IsEmpty() || runtime->HasPendingException();
416 }
417 }  // namespace OHOS::Ace::Framework
418