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