• 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_engine.h"
17 
18 #include "ark_native_deferred.h"
19 #include "ark_native_reference.h"
20 
21 #ifdef ENABLE_CONTAINER_SCOPE
22 #include "core/common/container_scope.h"
23 #endif
24 
25 #include "native_engine/native_property.h"
26 
27 #include "native_value/ark_native_array.h"
28 #include "native_value/ark_native_array_buffer.h"
29 #include "native_value/ark_native_big_int.h"
30 #include "native_value/ark_native_boolean.h"
31 #include "native_value/ark_native_data_view.h"
32 #include "native_value/ark_native_external.h"
33 #include "native_value/ark_native_function.h"
34 #include "native_value/ark_native_number.h"
35 #include "native_value/ark_native_object.h"
36 #include "native_value/ark_native_string.h"
37 #include "native_value/ark_native_typed_array.h"
38 #include "native_value/ark_native_date.h"
39 
40 #include "parameters.h"
41 #include "securec.h"
42 #include "utils/log.h"
43 
44 using panda::BooleanRef;
45 using panda::ObjectRef;
46 using panda::StringRef;
47 using panda::FunctionRef;
48 using panda::PrimitiveRef;
49 using panda::JSValueRef;
50 using panda::ArrayBufferRef;
51 using panda::TypedArrayRef;
52 using panda::PromiseCapabilityRef;
53 using panda::NativePointerRef;
54 using panda::SymbolRef;
55 using panda::IntegerRef;
56 using panda::DateRef;
57 using panda::BigIntRef;
58 static constexpr auto PANDA_MAIN_FUNCTION = "_GLOBAL::func_main_0";
59 
ArkNativeEngine(EcmaVM * vm,void * jsEngine)60 ArkNativeEngine::ArkNativeEngine(EcmaVM* vm, void* jsEngine) : NativeEngine(jsEngine), vm_(vm), topScope_(vm)
61 {
62     Local<StringRef> requireName = StringRef::NewFromUtf8(vm, "requireNapi");
63     Local<StringRef> requireInternalName = StringRef::NewFromUtf8(vm, "requireInternal");
64     void* requireData = static_cast<void*>(this);
65 
66     Local<FunctionRef> requireNapi =
67         FunctionRef::New(
68             vm,
69             [](EcmaVM *ecmaVm, Local<JSValueRef> thisObj,
70                const Local<JSValueRef> argv[],  // NOLINTNEXTLINE(modernize-avoid-c-arrays)
71                int32_t length, void *data) -> Local<JSValueRef> {
72                 panda::EscapeLocalScope scope(ecmaVm);
73                 NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
74                 ArkNativeEngine* engine = static_cast<ArkNativeEngine*>(data);
75                 Local<StringRef> moduleName(argv[0]);
76                 bool isAppModule = false;
77                 int32_t lengthMax = 2;
78                 if (length == lengthMax) {
79                     Local<BooleanRef> ret(argv[1]);
80                     isAppModule = ret->Value();
81                 }
82                 NativeModule* module =
83                     moduleManager->LoadNativeModule(moduleName->ToString().c_str(), nullptr, isAppModule, false, true);
84                 Global<JSValueRef> exports(ecmaVm, JSValueRef::Undefined(ecmaVm));
85                 if (module != nullptr) {
86                     auto it = engine->loadedModules_.find(module);
87                     if (it != engine->loadedModules_.end()) {
88                         return scope.Escape(it->second.ToLocal(ecmaVm));
89                     }
90 
91                     if (module->jsCode != nullptr) {
92                         HILOG_INFO("load js code");
93                         char fileName[NAPI_PATH_MAX] = { 0 };
94                         const char* name = module->name;
95                         if (sprintf_s(fileName, sizeof(fileName), "lib%s.z.so/%s.js", name, name) == -1) {
96                             HILOG_ERROR("sprintf_s file name failed");
97                             return scope.Escape(exports.ToLocal(ecmaVm));
98                         }
99                         HILOG_DEBUG("load js code from %{public}s", fileName);
100                         NativeValue* exportObject = engine->LoadArkModule(module->jsCode, module->jsCodeLen, fileName);
101                         if (exportObject == nullptr) {
102                             HILOG_ERROR("load module failed");
103                             return scope.Escape(exports.ToLocal(ecmaVm));
104                         } else {
105                             exports = *exportObject;
106                             engine->loadedModules_[module] = Global<JSValueRef>(ecmaVm, exports.ToLocal(ecmaVm));
107                         }
108                     } else if (module->registerCallback != nullptr) {
109                         NativeValue* exportObject = engine->CreateObject();
110                         module->registerCallback(engine, exportObject);
111                         exports = *exportObject;
112                         engine->loadedModules_[module] = Global<JSValueRef>(ecmaVm, exports.ToLocal(ecmaVm));
113                     } else {
114                         HILOG_ERROR("init module failed");
115                         return scope.Escape(exports.ToLocal(ecmaVm));
116                     }
117                 }
118                 return scope.Escape(exports.ToLocal(ecmaVm));
119             },
120             requireData);
121 
122     Local<FunctionRef> requireInternal =
123         FunctionRef::New(
124             vm,
125             [](EcmaVM *ecmaVm, Local<JSValueRef> thisObj,
126                const Local<JSValueRef> argv[],  // NOLINTNEXTLINE(modernize-avoid-c-arrays)
127                int32_t length, void *data) -> Local<JSValueRef> {
128                 panda::EscapeLocalScope scope(ecmaVm);
129                 NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
130                 ArkNativeEngine* engine = static_cast<ArkNativeEngine*>(data);
131                 Local<StringRef> moduleName(argv[0]);
132                 NativeModule* module = moduleManager->LoadNativeModule(moduleName->ToString().c_str(), nullptr, false);
133                 Global<JSValueRef> exports(ecmaVm, JSValueRef::Undefined(ecmaVm));
134                 if (module != nullptr) {
135                     auto it = engine->loadedModules_.find(module);
136                     if (it != engine->loadedModules_.end()) {
137                         return scope.Escape(it->second.ToLocal(ecmaVm));
138                     }
139 
140                     NativeValue* exportObject = engine->CreateObject();
141                     if (exportObject != nullptr) {
142                         module->registerCallback(engine, exportObject);
143                         exports = *exportObject;
144                         engine->loadedModules_[module] = Global<JSValueRef>(ecmaVm, exports.ToLocal(ecmaVm));
145                     } else {
146                         HILOG_ERROR("exportObject is nullptr");
147                         return scope.Escape(exports.ToLocal(ecmaVm));
148                     }
149                 }
150                 return scope.Escape(exports.ToLocal(ecmaVm));
151             },
152             requireData);
153 
154     Local<ObjectRef> global = panda::JSNApi::GetGlobalObject(vm);
155     global->Set(vm, requireName, requireNapi);
156     global->Set(vm, requireInternalName, requireInternal);
157     // need to call init of base class.
158     Init();
159 }
160 
~ArkNativeEngine()161 ArkNativeEngine::~ArkNativeEngine()
162 {
163     // need to call deinit before base class.
164     Deinit();
165 
166     // Free cached objects
167     for (auto&& [module, exportObj] : loadedModules_) {
168         exportObj.FreeGlobalHandleAddr();
169     }
170     // Free callbackRef
171     if (promiseRejectCallbackRef_ != nullptr) {
172         delete promiseRejectCallbackRef_;
173     }
174     if (checkCallbackRef_ != nullptr) {
175         delete checkCallbackRef_;
176     }
177 }
178 
GetModuleFromName(const std::string & moduleName,bool isAppModule,const std::string & id,const std::string & param,const std::string & instanceName,void ** instance)179 panda::Global<panda::ObjectRef> ArkNativeEngine::GetModuleFromName(
180     const std::string& moduleName, bool isAppModule, const std::string& id, const std::string& param,
181     const std::string& instanceName, void** instance)
182 {
183     Global<ObjectRef> exports(vm_, JSValueRef::Undefined(vm_));
184     NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
185     NativeModule* module = moduleManager->LoadNativeModule(moduleName.c_str(), nullptr, isAppModule);
186     if (module != nullptr) {
187         NativeValue* idValue = new ArkNativeString(this, id.c_str(), id.size());
188         NativeValue* paramValue = new ArkNativeString(this, param.c_str(), param.size());
189         NativeValue* exportObject = new ArkNativeObject(this);
190 
191         NativePropertyDescriptor idProperty, paramProperty;
192         idProperty.utf8name = "id";
193         idProperty.value = idValue;
194         paramProperty.utf8name = "param";
195         paramProperty.value = paramValue;
196 
197         ArkNativeObject* exportObj = reinterpret_cast<ArkNativeObject*>(exportObject);
198         exportObj->DefineProperty(idProperty);
199         exportObj->DefineProperty(paramProperty);
200         module->registerCallback(this, exportObject);
201 
202         napi_value nExport = reinterpret_cast<napi_value>(exportObject);
203         napi_value exportInstance = nullptr;
204         napi_status status = napi_get_named_property(
205             reinterpret_cast<napi_env>(this), nExport, instanceName.c_str(), &exportInstance);
206         if (status != napi_ok) {
207             HILOG_ERROR("GetModuleFromName napi_get_named_property status != napi_ok");
208         }
209 
210         status = napi_unwrap(reinterpret_cast<napi_env>(this), exportInstance, reinterpret_cast<void**>(instance));
211         if (status != napi_ok) {
212             HILOG_ERROR("GetModuleFromName napi_unwrap status != napi_ok");
213         }
214 
215         exports = *exportObject;
216     }
217     return exports;
218 }
219 
LoadModuleByName(const std::string & moduleName,bool isAppModule,const std::string & param,const std::string & instanceName,void * instance)220 panda::Global<panda::ObjectRef> ArkNativeEngine::LoadModuleByName(
221     const std::string& moduleName, bool isAppModule, const std::string& param,
222     const std::string& instanceName, void* instance)
223 {
224     Global<ObjectRef> exports(vm_, JSValueRef::Undefined(vm_));
225     NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
226     NativeModule* module = moduleManager->LoadNativeModule(moduleName.c_str(), nullptr, isAppModule);
227     if (module != nullptr) {
228         NativeValue* exportObject = new ArkNativeObject(this);
229         ArkNativeObject* exportObj = reinterpret_cast<ArkNativeObject*>(exportObject);
230 
231         NativePropertyDescriptor paramProperty, instanceProperty;
232 
233         NativeValue* paramValue = new ArkNativeString(this, param.c_str(), param.size());
234         paramProperty.utf8name = "param";
235         paramProperty.value = paramValue;
236 
237         auto instanceValue = new ArkNativeObject(this);
238         instanceValue->SetNativePointer(instance, nullptr, nullptr);
239         instanceProperty.utf8name = instanceName.c_str();
240         instanceProperty.value = instanceValue;
241 
242         exportObj->DefineProperty(paramProperty);
243         exportObj->DefineProperty(instanceProperty);
244 
245         module->registerCallback(this, exportObject);
246         exports = *exportObject;
247     }
248     return exports;
249 }
250 
Loop(LoopMode mode,bool needSync)251 void ArkNativeEngine::Loop(LoopMode mode, bool needSync)
252 {
253     LocalScope scope(vm_);
254     NativeEngine::Loop(mode, needSync);
255     panda::JSNApi::ExecutePendingJob(vm_);
256 }
257 
GetGlobal()258 NativeValue* ArkNativeEngine::GetGlobal()
259 {
260     LocalScope scope(vm_);
261     Local<ObjectRef> value = panda::JSNApi::GetGlobalObject(vm_);
262     return ArkValueToNativeValue(this, value);
263 }
264 
CreateNull()265 NativeValue* ArkNativeEngine::CreateNull()
266 {
267     LocalScope scope(vm_);
268     Local<PrimitiveRef> value = JSValueRef::Null(vm_);
269     return new ArkNativeValue(this, value);
270 }
271 
CreateUndefined()272 NativeValue* ArkNativeEngine::CreateUndefined()
273 {
274     LocalScope scope(vm_);
275     Local<PrimitiveRef> value = JSValueRef::Undefined(vm_);
276     return new ArkNativeValue(this, value);
277 }
278 
CreateBoolean(bool value)279 NativeValue* ArkNativeEngine::CreateBoolean(bool value)
280 {
281     return new ArkNativeBoolean(this, value);
282 }
283 
CreateNumber(int32_t value)284 NativeValue* ArkNativeEngine::CreateNumber(int32_t value)
285 {
286     return new ArkNativeNumber(this, value);
287 }
288 
CreateNumber(uint32_t value)289 NativeValue* ArkNativeEngine::CreateNumber(uint32_t value)
290 {
291     return new ArkNativeNumber(this, value);
292 }
293 
CreateNumber(int64_t value)294 NativeValue* ArkNativeEngine::CreateNumber(int64_t value)
295 {
296     return new ArkNativeNumber(this, value);
297 }
298 
CreateNumber(double value)299 NativeValue* ArkNativeEngine::CreateNumber(double value)
300 {
301     return new ArkNativeNumber(this, value);
302 }
303 
CreateBigInt(int64_t value)304 NativeValue* ArkNativeEngine::CreateBigInt(int64_t value)
305 {
306     return new ArkNativeBigInt(this, value);
307 }
308 
CreateBigInt(uint64_t value)309 NativeValue* ArkNativeEngine::CreateBigInt(uint64_t value)
310 {
311     return new ArkNativeBigInt(this, value, true);
312 }
313 
CreateString(const char * value,size_t length)314 NativeValue* ArkNativeEngine::CreateString(const char* value, size_t length)
315 {
316     return new ArkNativeString(this, value, length);
317 }
318 
CreateString16(const char16_t * value,size_t length)319 NativeValue* ArkNativeEngine::CreateString16(const char16_t* value, size_t length)
320 {
321     return nullptr;
322 }
323 
CreateSymbol(NativeValue * value)324 NativeValue* ArkNativeEngine::CreateSymbol(NativeValue* value)
325 {
326     LocalScope scope(vm_);
327     Global<StringRef> str = *value;
328     Local<SymbolRef> symbol = SymbolRef::New(vm_, str.ToLocal(vm_));
329     return new ArkNativeValue(this, symbol);
330 }
331 
CreateExternal(void * value,NativeFinalize callback,void * hint)332 NativeValue* ArkNativeEngine::CreateExternal(void* value, NativeFinalize callback, void* hint)
333 {
334     return new ArkNativeExternal(this, value, callback, hint);
335 }
336 
CreateObject()337 NativeValue* ArkNativeEngine::CreateObject()
338 {
339     return new ArkNativeObject(this);
340 }
341 
CreateFunction(const char * name,size_t length,NativeCallback cb,void * value)342 NativeValue* ArkNativeEngine::CreateFunction(const char* name, size_t length, NativeCallback cb, void* value)
343 {
344     return new ArkNativeFunction(this, name, length, cb, value);
345 }
346 
CreateArray(size_t length)347 NativeValue* ArkNativeEngine::CreateArray(size_t length)
348 {
349     return new ArkNativeArray(this, length);
350 }
351 
CreateArrayBuffer(void ** value,size_t length)352 NativeValue* ArkNativeEngine::CreateArrayBuffer(void** value, size_t length)
353 {
354     return new ArkNativeArrayBuffer(this, (uint8_t**)value, length);
355 }
356 
CreateArrayBufferExternal(void * value,size_t length,NativeFinalize cb,void * hint)357 NativeValue* ArkNativeEngine::CreateArrayBufferExternal(void* value, size_t length, NativeFinalize cb, void* hint)
358 {
359     return new ArkNativeArrayBuffer(this, (uint8_t*)value, length, cb, hint);
360 }
361 
CreateTypedArray(NativeTypedArrayType type,NativeValue * value,size_t length,size_t offset)362 NativeValue* ArkNativeEngine::CreateTypedArray(NativeTypedArrayType type,
363                                                NativeValue* value,
364                                                size_t length,
365                                                size_t offset)
366 {
367     LocalScope scope(vm_);
368     Global<ArrayBufferRef> globalBuffer = *value;
369     Local<ArrayBufferRef> buffer = globalBuffer.ToLocal(vm_);
370     Local<TypedArrayRef> typedArray(JSValueRef::Undefined(vm_));
371 
372     switch (type) {
373         case NATIVE_INT8_ARRAY:
374             typedArray = panda::Int8ArrayRef::New(vm_, buffer, offset, length);
375             break;
376         case NATIVE_UINT8_ARRAY:
377             typedArray = panda::Uint8ArrayRef::New(vm_, buffer, offset, length);
378             break;
379         case NATIVE_UINT8_CLAMPED_ARRAY:
380             typedArray = panda::Uint8ClampedArrayRef::New(vm_, buffer, offset, length);
381             break;
382         case NATIVE_INT16_ARRAY:
383             typedArray = panda::Int16ArrayRef::New(vm_, buffer, offset, length);
384             break;
385         case NATIVE_UINT16_ARRAY:
386             typedArray = panda::Uint16ArrayRef::New(vm_, buffer, offset, length);
387             break;
388         case NATIVE_INT32_ARRAY:
389             typedArray = panda::Int32ArrayRef::New(vm_, buffer, offset, length);
390             break;
391         case NATIVE_UINT32_ARRAY:
392             typedArray = panda::Uint32ArrayRef::New(vm_, buffer, offset, length);
393             break;
394         case NATIVE_FLOAT32_ARRAY:
395             typedArray = panda::Float32ArrayRef::New(vm_, buffer, offset, length);
396             break;
397         case NATIVE_FLOAT64_ARRAY:
398             typedArray = panda::Float64ArrayRef::New(vm_, buffer, offset, length);
399             break;
400         case NATIVE_BIGINT64_ARRAY:
401             // not support yet
402             return nullptr;
403         case NATIVE_BIGUINT64_ARRAY:
404             // not support yet
405             return nullptr;
406         default:
407             return nullptr;
408     }
409     return new ArkNativeTypedArray(this, typedArray);
410 }
411 
CreateDataView(NativeValue * value,size_t length,size_t offset)412 NativeValue* ArkNativeEngine::CreateDataView(NativeValue* value, size_t length, size_t offset)
413 {
414     return new ArkNativeDataView(this, value, length, offset);
415 }
416 
CreatePromise(NativeDeferred ** deferred)417 NativeValue* ArkNativeEngine::CreatePromise(NativeDeferred** deferred)
418 {
419     LocalScope scope(vm_);
420     Local<PromiseCapabilityRef> capability = PromiseCapabilityRef::New(vm_);
421     *deferred = new ArkNativeDeferred(this, capability);
422 
423     return new ArkNativeValue(this, capability->GetPromise(vm_));
424 }
425 
CreateError(NativeValue * code,NativeValue * message)426 NativeValue* ArkNativeEngine::CreateError(NativeValue* code, NativeValue* message)
427 {
428     LocalScope scope(vm_);
429     Local<JSValueRef> errorVal = panda::Exception::Error(vm_, *message);
430     if (code != nullptr) {
431         Local<StringRef> codeKey = StringRef::NewFromUtf8(vm_, "code");
432         Local<ObjectRef> errorObj(errorVal);
433         errorObj->Set(vm_, codeKey, *code);
434     }
435     return ArkValueToNativeValue(this, errorVal);
436 }
437 
CallFunction(NativeValue * thisVar,NativeValue * function,NativeValue * const * argv,size_t argc)438 NativeValue* ArkNativeEngine::CallFunction(NativeValue* thisVar,
439                                            NativeValue* function,
440                                            NativeValue* const* argv,
441                                            size_t argc)
442 {
443     if (function == nullptr) {
444         return nullptr;
445     }
446     LocalScope scope(vm_);
447     Local<JSValueRef> thisObj = JSValueRef::Undefined(vm_);
448     if (thisVar != nullptr) {
449         Global<JSValueRef> globalObj = *thisVar;
450         thisObj = globalObj.ToLocal(vm_);
451     }
452     Global<FunctionRef> funcObj = *function;
453 #ifdef ENABLE_CONTAINER_SCOPE
454     auto nativeFunction = static_cast<NativeFunction*>(function->GetInterface(NativeFunction::INTERFACE_ID));
455     if (nativeFunction == nullptr) {
456         HILOG_ERROR("nativeFunction is null");
457         return nullptr;
458     }
459     auto arkNativeFunc = static_cast<ArkNativeFunction*>(nativeFunction);
460     OHOS::Ace::ContainerScope containerScope(arkNativeFunc->GetScopeId());
461 #endif
462     std::vector<Local<JSValueRef>> args;
463     args.reserve(argc);
464     for (size_t i = 0; i < argc; i++) {
465         if (argv[i] != nullptr) {
466             Global<JSValueRef> arg = *argv[i];
467             args.emplace_back(arg.ToLocal(vm_));
468         } else {
469             args.emplace_back(JSValueRef::Undefined(vm_));
470         }
471     }
472 
473     Local<JSValueRef> value = funcObj->Call(vm_, thisObj, args.data(), argc);
474     Local<ObjectRef> excep = panda::JSNApi::GetUncaughtException(vm_);
475     HandleUncaughtException();
476     if (!excep.IsNull()) {
477         Local<StringRef> exceptionMsg = excep->ToString(vm_);
478         exceptionStr_ = exceptionMsg->ToString();
479     }
480 
481     return ArkValueToNativeValue(this, value);
482 }
483 
RunScript(NativeValue * script)484 NativeValue* ArkNativeEngine::RunScript(NativeValue* script)
485 {
486     // not support yet
487     return nullptr;
488 }
489 
SetPackagePath(const std::string & packagePath)490 void ArkNativeEngine::SetPackagePath(const std::string& packagePath)
491 {
492     auto moduleManager = NativeModuleManager::GetInstance();
493     if (moduleManager && !packagePath.empty()) {
494         moduleManager->SetAppLibPath(packagePath.c_str());
495     }
496 }
497 
DefineClass(const char * name,NativeCallback callback,void * data,const NativePropertyDescriptor * properties,size_t length)498 NativeValue* ArkNativeEngine::DefineClass(const char* name,
499                                           NativeCallback callback,
500                                           void* data,
501                                           const NativePropertyDescriptor* properties,
502                                           size_t length)
503 {
504     LocalScope scope(vm_);
505     auto classConstructor = new ArkNativeFunction(this, name, callback, data);
506     auto classPrototype = classConstructor->GetFunctionPrototype();
507 
508     for (size_t i = 0; i < length; i++) {
509         if (properties[i].attributes & NATIVE_STATIC) {
510             classConstructor->DefineProperty(properties[i]);
511         } else {
512             if (classPrototype == nullptr) {
513                 HILOG_ERROR("ArkNativeEngine::Class's prototype is null");
514                 continue;
515             }
516             static_cast<ArkNativeObject*>(classPrototype)->DefineProperty(properties[i]);
517         }
518     }
519 
520     return classConstructor;
521 }
522 
CreateInstance(NativeValue * constructor,NativeValue * const * argv,size_t argc)523 NativeValue* ArkNativeEngine::CreateInstance(NativeValue* constructor, NativeValue* const* argv, size_t argc)
524 {
525     if (constructor == nullptr) {
526         return nullptr;
527     }
528     LocalScope scope(vm_);
529     Global<FunctionRef> value = *constructor;
530 
531     std::vector<Local<JSValueRef>> args;
532     args.reserve(argc);
533     for (size_t i = 0; i < argc; i++) {
534         if (argv[i] != nullptr) {
535             Global<JSValueRef> arg = *argv[i];
536             args.emplace_back(arg.ToLocal(vm_));
537         } else {
538             args.emplace_back(JSValueRef::Undefined(vm_));
539         }
540     }
541 
542     Local<JSValueRef> instance = value->Constructor(vm_, args.data(), argc);
543 
544     return ArkValueToNativeValue(this, instance);
545 }
546 
CreateReference(NativeValue * value,uint32_t initialRefcount,NativeFinalize callback,void * data,void * hint)547 NativeReference* ArkNativeEngine::CreateReference(NativeValue* value, uint32_t initialRefcount,
548     NativeFinalize callback, void* data, void* hint)
549 {
550     return new ArkNativeReference(this, value, initialRefcount);
551 }
552 
Throw(NativeValue * error)553 bool ArkNativeEngine::Throw(NativeValue* error)
554 {
555     LocalScope scope(vm_);
556     Global<JSValueRef> errorVal = *error;
557     panda::JSNApi::ThrowException(vm_, errorVal.ToLocal(vm_));
558     lastException_ = error;
559     return true;
560 }
561 
Throw(NativeErrorType type,const char * code,const char * message)562 bool ArkNativeEngine::Throw(NativeErrorType type, const char* code, const char* message)
563 {
564     LocalScope scope(vm_);
565     Local<JSValueRef> error(JSValueRef::Undefined(vm_));
566     switch (type) {
567         case NATIVE_COMMON_ERROR:
568             error = panda::Exception::Error(vm_, StringRef::NewFromUtf8(vm_, message));
569             break;
570         case NATIVE_TYPE_ERROR:
571             error = panda::Exception::TypeError(vm_, StringRef::NewFromUtf8(vm_, message));
572             break;
573         case NATIVE_RANGE_ERROR:
574             error = panda::Exception::RangeError(vm_, StringRef::NewFromUtf8(vm_, message));
575             break;
576         default:
577             return false;
578     }
579     if (code != nullptr) {
580         Local<JSValueRef> codeKey = StringRef::NewFromUtf8(vm_, "code");
581         Local<JSValueRef> codeValue = StringRef::NewFromUtf8(vm_, code);
582         Local<ObjectRef> errorObj(error);
583         errorObj->Set(vm_, codeKey, codeValue);
584     }
585 
586     panda::JSNApi::ThrowException(vm_, error);
587     lastException_ = ArkValueToNativeValue(this, error);
588     return true;
589 }
590 
CreateRuntimeFunc(NativeEngine * engine,void * jsEngine)591 NativeEngine* ArkNativeEngine::CreateRuntimeFunc(NativeEngine* engine, void* jsEngine)
592 {
593     panda::RuntimeOption option;
594     int arkProperties = OHOS::system::GetIntParameter<int>("persist.ark.properties", -1);
595     option.SetArkProperties(arkProperties);
596     HILOG_INFO("ArkNativeEngine::CreateRuntime ark properties = %{public}d", arkProperties);
597     option.SetGcType(panda::RuntimeOption::GC_TYPE::GEN_GC);
598     const int64_t poolSize = 0x1000000;
599     option.SetGcPoolSize(poolSize);
600     option.SetLogLevel(panda::RuntimeOption::LOG_LEVEL::ERROR);
601     option.SetDebuggerLibraryPath("");
602     EcmaVM* vm = panda::JSNApi::CreateJSVM(option);
603     if (vm == nullptr) {
604         return nullptr;
605     }
606 
607     ArkNativeEngine* arkEngine = new ArkNativeEngine(vm, jsEngine);
608 
609     // init callback
610     arkEngine->RegisterWorkerFunction(engine);
611 
612     auto cleanEnv = [vm]() {
613         if (vm != nullptr) {
614             HILOG_INFO("cleanEnv is called");
615             panda::JSNApi::DestroyJSVM(vm);
616         }
617     };
618     arkEngine->SetCleanEnv(cleanEnv);
619 
620     return arkEngine;
621 }
622 
CreateRuntime()623 void* ArkNativeEngine::CreateRuntime()
624 {
625     return ArkNativeEngine::CreateRuntimeFunc(this, jsEngine_);
626 }
627 
Serialize(NativeEngine * context,NativeValue * value,NativeValue * transfer)628 NativeValue* ArkNativeEngine::Serialize(NativeEngine* context, NativeValue* value, NativeValue* transfer)
629 {
630     const panda::ecmascript::EcmaVM* vm = reinterpret_cast<ArkNativeEngine*>(context)->GetEcmaVm();
631     LocalScope scope(vm);
632     Local<JSValueRef> arkValue = *value;
633     Local<JSValueRef> arkTransfer = *transfer;
634     void* result = panda::JSNApi::SerializeValue(vm, arkValue, arkTransfer);
635     return reinterpret_cast<NativeValue*>(result);
636 }
637 
Deserialize(NativeEngine * context,NativeValue * recorder)638 NativeValue* ArkNativeEngine::Deserialize(NativeEngine* context, NativeValue* recorder)
639 {
640     const panda::ecmascript::EcmaVM* vm = reinterpret_cast<ArkNativeEngine*>(context)->GetEcmaVm();
641     LocalScope scope(vm);
642     Local<JSValueRef> result = panda::JSNApi::DeserializeValue(vm, recorder);
643     return ArkValueToNativeValue(this, result);
644 }
645 
GetExceptionForWorker() const646 ExceptionInfo* ArkNativeEngine::GetExceptionForWorker() const
647 {
648     if (exceptionStr_.empty()) {
649         HILOG_ERROR("worker:: exception is null");
650         return nullptr;
651     }
652 
653     ExceptionInfo* exceptionInfo = new ExceptionInfo();
654     size_t msgLength = exceptionStr_.length();
655     char* exceptionMessage = new char[msgLength + 1] { 0 };
656     if (memcpy_s(exceptionMessage, msgLength + 1, exceptionStr_.c_str(), msgLength) != EOK) {
657         HILOG_ERROR("worker:: memcpy_s error");
658         delete exceptionInfo;
659         delete[] exceptionMessage;
660         return nullptr;
661     }
662     exceptionInfo->message_ = exceptionMessage;
663     // need add colno, lineno when ark exception support
664     return exceptionInfo;
665 }
666 
DeleteSerializationData(NativeValue * value) const667 void ArkNativeEngine::DeleteSerializationData(NativeValue* value) const
668 {
669     void* data = reinterpret_cast<void*>(value);
670     panda::JSNApi::DeleteSerializationData(data);
671 }
672 
StartCpuProfiler(const std::string fileName)673 void ArkNativeEngine::StartCpuProfiler(const std::string fileName)
674 {
675     panda::JSNApi::StartCpuProfiler(vm_, fileName);
676 }
677 
StopCpuProfiler()678 void ArkNativeEngine::StopCpuProfiler()
679 {
680     panda::JSNApi::StopCpuProfiler();
681 }
682 
ResumeVM()683 void ArkNativeEngine::ResumeVM()
684 {
685     panda::JSNApi::ResumeVM(vm_);
686 }
687 
SuspendVM()688 bool ArkNativeEngine::SuspendVM()
689 {
690     return panda::JSNApi::SuspendVM(vm_);
691 }
692 
IsSuspended()693 bool ArkNativeEngine::IsSuspended()
694 {
695     return panda::JSNApi::IsSuspended(vm_);
696 }
697 
CheckSafepoint()698 bool ArkNativeEngine::CheckSafepoint()
699 {
700     return panda::JSNApi::CheckSafepoint(vm_);
701 }
702 
RunBufferScript(std::vector<uint8_t> & buffer)703 NativeValue* ArkNativeEngine::RunBufferScript(std::vector<uint8_t>& buffer)
704 {
705     panda::JSExecutionScope executionScope(vm_);
706     LocalScope scope(vm_);
707     [[maybe_unused]] bool ret = panda::JSNApi::Execute(vm_, buffer.data(), buffer.size(), PANDA_MAIN_FUNCTION);
708 
709     Local<ObjectRef> excep = panda::JSNApi::GetUncaughtException(vm_);
710     HandleUncaughtException();
711     if (!excep.IsNull()) {
712         Local<StringRef> exceptionMsg = excep->ToString(vm_);
713         exceptionStr_ = exceptionMsg->ToString();
714         return nullptr;
715     }
716     return CreateUndefined();
717 }
718 
RunActor(std::vector<uint8_t> & buffer,const char * descriptor)719 NativeValue* ArkNativeEngine::RunActor(std::vector<uint8_t>& buffer, const char* descriptor)
720 {
721     panda::JSExecutionScope executionScope(vm_);
722     LocalScope scope(vm_);
723     std::string desc(descriptor);
724     [[maybe_unused]] bool ret = panda::JSNApi::Execute(vm_, buffer.data(), buffer.size(), PANDA_MAIN_FUNCTION, desc);
725     Local<ObjectRef> excep = panda::JSNApi::GetAndClearUncaughtException(vm_);
726     if (!excep.IsNull()) {
727         Local<StringRef> exceptionMsg = excep->ToString(vm_);
728         exceptionStr_ = exceptionMsg->ToString();
729         return nullptr;
730     }
731     return CreateUndefined();
732 }
733 
LoadArkModule(const char * str,int32_t len,const std::string & fileName)734 NativeValue* ArkNativeEngine::LoadArkModule(const char* str, int32_t len, const std::string& fileName)
735 {
736     LocalScope scope(vm_);
737     HILOG_DEBUG("ArkNativeEngine::LoadModule start, buffer = %{public}s", str);
738     if (str == nullptr || len <= 0 || fileName.empty()) {
739         HILOG_ERROR("fileName is nullptr or source code is nullptr");
740         return nullptr;
741     }
742 
743     bool res = JSNApi::ExecuteModuleFromBuffer(vm_, str, len, fileName);
744     if (!res) {
745         HILOG_ERROR("Execute module failed");
746         return nullptr;
747     }
748 
749     Local<ObjectRef> exportObj = JSNApi::GetExportObject(vm_, fileName, "default");
750     if (exportObj->IsNull()) {
751         HILOG_ERROR("Get export object failed");
752         return nullptr;
753     }
754 
755     HILOG_DEBUG("ArkNativeEngine::LoadModule end");
756     return ArkValueToNativeValue(this, exportObj);
757 }
758 
LoadModule(NativeValue * str,const std::string & fileName)759 NativeValue* ArkNativeEngine::LoadModule(NativeValue* str, const std::string& fileName)
760 {
761     return nullptr;
762 }
763 
ArkValueToNativeValue(ArkNativeEngine * engine,Local<JSValueRef> value)764 NativeValue* ArkNativeEngine::ArkValueToNativeValue(ArkNativeEngine* engine, Local<JSValueRef> value)
765 {
766     NativeValue* result = nullptr;
767     if (value->IsNull() || value->IsUndefined() || value->IsSymbol() || value->IsPromise()) {
768         result = new ArkNativeValue(engine, value);
769     } else if (value->IsNumber()) {
770         result = new ArkNativeNumber(engine, value);
771     } else if (value->IsString()) {
772         result = new ArkNativeString(engine, value);
773     } else if (value->IsArray(engine->GetEcmaVm())) {
774         result = new ArkNativeArray(engine, value);
775     } else if (value->IsFunction()) {
776         result = new ArkNativeFunction(engine, value);
777     } else if (value->IsArrayBuffer()) {
778         result = new ArkNativeArrayBuffer(engine, value);
779     } else if (value->IsDataView()) {
780         result = new ArkNativeDataView(engine, value);
781     } else if (value->IsTypedArray()) {
782         result = new ArkNativeTypedArray(engine, value);
783     } else if (value->IsNativePointer()) {
784         result = new ArkNativeExternal(engine, value);
785     } else if (value->IsDate()) {
786         result = new ArkNativeDate(engine, value);
787     } else if (value->IsBigInt()) {
788         result = new ArkNativeBigInt(engine, value);
789     } else if (value->IsObject()) {
790         result = new ArkNativeObject(engine, value);
791     } else if (value->IsBoolean()) {
792         result = new ArkNativeBoolean(engine, value);
793     }
794     return result;
795 }
796 
ValueToNativeValue(JSValueWrapper & value)797 NativeValue* ArkNativeEngine::ValueToNativeValue(JSValueWrapper& value)
798 {
799     LocalScope scope(vm_);
800     Global<JSValueRef> arkValue = value;
801     return ArkValueToNativeValue(this, arkValue.ToLocal(vm_));
802 }
803 
ExecuteJsBin(const std::string & fileName)804 bool ArkNativeEngine::ExecuteJsBin(const std::string& fileName)
805 {
806     panda::JSExecutionScope executionScope(vm_);
807     LocalScope scope(vm_);
808     bool ret = JSNApi::Execute(vm_, fileName, PANDA_MAIN_FUNCTION);
809     return ret;
810 }
811 
CreateBuffer(void ** value,size_t length)812 NativeValue* ArkNativeEngine::CreateBuffer(void** value, size_t length)
813 {
814     return nullptr;
815 }
816 
CreateBufferCopy(void ** value,size_t length,const void * data)817 NativeValue* ArkNativeEngine::CreateBufferCopy(void** value, size_t length, const void* data)
818 {
819     return nullptr;
820 }
821 
CreateBufferExternal(void * value,size_t length,NativeFinalize cb,void * hint)822 NativeValue* ArkNativeEngine::CreateBufferExternal(void* value, size_t length, NativeFinalize cb, void* hint)
823 {
824     return nullptr;
825 }
826 
CreateDate(double value)827 NativeValue* ArkNativeEngine::CreateDate(double value)
828 {
829     return ArkValueToNativeValue(this, DateRef::New(vm_, value));
830 }
831 
CreateBigWords(int sign_bit,size_t word_count,const uint64_t * words)832 NativeValue* ArkNativeEngine::CreateBigWords(int sign_bit, size_t word_count, const uint64_t* words)
833 {
834     LocalScope scope(vm_);
835     constexpr int bigintMod = 2; // 2 : used for even number judgment
836     bool sign = false;
837     if ((sign_bit % bigintMod) == 1) {
838         sign = true;
839     }
840     uint32_t size = (uint32_t)word_count;
841 
842     Local<JSValueRef> value = BigIntRef::CreateBigWords(vm_, sign, size, words);
843 
844     return new ArkNativeBigInt(this, value);
845 }
846 
TriggerFatalException(NativeValue * error)847 bool ArkNativeEngine::TriggerFatalException(NativeValue* error)
848 {
849     return true;
850 }
851 
AdjustExternalMemory(int64_t ChangeInBytes,int64_t * AdjustedValue)852 bool ArkNativeEngine::AdjustExternalMemory(int64_t ChangeInBytes, int64_t* AdjustedValue)
853 {
854     return true;
855 }
856 
SetPromiseRejectCallback(NativeReference * rejectCallbackRef,NativeReference * checkCallbackRef)857 void ArkNativeEngine::SetPromiseRejectCallback(NativeReference* rejectCallbackRef, NativeReference* checkCallbackRef)
858 {
859     if (rejectCallbackRef == nullptr || checkCallbackRef == nullptr) {
860         HILOG_ERROR("rejectCallbackRef or checkCallbackRef is nullptr");
861         return;
862     }
863     promiseRejectCallbackRef_ = rejectCallbackRef;
864     checkCallbackRef_ = checkCallbackRef;
865     JSNApi::SetHostPromiseRejectionTracker(vm_, reinterpret_cast<void*>(PromiseRejectCallback),
866                                            reinterpret_cast<void*>(this));
867 }
868 
869 // values = {type, promise, reason}
PromiseRejectCallback(void * info)870 void ArkNativeEngine::PromiseRejectCallback(void* info)
871 {
872     panda::PromiseRejectInfo* promiseRejectInfo = reinterpret_cast<panda::PromiseRejectInfo*>(info);
873     ArkNativeEngine* env = reinterpret_cast<ArkNativeEngine*>(promiseRejectInfo->GetData());
874     const panda::ecmascript::EcmaVM* vm = env->GetEcmaVm();
875     LocalScope scope(vm);
876     Local<JSValueRef> promise = promiseRejectInfo->GetPromise();
877     Local<JSValueRef> reason = promiseRejectInfo->GetReason();
878     panda::PromiseRejectInfo::PROMISE_REJECTION_EVENT operation = promiseRejectInfo->GetOperation();
879 
880     if (env == nullptr) {
881         HILOG_ERROR("engine is nullptr");
882         return;
883     }
884 
885     if (env->promiseRejectCallbackRef_ == nullptr || env->checkCallbackRef_ == nullptr) {
886         HILOG_ERROR("promiseRejectCallbackRef or checkCallbackRef is nullptr");
887         return;
888     }
889 
890     Local<JSValueRef> type(IntegerRef::New(vm, static_cast<int32_t>(operation)));
891 
892     Local<JSValueRef> args[] = {type, promise, reason};
893     Global<FunctionRef> promiseRejectCallback = *(env->promiseRejectCallbackRef_->Get());
894     if (!promiseRejectCallback.IsEmpty()) {
895         promiseRejectCallback->Call(vm, JSValueRef::Undefined(vm), args, 3); // 3 args size
896     }
897 
898     if (operation == panda::PromiseRejectInfo::PROMISE_REJECTION_EVENT::REJECT) {
899         Global<JSValueRef> checkCallback = *(env->checkCallbackRef_->Get());
900         if (!checkCallback.IsEmpty()) {
901             JSNApi::SetHostEnqueueJob(vm, checkCallback.ToLocal(vm));
902         }
903     }
904 }
905 
DumpHeapSnapShot(const std::string & path,bool isVmMode,DumpFormat dumpFormat)906 void ArkNativeEngine::DumpHeapSnapShot(const std::string &path, bool isVmMode, DumpFormat dumpFormat)
907 {
908     if (dumpFormat == DumpFormat::JSON) {
909         DFXJSNApi::DumpHeapSnapShot(vm_, 0, path, isVmMode);
910     }
911     if (dumpFormat == DumpFormat::BINARY) {
912         DFXJSNApi::DumpHeapSnapShot(vm_, 1, path, isVmMode);
913     }
914     if (dumpFormat == DumpFormat::OTHER) {
915         DFXJSNApi::DumpHeapSnapShot(vm_, 2, path, isVmMode); // 2:enum is 2
916     }
917 }
918 
BuildNativeAndJsBackStackTrace()919 std::string ArkNativeEngine::BuildNativeAndJsBackStackTrace()
920 {
921     std::string stackTraceStr = DFXJSNApi::BuildNativeAndJsBackStackTrace(vm_);
922     return stackTraceStr;
923 }
924 
StartHeapTracking(double timeInterval,bool isVmMode)925 bool ArkNativeEngine::StartHeapTracking(double timeInterval, bool isVmMode)
926 {
927     return DFXJSNApi::StartHeapTracking(vm_, timeInterval, isVmMode);
928 }
929 
StopHeapTracking(const std::string & filePath,DumpFormat dumpFormat)930 bool ArkNativeEngine::StopHeapTracking(const std::string &filePath, DumpFormat dumpFormat)
931 {
932     if (dumpFormat == DumpFormat::JSON) {
933         return DFXJSNApi::StopHeapTracking(vm_, 0, filePath);
934     }
935     if (dumpFormat == DumpFormat::BINARY) {
936         return DFXJSNApi::StopHeapTracking(vm_, 1, filePath);
937     }
938     if (dumpFormat == DumpFormat::OTHER) {
939         return DFXJSNApi::StopHeapTracking(vm_, 2, filePath); // 2:enum is 2
940     }
941     return false;
942 }
943 
PrintStatisticResult()944 void ArkNativeEngine::PrintStatisticResult()
945 {
946     DFXJSNApi::PrintStatisticResult(vm_);
947 }
948 
StartRuntimeStat()949 void ArkNativeEngine::StartRuntimeStat()
950 {
951     DFXJSNApi::StartRuntimeStat(vm_);
952 }
953 
StopRuntimeStat()954 void ArkNativeEngine::StopRuntimeStat()
955 {
956     DFXJSNApi::StopRuntimeStat(vm_);
957 }
958 
GetArrayBufferSize()959 size_t ArkNativeEngine::GetArrayBufferSize()
960 {
961     return DFXJSNApi::GetArrayBufferSize(vm_);
962 }
963 
GetHeapTotalSize()964 size_t ArkNativeEngine::GetHeapTotalSize()
965 {
966     return DFXJSNApi::GetHeapTotalSize(vm_);
967 }
968 
GetHeapUsedSize()969 size_t ArkNativeEngine::GetHeapUsedSize()
970 {
971     return DFXJSNApi::GetHeapUsedSize(vm_);
972 }
973 
RegisterUncaughtExceptionHandler(UncaughtExceptionCallback callback)974 void ArkNativeEngine::RegisterUncaughtExceptionHandler(UncaughtExceptionCallback callback)
975 {
976     JSNApi::EnableUserUncaughtErrorHandler(vm_);
977     uncaughtExceptionCallback_ = callback;
978 }
979 
HandleUncaughtException()980 void ArkNativeEngine::HandleUncaughtException()
981 {
982     LocalScope scope(vm_);
983     Local<ObjectRef> exception = JSNApi::GetAndClearUncaughtException(vm_);
984     if (!exception.IsEmpty() && !exception->IsHole() && uncaughtExceptionCallback_ != nullptr) {
985         uncaughtExceptionCallback_(ArkValueToNativeValue(this, exception));
986     }
987 }
988