• 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 "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() {}