1 /*
2 * Copyright (c) 2021-2022 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 #ifdef ENABLE_HITRACE
19 #include <sys/prctl.h>
20 #endif
21
22 #include <sstream>
23 #include "ark_crash_holder.h"
24 #include "ark_finalizers_pack.h"
25 #include "ark_native_deferred.h"
26 #include "ark_native_reference.h"
27 #include "native_engine/native_property.h"
28 #include "native_engine/native_utils.h"
29 #include "native_sendable.h"
30 #include "securec.h"
31 #include "utils/file.h"
32 #include "utils/log.h"
33 #if !defined(PREVIEW) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
34 #include "parameters.h"
35 #include <uv.h>
36 #endif
37 #ifdef OHOS_STANDARD_PLATFORM
38 #include "unwinder.h"
39 #endif
40 #ifdef ENABLE_CONTAINER_SCOPE
41 #include "core/common/container_scope.h"
42 #endif
43 #if defined(ENABLE_EVENT_HANDLER)
44 #include "event_handler.h"
45 #endif
46 #ifdef ENABLE_HITRACE
47 #include "hitrace/trace.h"
48 #include "hitrace_meter.h"
49 #include "parameter.h"
50 #include "musl_preinit_common.h"
51 #include "memory_trace.h"
52
53 // LCOV_EXCL_START
54 struct alignas(8) HookJsConfig { // 8 is 8 bit
55 int32_t jsStackReport = 0;
56 uint8_t maxJsStackDepth = 0;
57 bool jsFpUnwind = false;
58 char filterNapiName[64] = { "" };
59 };
60
61 class BlockHookScope {
62 public:
BlockHookScope()63 BlockHookScope()
64 {
65 previousState_ = __set_hook_flag(false);
66 }
~BlockHookScope()67 ~BlockHookScope()
68 {
69 __set_hook_flag(previousState_);
70 }
71 private:
72 bool previousState_ {true};
73 };
74
75 static HookJsConfig* g_hookJsConfig = nullptr;
76 static std::once_flag g_hookOnceFlag;
77 static std::string JS_CALL_STACK_DEPTH_SEP = ","; // ',' is js call stack depth separator
78 static std::string JS_SYMBOL_FILEPATH_SEP = "|"; // '|' is js symbol and filepath separator
79 static constexpr uint64_t BUF_SIZE = 128;
80 #endif
81
82 using panda::JsiRuntimeCallInfo;
83 using panda::BooleanRef;
84 using panda::ObjectRef;
85 using panda::StringRef;
86 using panda::Global;
87 using panda::JSNApi;
88 using panda::FunctionRef;
89 using panda::PrimitiveRef;
90 using panda::ArrayBufferRef;
91 using panda::TypedArrayRef;
92 using panda::PromiseCapabilityRef;
93 using panda::PropertyAttribute;
94 using panda::NativePointerRef;
95 using panda::SymbolRef;
96 using panda::IntegerRef;
97 using panda::DateRef;
98 using panda::BigIntRef;
99 static constexpr auto PANDA_MAIN_FUNCTION = "_GLOBAL::func_main_0";
100 static constexpr auto PANDA_MODULE_NAME = "_GLOBAL_MODULE_NAME";
101 static constexpr auto PANDA_MODULE_NAME_LEN = 32;
102 static std::unordered_set<std::string> NATIVE_MODULE = {"system.app", "ohos.app", "system.router",
103 "system.curves", "ohos.curves", "system.matrix4", "ohos.matrix4"};
104 static constexpr auto NATIVE_MODULE_PREFIX = "@native:";
105 static constexpr auto OHOS_MODULE_PREFIX = "@ohos:";
106 #ifdef ENABLE_HITRACE
107 constexpr auto NAPI_PROFILER_PARAM_SIZE = 10;
108 std::atomic<uint64_t> g_chainId = 0;
109 constexpr int NAPI_CALL_STACK = 2; // just for napi call stack
110 #endif
111
112 std::string ArkNativeEngine::tempModuleName_ {""};
113 bool ArkNativeEngine::napiProfilerEnabled {false};
114 bool ArkNativeEngine::napiProfilerParamReaded {false};
115 PermissionCheckCallback ArkNativeEngine::permissionCheckCallback_ {nullptr};
116
117 // This interface is using by ace_engine
LocalValueToLocalNapiValue(panda::Local<panda::JSValueRef> local)118 napi_value LocalValueToLocalNapiValue(panda::Local<panda::JSValueRef> local)
119 {
120 return JsValueFromLocalValue(local);
121 }
122
123 // This interface is using by ace_engine
NapiValueToLocalValue(napi_value v)124 panda::Local<panda::JSValueRef> NapiValueToLocalValue(napi_value v)
125 {
126 return LocalValueFromJsValue(v);
127 }
128
129 #ifdef ENABLE_CONTAINER_SCOPE
FunctionSetContainerId(const EcmaVM * vm,panda::Local<panda::JSValueRef> & value)130 void FunctionSetContainerId(const EcmaVM *vm, panda::Local<panda::JSValueRef> &value)
131 {
132 if (!value->IsFunction(vm)) {
133 return;
134 }
135 panda::Local<panda::FunctionRef> funcValue(value);
136 if (funcValue->IsNative(vm)) {
137 return;
138 }
139
140 auto extraInfo = funcValue->GetData(vm);
141 if (extraInfo != nullptr) {
142 return;
143 }
144
145 NapiFunctionInfo *funcInfo = NapiFunctionInfo::CreateNewInstance();
146 if (funcInfo == nullptr) {
147 HILOG_ERROR("funcInfo is nullptr");
148 return;
149 }
150 funcInfo->scopeId = OHOS::Ace::ContainerScope::CurrentId();
151 funcValue->SetData(vm, reinterpret_cast<void*>(funcInfo),
152 [](void* env, void *externalPointer, void *data) {
153 auto info = reinterpret_cast<NapiFunctionInfo*>(data);
154 if (info != nullptr) {
155 delete info;
156 info = nullptr;
157 }
158 }, true);
159 }
160 #endif
161
NapiDefineClass(napi_env env,const char * name,NapiNativeCallback callback,void * data,const NapiPropertyDescriptor * properties,size_t length)162 panda::Local<panda::JSValueRef> NapiDefineClass(napi_env env, const char* name, NapiNativeCallback callback,
163 void* data, const NapiPropertyDescriptor* properties, size_t length)
164 {
165 auto vm = const_cast<EcmaVM*>(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm());
166 std::string className(name);
167 if (ArkNativeEngine::napiProfilerEnabled) {
168 className = ArkNativeEngine::tempModuleName_ + "." + name;
169 }
170
171 NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
172 if (funcInfo == nullptr) {
173 HILOG_ERROR("funcInfo is nullptr");
174 return panda::JSValueRef::Undefined(vm);
175 }
176 funcInfo->callback = callback;
177 funcInfo->data = data;
178 #ifdef ENABLE_CONTAINER_SCOPE
179 funcInfo->scopeId = OHOS::Ace::ContainerScope::CurrentId();
180 #endif
181
182 Local<panda::FunctionRef> fn = panda::FunctionRef::NewConcurrentClassFunction(vm, ArkNativeFunctionCallBack,
183 [](void* env, void* externalPointer, void* data) {
184 auto info = reinterpret_cast<NapiFunctionInfo*>(data);
185 if (info != nullptr) {
186 delete info;
187 }
188 },
189 reinterpret_cast<void*>(funcInfo), true);
190
191 Local<panda::StringRef> fnName = panda::StringRef::NewFromUtf8(vm, className.c_str());
192 fn->SetName(vm, fnName);
193
194 if (length == 0) {
195 return fn;
196 }
197 Local<panda::ObjectRef> classPrototype = fn->GetFunctionPrototype(vm);
198 Local<panda::ObjectRef> fnObj = fn->ToObject(vm);
199 for (size_t i = 0; i < length; i++) {
200 if (properties[i].attributes & NATIVE_STATIC) {
201 NapiDefineProperty(env, fnObj, properties[i]);
202 } else {
203 if (classPrototype->IsUndefined()) {
204 HILOG_ERROR("ArkNativeEngineImpl::Class's prototype is null");
205 continue;
206 }
207 reinterpret_cast<ArkNativeEngine*>(env)->SetModuleName(classPrototype, className);
208 NapiDefineProperty(env, classPrototype, properties[i]);
209 }
210 }
211
212 return fn;
213 }
214
NapiNativeCreateSendableFunction(napi_env env,const char * name,NapiNativeCallback cb,void * value)215 Local<panda::JSValueRef> NapiNativeCreateSendableFunction(napi_env env,
216 const char* name,
217 NapiNativeCallback cb,
218 void* value)
219 {
220 auto engine = reinterpret_cast<NativeEngine*>(env);
221 auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
222 NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
223 if (funcInfo == nullptr) {
224 HILOG_ERROR("funcInfo is nullptr");
225 return JSValueRef::Undefined(vm);
226 }
227 funcInfo->callback = cb;
228 funcInfo->data = value;
229
230 Local<panda::FunctionRef> fn = panda::FunctionRef::NewSendable(
231 vm, ArkNativeFunctionCallBack,
232 [](void* env, void* externalPointer, void* data) {
233 auto info = reinterpret_cast<NapiFunctionInfo*>(data);
234 if (info != nullptr) {
235 delete info;
236 }
237 },
238 reinterpret_cast<void*>(funcInfo), true);
239 return fn;
240 }
241
NapiDefineSendableClass(napi_env env,const char * name,NapiNativeCallback callback,void * data,const NapiPropertyDescriptor * properties,size_t propertiesLength,napi_value parent)242 panda::Local<panda::JSValueRef> NapiDefineSendableClass(napi_env env,
243 const char* name,
244 NapiNativeCallback callback,
245 void* data,
246 const NapiPropertyDescriptor* properties,
247 size_t propertiesLength,
248 napi_value parent)
249 {
250 const EcmaVM* vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
251 NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
252 if (funcInfo == nullptr) {
253 HILOG_FATAL("funcInfo is nullptr");
254 return JSValueRef::Undefined(vm);
255 }
256 funcInfo->callback = callback;
257 funcInfo->data = data;
258
259 std::string className(name);
260 if (ArkNativeEngine::napiProfilerEnabled) {
261 className = ArkNativeEngine::tempModuleName_ + "." + name;
262 }
263
264 Local<panda::StringRef> fnName = panda::StringRef::NewFromUtf8(vm, className.c_str());
265 Local<JSValueRef> localParent = JSValueRef::Null(vm);
266 if (parent != nullptr) {
267 localParent = LocalValueFromJsValue(parent);
268 }
269
270 auto infos = NativeSendable::CreateSendablePropertiesInfos(env, properties, propertiesLength);
271 Local<panda::FunctionRef> fn = panda::FunctionRef::NewSendableClassFunction(
272 vm, ArkNativeFunctionCallBack,
273 [](void* env, void* externalPointer, void* data) {
274 auto info = reinterpret_cast<NapiFunctionInfo*>(data);
275 if (info != nullptr) {
276 delete info;
277 }
278 },
279 reinterpret_cast<void*>(funcInfo), fnName, infos, localParent, true);
280
281 return fn;
282 }
283
284 struct MoudleNameLocker {
MoudleNameLockerMoudleNameLocker285 explicit MoudleNameLocker(std::string moduleName)
286 {
287 ArkNativeEngine::tempModuleName_ = moduleName;
288 }
~MoudleNameLockerMoudleNameLocker289 ~MoudleNameLocker()
290 {
291 ArkNativeEngine::tempModuleName_ = "";
292 }
293 };
294
GetNativePtrCallBack(void * data)295 void* ArkNativeEngine::GetNativePtrCallBack(void* data)
296 {
297 if (data == nullptr) {
298 HILOG_ERROR("data is nullptr");
299 return nullptr;
300 }
301 auto info = reinterpret_cast<NapiFunctionInfo*>(data);
302 auto cb = reinterpret_cast<void*>(info->callback);
303 return cb;
304 }
305
CheckArkApiAllowList(NativeModule * module,panda::ecmascript::ApiCheckContext context,panda::Local<panda::ObjectRef> & exportCopy)306 bool ArkNativeEngine::CheckArkApiAllowList(
307 NativeModule* module, panda::ecmascript::ApiCheckContext context, panda::Local<panda::ObjectRef>& exportCopy)
308 {
309 std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker = module->apiAllowListChecker;
310 if (apiAllowListChecker != nullptr) {
311 const std::string apiPath = context.moduleName->ToString(context.ecmaVm);
312 if ((*apiAllowListChecker)(apiPath)) {
313 CopyPropertyApiFilter(apiAllowListChecker, context.ecmaVm, context.exportObj, exportCopy, apiPath);
314 }
315 return true;
316 }
317 return false;
318 }
319
CopyPropertyApiFilter(const std::unique_ptr<ApiAllowListChecker> & apiAllowListChecker,const EcmaVM * ecmaVm,const panda::Local<panda::ObjectRef> exportObj,panda::Local<panda::ObjectRef> & exportCopy,const std::string & apiPath)320 void ArkNativeEngine::CopyPropertyApiFilter(const std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker,
321 const EcmaVM* ecmaVm, const panda::Local<panda::ObjectRef> exportObj, panda::Local<panda::ObjectRef>& exportCopy,
322 const std::string& apiPath)
323 {
324 panda::Local<panda::ArrayRef> namesArrayRef = exportObj->GetAllPropertyNames(ecmaVm, NATIVE_DEFAULT);
325 for (uint32_t i = 0; i < namesArrayRef->Length(ecmaVm); ++i) {
326 const panda::Local<panda::JSValueRef> nameValue = panda::ArrayRef::GetValueAt(ecmaVm, namesArrayRef, i);
327 const panda::Local<panda::JSValueRef> value = exportObj->Get(ecmaVm, nameValue);
328 const std::string curPath = apiPath + "." + nameValue->ToString(ecmaVm)->ToString(ecmaVm);
329 if ((*apiAllowListChecker)(curPath)) {
330 const std::string valueType = value->Typeof(ecmaVm)->ToString(ecmaVm);
331 if (valueType == "object") {
332 panda::Local<panda::ObjectRef> subObject = ObjectRef::New(ecmaVm);
333 CopyPropertyApiFilter(apiAllowListChecker, ecmaVm, value, subObject, curPath);
334 exportCopy->Set(ecmaVm, nameValue, subObject);
335 HILOG_DEBUG("Set the package '%{public}s' to the allow list", curPath.c_str());
336 } else if (valueType == "function") {
337 exportCopy->Set(ecmaVm, nameValue, value);
338 HILOG_DEBUG("Set the function '%{public}s' to the allow list", curPath.c_str());
339 } else {
340 exportCopy->Set(ecmaVm, nameValue, value);
341 HILOG_DEBUG("Set the element type is '%{public}s::%{public}s' to the allow list", valueType.c_str(),
342 curPath.c_str());
343 }
344 }
345 }
346 }
347
ArkNativeEngine(EcmaVM * vm,void * jsEngine,bool isLimitedWorker)348 ArkNativeEngine::ArkNativeEngine(EcmaVM* vm, void* jsEngine, bool isLimitedWorker) : NativeEngine(jsEngine),
349 vm_(vm),
350 topScope_(vm),
351 isLimitedWorker_(isLimitedWorker)
352 {
353 HILOG_DEBUG("ArkNativeEngine::ArkNativeEngine");
354 panda::JSNApi::SetEnv(vm, this);
355 #ifdef ENABLE_HITRACE
356 if (!ArkNativeEngine::napiProfilerParamReaded) {
357 char napiProfilerParam[NAPI_PROFILER_PARAM_SIZE] = {0};
358 int ret = GetParameter("persist.hiviewdfx.napiprofiler.enabled", "false",
359 napiProfilerParam, sizeof(napiProfilerParam));
360 if (ret > 0 && strcmp(napiProfilerParam, "true") == 0) {
361 ArkNativeEngine::napiProfilerEnabled = true;
362 }
363 ArkNativeEngine::napiProfilerParamReaded = true;
364 }
365 #endif
366 LocalScope scope(vm_);
367 Local<StringRef> requireInternalName = StringRef::NewFromUtf8(vm, "requireInternal");
368 void* requireData = static_cast<void*>(this);
369
370 options_ = new NapiOptions();
371 crossThreadCheck_ = JSNApi::IsMultiThreadCheckEnabled(vm);
372 #if defined(OHOS_PLATFORM) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
373 int napiProperties = OHOS::system::GetIntParameter<int>("persist.ark.napi.properties", -1);
374 if (options_ != nullptr) {
375 options_->SetProperties(napiProperties);
376 }
377 #endif
378 Local<FunctionRef> requireNapi =
379 FunctionRef::New(
380 vm,
381 [](JsiRuntimeCallInfo *info) -> Local<JSValueRef> {
382 EcmaVM *ecmaVm = info->GetVM();
383 panda::EscapeLocalScope scope(ecmaVm);
384 NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
385 ArkNativeEngine* arkNativeEngine = static_cast<ArkNativeEngine*>(info->GetData());
386 Local<StringRef> moduleName(info->GetCallArgRef(0));
387 NativeModule* module = nullptr;
388 bool isAppModule = false;
389 std::string errInfo = "";
390 Local<JSValueRef> exports(JSValueRef::Undefined(ecmaVm));
391 #ifdef IOS_PLATFORM
392 if (arkNativeEngine->isLimitedWorker_) {
393 if (!moduleManager->CheckModuleRestricted(moduleName->ToString(ecmaVm).c_str())) {
394 HILOG_ERROR("module %{public}s does not found in whitelist",
395 moduleName->ToString(ecmaVm).c_str());
396 return scope.Escape(exports);
397 }
398 }
399 module = moduleManager->LoadNativeModule(
400 moduleName->ToString(ecmaVm).c_str(), nullptr, false, errInfo, false, "");
401 #else
402 const uint32_t lengthMax = 2;
403 if (info->GetArgsNumber() >= lengthMax) {
404 Local<BooleanRef> ret(info->GetCallArgRef(1));
405 isAppModule = ret->Value();
406 }
407 arkNativeEngine->isAppModule_ = isAppModule;
408 if (arkNativeEngine->isLimitedWorker_ && !isAppModule) {
409 if (!moduleManager->CheckModuleRestricted(moduleName->ToString(ecmaVm).c_str())) {
410 HILOG_ERROR("module %{public}s does not found in whitelist",
411 moduleName->ToString(ecmaVm).c_str());
412 return scope.Escape(exports);
413 }
414 }
415
416 if (info->GetArgsNumber() == 3) { // 3:Determine if the number of parameters is equal to 3
417 Local<StringRef> path(info->GetCallArgRef(2)); // 2:Take the second parameter
418 module = moduleManager->LoadNativeModule(moduleName->ToString(ecmaVm).c_str(),
419 path->ToString(ecmaVm).c_str(), isAppModule, errInfo, false, "");
420 } else if (info->GetArgsNumber() == 4) { // 4:Determine if the number of parameters is equal to 4
421 Local<StringRef> path(info->GetCallArgRef(2)); // 2:Take the second parameter
422 Local<StringRef> relativePath(info->GetCallArgRef(3)); // 3:Take the second parameter
423 module = moduleManager->LoadNativeModule(moduleName->ToString(ecmaVm).c_str(), nullptr, isAppModule,
424 errInfo, false, relativePath->ToString(ecmaVm).c_str());
425 } else {
426 module =
427 moduleManager->LoadNativeModule(moduleName->ToString(ecmaVm).c_str(),
428 nullptr, isAppModule, errInfo, false, "");
429 }
430 #endif
431 if (module != nullptr) {
432 auto it = arkNativeEngine->loadedModules_.find(module);
433 if (it != arkNativeEngine->loadedModules_.end()) {
434 return scope.Escape(it->second.ToLocal(ecmaVm));
435 }
436 std::string strModuleName = moduleName->ToString(ecmaVm);
437 moduleManager->SetNativeEngine(strModuleName, arkNativeEngine);
438 MoudleNameLocker nameLocker(strModuleName);
439
440 if (module->jsCode == nullptr && module->getABCCode != nullptr) {
441 module->getABCCode(&module->jsCode, &module->jsCodeLen);
442 }
443 if (module->jsABCCode != nullptr || module->jsCode != nullptr) {
444 char fileName[NAPI_PATH_MAX] = { 0 };
445 const char* name = module->name;
446 if (sprintf_s(fileName, sizeof(fileName), "lib%s.z.so/%s.js", name, name) == -1) {
447 HILOG_ERROR("sprintf_s file name failed");
448 return scope.Escape(exports);
449 }
450 HILOG_DEBUG("load js code from %{public}s", fileName);
451 const void *buffer = nullptr;
452 if (module->jsABCCode) {
453 buffer = static_cast<const void *>(module->jsABCCode);
454 } else {
455 buffer = static_cast<const void *>(module->jsCode);
456 }
457 auto exportObject = arkNativeEngine->LoadArkModule(buffer,
458 module->jsCodeLen, fileName);
459 if (exportObject->IsUndefined()) {
460 HILOG_ERROR("load module failed");
461 return scope.Escape(exports);
462 } else {
463 exports = exportObject;
464 arkNativeEngine->loadedModules_[module] = Global<JSValueRef>(ecmaVm, exports);
465 }
466 } else if (module->registerCallback != nullptr) {
467 Local<ObjectRef> exportObj = ObjectRef::New(ecmaVm);
468 #ifdef ENABLE_HITRACE
469 StartTrace(HITRACE_TAG_ACE, "NAPI module init, name = " + std::string(module->name));
470 #endif
471 arkNativeEngine->SetModuleName(exportObj, module->name);
472 module->registerCallback(reinterpret_cast<napi_env>(arkNativeEngine),
473 JsValueFromLocalValue(exportObj));
474 #ifdef ENABLE_HITRACE
475 FinishTrace(HITRACE_TAG_ACE);
476 #endif
477 panda::Local<panda::ObjectRef> exportCopy = panda::ObjectRef::New(ecmaVm);
478 panda::ecmascript::ApiCheckContext context{moduleManager, ecmaVm, moduleName, exportObj, scope};
479 if (CheckArkApiAllowList(module, context, exportCopy)) {
480 return scope.Escape(exportCopy);
481 }
482 exports = exportObj;
483 arkNativeEngine->loadedModules_[module] = Global<JSValueRef>(ecmaVm, exports);
484 } else {
485 HILOG_ERROR("init module failed");
486 return scope.Escape(exports);
487 }
488 }
489 if (module == nullptr) {
490 HILOG_INFO("%{public}s", errInfo.c_str());
491 exports = panda::ObjectRef::CreateNativeModuleFailureInfo(ecmaVm, errInfo);
492 }
493 return scope.Escape(exports);
494 },
495 nullptr,
496 requireData);
497
498 Local<FunctionRef> requireInternal =
499 FunctionRef::New(
500 vm,
501 [](JsiRuntimeCallInfo *info) -> Local<JSValueRef> {
502 EcmaVM *ecmaVm = info->GetVM();
503 panda::EscapeLocalScope scope(ecmaVm);
504 NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
505 ArkNativeEngine* arkNativeEngine = static_cast<ArkNativeEngine*>(info->GetData());
506 Local<StringRef> moduleName(info->GetCallArgRef(0));
507 std::string errInfo = "";
508 Local<JSValueRef> exports(JSValueRef::Undefined(ecmaVm));
509 if (arkNativeEngine->isLimitedWorker_) {
510 if (!moduleManager->CheckModuleRestricted(moduleName->ToString(ecmaVm).c_str())) {
511 HILOG_ERROR("module %{public}s does not found in whitelist",
512 moduleName->ToString(ecmaVm).c_str());
513 return scope.Escape(exports);
514 }
515 }
516 NativeModule* module = moduleManager->LoadNativeModule(moduleName->ToString(ecmaVm).c_str(),
517 nullptr, false, errInfo, false, "");
518 MoudleNameLocker nameLocker(moduleName->ToString(ecmaVm).c_str());
519 if (module != nullptr && arkNativeEngine) {
520 if (module->registerCallback == nullptr) {
521 if (module->name != nullptr) {
522 HILOG_ERROR("requireInternal Init function is nullptr. module name: %{public}s",
523 module->name);
524 } else {
525 HILOG_ERROR("requireInternal Init function is nullptr.");
526 }
527 return scope.Escape(exports);
528 }
529
530 auto it = arkNativeEngine->loadedModules_.find(module);
531 if (it != arkNativeEngine->loadedModules_.end()) {
532 return scope.Escape(it->second.ToLocal(ecmaVm));
533 }
534 std::string strModuleName = moduleName->ToString(ecmaVm);
535 moduleManager->SetNativeEngine(strModuleName, arkNativeEngine);
536 Local<ObjectRef> exportObj = ObjectRef::New(ecmaVm);
537 if (exportObj->IsObject(ecmaVm)) {
538 arkNativeEngine->SetModuleName(exportObj, module->name);
539 module->registerCallback(reinterpret_cast<napi_env>(arkNativeEngine),
540 JsValueFromLocalValue(exportObj));
541 exports = exportObj;
542 arkNativeEngine->loadedModules_[module] = Global<JSValueRef>(ecmaVm, exports);
543 } else {
544 HILOG_ERROR("exportObject is nullptr");
545 return scope.Escape(exports);
546 }
547 }
548 return scope.Escape(exports);
549 },
550 nullptr,
551 requireData);
552
553 Local<ObjectRef> global = panda::JSNApi::GetGlobalObject(vm);
554 #if !defined(PREVIEW)
555 Local<StringRef> requireName = StringRef::NewFromUtf8(vm, "requireNapi");
556 global->Set(vm, requireName, requireNapi);
557 #else
558 Local<StringRef> requireNapiPreview = StringRef::NewFromUtf8(vm, "requireNapiPreview");
559 global->Set(vm, requireNapiPreview, requireNapi);
560 #endif
561 global->Set(vm, requireInternalName, requireInternal);
562 JSNApi::SetNativePtrGetter(vm, reinterpret_cast<void*>(ArkNativeEngine::GetNativePtrCallBack));
563 // need to call init of base class.
564 NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
565 std::function<bool(const std::string&)> func = [moduleManager](const std::string& moduleKey) -> bool {
566 return moduleManager->UnloadNativeModule(moduleKey);
567 };
568 JSNApi::SetUnloadNativeModuleCallback(vm, func);
569 Init();
570 panda::JSNApi::SetLoop(vm, loop_);
571 panda::JSNApi::SetWeakFinalizeTaskCallback(vm, [this] () -> void {
572 this->PostFinalizeTasks();
573 });
574 JSNApi::SetAsyncCleanTaskCallback(vm, [this] (AsyncNativeCallbacksPack *callbacksPack) {
575 this->PostAsyncTask(callbacksPack);
576 });
577 #if defined(ENABLE_EVENT_HANDLER)
578 if (JSNApi::IsJSMainThreadOfEcmaVM(vm)) {
579 arkIdleMonitor_ = std::make_shared<ArkIdleMonitor>(vm);
580 JSNApi::SetTriggerGCTaskCallback(vm, [this](TriggerGCData& data) {
581 this->PostTriggerGCTask(data);
582 });
583 arkIdleMonitor_->SetStartTimerCallback();
584 PostLooperTriggerIdleGCTask();
585 }
586 #endif
587 }
588
~ArkNativeEngine()589 ArkNativeEngine::~ArkNativeEngine()
590 {
591 HILOG_DEBUG("ArkNativeEngine::~ArkNativeEngine");
592 Deinit();
593 // Free cached objects
594 for (auto&& [module, exportObj] : loadedModules_) {
595 exportObj.FreeGlobalHandleAddr();
596 }
597 // Free callbackRef
598 if (promiseRejectCallbackRef_ != nullptr) {
599 delete promiseRejectCallbackRef_;
600 }
601 if (checkCallbackRef_ != nullptr) {
602 delete checkCallbackRef_;
603 }
604 if (options_ != nullptr) {
605 delete options_;
606 options_ = nullptr;
607 }
608 }
609
610 #ifdef ENABLE_HITRACE
CheckHookConfig(const std::string & nameRef)611 static inline bool CheckHookConfig(const std::string &nameRef)
612 {
613 if (g_hookJsConfig == nullptr || g_hookJsConfig->jsStackReport <= 0 ||
614 g_hookJsConfig->maxJsStackDepth == 0 || !g_hookJsConfig->jsFpUnwind) {
615 return false;
616 } else if (g_hookJsConfig->filterNapiName[0] != '\0' &&
617 nameRef.find(g_hookJsConfig->filterNapiName) != std::string::npos) {
618 return false;
619 }
620 return true;
621 }
622 #endif
623
StartNapiProfilerTrace(panda::JsiRuntimeCallInfo * runtimeInfo,void * cb)624 static inline uint64_t StartNapiProfilerTrace(panda::JsiRuntimeCallInfo* runtimeInfo, void* cb)
625 {
626 #ifdef ENABLE_HITRACE
627 if (ArkNativeEngine::napiProfilerEnabled) {
628 EcmaVM *vm = runtimeInfo->GetVM();
629 LocalScope scope(vm);
630 Local<panda::FunctionRef> fn = runtimeInfo->GetFunctionRef();
631 Local<panda::StringRef> nameRef = fn->GetName(vm);
632 char threadName[BUF_SIZE];
633 prctl(PR_GET_NAME, threadName);
634 StartTraceArgs(HITRACE_TAG_ACE, "Napi called:%s, tname:%s", nameRef->ToString(vm).c_str(), threadName);
635 }
636 bool hookFlag = __get_hook_flag() && __get_global_hook_flag();
637 if (!hookFlag) {
638 return 0;
639 }
640 EcmaVM* vm = runtimeInfo->GetVM();
641 LocalScope scope(vm);
642 Local<panda::FunctionRef> fn = runtimeInfo->GetFunctionRef();
643 Local<panda::StringRef> nameRef = fn->GetName(vm);
644 if (g_hookJsConfig == nullptr) {
645 std::call_once(g_hookOnceFlag, []() { g_hookJsConfig = (HookJsConfig*)__get_hook_config(); });
646 }
647 // add memtrace function
648 if (g_hookJsConfig != nullptr && g_hookJsConfig->jsStackReport == NAPI_CALL_STACK && !g_hookJsConfig->jsFpUnwind) {
649 OHOS::HiviewDFX::HiTraceChain::ClearId();
650 std::unique_ptr<OHOS::HiviewDFX::HiTraceId> arkCallBackTraceId = std::make_unique<OHOS::HiviewDFX::HiTraceId>(
651 OHOS::HiviewDFX::HiTraceChain::Begin("New ArkCallBackTrace", 0));
652 char buffer[256] = {0}; // 256 : buffer size of tag name
653 if (sprintf_s(buffer, sizeof(buffer), "napi:0x%x:%s", arkCallBackTraceId->GetChainId(),
654 nameRef->ToString(vm).c_str()) == -1) {
655 return 0;
656 }
657 uint64_t addr = reinterpret_cast<uint64_t>(cb);
658 ++g_chainId;
659 (void)memtrace(reinterpret_cast<void*>(addr + g_chainId), 8, buffer, true); // 8: the size of addr
660 return 0;
661 }
662 if (!CheckHookConfig(nameRef->ToString(vm))) {
663 return 0;
664 }
665 BlockHookScope blockHook; // block hook
666 std::string rawStack;
667 std::vector<JsFrameInfo> jsFrames;
668 uint64_t nestChainId = 0;
669 jsFrames.reserve(g_hookJsConfig->maxJsStackDepth);
670 auto env = reinterpret_cast<napi_env>(JSNApi::GetEnv(vm));
671 auto engine = reinterpret_cast<NativeEngine*>(env);
672 engine->BuildJsStackInfoListWithCustomDepth(jsFrames);
673 std::stringstream ssRawStack;
674 for (size_t i = 0; i < jsFrames.size() && i < g_hookJsConfig->maxJsStackDepth; i++) {
675 ssRawStack << jsFrames[i].functionName << JS_SYMBOL_FILEPATH_SEP << jsFrames[i].fileName << ":" <<
676 jsFrames[i].pos;
677 if (i < jsFrames.size() - 1) {
678 ssRawStack << JS_CALL_STACK_DEPTH_SEP;
679 }
680 }
681 rawStack = ssRawStack.str();
682 OHOS::HiviewDFX::HiTraceChain::Begin("ArkNativeFunctionCallBack", 0);
683 OHOS::HiviewDFX::HiTraceId hitraceId = OHOS::HiviewDFX::HiTraceChain::GetId();
684 // resolve nested calls to napi and ts
685 if (hitraceId.IsValid()) {
686 nestChainId = hitraceId.GetChainId();
687 }
688 uint64_t chainId = ++g_chainId;
689 hitraceId.SetChainId(chainId);
690 OHOS::HiviewDFX::HiTraceChain::SetId(hitraceId);
691 __send_hook_misc_data(chainId, rawStack.c_str(), rawStack.size() + 1, 1);
692 return nestChainId;
693
694 #endif
695 return 0;
696 }
697
FinishNapiProfilerTrace(uint64_t value)698 static inline void FinishNapiProfilerTrace(uint64_t value)
699 {
700 #ifdef ENABLE_HITRACE
701 if (ArkNativeEngine::napiProfilerEnabled) {
702 FinishTrace(HITRACE_TAG_ACE);
703 }
704 bool hookFlag = __get_hook_flag() && __get_global_hook_flag();
705 if (!hookFlag) {
706 return;
707 }
708 BlockHookScope blockHook; // block hook
709 OHOS::HiviewDFX::HiTraceId hitraceId = OHOS::HiviewDFX::HiTraceChain::GetId();
710 if (hitraceId.IsValid()) {
711 OHOS::HiviewDFX::HiTraceChain::End(hitraceId);
712 OHOS::HiviewDFX::HiTraceChain::ClearId();
713 }
714 // resolve nested calls to napi and ts
715 if (value) {
716 hitraceId.SetChainId(value);
717 OHOS::HiviewDFX::HiTraceChain::SetId(hitraceId);
718 }
719
720 #endif
721 }
722
723 template <bool changeState>
ArkNativeFunctionCallBack(JsiRuntimeCallInfo * runtimeInfo)724 panda::JSValueRef ArkNativeFunctionCallBack(JsiRuntimeCallInfo *runtimeInfo)
725 {
726 EcmaVM *vm = runtimeInfo->GetVM();
727 panda::LocalScope scope(vm);
728 bool getStackBeforeCallNapiSuccess = false;
729 JSNApi::GetStackBeforeCallNapiSuccess(vm, getStackBeforeCallNapiSuccess);
730 auto info = reinterpret_cast<NapiFunctionInfo*>(runtimeInfo->GetData());
731 auto env = reinterpret_cast<napi_env>(JSNApi::GetEnv(vm));
732 auto engine = reinterpret_cast<NativeEngine*>(env);
733 auto cb = info->callback;
734 if (engine == nullptr) {
735 HILOG_ERROR("native engine is null");
736 return **JSValueRef::Undefined(vm);
737 }
738 uint64_t nestChainId = StartNapiProfilerTrace(runtimeInfo, reinterpret_cast<void *>(cb));
739 if (JSNApi::IsMixedDebugEnabled(vm)) {
740 JSNApi::NotifyNativeCalling(vm, reinterpret_cast<void *>(cb));
741 }
742
743 napi_value result = nullptr;
744 if (cb != nullptr) {
745 if constexpr (changeState) {
746 panda::JsiNativeScope nativeScope(vm);
747 result = cb(env, runtimeInfo);
748 } else {
749 result = cb(env, runtimeInfo);
750 }
751 }
752
753 if (JSNApi::IsMixedDebugEnabled(vm)) {
754 JSNApi::NotifyNativeReturn(vm, reinterpret_cast<void *>(cb));
755 }
756
757 Local<panda::JSValueRef> localRet = panda::JSValueRef::Undefined(vm);
758 if (result != nullptr) {
759 localRet = LocalValueFromJsValue(result);
760 }
761
762 FinishNapiProfilerTrace(nestChainId);
763 // Fixme: Rethrow error to engine while clear lastException_
764 if (!engine->lastException_.IsEmpty()) {
765 engine->lastException_.Empty();
766 }
767
768 if (localRet.IsEmpty()) {
769 return **JSValueRef::Undefined(vm);
770 }
771 if (getStackBeforeCallNapiSuccess) {
772 JSNApi::GetStackAfterCallNapi(vm);
773 }
774 return **localRet;
775 }
776
NapiNativeCreateFunction(napi_env env,const char * name,NapiNativeCallback cb,void * value)777 static Local<panda::JSValueRef> NapiNativeCreateFunction(napi_env env, const char* name,
778 NapiNativeCallback cb, void* value)
779 {
780 auto engine = reinterpret_cast<NativeEngine*>(env);
781 auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
782 NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
783 if (funcInfo == nullptr) {
784 HILOG_ERROR("funcInfo is nullptr");
785 return JSValueRef::Undefined(vm);
786 }
787 funcInfo->callback = cb;
788 funcInfo->data = value;
789 #ifdef ENABLE_CONTAINER_SCOPE
790 funcInfo->scopeId = OHOS::Ace::ContainerScope::CurrentId();
791 #endif
792
793 Local<panda::FunctionRef> fn = panda::FunctionRef::NewConcurrent(
794 vm, ArkNativeFunctionCallBack,
795 [](void* env, void* externalPointer, void* data) {
796 auto info = reinterpret_cast<NapiFunctionInfo*>(data);
797 if (info != nullptr) {
798 delete info;
799 }
800 },
801 reinterpret_cast<void*>(funcInfo), true
802 );
803 Local<panda::StringRef> fnName = panda::StringRef::NewFromUtf8(vm, name);
804 fn->SetName(vm, fnName);
805 return fn;
806 }
807
GetProperty(EcmaVM * vm,Local<panda::ObjectRef> & obj,const char * name)808 static Local<JSValueRef> GetProperty(EcmaVM* vm, Local<panda::ObjectRef> &obj, const char* name)
809 {
810 Local<StringRef> key = StringRef::NewFromUtf8(vm, name);
811 Local<JSValueRef> val = obj->Get(vm, key);
812 return val;
813 }
814
GetCString(EcmaVM * vm,Local<StringRef> str,char * buffer,size_t size,size_t * length)815 void GetCString(EcmaVM* vm, Local<StringRef> str, char* buffer, size_t size, size_t* length)
816 {
817 if (length == nullptr) {
818 return;
819 }
820 if (buffer == nullptr) {
821 *length = str->Utf8Length(vm, true) - 1;
822 } else if (size != 0) {
823 int copied = str->WriteUtf8(vm, buffer, size - 1, true) - 1;
824 buffer[copied] = '\0';
825 *length = copied;
826 } else {
827 *length = 0;
828 }
829 }
830
NapiGetModuleName(napi_env env,Local<panda::ObjectRef> & obj)831 std::string NapiGetModuleName(napi_env env, Local<panda::ObjectRef> &obj)
832 {
833 auto engine = reinterpret_cast<NativeEngine*>(env);
834 auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
835 std::string moduleName("");
836 auto nativeModuleName = GetProperty(vm, obj, PANDA_MODULE_NAME);
837 if (nativeModuleName->IsString(vm)) {
838 char arrayName[PANDA_MODULE_NAME_LEN] = {0};
839 size_t len = 0;
840 GetCString(vm, nativeModuleName, arrayName, PANDA_MODULE_NAME_LEN, &len);
841 moduleName += arrayName;
842 moduleName += ".";
843 }
844 return moduleName;
845 }
846
NapiDefinePropertyInner(napi_env env,Local<panda::ObjectRef> & obj,NapiPropertyDescriptor & propertyDescriptor,Local<panda::JSValueRef> & propertyName,bool & result)847 void NapiDefinePropertyInner(napi_env env,
848 Local<panda::ObjectRef> &obj,
849 NapiPropertyDescriptor &propertyDescriptor,
850 Local<panda::JSValueRef> &propertyName,
851 bool &result)
852 {
853 auto engine = reinterpret_cast<NativeEngine*>(env);
854 auto vm = engine->GetEcmaVm();
855 bool writable = (propertyDescriptor.attributes & NATIVE_WRITABLE) != 0;
856 bool enumable = (propertyDescriptor.attributes & NATIVE_ENUMERABLE) != 0;
857 bool configable = (propertyDescriptor.attributes & NATIVE_CONFIGURABLE) != 0;
858 std::string fullName("");
859 if (propertyDescriptor.getter != nullptr || propertyDescriptor.setter != nullptr) {
860 #ifdef ENABLE_HITRACE
861 fullName += NapiGetModuleName(env, obj);
862 #endif
863 Local<panda::JSValueRef> localGetter = panda::JSValueRef::Undefined(vm);
864 Local<panda::JSValueRef> localSetter = panda::JSValueRef::Undefined(vm);
865
866 if (propertyDescriptor.getter != nullptr) {
867 fullName += "getter";
868 localGetter = NapiNativeCreateFunction(env, fullName.c_str(),
869 propertyDescriptor.getter, propertyDescriptor.data);
870 }
871 if (propertyDescriptor.setter != nullptr) {
872 fullName += "setter";
873 localSetter = NapiNativeCreateFunction(env, fullName.c_str(),
874 propertyDescriptor.setter, propertyDescriptor.data);
875 }
876
877 PropertyAttribute attr(panda::JSValueRef::Undefined(vm), false, enumable, configable);
878 result = obj->SetAccessorProperty(vm, propertyName, localGetter, localSetter, attr);
879 } else if (propertyDescriptor.method != nullptr) {
880 #ifdef ENABLE_HITRACE
881 fullName += NapiGetModuleName(env, obj);
882 #endif
883 if (propertyDescriptor.utf8name != nullptr) {
884 fullName += propertyDescriptor.utf8name;
885 } else {
886 fullName += propertyName->IsString(vm)
887 ? Local<panda::StringRef>(propertyName)->ToString(vm)
888 : Local<panda::SymbolRef>(propertyName)->GetDescription(vm)->ToString(vm);
889 }
890 Local<panda::JSValueRef> cbObj = NapiNativeCreateFunction(env, fullName.c_str(),
891 propertyDescriptor.method, propertyDescriptor.data);
892 PropertyAttribute attr(cbObj, writable, enumable, configable);
893 result = obj->DefineProperty(vm, propertyName, attr);
894 } else {
895 Local<panda::JSValueRef> val = LocalValueFromJsValue(propertyDescriptor.value);
896
897 PropertyAttribute attr(val, writable, enumable, configable);
898 result = obj->DefineProperty(vm, propertyName, attr);
899 }
900 }
901
NapiDefineProperty(napi_env env,Local<panda::ObjectRef> & obj,NapiPropertyDescriptor propertyDescriptor)902 bool NapiDefineProperty(napi_env env, Local<panda::ObjectRef> &obj, NapiPropertyDescriptor propertyDescriptor)
903 {
904 auto engine = reinterpret_cast<NativeEngine*>(env);
905 auto vm = engine->GetEcmaVm();
906 bool result = false;
907 Local<panda::JSValueRef> propertyName;
908 if (propertyDescriptor.utf8name != nullptr) {
909 propertyName = panda::StringRef::NewFromUtf8(vm, propertyDescriptor.utf8name);
910 } else {
911 propertyName = LocalValueFromJsValue(propertyDescriptor.name);
912 }
913 if (obj->IsJSShared(vm)) {
914 NativeSendable::NapiDefineSendabledProperty(env, obj, propertyDescriptor, propertyName, result);
915 } else {
916 NapiDefinePropertyInner(env, obj, propertyDescriptor, propertyName, result);
917 }
918 Local<panda::ObjectRef> excep = panda::JSNApi::GetUncaughtException(vm);
919 if (!excep.IsNull()) {
920 HILOG_DEBUG("ArkNativeObject::DefineProperty occur Exception");
921 panda::JSNApi::GetAndClearUncaughtException(vm);
922 }
923 return result;
924 }
925
NapiCreateObjectWithProperties(napi_env env,size_t propertyCount,const napi_property_descriptor * properties,Local<panda::JSValueRef> * keys,PropertyAttribute * attrs)926 panda::Local<panda::ObjectRef> NapiCreateObjectWithProperties(napi_env env, size_t propertyCount,
927 const napi_property_descriptor *properties,
928 Local<panda::JSValueRef> *keys,
929 PropertyAttribute *attrs)
930 {
931 auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
932 panda::EscapeLocalScope scope(vm);
933 for (size_t i = 0; i < propertyCount; ++i) {
934 const napi_property_descriptor &property = properties[i];
935
936 const char* utf8name = property.utf8name;
937 uint32_t attributes = property.attributes;
938 bool writable = (attributes & NATIVE_WRITABLE) != 0;
939 bool enumable = (attributes & NATIVE_ENUMERABLE) != 0;
940 bool configable = (attributes & NATIVE_CONFIGURABLE) != 0;
941 NapiNativeCallback method = reinterpret_cast<NapiNativeCallback>(property.method);
942 NapiNativeCallback getter = reinterpret_cast<NapiNativeCallback>(property.getter);
943 NapiNativeCallback setter = reinterpret_cast<NapiNativeCallback>(property.setter);
944 napi_value value = property.value;
945 void *data = property.data;
946
947 Local<panda::JSValueRef> val = panda::JSValueRef::Undefined(vm);
948
949 std::string fullName("");
950 if (getter != nullptr || setter != nullptr) {
951 Local<panda::JSValueRef> localGetter = panda::JSValueRef::Undefined(vm);
952 Local<panda::JSValueRef> localSetter = panda::JSValueRef::Undefined(vm);
953
954 if (getter != nullptr) {
955 fullName += "getter";
956 localGetter = NapiNativeCreateFunction(env, fullName.c_str(), getter, data);
957 }
958 if (setter != nullptr) {
959 fullName += "setter";
960 localSetter = NapiNativeCreateFunction(env, fullName.c_str(), setter, data);
961 }
962
963 val = panda::ObjectRef::CreateAccessorData(vm, localGetter, localSetter);
964 writable = false;
965 } else if (method != nullptr) {
966 fullName += utf8name;
967 val = NapiNativeCreateFunction(env, fullName.c_str(), method, data);
968 } else {
969 val = LocalValueFromJsValue(value);
970 }
971 new (reinterpret_cast<void *>(&attrs[i])) PropertyAttribute(val, writable, enumable, configable);
972 keys[i] = panda::StringRef::NewFromUtf8(vm, utf8name);
973 }
974 Local<panda::ObjectRef> object = panda::ObjectRef::NewWithProperties(vm, propertyCount, keys, attrs);
975 return scope.Escape(object);
976 }
977
NapiCreateSObjectWithProperties(napi_env env,size_t propertyCount,const NapiPropertyDescriptor * properties)978 panda::Local<panda::ObjectRef> NapiCreateSObjectWithProperties(napi_env env,
979 size_t propertyCount,
980 const NapiPropertyDescriptor* properties)
981 {
982 auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
983 panda::EscapeLocalScope scope(vm);
984 FunctionRef::SendablePropertiesInfo info;
985 for (size_t i = 0; i < propertyCount; ++i) {
986 NativeSendable::InitSendablePropertiesInfo(env, info, properties[i]);
987 }
988 Local<panda::ObjectRef> object = panda::ObjectRef::NewSWithProperties(vm, info);
989 return scope.Escape(object);
990 }
991
GetModuleFromName(const std::string & moduleName,bool isAppModule,const std::string & id,const std::string & param,const std::string & instanceName,void ** instance)992 panda::Local<panda::ObjectRef> ArkNativeEngine::GetModuleFromName(
993 const std::string& moduleName, bool isAppModule, const std::string& id, const std::string& param,
994 const std::string& instanceName, void** instance)
995 {
996 panda::EscapeLocalScope scope(vm_);
997 Local<ObjectRef> exports(JSValueRef::Undefined(vm_));
998 NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
999 std::string errInfo = "";
1000 NativeModule* module = moduleManager->LoadNativeModule(moduleName.c_str(), nullptr, isAppModule, errInfo);
1001 if (module != nullptr) {
1002 Local<StringRef> idStr = StringRef::NewFromUtf8(vm_, id.c_str(), id.size());
1003 napi_value idValue = JsValueFromLocalValue(idStr);
1004 Local<StringRef> paramStr = StringRef::NewFromUtf8(vm_, param.c_str(), param.size());
1005 napi_value paramValue = JsValueFromLocalValue(paramStr);
1006 Local<ObjectRef> exportObj = ObjectRef::New(vm_);
1007 NapiPropertyDescriptor idProperty, paramProperty;
1008 idProperty.utf8name = "id";
1009 idProperty.value = idValue;
1010 paramProperty.utf8name = "param";
1011 paramProperty.value = paramValue;
1012 SetModuleName(exportObj, module->name);
1013 NapiDefineProperty(reinterpret_cast<napi_env>(this), exportObj, idProperty);
1014 NapiDefineProperty(reinterpret_cast<napi_env>(this), exportObj, paramProperty);
1015 MoudleNameLocker nameLocker(module->name);
1016 module->registerCallback(reinterpret_cast<napi_env>(this), JsValueFromLocalValue(exportObj));
1017 napi_value nExport = JsValueFromLocalValue(exportObj);
1018 napi_value exportInstance = nullptr;
1019 napi_status status = napi_get_named_property(
1020 reinterpret_cast<napi_env>(this), nExport, instanceName.c_str(), &exportInstance);
1021 if (status != napi_ok) {
1022 HILOG_ERROR("GetModuleFromName napi_get_named_property status != napi_ok");
1023 }
1024
1025 status = napi_unwrap(reinterpret_cast<napi_env>(this), exportInstance, reinterpret_cast<void**>(instance));
1026 if (status != napi_ok) {
1027 HILOG_ERROR("GetModuleFromName napi_unwrap status != napi_ok");
1028 }
1029 exports = exportObj;
1030 }
1031 return scope.Escape(exports);
1032 }
1033
CreatePromise(NativeDeferred ** deferred)1034 napi_value ArkNativeEngine::CreatePromise(NativeDeferred** deferred)
1035 {
1036 panda::EscapeLocalScope scope(vm_);
1037 Local<PromiseCapabilityRef> capability = PromiseCapabilityRef::New(vm_);
1038 *deferred = new ArkNativeDeferred(this, capability);
1039 Local<JSValueRef> promiseValue = capability->GetPromise(vm_);
1040 return JsValueFromLocalValue(scope.Escape(promiseValue));
1041 }
1042
LoadModuleByName(const std::string & moduleName,bool isAppModule,const std::string & param,const std::string & instanceName,void * instance,const std::string & path)1043 panda::Local<panda::ObjectRef> ArkNativeEngine::LoadModuleByName(const std::string& moduleName, bool isAppModule,
1044 const std::string& param, const std::string& instanceName, void* instance, const std::string& path)
1045 {
1046 panda::EscapeLocalScope scope(vm_);
1047 Local<ObjectRef> exports(JSValueRef::Undefined(vm_));
1048 NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
1049 std::string errInfo = "";
1050 NativeModule* module = moduleManager->LoadNativeModule(moduleName.c_str(),
1051 path.empty() ? nullptr : path.c_str(), isAppModule, errInfo);
1052 if (module != nullptr) {
1053 Local<ObjectRef> exportObj = ObjectRef::New(vm_);
1054 NapiPropertyDescriptor paramProperty, instanceProperty;
1055 Local<StringRef> paramStr = StringRef::NewFromUtf8(vm_, param.c_str(), param.size());
1056 napi_value paramValue = JsValueFromLocalValue(paramStr);
1057 paramProperty.utf8name = "param";
1058 paramProperty.value = paramValue;
1059 Local<ObjectRef> instanceValue = ObjectRef::New(vm_);
1060 Local<StringRef> key = StringRef::GetNapiWrapperString(vm_);
1061 if (instance == nullptr && instanceValue->Has(vm_, key)) {
1062 Local<ObjectRef> wrapper = instanceValue->Get(vm_, key);
1063 auto ref = reinterpret_cast<NativeReference*>(wrapper->GetNativePointerField(vm_, 0));
1064 wrapper->SetNativePointerField(vm_, 0, nullptr, nullptr, nullptr, 0);
1065 instanceValue->Delete(vm_, key);
1066 delete ref;
1067 } else {
1068 Local<ObjectRef> object = ObjectRef::New(vm_);
1069 NativeReference* ref = nullptr;
1070 Local<JSValueRef> value(instanceValue);
1071 ref = new ArkNativeReference(this, value, 0, true, nullptr, instance, nullptr);
1072
1073 object->SetNativePointerFieldCount(vm_, 1);
1074 object->SetNativePointerField(vm_, 0, ref, nullptr, nullptr, 0);
1075 PropertyAttribute attr(object, true, false, true);
1076 instanceValue->DefineProperty(vm_, key, attr);
1077 }
1078 instanceProperty.utf8name = instanceName.c_str();
1079 instanceProperty.value = JsValueFromLocalValue(instanceValue);
1080 SetModuleName(exportObj, module->name);
1081 NapiDefineProperty(reinterpret_cast<napi_env>(this), exportObj, paramProperty);
1082 NapiDefineProperty(reinterpret_cast<napi_env>(this), exportObj, instanceProperty);
1083
1084 MoudleNameLocker nameLocker(module->name);
1085 module->registerCallback(reinterpret_cast<napi_env>(this), JsValueFromLocalValue(exportObj));
1086 exports = exportObj;
1087 }
1088 return scope.Escape(exports);
1089 }
1090
Loop(LoopMode mode,bool needSync)1091 void ArkNativeEngine::Loop(LoopMode mode, bool needSync)
1092 {
1093 LocalScope scope(vm_);
1094 NativeEngine::Loop(mode, needSync);
1095 panda::JSNApi::ExecutePendingJob(vm_);
1096 }
1097
SetModuleName(Local<ObjectRef> & nativeObj,std::string moduleName)1098 void ArkNativeEngine::SetModuleName(Local<ObjectRef> &nativeObj, std::string moduleName)
1099 {
1100 #ifdef ENABLE_HITRACE
1101 if (ArkNativeEngine::napiProfilerEnabled) {
1102 Local<StringRef> moduleNameStr = StringRef::NewFromUtf8(vm_, moduleName.c_str(), moduleName.size());
1103 Local<StringRef> key = StringRef::NewFromUtf8(vm_, PANDA_MODULE_NAME);
1104 nativeObj->Set(vm_, key, moduleNameStr);
1105 }
1106 #endif
1107 }
1108
ConcurrentCallbackFunc(Local<JSValueRef> result,bool success,void * taskInfo,void * data)1109 static void ConcurrentCallbackFunc(Local<JSValueRef> result, bool success, void *taskInfo, void *data)
1110 {
1111 if (data == nullptr) {
1112 return;
1113 }
1114 auto engine = static_cast<ArkNativeEngine *>(data);
1115 auto concurrentCallbackFunc = engine->GetConcurrentCallbackFunc();
1116 if (concurrentCallbackFunc == nullptr) {
1117 return;
1118 }
1119 napi_env env = reinterpret_cast<napi_env>(engine);
1120 concurrentCallbackFunc(env, ArkNativeEngine::ArkValueToNapiValue(env, result), success, taskInfo);
1121 }
1122
InitTaskPoolThread(NativeEngine * engine,NapiConcurrentCallback callback)1123 bool ArkNativeEngine::InitTaskPoolThread(NativeEngine* engine, NapiConcurrentCallback callback)
1124 {
1125 concurrentCallbackFunc_ = callback;
1126 return JSNApi::InitForConcurrentThread(vm_, ConcurrentCallbackFunc, static_cast<void *>(this));
1127 }
1128
InitTaskPoolThread(napi_env env,NapiConcurrentCallback callback)1129 bool ArkNativeEngine::InitTaskPoolThread(napi_env env, NapiConcurrentCallback callback)
1130 {
1131 concurrentCallbackFunc_ = callback;
1132 return JSNApi::InitForConcurrentThread(vm_, ConcurrentCallbackFunc, static_cast<void *>(this));
1133 }
1134
InitTaskPoolFunc(napi_env env,napi_value func,void * taskInfo)1135 bool ArkNativeEngine::InitTaskPoolFunc(napi_env env, napi_value func, void* taskInfo)
1136 {
1137 LocalScope scope(vm_);
1138 Local<JSValueRef> function = LocalValueFromJsValue(func);
1139 return JSNApi::InitForConcurrentFunction(vm_, function, taskInfo);
1140 }
1141
HasPendingJob() const1142 bool ArkNativeEngine::HasPendingJob() const
1143 {
1144 return JSNApi::HasPendingJob(vm_);
1145 }
1146
IsProfiling() const1147 bool ArkNativeEngine::IsProfiling() const
1148 {
1149 return JSNApi::IsProfiling(vm_);
1150 }
1151
IsExecutingPendingJob() const1152 bool ArkNativeEngine::IsExecutingPendingJob() const
1153 {
1154 return panda::JSNApi::IsExecutingPendingJob(vm_);
1155 }
1156
GetCurrentTaskInfo() const1157 void* ArkNativeEngine::GetCurrentTaskInfo() const
1158 {
1159 return JSNApi::GetCurrentTaskInfo(vm_);
1160 }
1161
ClearCurrentTaskInfo()1162 void ArkNativeEngine::ClearCurrentTaskInfo()
1163 {
1164 JSNApi::ClearCurrentTaskInfo(vm_);
1165 }
1166
TerminateExecution() const1167 void ArkNativeEngine::TerminateExecution() const
1168 {
1169 DFXJSNApi::TerminateExecution(vm_);
1170 }
1171
NotifyTaskBegin() const1172 void ArkNativeEngine::NotifyTaskBegin() const
1173 {
1174 JSNApi::NotifyTaskBegin(vm_);
1175 }
1176
NotifyTaskFinished() const1177 void ArkNativeEngine::NotifyTaskFinished() const
1178 {
1179 JSNApi::NotifyTaskFinished(vm_);
1180 }
1181
CallFunction(napi_value thisVar,napi_value function,napi_value const * argv,size_t argc)1182 napi_value ArkNativeEngine::CallFunction(
1183 napi_value thisVar, napi_value function, napi_value const* argv, size_t argc)
1184 {
1185 if (function == nullptr) {
1186 return nullptr;
1187 }
1188 panda::EscapeLocalScope scope(vm_);
1189 Local<JSValueRef> thisObj = JSValueRef::Undefined(vm_);
1190 if (thisVar != nullptr) {
1191 thisObj = LocalValueFromJsValue(thisVar);
1192 }
1193 Local<FunctionRef> funcObj = LocalValueFromJsValue(function);
1194 std::vector<Local<JSValueRef>> args;
1195 args.reserve(argc);
1196 for (size_t i = 0; i < argc; i++) {
1197 if (argv[i] != nullptr) {
1198 args.emplace_back(LocalValueFromJsValue(argv[i]));
1199 } else {
1200 args.emplace_back(JSValueRef::Undefined(vm_));
1201 }
1202 }
1203
1204 Local<JSValueRef> value = funcObj->Call(vm_, thisObj, args.data(), argc);
1205 if (panda::JSNApi::HasPendingException(vm_)) {
1206 HILOG_ERROR("pending exception when js function called");
1207 HILOG_ERROR("print exception info: ");
1208 panda::JSNApi::PrintExceptionInfo(vm_);
1209 return nullptr;
1210 }
1211
1212 return JsValueFromLocalValue(scope.Escape(value));
1213 }
1214
NapiNewTypedArray(const EcmaVM * vm,NativeTypedArrayType typedArrayType,Local<panda::ArrayBufferRef> arrayBuf,size_t byte_offset,size_t length,napi_value * result)1215 bool ArkNativeEngine::NapiNewTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType,
1216 Local<panda::ArrayBufferRef> arrayBuf,
1217 size_t byte_offset, size_t length, napi_value* result)
1218 {
1219 Local<panda::TypedArrayRef> typedArray;
1220 switch (typedArrayType) {
1221 case NATIVE_INT8_ARRAY:
1222 typedArray = panda::Int8ArrayRef::New(vm, arrayBuf, byte_offset, length);
1223 break;
1224 case NATIVE_UINT8_ARRAY:
1225 typedArray = panda::Uint8ArrayRef::New(vm, arrayBuf, byte_offset, length);
1226 break;
1227 case NATIVE_UINT8_CLAMPED_ARRAY:
1228 typedArray = panda::Uint8ClampedArrayRef::New(vm, arrayBuf, byte_offset, length);
1229 break;
1230 case NATIVE_INT16_ARRAY:
1231 typedArray = panda::Int16ArrayRef::New(vm, arrayBuf, byte_offset, length);
1232 break;
1233 case NATIVE_UINT16_ARRAY:
1234 typedArray = panda::Uint16ArrayRef::New(vm, arrayBuf, byte_offset, length);
1235 break;
1236 case NATIVE_INT32_ARRAY:
1237 typedArray = panda::Int32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1238 break;
1239 case NATIVE_UINT32_ARRAY:
1240 typedArray = panda::Uint32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1241 break;
1242 case NATIVE_FLOAT32_ARRAY:
1243 typedArray = panda::Float32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1244 break;
1245 case NATIVE_FLOAT64_ARRAY:
1246 typedArray = panda::Float64ArrayRef::New(vm, arrayBuf, byte_offset, length);
1247 break;
1248 case NATIVE_BIGINT64_ARRAY:
1249 typedArray = panda::BigInt64ArrayRef::New(vm, arrayBuf, byte_offset, length);
1250 break;
1251 case NATIVE_BIGUINT64_ARRAY:
1252 typedArray = panda::BigUint64ArrayRef::New(vm, arrayBuf, byte_offset, length);
1253 break;
1254 default:
1255 *result = nullptr;
1256 return false;
1257 }
1258 *result = JsValueFromLocalValue(typedArray);
1259 return true;
1260 }
1261
NapiNewSendableTypedArray(const EcmaVM * vm,NativeTypedArrayType typedArrayType,Local<panda::SendableArrayBufferRef> arrayBuf,size_t byte_offset,size_t length,napi_value * result)1262 bool ArkNativeEngine::NapiNewSendableTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType,
1263 Local<panda::SendableArrayBufferRef> arrayBuf,
1264 size_t byte_offset, size_t length, napi_value* result)
1265 {
1266 Local<panda::SendableTypedArrayRef> typedArray;
1267 switch (typedArrayType) {
1268 case NATIVE_INT8_ARRAY:
1269 typedArray = panda::SharedInt8ArrayRef::New(vm, arrayBuf, byte_offset, length);
1270 break;
1271 case NATIVE_UINT8_ARRAY:
1272 typedArray = panda::SharedUint8ArrayRef::New(vm, arrayBuf, byte_offset, length);
1273 break;
1274 case NATIVE_INT16_ARRAY:
1275 typedArray = panda::SharedInt16ArrayRef::New(vm, arrayBuf, byte_offset, length);
1276 break;
1277 case NATIVE_UINT16_ARRAY:
1278 typedArray = panda::SharedUint16ArrayRef::New(vm, arrayBuf, byte_offset, length);
1279 break;
1280 case NATIVE_INT32_ARRAY:
1281 typedArray = panda::SharedInt32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1282 break;
1283 case NATIVE_UINT32_ARRAY:
1284 typedArray = panda::SharedUint32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1285 break;
1286 case NATIVE_FLOAT32_ARRAY:
1287 typedArray = panda::SharedFloat32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1288 break;
1289 case NATIVE_UINT8_CLAMPED_ARRAY:
1290 typedArray = panda::SharedUint8ClampedArrayRef::New(vm, arrayBuf, byte_offset, length);
1291 break;
1292 default:
1293 *result = nullptr;
1294 return false;
1295 }
1296 *result = JsValueFromLocalValue(typedArray);
1297 return true;
1298 }
1299
GetTypedArrayType(panda::Local<panda::TypedArrayRef> typedArray)1300 NativeTypedArrayType ArkNativeEngine::GetTypedArrayType(panda::Local<panda::TypedArrayRef> typedArray)
1301 {
1302 NativeTypedArrayType thisType = NATIVE_INT8_ARRAY;
1303 if (typedArray->IsInt8Array(vm_)) {
1304 thisType = NATIVE_INT8_ARRAY;
1305 } else if (typedArray->IsUint8Array(vm_)) {
1306 thisType = NATIVE_UINT8_ARRAY;
1307 } else if (typedArray->IsUint8ClampedArray(vm_)) {
1308 thisType = NATIVE_UINT8_CLAMPED_ARRAY;
1309 } else if (typedArray->IsInt16Array(vm_)) {
1310 thisType = NATIVE_INT16_ARRAY;
1311 } else if (typedArray->IsUint16Array(vm_)) {
1312 thisType = NATIVE_UINT16_ARRAY;
1313 } else if (typedArray->IsInt32Array(vm_)) {
1314 thisType = NATIVE_INT32_ARRAY;
1315 } else if (typedArray->IsUint32Array(vm_)) {
1316 thisType = NATIVE_UINT32_ARRAY;
1317 } else if (typedArray->IsFloat32Array(vm_)) {
1318 thisType = NATIVE_FLOAT32_ARRAY;
1319 } else if (typedArray->IsFloat64Array(vm_)) {
1320 thisType = NATIVE_FLOAT64_ARRAY;
1321 } else if (typedArray->IsBigInt64Array(vm_)) {
1322 thisType = NATIVE_BIGINT64_ARRAY;
1323 } else if (typedArray->IsBigUint64Array(vm_)) {
1324 thisType = NATIVE_BIGUINT64_ARRAY;
1325 }
1326
1327 return thisType;
1328 }
1329
GetSendableTypedArrayType(panda::Local<panda::SendableTypedArrayRef> typedArray)1330 NativeTypedArrayType ArkNativeEngine::GetSendableTypedArrayType(panda::Local<panda::SendableTypedArrayRef> typedArray)
1331 {
1332 NativeTypedArrayType thisType = NATIVE_INT8_ARRAY;
1333 if (typedArray->IsJSSharedInt8Array(vm_)) {
1334 thisType = NATIVE_INT8_ARRAY;
1335 } else if (typedArray->IsJSSharedUint8Array(vm_)) {
1336 thisType = NATIVE_UINT8_ARRAY;
1337 } else if (typedArray->IsJSSharedInt16Array(vm_)) {
1338 thisType = NATIVE_INT16_ARRAY;
1339 } else if (typedArray->IsJSSharedUint16Array(vm_)) {
1340 thisType = NATIVE_UINT16_ARRAY;
1341 } else if (typedArray->IsJSSharedInt32Array(vm_)) {
1342 thisType = NATIVE_INT32_ARRAY;
1343 } else if (typedArray->IsJSSharedUint32Array(vm_)) {
1344 thisType = NATIVE_UINT32_ARRAY;
1345 } else if (typedArray->IsJSSharedFloat32Array(vm_)) {
1346 thisType = NATIVE_FLOAT32_ARRAY;
1347 } else if (typedArray->IsJSSharedUint8ClampedArray(vm_)) {
1348 thisType = NATIVE_UINT8_CLAMPED_ARRAY;
1349 }
1350
1351 return thisType;
1352 }
1353
1354 /*
1355 * Before: input: 1. @ohos.hilog
1356 2. @system.app (NATIVE_MODULE contains this name)
1357 * After: return: 1.@ohos:hilog
1358 * 2.@native:system.app
1359 */
GetOhmurl(std::string path)1360 std::string ArkNativeEngine::GetOhmurl(std::string path)
1361 {
1362 const std::regex reg("@(ohos|system)\\.(\\S+)");
1363 path.erase(0, path.find_first_not_of(" "));
1364 path.erase(path.find_last_not_of(" ") + 1);
1365 bool ret = std::regex_match(path, reg);
1366 if (!ret) {
1367 HILOG_ERROR("ArkNativeEngine:The module name doesn't comply with the naming rules");
1368 return "";
1369 }
1370 std::string systemModule = path.substr(1);
1371 if (NATIVE_MODULE.count(systemModule)) {
1372 return NATIVE_MODULE_PREFIX + systemModule;
1373 } else {
1374 int pos = static_cast<int>(path.find('.'));
1375 std::string systemKey = path.substr(pos + 1, systemModule.size());
1376 return OHOS_MODULE_PREFIX + systemKey;
1377 }
1378 }
1379
NapiLoadNativeModule(std::string path)1380 Local<JSValueRef> ArkNativeEngine::NapiLoadNativeModule(std::string path)
1381 {
1382 std::string key = GetOhmurl(path);
1383 if (key.size() == 0) {
1384 return JSValueRef::Undefined(vm_);
1385 }
1386 return panda::JSNApi::ExecuteNativeModule(vm_, key);
1387 }
1388
CheckLoadType(const std::string & path)1389 ModuleTypes ArkNativeEngine::CheckLoadType(const std::string &path)
1390 {
1391 if (path[0] == '@') {
1392 return ModuleTypes::NATIVE_MODULE;
1393 } else if (path.find("ets/") == 0) { // ets/xxx/xxx
1394 return ModuleTypes::MODULE_INNER_FILE;
1395 }
1396 return ModuleTypes::UNKNOWN;
1397 }
1398
NapiLoadModule(const char * path,const char * module_info)1399 napi_value ArkNativeEngine::NapiLoadModule(const char* path, const char* module_info)
1400 {
1401 if (path == nullptr) {
1402 HILOG_ERROR("ArkNativeEngine:The module name is empty");
1403 return nullptr;
1404 }
1405 panda::EscapeLocalScope scope(vm_);
1406 Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
1407 Local<ObjectRef> exportObj(undefObj);
1408 std::string inputPath(path);
1409 std::string modulePath;
1410 if (module_info != nullptr) {
1411 modulePath = module_info;
1412 }
1413 switch (CheckLoadType(inputPath)) {
1414 case ModuleTypes::NATIVE_MODULE: {
1415 exportObj = NapiLoadNativeModule(inputPath);
1416 break;
1417 }
1418 case ModuleTypes::MODULE_INNER_FILE: {
1419 exportObj = panda::JSNApi::GetModuleNameSpaceFromFile(vm_, inputPath, modulePath);
1420 break;
1421 }
1422 default: {
1423 std::string msg = "ArkNativeEngine:NapiLoadModule input path:" + inputPath + " is invalid.";
1424 ThrowException(msg.c_str());
1425 }
1426 }
1427 if (!exportObj->IsObject(vm_)) {
1428 ThrowException("ArkNativeEngine:NapiLoadModule failed.");
1429 return JsValueFromLocalValue(scope.Escape(undefObj));
1430 }
1431 return JsValueFromLocalValue(scope.Escape(exportObj));
1432 }
1433
NapiLoadModuleWithInfo(const char * path,const char * module_info)1434 napi_value ArkNativeEngine::NapiLoadModuleWithInfo(const char* path, const char* module_info)
1435 {
1436 if (path == nullptr) {
1437 HILOG_ERROR("ArkNativeEngine:The module name is empty");
1438 return nullptr;
1439 }
1440 panda::EscapeLocalScope scope(vm_);
1441 Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
1442 Local<ObjectRef> exportObj(undefObj);
1443 std::string inputPath(path);
1444 std::string modulePath;
1445 if (module_info != nullptr) {
1446 modulePath = module_info;
1447 exportObj = panda::JSNApi::GetModuleNameSpaceWithModuleInfo(vm_, inputPath, modulePath);
1448 } else {
1449 exportObj = NapiLoadNativeModule(inputPath);
1450 }
1451
1452 if (!exportObj->IsObject(vm_)) {
1453 ThrowException("ArkNativeEngine:NapiLoadModuleWithInfo failed.");
1454 return JsValueFromLocalValue(scope.Escape(undefObj));
1455 }
1456 return JsValueFromLocalValue(scope.Escape(exportObj));
1457 }
1458
SuspendVMById(uint32_t tid)1459 bool ArkNativeEngine::SuspendVMById(uint32_t tid)
1460 {
1461 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
1462 return DFXJSNApi::SuspendVMById(vm_, tid);
1463 #else
1464 HILOG_WARN("ARK does not support dfx on windows");
1465 return false;
1466 #endif
1467 }
1468
ResumeVMById(uint32_t tid)1469 void ArkNativeEngine::ResumeVMById(uint32_t tid)
1470 {
1471 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
1472 DFXJSNApi::ResumeVMById(vm_, tid);
1473 #else
1474 HILOG_WARN("ARK does not support dfx on windows");
1475 return;
1476 #endif
1477 }
1478
SetPackagePath(const std::string appLibPathKey,const std::vector<std::string> & packagePath)1479 void ArkNativeEngine::SetPackagePath(const std::string appLibPathKey, const std::vector<std::string>& packagePath)
1480 {
1481 auto moduleManager = NativeModuleManager::GetInstance();
1482 if (moduleManager && !packagePath.empty()) {
1483 moduleManager->SetAppLibPath(appLibPathKey, packagePath);
1484 }
1485 }
1486
CreateInstance(napi_value constructor,napi_value const * argv,size_t argc)1487 napi_value ArkNativeEngine::CreateInstance(napi_value constructor, napi_value const *argv, size_t argc)
1488 {
1489 if (constructor == nullptr) {
1490 return nullptr;
1491 }
1492 panda::EscapeLocalScope scope(vm_);
1493 Local<FunctionRef> value = LocalValueFromJsValue(constructor);
1494 std::vector<Local<JSValueRef>> args;
1495 args.reserve(argc);
1496 for (size_t i = 0; i < argc; i++) {
1497 if (argv[i] != nullptr) {
1498 args.emplace_back(LocalValueFromJsValue(argv[i]));
1499 } else {
1500 args.emplace_back(JSValueRef::Undefined(vm_));
1501 }
1502 }
1503 Local<JSValueRef> instance = value->Constructor(vm_, args.data(), argc);
1504 Local<ObjectRef> excep = panda::JSNApi::GetUncaughtException(vm_);
1505 if (!excep.IsNull()) {
1506 HILOG_ERROR("ArkNativeEngineImpl::CreateInstance occur Exception");
1507 return nullptr;
1508 }
1509 return JsValueFromLocalValue(scope.Escape(instance));
1510 }
1511
CreateReference(napi_value value,uint32_t initialRefcount,bool flag,NapiNativeFinalize callback,void * data,void * hint,size_t nativeBindingSize)1512 NativeReference* ArkNativeEngine::CreateReference(napi_value value, uint32_t initialRefcount,
1513 bool flag, NapiNativeFinalize callback, void* data, void* hint, size_t nativeBindingSize)
1514 {
1515 return new ArkNativeReference(this, value, initialRefcount, flag, callback, data, hint, false, nativeBindingSize);
1516 }
1517
CreateAsyncReference(napi_value value,uint32_t initialRefcount,bool flag,NapiNativeFinalize callback,void * data,void * hint)1518 NativeReference* ArkNativeEngine::CreateAsyncReference(napi_value value, uint32_t initialRefcount,
1519 bool flag, NapiNativeFinalize callback, void* data, void* hint)
1520 {
1521 return new ArkNativeReference(this, value, initialRefcount, flag, callback, data, hint, true);
1522 }
1523
RunCallbacks(TriggerGCData * triggerGCData)1524 __attribute__((optnone)) void ArkNativeEngine::RunCallbacks(TriggerGCData *triggerGCData)
1525 {
1526 #ifdef ENABLE_HITRACE
1527 StartTrace(HITRACE_TAG_ACE, "RunTriggerGCTaskCallback");
1528 #endif
1529 std::pair<void *, uint8_t> ¶m = *triggerGCData;
1530 JSNApi::TriggerIdleGC(reinterpret_cast<panda::ecmascript::EcmaVM *>(param.first),
1531 static_cast<panda::JSNApi::TRIGGER_IDLE_GC_TYPE>(param.second));
1532 #ifdef ENABLE_HITRACE
1533 FinishTrace(HITRACE_TAG_ACE);
1534 #endif
1535 }
1536
RunCallbacks(ArkFinalizersPack * finalizersPack)1537 __attribute__((optnone)) void ArkNativeEngine::RunCallbacks(ArkFinalizersPack *finalizersPack)
1538 {
1539 #ifdef ENABLE_HITRACE
1540 StartTrace(HITRACE_TAG_ACE, "RunFinalizeCallbacks:" + std::to_string(finalizersPack->GetNumFinalizers()));
1541 #endif
1542 finalizersPack->ProcessAll();
1543 #ifdef ENABLE_HITRACE
1544 FinishTrace(HITRACE_TAG_ACE);
1545 #endif
1546 }
1547
RunAsyncCallbacks(std::vector<RefFinalizer> * finalizers)1548 __attribute__((optnone)) void ArkNativeEngine::RunAsyncCallbacks(std::vector<RefFinalizer> *finalizers)
1549 {
1550 #ifdef ENABLE_HITRACE
1551 StartTrace(HITRACE_TAG_ACE, "RunFinalizeCallbacks:" + std::to_string(finalizers->size()));
1552 #endif
1553 INIT_CRASH_HOLDER(holder);
1554 for (auto iter : (*finalizers)) {
1555 NapiNativeFinalize callback = iter.first;
1556 std::tuple<NativeEngine*, void*, void*> ¶m = iter.second;
1557 holder.UpdateCallbackPtr(reinterpret_cast<uintptr_t>(callback));
1558 callback(reinterpret_cast<napi_env>(std::get<0>(param)),
1559 std::get<1>(param), std::get<2>(param)); // 2 is the param.
1560 }
1561 #ifdef ENABLE_HITRACE
1562 FinishTrace(HITRACE_TAG_ACE);
1563 #endif
1564 }
1565
PostFinalizeTasks()1566 void ArkNativeEngine::PostFinalizeTasks()
1567 {
1568 if (IsInDestructor()) {
1569 return;
1570 }
1571 if (!pendingAsyncFinalizers_.empty()) {
1572 uv_work_t *asynWork = new uv_work_t;
1573 std::vector<RefFinalizer> *asyncFinalizers = new std::vector<RefFinalizer>();
1574 asyncFinalizers->swap(pendingAsyncFinalizers_);
1575 asynWork->data = reinterpret_cast<void *>(asyncFinalizers);
1576
1577 int ret = uv_queue_work_with_qos(GetUVLoop(), asynWork, [](uv_work_t *asynWork) {
1578 std::vector<RefFinalizer> *finalizers = reinterpret_cast<std::vector<RefFinalizer> *>(asynWork->data);
1579 RunAsyncCallbacks(finalizers);
1580 HILOG_DEBUG("uv_queue_work async running ");
1581 delete finalizers;
1582 }, [](uv_work_t *asynWork, int32_t) {
1583 delete asynWork;
1584 }, uv_qos_t(napi_qos_background));
1585 if (ret != 0) {
1586 HILOG_ERROR("uv_queue_work fail ret '%{public}d'", ret);
1587 RunAsyncCallbacks(asyncFinalizers);
1588 delete asynWork;
1589 delete asyncFinalizers;
1590 }
1591 }
1592 if (arkFinalizersPack_.Empty()) {
1593 return;
1594 }
1595 ArkFinalizersPack *finalizersPack = new ArkFinalizersPack();
1596 std::swap(arkFinalizersPack_, *finalizersPack);
1597 if (!IsMainThread()) {
1598 panda::JsiNativeScope nativeScope(vm_);
1599 RunCallbacks(finalizersPack);
1600 delete finalizersPack;
1601 return;
1602 }
1603 size_t bindingSize = finalizersPack->GetTotalNativeBindingSize();
1604 if (pendingFinalizersPackNativeBindingSize_ > FINALIZERS_PACK_PENDING_NATIVE_BINDING_SIZE_THRESHOLD &&
1605 bindingSize > 0) {
1606 HILOG_DEBUG("Pending Finalizers NativeBindingSize '%{public}zu' large than '%{public}zu', process sync.",
1607 pendingFinalizersPackNativeBindingSize_, FINALIZERS_PACK_PENDING_NATIVE_BINDING_SIZE_THRESHOLD);
1608 panda::JsiNativeScope nativeScope(vm_);
1609 RunCallbacks(finalizersPack);
1610 delete finalizersPack;
1611 return;
1612 }
1613 uv_work_t *syncWork = new uv_work_t;
1614 finalizersPack->RegisterFinishNotify([this] (size_t totalNativeBindingSize) {
1615 this->DecreasePendingFinalizersPackNativeBindingSize(totalNativeBindingSize);
1616 });
1617 IncreasePendingFinalizersPackNativeBindingSize(bindingSize);
1618
1619 syncWork->data = reinterpret_cast<void *>(finalizersPack);
1620 int ret = uv_queue_work_with_qos(GetUVLoop(), syncWork, [](uv_work_t *) {}, [](uv_work_t *syncWork, int32_t) {
1621 ArkFinalizersPack *finalizersPack = reinterpret_cast<ArkFinalizersPack*>(syncWork->data);
1622 RunCallbacks(finalizersPack);
1623 HILOG_DEBUG("uv_queue_work running");
1624 delete syncWork;
1625 delete finalizersPack;
1626 }, uv_qos_t(napi_qos_background));
1627 if (ret != 0) {
1628 HILOG_ERROR("uv_queue_work fail ret '%{public}d'", ret);
1629 panda::JsiNativeScope nativeScope(vm_);
1630 RunCallbacks(finalizersPack);
1631 delete syncWork;
1632 delete finalizersPack;
1633 }
1634 }
1635
RunCallbacks(AsyncNativeCallbacksPack * callbacksPack)1636 __attribute__((optnone)) void ArkNativeEngine::RunCallbacks(AsyncNativeCallbacksPack *callbacksPack)
1637 {
1638 #ifdef ENABLE_HITRACE
1639 StartTrace(HITRACE_TAG_ACE, "RunNativeCallbacks:" + std::to_string(callbacksPack->GetNumCallBacks()));
1640 #endif
1641 callbacksPack->ProcessAll();
1642 #ifdef ENABLE_HITRACE
1643 FinishTrace(HITRACE_TAG_ACE);
1644 #endif
1645 }
1646
PostAsyncTask(AsyncNativeCallbacksPack * callBacksPack)1647 void ArkNativeEngine::PostAsyncTask(AsyncNativeCallbacksPack *callBacksPack)
1648 {
1649 if (IsInDestructor()) {
1650 delete callBacksPack;
1651 return;
1652 }
1653 uv_work_t *syncWork = new uv_work_t;
1654 syncWork->data = reinterpret_cast<void *>(callBacksPack);
1655
1656 int ret = uv_queue_work_with_qos(GetUVLoop(), syncWork, [](uv_work_t *) {}, [](uv_work_t *syncWork, int32_t) {
1657 AsyncNativeCallbacksPack *finalizers = reinterpret_cast<AsyncNativeCallbacksPack*>(syncWork->data);
1658 RunCallbacks(finalizers);
1659 HILOG_DEBUG("uv_queue_work running");
1660 delete syncWork;
1661 delete finalizers;
1662 }, uv_qos_t(napi_qos_background));
1663 if (ret != 0) {
1664 HILOG_ERROR("uv_queue_work fail ret '%{public}d'", ret);
1665 panda::JsiNativeScope nativeScope(vm_);
1666 RunCallbacks(callBacksPack);
1667 delete callBacksPack;
1668 delete syncWork;
1669 }
1670 }
1671
PostTriggerGCTask(TriggerGCData & data)1672 void ArkNativeEngine::PostTriggerGCTask(TriggerGCData& data)
1673 {
1674 TriggerGCData *triggerGCData = new TriggerGCData(data);
1675 uv_work_t *syncWork = new uv_work_t;
1676 syncWork->data = reinterpret_cast<void *>(triggerGCData);
1677 int ret = uv_queue_work_with_qos(GetUVLoop(), syncWork, [](uv_work_t *) {}, [](uv_work_t *syncWork, int32_t) {
1678 auto triggerGCData = reinterpret_cast<TriggerGCData *>(syncWork->data);
1679 RunCallbacks(triggerGCData);
1680 delete syncWork;
1681 delete triggerGCData;
1682 }, uv_qos_t(napi_qos_user_initiated));
1683 if (ret != 0) {
1684 HILOG_ERROR("uv_queue_work fail ret '%{public}d'", ret);
1685 RunCallbacks(triggerGCData);
1686 delete syncWork;
1687 delete triggerGCData;
1688 }
1689 }
1690
1691 #if defined(OHOS_PLATFORM) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
SetAttribute(bool isLimitedWorker,panda::RuntimeOption & option)1692 void ArkNativeEngine::SetAttribute(bool isLimitedWorker, panda::RuntimeOption &option)
1693 {
1694 int arkProperties = OHOS::system::GetIntParameter<int>("persist.ark.properties", -1);
1695 std::string bundleName = OHOS::system::GetParameter("persist.ark.arkbundlename", "");
1696 std::string memConfigProperty = OHOS::system::GetParameter("persist.ark.mem_config_property", "");
1697 size_t gcThreadNum = OHOS::system::GetUintParameter<size_t>("persist.ark.gcthreads", 7);
1698 size_t longPauseTime = OHOS::system::GetUintParameter<size_t>("persist.ark.longpausetime", 40);
1699 bool asmInterpreterEnabled = OHOS::system::GetBoolParameter("persist.ark.asminterpreter", true);
1700 std::string asmOpcodeDisableRange = OHOS::system::GetParameter("persist.ark.asmopcodedisablerange", "");
1701 bool builtinsLazyEnabled = OHOS::system::GetBoolParameter("persist.ark.enablebuiltinslazy", true);
1702 option.SetEnableBuiltinsLazy(builtinsLazyEnabled);
1703 option.SetArkProperties(arkProperties);
1704 option.SetArkBundleName(bundleName);
1705 option.SetMemConfigProperty(memConfigProperty);
1706 option.SetGcThreadNum(gcThreadNum);
1707 option.SetLongPauseTime(longPauseTime);
1708 option.SetEnableAsmInterpreter(asmInterpreterEnabled);
1709 option.SetAsmOpcodeDisableRange(asmOpcodeDisableRange);
1710 option.SetIsWorker();
1711 option.SetIsRestrictedWorker(isLimitedWorker);
1712 HILOG_DEBUG("ArkNativeEngineImpl::CreateRuntimeFunc ark properties = %{public}d, bundlename = %{public}s",
1713 arkProperties, bundleName.c_str());
1714 }
1715 #endif
1716
CreateRuntimeFunc(NativeEngine * engine,void * jsEngine,bool isLimitedWorker)1717 NativeEngine* ArkNativeEngine::CreateRuntimeFunc(NativeEngine* engine, void* jsEngine, bool isLimitedWorker)
1718 {
1719 panda::RuntimeOption option;
1720 #if defined(OHOS_PLATFORM) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1721 SetAttribute(isLimitedWorker, option);
1722 #endif
1723 option.SetGcType(panda::RuntimeOption::GC_TYPE::GEN_GC);
1724 const int64_t poolSize = 0x1000000;
1725 option.SetGcPoolSize(poolSize);
1726 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
1727 option.SetLogLevel(panda::RuntimeOption::LOG_LEVEL::INFO);
1728 #endif
1729 option.SetDebuggerLibraryPath("");
1730 EcmaVM* vm = panda::JSNApi::CreateJSVM(option);
1731 if (vm == nullptr) {
1732 return nullptr;
1733 }
1734 // worker adaptation mergeabc
1735 const panda::ecmascript::EcmaVM* hostVM = reinterpret_cast<ArkNativeEngine*>(engine)->GetEcmaVm();
1736 panda::JSNApi::SynchronizVMInfo(vm, hostVM);
1737 ArkNativeEngine* arkEngine = new ArkNativeEngine(vm, jsEngine, isLimitedWorker);
1738 // init callback
1739 arkEngine->RegisterWorkerFunction(engine);
1740 arkEngine->SetHostEngine(engine);
1741 // sync apiVersion
1742 arkEngine->SetApiVersion(engine->GetApiVersion());
1743
1744 auto cleanEnv = [vm]() {
1745 if (vm != nullptr) {
1746 HILOG_DEBUG("cleanEnv is called");
1747 panda::JSNApi::DestroyJSVM(vm);
1748 }
1749 };
1750 arkEngine->SetCleanEnv(cleanEnv);
1751 if (hostVM != nullptr) {
1752 panda::JSNApi::AddWorker(const_cast<EcmaVM*>(hostVM), vm);
1753 }
1754 return arkEngine;
1755 }
1756
CreateRuntime(bool isLimitedWorker)1757 void* ArkNativeEngine::CreateRuntime(bool isLimitedWorker)
1758 {
1759 return ArkNativeEngine::CreateRuntimeFunc(this, jsEngine_, isLimitedWorker);
1760 }
1761
SetJsDumpThresholds(size_t thresholds)1762 void ArkNativeEngine::SetJsDumpThresholds(size_t thresholds)
1763 {
1764 DFXJSNApi::SetJsDumpThresholds(vm_, thresholds);
1765 }
1766
SetAppFreezeFilterCallback(AppFreezeFilterCallback callback)1767 void ArkNativeEngine::SetAppFreezeFilterCallback(AppFreezeFilterCallback callback)
1768 {
1769 DFXJSNApi::SetAppFreezeFilterCallback(vm_, callback);
1770 }
1771
StartCpuProfiler(const std::string & fileName)1772 void ArkNativeEngine::StartCpuProfiler(const std::string& fileName)
1773 {
1774 JSNApi::SetNativePtrGetter(vm_, reinterpret_cast<void*>(ArkNativeEngine::GetNativePtrCallBack));
1775 DFXJSNApi::StartCpuProfilerForFile(vm_, fileName);
1776 }
1777
StopCpuProfiler()1778 void ArkNativeEngine::StopCpuProfiler()
1779 {
1780 DFXJSNApi::StopCpuProfilerForFile(vm_);
1781 JSNApi::SetNativePtrGetter(vm_, nullptr);
1782 }
1783
ResumeVM()1784 void ArkNativeEngine::ResumeVM()
1785 {
1786 DFXJSNApi::ResumeVM(vm_);
1787 }
1788
SuspendVM()1789 bool ArkNativeEngine::SuspendVM()
1790 {
1791 return DFXJSNApi::SuspendVM(vm_);
1792 }
1793
IsSuspended()1794 bool ArkNativeEngine::IsSuspended()
1795 {
1796 return DFXJSNApi::IsSuspended(vm_);
1797 }
1798
CheckSafepoint()1799 bool ArkNativeEngine::CheckSafepoint()
1800 {
1801 return DFXJSNApi::CheckSafepoint(vm_);
1802 }
1803
GetCurrentModuleInfo(std::string & moduleName,std::string & fileName,bool needRecordName)1804 void ArkNativeEngine::GetCurrentModuleInfo(std::string& moduleName, std::string& fileName, bool needRecordName)
1805 {
1806 LocalScope scope(vm_);
1807 std::pair<std::string, std::string> moduleInfo = panda::JSNApi::GetCurrentModuleInfo(vm_, needRecordName);
1808 moduleName = moduleInfo.first; // if needRecordName is true, then moduleName is recordName.
1809 fileName = moduleInfo.second;
1810 }
1811
GetIsBundle()1812 bool ArkNativeEngine::GetIsBundle()
1813 {
1814 LocalScope scope(vm_);
1815 return panda::JSNApi::IsBundle(vm_);
1816 }
1817
GetIsNormalizedOhmUrlPack()1818 bool ArkNativeEngine::GetIsNormalizedOhmUrlPack()
1819 {
1820 LocalScope scope(vm_);
1821 return panda::JSNApi::IsNormalizedOhmUrlPack(vm_);
1822 }
1823
GetIsDebugModeEnabled()1824 bool ArkNativeEngine::GetIsDebugModeEnabled()
1825 {
1826 LocalScope scope(vm_);
1827 return panda::JSNApi::IsDebugModeEnabled(vm_);
1828 }
1829
GetBundleName()1830 std::string ArkNativeEngine::GetBundleName()
1831 {
1832 LocalScope scope(vm_);
1833 return panda::JSNApi::GetBundleName(vm_);
1834 }
1835
GetPkgName(const std::string & moduleName)1836 std::string ArkNativeEngine::GetPkgName(const std::string &moduleName)
1837 {
1838 LocalScope scope(vm_);
1839 return panda::JSNApi::GetPkgName(vm_, moduleName);
1840 }
1841
GetProcessStartRealTime()1842 int ArkNativeEngine::GetProcessStartRealTime()
1843 {
1844 LocalScope scope(vm_);
1845 return panda::JSNApi::GetStartRealTime(vm_);
1846 }
1847
IsExecuteModuleInAbcFile(std::string bundleName,std::string moduleName,std::string ohmurl)1848 bool ArkNativeEngine::IsExecuteModuleInAbcFile(std::string bundleName, std::string moduleName, std::string ohmurl)
1849 {
1850 LocalScope scope(vm_);
1851 return panda::JSNApi::IsExecuteModuleInAbcFile(vm_, bundleName, moduleName, ohmurl);
1852 }
1853
ValueToNapiValue(JSValueWrapper & value)1854 napi_value ArkNativeEngine::ValueToNapiValue(JSValueWrapper& value)
1855 {
1856 Global<JSValueRef> arkValue = value;
1857 return JsValueFromLocalValue(arkValue.ToLocal(vm_));
1858 }
1859
ArkValueToNapiValue(napi_env env,Local<JSValueRef> value)1860 napi_value ArkNativeEngine::ArkValueToNapiValue(napi_env env, Local<JSValueRef> value)
1861 {
1862 return JsValueFromLocalValue(value);
1863 }
1864
GetSourceCodeInfo(napi_value value,ErrorPos pos)1865 std::string ArkNativeEngine::GetSourceCodeInfo(napi_value value, ErrorPos pos)
1866 {
1867 if (value == nullptr || pos.first == 0) {
1868 return "";
1869 }
1870
1871 LocalScope scope(vm_);
1872 Local<panda::FunctionRef> func = LocalValueFromJsValue(value);
1873 uint32_t line = pos.first;
1874 uint32_t column = pos.second;
1875 Local<panda::StringRef> sourceCode = func->GetSourceCode(vm_, line);
1876 std::string sourceCodeStr = sourceCode->ToString(vm_);
1877 if (sourceCodeStr.empty()) {
1878 return "";
1879 }
1880 std::string sourceCodeInfo = "SourceCode:\n";
1881 sourceCodeInfo.append(sourceCodeStr).append("\n");
1882 for (uint32_t k = 1; k < column; k++) {
1883 sourceCodeInfo.push_back(' ');
1884 }
1885 sourceCodeInfo.append("^\n");
1886 return sourceCodeInfo;
1887 }
1888
TriggerFatalException(panda::Local<panda::JSValueRef> exceptionValue)1889 void ArkNativeEngine::TriggerFatalException(panda::Local<panda::JSValueRef> exceptionValue)
1890 {
1891 panda::JSNApi::ThrowException(GetEcmaVm(), exceptionValue);
1892 HandleUncaughtException();
1893 }
1894
AdjustExternalMemory(int64_t ChangeInBytes,int64_t * AdjustedValue)1895 bool ArkNativeEngine::AdjustExternalMemory(int64_t ChangeInBytes, int64_t* AdjustedValue)
1896 {
1897 return true;
1898 }
1899
SetPromiseRejectCallback(NativeReference * rejectCallbackRef,NativeReference * checkCallbackRef)1900 void ArkNativeEngine::SetPromiseRejectCallback(NativeReference* rejectCallbackRef, NativeReference* checkCallbackRef)
1901 {
1902 if (rejectCallbackRef == nullptr || checkCallbackRef == nullptr) {
1903 HILOG_ERROR("rejectCallbackRef or checkCallbackRef is nullptr");
1904 return;
1905 }
1906 promiseRejectCallbackRef_ = rejectCallbackRef;
1907 checkCallbackRef_ = checkCallbackRef;
1908 JSNApi::SetHostPromiseRejectionTracker(vm_, reinterpret_cast<void*>(PromiseRejectCallback),
1909 reinterpret_cast<void*>(this));
1910 }
1911
PromiseRejectCallback(void * info)1912 void ArkNativeEngine::PromiseRejectCallback(void* info)
1913 {
1914 panda::PromiseRejectInfo* promiseRejectInfo = reinterpret_cast<panda::PromiseRejectInfo*>(info);
1915 ArkNativeEngine* env = reinterpret_cast<ArkNativeEngine*>(promiseRejectInfo->GetData());
1916
1917 if (env == nullptr) {
1918 HILOG_ERROR("engine is nullptr");
1919 return;
1920 }
1921
1922 if (env->promiseRejectCallbackRef_ == nullptr || env->checkCallbackRef_ == nullptr) {
1923 HILOG_ERROR("promiseRejectCallbackRef or checkCallbackRef is nullptr");
1924 return;
1925 }
1926 panda::ecmascript::EcmaVM* vm = const_cast<EcmaVM*>(env->GetEcmaVm());
1927 LocalScope scope(vm);
1928 Local<JSValueRef> promise = promiseRejectInfo->GetPromise();
1929 Local<JSValueRef> reason = promiseRejectInfo->GetReason();
1930 panda::PromiseRejectInfo::PROMISE_REJECTION_EVENT operation = promiseRejectInfo->GetOperation();
1931
1932 Local<JSValueRef> type(IntegerRef::New(vm, static_cast<int32_t>(operation)));
1933
1934 Local<JSValueRef> args[] = {type, promise, reason};
1935
1936 napi_value promiseNapiRejectCallback = env->promiseRejectCallbackRef_->Get(env);
1937 Local<FunctionRef> promiseRejectCallback = LocalValueFromJsValue(promiseNapiRejectCallback);
1938 if (!promiseRejectCallback.IsEmpty()) {
1939 promiseRejectCallback->Call(vm, JSValueRef::Undefined(vm), args, 3); // 3 args size
1940 }
1941
1942 if (operation == panda::PromiseRejectInfo::PROMISE_REJECTION_EVENT::REJECT) {
1943 Local<JSValueRef> checkCallback = LocalValueFromJsValue(env->checkCallbackRef_->Get(env));
1944 if (!checkCallback.IsEmpty()) {
1945 JSNApi::SetHostEnqueueJob(vm, checkCallback, panda::QueueType::QUEUE_SCRIPT);
1946 }
1947 }
1948 }
1949
DumpHeapSnapshot(const std::string & path,bool isVmMode,DumpFormat dumpFormat,bool isPrivate,bool captureNumericValue)1950 void ArkNativeEngine::DumpHeapSnapshot(const std::string& path, bool isVmMode, DumpFormat dumpFormat,
1951 bool isPrivate, bool captureNumericValue)
1952 {
1953 panda::ecmascript::DumpSnapShotOption dumpOption;
1954 dumpOption.isVmMode = isVmMode;
1955 dumpOption.isSync = true;
1956 if (dumpFormat == DumpFormat::JSON) {
1957 dumpOption.dumpFormat = panda::ecmascript::DumpFormat::JSON;
1958 dumpOption.isPrivate = isPrivate;
1959 dumpOption.captureNumericValue = captureNumericValue;
1960 DFXJSNApi::DumpHeapSnapshot(vm_, path, dumpOption);
1961 }
1962 if (dumpFormat == DumpFormat::BINARY) {
1963 dumpOption.dumpFormat = panda::ecmascript::DumpFormat::BINARY;
1964 DFXJSNApi::DumpHeapSnapshot(vm_, path, dumpOption);
1965 }
1966 if (dumpFormat == DumpFormat::OTHER) {
1967 dumpOption.dumpFormat = panda::ecmascript::DumpFormat::OTHER;
1968 DFXJSNApi::DumpHeapSnapshot(vm_, path, dumpOption); // 2:enum is 2
1969 }
1970 }
1971
DumpCpuProfile()1972 void ArkNativeEngine::DumpCpuProfile()
1973 {
1974 DFXJSNApi::DumpCpuProfile(vm_);
1975 }
1976
DumpHeapSnapshot(bool isVmMode,DumpFormat dumpFormat,bool isPrivate,bool isFullGC)1977 void ArkNativeEngine::DumpHeapSnapshot(bool isVmMode, DumpFormat dumpFormat, bool isPrivate, bool isFullGC)
1978 {
1979 panda::ecmascript::DumpSnapShotOption dumpOption;
1980 dumpOption.isVmMode = isVmMode;
1981 dumpOption.isPrivate = isPrivate;
1982 dumpOption.isFullGC = isFullGC;
1983 dumpOption.isSync = false;
1984 if (dumpFormat == DumpFormat::JSON) {
1985 dumpOption.dumpFormat = panda::ecmascript::DumpFormat::JSON;
1986 DFXJSNApi::DumpHeapSnapshot(vm_, dumpOption);
1987 }
1988 if (dumpFormat == DumpFormat::BINARY) {
1989 dumpOption.dumpFormat = panda::ecmascript::DumpFormat::BINARY;
1990 DFXJSNApi::DumpHeapSnapshot(vm_, dumpOption);
1991 }
1992 if (dumpFormat == DumpFormat::OTHER) {
1993 dumpOption.dumpFormat = panda::ecmascript::DumpFormat::OTHER;
1994 DFXJSNApi::DumpHeapSnapshot(vm_, dumpOption);
1995 }
1996 }
1997
BuildNativeAndJsStackTrace(std::string & stackTraceStr)1998 bool ArkNativeEngine::BuildNativeAndJsStackTrace(std::string& stackTraceStr)
1999 {
2000 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
2001 return DFXJSNApi::BuildNativeAndJsStackTrace(vm_, stackTraceStr);
2002 #else
2003 HILOG_WARN("ARK does not support dfx on windows");
2004 return false;
2005 #endif
2006 }
2007
BuildJsStackTrace(std::string & stackTraceStr)2008 bool ArkNativeEngine::BuildJsStackTrace(std::string& stackTraceStr)
2009 {
2010 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
2011 return DFXJSNApi::BuildJsStackTrace(vm_, stackTraceStr);
2012 #else
2013 HILOG_WARN("ARK does not support dfx on windows");
2014 return false;
2015 #endif
2016 }
2017
BuildJsStackInfoListWithCustomDepth(std::vector<JsFrameInfo> & jsFrames)2018 bool ArkNativeEngine::BuildJsStackInfoListWithCustomDepth(std::vector<JsFrameInfo>& jsFrames)
2019 {
2020 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
2021 bool sign = DFXJSNApi::BuildJsStackInfoList(vm_, gettid(), jsFrames);
2022 return sign;
2023 #else
2024 HILOG_WARN("ARK does not support dfx on windows");
2025 return false;
2026 #endif
2027 }
2028
DeleteWorker(NativeEngine * workerEngine)2029 bool ArkNativeEngine::DeleteWorker(NativeEngine* workerEngine)
2030 {
2031 if (workerEngine != nullptr) {
2032 #if !defined(PREVIEW)
2033 const panda::ecmascript::EcmaVM* workerVM = reinterpret_cast<ArkNativeEngine*>(workerEngine)->GetEcmaVm();
2034 if (workerVM != nullptr) {
2035 return panda::JSNApi::DeleteWorker(vm_, const_cast<EcmaVM*>(workerVM));
2036 }
2037 #else
2038 HILOG_WARN("ARK does not support dfx on windows");
2039 #endif
2040 return false;
2041 }
2042 return false;
2043 }
2044
StartHeapTracking(double timeInterval,bool isVmMode)2045 bool ArkNativeEngine::StartHeapTracking(double timeInterval, bool isVmMode)
2046 {
2047 return DFXJSNApi::StartHeapTracking(vm_, timeInterval, isVmMode);
2048 }
2049
StopHeapTracking(const std::string & filePath)2050 bool ArkNativeEngine::StopHeapTracking(const std::string &filePath)
2051 {
2052 return DFXJSNApi::StopHeapTracking(vm_, filePath);
2053 }
2054
2055 #if !defined(PREVIEW)
PrintStatisticResult()2056 void ArkNativeEngine::PrintStatisticResult()
2057 {
2058 DFXJSNApi::PrintStatisticResult(vm_);
2059 }
2060
StartRuntimeStat()2061 void ArkNativeEngine::StartRuntimeStat()
2062 {
2063 DFXJSNApi::StartRuntimeStat(vm_);
2064 }
2065
StopRuntimeStat()2066 void ArkNativeEngine::StopRuntimeStat()
2067 {
2068 DFXJSNApi::StopRuntimeStat(vm_);
2069 }
2070
GetArrayBufferSize()2071 size_t ArkNativeEngine::GetArrayBufferSize()
2072 {
2073 return DFXJSNApi::GetArrayBufferSize(vm_);
2074 }
2075
GetHeapTotalSize()2076 size_t ArkNativeEngine::GetHeapTotalSize()
2077 {
2078 return DFXJSNApi::GetHeapTotalSize(vm_);
2079 }
2080
GetHeapUsedSize()2081 size_t ArkNativeEngine::GetHeapUsedSize()
2082 {
2083 return DFXJSNApi::GetHeapUsedSize(vm_);
2084 }
2085
GetHeapObjectSize()2086 size_t ArkNativeEngine::GetHeapObjectSize()
2087 {
2088 return DFXJSNApi::GetHeapObjectSize(vm_);
2089 }
2090
GetHeapLimitSize()2091 size_t ArkNativeEngine::GetHeapLimitSize()
2092 {
2093 return DFXJSNApi::GetHeapLimitSize(vm_);
2094 }
2095
GetProcessHeapLimitSize()2096 size_t ArkNativeEngine::GetProcessHeapLimitSize()
2097 {
2098 return DFXJSNApi::GetProcessHeapLimitSize();
2099 }
2100
GetGCCount()2101 size_t ArkNativeEngine::GetGCCount()
2102 {
2103 return DFXJSNApi::GetGCCount(vm_);
2104 }
2105
GetGCDuration()2106 size_t ArkNativeEngine::GetGCDuration()
2107 {
2108 return DFXJSNApi::GetGCDuration(vm_);
2109 }
2110
GetAccumulatedAllocateSize()2111 size_t ArkNativeEngine::GetAccumulatedAllocateSize()
2112 {
2113 return DFXJSNApi::GetAccumulatedAllocateSize(vm_);
2114 }
2115
GetAccumulatedFreeSize()2116 size_t ArkNativeEngine::GetAccumulatedFreeSize()
2117 {
2118 return DFXJSNApi::GetAccumulatedFreeSize(vm_);
2119 }
2120
GetFullGCLongTimeCount()2121 size_t ArkNativeEngine::GetFullGCLongTimeCount()
2122 {
2123 return DFXJSNApi::GetFullGCLongTimeCount(vm_);
2124 }
2125
NotifyApplicationState(bool inBackground)2126 void ArkNativeEngine::NotifyApplicationState(bool inBackground)
2127 {
2128 DFXJSNApi::NotifyApplicationState(vm_, inBackground);
2129 arkIdleMonitor_->NotifyChangeBackgroundState(inBackground);
2130 }
2131
NotifyIdleStatusControl(std::function<void (bool)> callback)2132 void ArkNativeEngine::NotifyIdleStatusControl(std::function<void(bool)> callback)
2133 {
2134 DFXJSNApi::NotifyIdleStatusControl(vm_, callback);
2135 }
2136
NotifyIdleTime(int idleMicroSec)2137 void ArkNativeEngine::NotifyIdleTime(int idleMicroSec)
2138 {
2139 DFXJSNApi::NotifyIdleTime(vm_, idleMicroSec);
2140 }
2141
NotifyMemoryPressure(bool inHighMemoryPressure)2142 void ArkNativeEngine::NotifyMemoryPressure(bool inHighMemoryPressure)
2143 {
2144 DFXJSNApi::NotifyMemoryPressure(vm_, inHighMemoryPressure);
2145 }
2146
NotifyForceExpandState(int32_t value)2147 void ArkNativeEngine::NotifyForceExpandState(int32_t value)
2148 {
2149 switch (ForceExpandState(value)) {
2150 case ForceExpandState::FINISH_COLD_START:
2151 DFXJSNApi::NotifyFinishColdStart(vm_, true);
2152 break;
2153 case ForceExpandState::START_HIGH_SENSITIVE:
2154 DFXJSNApi::NotifyHighSensitive(vm_, true);
2155 break;
2156 case ForceExpandState::FINISH_HIGH_SENSITIVE:
2157 DFXJSNApi::NotifyHighSensitive(vm_, false);
2158 break;
2159 default:
2160 HILOG_ERROR("Invalid Force Expand State: %{public}d.", value);
2161 break;
2162 }
2163 }
2164 #else
PrintStatisticResult()2165 void ArkNativeEngine::PrintStatisticResult()
2166 {
2167 HILOG_WARN("ARK does not support dfx on windows");
2168 }
2169
StartRuntimeStat()2170 void ArkNativeEngine::StartRuntimeStat()
2171 {
2172 HILOG_WARN("ARK does not support dfx on windows");
2173 }
2174
StopRuntimeStat()2175 void ArkNativeEngine::StopRuntimeStat()
2176 {
2177 HILOG_WARN("ARK does not support dfx on windows");
2178 }
2179
GetArrayBufferSize()2180 size_t ArkNativeEngine::GetArrayBufferSize()
2181 {
2182 HILOG_WARN("ARK does not support dfx on windows");
2183 return 0;
2184 }
2185
GetHeapTotalSize()2186 size_t ArkNativeEngine::GetHeapTotalSize()
2187 {
2188 HILOG_WARN("ARK does not support dfx on windows");
2189 return 0;
2190 }
2191
GetHeapUsedSize()2192 size_t ArkNativeEngine::GetHeapUsedSize()
2193 {
2194 HILOG_WARN("ARK does not support dfx on windows");
2195 return 0;
2196 }
2197
GetHeapObjectSize()2198 size_t ArkNativeEngine::GetHeapObjectSize()
2199 {
2200 HILOG_WARN("ARK does not support dfx on windows");
2201 return 0;
2202 }
2203
GetHeapLimitSize()2204 size_t ArkNativeEngine::GetHeapLimitSize()
2205 {
2206 HILOG_WARN("ARK does not support dfx on windows");
2207 return 0;
2208 }
2209
GetProcessHeapLimitSize()2210 size_t ArkNativeEngine::GetProcessHeapLimitSize()
2211 {
2212 HILOG_WARN("ARK does not support dfx on windows");
2213 return 0;
2214 }
2215
GetGCCount()2216 size_t ArkNativeEngine::GetGCCount()
2217 {
2218 HILOG_WARN("ARK does not support dfx on windows");
2219 return 0;
2220 }
2221
GetGCDuration()2222 size_t ArkNativeEngine::GetGCDuration()
2223 {
2224 HILOG_WARN("ARK does not support dfx on windows");
2225 return 0;
2226 }
2227
GetAccumulatedAllocateSize()2228 size_t ArkNativeEngine::GetAccumulatedAllocateSize()
2229 {
2230 HILOG_WARN("ARK does not support dfx on windows");
2231 return 0;
2232 }
2233
GetAccumulatedFreeSize()2234 size_t ArkNativeEngine::GetAccumulatedFreeSize()
2235 {
2236 HILOG_WARN("ARK does not support dfx on windows");
2237 return 0;
2238 }
2239
GetFullGCLongTimeCount()2240 size_t ArkNativeEngine::GetFullGCLongTimeCount()
2241 {
2242 HILOG_WARN("ARK does not support dfx on windows");
2243 return 0;
2244 }
2245
2246 void ArkNativeEngine::NotifyApplicationState([[maybe_unused]] bool inBackground)
2247 {
2248 HILOG_WARN("ARK does not support dfx on windows");
2249 }
2250
2251 void ArkNativeEngine::NotifyIdleStatusControl([[maybe_unused]] std::function<void(bool)> callback)
2252 {
2253 HILOG_WARN("ARK does not support dfx on windows");
2254 }
2255
2256 void ArkNativeEngine::NotifyIdleTime([[maybe_unused]] int idleMicroSec)
2257 {
2258 HILOG_WARN("ARK does not support dfx on windows");
2259 }
2260
2261 void ArkNativeEngine::NotifyMemoryPressure([[maybe_unused]] bool inHighMemoryPressure)
2262 {
2263 HILOG_WARN("ARK does not support dfx on windows");
2264 }
2265
2266 void ArkNativeEngine::NotifyForceExpandState([[maybe_unused]] int32_t value)
2267 {
2268 HILOG_WARN("ARK does not support dfx on windows");
2269 }
2270 #endif
2271
SetMockModuleList(const std::map<std::string,std::string> & list)2272 void ArkNativeEngine::SetMockModuleList(const std::map<std::string, std::string> &list)
2273 {
2274 JSNApi::SetMockModuleList(vm_, list);
2275 }
2276
RegisterNapiUncaughtExceptionHandler(NapiUncaughtExceptionCallback callback)2277 void ArkNativeEngine::RegisterNapiUncaughtExceptionHandler(NapiUncaughtExceptionCallback callback)
2278 {
2279 JSNApi::EnableUserUncaughtErrorHandler(vm_);
2280 napiUncaughtExceptionCallback_ = callback;
2281 }
2282
HandleUncaughtException()2283 void ArkNativeEngine::HandleUncaughtException()
2284 {
2285 if (napiUncaughtExceptionCallback_ == nullptr) {
2286 return;
2287 }
2288 LocalScope scope(vm_);
2289 lastException_.Empty();
2290 Local<ObjectRef> exception = JSNApi::GetAndClearUncaughtException(vm_);
2291 if (!exception.IsEmpty() && !exception->IsHole()) {
2292 if (napiUncaughtExceptionCallback_ != nullptr) {
2293 napiUncaughtExceptionCallback_(ArkValueToNapiValue(reinterpret_cast<napi_env>(this), exception));
2294 }
2295 }
2296 }
2297
HasPendingException()2298 bool ArkNativeEngine::HasPendingException()
2299 {
2300 return panda::JSNApi::HasPendingException(vm_);
2301 }
2302
RegisterPermissionCheck(PermissionCheckCallback callback)2303 void ArkNativeEngine::RegisterPermissionCheck(PermissionCheckCallback callback)
2304 {
2305 if (permissionCheckCallback_ == nullptr) {
2306 permissionCheckCallback_ = callback;
2307 }
2308 }
2309
ExecutePermissionCheck()2310 bool ArkNativeEngine::ExecutePermissionCheck()
2311 {
2312 if (permissionCheckCallback_ != nullptr) {
2313 return permissionCheckCallback_();
2314 } else {
2315 HILOG_INFO("permissionCheckCallback_ is still nullptr when executing permission check!");
2316 return true;
2317 }
2318 }
2319
RegisterTranslateBySourceMap(SourceMapCallback callback)2320 void ArkNativeEngine::RegisterTranslateBySourceMap(SourceMapCallback callback)
2321 {
2322 if (SourceMapCallback_ == nullptr) {
2323 SourceMapCallback_ = callback;
2324 }
2325 // regedit SourceMapCallback to ark_js_runtime
2326 panda::JSNApi::SetSourceMapCallback(vm_, callback);
2327 }
2328
RegisterSourceMapTranslateCallback(SourceMapTranslateCallback callback)2329 void ArkNativeEngine::RegisterSourceMapTranslateCallback(SourceMapTranslateCallback callback)
2330 {
2331 panda::JSNApi::SetSourceMapTranslateCallback(vm_, callback);
2332 }
2333
ExecuteTranslateBySourceMap(const std::string & rawStack)2334 std::string ArkNativeEngine::ExecuteTranslateBySourceMap(const std::string& rawStack)
2335 {
2336 if (SourceMapCallback_ != nullptr) {
2337 return SourceMapCallback_(rawStack);
2338 } else {
2339 HILOG_WARN("SourceMapCallback_ is nullptr.");
2340 return rawStack;
2341 }
2342 }
2343
IsMixedDebugEnabled()2344 bool ArkNativeEngine::IsMixedDebugEnabled()
2345 {
2346 return JSNApi::IsMixedDebugEnabled(vm_);
2347 }
2348
NotifyNativeCalling(const void * nativeAddress)2349 void ArkNativeEngine::NotifyNativeCalling(const void *nativeAddress)
2350 {
2351 JSNApi::NotifyNativeCalling(vm_, nativeAddress);
2352 }
2353
AllowCrossThreadExecution() const2354 void ArkNativeEngine::AllowCrossThreadExecution() const
2355 {
2356 JSNApi::AllowCrossThreadExecution(vm_);
2357 }
2358
2359 #if !defined(is_arkui_x) && defined(OHOS_PLATFORM)
DumpHybridStack(const EcmaVM * vm)2360 std::string DumpHybridStack(const EcmaVM* vm)
2361 {
2362 constexpr size_t skipframes = 5;
2363 auto unwinder = std::make_shared<OHOS::HiviewDFX::Unwinder>();
2364 std::vector<OHOS::HiviewDFX::DfxFrame> frames;
2365 unwinder->EnableMethodIdLocal(true);
2366 if (unwinder->UnwindLocal(false, false, DEFAULT_MAX_FRAME_NUM, skipframes)) {
2367 frames = unwinder->GetFrames();
2368 } else {
2369 HILOG_ERROR("Failed to unwind local");
2370 }
2371
2372 for (auto &frame : frames) {
2373 if (frame.isJsFrame) {
2374 DFXJSNApi::TranslateJSStackInfo(vm, frame.mapName, frame.line, frame.column);
2375 }
2376 }
2377
2378 return OHOS::HiviewDFX::Unwinder::GetFramesStr(frames);
2379 }
2380 #endif
2381
PostLooperTriggerIdleGCTask()2382 void ArkNativeEngine::PostLooperTriggerIdleGCTask()
2383 {
2384 #if defined(ENABLE_EVENT_HANDLER)
2385 std::shared_ptr<OHOS::AppExecFwk::EventRunner> mainThreadRunner =
2386 OHOS::AppExecFwk::EventRunner::GetMainEventRunner();
2387 if (mainThreadRunner.get() == nullptr) {
2388 HILOG_FATAL("ArkNativeEngine:: the mainEventRunner is nullptr");
2389 return;
2390 }
2391 std::weak_ptr<ArkIdleMonitor> weakArkIdleMonitor = arkIdleMonitor_;
2392 auto callback = [weakArkIdleMonitor](OHOS::AppExecFwk::EventRunnerStage stage,
2393 const OHOS::AppExecFwk::StageInfo* info) -> int {
2394 auto arkIdleMonitor = weakArkIdleMonitor.lock();
2395 if (nullptr == arkIdleMonitor) {
2396 HILOG_ERROR("ArkIdleMonitor has been destructed.");
2397 return 0;
2398 }
2399 switch (stage) {
2400 case OHOS::AppExecFwk::EventRunnerStage::STAGE_BEFORE_WAITING:
2401 arkIdleMonitor->NotifyLooperIdleStart(info->timestamp, info->sleepTime);
2402 break;
2403 case OHOS::AppExecFwk::EventRunnerStage::STAGE_AFTER_WAITING:
2404 arkIdleMonitor->NotifyLooperIdleEnd(info->timestamp);
2405 break;
2406 default:
2407 HILOG_ERROR("this branch is unreachable");
2408 }
2409 return 0;
2410 };
2411 uint32_t stage = (static_cast<uint32_t>(OHOS::AppExecFwk::EventRunnerStage::STAGE_BEFORE_WAITING) |
2412 static_cast<uint32_t>(OHOS::AppExecFwk::EventRunnerStage::STAGE_AFTER_WAITING));
2413 mainThreadRunner->GetEventQueue()->AddObserver(OHOS::AppExecFwk::Observer::ARKTS_GC, stage, callback);
2414 #endif
2415 }
2416
GetObjectHash(napi_env env,napi_value src)2417 int32_t ArkNativeEngine::GetObjectHash(napi_env env, napi_value src)
2418 {
2419 auto engine = reinterpret_cast<NativeEngine*>(env);
2420 auto vm = engine->GetEcmaVm();
2421 auto nativeValue = LocalValueFromJsValue(src);
2422 return DFXJSNApi::GetObjectHash(vm, nativeValue);
2423 }
2424 // LCOV_EXCL_STOP
2425
RunScriptPath(const char * path,bool checkPath)2426 bool ArkNativeEngine::RunScriptPath(const char* path, bool checkPath)
2427 {
2428 if (checkPath && !IsValidPandaFile(path)) {
2429 HILOG_ERROR("file is not exist or format is invalid");
2430 return false;
2431 }
2432 // LCOV_EXCL_START
2433 panda::JSExecutionScope executionScope(vm_);
2434 LocalScope scope(vm_);
2435 [[maybe_unused]] bool ret = panda::JSNApi::Execute(vm_, path, PANDA_MAIN_FUNCTION);
2436 if (panda::JSNApi::HasPendingException(vm_)) {
2437 HandleUncaughtException();
2438 return false;
2439 }
2440 // LCOV_EXCL_STOP
2441 return true;
2442 }
2443
IsValidPandaFile(const char * path)2444 bool ArkNativeEngine::IsValidPandaFile(const char* path)
2445 {
2446 if (path == nullptr) {
2447 HILOG_ERROR("file path is nullptr");
2448 return false;
2449 }
2450
2451 char filePath[PATH_MAX + 1] = { 0 };
2452 if (!RealPath(path, filePath, PATH_MAX + 1)) {
2453 HILOG_ERROR("failed to format path");
2454 return false;
2455 }
2456 struct stat fileStat;
2457 int ret = stat(filePath, &fileStat);
2458 if (ret != 0) {
2459 HILOG_ERROR("script file \"%{public}s\" is not exist", filePath);
2460 return false;
2461 }
2462
2463 if (!(fileStat.st_mode & S_IFREG)) {
2464 HILOG_ERROR("script path \"%{public}s\" is a directory", filePath);
2465 return false;
2466 }
2467 std::ifstream abcStream(filePath, std::ios::in | std::ios::binary);
2468
2469 constexpr size_t fileHeaderLength = sizeof(uint64_t);
2470 uint8_t fileHeader[fileHeaderLength] = { 0 };
2471 if (abcStream.is_open()) {
2472 size_t fileSize = fileStat.st_size;
2473 if (fileSize < fileHeaderLength) {
2474 HILOG_ERROR("faild to read file header, invalid format \"%{public}s\"", filePath);
2475 abcStream.close();
2476 return false;
2477 }
2478 abcStream.read(reinterpret_cast<char*>(fileHeader), fileHeaderLength);
2479 abcStream.close();
2480 return IsValidScriptBuffer(fileHeader, fileHeaderLength);
2481 }
2482 return false;
2483 }
2484
IsValidScriptBuffer(uint8_t * scriptBuffer,size_t bufferSize)2485 bool ArkNativeEngine::IsValidScriptBuffer(uint8_t* scriptBuffer, size_t bufferSize)
2486 {
2487 if (scriptBuffer == nullptr) {
2488 HILOG_ERROR("buffer is nullptr");
2489 return false;
2490 }
2491 constexpr size_t headerLen = sizeof(uint64_t);
2492 if (bufferSize < headerLen) {
2493 HILOG_ERROR("invalid buffer");
2494 return false;
2495 }
2496 constexpr char pandaFileHeader[headerLen] = "PANDA";
2497 const uint64_t bytePandaHeader = *reinterpret_cast<const uint64_t*>(pandaFileHeader);
2498 char fileHeader[headerLen] = { 0 };
2499 // Ensure destMax paramter is set correctly to avoid buffer overflows
2500 if (memcpy_s(fileHeader, sizeof(fileHeader), scriptBuffer, sizeof(fileHeader)) != 0) {
2501 HILOG_ERROR("faild to read file header of buffer");
2502 return false;
2503 }
2504
2505 uint64_t byteFileHeader = *reinterpret_cast<uint64_t*>(fileHeader);
2506 if (byteFileHeader != bytePandaHeader) {
2507 HILOG_ERROR("invalid format of file buffer");
2508 return false;
2509 }
2510 return true;
2511 }
2512
2513 // The security interface needs to be modified accordingly.
RunScriptBuffer(const char * path,std::vector<uint8_t> & buffer,bool isBundle)2514 napi_value ArkNativeEngine::RunScriptBuffer(const char* path, std::vector<uint8_t>& buffer, bool isBundle)
2515 {
2516 if (!IsValidScriptBuffer(buffer.data(), buffer.size())) {
2517 HILOG_ERROR("invalid script buffer");
2518 return nullptr;
2519 }
2520
2521 // LCOV_EXCL_START
2522 panda::EscapeLocalScope scope(vm_);
2523 [[maybe_unused]] bool ret = false;
2524 if (isBundle) {
2525 ret = panda::JSNApi::Execute(vm_, buffer.data(), buffer.size(), PANDA_MAIN_FUNCTION, path);
2526 } else {
2527 ret = panda::JSNApi::ExecuteModuleBuffer(vm_, buffer.data(), buffer.size(), path);
2528 }
2529
2530 if (panda::JSNApi::HasPendingException(vm_)) {
2531 HandleUncaughtException();
2532 return nullptr;
2533 }
2534 Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
2535 // LCOV_EXCL_STOP
2536 return JsValueFromLocalValue(scope.Escape(undefObj));
2537 }
2538
RunScriptBuffer(const std::string & path,uint8_t * buffer,size_t size,bool isBundle)2539 bool ArkNativeEngine::RunScriptBuffer(const std::string& path, uint8_t* buffer, size_t size, bool isBundle)
2540 {
2541 if (!IsValidScriptBuffer(buffer, size)) {
2542 HILOG_ERROR("invalid script buffer");
2543 return false;
2544 }
2545
2546 // LCOV_EXCL_START
2547 panda::JSExecutionScope executionScope(vm_);
2548 LocalScope scope(vm_);
2549 bool ret = false;
2550 if (isBundle) {
2551 ret = panda::JSNApi::ExecuteSecure(vm_, buffer, size, PANDA_MAIN_FUNCTION, path);
2552 } else {
2553 ret = panda::JSNApi::ExecuteModuleBufferSecure(vm_, buffer, size, path);
2554 }
2555
2556 if (panda::JSNApi::HasPendingException(vm_)) {
2557 HandleUncaughtException();
2558 return false;
2559 }
2560 return ret;
2561 // LCOV_EXCL_STOP
2562 }
2563
RunBufferScript(std::vector<uint8_t> & buffer)2564 napi_value ArkNativeEngine::RunBufferScript(std::vector<uint8_t>& buffer)
2565 {
2566 if (!IsValidScriptBuffer(buffer.data(), buffer.size())) {
2567 HILOG_ERROR("invalid script buffer");
2568 return nullptr;
2569 }
2570
2571 // LCOV_EXCL_START
2572 panda::EscapeLocalScope scope(vm_);
2573 [[maybe_unused]] bool ret = panda::JSNApi::Execute(vm_, buffer.data(), buffer.size(), PANDA_MAIN_FUNCTION);
2574
2575 if (panda::JSNApi::HasPendingException(vm_)) {
2576 HandleUncaughtException();
2577 return nullptr;
2578 }
2579 Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
2580 return JsValueFromLocalValue(scope.Escape(undefObj));
2581 // LCOV_EXCL_STOP
2582 }
2583
2584 #define EXECUTE_BUFFER(functionName) \
2585 if (panda::JSNApi::IsBundle(vm_)) { \
2586 /* FA doesn't enable securemem */ \
2587 ret = panda::JSNApi::Execute(vm_, buffer, bufferSize, PANDA_MAIN_FUNCTION, desc); \
2588 } else if (bufferSize != 0) { \
2589 if (entryPoint == nullptr) { \
2590 HILOG_DEBUG("Input entryPoint is nullptr, please input entryPoint for merged ESModule"); \
2591 /* this path for bundle and abc compiled by single module js */ \
2592 ret = panda::JSNApi::functionName(vm_, buffer, bufferSize, PANDA_MAIN_FUNCTION, desc); \
2593 } else { \
2594 /* this path for mergeabc with specific entryPoint */ \
2595 ret = panda::JSNApi::functionName(vm_, buffer, bufferSize, entryPoint, desc); \
2596 } \
2597 } else { \
2598 /* this path for worker */ \
2599 ret = panda::JSNApi::Execute(vm_, desc, PANDA_MAIN_FUNCTION); \
2600 }
2601
RunActor(uint8_t * buffer,size_t bufferSize,const char * descriptor,char * entryPoint,bool checkPath)2602 napi_value ArkNativeEngine::RunActor(uint8_t* buffer, size_t bufferSize,
2603 const char* descriptor, char* entryPoint, bool checkPath)
2604 {
2605 if (buffer == nullptr && descriptor == nullptr) {
2606 HILOG_ERROR("invalid param, both buffer and descriptor are nullptr");
2607 return nullptr;
2608 }
2609
2610 if ((buffer != nullptr && !IsValidScriptBuffer(buffer, bufferSize)) &&
2611 (checkPath && descriptor != nullptr && !IsValidPandaFile(descriptor))) {
2612 HILOG_ERROR("invalid param");
2613 return nullptr;
2614 }
2615
2616 // LCOV_EXCL_START
2617 panda::EscapeLocalScope scope(vm_);
2618 std::string desc(descriptor);
2619 [[maybe_unused]] bool ret = false;
2620 // if apiVersion > API11, use secure path.
2621 if (IsApplicationApiVersionAPI11Plus()) {
2622 EXECUTE_BUFFER(ExecuteSecure);
2623 } else {
2624 EXECUTE_BUFFER(Execute);
2625 }
2626 if (panda::JSNApi::HasPendingException(vm_)) {
2627 HandleUncaughtException();
2628 return nullptr;
2629 }
2630 Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
2631 return JsValueFromLocalValue(scope.Escape(undefObj));
2632 // LCOV_EXCL_STOP
2633 }
2634
LoadArkModule(const void * buffer,int32_t len,const std::string & fileName)2635 panda::Local<panda::ObjectRef> ArkNativeEngine::LoadArkModule(const void* buffer,
2636 int32_t len, const std::string& fileName)
2637 {
2638 panda::EscapeLocalScope scope(vm_);
2639 Local<ObjectRef> undefObj(JSValueRef::Undefined(vm_));
2640 if (buffer == nullptr || len <= 0 || fileName.empty()) {
2641 HILOG_ERROR("fileName is nullptr or source code is nullptr");
2642 return scope.Escape(undefObj);
2643 }
2644 if (!IsValidScriptBuffer(reinterpret_cast<uint8_t*>(const_cast<void*>(buffer)), len)) {
2645 HILOG_ERROR("invalid script buffer");
2646 return scope.Escape(undefObj);
2647 }
2648
2649 // LCOV_EXCL_START
2650 bool res = JSNApi::ExecuteModuleFromBuffer(vm_, buffer, len, fileName);
2651 if (!res) {
2652 HILOG_ERROR("Execute module failed");
2653 return scope.Escape(undefObj);
2654 }
2655
2656 Local<ObjectRef> exportObj = JSNApi::GetExportObjectFromBuffer(vm_, fileName, "default");
2657 if (exportObj->IsNull()) {
2658 HILOG_ERROR("Get export object failed");
2659 return scope.Escape(undefObj);
2660 }
2661
2662 HILOG_DEBUG("ArkNativeEngineImpl::LoadModule end");
2663 return scope.Escape(exportObj);
2664 // LCOV_EXCL_STOP
2665 }
2666
ExecuteJsBin(const std::string & fileName,bool checkPath)2667 bool ArkNativeEngine::ExecuteJsBin(const std::string& fileName, bool checkPath)
2668 {
2669 if (checkPath && !IsValidPandaFile(fileName.c_str())) {
2670 HILOG_ERROR("faild to execute js bin, file is not exist or format is invalid");
2671 return false;
2672 }
2673 // LCOV_EXCL_START
2674 panda::JSExecutionScope executionScope(vm_);
2675 LocalScope scope(vm_);
2676 bool ret = JSNApi::Execute(vm_, fileName, PANDA_MAIN_FUNCTION);
2677 return ret;
2678 // LCOV_EXCL_STOP
2679 }
2680