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