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/declarative_frontend/engine/quickjs/qjs_types.h"
17
18 #include "frameworks/bridge/declarative_frontend/engine/quickjs/qjs_bindings.h"
19 #include "frameworks/bridge/declarative_frontend/engine/quickjs/qjs_declarative_engine_instance.h"
20 #include "frameworks/bridge/declarative_frontend/engine/quickjs/qjs_ref.h"
21 #include "frameworks/bridge/js_frontend/engine/quickjs/qjs_utils.h"
22
23 namespace OHOS::Ace::Framework {
24
PrintRefCount(JSValue val)25 void PrintRefCount(JSValue val)
26 {
27 if (JS_VALUE_HAS_REF_COUNT(val)) {
28 JSRefCountHeader* p = static_cast<JSRefCountHeader*>(JS_VALUE_GET_PTR(val));
29 LOGE("Ref count of value: %d", p->ref_count);
30 } else {
31 LOGE("no ref count");
32 }
33 }
34
QJSValue()35 QJSValue::QJSValue()
36 {
37 value_ = JS_UNDEFINED;
38 }
39
QJSValue(JSValue rhs)40 QJSValue::QJSValue(JSValue rhs)
41 {
42 value_ = rhs;
43 }
44
~QJSValue()45 QJSValue::~QJSValue() {}
46
QJSValue(const QJSValue & rhs)47 QJSValue::QJSValue(const QJSValue& rhs)
48 {
49 value_ = rhs.value_;
50 }
51
QJSValue(QJSValue && rhs)52 QJSValue::QJSValue(QJSValue&& rhs)
53 {
54 value_ = std::move(rhs.value_);
55 rhs.value_ = JS_UNDEFINED;
56 }
57
operator =(const QJSValue & rhs)58 QJSValue& QJSValue::operator=(const QJSValue& rhs)
59 {
60 value_ = rhs.value_;
61 return *this;
62 }
63
operator =(QJSValue && rhs)64 QJSValue& QJSValue::operator=(QJSValue&& rhs)
65 {
66 value_ = std::move(rhs.value_);
67 rhs.value_ = JS_UNDEFINED;
68 return *this;
69 }
70
Dup() const71 QJSValue QJSValue::Dup() const
72 {
73 return QJSValue(JS_DupValue(nullptr, value_));
74 }
75
Free()76 void QJSValue::Free()
77 {
78 JSRuntime* rt = QJSDeclarativeEngineInstance::GetQJSRuntime();
79 if (rt == nullptr) {
80 LOGE("rt is nullptr");
81 return;
82 }
83 JS_FreeValueRT(rt, value_);
84 value_ = JS_UNDEFINED;
85 }
86
Reset()87 void QJSValue::Reset()
88 {
89 value_ = JS_UNDEFINED;
90 }
91
IsEmpty() const92 bool QJSValue::IsEmpty() const
93 {
94 return JS_IsUndefined(value_) || JS_IsNull(value_);
95 }
96
IsFunction() const97 bool QJSValue::IsFunction() const
98 {
99 return JS_IsFunction(QJSContext::Current(), value_);
100 }
101
IsNumber() const102 bool QJSValue::IsNumber() const
103 {
104 return JS_IsNumber(value_);
105 }
106
IsString() const107 bool QJSValue::IsString() const
108 {
109 return JS_IsString(value_);
110 }
111
IsBoolean() const112 bool QJSValue::IsBoolean() const
113 {
114 return JS_IsBool(value_);
115 }
116
IsObject() const117 bool QJSValue::IsObject() const
118 {
119 return JS_IsObject(value_);
120 }
121
IsArray() const122 bool QJSValue::IsArray() const
123 {
124 return JS_IsArray(QJSContext::Current(), value_);
125 }
126
IsUndefined() const127 bool QJSValue::IsUndefined() const
128 {
129 return JS_IsUndefined(value_);
130 }
131
IsNull() const132 bool QJSValue::IsNull() const
133 {
134 return JS_IsNull(value_);
135 }
136
ToString() const137 std::string QJSValue::ToString() const
138 {
139 if (!IsObject()) {
140 return ScopedString(value_);
141 }
142 return ScopedString::Stringify(value_);
143 }
144
ToBoolean() const145 bool QJSValue::ToBoolean() const
146 {
147 bool value = JS_ToBool(QJSContext::Current(), value_) == 1 ? true : false;
148 return value;
149 }
150
GetJsContext() const151 JSContext* QJSValue::GetJsContext() const
152 {
153 return QJSContext::Current();
154 }
155
QJSObject()156 QJSObject::QJSObject() : QJSValue() {}
QJSObject(JSValue val)157 QJSObject::QJSObject(JSValue val) : QJSValue(val) {}
158
New()159 QJSObject QJSObject::New()
160 {
161 return QJSObject(JS_NewObject(QJSContext::Current()));
162 }
163
GetPropertyNames() const164 QJSRef<QJSArray> QJSObject::GetPropertyNames() const
165 {
166 JSPropertyEnum* pTab = nullptr;
167 uint32_t len = 0;
168 if (!CheckAndGetJsProperty(QJSContext::Current(), GetHandle(), &pTab, &len)) {
169 return QJSRef<QJSArray>::Make(QJSArray::New());
170 }
171 JS_GetOwnPropertyNames(QJSContext::Current(), &pTab, &len, GetHandle(), JS_GPN_STRING_MASK);
172 JSValue value = JS_AtomToValue(QJSContext::Current(), pTab->atom);
173 return QJSRef<QJSArray>::Make(value);
174 }
175
GetProperty(const char * prop) const176 QJSRef<QJSValue> QJSObject::GetProperty(const char* prop) const
177 {
178 return QJSRef<QJSValue>::Make(JS_GetPropertyStr(QJSContext::Current(), GetHandle(), prop));
179 }
180
ToJsonObject(const char * value) const181 QJSRef<QJSValue> QJSObject::ToJsonObject(const char* value) const
182 {
183 JSContext* ctx = QJSContext::Current();
184 JSValue jsonObj = JS_ParseJSON(ctx, value, strlen(value), "");
185 return QJSRef<QJSValue>::Make(jsonObj);
186 }
187
SetPropertyJsonObject(const char * prop,const char * value) const188 void QJSObject::SetPropertyJsonObject(const char* prop, const char* value) const
189 {
190 JSContext* ctx = QJSContext::Current();
191 JSValue jsonObj = JS_ParseJSON(ctx, value, strlen(value), "");
192 JS_SetPropertyStr(ctx, GetHandle(), prop, jsonObj);
193 }
194
SetPropertyObject(const char * prop,QJSRef<QJSValue> value) const195 void QJSObject::SetPropertyObject(const char* prop, QJSRef<QJSValue> value) const
196 {
197 JS_SetPropertyStr(QJSContext::Current(), GetHandle(), prop, value->GetHandle());
198 }
199
New()200 JSValue QJSObjTemplate::New()
201 {
202 return JS_NewObject(QJSContext::Current());
203 }
204
QJSObjTemplate(JSValue val)205 QJSObjTemplate::QJSObjTemplate(JSValue val) : QJSValue(val) {}
206
SetInternalFieldCount(int32_t count) const207 void QJSObjTemplate::SetInternalFieldCount(int32_t count) const {}
208
NewInstance() const209 QJSRef<QJSObject> QJSObjTemplate::NewInstance() const
210 {
211 return QJSRef<QJSObject>::Make(JS_NewObject(QJSContext::Current()));
212 }
213
QJSFunction()214 QJSFunction::QJSFunction() {}
QJSFunction(JSValue val)215 QJSFunction::QJSFunction(JSValue val) : QJSValue(val), ctx_(QJSContext::Current()) {}
216
Call(QJSRef<QJSValue> thisVal,int argc,QJSRef<QJSValue> argv[]) const217 QJSRef<QJSValue> QJSFunction::Call(QJSRef<QJSValue> thisVal, int argc, QJSRef<QJSValue> argv[]) const
218 {
219 std::vector<JSValue> args;
220 for (int i = 0; i < argc; ++i) {
221 args.push_back(argv[i].Get().GetHandle());
222 }
223 QJSContext::Scope scp(ctx_);
224 JSValue res = JS_Call(QJSContext::Current(), GetHandle(), thisVal.Get().GetHandle(), argc, args.data());
225 if (JS_IsException(res)) {
226 QJSUtils::JsStdDumpErrorAce(QJSContext::Current());
227 JS_FreeValue(QJSContext::Current(), res);
228 return QJSRef<QJSValue>::Make(JS_NULL);
229 }
230 js_std_loop(ctx_);
231 return QJSRef<QJSValue>::Make(res);
232 }
233
New(FunctionCallback func)234 JSValue QJSFunction::New(FunctionCallback func)
235 {
236 JSValue funcObj = JS_NewCFunction2(QJSContext::Current(), func, "callback", 0, JS_CFUNC_constructor_or_func, 0);
237 return funcObj;
238 }
239
QJSArray()240 QJSArray::QJSArray() {}
QJSArray(JSValue val)241 QJSArray::QJSArray(JSValue val) : QJSValue(val) {}
242
New()243 QJSArray QJSArray::New()
244 {
245 return QJSArray(JS_NewArray(QJSContext::Current()));
246 }
247
GetValueAt(size_t index) const248 QJSRef<QJSValue> QJSArray::GetValueAt(size_t index) const
249 {
250 JSContext* ctx = QJSContext::Current();
251 JSValue val = JS_GetPropertyUint32(ctx, GetHandle(), index);
252 return QJSRef<QJSValue>::Make(val);
253 }
254
SetValueAt(size_t index,QJSRef<QJSValue> value) const255 void QJSArray::SetValueAt(size_t index, QJSRef<QJSValue> value) const
256 {
257 JSContext* ctx = QJSContext::Current();
258 JS_SetPropertyUint32(ctx, GetHandle(), index, value.Get().GetHandle());
259 }
260
Length() const261 size_t QJSArray::Length() const
262 {
263 return QJSUtils::JsGetArrayLength(QJSContext::Current(), GetHandle());
264 }
265
QJSString(const char * str)266 QJSString::QJSString(const char* str) : QJSValue(JS_NewStringLen(QJSContext::Current(), str, strlen(str))) {}
QJSString(JSValue str)267 QJSString::QJSString(JSValue str) : QJSValue(str) {}
268
New(const char * str)269 QJSString QJSString::New(const char* str)
270 {
271 return QJSString(str);
272 }
QJSCallbackInfo(JSContext * ctx,JSValueConst thisObj,int argc,JSValueConst * argv)273 QJSCallbackInfo::QJSCallbackInfo(JSContext* ctx, JSValueConst thisObj, int argc, JSValueConst* argv)
274 : ctx_(ctx), thisObj_(thisObj), argc_(argc), argv_(argv)
275 {}
276
operator [](size_t index) const277 QJSRef<QJSValue> QJSCallbackInfo::operator[](size_t index) const
278 {
279 QJSRef<QJSValue> val = QJSRef<QJSValue>::Make(argv_[index]);
280 return val;
281 }
282
This() const283 QJSRef<QJSObject> QJSCallbackInfo::This() const
284 {
285 return QJSRef<QJSObject>::Make(thisObj_);
286 }
287
Length() const288 int QJSCallbackInfo::Length() const
289 {
290 return argc_;
291 }
292
ReturnSelf() const293 void QJSCallbackInfo::ReturnSelf() const
294 {
295 retVal_ = JS_DupValue(nullptr, thisObj_);
296 }
297
QJSGCMarkCallbackInfo(JSRuntime * rt,JS_MarkFunc * markFunc)298 QJSGCMarkCallbackInfo::QJSGCMarkCallbackInfo(JSRuntime* rt, JS_MarkFunc* markFunc) : rt_(rt), markFunc_(markFunc) {}
299
Mark(JSValue val) const300 void QJSGCMarkCallbackInfo::Mark(JSValue val) const
301 {
302 JS_MarkValue(rt_, val, markFunc_);
303 }
304
305 } // namespace OHOS::Ace::Framework
306