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 "ark_native_object.h"
17
18 #include "ark_headers.h"
19 #include "ark_native_array.h"
20 #include "ark_native_external.h"
21 #include "ark_native_function.h"
22 #include "ark_native_reference.h"
23 #include "ark_native_string.h"
24
25 #include "native_engine/native_property.h"
26
27 #include "utils/log.h"
28
29 using panda::ObjectRef;
30 using panda::StringRef;
31 using panda::NativePointerRef;
32 using panda::ArrayRef;
33 using panda::PropertyAttribute;
34
35 DetachCallback ArkNativeObject::detach_ = nullptr;
36 AttachCallback ArkNativeObject::attach_ = nullptr;
37
ArkNativeObject(ArkNativeEngine * engine)38 ArkNativeObject::ArkNativeObject(ArkNativeEngine* engine)
39 : ArkNativeObject(engine, JSValueRef::Undefined(engine->GetEcmaVm()))
40 {
41 auto vm = engine->GetEcmaVm();
42 LocalScope scope(vm);
43 Local<ObjectRef> object = ObjectRef::New(vm);
44 value_ = Global<ObjectRef>(vm, object);
45 }
46
ArkNativeObject(ArkNativeEngine * engine,Local<JSValueRef> value)47 ArkNativeObject::ArkNativeObject(ArkNativeEngine* engine, Local<JSValueRef> value) : ArkNativeValue(engine, value) {}
48
ArkNativeObject(ArkNativeEngine * engine,void * detach,void * attach)49 ArkNativeObject::ArkNativeObject(ArkNativeEngine* engine, void* detach, void* attach)
50 : ArkNativeObject(engine, JSValueRef::Undefined(engine->GetEcmaVm()))
51 {
52 auto vm = engine->GetEcmaVm();
53 LocalScope scope(vm);
54 Local<ObjectRef> object = ObjectRef::New(vm, detach, attach);
55 value_ = Global<ObjectRef>(vm, object);
56 }
57
DetachFuncCallback(void * engine,void * object,void * hint,void * detachData)58 void* ArkNativeObject::DetachFuncCallback(void* engine, void* object, void* hint, void* detachData)
59 {
60 if (detachData == nullptr || (engine == nullptr || object ==nullptr)) {
61 HILOG_ERROR("DetachFuncCallback params has nullptr");
62 return nullptr;
63 }
64 DetachCallback detach = reinterpret_cast<DetachCallback>(detachData);
65 void* detachVal = detach(reinterpret_cast<NativeEngine*>(engine), object, hint);
66 return detachVal;
67 }
68
AttachFuncCallback(void * engine,void * buffer,void * hint,void * attachData)69 Local<JSValueRef> ArkNativeObject::AttachFuncCallback(void* engine, void* buffer, void* hint, void* attachData)
70 {
71 panda::EscapeLocalScope scope(reinterpret_cast<ArkNativeEngine*>(engine)->GetEcmaVm());
72 if (attachData == nullptr || (engine == nullptr || buffer ==nullptr)) {
73 HILOG_ERROR("AttachFuncCallback params has nullptr");
74 }
75 AttachCallback attach = reinterpret_cast<AttachCallback>(attachData);
76 NativeValue* attachVal = attach(reinterpret_cast<NativeEngine*>(engine), buffer, hint);
77 Global<JSValueRef> result = *attachVal;
78 return scope.Escape(result.ToLocal(reinterpret_cast<ArkNativeEngine*>(engine)->GetEcmaVm()));
79 }
80
ArkNativeObject(ArkNativeEngine * engine,DetachCallback detach,AttachCallback attach)81 ArkNativeObject::ArkNativeObject(ArkNativeEngine* engine, DetachCallback detach, AttachCallback attach)
82 : ArkNativeObject(engine, JSValueRef::Undefined(engine->GetEcmaVm()))
83 {
84 {
85 std::lock_guard<std::mutex> lock(funcMutex_);
86 detach_ = detach;
87 attach_ = attach;
88 }
89 auto vm = engine->GetEcmaVm();
90 LocalScope scope(vm);
91 Local<ObjectRef> object = ObjectRef::New(
92 vm, reinterpret_cast<void*>(DetachFuncCallback), reinterpret_cast<void*>(AttachFuncCallback));
93 value_ = Global<ObjectRef>(vm, object);
94 }
95
~ArkNativeObject()96 ArkNativeObject::~ArkNativeObject() {}
97
ConvertToNativeBindingObject(void * engine,DetachCallback detachData,AttachCallback attachData,void * object,void * hint)98 bool ArkNativeObject::ConvertToNativeBindingObject(
99 void* engine, DetachCallback detachData, AttachCallback attachData, void *object, void *hint)
100 {
101 if (detachData == nullptr || (attachData == nullptr || object == nullptr)) {
102 HILOG_ERROR("ConvertToNativeBindingObject params has nullptr");
103 return false;
104 }
105 auto vm = reinterpret_cast<ArkNativeEngine*>(engine)->GetEcmaVm();
106 Global<ObjectRef> obj = value_;
107 bool res = obj->Set(vm, reinterpret_cast<void*>(DetachFuncCallback), reinterpret_cast<void*>(AttachFuncCallback));
108 this->SetNativeBindingPointer(
109 engine, object, hint, reinterpret_cast<void *>(detachData), reinterpret_cast<void *>(attachData));
110 return res;
111 }
112
GetInterface(int interfaceId)113 void* ArkNativeObject::GetInterface(int interfaceId)
114 {
115 return (NativeObject::INTERFACE_ID == interfaceId) ? (NativeObject*)this : nullptr;
116 }
117
SetNativePointer(void * pointer,NativeFinalize cb,void * hint,NativeReference ** reference,size_t nativeBindingSize)118 void ArkNativeObject::SetNativePointer(void* pointer, NativeFinalize cb, void* hint,
119 NativeReference** reference, size_t nativeBindingSize)
120 {
121 auto vm = engine_->GetEcmaVm();
122 LocalScope scope(vm);
123 Global<ObjectRef> value = value_;
124
125 Local<StringRef> key = StringRef::GetNapiWrapperString(vm);
126 if (pointer == nullptr && value->Has(vm, key)) {
127 Local<ObjectRef> wrapper = value->Get(vm, key);
128 auto ref = reinterpret_cast<ArkNativeReference*>(wrapper->GetNativePointerField(0));
129 // Try to remove native pointer from ArrayDataList
130 ASSERT(nativeBindingSize == 0);
131 wrapper->SetNativePointerField(0, nullptr, nullptr, nullptr, nativeBindingSize);
132 value->Delete(vm, key);
133 delete ref;
134 } else {
135 Local<ObjectRef> object = ObjectRef::New(vm);
136 ArkNativeReference* ref = nullptr;
137 if (reference != nullptr) {
138 ref = new ArkNativeReference(engine_, this, 1, false, cb, pointer, hint);
139 *reference = ref;
140 } else {
141 ref = new ArkNativeReference(engine_, this, 0, true, cb, pointer, hint);
142 }
143 object->SetNativePointerFieldCount(1);
144 object->SetNativePointerField(0, ref, nullptr, nullptr, nativeBindingSize);
145 PropertyAttribute attr(object, true, false, true);
146 value->DefineProperty(vm, key, attr);
147 }
148 }
149
GetNativePointer()150 void* ArkNativeObject::GetNativePointer()
151 {
152 auto vm = engine_->GetEcmaVm();
153 LocalScope scope(vm);
154 Global<ObjectRef> value = value_;
155 Local<StringRef> key = StringRef::GetNapiWrapperString(vm);
156 Local<JSValueRef> val = value->Get(vm, key);
157 void* result = nullptr;
158 if (val->IsObject()) {
159 Local<ObjectRef> ext(val);
160 auto ref = reinterpret_cast<ArkNativeReference*>(ext->GetNativePointerField(0));
161 result = ref != nullptr ? ref->GetData() : nullptr;
162 }
163 return result;
164 }
165
SetNativeBindingPointer(void * enginePointer,void * objPointer,void * hint,void * detachData,void * attachData)166 void ArkNativeObject::SetNativeBindingPointer(
167 void *enginePointer, void *objPointer, void *hint, void *detachData, void *attachData)
168 {
169 auto vm = engine_->GetEcmaVm();
170 LocalScope scope(vm);
171 Global<ObjectRef> value = value_;
172
173 Local<ObjectRef> object = Local<ObjectRef>(value.ToLocal(vm));
174 object->SetNativePointerFieldCount(5); // 5 : NativeEngine, NativeObject, hint, detachData, attachData
175 object->SetNativePointerField(0, enginePointer, nullptr, nullptr);
176 object->SetNativePointerField(1, objPointer, nullptr, nullptr);
177 object->SetNativePointerField(2, hint, nullptr, nullptr); // 2 : hint
178 object->SetNativePointerField(3, detachData, nullptr, nullptr); // 3 : detachData
179 object->SetNativePointerField(4, attachData, nullptr, nullptr); // 4 : attachData
180 }
181
GetNativeBindingPointer(uint32_t index)182 void* ArkNativeObject::GetNativeBindingPointer(uint32_t index)
183 {
184 auto vm = engine_->GetEcmaVm();
185 LocalScope scope(vm);
186 Global<ObjectRef> value = value_;
187 uint32_t paramCount = static_cast<uint32_t>(value->GetNativePointerFieldCount());
188 if (index >= paramCount) {
189 HILOG_ERROR("index more than nativebindingpointer count");
190 return nullptr;
191 }
192 return value->GetNativePointerField(index);
193 }
194
GetPropertyNames()195 NativeValue* ArkNativeObject::GetPropertyNames()
196 {
197 auto vm = engine_->GetEcmaVm();
198 LocalScope scope(vm);
199 Global<ObjectRef> val = value_;
200 Local<ArrayRef> arrayVal = val->GetOwnPropertyNames(vm);
201 NativeChunk& chunk = engine_->GetNativeChunk();
202 return chunk.New<ArkNativeArray>(engine_, arrayVal);
203 }
204
GetEnumerablePropertyNames()205 NativeValue* ArkNativeObject::GetEnumerablePropertyNames()
206 {
207 auto vm = engine_->GetEcmaVm();
208 LocalScope scope(vm);
209 Global<ObjectRef> val = value_;
210 Local<ArrayRef> arrayVal = val->GetOwnEnumerablePropertyNames(vm);
211 NativeChunk& chunk = engine_->GetNativeChunk();
212 return chunk.New<ArkNativeArray>(engine_, arrayVal);
213 }
214
GetPrototype()215 NativeValue* ArkNativeObject::GetPrototype()
216 {
217 auto vm = engine_->GetEcmaVm();
218 LocalScope scope(vm);
219 Global<ObjectRef> obj = value_;
220 Local<JSValueRef> val = obj->GetPrototype(vm);
221
222 return ArkNativeEngine::ArkValueToNativeValue(engine_, val);
223 }
224
DefineProperty(NativePropertyDescriptor propertyDescriptor)225 bool ArkNativeObject::DefineProperty(NativePropertyDescriptor propertyDescriptor)
226 {
227 auto vm = engine_->GetEcmaVm();
228 LocalScope scope(vm);
229 Global<ObjectRef> obj = value_;
230 bool result = false;
231 Local<StringRef> propertyName = StringRef::NewFromUtf8(vm, propertyDescriptor.utf8name);
232
233 bool writable = (propertyDescriptor.attributes & NATIVE_WRITABLE) != 0;
234 bool enumable = (propertyDescriptor.attributes & NATIVE_ENUMERABLE) != 0;
235 bool configable = (propertyDescriptor.attributes & NATIVE_CONFIGURABLE) != 0;
236
237 NativeScopeManager* scopeManager = engine_->GetScopeManager();
238 if (scopeManager == nullptr) {
239 HILOG_ERROR("scope manager is null");
240 return false;
241 }
242 NativeScope* nativeScope = scopeManager->Open();
243 std::string fullName("");
244 #ifdef ENABLE_HITRACE
245 fullName += GetModuleName();
246 #endif
247 NativeChunk& chunk = engine_->GetNativeChunk();
248 if (propertyDescriptor.getter != nullptr || propertyDescriptor.setter != nullptr) {
249 Local<JSValueRef> localGetter = JSValueRef::Undefined(vm);
250 Local<JSValueRef> localSetter = JSValueRef::Undefined(vm);
251
252 if (propertyDescriptor.getter != nullptr) {
253 fullName += "getter";
254 NativeValue* getter = chunk.New<ArkNativeFunction>(
255 engine_, fullName.c_str(), 0, propertyDescriptor.getter, propertyDescriptor.data);
256 Global<JSValueRef> globalGetter = *getter;
257 localGetter = globalGetter.ToLocal(vm);
258 }
259 if (propertyDescriptor.setter != nullptr) {
260 fullName += "setter";
261 NativeValue* setter = chunk.New<ArkNativeFunction>(
262 engine_, fullName.c_str(), 0, propertyDescriptor.setter, propertyDescriptor.data);
263 Global<JSValueRef> globalSetter = *setter;
264 localSetter = globalSetter.ToLocal(vm);
265 }
266
267 PropertyAttribute attr(JSValueRef::Undefined(engine_->GetEcmaVm()), false, enumable, configable);
268 result = obj->SetAccessorProperty(vm, propertyName, localGetter, localSetter, attr);
269 } else if (propertyDescriptor.method != nullptr) {
270 fullName += propertyDescriptor.utf8name;
271 NativeValue* cb = chunk.New<ArkNativeFunction>(engine_, fullName.c_str(), 0, propertyDescriptor.method,
272 propertyDescriptor.data);
273 Global<JSValueRef> globalCb = *cb;
274 PropertyAttribute attr(globalCb.ToLocal(vm), writable, enumable, configable);
275 result = obj->DefineProperty(vm, propertyName, attr);
276 } else {
277 Global<JSValueRef> value = *(propertyDescriptor.value);
278
279 PropertyAttribute attr(value.ToLocal(vm), writable, enumable, configable);
280 result = obj->DefineProperty(vm, propertyName, attr);
281 }
282 Local<ObjectRef> excep = panda::JSNApi::GetUncaughtException(vm);
283 if (!excep.IsNull()) {
284 HILOG_ERROR("ArkNativeObject::DefineProperty occur Exception");
285 panda::JSNApi::GetAndClearUncaughtException(vm);
286 }
287 scopeManager->Close(nativeScope);
288 return result;
289 }
290
SetProperty(NativeValue * key,NativeValue * value)291 bool ArkNativeObject::SetProperty(NativeValue* key, NativeValue* value)
292 {
293 auto vm = engine_->GetEcmaVm();
294 LocalScope scope(vm);
295 Global<ObjectRef> obj = value_;
296 Global<JSValueRef> k = *key;
297 Global<JSValueRef> val = *value;
298
299 return obj->Set(vm, k.ToLocal(vm), val.ToLocal(vm));
300 }
301
GetProperty(NativeValue * key)302 NativeValue* ArkNativeObject::GetProperty(NativeValue* key)
303 {
304 auto vm = engine_->GetEcmaVm();
305 LocalScope scope(vm);
306 Global<JSValueRef> k = *key;
307 Global<ObjectRef> obj = value_;
308
309 Local<JSValueRef> val = obj->Get(vm, k.ToLocal(vm));
310 return ArkNativeEngine::ArkValueToNativeValue(engine_, val);
311 }
312
HasProperty(NativeValue * key)313 bool ArkNativeObject::HasProperty(NativeValue* key)
314 {
315 auto vm = engine_->GetEcmaVm();
316 LocalScope scope(vm);
317 Global<ObjectRef> obj = value_;
318 Global<JSValueRef> k = *key;
319
320 return obj->Has(vm, k.ToLocal(vm));
321 }
322
DeleteProperty(NativeValue * key)323 bool ArkNativeObject::DeleteProperty(NativeValue* key)
324 {
325 auto vm = engine_->GetEcmaVm();
326 LocalScope scope(vm);
327 Global<JSValueRef> k = *key;
328 Global<ObjectRef> obj = value_;
329
330 return obj->Delete(vm, k.ToLocal(vm));
331 }
332
SetProperty(const char * name,NativeValue * value)333 bool ArkNativeObject::SetProperty(const char* name, NativeValue* value)
334 {
335 auto vm = engine_->GetEcmaVm();
336 LocalScope scope(vm);
337
338 Global<ObjectRef> obj = value_;
339 Local<StringRef> key = StringRef::NewFromUtf8(vm, name);
340 Global<JSValueRef> val = *value;
341
342 return obj->Set(vm, key, val.ToLocal(vm));
343 }
344
GetProperty(const char * name)345 NativeValue* ArkNativeObject::GetProperty(const char* name)
346 {
347 auto vm = engine_->GetEcmaVm();
348 LocalScope scope(vm);
349
350 Local<StringRef> key = StringRef::NewFromUtf8(vm, name);
351 Global<ObjectRef> obj = value_;
352 Local<JSValueRef> val = obj->Get(vm, key);
353 return ArkNativeEngine::ArkValueToNativeValue(engine_, val);
354 }
355
HasProperty(const char * name)356 bool ArkNativeObject::HasProperty(const char* name)
357 {
358 auto vm = engine_->GetEcmaVm();
359 LocalScope scope(vm);
360
361 Local<StringRef> key = StringRef::NewFromUtf8(vm, name);
362 Global<ObjectRef> obj = value_;
363
364 return obj->Has(vm, key);
365 }
366
DeleteProperty(const char * name)367 bool ArkNativeObject::DeleteProperty(const char* name)
368 {
369 auto vm = engine_->GetEcmaVm();
370 LocalScope scope(vm);
371
372 Local<StringRef> key = StringRef::NewFromUtf8(vm, name);
373 Global<ObjectRef> obj = value_;
374
375 return obj->Delete(vm, key);
376 }
377
SetPrivateProperty(const char * name,NativeValue * value)378 bool ArkNativeObject::SetPrivateProperty(const char* name, NativeValue* value)
379 {
380 return false;
381 }
382
GetPrivateProperty(const char * name)383 NativeValue* ArkNativeObject::GetPrivateProperty(const char* name)
384 {
385 return nullptr;
386 }
387
HasPrivateProperty(const char * name)388 bool ArkNativeObject::HasPrivateProperty(const char* name)
389 {
390 return false;
391 }
392
DeletePrivateProperty(const char * name)393 bool ArkNativeObject::DeletePrivateProperty(const char* name)
394 {
395 return false;
396 }
397
GetAllPropertyNames(napi_key_collection_mode keyMode,napi_key_filter keyFilter,napi_key_conversion keyConversion)398 NativeValue* ArkNativeObject::GetAllPropertyNames(
399 napi_key_collection_mode keyMode, napi_key_filter keyFilter, napi_key_conversion keyConversion)
400 {
401 return nullptr;
402 }
403
AssociateTypeTag(NapiTypeTag * typeTag)404 bool ArkNativeObject::AssociateTypeTag(NapiTypeTag* typeTag)
405 {
406 return true;
407 }
408
CheckTypeTag(NapiTypeTag * typeTag)409 bool ArkNativeObject::CheckTypeTag(NapiTypeTag* typeTag)
410 {
411 return true;
412 }
413
SetModuleName(std::string moduleName)414 void ArkNativeObject::SetModuleName(std::string moduleName)
415 {
416 NativeChunk& chunk = engine_->GetNativeChunk();
417 NativeValue* moduleValue = chunk.New<ArkNativeString>(engine_, moduleName.c_str(),
418 moduleName.size());
419 this->SetProperty(ArkNativeObject::PANDA_MODULE_NAME, moduleValue);
420 }
421
GetModuleName()422 std::string ArkNativeObject::GetModuleName()
423 {
424 std::string moduleName("");
425 auto nativeModuleName = this->GetProperty(ArkNativeObject::PANDA_MODULE_NAME);
426 if (nativeModuleName != nullptr && nativeModuleName->TypeOf() == NATIVE_STRING) {
427 auto nativeString = reinterpret_cast<NativeString*>(nativeModuleName->GetInterface(NativeString::INTERFACE_ID));
428 char arrayName[PANDA_MODULE_NAME_LEN] = {0};
429 size_t len = 0;
430 nativeString->GetCString(arrayName, PANDA_MODULE_NAME_LEN, &len);
431 moduleName += arrayName;
432 moduleName += ".";
433 }
434 return moduleName;
435 }
436
AddFinalizer(void * pointer,NativeFinalize cb,void * hint)437 void ArkNativeObject::AddFinalizer(void* pointer, NativeFinalize cb, void* hint) {}
438
Freeze()439 void ArkNativeObject::Freeze() {}
440
Seal()441 void ArkNativeObject::Seal() {}