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 #include <iostream>
19
20 // NOLINTNEXTLINE(readability-identifier-naming)
21 namespace OHOS::Ace::Framework {
ToInt32(shared_ptr<JsRuntime> runtime)22 int32_t ArkJSValue::ToInt32(shared_ptr<JsRuntime> runtime)
23 {
24 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
25 LocalScope scope(pandaRuntime->GetEcmaVm());
26 if (CheckException(pandaRuntime)) {
27 return 0;
28 }
29 return value_->Int32Value(pandaRuntime->GetEcmaVm());
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 LocalScope scope(pandaRuntime->GetEcmaVm());
36 if (CheckException(pandaRuntime)) {
37 return 0;
38 }
39 Local<NumberRef> number = value_->ToNumber(pandaRuntime->GetEcmaVm());
40 if (!CheckException(pandaRuntime, number)) {
41 return number->Value();
42 }
43 return 0;
44 }
45
ToString(shared_ptr<JsRuntime> runtime)46 std::string ArkJSValue::ToString(shared_ptr<JsRuntime> runtime)
47 {
48 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
49 LocalScope scope(pandaRuntime->GetEcmaVm());
50 if (CheckException(pandaRuntime)) {
51 return "";
52 }
53 Local<StringRef> string = value_->ToString(pandaRuntime->GetEcmaVm());
54 if (!CheckException(pandaRuntime, string)) {
55 return string->ToString();
56 }
57 return "";
58 }
59
ToBoolean(shared_ptr<JsRuntime> runtime)60 bool ArkJSValue::ToBoolean(shared_ptr<JsRuntime> runtime)
61 {
62 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
63 LocalScope scope(pandaRuntime->GetEcmaVm());
64 return !CheckException(pandaRuntime) && value_->BooleaValue();
65 }
66
IsUndefined(shared_ptr<JsRuntime> runtime)67 bool ArkJSValue::IsUndefined([[maybe_unused]] shared_ptr<JsRuntime> runtime)
68 {
69 return !value_.IsEmpty() && value_->IsUndefined();
70 }
71
IsNull(shared_ptr<JsRuntime> runtime)72 bool ArkJSValue::IsNull([[maybe_unused]] shared_ptr<JsRuntime> runtime)
73 {
74 return !value_.IsEmpty() && value_->IsNull();
75 }
76
IsBoolean(shared_ptr<JsRuntime> runtime)77 bool ArkJSValue::IsBoolean([[maybe_unused]] shared_ptr<JsRuntime> runtime)
78 {
79 return !value_.IsEmpty() && value_->IsBoolean();
80 }
81
IsInt32(shared_ptr<JsRuntime> runtime)82 bool ArkJSValue::IsInt32([[maybe_unused]] shared_ptr<JsRuntime> runtime)
83 {
84 return !value_.IsEmpty() && value_->IsInt();
85 }
86
WithinInt32(shared_ptr<JsRuntime> runtime)87 bool ArkJSValue::WithinInt32([[maybe_unused]] shared_ptr<JsRuntime> runtime)
88 {
89 return !value_.IsEmpty() && value_->WithinInt32();
90 }
91
IsString(shared_ptr<JsRuntime> runtime)92 bool ArkJSValue::IsString([[maybe_unused]] shared_ptr<JsRuntime> runtime)
93 {
94 return !value_.IsEmpty() && value_->IsString();
95 }
96
IsNumber(shared_ptr<JsRuntime> runtime)97 bool ArkJSValue::IsNumber([[maybe_unused]] shared_ptr<JsRuntime> runtime)
98 {
99 return !value_.IsEmpty() && value_->IsNumber();
100 }
101
IsObject(shared_ptr<JsRuntime> runtime)102 bool ArkJSValue::IsObject([[maybe_unused]] shared_ptr<JsRuntime> runtime)
103 {
104 return !value_.IsEmpty() && value_->IsObject();
105 }
106
IsArray(shared_ptr<JsRuntime> runtime)107 bool ArkJSValue::IsArray([[maybe_unused]] shared_ptr<JsRuntime> runtime)
108 {
109 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
110 return !value_.IsEmpty() && value_->IsArray(pandaRuntime->GetEcmaVm());
111 }
112
IsFunction(shared_ptr<JsRuntime> runtime)113 bool ArkJSValue::IsFunction([[maybe_unused]] shared_ptr<JsRuntime> runtime)
114 {
115 return !value_.IsEmpty() && value_->IsFunction();
116 }
117
118 // NOLINTNEXTLINE(performance-unnecessary-value-param)
IsException(shared_ptr<JsRuntime> runtime)119 bool ArkJSValue::IsException([[maybe_unused]] shared_ptr<JsRuntime> runtime)
120 {
121 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
122 return value_.IsEmpty() || pandaRuntime->HasPendingException();
123 }
124
Call(shared_ptr<JsRuntime> runtime,shared_ptr<JsValue> thisObj,std::vector<shared_ptr<JsValue>> argv,int32_t argc)125 shared_ptr<JsValue> ArkJSValue::Call(shared_ptr<JsRuntime> runtime, shared_ptr<JsValue> thisObj,
126 std::vector<shared_ptr<JsValue>> argv, int32_t argc)
127 {
128 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
129 JSExecutionScope executionScope(pandaRuntime->GetEcmaVm());
130 LocalScope scope(pandaRuntime->GetEcmaVm());
131 if (!IsFunction(pandaRuntime)) {
132 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(pandaRuntime->GetEcmaVm()));
133 }
134 std::vector<Local<JSValueRef>> arguments;
135 arguments.reserve(argc);
136 for (const shared_ptr<JsValue> &arg : argv) {
137 arguments.emplace_back(std::static_pointer_cast<ArkJSValue>(arg)->GetValue(pandaRuntime));
138 }
139 Local<JSValueRef> thisValue = std::static_pointer_cast<ArkJSValue>(thisObj)->GetValue(pandaRuntime);
140 Local<FunctionRef> function(GetValue(pandaRuntime));
141 Local<JSValueRef> result = function->Call(pandaRuntime->GetEcmaVm(), thisValue, arguments.data(), argc);
142 Local<ObjectRef> exception = JSNApi::GetUncaughtException(pandaRuntime->GetEcmaVm());
143 pandaRuntime->HandleUncaughtException();
144 if (!exception.IsEmpty() && !exception->IsHole()) {
145 result = JSValueRef::Undefined(pandaRuntime->GetEcmaVm());
146 }
147 return std::make_shared<ArkJSValue>(pandaRuntime, result);
148 }
149
GetPropertyNames(shared_ptr<JsRuntime> runtime,shared_ptr<JsValue> & propName,int32_t & len)150 bool ArkJSValue::GetPropertyNames(shared_ptr<JsRuntime> runtime, shared_ptr<JsValue> &propName, int32_t &len)
151 {
152 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
153 LocalScope scope(pandaRuntime->GetEcmaVm());
154 if (CheckException(pandaRuntime)) {
155 return false;
156 }
157 Local<ObjectRef> obj = value_->ToObject(pandaRuntime->GetEcmaVm());
158 if (CheckException(pandaRuntime, obj)) {
159 return false;
160 }
161 Local<ArrayRef> names = obj->GetOwnPropertyNames(pandaRuntime->GetEcmaVm());
162 len = names->Length(pandaRuntime->GetEcmaVm());
163 if (!propName) {
164 propName = std::make_shared<ArkJSValue>(pandaRuntime, names);
165 } else {
166 std::static_pointer_cast<ArkJSValue>(propName)->SetValue(pandaRuntime, names);
167 }
168 return true;
169 }
170
GetEnumerablePropertyNames(shared_ptr<JsRuntime> runtime,shared_ptr<JsValue> & propName,int32_t & len)171 bool ArkJSValue::GetEnumerablePropertyNames(shared_ptr<JsRuntime> runtime, shared_ptr<JsValue> &propName, int32_t &len)
172 {
173 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
174 LocalScope scope(pandaRuntime->GetEcmaVm());
175 if (CheckException(pandaRuntime)) {
176 return false;
177 }
178 Local<ObjectRef> obj = value_->ToObject(pandaRuntime->GetEcmaVm());
179 if (CheckException(pandaRuntime, obj)) {
180 return false;
181 }
182 Local<ArrayRef> names = obj->GetOwnEnumerablePropertyNames(pandaRuntime->GetEcmaVm());
183 len = names->Length(pandaRuntime->GetEcmaVm());
184 if (!propName) {
185 propName = std::make_shared<ArkJSValue>(pandaRuntime, names);
186 } else {
187 std::static_pointer_cast<ArkJSValue>(propName)->SetValue(pandaRuntime, names);
188 }
189 return true;
190 }
191
GetProperty(shared_ptr<JsRuntime> runtime,int32_t idx)192 shared_ptr<JsValue> ArkJSValue::GetProperty(shared_ptr<JsRuntime> runtime, int32_t idx)
193 {
194 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
195 LocalScope scope(pandaRuntime->GetEcmaVm());
196 if (CheckException(pandaRuntime)) {
197 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(pandaRuntime->GetEcmaVm()));
198 }
199 Local<ObjectRef> obj = value_->ToObject(pandaRuntime->GetEcmaVm());
200 if (CheckException(pandaRuntime, obj)) {
201 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(pandaRuntime->GetEcmaVm()));
202 }
203 Local<JSValueRef> property = obj->Get(pandaRuntime->GetEcmaVm(), idx);
204 if (CheckException(pandaRuntime, property)) {
205 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(pandaRuntime->GetEcmaVm()));
206 }
207 return std::make_shared<ArkJSValue>(pandaRuntime, property);
208 }
209
GetProperty(shared_ptr<JsRuntime> runtime,const std::string & name)210 shared_ptr<JsValue> ArkJSValue::GetProperty(shared_ptr<JsRuntime> runtime, const std::string &name)
211 {
212 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
213 LocalScope scope(pandaRuntime->GetEcmaVm());
214 shared_ptr<JsValue> key = pandaRuntime->NewString(name);
215 return GetProperty(runtime, key);
216 }
217
GetProperty(shared_ptr<JsRuntime> runtime,const shared_ptr<JsValue> & name)218 shared_ptr<JsValue> ArkJSValue::GetProperty(shared_ptr<JsRuntime> runtime, const shared_ptr<JsValue> &name)
219 {
220 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
221 LocalScope scope(pandaRuntime->GetEcmaVm());
222 if (CheckException(pandaRuntime)) {
223 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(pandaRuntime->GetEcmaVm()));
224 }
225 Local<ObjectRef> obj = value_->ToObject(pandaRuntime->GetEcmaVm());
226 if (CheckException(pandaRuntime, obj)) {
227 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(pandaRuntime->GetEcmaVm()));
228 }
229 Local<JSValueRef> key = std::static_pointer_cast<ArkJSValue>(name)->GetValue(pandaRuntime);
230 Local<JSValueRef> property = obj->Get(pandaRuntime->GetEcmaVm(), key);
231 if (CheckException(pandaRuntime, property)) {
232 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(pandaRuntime->GetEcmaVm()));
233 }
234 return std::make_shared<ArkJSValue>(pandaRuntime, property);
235 }
236
SetProperty(shared_ptr<JsRuntime> runtime,const std::string & name,const shared_ptr<JsValue> & value)237 bool ArkJSValue::SetProperty(shared_ptr<JsRuntime> runtime, const std::string &name, const shared_ptr<JsValue> &value)
238 {
239 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
240 LocalScope scope(pandaRuntime->GetEcmaVm());
241 shared_ptr<JsValue> key = pandaRuntime->NewString(name);
242 return SetProperty(runtime, key, value);
243 }
244
SetProperty(shared_ptr<JsRuntime> runtime,const shared_ptr<JsValue> & name,const shared_ptr<JsValue> & value)245 bool ArkJSValue::SetProperty(shared_ptr<JsRuntime> runtime, const shared_ptr<JsValue> &name,
246 const shared_ptr<JsValue> &value)
247 {
248 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
249 LocalScope scope(pandaRuntime->GetEcmaVm());
250 if (CheckException(pandaRuntime)) {
251 return false;
252 }
253 Local<ObjectRef> obj = value_->ToObject(pandaRuntime->GetEcmaVm());
254 if (CheckException(pandaRuntime, obj)) {
255 return false;
256 }
257 Local<JSValueRef> key = std::static_pointer_cast<ArkJSValue>(name)->GetValue(pandaRuntime);
258 Local<JSValueRef> value_ref = std::static_pointer_cast<ArkJSValue>(value)->GetValue(pandaRuntime);
259 return obj->Set(pandaRuntime->GetEcmaVm(), key, value_ref);
260 }
261
SetAccessorProperty(shared_ptr<JsRuntime> runtime,const std::string & name,const shared_ptr<JsValue> & getter,const shared_ptr<JsValue> & setter)262 bool ArkJSValue::SetAccessorProperty(shared_ptr<JsRuntime> runtime, const std::string &name,
263 const shared_ptr<JsValue> &getter, const shared_ptr<JsValue> &setter)
264 {
265 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
266 LocalScope scope(pandaRuntime->GetEcmaVm());
267 shared_ptr<JsValue> key = pandaRuntime->NewString(name);
268 return SetAccessorProperty(runtime, key, getter, setter);
269 }
270
SetAccessorProperty(shared_ptr<JsRuntime> runtime,const shared_ptr<JsValue> & name,const shared_ptr<JsValue> & getter,const shared_ptr<JsValue> & setter)271 bool ArkJSValue::SetAccessorProperty(shared_ptr<JsRuntime> runtime, const shared_ptr<JsValue> &name,
272 const shared_ptr<JsValue> &getter, const shared_ptr<JsValue> &setter)
273 {
274 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
275 LocalScope scope(pandaRuntime->GetEcmaVm());
276 if (CheckException(pandaRuntime)) {
277 return false;
278 }
279 Local<ObjectRef> obj = value_->ToObject(pandaRuntime->GetEcmaVm());
280 if (CheckException(pandaRuntime, obj)) {
281 return false;
282 }
283 Local<JSValueRef> key = std::static_pointer_cast<ArkJSValue>(name)->GetValue(pandaRuntime);
284 Local<JSValueRef> getterValue = std::static_pointer_cast<ArkJSValue>(getter)->GetValue(pandaRuntime);
285 Local<JSValueRef> setterValue = std::static_pointer_cast<ArkJSValue>(setter)->GetValue(pandaRuntime);
286 return obj->SetAccessorProperty(pandaRuntime->GetEcmaVm(), key, getterValue, setterValue);
287 }
288
GetArrayLength(shared_ptr<JsRuntime> runtime)289 int32_t ArkJSValue::GetArrayLength(shared_ptr<JsRuntime> runtime)
290 {
291 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
292 LocalScope scope(pandaRuntime->GetEcmaVm());
293 if (CheckException(pandaRuntime)) {
294 return -1;
295 }
296 Local<ArrayRef> array(GetValue(pandaRuntime));
297 return array->Length(pandaRuntime->GetEcmaVm());
298 }
299
GetElement(shared_ptr<JsRuntime> runtime,int32_t idx)300 shared_ptr<JsValue> ArkJSValue::GetElement(shared_ptr<JsRuntime> runtime, int32_t idx)
301 {
302 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
303 LocalScope scope(pandaRuntime->GetEcmaVm());
304 if (CheckException(pandaRuntime)) {
305 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(pandaRuntime->GetEcmaVm()));
306 }
307 Local<ArrayRef> obj(GetValue(pandaRuntime));
308 if (CheckException(pandaRuntime, obj)) {
309 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(pandaRuntime->GetEcmaVm()));
310 }
311 Local<JSValueRef> property = obj->Get(pandaRuntime->GetEcmaVm(), idx);
312 if (CheckException(pandaRuntime, property)) {
313 return std::make_shared<ArkJSValue>(pandaRuntime, JSValueRef::Undefined(pandaRuntime->GetEcmaVm()));
314 }
315 return std::make_shared<ArkJSValue>(pandaRuntime, property);
316 }
317
GetJsonString(const shared_ptr<JsRuntime> & runtime)318 std::string ArkJSValue::GetJsonString(const shared_ptr<JsRuntime>& runtime)
319 {
320 shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
321 LocalScope scope(pandaRuntime->GetEcmaVm());
322 auto stringify = panda::JSON::Stringify(pandaRuntime->GetEcmaVm(), GetValue(pandaRuntime));
323 if (CheckException(pandaRuntime, stringify)) {
324 return "";
325 }
326 auto valueStr = panda::Local<panda::StringRef>(stringify);
327 if (CheckException(pandaRuntime, valueStr)) {
328 return "";
329 }
330 return valueStr->ToString();
331 }
332
CheckException(const shared_ptr<ArkJSRuntime> & runtime) const333 bool ArkJSValue::CheckException(const shared_ptr<ArkJSRuntime> &runtime) const
334 {
335 return value_.IsEmpty() || runtime->HasPendingException();
336 }
337
CheckException(const shared_ptr<ArkJSRuntime> & runtime,const Local<JSValueRef> & value) const338 bool ArkJSValue::CheckException(const shared_ptr<ArkJSRuntime> &runtime, const Local<JSValueRef> &value) const
339 {
340 return value.IsEmpty() || runtime->HasPendingException();
341 }
342 } // namespace OHOS::Ace::Framework