1 /* 2 * Copyright (c) 2021-2023 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 "jsnapi_helper.h" 17 18 #include <array> 19 #include <cstdint> 20 #include <fcntl.h> 21 #include <sys/types.h> 22 #include <unistd.h> 23 24 #include "ecmascript/base/builtins_base.h" 25 #include "ecmascript/base/json_parser.h" 26 #include "ecmascript/base/json_stringifier.h" 27 #include "ecmascript/base/path_helper.h" 28 #include "ecmascript/base/string_helper.h" 29 #include "ecmascript/base/typed_array_helper-inl.h" 30 #include "ecmascript/builtins/builtins_object.h" 31 #include "ecmascript/builtins/builtins_string.h" 32 #include "ecmascript/builtins/builtins_typedarray.h" 33 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER) 34 #include "ecmascript/dfx/cpu_profiler/cpu_profiler.h" 35 #endif 36 #include "ecmascript/byte_array.h" 37 #include "ecmascript/compiler/aot_file/an_file_data_manager.h" 38 #include "ecmascript/compiler/aot_file/aot_file_manager.h" 39 #include "ecmascript/debugger/js_debugger_manager.h" 40 #include "ecmascript/ecma_context.h" 41 #include "ecmascript/ecma_global_storage.h" 42 #include "ecmascript/ecma_runtime_call_info.h" 43 #include "ecmascript/ecma_string.h" 44 #include "ecmascript/ecma_vm.h" 45 #include "ecmascript/global_env.h" 46 #include "ecmascript/interpreter/fast_runtime_stub-inl.h" 47 #include "ecmascript/interpreter/frame_handler.h" 48 #include "ecmascript/jobs/micro_job_queue.h" 49 #include "ecmascript/js_array.h" 50 #include "ecmascript/js_arraybuffer.h" 51 #include "ecmascript/js_dataview.h" 52 #include "ecmascript/js_file_path.h" 53 #include "ecmascript/js_function.h" 54 #include "ecmascript/js_generator_object.h" 55 #include "ecmascript/js_iterator.h" 56 #include "ecmascript/js_map.h" 57 #include "ecmascript/js_map_iterator.h" 58 #include "ecmascript/js_primitive_ref.h" 59 #include "ecmascript/js_promise.h" 60 #include "ecmascript/js_regexp.h" 61 #include "ecmascript/js_runtime_options.h" 62 #include "ecmascript/js_serializer.h" 63 #include "ecmascript/js_set.h" 64 #include "ecmascript/js_set_iterator.h" 65 #include "ecmascript/js_tagged_number.h" 66 #include "ecmascript/js_thread.h" 67 #include "ecmascript/js_typed_array.h" 68 #include "ecmascript/jspandafile/debug_info_extractor.h" 69 #include "ecmascript/jspandafile/js_pandafile_executor.h" 70 #include "ecmascript/jspandafile/js_pandafile_manager.h" 71 #include "ecmascript/linked_hash_table.h" 72 #include "ecmascript/log.h" 73 #include "ecmascript/mem/mem.h" 74 #include "ecmascript/mem/mem_map_allocator.h" 75 #include "ecmascript/mem/region.h" 76 #include "ecmascript/module/js_module_manager.h" 77 #include "ecmascript/module/js_module_source_text.h" 78 #include "ecmascript/module/module_path_helper.h" 79 #include "ecmascript/object_factory.h" 80 #include "ecmascript/patch/quick_fix_manager.h" 81 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h" 82 #include "ecmascript/platform/file.h" 83 #include "ecmascript/regexp/regexp_parser.h" 84 #include "ecmascript/tagged_array.h" 85 #include "ecmascript/js_weak_container.h" 86 #ifdef ARK_SUPPORT_INTL 87 #include "ecmascript/js_bigint.h" 88 #include "ecmascript/js_collator.h" 89 #include "ecmascript/js_date_time_format.h" 90 #include "ecmascript/js_number_format.h" 91 #endif 92 93 #include "ohos/init_data.h" 94 95 #include "libpandabase/os/mutex.h" 96 97 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER) && defined(PANDA_TARGET_IOS) 98 namespace OHOS::ArkCompiler::Toolchain { 99 using DebuggerPostTask = std::function<void(std::function<void()> &&)>; 100 extern "C" { 101 bool StartDebug(const std::string& componentName, void* vm, bool isDebugMode, int32_t instanceId, 102 const DebuggerPostTask& debuggerPostTask, int port); 103 void StopDebug(const std::string& componentName); 104 } 105 } // namespace OHOS::ArkCompiler::Toolchain 106 const std::string DEBUGGER_NAME = "PandaDebugger"; 107 #endif 108 109 namespace panda { 110 using ecmascript::ECMAObject; 111 using ecmascript::EcmaString; 112 using ecmascript::EcmaStringAccessor; 113 using ecmascript::ErrorType; 114 using ecmascript::FastRuntimeStub; 115 using ecmascript::GlobalEnv; 116 using ecmascript::GlobalEnvConstants; 117 using ecmascript::EcmaRuntimeCallInfo; 118 using ecmascript::JSArray; 119 using ecmascript::JSArrayBuffer; 120 using ecmascript::JSDataView; 121 using ecmascript::ByteArray; 122 using ecmascript::JSDate; 123 using ecmascript::JSFunction; 124 using ecmascript::JSFunctionBase; 125 using ecmascript::JSHClass; 126 using ecmascript::JSMap; 127 using ecmascript::Method; 128 using ecmascript::JSNativePointer; 129 using ecmascript::JSObject; 130 using ecmascript::JSPandaFile; 131 using ecmascript::JSPandaFileManager; 132 using ecmascript::JSPrimitiveRef; 133 using ecmascript::JSPromise; 134 using ecmascript::JSRegExp; 135 using ecmascript::JSSerializer; 136 using ecmascript::JSSet; 137 using ecmascript::JSSymbol; 138 using ecmascript::JSTaggedNumber; 139 using ecmascript::JSTaggedType; 140 using ecmascript::JSTaggedValue; 141 using ecmascript::JSThread; 142 using ecmascript::LinkedHashMap; 143 using ecmascript::LinkedHashSet; 144 using ecmascript::ObjectFactory; 145 using ecmascript::PromiseCapability; 146 using ecmascript::PropertyDescriptor; 147 using ecmascript::OperationResult; 148 using ecmascript::Region; 149 using ecmascript::TaggedArray; 150 using ecmascript::JSTypedArray; 151 using ecmascript::base::BuiltinsBase; 152 using ecmascript::builtins::BuiltinsObject; 153 using ecmascript::base::JsonParser; 154 using ecmascript::base::JsonStringifier; 155 using ecmascript::base::StringHelper; 156 using ecmascript::base::TypedArrayHelper; 157 using ecmascript::job::MicroJobQueue; 158 using ecmascript::job::QueueType; 159 using ecmascript::JSRuntimeOptions; 160 using ecmascript::BigInt; 161 using ecmascript::MemMapAllocator; 162 using ecmascript::JSMapIterator; 163 using ecmascript::JSSetIterator; 164 using ecmascript::IterationKind; 165 using ecmascript::JSGeneratorState; 166 using ecmascript::JSIterator; 167 using ecmascript::JSGeneratorFunction; 168 using ecmascript::JSGeneratorObject; 169 using ecmascript::GeneratorContext; 170 using ecmascript::JSProxy; 171 #ifdef ARK_SUPPORT_INTL 172 using ecmascript::JSCollator; 173 using ecmascript::JSDateTimeFormat; 174 using ecmascript::JSNumberFormat; 175 #endif 176 using ecmascript::RegExpParser; 177 using ecmascript::DebugInfoExtractor; 178 using ecmascript::PatchErrorCode; 179 using ecmascript::base::NumberHelper; 180 using ecmascript::Log; 181 using ecmascript::EcmaContext; 182 using ecmascript::JSWeakMap; 183 using ecmascript::JSWeakSet; 184 template<typename T> 185 using JSHandle = ecmascript::JSHandle<T>; 186 187 template<typename T> 188 using JSMutableHandle = ecmascript::JSMutableHandle<T>; 189 190 using PathHelper = ecmascript::base::PathHelper; 191 using ModulePathHelper = ecmascript::ModulePathHelper; 192 193 namespace { 194 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects) 195 constexpr std::string_view ENTRY_POINTER = "_GLOBAL::func_main_0"; 196 } 197 int JSNApi::vmCount_ = 0; 198 bool JSNApi::initialize_ = false; 199 static os::memory::Mutex *mutex = new panda::os::memory::Mutex(); 200 #define XPM_PROC_PREFIX "/proc/" 201 #define XPM_PROC_SUFFIX "/xpm_region" 202 #define XPM_PROC_LENGTH 50 203 CheckSecureMem(uintptr_t mem)204 static bool CheckSecureMem(uintptr_t mem) 205 { 206 static bool hasOpen = false; 207 static uintptr_t secureMemStart = 0; 208 static uintptr_t secureMemEnd = 0; 209 if (!hasOpen) { 210 char procPath[XPM_PROC_LENGTH] = {0}; 211 pid_t pid = getpid(); 212 LOG_ECMA(DEBUG) << "Check secure memory in : " << pid << " with mem: " << std::hex << mem; 213 if (sprintf_s(procPath, XPM_PROC_LENGTH, "%s%d%s", XPM_PROC_PREFIX, pid, XPM_PROC_SUFFIX) <= 0) { 214 LOG_ECMA(ERROR) << "sprintf proc path failed"; 215 return false; 216 } 217 int fd = open(procPath, O_RDONLY); 218 if (fd < 0) { 219 LOG_ECMA(ERROR) << "Can not open xpm proc file, do not check secure memory anymore."; 220 // No verification is performed when a file fails to be opened. 221 hasOpen = true; 222 return true; 223 } 224 225 char xpmValidateRegion[XPM_PROC_LENGTH] = {0}; 226 int ret = read(fd, xpmValidateRegion, sizeof(xpmValidateRegion)); 227 if (ret <= 0) { 228 LOG_ECMA(ERROR) << "Read xpm proc file failed"; 229 close(fd); 230 return false; 231 } 232 close(fd); 233 234 if (sscanf_s(xpmValidateRegion, "%lx-%lx", &secureMemStart, &secureMemEnd) <= 0) { 235 LOG_ECMA(ERROR) << "sscanf_s xpm validate region failed"; 236 return false; 237 } 238 // The check is not performed when the file is already opened. 239 hasOpen = true; 240 } 241 242 // xpm proc does not exist, the read value is 0, and the check is not performed. 243 if (secureMemStart == 0 && secureMemEnd == 0) { 244 LOG_ECMA(ERROR) << "Secure memory check: xpm proc does not exist, do not check secure memory anymore."; 245 return true; 246 } 247 248 LOG_ECMA(DEBUG) << "Secure memory check in memory start: " << std::hex << secureMemStart 249 << " memory end: " << secureMemEnd; 250 if (mem < secureMemStart || mem >= secureMemEnd) { 251 LOG_ECMA(ERROR) << "Secure memory check failed, mem out of secure memory, mem: " << std::hex << mem; 252 return false; 253 } 254 return true; 255 } 256 257 #define CHECK_HAS_PENDING_EXCEPTION(vm, returnVal) \ 258 do { \ 259 if (vm->GetJSThread()->HasPendingException()) { \ 260 LOG_ECMA(ERROR) << "pending exception before jsnapi interface called" << \ 261 ", which is " << __FUNCTION__ << " in line: " << __LINE__; \ 262 LOG_ECMA(ERROR) << "print exception info:"; \ 263 JSNApi::PrintExceptionInfo(vm); \ 264 return returnVal; \ 265 } \ 266 } while (false) 267 268 #define CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm) \ 269 CHECK_HAS_PENDING_EXCEPTION(vm, JSValueRef::Undefined(vm)) 270 271 #define CHECK_HAS_PENDING_EXCEPTION_WITHOUT_RETURN(vm) \ 272 do { \ 273 if (vm->GetJSThread()->HasPendingException()) { \ 274 LOG_ECMA(ERROR) << "pending exception before jsnapi interface called" << \ 275 ", which is " << __FUNCTION__ << " in line: " << __LINE__; \ 276 LOG_ECMA(ERROR) << "print exception info:"; \ 277 JSNApi::PrintExceptionInfo(vm); \ 278 return; \ 279 } \ 280 } while (false) 281 282 // ------------------------------------ Panda ----------------------------------------------- CreateJSVM(const RuntimeOption & option)283 EcmaVM *JSNApi::CreateJSVM(const RuntimeOption &option) 284 { 285 JSRuntimeOptions runtimeOptions; 286 runtimeOptions.SetArkProperties(option.GetArkProperties()); 287 runtimeOptions.SetArkBundleName(option.GetArkBundleName()); 288 runtimeOptions.SetLongPauseTime(option.GetLongPauseTime()); 289 runtimeOptions.SetGcThreadNum(option.GetGcThreadNum()); 290 runtimeOptions.SetIsWorker(option.GetIsWorker()); 291 // Mem 292 runtimeOptions.SetHeapSizeLimit(option.GetGcPoolSize()); 293 // Disable the asm-interpreter of ark-engine for ios-platform temporarily. 294 #if !defined(PANDA_TARGET_IOS) 295 // asmInterpreter 296 runtimeOptions.SetEnableAsmInterpreter(option.GetEnableAsmInterpreter()); 297 #else 298 runtimeOptions.SetEnableAsmInterpreter(false); 299 #endif 300 runtimeOptions.SetEnableBuiltinsLazy(option.GetEnableBuiltinsLazy()); 301 runtimeOptions.SetAsmOpcodeDisableRange(option.GetAsmOpcodeDisableRange()); 302 // aot 303 runtimeOptions.SetEnableAOT(option.GetEnableAOT()); 304 runtimeOptions.SetEnablePGOProfiler(option.GetEnableProfile()); 305 runtimeOptions.SetPGOProfilerPath(option.GetProfileDir()); 306 307 // Dfx 308 runtimeOptions.SetLogLevel(Log::LevelToString(Log::ConvertFromRuntime(option.GetLogLevel()))); 309 runtimeOptions.SetEnableArkTools(option.GetEnableArkTools()); 310 return CreateEcmaVM(runtimeOptions); 311 } 312 CreateJSContext(EcmaVM * vm)313 EcmaContext *JSNApi::CreateJSContext(EcmaVM *vm) 314 { 315 JSThread *thread = vm->GetJSThread(); 316 return EcmaContext::CreateAndInitialize(thread); 317 } 318 SwitchCurrentContext(EcmaVM * vm,EcmaContext * context)319 void JSNApi::SwitchCurrentContext(EcmaVM *vm, EcmaContext *context) 320 { 321 JSThread *thread = vm->GetJSThread(); 322 thread->SwitchCurrentContext(context); 323 } 324 DestroyJSContext(EcmaVM * vm,EcmaContext * context)325 void JSNApi::DestroyJSContext(EcmaVM *vm, EcmaContext *context) 326 { 327 JSThread *thread = vm->GetJSThread(); 328 EcmaContext::CheckAndDestroy(thread, context); 329 } 330 CreateEcmaVM(const JSRuntimeOptions & options)331 EcmaVM *JSNApi::CreateEcmaVM(const JSRuntimeOptions &options) 332 { 333 { 334 os::memory::LockHolder lock(*mutex); 335 vmCount_++; 336 if (!initialize_) { 337 ecmascript::Log::Initialize(options); 338 InitializeIcuData(options); 339 InitializeMemMapAllocator(); 340 InitializePGOProfiler(options); 341 initialize_ = true; 342 } 343 } 344 auto config = ecmascript::EcmaParamConfiguration(options.IsWorker(), 345 MemMapAllocator::GetInstance()->GetCapacity()); 346 LOG_ECMA(DEBUG) << " [NAPI]: CreateEcmaVM, isWorker = " << options.IsWorker() << ", vmCount = " << vmCount_; 347 MemMapAllocator::GetInstance()->IncreaseAndCheckReserved(config.GetMaxHeapSize()); 348 return EcmaVM::Create(options, config); 349 } 350 DestroyJSVM(EcmaVM * ecmaVm)351 void JSNApi::DestroyJSVM(EcmaVM *ecmaVm) 352 { 353 os::memory::LockHolder lock(*mutex); 354 if (!initialize_) { 355 return; 356 } 357 auto &config = ecmaVm->GetEcmaParamConfiguration(); 358 MemMapAllocator::GetInstance()->DecreaseReserved(config.GetMaxHeapSize()); 359 EcmaVM::Destroy(ecmaVm); 360 vmCount_--; 361 if (vmCount_ <= 0) { 362 DestroyAnDataManager(); 363 DestroyMemMapAllocator(); 364 DestroyPGOProfiler(); 365 initialize_ = false; 366 } 367 } 368 TriggerGC(const EcmaVM * vm,TRIGGER_GC_TYPE gcType)369 void JSNApi::TriggerGC(const EcmaVM *vm, TRIGGER_GC_TYPE gcType) 370 { 371 if (vm->GetJSThread() != nullptr && vm->IsInitialized()) { 372 CHECK_HAS_PENDING_EXCEPTION_WITHOUT_RETURN(vm); 373 switch (gcType) { 374 case TRIGGER_GC_TYPE::SEMI_GC: 375 vm->CollectGarbage(vm->GetHeap()->SelectGCType(), ecmascript::GCReason::EXTERNAL_TRIGGER); 376 break; 377 case TRIGGER_GC_TYPE::OLD_GC: 378 vm->CollectGarbage(ecmascript::TriggerGCType::OLD_GC, ecmascript::GCReason::EXTERNAL_TRIGGER); 379 break; 380 case TRIGGER_GC_TYPE::FULL_GC: 381 vm->CollectGarbage(ecmascript::TriggerGCType::FULL_GC, ecmascript::GCReason::EXTERNAL_TRIGGER); 382 break; 383 default: 384 break; 385 } 386 } 387 } 388 ThrowException(const EcmaVM * vm,Local<JSValueRef> error)389 void JSNApi::ThrowException(const EcmaVM *vm, Local<JSValueRef> error) 390 { 391 auto thread = vm->GetJSThread(); 392 if (thread->HasPendingException()) { 393 LOG_ECMA(ERROR) << "An exception has already occurred before, keep old exception here."; 394 return; 395 } 396 thread->SetException(JSNApiHelper::ToJSTaggedValue(*error)); 397 } 398 PrintExceptionInfo(const EcmaVM * vm)399 void JSNApi::PrintExceptionInfo(const EcmaVM *vm) 400 { 401 JSThread* thread = vm->GetJSThread(); 402 [[maybe_unused]] ecmascript::EcmaHandleScope handleScope(thread); 403 404 if (!HasPendingException(vm)) { 405 return; 406 } 407 Local<ObjectRef> exception = GetAndClearUncaughtException(vm); 408 JSHandle<JSTaggedValue> exceptionHandle = JSNApiHelper::ToJSHandle(exception); 409 if (exceptionHandle->IsJSError()) { 410 vm->PrintJSErrorInfo(exceptionHandle); 411 ThrowException(vm, exception); 412 return; 413 } 414 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, exceptionHandle); 415 ecmascript::CString string = ConvertToString(*result); 416 LOG_ECMA(ERROR) << string; 417 ThrowException(vm, exception); 418 } 419 StartDebugger(EcmaVM * vm,const DebugOption & option,int32_t instanceId,const DebuggerPostTask & debuggerPostTask)420 bool JSNApi::StartDebugger([[maybe_unused]] EcmaVM *vm, [[maybe_unused]] const DebugOption &option, 421 [[maybe_unused]] int32_t instanceId, 422 [[maybe_unused]] const DebuggerPostTask &debuggerPostTask) 423 { 424 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER) 425 #if !defined(PANDA_TARGET_IOS) 426 if (vm == nullptr) { 427 return false; 428 } 429 CHECK_HAS_PENDING_EXCEPTION(vm, false); 430 const auto &handler = vm->GetJsDebuggerManager()->GetDebugLibraryHandle(); 431 if (handler.IsValid()) { 432 return false; 433 } 434 435 if (option.libraryPath == nullptr) { 436 return false; 437 } 438 auto handle = panda::os::library_loader::Load(std::string(option.libraryPath)); 439 if (!handle) { 440 return false; 441 } 442 443 using StartDebugger = bool (*)( 444 const std::string &, EcmaVM *, bool, int32_t, const DebuggerPostTask &, int); 445 446 auto sym = panda::os::library_loader::ResolveSymbol(handle.Value(), "StartDebug"); 447 if (!sym) { 448 LOG_ECMA(ERROR) << sym.Error().ToString(); 449 return false; 450 } 451 452 bool ret = reinterpret_cast<StartDebugger>(sym.Value())( 453 "PandaDebugger", vm, option.isDebugMode, instanceId, debuggerPostTask, option.port); 454 if (ret) { 455 vm->GetJsDebuggerManager()->SetDebugMode(option.isDebugMode); 456 vm->GetJsDebuggerManager()->SetDebugLibraryHandle(std::move(handle.Value())); 457 } 458 return ret; 459 #else 460 if (vm == nullptr) { 461 return false; 462 } 463 CHECK_HAS_PENDING_EXCEPTION(vm, false); 464 bool ret = OHOS::ArkCompiler::Toolchain::StartDebug( 465 DEBUGGER_NAME, vm, option.isDebugMode, instanceId, debuggerPostTask, option.port); 466 if (ret) { 467 vm->GetJsDebuggerManager()->SetDebugMode(option.isDebugMode); 468 } 469 return ret; 470 #endif // PANDA_TARGET_IOS 471 #else 472 LOG_ECMA(ERROR) << "Not support arkcompiler debugger"; 473 return false; 474 #endif // ECMASCRIPT_SUPPORT_DEBUGGER 475 } 476 StopDebugger(EcmaVM * vm)477 bool JSNApi::StopDebugger([[maybe_unused]] EcmaVM *vm) 478 { 479 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER) 480 #if !defined(PANDA_TARGET_IOS) 481 if (vm == nullptr) { 482 return false; 483 } 484 CHECK_HAS_PENDING_EXCEPTION(vm, false); 485 486 const auto &handle = vm->GetJsDebuggerManager()->GetDebugLibraryHandle(); 487 488 using StopDebug = void (*)(const std::string &); 489 490 auto sym = panda::os::library_loader::ResolveSymbol(handle, "StopDebug"); 491 if (!sym) { 492 LOG_ECMA(ERROR) << sym.Error().ToString(); 493 return false; 494 } 495 496 reinterpret_cast<StopDebug>(sym.Value())("PandaDebugger"); 497 498 vm->GetJsDebuggerManager()->SetDebugMode(false); 499 return true; 500 #else 501 if (vm == nullptr) { 502 return false; 503 } 504 CHECK_HAS_PENDING_EXCEPTION(vm, false); 505 506 OHOS::ArkCompiler::Toolchain::StopDebug(DEBUGGER_NAME); 507 vm->GetJsDebuggerManager()->SetDebugMode(false); 508 return true; 509 #endif // PANDA_TARGET_IOS 510 #else 511 LOG_ECMA(ERROR) << "Not support arkcompiler debugger"; 512 return false; 513 #endif // ECMASCRIPT_SUPPORT_DEBUGGER 514 } 515 IsMixedDebugEnabled(const EcmaVM * vm)516 bool JSNApi::IsMixedDebugEnabled([[maybe_unused]] const EcmaVM *vm) 517 { 518 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER) 519 CHECK_HAS_PENDING_EXCEPTION(vm, false); 520 return vm->GetJsDebuggerManager()->IsMixedDebugEnabled(); 521 #else 522 return false; 523 #endif 524 } 525 NotifyNativeCalling(const EcmaVM * vm,const void * nativeAddress)526 void JSNApi::NotifyNativeCalling([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const void *nativeAddress) 527 { 528 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER) 529 CHECK_HAS_PENDING_EXCEPTION_WITHOUT_RETURN(vm); 530 vm->GetJsDebuggerManager()->GetNotificationManager()->NativeCallingEvent(nativeAddress); 531 #else 532 LOG_ECMA(ERROR) << "Not support arkcompiler debugger"; 533 #endif 534 } 535 LoadAotFile(EcmaVM * vm,const std::string & moduleName)536 void JSNApi::LoadAotFile(EcmaVM *vm, const std::string &moduleName) 537 { 538 CHECK_HAS_PENDING_EXCEPTION_WITHOUT_RETURN(vm); 539 if (!ecmascript::AnFileDataManager::GetInstance()->IsEnable()) { 540 return; 541 } 542 std::string aotFileName = ecmascript::AnFileDataManager::GetInstance()->GetDir(); 543 aotFileName += moduleName; 544 LOG_ECMA(INFO) << "start to load aot file: " << aotFileName; 545 vm->GetJSThread()->GetCurrentEcmaContext()->LoadAOTFiles(aotFileName); 546 } 547 ExecuteInContext(EcmaVM * vm,const std::string & fileName,const std::string & entry,bool needUpdate)548 bool JSNApi::ExecuteInContext(EcmaVM *vm, const std::string &fileName, const std::string &entry, bool needUpdate) 549 { 550 LOG_ECMA(DEBUG) << "start to execute ark file in context: " << fileName; 551 JSThread *thread = vm->GetAssociatedJSThread(); 552 EcmaContext::MountContext(thread); 553 if (!ecmascript::JSPandaFileExecutor::ExecuteFromFile(thread, fileName.c_str(), entry, needUpdate)) { 554 LOG_ECMA(ERROR) << "Cannot execute ark file '" << fileName 555 << "' with entry '" << entry << "'" << std::endl; 556 return false; 557 } 558 EcmaContext::UnmountContext(thread); 559 return true; 560 } 561 Execute(EcmaVM * vm,const std::string & fileName,const std::string & entry,bool needUpdate)562 bool JSNApi::Execute(EcmaVM *vm, const std::string &fileName, const std::string &entry, bool needUpdate) 563 { 564 CHECK_HAS_PENDING_EXCEPTION(vm, false); 565 LOG_ECMA(DEBUG) << "start to execute ark file: " << fileName; 566 JSThread *thread = vm->GetAssociatedJSThread(); 567 if (!ecmascript::JSPandaFileExecutor::ExecuteFromFile(thread, fileName.c_str(), entry, needUpdate)) { 568 LOG_ECMA(ERROR) << "Cannot execute ark file '" << fileName 569 << "' with entry '" << entry << "'" << std::endl; 570 return false; 571 } 572 return true; 573 } 574 575 // The security interface needs to be modified accordingly. Execute(EcmaVM * vm,const uint8_t * data,int32_t size,const std::string & entry,const std::string & filename,bool needUpdate)576 bool JSNApi::Execute(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &entry, 577 const std::string &filename, bool needUpdate) 578 { 579 CHECK_HAS_PENDING_EXCEPTION(vm, false); 580 LOG_ECMA(DEBUG) << "start to execute ark buffer: " << filename; 581 JSThread *thread = vm->GetAssociatedJSThread(); 582 if (!ecmascript::JSPandaFileExecutor::ExecuteFromBuffer(thread, data, size, entry, filename.c_str(), needUpdate)) { 583 LOG_ECMA(ERROR) << "Cannot execute ark buffer file '" << filename 584 << "' with entry '" << entry << "'" << std::endl; 585 return false; 586 } 587 return true; 588 } 589 590 // The security interface needs to be modified accordingly. ExecuteModuleBuffer(EcmaVM * vm,const uint8_t * data,int32_t size,const std::string & filename,bool needUpdate)591 bool JSNApi::ExecuteModuleBuffer(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &filename, 592 bool needUpdate) 593 { 594 CHECK_HAS_PENDING_EXCEPTION(vm, false); 595 LOG_ECMA(DEBUG) << "start to execute module buffer: " << filename; 596 JSThread *thread = vm->GetAssociatedJSThread(); 597 if (!ecmascript::JSPandaFileExecutor::ExecuteModuleBuffer(thread, data, size, filename.c_str(), needUpdate)) { 598 LOG_ECMA(ERROR) << "Cannot execute module buffer file '" << filename; 599 return false; 600 } 601 return true; 602 } 603 ExecuteSecure(EcmaVM * vm,uint8_t * data,int32_t size,const std::string & entry,const std::string & filename,bool needUpdate)604 bool JSNApi::ExecuteSecure(EcmaVM *vm, uint8_t *data, int32_t size, const std::string &entry, 605 const std::string &filename, bool needUpdate) 606 { 607 LOG_ECMA(INFO) << "start to execute ark buffer with secure memory: " << filename; 608 if (!CheckSecureMem(reinterpret_cast<uintptr_t>(data))) { 609 LOG_ECMA(ERROR) << "Secure memory check failed, please execute in srcure memory."; 610 return false; 611 } 612 JSThread *thread = vm->GetAssociatedJSThread(); 613 if (!ecmascript::JSPandaFileExecutor::ExecuteFromBufferSecure(thread, data, size, entry, filename.c_str(), 614 needUpdate)) { 615 LOG_ECMA(ERROR) << "Cannot execute ark buffer file '" << filename 616 << "' with entry '" << entry << "'" << std::endl; 617 return false; 618 } 619 return true; 620 } 621 ExecuteModuleBufferSecure(EcmaVM * vm,uint8_t * data,int32_t size,const std::string & filename,bool needUpdate)622 bool JSNApi::ExecuteModuleBufferSecure(EcmaVM *vm, uint8_t* data, int32_t size, const std::string &filename, 623 bool needUpdate) 624 { 625 LOG_ECMA(INFO) << "start to execute module buffer with secure memory: " << filename; 626 if (!CheckSecureMem(reinterpret_cast<uintptr_t>(data))) { 627 LOG_ECMA(ERROR) << "Secure memory check failed, please execute in srcure memory."; 628 return false; 629 } 630 JSThread *thread = vm->GetAssociatedJSThread(); 631 if (!ecmascript::JSPandaFileExecutor::ExecuteModuleBufferSecure(thread, data, size, filename.c_str(), 632 needUpdate)) { 633 LOG_ECMA(ERROR) << "Cannot execute module buffer file '" << filename; 634 return false; 635 } 636 return true; 637 } 638 PreFork(EcmaVM * vm)639 void JSNApi::PreFork(EcmaVM *vm) 640 { 641 vm->PreFork(); 642 } 643 PostFork(EcmaVM * vm,const RuntimeOption & option)644 void JSNApi::PostFork(EcmaVM *vm, const RuntimeOption &option) 645 { 646 JSRuntimeOptions &jsOption = vm->GetJSOptions(); 647 LOG_ECMA(INFO) << "asmint: " << jsOption.GetEnableAsmInterpreter() 648 << ", aot: " << jsOption.GetEnableAOT() 649 << ", bundle name: " << option.GetBundleName(); 650 jsOption.SetEnablePGOProfiler(option.GetEnableProfile()); 651 vm->ResetPGOProfiler(); 652 JSRuntimeOptions runtimeOptions; 653 runtimeOptions.SetLogLevel(Log::LevelToString(Log::ConvertFromRuntime(option.GetLogLevel()))); 654 Log::Initialize(runtimeOptions); 655 656 if (jsOption.GetEnableAOT() && option.GetAnDir().size()) { 657 ecmascript::AnFileDataManager::GetInstance()->SetDir(option.GetAnDir()); 658 ecmascript::AnFileDataManager::GetInstance()->SetEnable(true); 659 } 660 661 vm->PostFork(); 662 } 663 addWorker(EcmaVM * hostVm,EcmaVM * workerVm)664 void JSNApi::addWorker(EcmaVM *hostVm, EcmaVM *workerVm) 665 { 666 if (hostVm != nullptr && workerVm != nullptr) { 667 hostVm->WorkersetInfo(hostVm, workerVm); 668 } 669 } 670 DeleteWorker(EcmaVM * hostVm,EcmaVM * workerVm)671 bool JSNApi::DeleteWorker(EcmaVM *hostVm, EcmaVM *workerVm) 672 { 673 if (hostVm != nullptr && workerVm != nullptr) { 674 return hostVm->DeleteWorker(hostVm, workerVm); 675 } 676 return false; 677 } 678 GetUncaughtException(const EcmaVM * vm)679 Local<ObjectRef> JSNApi::GetUncaughtException(const EcmaVM *vm) 680 { 681 return JSNApiHelper::ToLocal<ObjectRef>(vm->GetEcmaUncaughtException()); 682 } 683 GetAndClearUncaughtException(const EcmaVM * vm)684 Local<ObjectRef> JSNApi::GetAndClearUncaughtException(const EcmaVM *vm) 685 { 686 return JSNApiHelper::ToLocal<ObjectRef>(vm->GetAndClearEcmaUncaughtException()); 687 } 688 HasPendingException(const EcmaVM * vm)689 bool JSNApi::HasPendingException(const EcmaVM *vm) 690 { 691 return vm->GetJSThread()->HasPendingException(); 692 } 693 EnableUserUncaughtErrorHandler(EcmaVM * vm)694 void JSNApi::EnableUserUncaughtErrorHandler(EcmaVM *vm) 695 { 696 return vm->GetJSThread()->GetCurrentEcmaContext()->EnableUserUncaughtErrorHandler(); 697 } 698 GetGlobalObject(const EcmaVM * vm)699 Local<ObjectRef> JSNApi::GetGlobalObject(const EcmaVM *vm) 700 { 701 JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv(); 702 JSHandle<JSTaggedValue> global(vm->GetJSThread(), globalEnv->GetGlobalObject()); 703 return JSNApiHelper::ToLocal<ObjectRef>(global); 704 } 705 ExecutePendingJob(const EcmaVM * vm)706 void JSNApi::ExecutePendingJob(const EcmaVM *vm) 707 { 708 CHECK_HAS_PENDING_EXCEPTION_WITHOUT_RETURN(vm); 709 EcmaVM::ConstCast(vm)->GetJSThread()->GetCurrentEcmaContext()->ExecutePromisePendingJob(); 710 } 711 GetHandleAddr(const EcmaVM * vm,uintptr_t localAddress)712 uintptr_t JSNApi::GetHandleAddr(const EcmaVM *vm, uintptr_t localAddress) 713 { 714 if (localAddress == 0) { 715 return 0; 716 } 717 JSTaggedType value = *(reinterpret_cast<JSTaggedType *>(localAddress)); 718 return ecmascript::EcmaHandleScope::NewHandle(vm->GetJSThread(), value); 719 } 720 GetGlobalHandleAddr(const EcmaVM * vm,uintptr_t localAddress)721 uintptr_t JSNApi::GetGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress) 722 { 723 if (localAddress == 0) { 724 return 0; 725 } 726 JSTaggedType value = *(reinterpret_cast<JSTaggedType *>(localAddress)); 727 return vm->GetJSThread()->NewGlobalHandle(value); 728 } 729 SetWeak(const EcmaVM * vm,uintptr_t localAddress)730 uintptr_t JSNApi::SetWeak(const EcmaVM *vm, uintptr_t localAddress) 731 { 732 CHECK_HAS_PENDING_EXCEPTION(vm, 0); 733 if (localAddress == 0) { 734 return 0; 735 } 736 return vm->GetJSThread()->SetWeak(localAddress); 737 } 738 SetWeakCallback(const EcmaVM * vm,uintptr_t localAddress,void * ref,WeakRefClearCallBack freeGlobalCallBack,WeakRefClearCallBack nativeFinalizeCallback)739 uintptr_t JSNApi::SetWeakCallback(const EcmaVM *vm, uintptr_t localAddress, void *ref, 740 WeakRefClearCallBack freeGlobalCallBack, WeakRefClearCallBack nativeFinalizeCallback) 741 { 742 CHECK_HAS_PENDING_EXCEPTION(vm, 0); 743 if (localAddress == 0) { 744 return 0; 745 } 746 return vm->GetJSThread()->SetWeak(localAddress, ref, freeGlobalCallBack, nativeFinalizeCallback); 747 } 748 ClearWeak(const EcmaVM * vm,uintptr_t localAddress)749 uintptr_t JSNApi::ClearWeak(const EcmaVM *vm, uintptr_t localAddress) 750 { 751 CHECK_HAS_PENDING_EXCEPTION(vm, 0); 752 if (localAddress == 0) { 753 return 0; 754 } 755 if (JSTaggedValue(reinterpret_cast<ecmascript::Node *>(localAddress)->GetObject()) 756 .IsUndefined()) { 757 LOG_ECMA(ERROR) << "The object of weak reference has been recycled!"; 758 return 0; 759 } 760 return vm->GetJSThread()->ClearWeak(localAddress); 761 } 762 IsWeak(const EcmaVM * vm,uintptr_t localAddress)763 bool JSNApi::IsWeak(const EcmaVM *vm, uintptr_t localAddress) 764 { 765 CHECK_HAS_PENDING_EXCEPTION(vm, false); 766 if (localAddress == 0) { 767 return false; 768 } 769 return vm->GetJSThread()->IsWeak(localAddress); 770 } 771 DisposeGlobalHandleAddr(const EcmaVM * vm,uintptr_t addr)772 void JSNApi::DisposeGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr) 773 { 774 if (addr == 0 || !reinterpret_cast<ecmascript::Node *>(addr)->IsUsing()) { 775 return; 776 } 777 vm->GetJSThread()->DisposeGlobalHandle(addr); 778 } 779 SerializeValue(const EcmaVM * vm,Local<JSValueRef> value,Local<JSValueRef> transfer)780 void *JSNApi::SerializeValue(const EcmaVM *vm, Local<JSValueRef> value, Local<JSValueRef> transfer) 781 { 782 CHECK_HAS_PENDING_EXCEPTION(vm, nullptr); 783 ecmascript::JSThread *thread = vm->GetJSThread(); 784 ecmascript::Serializer serializer(thread); 785 JSHandle<JSTaggedValue> arkValue = JSNApiHelper::ToJSHandle(value); 786 JSHandle<JSTaggedValue> arkTransfer = JSNApiHelper::ToJSHandle(transfer); 787 std::unique_ptr<ecmascript::SerializationData> data; 788 if (serializer.WriteValue(thread, arkValue, arkTransfer)) { 789 data = serializer.Release(); 790 } 791 if (data == nullptr) { 792 return nullptr; 793 } else { 794 return reinterpret_cast<void *>(data.release()); 795 } 796 } 797 DeserializeValue(const EcmaVM * vm,void * recoder,void * hint)798 Local<JSValueRef> JSNApi::DeserializeValue(const EcmaVM *vm, void *recoder, void *hint) 799 { 800 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 801 ecmascript::JSThread *thread = vm->GetJSThread(); 802 std::unique_ptr<ecmascript::SerializationData> data(reinterpret_cast<ecmascript::SerializationData *>(recoder)); 803 ecmascript::Deserializer deserializer(thread, data.release(), hint); 804 JSHandle<JSTaggedValue> result = deserializer.ReadValue(); 805 return JSNApiHelper::ToLocal<ObjectRef>(result); 806 } 807 DeleteSerializationData(void * data)808 void JSNApi::DeleteSerializationData(void *data) 809 { 810 ecmascript::SerializationData *value = reinterpret_cast<ecmascript::SerializationData *>(data); 811 delete value; 812 value = nullptr; 813 } 814 HostPromiseRejectionTracker(const EcmaVM * vm,const JSHandle<JSPromise> promise,const JSHandle<JSTaggedValue> reason,const ecmascript::PromiseRejectionEvent operation,void * data)815 void HostPromiseRejectionTracker(const EcmaVM *vm, 816 const JSHandle<JSPromise> promise, 817 const JSHandle<JSTaggedValue> reason, 818 const ecmascript::PromiseRejectionEvent operation, 819 void* data) 820 { 821 CHECK_HAS_PENDING_EXCEPTION_WITHOUT_RETURN(vm); 822 ecmascript::PromiseRejectCallback promiseRejectCallback = 823 vm->GetJSThread()->GetCurrentEcmaContext()->GetPromiseRejectCallback(); 824 if (promiseRejectCallback != nullptr) { 825 Local<JSValueRef> promiseVal = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>::Cast(promise)); 826 PromiseRejectInfo promiseRejectInfo(promiseVal, JSNApiHelper::ToLocal<JSValueRef>(reason), 827 static_cast<PromiseRejectInfo::PROMISE_REJECTION_EVENT>(operation), data); 828 promiseRejectCallback(reinterpret_cast<void*>(&promiseRejectInfo)); 829 } 830 } 831 SetHostPromiseRejectionTracker(EcmaVM * vm,void * cb,void * data)832 void JSNApi::SetHostPromiseRejectionTracker(EcmaVM *vm, void *cb, void* data) 833 { 834 vm->GetJSThread()->GetCurrentEcmaContext()->SetHostPromiseRejectionTracker(HostPromiseRejectionTracker); 835 vm->GetJSThread()->GetCurrentEcmaContext()->SetPromiseRejectCallback( 836 reinterpret_cast<ecmascript::PromiseRejectCallback>(cb)); 837 vm->GetJSThread()->GetCurrentEcmaContext()->SetData(data); 838 } 839 SetHostResolveBufferTracker(EcmaVM * vm,std::function<bool (std::string dirPath,uint8_t ** buff,size_t * buffSize)> cb)840 void JSNApi::SetHostResolveBufferTracker(EcmaVM *vm, 841 std::function<bool(std::string dirPath, uint8_t **buff, size_t *buffSize)> cb) 842 { 843 vm->SetResolveBufferCallback(cb); 844 } 845 SetUnloadNativeModuleCallback(EcmaVM * vm,const std::function<bool (const std::string & moduleKey)> & cb)846 void JSNApi::SetUnloadNativeModuleCallback(EcmaVM *vm, const std::function<bool(const std::string &moduleKey)> &cb) 847 { 848 vm->SetUnloadNativeModuleCallback(cb); 849 } 850 SetNativePtrGetter(EcmaVM * vm,void * cb)851 void JSNApi::SetNativePtrGetter(EcmaVM *vm, void* cb) 852 { 853 vm->SetNativePtrGetter(reinterpret_cast<ecmascript::NativePtrGetter>(cb)); 854 } 855 SetHostEnqueueJob(const EcmaVM * vm,Local<JSValueRef> cb)856 void JSNApi::SetHostEnqueueJob(const EcmaVM *vm, Local<JSValueRef> cb) 857 { 858 CHECK_HAS_PENDING_EXCEPTION_WITHOUT_RETURN(vm); 859 JSHandle<JSFunction> fun = JSHandle<JSFunction>::Cast(JSNApiHelper::ToJSHandle(cb)); 860 JSHandle<TaggedArray> array = vm->GetFactory()->EmptyArray(); 861 JSHandle<MicroJobQueue> job = vm->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue(); 862 MicroJobQueue::EnqueueJob(vm->GetJSThread(), job, QueueType::QUEUE_PROMISE, fun, array); 863 } 864 PromiseRejectInfo(Local<JSValueRef> promise,Local<JSValueRef> reason,PromiseRejectInfo::PROMISE_REJECTION_EVENT operation,void * data)865 PromiseRejectInfo::PromiseRejectInfo(Local<JSValueRef> promise, Local<JSValueRef> reason, 866 PromiseRejectInfo::PROMISE_REJECTION_EVENT operation, void* data) 867 : promise_(promise), reason_(reason), operation_(operation), data_(data) {} 868 GetPromise() const869 Local<JSValueRef> PromiseRejectInfo::GetPromise() const 870 { 871 return promise_; 872 } 873 GetReason() const874 Local<JSValueRef> PromiseRejectInfo::GetReason() const 875 { 876 return reason_; 877 } 878 GetOperation() const879 PromiseRejectInfo::PROMISE_REJECTION_EVENT PromiseRejectInfo::GetOperation() const 880 { 881 return operation_; 882 } 883 GetData() const884 void* PromiseRejectInfo::GetData() const 885 { 886 return data_; 887 } 888 ExecuteModuleFromBuffer(EcmaVM * vm,const void * data,int32_t size,const std::string & file)889 bool JSNApi::ExecuteModuleFromBuffer(EcmaVM *vm, const void *data, int32_t size, const std::string &file) 890 { 891 CHECK_HAS_PENDING_EXCEPTION(vm, false); 892 JSThread *thread = vm->GetAssociatedJSThread(); 893 if (!ecmascript::JSPandaFileExecutor::ExecuteFromBuffer(thread, data, size, ENTRY_POINTER, file.c_str())) { 894 std::cerr << "Cannot execute panda file from memory" << std::endl; 895 return false; 896 } 897 return true; 898 } 899 GetExportObject(EcmaVM * vm,const std::string & file,const std::string & key)900 Local<ObjectRef> JSNApi::GetExportObject(EcmaVM *vm, const std::string &file, const std::string &key) 901 { 902 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 903 ecmascript::CString entry = file.c_str(); 904 JSThread *thread = vm->GetJSThread(); 905 ecmascript::CString name = vm->GetAssetPath(); 906 if (!vm->IsBundlePack()) { 907 ModulePathHelper::ParseOhmUrl(vm, entry, name, entry); 908 std::shared_ptr<JSPandaFile> jsPandaFile = 909 JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, name, entry.c_str(), false); 910 if (jsPandaFile == nullptr) { 911 JSHandle<JSTaggedValue> exportObj(thread, JSTaggedValue::Null()); 912 return JSNApiHelper::ToLocal<ObjectRef>(exportObj); 913 } 914 if (!jsPandaFile->IsRecordWithBundleName()) { 915 PathHelper::AdaptOldIsaRecord(entry); 916 } 917 } 918 ecmascript::ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); 919 JSHandle<ecmascript::SourceTextModule> ecmaModule = moduleManager->HostGetImportedModule(entry); 920 if (ecmaModule->GetIsNewBcVersion()) { 921 int index = ecmascript::ModuleManager::GetExportObjectIndex(vm, ecmaModule, key); 922 JSTaggedValue result = ecmaModule->GetModuleValue(thread, index, false); 923 JSHandle<JSTaggedValue> exportObj(thread, result); 924 return JSNApiHelper::ToLocal<ObjectRef>(exportObj); 925 } 926 ObjectFactory *factory = vm->GetFactory(); 927 JSHandle<EcmaString> keyHandle = factory->NewFromASCII(key.c_str()); 928 929 JSTaggedValue result = ecmaModule->GetModuleValue(thread, keyHandle.GetTaggedValue(), false); 930 JSHandle<JSTaggedValue> exportObj(thread, result); 931 return JSNApiHelper::ToLocal<ObjectRef>(exportObj); 932 } 933 GetExportObjectFromBuffer(EcmaVM * vm,const std::string & file,const std::string & key)934 Local<ObjectRef> JSNApi::GetExportObjectFromBuffer(EcmaVM *vm, const std::string &file, 935 const std::string &key) 936 { 937 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 938 JSThread *thread = vm->GetJSThread(); 939 ecmascript::ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); 940 JSHandle<ecmascript::SourceTextModule> ecmaModule = moduleManager->HostGetImportedModule(file.c_str()); 941 942 if (ecmaModule->GetIsNewBcVersion()) { 943 int index = ecmascript::ModuleManager::GetExportObjectIndex(vm, ecmaModule, key); 944 JSTaggedValue result = ecmaModule->GetModuleValue(thread, index, false); 945 JSHandle<JSTaggedValue> exportObj(thread, result); 946 return JSNApiHelper::ToLocal<ObjectRef>(exportObj); 947 } 948 949 ObjectFactory *factory = vm->GetFactory(); 950 JSHandle<EcmaString> keyHandle = factory->NewFromASCII(key.c_str()); 951 JSTaggedValue result = ecmaModule->GetModuleValue(thread, keyHandle.GetTaggedValue(), false); 952 JSHandle<JSTaggedValue> exportObj(thread, result); 953 return JSNApiHelper::ToLocal<ObjectRef>(exportObj); 954 } 955 956 // Initialize IcuData Path InitializeIcuData(const JSRuntimeOptions & options)957 void JSNApi::InitializeIcuData(const JSRuntimeOptions &options) 958 { 959 std::string icuPath = options.GetIcuDataPath(); 960 if (icuPath == "default") { 961 #if !WIN_OR_MAC_OR_IOS_PLATFORM && !defined(PANDA_TARGET_LINUX) 962 SetHwIcuDirectory(); 963 #endif 964 } else { 965 std::string absPath; 966 if (ecmascript::RealPath(icuPath, absPath)) { 967 u_setDataDirectory(absPath.c_str()); 968 } 969 } 970 } 971 InitializeMemMapAllocator()972 void JSNApi::InitializeMemMapAllocator() 973 { 974 MemMapAllocator::GetInstance()->Initialize(ecmascript::DEFAULT_REGION_SIZE); 975 } 976 DestroyMemMapAllocator()977 void JSNApi::DestroyMemMapAllocator() 978 { 979 MemMapAllocator::GetInstance()->Finalize(); 980 } 981 InitializePGOProfiler(const ecmascript::JSRuntimeOptions & options)982 void JSNApi::InitializePGOProfiler(const ecmascript::JSRuntimeOptions &options) 983 { 984 ecmascript::PGOProfilerManager::GetInstance()->Initialize( 985 options.GetPGOProfilerPath(), options.GetPGOHotnessThreshold()); 986 } 987 DestroyPGOProfiler()988 void JSNApi::DestroyPGOProfiler() 989 { 990 ecmascript::PGOProfilerManager::GetInstance()->Destroy(); 991 } 992 DestroyAnDataManager()993 void JSNApi::DestroyAnDataManager() 994 { 995 ecmascript::AnFileDataManager::GetInstance()->SafeDestroyAllData(); 996 } 997 FunctionCallScope(EcmaVM * vm)998 FunctionCallScope::FunctionCallScope(EcmaVM *vm) : vm_(vm) 999 { 1000 vm_->IncreaseCallDepth(); 1001 } 1002 ~FunctionCallScope()1003 FunctionCallScope::~FunctionCallScope() 1004 { 1005 vm_->DecreaseCallDepth(); 1006 if (vm_->IsTopLevelCallDepth()) { 1007 JSThread *thread = vm_->GetJSThread(); 1008 thread->GetCurrentEcmaContext()->ExecutePromisePendingJob(); 1009 } 1010 } 1011 1012 // ----------------------------------- HandleScope ------------------------------------- LocalScope(const EcmaVM * vm)1013 LocalScope::LocalScope(const EcmaVM *vm) : thread_(vm->GetJSThread()) 1014 { 1015 auto context = reinterpret_cast<JSThread *>(thread_)->GetCurrentEcmaContext(); 1016 prevNext_ = context->GetHandleScopeStorageNext(); 1017 prevEnd_ = context->GetHandleScopeStorageEnd(); 1018 prevHandleStorageIndex_ = context->GetCurrentHandleStorageIndex(); 1019 context->HandleScopeCountAdd(); 1020 } 1021 LocalScope(const EcmaVM * vm,JSTaggedType value)1022 LocalScope::LocalScope(const EcmaVM *vm, JSTaggedType value) : thread_(vm->GetJSThread()) 1023 { 1024 auto context = reinterpret_cast<JSThread *>(thread_)->GetCurrentEcmaContext(); 1025 ecmascript::EcmaHandleScope::NewHandle(reinterpret_cast<JSThread *>(thread_), value); 1026 prevNext_ = context->GetHandleScopeStorageNext(); 1027 prevEnd_ = context->GetHandleScopeStorageEnd(); 1028 prevHandleStorageIndex_ = context->GetCurrentHandleStorageIndex(); 1029 context->HandleScopeCountAdd(); 1030 } 1031 ~LocalScope()1032 LocalScope::~LocalScope() 1033 { 1034 auto context = reinterpret_cast<JSThread *>(thread_)->GetCurrentEcmaContext(); 1035 context->HandleScopeCountDec(); 1036 context->SetHandleScopeStorageNext(static_cast<JSTaggedType *>(prevNext_)); 1037 if (context->GetHandleScopeStorageEnd() != prevEnd_) { 1038 context->SetHandleScopeStorageEnd(static_cast<JSTaggedType *>(prevEnd_)); 1039 context->ShrinkHandleStorage(prevHandleStorageIndex_); 1040 } 1041 } 1042 1043 // ----------------------------------- EscapeLocalScope ------------------------------ EscapeLocalScope(const EcmaVM * vm)1044 EscapeLocalScope::EscapeLocalScope(const EcmaVM *vm) : LocalScope(vm, JSTaggedValue::Undefined().GetRawData()) 1045 { 1046 auto thread = vm->GetJSThread(); 1047 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 1048 escapeHandle_ = ToUintPtr(thread->GetCurrentEcmaContext()->GetHandleScopeStorageNext() - 1); 1049 } 1050 1051 // ----------------------------------- PritimitiveRef --------------------------------------- GetValue(const EcmaVM * vm)1052 Local<JSValueRef> PrimitiveRef::GetValue(const EcmaVM *vm) 1053 { 1054 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1055 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 1056 LOG_IF_SPECIAL(obj, ERROR); 1057 if (obj->IsJSPrimitiveRef()) { 1058 JSTaggedValue primitiveValue = JSPrimitiveRef::Cast(obj->GetTaggedObject())->GetValue(); 1059 JSHandle<JSTaggedValue> value(vm->GetJSThread(), primitiveValue); 1060 return JSNApiHelper::ToLocal<JSValueRef>(value); 1061 } 1062 return Local<JSValueRef>(); 1063 } 1064 1065 // ----------------------------------- NumberRef --------------------------------------- New(const EcmaVM * vm,double input)1066 Local<NumberRef> NumberRef::New(const EcmaVM *vm, double input) 1067 { 1068 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1069 JSThread *thread = vm->GetJSThread(); 1070 if (std::isnan(input)) { 1071 input = ecmascript::base::NAN_VALUE; 1072 } 1073 JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input)); 1074 return JSNApiHelper::ToLocal<NumberRef>(number); 1075 } 1076 New(const EcmaVM * vm,int32_t input)1077 Local<NumberRef> NumberRef::New(const EcmaVM *vm, int32_t input) 1078 { 1079 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1080 JSThread *thread = vm->GetJSThread(); 1081 JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input)); 1082 return JSNApiHelper::ToLocal<NumberRef>(number); 1083 } 1084 New(const EcmaVM * vm,uint32_t input)1085 Local<NumberRef> NumberRef::New(const EcmaVM *vm, uint32_t input) 1086 { 1087 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1088 JSThread *thread = vm->GetJSThread(); 1089 JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input)); 1090 return JSNApiHelper::ToLocal<NumberRef>(number); 1091 } 1092 New(const EcmaVM * vm,int64_t input)1093 Local<NumberRef> NumberRef::New(const EcmaVM *vm, int64_t input) 1094 { 1095 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1096 JSThread *thread = vm->GetJSThread(); 1097 JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input)); 1098 return JSNApiHelper::ToLocal<NumberRef>(number); 1099 } 1100 Value()1101 double NumberRef::Value() 1102 { 1103 return JSTaggedNumber(JSNApiHelper::ToJSTaggedValue(this)).GetNumber(); 1104 } 1105 1106 // ----------------------------------- BigIntRef --------------------------------------- New(const EcmaVM * vm,uint64_t input)1107 Local<BigIntRef> BigIntRef::New(const EcmaVM *vm, uint64_t input) 1108 { 1109 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1110 JSThread *thread = vm->GetJSThread(); 1111 JSHandle<BigInt> big = BigInt::Uint64ToBigInt(thread, input); 1112 JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big); 1113 return JSNApiHelper::ToLocal<BigIntRef>(bigint); 1114 } 1115 New(const EcmaVM * vm,int64_t input)1116 Local<BigIntRef> BigIntRef::New(const EcmaVM *vm, int64_t input) 1117 { 1118 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1119 JSThread *thread = vm->GetJSThread(); 1120 JSHandle<BigInt> big = BigInt::Int64ToBigInt(thread, input); 1121 JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big); 1122 return JSNApiHelper::ToLocal<BigIntRef>(bigint); 1123 } 1124 CreateBigWords(const EcmaVM * vm,bool sign,uint32_t size,const uint64_t * words)1125 Local<JSValueRef> BigIntRef::CreateBigWords(const EcmaVM *vm, bool sign, uint32_t size, const uint64_t* words) 1126 { 1127 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1128 JSThread *thread = vm->GetJSThread(); 1129 JSHandle<BigInt> big = BigInt::CreateBigWords(thread, sign, size, words); 1130 JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big); 1131 return JSNApiHelper::ToLocal<JSValueRef>(bigint); 1132 } 1133 BigIntToInt64(const EcmaVM * vm,int64_t * cValue,bool * lossless)1134 void BigIntRef::BigIntToInt64(const EcmaVM *vm, int64_t *cValue, bool *lossless) 1135 { 1136 CHECK_HAS_PENDING_EXCEPTION_WITHOUT_RETURN(vm); 1137 JSThread *thread = vm->GetJSThread(); 1138 JSHandle<JSTaggedValue> bigintVal(JSNApiHelper::ToJSHandle(this)); 1139 LOG_IF_SPECIAL(bigintVal, ERROR); 1140 BigInt::BigIntToInt64(thread, bigintVal, cValue, lossless); 1141 } 1142 BigIntToUint64(const EcmaVM * vm,uint64_t * cValue,bool * lossless)1143 void BigIntRef::BigIntToUint64(const EcmaVM *vm, uint64_t *cValue, bool *lossless) 1144 { 1145 CHECK_HAS_PENDING_EXCEPTION_WITHOUT_RETURN(vm); 1146 JSThread *thread = vm->GetJSThread(); 1147 JSHandle<JSTaggedValue> bigintVal(JSNApiHelper::ToJSHandle(this)); 1148 LOG_IF_SPECIAL(bigintVal, ERROR); 1149 BigInt::BigIntToUint64(thread, bigintVal, cValue, lossless); 1150 } 1151 GetWordsArray(bool * signBit,size_t wordCount,uint64_t * words)1152 void BigIntRef::GetWordsArray(bool* signBit, size_t wordCount, uint64_t* words) 1153 { 1154 JSHandle<BigInt> bigintVal(JSNApiHelper::ToJSHandle(this)); 1155 LOG_IF_SPECIAL(bigintVal, FATAL); 1156 uint32_t len = bigintVal->GetLength(); 1157 uint32_t count = 0; 1158 uint32_t index = 0; 1159 for (; index < wordCount - 1; ++index) { 1160 words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++)); 1161 words[index] |= static_cast<uint64_t>(bigintVal->GetDigit(count++)) << 32; // 32 : int32_t bits 1162 } 1163 if (len % 2 == 0) { // 2 : len is odd or even 1164 words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++)); 1165 words[index] |= static_cast<uint64_t>(bigintVal->GetDigit(count++)) << 32; // 32 : int32_t bits 1166 } else { 1167 words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++)); 1168 } 1169 *signBit = bigintVal->GetSign(); 1170 } 1171 GetWordsArraySize()1172 uint32_t BigIntRef::GetWordsArraySize() 1173 { 1174 JSHandle<BigInt> bigintVal(JSNApiHelper::ToJSHandle(this)); 1175 LOG_IF_SPECIAL(bigintVal, FATAL); 1176 uint32_t len = bigintVal->GetLength(); 1177 return len % 2 != 0 ? len / 2 + 1 : len / 2; // 2 : len is odd or even 1178 } 1179 1180 // ----------------------------------- BooleanRef --------------------------------------- New(const EcmaVM * vm,bool input)1181 Local<BooleanRef> BooleanRef::New(const EcmaVM *vm, bool input) 1182 { 1183 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1184 JSThread *thread = vm->GetJSThread(); 1185 JSHandle<JSTaggedValue> boolean(thread, JSTaggedValue(input)); 1186 return JSNApiHelper::ToLocal<BooleanRef>(boolean); 1187 } 1188 Value()1189 bool BooleanRef::Value() 1190 { 1191 return JSNApiHelper::ToJSTaggedValue(this).IsTrue(); 1192 } 1193 1194 // ----------------------------------- IntegerRef --------------------------------------- New(const EcmaVM * vm,int input)1195 Local<IntegerRef> IntegerRef::New(const EcmaVM *vm, int input) 1196 { 1197 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1198 JSThread *thread = vm->GetJSThread(); 1199 JSHandle<JSTaggedValue> integer(thread, JSTaggedValue(input)); 1200 return JSNApiHelper::ToLocal<IntegerRef>(integer); 1201 } 1202 NewFromUnsigned(const EcmaVM * vm,unsigned int input)1203 Local<IntegerRef> IntegerRef::NewFromUnsigned(const EcmaVM *vm, unsigned int input) 1204 { 1205 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1206 JSThread *thread = vm->GetJSThread(); 1207 JSHandle<JSTaggedValue> integer(thread, JSTaggedValue(input)); 1208 return JSNApiHelper::ToLocal<IntegerRef>(integer); 1209 } 1210 Value()1211 int IntegerRef::Value() 1212 { 1213 return JSNApiHelper::ToJSTaggedValue(this).GetInt(); 1214 } 1215 1216 // ----------------------------------- StringRef ---------------------------------------- NewFromUtf8(const EcmaVM * vm,const char * utf8,int length)1217 Local<StringRef> StringRef::NewFromUtf8(const EcmaVM *vm, const char *utf8, int length) 1218 { 1219 ObjectFactory *factory = vm->GetFactory(); 1220 if (length < 0) { 1221 JSHandle<JSTaggedValue> current(factory->NewFromUtf8(utf8)); 1222 return JSNApiHelper::ToLocal<StringRef>(current); 1223 } 1224 JSHandle<JSTaggedValue> current(factory->NewFromUtf8(reinterpret_cast<const uint8_t *>(utf8), length)); 1225 return JSNApiHelper::ToLocal<StringRef>(current); 1226 } 1227 NewFromUtf16(const EcmaVM * vm,const char16_t * utf16,int length)1228 Local<StringRef> StringRef::NewFromUtf16(const EcmaVM *vm, const char16_t *utf16, int length) 1229 { 1230 ObjectFactory *factory = vm->GetFactory(); 1231 if (length < 0) { 1232 JSHandle<JSTaggedValue> current(factory->NewFromUtf16(utf16)); 1233 return JSNApiHelper::ToLocal<StringRef>(current); 1234 } 1235 JSHandle<JSTaggedValue> current(factory->NewFromUtf16(reinterpret_cast<const uint16_t *>(utf16), length)); 1236 return JSNApiHelper::ToLocal<StringRef>(current); 1237 } 1238 ToString()1239 std::string StringRef::ToString() 1240 { 1241 return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)).ToStdString(); 1242 } 1243 Length()1244 uint32_t StringRef::Length() 1245 { 1246 return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)).GetLength(); 1247 } 1248 Utf8Length(const EcmaVM * vm)1249 int32_t StringRef::Utf8Length(const EcmaVM *vm) 1250 { 1251 CHECK_HAS_PENDING_EXCEPTION(vm, 0); 1252 JSHandle<EcmaString> strHandle(vm->GetJSThread(), EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(this))); 1253 return EcmaStringAccessor(EcmaStringAccessor::Flatten(vm, strHandle)).GetUtf8Length(); 1254 } 1255 WriteUtf8(char * buffer,int length,bool isWriteBuffer)1256 int StringRef::WriteUtf8(char *buffer, int length, bool isWriteBuffer) 1257 { 1258 return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)) 1259 .WriteToFlatUtf8(reinterpret_cast<uint8_t *>(buffer), length, isWriteBuffer); 1260 } 1261 WriteUtf16(char16_t * buffer,int length)1262 int StringRef::WriteUtf16(char16_t *buffer, int length) 1263 { 1264 return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)) 1265 .WriteToUtf16(reinterpret_cast<uint16_t *>(buffer), length); 1266 } 1267 WriteLatin1(char * buffer,int length)1268 int StringRef::WriteLatin1(char *buffer, int length) 1269 { 1270 return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)) 1271 .WriteToOneByte(reinterpret_cast<uint8_t *>(buffer), length); 1272 } 1273 GetNapiWrapperString(const EcmaVM * vm)1274 Local<StringRef> StringRef::GetNapiWrapperString(const EcmaVM *vm) 1275 { 1276 JSHandle<JSTaggedValue> napiWapperString = vm->GetJSThread()->GlobalConstants()->GetHandledNapiWrapperString(); 1277 return JSNApiHelper::ToLocal<StringRef>(napiWapperString); 1278 } 1279 1280 // ----------------------------------- SymbolRef ----------------------------------------- New(const EcmaVM * vm,Local<StringRef> description)1281 Local<SymbolRef> SymbolRef::New(const EcmaVM *vm, Local<StringRef> description) 1282 { 1283 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1284 ObjectFactory *factory = vm->GetFactory(); 1285 JSHandle<JSSymbol> symbol = factory->NewJSSymbol(); 1286 JSTaggedValue desc = JSNApiHelper::ToJSTaggedValue(*description); 1287 symbol->SetDescription(vm->GetJSThread(), desc); 1288 return JSNApiHelper::ToLocal<SymbolRef>(JSHandle<JSTaggedValue>(symbol)); 1289 } 1290 GetDescription(const EcmaVM * vm)1291 Local<StringRef> SymbolRef::GetDescription(const EcmaVM *vm) 1292 { 1293 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1294 JSTaggedValue description = JSSymbol::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())->GetDescription(); 1295 if (!description.IsString()) { 1296 auto constants = vm->GetJSThread()->GlobalConstants(); 1297 return JSNApiHelper::ToLocal<StringRef>(constants->GetHandledEmptyString()); 1298 } 1299 JSHandle<JSTaggedValue> descriptionHandle(vm->GetJSThread(), description); 1300 return JSNApiHelper::ToLocal<StringRef>(descriptionHandle); 1301 } 1302 1303 // -------------------------------- NativePointerRef ------------------------------------ New(const EcmaVM * vm,void * nativePointer,size_t nativeBindingsize)1304 Local<NativePointerRef> NativePointerRef::New(const EcmaVM *vm, void *nativePointer, size_t nativeBindingsize) 1305 { 1306 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1307 ObjectFactory *factory = vm->GetFactory(); 1308 JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(nativePointer, nullptr, nullptr, 1309 false, nativeBindingsize); 1310 return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj)); 1311 } 1312 New(const EcmaVM * vm,void * nativePointer,NativePointerCallback callBack,void * data,size_t nativeBindingsize)1313 Local<NativePointerRef> NativePointerRef::New( 1314 const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack, void *data, size_t nativeBindingsize) 1315 { 1316 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1317 ObjectFactory *factory = vm->GetFactory(); 1318 JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(nativePointer, callBack, data, 1319 false, nativeBindingsize); 1320 return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj)); 1321 } 1322 Value()1323 void *NativePointerRef::Value() 1324 { 1325 JSHandle<JSTaggedValue> nativePointer = JSNApiHelper::ToJSHandle(this); 1326 LOG_IF_SPECIAL(nativePointer, FATAL); 1327 return JSHandle<JSNativePointer>(nativePointer)->GetExternalPointer(); 1328 } 1329 1330 // ----------------------------------- ObjectRef ---------------------------------------- New(const EcmaVM * vm)1331 Local<ObjectRef> ObjectRef::New(const EcmaVM *vm) 1332 { 1333 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1334 ObjectFactory *factory = vm->GetFactory(); 1335 JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv(); 1336 JSHandle<JSFunction> constructor(globalEnv->GetObjectFunction()); 1337 JSHandle<JSTaggedValue> object(factory->NewJSObjectByConstructor(constructor)); 1338 return JSNApiHelper::ToLocal<ObjectRef>(object); 1339 } 1340 New(const EcmaVM * vm,void * detach,void * attach)1341 Local<ObjectRef> ObjectRef::New(const EcmaVM *vm, void *detach, void *attach) 1342 { 1343 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1344 ObjectFactory *factory = vm->GetFactory(); 1345 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 1346 JSHandle<JSFunction> constructor(env->GetObjectFunction()); 1347 JSHandle<JSTaggedValue> object(factory->NewJSObjectByConstructor(constructor)); 1348 JSHandle<JSTaggedValue> detachKey = env->GetDetachSymbol(); 1349 JSHandle<JSTaggedValue> attachKey = env->GetAttachSymbol(); 1350 JSHandle<JSTaggedValue> detachValue = JSNApiHelper::ToJSHandle(NativePointerRef::New(vm, detach)); 1351 JSHandle<JSTaggedValue> attachValue = JSNApiHelper::ToJSHandle(NativePointerRef::New(vm, attach)); 1352 JSTaggedValue::SetProperty(vm->GetJSThread(), object, detachKey, detachValue); 1353 JSTaggedValue::SetProperty(vm->GetJSThread(), object, attachKey, attachValue); 1354 RETURN_VALUE_IF_ABRUPT(vm->GetJSThread(), JSValueRef::Undefined(vm)); 1355 return JSNApiHelper::ToLocal<ObjectRef>(object); 1356 } 1357 Set(const EcmaVM * vm,void * detach,void * attach)1358 bool ObjectRef::Set(const EcmaVM *vm, void *detach, void *attach) 1359 { 1360 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1361 [[maybe_unused]] LocalScope scope(vm); 1362 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 1363 JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(this); 1364 LOG_IF_SPECIAL(object, ERROR); 1365 JSHandle<JSTaggedValue> detachKey = env->GetDetachSymbol(); 1366 JSHandle<JSTaggedValue> attachKey = env->GetAttachSymbol(); 1367 JSHandle<JSTaggedValue> detachValue = JSNApiHelper::ToJSHandle(NativePointerRef::New(vm, detach)); 1368 JSHandle<JSTaggedValue> attachValue = JSNApiHelper::ToJSHandle(NativePointerRef::New(vm, attach)); 1369 bool detachResult = JSTaggedValue::SetProperty(vm->GetJSThread(), object, detachKey, detachValue); 1370 bool attachResult = JSTaggedValue::SetProperty(vm->GetJSThread(), object, attachKey, attachValue); 1371 RETURN_VALUE_IF_ABRUPT(vm->GetJSThread(), false); 1372 return detachResult && attachResult; 1373 } 1374 Set(const EcmaVM * vm,Local<JSValueRef> key,Local<JSValueRef> value)1375 bool ObjectRef::Set(const EcmaVM *vm, Local<JSValueRef> key, Local<JSValueRef> value) 1376 { 1377 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1378 [[maybe_unused]] LocalScope scope(vm); 1379 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 1380 LOG_IF_SPECIAL(obj, ERROR); 1381 JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key); 1382 JSHandle<JSTaggedValue> valueValue = JSNApiHelper::ToJSHandle(value); 1383 bool result = JSTaggedValue::SetProperty(vm->GetJSThread(), obj, keyValue, valueValue); 1384 RETURN_VALUE_IF_ABRUPT(vm->GetJSThread(), false); 1385 return result; 1386 } 1387 Set(const EcmaVM * vm,uint32_t key,Local<JSValueRef> value)1388 bool ObjectRef::Set(const EcmaVM *vm, uint32_t key, Local<JSValueRef> value) 1389 { 1390 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1391 [[maybe_unused]] LocalScope scope(vm); 1392 Local<JSValueRef> keyValue = NumberRef::New(vm, key); 1393 return Set(vm, keyValue, value); 1394 } 1395 SetAccessorProperty(const EcmaVM * vm,Local<JSValueRef> key,Local<FunctionRef> getter,Local<FunctionRef> setter,PropertyAttribute attribute)1396 bool ObjectRef::SetAccessorProperty(const EcmaVM *vm, Local<JSValueRef> key, Local<FunctionRef> getter, 1397 Local<FunctionRef> setter, PropertyAttribute attribute) 1398 { 1399 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1400 [[maybe_unused]] LocalScope scope(vm); 1401 JSThread *thread = vm->GetJSThread(); 1402 JSHandle<JSTaggedValue> getterValue = JSNApiHelper::ToJSHandle(getter); 1403 JSHandle<JSTaggedValue> setterValue = JSNApiHelper::ToJSHandle(setter); 1404 PropertyDescriptor desc(thread, attribute.IsWritable(), attribute.IsEnumerable(), attribute.IsConfigurable()); 1405 desc.SetValue(JSNApiHelper::ToJSHandle(attribute.GetValue(vm))); 1406 desc.SetSetter(setterValue); 1407 desc.SetGetter(getterValue); 1408 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 1409 LOG_IF_SPECIAL(obj, ERROR); 1410 JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key); 1411 bool result = JSTaggedValue::DefineOwnProperty(thread, obj, keyValue, desc); 1412 RETURN_VALUE_IF_ABRUPT(thread, false); 1413 return result; 1414 } 1415 Get(const EcmaVM * vm,Local<JSValueRef> key)1416 Local<JSValueRef> ObjectRef::Get(const EcmaVM *vm, Local<JSValueRef> key) 1417 { 1418 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1419 EscapeLocalScope scope(vm); 1420 JSThread *thread = vm->GetJSThread(); 1421 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 1422 LOG_IF_SPECIAL(obj, ERROR); 1423 JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key); 1424 OperationResult ret = JSTaggedValue::GetProperty(thread, obj, keyValue); 1425 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 1426 if (!ret.GetPropertyMetaData().IsFound()) { 1427 return JSValueRef::Undefined(vm); 1428 } 1429 return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(ret.GetValue())); 1430 } 1431 Get(const EcmaVM * vm,int32_t key)1432 Local<JSValueRef> ObjectRef::Get(const EcmaVM *vm, int32_t key) 1433 { 1434 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1435 Local<JSValueRef> keyValue = IntegerRef::New(vm, key); 1436 return Get(vm, keyValue); 1437 } 1438 GetOwnProperty(const EcmaVM * vm,Local<JSValueRef> key,PropertyAttribute & property)1439 bool ObjectRef::GetOwnProperty(const EcmaVM *vm, Local<JSValueRef> key, PropertyAttribute &property) 1440 { 1441 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1442 JSThread *thread = vm->GetJSThread(); 1443 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 1444 LOG_IF_SPECIAL(obj, ERROR); 1445 JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key); 1446 PropertyDescriptor desc(thread); 1447 bool ret = JSObject::GetOwnProperty(thread, JSHandle<JSObject>(obj), keyValue, desc); 1448 if (!ret) { 1449 return false; 1450 } 1451 property.SetValue(JSNApiHelper::ToLocal<JSValueRef>(desc.GetValue())); 1452 if (desc.HasGetter()) { 1453 property.SetGetter(JSNApiHelper::ToLocal<JSValueRef>(desc.GetGetter())); 1454 } 1455 if (desc.HasSetter()) { 1456 property.SetSetter(JSNApiHelper::ToLocal<JSValueRef>(desc.GetSetter())); 1457 } 1458 if (desc.HasWritable()) { 1459 property.SetWritable(desc.IsWritable()); 1460 } 1461 if (desc.HasEnumerable()) { 1462 property.SetEnumerable(desc.IsEnumerable()); 1463 } 1464 if (desc.HasConfigurable()) { 1465 property.SetConfigurable(desc.IsConfigurable()); 1466 } 1467 1468 return true; 1469 } 1470 GetOwnPropertyNames(const EcmaVM * vm)1471 Local<ArrayRef> ObjectRef::GetOwnPropertyNames(const EcmaVM *vm) 1472 { 1473 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1474 JSThread *thread = vm->GetJSThread(); 1475 JSHandle<JSTaggedValue> obj(JSNApiHelper::ToJSHandle(this)); 1476 LOG_IF_SPECIAL(obj, ERROR); 1477 JSHandle<TaggedArray> array(JSTaggedValue::GetOwnPropertyKeys(thread, obj)); 1478 JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array)); 1479 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 1480 return JSNApiHelper::ToLocal<ArrayRef>(jsArray); 1481 } 1482 GetAllPropertyNames(const EcmaVM * vm,uint32_t filter)1483 Local<ArrayRef> ObjectRef::GetAllPropertyNames(const EcmaVM *vm, uint32_t filter) 1484 { 1485 // This interface is only used by napi. 1486 // This interface currently only supports normal objects. 1487 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1488 JSThread *thread = vm->GetJSThread(); 1489 JSHandle<JSTaggedValue> obj(JSNApiHelper::ToJSHandle(this)); 1490 LOG_IF_SPECIAL(obj, ERROR); 1491 JSHandle<TaggedArray> array(JSTaggedValue::GetAllPropertyKeys(thread, obj, filter)); 1492 JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array)); 1493 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 1494 return JSNApiHelper::ToLocal<ArrayRef>(jsArray); 1495 } 1496 GetOwnEnumerablePropertyNames(const EcmaVM * vm)1497 Local<ArrayRef> ObjectRef::GetOwnEnumerablePropertyNames(const EcmaVM *vm) 1498 { 1499 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1500 JSThread *thread = vm->GetJSThread(); 1501 JSHandle<JSObject> obj(JSNApiHelper::ToJSHandle(this)); 1502 LOG_IF_SPECIAL(obj, ERROR); 1503 JSHandle<TaggedArray> array(JSObject::EnumerableOwnNames(thread, obj)); 1504 JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array)); 1505 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 1506 return JSNApiHelper::ToLocal<ArrayRef>(jsArray); 1507 } 1508 GetPrototype(const EcmaVM * vm)1509 Local<JSValueRef> ObjectRef::GetPrototype(const EcmaVM *vm) 1510 { 1511 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1512 JSThread *thread = vm->GetJSThread(); 1513 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this)); 1514 LOG_IF_SPECIAL(object, ERROR); 1515 JSHandle<JSTaggedValue> prototype(thread, JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(object))); 1516 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 1517 return JSNApiHelper::ToLocal<JSValueRef>(prototype); 1518 } 1519 SetPrototype(const EcmaVM * vm,Local<ObjectRef> prototype)1520 bool ObjectRef::SetPrototype(const EcmaVM *vm, Local<ObjectRef> prototype) 1521 { 1522 JSThread *thread = vm->GetJSThread(); 1523 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this)); 1524 JSHandle<JSObject> proto(JSNApiHelper::ToJSHandle(prototype)); 1525 bool result = JSTaggedValue::SetPrototype(thread, JSHandle<JSTaggedValue>(object), JSHandle<JSTaggedValue>(proto)); 1526 RETURN_VALUE_IF_ABRUPT(thread, false); 1527 return result; 1528 } 1529 DefineProperty(const EcmaVM * vm,Local<JSValueRef> key,PropertyAttribute attribute)1530 bool ObjectRef::DefineProperty(const EcmaVM *vm, Local<JSValueRef> key, PropertyAttribute attribute) 1531 { 1532 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1533 JSThread *thread = vm->GetJSThread(); 1534 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this)); 1535 LOG_IF_SPECIAL(object, ERROR); 1536 JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key)); 1537 PropertyDescriptor desc(thread, attribute.IsWritable(), attribute.IsEnumerable(), attribute.IsConfigurable()); 1538 desc.SetValue(JSNApiHelper::ToJSHandle(attribute.GetValue(vm))); 1539 bool result = object->DefinePropertyOrThrow(thread, object, keyValue, desc); 1540 RETURN_VALUE_IF_ABRUPT(thread, false); 1541 return result; 1542 } 1543 Has(const EcmaVM * vm,Local<JSValueRef> key)1544 bool ObjectRef::Has(const EcmaVM *vm, Local<JSValueRef> key) 1545 { 1546 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1547 JSThread *thread = vm->GetJSThread(); 1548 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this)); 1549 LOG_IF_SPECIAL(object, ERROR); 1550 JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key)); 1551 bool result = object->HasProperty(thread, object, keyValue); 1552 RETURN_VALUE_IF_ABRUPT(thread, false); 1553 return result; 1554 } 1555 Has(const EcmaVM * vm,uint32_t key)1556 bool ObjectRef::Has(const EcmaVM *vm, uint32_t key) 1557 { 1558 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1559 JSThread *thread = vm->GetJSThread(); 1560 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this)); 1561 LOG_IF_SPECIAL(object, ERROR); 1562 bool result = object->HasProperty(thread, object, key); 1563 RETURN_VALUE_IF_ABRUPT(thread, false); 1564 return result; 1565 } 1566 Delete(const EcmaVM * vm,Local<JSValueRef> key)1567 bool ObjectRef::Delete(const EcmaVM *vm, Local<JSValueRef> key) 1568 { 1569 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1570 JSThread *thread = vm->GetJSThread(); 1571 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this)); 1572 LOG_IF_SPECIAL(object, ERROR); 1573 JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key)); 1574 bool result = object->DeleteProperty(thread, object, keyValue); 1575 RETURN_VALUE_IF_ABRUPT(thread, false); 1576 return result; 1577 } 1578 Delete(const EcmaVM * vm,uint32_t key)1579 bool ObjectRef::Delete(const EcmaVM *vm, uint32_t key) 1580 { 1581 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1582 JSThread *thread = vm->GetJSThread(); 1583 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this)); 1584 LOG_IF_SPECIAL(object, ERROR); 1585 JSHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue(key)); 1586 bool result = object->DeleteProperty(thread, object, keyHandle); 1587 RETURN_VALUE_IF_ABRUPT(thread, false); 1588 return result; 1589 } 1590 Freeze(const EcmaVM * vm)1591 Local<JSValueRef> ObjectRef::Freeze(const EcmaVM *vm) 1592 { 1593 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1594 EscapeLocalScope scope(vm); 1595 JSThread *thread = vm->GetJSThread(); 1596 JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(this); 1597 LOG_IF_SPECIAL(object, ERROR); 1598 JSHandle<JSObject> obj(object); 1599 bool status = JSObject::SetIntegrityLevel(thread, obj, ecmascript::IntegrityLevel::FROZEN); 1600 if (JSNApi::HasPendingException(vm)) { 1601 JSHandle<JSTaggedValue> exception(thread, JSTaggedValue::Exception()); 1602 return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(exception)); 1603 } 1604 if (!status) { 1605 LOG_ECMA(ERROR) << "Freeze: freeze failed"; 1606 Local<StringRef> message = StringRef::NewFromUtf8(vm, "Freeze: freeze failed"); 1607 Local<JSValueRef> error = Exception::Error(vm, message); 1608 JSNApi::ThrowException(vm, error); 1609 JSHandle<JSTaggedValue> exception(thread, JSTaggedValue::Exception()); 1610 return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(exception)); 1611 } 1612 JSHandle<JSTaggedValue> resultValue(obj); 1613 return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(resultValue)); 1614 } 1615 Seal(const EcmaVM * vm)1616 Local<JSValueRef> ObjectRef::Seal(const EcmaVM *vm) 1617 { 1618 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1619 EscapeLocalScope scope(vm); 1620 JSThread *thread = vm->GetJSThread(); 1621 JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(this); 1622 LOG_IF_SPECIAL(object, ERROR); 1623 JSHandle<JSObject> obj(object); 1624 bool status = JSObject::SetIntegrityLevel(thread, obj, ecmascript::IntegrityLevel::SEALED); 1625 if (JSNApi::HasPendingException(vm)) { 1626 JSHandle<JSTaggedValue> exception(thread, JSTaggedValue::Exception()); 1627 return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(exception)); 1628 } 1629 if (!status) { 1630 LOG_ECMA(ERROR) << "Seal: seal failed"; 1631 Local<StringRef> message = StringRef::NewFromUtf8(vm, "Freeze: freeze failed"); 1632 Local<JSValueRef> error = Exception::Error(vm, message); 1633 JSNApi::ThrowException(vm, error); 1634 JSHandle<JSTaggedValue> exception(thread, JSTaggedValue::Exception()); 1635 return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(exception)); 1636 } 1637 JSHandle<JSTaggedValue> resultValue(obj); 1638 return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(resultValue)); 1639 } 1640 SetNativePointerFieldCount(int32_t count)1641 void ObjectRef::SetNativePointerFieldCount(int32_t count) 1642 { 1643 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this)); 1644 LOG_IF_SPECIAL(object, FATAL); 1645 object->SetNativePointerFieldCount(count); 1646 } 1647 GetNativePointerFieldCount()1648 int32_t ObjectRef::GetNativePointerFieldCount() 1649 { 1650 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this)); 1651 LOG_IF_SPECIAL(object, FATAL); 1652 return object->GetNativePointerFieldCount(); 1653 } 1654 GetNativePointerField(int32_t index)1655 void *ObjectRef::GetNativePointerField(int32_t index) 1656 { 1657 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this)); 1658 LOG_IF_SPECIAL(object, FATAL); 1659 return object->GetNativePointerField(index); 1660 } 1661 SetNativePointerField(int32_t index,void * nativePointer,NativePointerCallback callBack,void * data,size_t nativeBindingsize)1662 void ObjectRef::SetNativePointerField(int32_t index, void *nativePointer, 1663 NativePointerCallback callBack, void *data, size_t nativeBindingsize) 1664 { 1665 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this)); 1666 LOG_IF_SPECIAL(object, FATAL); 1667 object->SetNativePointerField(index, nativePointer, callBack, data, nativeBindingsize); 1668 } 1669 1670 // ----------------------------------- FunctionRef -------------------------------------- New(EcmaVM * vm,FunctionCallback nativeFunc,Deleter deleter,void * data,bool callNapi,size_t nativeBindingsize)1671 Local<FunctionRef> FunctionRef::New(EcmaVM *vm, FunctionCallback nativeFunc, 1672 Deleter deleter, void *data, bool callNapi, size_t nativeBindingsize) 1673 { 1674 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1675 JSThread *thread = vm->GetJSThread(); 1676 ObjectFactory *factory = vm->GetFactory(); 1677 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 1678 JSHandle<JSFunction> current(factory->NewJSFunction(env, reinterpret_cast<void *>(Callback::RegisterCallback))); 1679 current->SetFunctionExtraInfo(thread, reinterpret_cast<void *>(nativeFunc), deleter, data, nativeBindingsize); 1680 current->SetCallNapi(callNapi); 1681 return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current)); 1682 } 1683 NewClassFunction(EcmaVM * vm,FunctionCallback nativeFunc,Deleter deleter,void * data,bool callNapi,size_t nativeBindingsize)1684 Local<FunctionRef> FunctionRef::NewClassFunction(EcmaVM *vm, FunctionCallback nativeFunc, 1685 Deleter deleter, void *data, bool callNapi, size_t nativeBindingsize) 1686 { 1687 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1688 EscapeLocalScope scope(vm); 1689 JSThread *thread = vm->GetJSThread(); 1690 ObjectFactory *factory = vm->GetFactory(); 1691 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 1692 JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutName()); 1693 JSHandle<JSFunction> current = 1694 factory->NewJSFunctionByHClass(reinterpret_cast<void *>(Callback::RegisterCallback), 1695 hclass, ecmascript::FunctionKind::CLASS_CONSTRUCTOR); 1696 1697 auto globalConst = thread->GlobalConstants(); 1698 JSHandle<JSTaggedValue> accessor = globalConst->GetHandledFunctionPrototypeAccessor(); 1699 current->SetPropertyInlinedProps(thread, JSFunction::CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX, 1700 accessor.GetTaggedValue()); 1701 1702 current->SetFunctionExtraInfo(thread, reinterpret_cast<void *>(nativeFunc), deleter, data, nativeBindingsize); 1703 1704 JSHandle<JSObject> clsPrototype = JSFunction::NewJSFunctionPrototype(thread, current); 1705 clsPrototype.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassPrototype(true); 1706 JSHandle<JSTaggedValue>::Cast(current)->GetTaggedObject()->GetClass()->SetClassConstructor(true); 1707 current->SetClassConstructor(true); 1708 JSHandle<JSTaggedValue> parent = env->GetFunctionPrototype(); 1709 JSObject::SetPrototype(thread, JSHandle<JSObject>::Cast(current), parent); 1710 current->SetHomeObject(thread, clsPrototype); 1711 current->SetCallNapi(callNapi); 1712 Local<FunctionRef> result = JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current)); 1713 return scope.Escape(result); 1714 } 1715 Call(const EcmaVM * vm,Local<JSValueRef> thisObj,const Local<JSValueRef> argv[],int32_t length)1716 Local<JSValueRef> FunctionRef::Call(const EcmaVM *vm, Local<JSValueRef> thisObj, 1717 const Local<JSValueRef> argv[], // NOLINTNEXTLINE(modernize-avoid-c-arrays) 1718 int32_t length) 1719 { 1720 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1721 EscapeLocalScope scope(vm); 1722 FunctionCallScope callScope(EcmaVM::ConstCast(vm)); 1723 JSThread *thread = vm->GetJSThread(); 1724 if (!IsFunction()) { 1725 return JSValueRef::Undefined(vm); 1726 } 1727 vm->GetJsDebuggerManager()->ClearSingleStepper(); 1728 JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this); 1729 LOG_IF_SPECIAL(func, ERROR); 1730 JSHandle<JSTaggedValue> thisValue = JSNApiHelper::ToJSHandle(thisObj); 1731 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 1732 EcmaRuntimeCallInfo *info = 1733 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisValue, undefined, length); 1734 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 1735 for (int32_t i = 0; i < length; i++) { 1736 JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(argv[i]); 1737 info->SetCallArg(i, arg.GetTaggedValue()); 1738 } 1739 JSTaggedValue result = JSFunction::Call(info); 1740 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 1741 JSHandle<JSTaggedValue> resultValue(thread, result); 1742 1743 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 1744 vm->GetHeap()->ClearKeptObjects(); 1745 1746 return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(resultValue)); 1747 } 1748 Constructor(const EcmaVM * vm,const Local<JSValueRef> argv[],int32_t length)1749 Local<JSValueRef> FunctionRef::Constructor(const EcmaVM *vm, 1750 const Local<JSValueRef> argv[], // NOLINTNEXTLINE(modernize-avoid-c-arrays) 1751 int32_t length) 1752 { 1753 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1754 FunctionCallScope callScope(EcmaVM::ConstCast(vm)); 1755 JSThread *thread = vm->GetJSThread(); 1756 if (!IsFunction()) { 1757 return JSValueRef::Undefined(vm); 1758 } 1759 JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this); 1760 LOG_IF_SPECIAL(func, ERROR); 1761 JSHandle<JSTaggedValue> newTarget = func; 1762 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 1763 EcmaRuntimeCallInfo *info = 1764 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, undefined, newTarget, length); 1765 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 1766 for (int32_t i = 0; i < length; i++) { 1767 JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(argv[i]); 1768 info->SetCallArg(i, arg.GetTaggedValue()); 1769 } 1770 JSTaggedValue result = JSFunction::Construct(info); 1771 1772 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 1773 JSHandle<JSTaggedValue> resultValue(thread, result); 1774 return JSNApiHelper::ToLocal<JSValueRef>(resultValue); 1775 } 1776 GetFunctionPrototype(const EcmaVM * vm)1777 Local<JSValueRef> FunctionRef::GetFunctionPrototype(const EcmaVM *vm) 1778 { 1779 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1780 JSThread *thread = vm->GetJSThread(); 1781 JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this); 1782 LOG_IF_SPECIAL(func, FATAL); 1783 JSHandle<JSTaggedValue> prototype(thread, JSHandle<JSFunction>(func)->GetFunctionPrototype()); 1784 return JSNApiHelper::ToLocal<JSValueRef>(prototype); 1785 } 1786 Inherit(const EcmaVM * vm,Local<FunctionRef> parent)1787 bool FunctionRef::Inherit(const EcmaVM *vm, Local<FunctionRef> parent) 1788 { 1789 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1790 [[maybe_unused]] LocalScope scope(vm); 1791 JSThread *thread = vm->GetJSThread(); 1792 JSHandle<JSTaggedValue> parentValue = JSNApiHelper::ToJSHandle(parent); 1793 JSHandle<JSObject> parentHandle = JSHandle<JSObject>::Cast(parentValue); 1794 JSHandle<JSObject> thisHandle = JSHandle<JSObject>::Cast(JSNApiHelper::ToJSHandle(this)); 1795 LOG_IF_SPECIAL(thisHandle, ERROR); 1796 // Set this.__proto__ to parent 1797 bool res = JSObject::SetPrototype(thread, thisHandle, parentValue); 1798 if (!res) { 1799 return false; 1800 } 1801 // Set this.Prototype.__proto__ to parent.Prototype 1802 JSHandle<JSTaggedValue> parentProtoType(thread, JSFunction::PrototypeGetter(thread, parentHandle)); 1803 JSHandle<JSTaggedValue> thisProtoType(thread, JSFunction::PrototypeGetter(thread, thisHandle)); 1804 return JSObject::SetPrototype(thread, JSHandle<JSObject>::Cast(thisProtoType), parentProtoType); 1805 } 1806 SetName(const EcmaVM * vm,Local<StringRef> name)1807 void FunctionRef::SetName(const EcmaVM *vm, Local<StringRef> name) 1808 { 1809 CHECK_HAS_PENDING_EXCEPTION_WITHOUT_RETURN(vm); 1810 [[maybe_unused]] LocalScope scope(vm); 1811 JSThread *thread = vm->GetJSThread(); 1812 JSFunction *func = JSFunction::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject()); 1813 JSTaggedValue key = JSNApiHelper::ToJSTaggedValue(*name); 1814 JSFunction::SetFunctionNameNoPrefix(thread, func, key); 1815 } 1816 GetName(const EcmaVM * vm)1817 Local<StringRef> FunctionRef::GetName(const EcmaVM *vm) 1818 { 1819 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1820 EscapeLocalScope scope(vm); 1821 JSThread *thread = vm->GetJSThread(); 1822 JSHandle<JSFunctionBase> func(thread, JSNApiHelper::ToJSTaggedValue(this)); 1823 JSHandle<JSTaggedValue> name = JSFunctionBase::GetFunctionName(thread, func); 1824 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 1825 return scope.Escape(JSNApiHelper::ToLocal<StringRef>(name)); 1826 } 1827 GetSourceCode(const EcmaVM * vm,int lineNumber)1828 Local<StringRef> FunctionRef::GetSourceCode(const EcmaVM *vm, int lineNumber) 1829 { 1830 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1831 EscapeLocalScope scope(vm); 1832 JSThread *thread = vm->GetJSThread(); 1833 JSHandle<JSFunctionBase> func(thread, JSNApiHelper::ToJSTaggedValue(this)); 1834 JSHandle<Method> method(thread, func->GetMethod()); 1835 const JSPandaFile *jsPandaFile = method->GetJSPandaFile(); 1836 DebugInfoExtractor *debugExtractor = JSPandaFileManager::GetInstance()->GetJSPtExtractor(jsPandaFile); 1837 ecmascript::CString entry = JSPandaFile::ENTRY_FUNCTION_NAME; 1838 if (!jsPandaFile->IsBundlePack()) { 1839 JSFunction *function = JSFunction::Cast(func.GetTaggedValue().GetTaggedObject()); 1840 JSTaggedValue recordName = function->GetRecordName(); 1841 ASSERT(!recordName.IsHole()); 1842 entry = ConvertToString(recordName); 1843 } 1844 1845 uint32_t mainMethodIndex = jsPandaFile->GetMainMethodIndex(entry); 1846 JSMutableHandle<JSTaggedValue> sourceCodeHandle(thread, BuiltinsBase::GetTaggedString(thread, "")); 1847 if (mainMethodIndex == 0) { 1848 return scope.Escape(JSNApiHelper::ToLocal<StringRef>(sourceCodeHandle)); 1849 } 1850 1851 const std::string &allSourceCode = debugExtractor->GetSourceCode(panda_file::File::EntityId(mainMethodIndex)); 1852 std::string sourceCode = StringHelper::GetSpecifiedLine(allSourceCode, lineNumber); 1853 uint32_t codeLen = sourceCode.length(); 1854 if (codeLen == 0) { 1855 return scope.Escape(JSNApiHelper::ToLocal<StringRef>(sourceCodeHandle)); 1856 } 1857 1858 if (sourceCode[codeLen - 1] == '\r') { 1859 sourceCode = sourceCode.substr(0, codeLen - 1); 1860 } 1861 sourceCodeHandle.Update(BuiltinsBase::GetTaggedString(thread, sourceCode.c_str())); 1862 return scope.Escape(JSNApiHelper::ToLocal<StringRef>(sourceCodeHandle)); 1863 } 1864 IsNative(const EcmaVM * vm)1865 bool FunctionRef::IsNative(const EcmaVM *vm) 1866 { 1867 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1868 JSThread *thread = vm->GetJSThread(); 1869 JSHandle<JSFunctionBase> func(thread, JSNApiHelper::ToJSTaggedValue(this)); 1870 JSHandle<Method> method(thread, func->GetMethod()); 1871 return method->IsNativeWithCallField(); 1872 } 1873 1874 // ----------------------------------- ArrayRef ---------------------------------------- New(const EcmaVM * vm,uint32_t length)1875 Local<ArrayRef> ArrayRef::New(const EcmaVM *vm, uint32_t length) 1876 { 1877 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1878 JSThread *thread = vm->GetJSThread(); 1879 JSTaggedNumber arrayLen(length); 1880 JSHandle<JSTaggedValue> array = JSArray::ArrayCreate(thread, arrayLen); 1881 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 1882 return JSNApiHelper::ToLocal<ArrayRef>(array); 1883 } 1884 Length(const EcmaVM * vm)1885 uint32_t ArrayRef::Length([[maybe_unused]] const EcmaVM *vm) 1886 { 1887 CHECK_HAS_PENDING_EXCEPTION(vm, 0); 1888 return JSArray::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())->GetArrayLength(); 1889 } 1890 GetValueAt(const EcmaVM * vm,Local<JSValueRef> obj,uint32_t index)1891 Local<JSValueRef> ArrayRef::GetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index) 1892 { 1893 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1894 JSThread *thread = vm->GetJSThread(); 1895 JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(obj); 1896 JSHandle<JSTaggedValue> result = JSArray::FastGetPropertyByValue(thread, object, index); 1897 return JSNApiHelper::ToLocal<JSValueRef>(result); 1898 } 1899 SetValueAt(const EcmaVM * vm,Local<JSValueRef> obj,uint32_t index,Local<JSValueRef> value)1900 bool ArrayRef::SetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index, Local<JSValueRef> value) 1901 { 1902 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1903 JSThread *thread = vm->GetJSThread(); 1904 JSHandle<JSTaggedValue> objectHandle = JSNApiHelper::ToJSHandle(obj); 1905 JSHandle<JSTaggedValue> valueHandle = JSNApiHelper::ToJSHandle(value); 1906 return JSArray::FastSetPropertyByValue(thread, objectHandle, index, valueHandle); 1907 } 1908 1909 // ---------------------------------- Promise -------------------------------------- New(const EcmaVM * vm)1910 Local<PromiseCapabilityRef> PromiseCapabilityRef::New(const EcmaVM *vm) 1911 { 1912 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1913 JSThread *thread = vm->GetJSThread(); 1914 JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv(); 1915 JSHandle<JSTaggedValue> constructor(globalEnv->GetPromiseFunction()); 1916 JSHandle<JSTaggedValue> capability(JSPromise::NewPromiseCapability(thread, constructor)); 1917 return JSNApiHelper::ToLocal<PromiseCapabilityRef>(capability); 1918 } 1919 GetPromise(const EcmaVM * vm)1920 Local<PromiseRef> PromiseCapabilityRef::GetPromise(const EcmaVM *vm) 1921 { 1922 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1923 JSThread *thread = vm->GetJSThread(); 1924 JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this)); 1925 LOG_IF_SPECIAL(capacity, FATAL); 1926 return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, capacity->GetPromise())); 1927 } 1928 Resolve(const EcmaVM * vm,Local<JSValueRef> value)1929 bool PromiseCapabilityRef::Resolve(const EcmaVM *vm, Local<JSValueRef> value) 1930 { 1931 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1932 JSThread *thread = vm->GetJSThread(); 1933 const GlobalEnvConstants *constants = thread->GlobalConstants(); 1934 1935 JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(value); 1936 JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this)); 1937 LOG_IF_SPECIAL(capacity, FATAL); 1938 JSHandle<JSTaggedValue> resolve(thread, capacity->GetResolve()); 1939 JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined()); 1940 EcmaRuntimeCallInfo *info = 1941 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, resolve, undefined, undefined, 1); 1942 RETURN_VALUE_IF_ABRUPT(thread, false); 1943 info->SetCallArg(arg.GetTaggedValue()); 1944 JSFunction::Call(info); 1945 RETURN_VALUE_IF_ABRUPT(thread, false); 1946 1947 thread->GetCurrentEcmaContext()->ExecutePromisePendingJob(); 1948 RETURN_VALUE_IF_ABRUPT(thread, false); 1949 vm->GetHeap()->ClearKeptObjects(); 1950 return true; 1951 } 1952 Reject(const EcmaVM * vm,Local<JSValueRef> reason)1953 bool PromiseCapabilityRef::Reject(const EcmaVM *vm, Local<JSValueRef> reason) 1954 { 1955 CHECK_HAS_PENDING_EXCEPTION(vm, false); 1956 JSThread *thread = vm->GetJSThread(); 1957 const GlobalEnvConstants *constants = thread->GlobalConstants(); 1958 1959 JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(reason); 1960 JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this)); 1961 LOG_IF_SPECIAL(capacity, FATAL); 1962 JSHandle<JSTaggedValue> reject(thread, capacity->GetReject()); 1963 JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined()); 1964 1965 EcmaRuntimeCallInfo *info = 1966 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, reject, undefined, undefined, 1); 1967 RETURN_VALUE_IF_ABRUPT(thread, false); 1968 info->SetCallArg(arg.GetTaggedValue()); 1969 JSFunction::Call(info); 1970 RETURN_VALUE_IF_ABRUPT(thread, false); 1971 1972 thread->GetCurrentEcmaContext()->ExecutePromisePendingJob(); 1973 RETURN_VALUE_IF_ABRUPT(thread, false); 1974 vm->GetHeap()->ClearKeptObjects(); 1975 return true; 1976 } 1977 Catch(const EcmaVM * vm,Local<FunctionRef> handler)1978 Local<PromiseRef> PromiseRef::Catch(const EcmaVM *vm, Local<FunctionRef> handler) 1979 { 1980 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 1981 JSThread *thread = vm->GetJSThread(); 1982 const GlobalEnvConstants *constants = thread->GlobalConstants(); 1983 1984 JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this); 1985 LOG_IF_SPECIAL(promise, ERROR); 1986 JSHandle<JSTaggedValue> catchKey(thread, constants->GetPromiseCatchString()); 1987 JSHandle<JSTaggedValue> reject = JSNApiHelper::ToJSHandle(handler); 1988 JSHandle<JSTaggedValue> undefined = constants->GetHandledUndefined(); 1989 EcmaRuntimeCallInfo *info = 1990 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 1); 1991 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 1992 info->SetCallArg(reject.GetTaggedValue()); 1993 JSTaggedValue result = JSFunction::Invoke(info, catchKey); 1994 1995 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 1996 return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result)); 1997 } 1998 Finally(const EcmaVM * vm,Local<FunctionRef> handler)1999 Local<PromiseRef> PromiseRef::Finally(const EcmaVM *vm, Local<FunctionRef> handler) 2000 { 2001 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2002 JSThread *thread = vm->GetJSThread(); 2003 const GlobalEnvConstants *constants = thread->GlobalConstants(); 2004 2005 JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this); 2006 LOG_IF_SPECIAL(promise, ERROR); 2007 JSHandle<JSTaggedValue> finallyKey = constants->GetHandledPromiseFinallyString(); 2008 JSHandle<JSTaggedValue> resolver = JSNApiHelper::ToJSHandle(handler); 2009 JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined()); 2010 EcmaRuntimeCallInfo *info = 2011 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 2); // 2: two args 2012 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2013 info->SetCallArg(resolver.GetTaggedValue(), undefined.GetTaggedValue()); 2014 JSTaggedValue result = JSFunction::Invoke(info, finallyKey); 2015 2016 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2017 return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result)); 2018 } 2019 Then(const EcmaVM * vm,Local<FunctionRef> handler)2020 Local<PromiseRef> PromiseRef::Then(const EcmaVM *vm, Local<FunctionRef> handler) 2021 { 2022 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2023 JSThread *thread = vm->GetJSThread(); 2024 const GlobalEnvConstants *constants = thread->GlobalConstants(); 2025 2026 JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this); 2027 LOG_IF_SPECIAL(promise, ERROR); 2028 JSHandle<JSTaggedValue> thenKey(thread, constants->GetPromiseThenString()); 2029 JSHandle<JSTaggedValue> resolver = JSNApiHelper::ToJSHandle(handler); 2030 JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined()); 2031 EcmaRuntimeCallInfo *info = 2032 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 2); // 2: two args 2033 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2034 info->SetCallArg(resolver.GetTaggedValue(), undefined.GetTaggedValue()); 2035 JSTaggedValue result = JSFunction::Invoke(info, thenKey); 2036 2037 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2038 return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result)); 2039 } 2040 Then(const EcmaVM * vm,Local<FunctionRef> onFulfilled,Local<FunctionRef> onRejected)2041 Local<PromiseRef> PromiseRef::Then(const EcmaVM *vm, Local<FunctionRef> onFulfilled, Local<FunctionRef> onRejected) 2042 { 2043 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2044 JSThread *thread = vm->GetJSThread(); 2045 const GlobalEnvConstants *constants = thread->GlobalConstants(); 2046 2047 JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this); 2048 LOG_IF_SPECIAL(promise, ERROR); 2049 JSHandle<JSTaggedValue> thenKey(thread, constants->GetPromiseThenString()); 2050 JSHandle<JSTaggedValue> resolver = JSNApiHelper::ToJSHandle(onFulfilled); 2051 JSHandle<JSTaggedValue> reject = JSNApiHelper::ToJSHandle(onRejected); 2052 JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined()); 2053 EcmaRuntimeCallInfo *info = 2054 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 2); // 2: two args 2055 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2056 info->SetCallArg(resolver.GetTaggedValue(), reject.GetTaggedValue()); 2057 JSTaggedValue result = JSFunction::Invoke(info, thenKey); 2058 2059 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2060 return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result)); 2061 } 2062 // ---------------------------------- Promise ------------------------------------- 2063 2064 // ---------------------------------- Buffer ----------------------------------- New(const EcmaVM * vm,int32_t length)2065 Local<ArrayBufferRef> ArrayBufferRef::New(const EcmaVM *vm, int32_t length) 2066 { 2067 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2068 ObjectFactory *factory = vm->GetFactory(); 2069 JSHandle<JSArrayBuffer> arrayBuffer = factory->NewJSArrayBuffer(length); 2070 return JSNApiHelper::ToLocal<ArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer)); 2071 } 2072 New(const EcmaVM * vm,void * buffer,int32_t length,const Deleter & deleter,void * data)2073 Local<ArrayBufferRef> ArrayBufferRef::New( 2074 const EcmaVM *vm, void *buffer, int32_t length, const Deleter &deleter, void *data) 2075 { 2076 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2077 ObjectFactory *factory = vm->GetFactory(); 2078 JSHandle<JSArrayBuffer> arrayBuffer = 2079 factory->NewJSArrayBuffer(buffer, length, reinterpret_cast<ecmascript::DeleteEntryPoint>(deleter), data); 2080 return JSNApiHelper::ToLocal<ArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer)); 2081 } 2082 ByteLength(const EcmaVM * vm)2083 int32_t ArrayBufferRef::ByteLength([[maybe_unused]] const EcmaVM *vm) 2084 { 2085 CHECK_HAS_PENDING_EXCEPTION(vm, 0); 2086 JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this)); 2087 LOG_IF_SPECIAL(arrayBuffer, FATAL); 2088 return arrayBuffer->GetArrayBufferByteLength(); 2089 } 2090 GetBuffer()2091 void *ArrayBufferRef::GetBuffer() 2092 { 2093 JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this)); 2094 LOG_IF_SPECIAL(arrayBuffer, FATAL); 2095 JSTaggedValue bufferData = arrayBuffer->GetArrayBufferData(); 2096 if (!bufferData.IsJSNativePointer()) { 2097 return nullptr; 2098 } 2099 return JSNativePointer::Cast(bufferData.GetTaggedObject())->GetExternalPointer(); 2100 } 2101 Detach(const EcmaVM * vm)2102 void ArrayBufferRef::Detach(const EcmaVM *vm) 2103 { 2104 JSThread *thread = vm->GetJSThread(); 2105 JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this)); 2106 arrayBuffer->Detach(thread); 2107 } 2108 IsDetach()2109 bool ArrayBufferRef::IsDetach() 2110 { 2111 JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this)); 2112 return arrayBuffer->IsDetach(); 2113 } 2114 BufferToStringCallback(ecmascript::EcmaRuntimeCallInfo * ecmaRuntimeCallInfo)2115 JSTaggedValue BufferRef::BufferToStringCallback(ecmascript::EcmaRuntimeCallInfo *ecmaRuntimeCallInfo) 2116 { 2117 JSThread *thread = ecmaRuntimeCallInfo->GetThread(); 2118 [[maybe_unused]] LocalScope scope(thread->GetEcmaVM()); 2119 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 2120 JSHandle<JSTaggedValue> arrayBuff = ecmaRuntimeCallInfo->GetThis(); 2121 JSHandle<JSArrayBuffer> arrayBuffer(arrayBuff); 2122 2123 uint32_t length = arrayBuffer->GetArrayBufferByteLength(); 2124 JSTaggedValue data = arrayBuffer->GetArrayBufferData(); 2125 2126 ecmascript::CVector<uint16_t> valueTable; 2127 valueTable.reserve(length); 2128 for (uint32_t i = 0; i < length; i++) { 2129 void* rawData = reinterpret_cast<void *>( 2130 ToUintPtr(JSNativePointer::Cast(data.GetTaggedObject())->GetExternalPointer()) + i); 2131 uint8_t *block = reinterpret_cast<uint8_t *>(rawData); 2132 uint16_t nextCv = static_cast<uint16_t>(*block); 2133 valueTable.emplace_back(nextCv); 2134 } 2135 2136 auto *char16tData0 = reinterpret_cast<const char16_t *>(valueTable.data()); 2137 std::u16string u16str(char16tData0, length); 2138 2139 const char16_t *constChar16tData = u16str.data(); 2140 auto *char16tData = const_cast<char16_t *>(constChar16tData); 2141 auto *uint16tData = reinterpret_cast<uint16_t *>(char16tData); 2142 uint32_t u16strSize = u16str.size(); 2143 JSTaggedValue rString = factory->NewFromUtf16Literal(uint16tData, u16strSize).GetTaggedValue(); 2144 JSHandle<EcmaString> StringHandle = JSTaggedValue::ToString(thread, rString); 2145 RETURN_VALUE_IF_ABRUPT(thread, JSTaggedValue::Undefined()); 2146 return StringHandle.GetTaggedValue(); 2147 } 2148 New(const EcmaVM * vm,int32_t length)2149 Local<BufferRef> BufferRef::New(const EcmaVM *vm, int32_t length) 2150 { 2151 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2152 ObjectFactory *factory = vm->GetFactory(); 2153 JSThread *thread = vm->GetJSThread(); 2154 JSHandle<JSArrayBuffer> arrayBuffer = JSHandle<JSArrayBuffer>::Cast(factory->NewJSArrayBuffer(length)); 2155 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 2156 JSHandle<JSFunction> current = 2157 factory->NewJSFunction(env, reinterpret_cast<void *>(BufferRef::BufferToStringCallback)); 2158 Local<StringRef> key = StringRef::NewFromUtf8(vm, "toString"); 2159 JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key); 2160 JSHandle<JSTaggedValue> currentTaggedValue(current); 2161 JSHandle<JSTaggedValue> obj(arrayBuffer); 2162 bool result = JSTaggedValue::SetProperty(vm->GetJSThread(), obj, keyValue, currentTaggedValue); 2163 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2164 if (!result) { 2165 LOG_ECMA(ERROR) << "SetProperty failed ! ! !"; 2166 } 2167 return JSNApiHelper::ToLocal<BufferRef>(obj); 2168 } 2169 New(const EcmaVM * vm,void * buffer,int32_t length,const Deleter & deleter,void * data)2170 Local<BufferRef> BufferRef::New( 2171 const EcmaVM *vm, void *buffer, int32_t length, const Deleter &deleter, void *data) 2172 { 2173 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2174 ObjectFactory *factory = vm->GetFactory(); 2175 JSThread *thread = vm->GetJSThread(); 2176 JSHandle<JSArrayBuffer> arrayBuffer = 2177 factory->NewJSArrayBuffer(buffer, length, reinterpret_cast<ecmascript::DeleteEntryPoint>(deleter), data); 2178 2179 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 2180 JSHandle<JSFunction> current = 2181 factory->NewJSFunction(env, reinterpret_cast<void *>(BufferRef::BufferToStringCallback)); 2182 Local<StringRef> key = StringRef::NewFromUtf8(vm, "toString"); 2183 JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key); 2184 JSHandle<JSTaggedValue> currentTaggedValue(current); 2185 JSHandle<JSTaggedValue> obj(arrayBuffer); 2186 bool result = JSTaggedValue::SetProperty(vm->GetJSThread(), obj, keyValue, currentTaggedValue); 2187 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2188 if (!result) { 2189 LOG_ECMA(ERROR) << "SetProperty failed ! ! !"; 2190 } 2191 return JSNApiHelper::ToLocal<ArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer)); 2192 } 2193 ByteLength(const EcmaVM * vm)2194 int32_t BufferRef::ByteLength([[maybe_unused]] const EcmaVM *vm) 2195 { 2196 JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this)); 2197 LOG_IF_SPECIAL(arrayBuffer, FATAL); 2198 return arrayBuffer->GetArrayBufferByteLength(); 2199 } 2200 GetBuffer()2201 void *BufferRef::GetBuffer() 2202 { 2203 JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this)); 2204 LOG_IF_SPECIAL(arrayBuffer, FATAL); 2205 JSTaggedValue bufferData = arrayBuffer->GetArrayBufferData(); 2206 if (!bufferData.IsJSNativePointer()) { 2207 return nullptr; 2208 } 2209 return JSNativePointer::Cast(bufferData.GetTaggedObject())->GetExternalPointer(); 2210 } 2211 // ---------------------------------- Buffer ----------------------------------- 2212 2213 // ---------------------------------- DataView ----------------------------------- New(const EcmaVM * vm,Local<ArrayBufferRef> arrayBuffer,uint32_t byteOffset,uint32_t byteLength)2214 Local<DataViewRef> DataViewRef::New( 2215 const EcmaVM *vm, Local<ArrayBufferRef> arrayBuffer, uint32_t byteOffset, uint32_t byteLength) 2216 { 2217 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2218 JSThread *thread = vm->GetJSThread(); 2219 ObjectFactory *factory = vm->GetFactory(); 2220 2221 JSHandle<JSArrayBuffer> buffer(JSNApiHelper::ToJSHandle(arrayBuffer)); 2222 JSHandle<JSDataView> dataView = factory->NewJSDataView(buffer, byteOffset, byteLength); 2223 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2224 return JSNApiHelper::ToLocal<DataViewRef>(JSHandle<JSTaggedValue>(dataView)); 2225 } 2226 ByteLength()2227 uint32_t DataViewRef::ByteLength() 2228 { 2229 JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this)); 2230 LOG_IF_SPECIAL(dataView, FATAL); 2231 return dataView->GetByteLength(); 2232 } 2233 ByteOffset()2234 uint32_t DataViewRef::ByteOffset() 2235 { 2236 JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this)); 2237 LOG_IF_SPECIAL(dataView, FATAL); 2238 return dataView->GetByteOffset(); 2239 } 2240 GetArrayBuffer(const EcmaVM * vm)2241 Local<ArrayBufferRef> DataViewRef::GetArrayBuffer(const EcmaVM *vm) 2242 { 2243 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2244 JSThread *thread = vm->GetJSThread(); 2245 JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this)); 2246 LOG_IF_SPECIAL(dataView, FATAL); 2247 JSHandle<JSTaggedValue> arrayBuffer(thread, dataView->GetViewedArrayBuffer()); 2248 return JSNApiHelper::ToLocal<ArrayBufferRef>(arrayBuffer); 2249 } 2250 // ---------------------------------- DataView ----------------------------------- 2251 2252 // ---------------------------------- TypedArray ----------------------------------- ByteLength(const EcmaVM * vm)2253 uint32_t TypedArrayRef::ByteLength([[maybe_unused]] const EcmaVM *vm) 2254 { 2255 CHECK_HAS_PENDING_EXCEPTION(vm, 0); 2256 JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this)); 2257 LOG_IF_SPECIAL(typedArray, FATAL); 2258 return typedArray->GetByteLength(); 2259 } 2260 ByteOffset(const EcmaVM * vm)2261 uint32_t TypedArrayRef::ByteOffset([[maybe_unused]] const EcmaVM *vm) 2262 { 2263 CHECK_HAS_PENDING_EXCEPTION(vm, 0); 2264 JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this)); 2265 LOG_IF_SPECIAL(typedArray, FATAL); 2266 return typedArray->GetByteOffset(); 2267 } 2268 ArrayLength(const EcmaVM * vm)2269 uint32_t TypedArrayRef::ArrayLength([[maybe_unused]] const EcmaVM *vm) 2270 { 2271 CHECK_HAS_PENDING_EXCEPTION(vm, 0); 2272 JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this)); 2273 LOG_IF_SPECIAL(typedArray, FATAL); 2274 return typedArray->GetArrayLength(); 2275 } 2276 GetArrayBuffer(const EcmaVM * vm)2277 Local<ArrayBufferRef> TypedArrayRef::GetArrayBuffer(const EcmaVM *vm) 2278 { 2279 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2280 JSThread *thread = vm->GetJSThread(); 2281 JSHandle<JSTypedArray> typeArray(JSNApiHelper::ToJSHandle(this)); 2282 LOG_IF_SPECIAL(typeArray, ERROR); 2283 JSHandle<JSTaggedValue> arrayBuffer(thread, JSTypedArray::GetOffHeapBuffer(thread, typeArray)); 2284 return JSNApiHelper::ToLocal<ArrayBufferRef>(arrayBuffer); 2285 } 2286 2287 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 2288 #define TYPED_ARRAY_NEW(Type) \ 2289 Local<Type##Ref> Type##Ref::New( \ 2290 const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset, int32_t length) \ 2291 { \ 2292 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); \ 2293 JSThread *thread = vm->GetJSThread(); \ 2294 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); \ 2295 \ 2296 JSHandle<JSTaggedValue> func = env->Get##Type##Function(); \ 2297 JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(buffer)); \ 2298 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); \ 2299 const uint32_t argsLength = 3; \ 2300 EcmaRuntimeCallInfo *info = \ 2301 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, undefined, func, argsLength); \ 2302 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); \ 2303 info->SetCallArg(arrayBuffer.GetTaggedValue(), JSTaggedValue(byteOffset), JSTaggedValue(length)); \ 2304 JSTaggedValue result = JSFunction::Construct(info); \ 2305 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); \ 2306 JSHandle<JSTaggedValue> resultHandle(thread, result); \ 2307 return JSNApiHelper::ToLocal<Type##Ref>(resultHandle); \ 2308 } 2309 2310 TYPED_ARRAY_ALL(TYPED_ARRAY_NEW) 2311 2312 #undef TYPED_ARRAY_NEW 2313 // ---------------------------------- TypedArray ----------------------------------- 2314 2315 // ---------------------------------- Error --------------------------------------- 2316 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 2317 #define EXCEPTION_ERROR_NEW(name, type) \ 2318 Local<JSValueRef> Exception::name(const EcmaVM *vm, Local<StringRef> message) \ 2319 { \ 2320 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); \ 2321 JSThread *thread = vm->GetJSThread(); \ 2322 if (thread->HasPendingException()) { \ 2323 thread->ClearException(); \ 2324 } \ 2325 ObjectFactory *factory = vm->GetFactory(); \ 2326 \ 2327 JSHandle<EcmaString> messageValue(JSNApiHelper::ToJSHandle(message)); \ 2328 JSHandle<JSTaggedValue> result(factory->NewJSError(ErrorType::type, messageValue)); \ 2329 return JSNApiHelper::ToLocal<JSValueRef>(result); \ 2330 } 2331 EXCEPTION_ERROR_ALL(EXCEPTION_ERROR_NEW)2332 EXCEPTION_ERROR_ALL(EXCEPTION_ERROR_NEW) 2333 2334 #undef EXCEPTION_ERROR_NEW 2335 // ---------------------------------- Error --------------------------------------- 2336 2337 // ---------------------------------- JSON ------------------------------------------ 2338 Local<JSValueRef> JSON::Parse(const EcmaVM *vm, Local<StringRef> string) 2339 { 2340 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2341 JSThread *thread = vm->GetJSThread(); 2342 auto ecmaStr = EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(*string).GetTaggedObject()); 2343 JSHandle<JSTaggedValue> result; 2344 if (EcmaStringAccessor(ecmaStr).IsUtf8()) { 2345 JsonParser<uint8_t> parser(thread); 2346 result = parser.ParseUtf8(EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(*string).GetTaggedObject())); 2347 } else { 2348 JsonParser<uint16_t> parser(thread); 2349 result = parser.ParseUtf16(EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(*string).GetTaggedObject())); 2350 } 2351 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2352 return JSNApiHelper::ToLocal<JSValueRef>(result); 2353 } 2354 Stringify(const EcmaVM * vm,Local<JSValueRef> json)2355 Local<JSValueRef> JSON::Stringify(const EcmaVM *vm, Local<JSValueRef> json) 2356 { 2357 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2358 JSThread *thread = vm->GetJSThread(); 2359 auto constants = thread->GlobalConstants(); 2360 JsonStringifier stringifier(thread); 2361 JSHandle<JSTaggedValue> str = stringifier.Stringify( 2362 JSNApiHelper::ToJSHandle(json), constants->GetHandledUndefined(), constants->GetHandledUndefined()); 2363 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2364 return JSNApiHelper::ToLocal<JSValueRef>(str); 2365 } 2366 GetOriginalSource(const EcmaVM * vm)2367 Local<StringRef> RegExpRef::GetOriginalSource(const EcmaVM *vm) 2368 { 2369 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2370 JSThread *thread = vm->GetJSThread(); 2371 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this)); 2372 LOG_IF_SPECIAL(regExp, FATAL); 2373 JSTaggedValue source = regExp->GetOriginalSource(); 2374 if (!source.IsString()) { 2375 auto constants = thread->GlobalConstants(); 2376 return JSNApiHelper::ToLocal<StringRef>(constants->GetHandledEmptyString()); 2377 } 2378 JSHandle<JSTaggedValue> sourceHandle(thread, source); 2379 return JSNApiHelper::ToLocal<StringRef>(sourceHandle); 2380 } 2381 GetOriginalFlags()2382 std::string RegExpRef::GetOriginalFlags() 2383 { 2384 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this)); 2385 LOG_IF_SPECIAL(regExp, FATAL); 2386 JSTaggedValue regExpFlags = regExp->GetOriginalFlags(); 2387 uint32_t regExpFlagsInt = static_cast<uint32_t>(regExpFlags.GetInt()); 2388 std::string strFlags = ""; 2389 if (regExpFlagsInt & RegExpParser::FLAG_GLOBAL) { 2390 strFlags += "g"; 2391 } 2392 if (regExpFlagsInt & RegExpParser::FLAG_IGNORECASE) { 2393 strFlags += "i"; 2394 } 2395 if (regExpFlagsInt & RegExpParser::FLAG_MULTILINE) { 2396 strFlags += "m"; 2397 } 2398 if (regExpFlagsInt & RegExpParser::FLAG_DOTALL) { 2399 strFlags += "s"; 2400 } 2401 if (regExpFlagsInt & RegExpParser::FLAG_UTF16) { 2402 strFlags += "u"; 2403 } 2404 if (regExpFlagsInt & RegExpParser::FLAG_STICKY) { 2405 strFlags += "y"; 2406 } 2407 std::sort(strFlags.begin(), strFlags.end()); 2408 return strFlags; 2409 } 2410 IsGlobal(const EcmaVM * vm)2411 Local<JSValueRef> RegExpRef::IsGlobal(const EcmaVM *vm) 2412 { 2413 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2414 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this)); 2415 LOG_IF_SPECIAL(regExp, FATAL); 2416 JSTaggedValue flags = regExp->GetOriginalFlags(); 2417 bool result = flags.GetInt() & RegExpParser::FLAG_GLOBAL; 2418 Local<JSValueRef> jsValue = BooleanRef::New(vm, result); 2419 return jsValue; 2420 } 2421 IsIgnoreCase(const EcmaVM * vm)2422 Local<JSValueRef> RegExpRef::IsIgnoreCase(const EcmaVM *vm) 2423 { 2424 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2425 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this)); 2426 LOG_IF_SPECIAL(regExp, FATAL); 2427 JSTaggedValue flags = regExp->GetOriginalFlags(); 2428 bool result = flags.GetInt() & RegExpParser::FLAG_IGNORECASE; 2429 Local<JSValueRef> jsValue = BooleanRef::New(vm, result); 2430 return jsValue; 2431 } 2432 IsMultiline(const EcmaVM * vm)2433 Local<JSValueRef> RegExpRef::IsMultiline(const EcmaVM *vm) 2434 { 2435 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2436 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this)); 2437 LOG_IF_SPECIAL(regExp, FATAL); 2438 JSTaggedValue flags = regExp->GetOriginalFlags(); 2439 bool result = flags.GetInt() & RegExpParser::FLAG_MULTILINE; 2440 Local<JSValueRef> jsValue = BooleanRef::New(vm, result); 2441 return jsValue; 2442 } 2443 IsDotAll(const EcmaVM * vm)2444 Local<JSValueRef> RegExpRef::IsDotAll(const EcmaVM *vm) 2445 { 2446 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2447 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this)); 2448 LOG_IF_SPECIAL(regExp, FATAL); 2449 JSTaggedValue flags = regExp->GetOriginalFlags(); 2450 bool result = flags.GetInt() & RegExpParser::FLAG_DOTALL; 2451 Local<JSValueRef> jsValue = BooleanRef::New(vm, result); 2452 return jsValue; 2453 } 2454 IsUtf16(const EcmaVM * vm)2455 Local<JSValueRef> RegExpRef::IsUtf16(const EcmaVM *vm) 2456 { 2457 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2458 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this)); 2459 LOG_IF_SPECIAL(regExp, FATAL); 2460 JSTaggedValue flags = regExp->GetOriginalFlags(); 2461 bool result = flags.GetInt() & RegExpParser::FLAG_UTF16; 2462 Local<JSValueRef> jsValue = BooleanRef::New(vm, result); 2463 return jsValue; 2464 } 2465 IsStick(const EcmaVM * vm)2466 Local<JSValueRef> RegExpRef::IsStick(const EcmaVM *vm) 2467 { 2468 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2469 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this)); 2470 LOG_IF_SPECIAL(regExp, FATAL); 2471 JSTaggedValue flags = regExp->GetOriginalFlags(); 2472 bool result = flags.GetInt() & RegExpParser::FLAG_STICKY; 2473 Local<JSValueRef> jsValue = BooleanRef::New(vm, result); 2474 return jsValue; 2475 } 2476 New(const EcmaVM * vm,double time)2477 Local<DateRef> DateRef::New(const EcmaVM *vm, double time) 2478 { 2479 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2480 JSThread *thread = vm->GetJSThread(); 2481 ObjectFactory *factory = vm->GetFactory(); 2482 JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv(); 2483 JSHandle<JSFunction> dateFunction(globalEnv->GetDateFunction()); 2484 JSHandle<JSDate> dateObject(factory->NewJSObjectByConstructor(dateFunction)); 2485 dateObject->SetTimeValue(thread, JSTaggedValue(time)); 2486 return JSNApiHelper::ToLocal<DateRef>(JSHandle<JSTaggedValue>(dateObject)); 2487 } 2488 ToString(const EcmaVM * vm)2489 Local<StringRef> DateRef::ToString(const EcmaVM *vm) 2490 { 2491 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2492 JSThread *thread = vm->GetJSThread(); 2493 JSHandle<JSDate> date(JSNApiHelper::ToJSHandle(this)); 2494 LOG_IF_SPECIAL(date, ERROR); 2495 JSTaggedValue dateStr = date->ToString(thread); 2496 if (!dateStr.IsString()) { 2497 auto constants = thread->GlobalConstants(); 2498 return JSNApiHelper::ToLocal<StringRef>(constants->GetHandledEmptyString()); 2499 } 2500 JSHandle<JSTaggedValue> dateStrHandle(thread, dateStr); 2501 return JSNApiHelper::ToLocal<StringRef>(dateStrHandle); 2502 } 2503 GetTime()2504 double DateRef::GetTime() 2505 { 2506 JSHandle<JSDate> date(JSNApiHelper::ToJSHandle(this)); 2507 LOG_IF_SPECIAL(date, ERROR); 2508 if (!date->IsDate()) { 2509 LOG_ECMA(ERROR) << "Not a Date Object"; 2510 } 2511 return date->GetTime().GetDouble(); 2512 } 2513 GetHandler(const EcmaVM * vm)2514 Local<JSValueRef> ProxyRef::GetHandler(const EcmaVM *vm) 2515 { 2516 JSHandle<JSProxy> jsProxy(JSNApiHelper::ToJSHandle(this)); 2517 JSThread *thread = vm->GetJSThread(); 2518 return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, jsProxy->GetHandler())); 2519 } 2520 GetTarget(const EcmaVM * vm)2521 Local<JSValueRef> ProxyRef::GetTarget(const EcmaVM *vm) 2522 { 2523 JSHandle<JSProxy> jsProxy(JSNApiHelper::ToJSHandle(this)); 2524 JSThread *thread = vm->GetJSThread(); 2525 return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, jsProxy->GetTarget())); 2526 } 2527 IsRevoked()2528 bool ProxyRef::IsRevoked() 2529 { 2530 JSHandle<JSProxy> jsProxy(JSNApiHelper::ToJSHandle(this)); 2531 return jsProxy->GetIsRevoked(); 2532 } 2533 Get(const EcmaVM * vm,Local<JSValueRef> key)2534 Local<JSValueRef> MapRef::Get(const EcmaVM *vm, Local<JSValueRef> key) 2535 { 2536 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2537 JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this)); 2538 LOG_IF_SPECIAL(map, FATAL); 2539 return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(vm->GetJSThread(), 2540 map->Get(JSNApiHelper::ToJSTaggedValue(*key)))); 2541 } 2542 Set(const EcmaVM * vm,Local<JSValueRef> key,Local<JSValueRef> value)2543 void MapRef::Set(const EcmaVM *vm, Local<JSValueRef> key, Local<JSValueRef> value) 2544 { 2545 CHECK_HAS_PENDING_EXCEPTION_WITHOUT_RETURN(vm); 2546 JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this)); 2547 LOG_IF_SPECIAL(map, ERROR); 2548 JSMap::Set(vm->GetJSThread(), map, JSNApiHelper::ToJSHandle(key), JSNApiHelper::ToJSHandle(value)); 2549 } 2550 New(const EcmaVM * vm)2551 Local<MapRef> MapRef::New(const EcmaVM *vm) 2552 { 2553 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2554 JSThread *thread = vm->GetJSThread(); 2555 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 2556 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 2557 JSHandle<JSTaggedValue> constructor = env->GetBuiltinsMapFunction(); 2558 JSHandle<JSMap> map = 2559 JSHandle<JSMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor)); 2560 JSHandle<LinkedHashMap> hashMap = LinkedHashMap::Create(thread); 2561 map->SetLinkedMap(thread, hashMap); 2562 JSHandle<JSTaggedValue> mapTag = JSHandle<JSTaggedValue>::Cast(map); 2563 return JSNApiHelper::ToLocal<MapRef>(mapTag); 2564 } 2565 GetSize()2566 int32_t MapRef::GetSize() 2567 { 2568 JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this)); 2569 LOG_IF_SPECIAL(map, FATAL); 2570 return map->GetSize(); 2571 } 2572 GetTotalElements()2573 int32_t MapRef::GetTotalElements() 2574 { 2575 JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this)); 2576 LOG_IF_SPECIAL(map, FATAL); 2577 return static_cast<int>((map->GetSize())) + 2578 LinkedHashMap::Cast(map->GetLinkedMap().GetTaggedObject())->NumberOfDeletedElements(); 2579 } 2580 GetKey(const EcmaVM * vm,int entry)2581 Local<JSValueRef> MapRef::GetKey(const EcmaVM *vm, int entry) 2582 { 2583 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2584 JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this)); 2585 LOG_IF_SPECIAL(map, FATAL); 2586 JSThread *thread = vm->GetJSThread(); 2587 return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, map->GetKey(entry))); 2588 } 2589 GetValue(const EcmaVM * vm,int entry)2590 Local<JSValueRef> MapRef::GetValue(const EcmaVM *vm, int entry) 2591 { 2592 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2593 JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this)); 2594 LOG_IF_SPECIAL(map, FATAL); 2595 JSThread *thread = vm->GetJSThread(); 2596 return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, map->GetValue(entry))); 2597 } 2598 GetSize()2599 int32_t WeakMapRef::GetSize() 2600 { 2601 JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this)); 2602 LOG_IF_SPECIAL(weakMap, FATAL); 2603 return weakMap->GetSize(); 2604 } 2605 GetTotalElements()2606 int32_t WeakMapRef::GetTotalElements() 2607 { 2608 JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this)); 2609 LOG_IF_SPECIAL(weakMap, FATAL); 2610 return weakMap->GetSize() + 2611 LinkedHashMap::Cast(weakMap->GetLinkedMap().GetTaggedObject())->NumberOfDeletedElements(); 2612 } 2613 GetKey(const EcmaVM * vm,int entry)2614 Local<JSValueRef> WeakMapRef::GetKey(const EcmaVM *vm, int entry) 2615 { 2616 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2617 JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this)); 2618 LOG_IF_SPECIAL(weakMap, FATAL); 2619 JSTaggedValue key = weakMap->GetKey(entry); 2620 JSThread *thread = vm->GetJSThread(); 2621 return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, key.GetWeakRawValue())); 2622 } 2623 GetValue(const EcmaVM * vm,int entry)2624 Local<JSValueRef> WeakMapRef::GetValue(const EcmaVM *vm, int entry) 2625 { 2626 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2627 JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this)); 2628 LOG_IF_SPECIAL(weakMap, FATAL); 2629 JSThread *thread = vm->GetJSThread(); 2630 return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, weakMap->GetValue(entry))); 2631 } 2632 GetSize()2633 int32_t SetRef::GetSize() 2634 { 2635 JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this)); 2636 LOG_IF_SPECIAL(set, FATAL); 2637 return set->GetSize(); 2638 } 2639 GetTotalElements()2640 int32_t SetRef::GetTotalElements() 2641 { 2642 JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this)); 2643 LOG_IF_SPECIAL(set, FATAL); 2644 return static_cast<int>(set->GetSize()) + 2645 LinkedHashSet::Cast(set->GetLinkedSet().GetTaggedObject())->NumberOfDeletedElements(); 2646 } 2647 GetValue(const EcmaVM * vm,int entry)2648 Local<JSValueRef> SetRef::GetValue(const EcmaVM *vm, int entry) 2649 { 2650 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2651 JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this)); 2652 LOG_IF_SPECIAL(set, FATAL); 2653 JSThread *thread = vm->GetJSThread(); 2654 return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, set->GetValue(entry))); 2655 } 2656 GetSize()2657 int32_t WeakSetRef::GetSize() 2658 { 2659 JSHandle<JSWeakSet> weakSet(JSNApiHelper::ToJSHandle(this)); 2660 LOG_IF_SPECIAL(weakSet, FATAL); 2661 return weakSet->GetSize(); 2662 } 2663 GetTotalElements()2664 int32_t WeakSetRef::GetTotalElements() 2665 { 2666 JSHandle<JSWeakSet> weakSet(JSNApiHelper::ToJSHandle(this)); 2667 LOG_IF_SPECIAL(weakSet, FATAL); 2668 return weakSet->GetSize() + 2669 LinkedHashSet::Cast(weakSet->GetLinkedSet().GetTaggedObject())->NumberOfDeletedElements(); 2670 } 2671 GetValue(const EcmaVM * vm,int entry)2672 Local<JSValueRef> WeakSetRef::GetValue(const EcmaVM *vm, int entry) 2673 { 2674 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2675 JSHandle<JSWeakSet> weakSet(JSNApiHelper::ToJSHandle(this)); 2676 LOG_IF_SPECIAL(weakSet, FATAL); 2677 JSTaggedValue value = weakSet->GetValue(entry); 2678 JSThread *thread = vm->GetJSThread(); 2679 return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, value.GetWeakRawValue())); 2680 } 2681 GetIndex()2682 int32_t MapIteratorRef::GetIndex() 2683 { 2684 JSHandle<JSMapIterator> jsMapIter(JSNApiHelper::ToJSHandle(this)); 2685 LOG_IF_SPECIAL(jsMapIter, FATAL); 2686 return jsMapIter->GetNextIndex(); 2687 } 2688 GetKind(const EcmaVM * vm)2689 Local<JSValueRef> MapIteratorRef::GetKind(const EcmaVM *vm) 2690 { 2691 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2692 JSHandle<JSMapIterator> jsMapIter(JSNApiHelper::ToJSHandle(this)); 2693 LOG_IF_SPECIAL(jsMapIter, FATAL); 2694 IterationKind iterKind = jsMapIter->GetIterationKind(); 2695 Local<JSValueRef> result; 2696 switch (iterKind) { 2697 case IterationKind::KEY: 2698 result = StringRef::NewFromUtf8(vm, "keys"); 2699 break; 2700 case IterationKind::VALUE: 2701 result = StringRef::NewFromUtf8(vm, "values"); 2702 break; 2703 case IterationKind::KEY_AND_VALUE: 2704 result = StringRef::NewFromUtf8(vm, "entries"); 2705 break; 2706 default: 2707 break; 2708 } 2709 return result; 2710 } 2711 GetIndex()2712 int32_t SetIteratorRef::GetIndex() 2713 { 2714 JSHandle<JSSetIterator> jsSetIter(JSNApiHelper::ToJSHandle(this)); 2715 LOG_IF_SPECIAL(jsSetIter, FATAL); 2716 return jsSetIter->GetNextIndex(); 2717 } 2718 GetKind(const EcmaVM * vm)2719 Local<JSValueRef> SetIteratorRef::GetKind(const EcmaVM *vm) 2720 { 2721 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2722 JSHandle<JSSetIterator> jsSetIter(JSNApiHelper::ToJSHandle(this)); 2723 LOG_IF_SPECIAL(jsSetIter, FATAL); 2724 IterationKind iterKind = jsSetIter->GetIterationKind(); 2725 Local<JSValueRef> result; 2726 switch (iterKind) { 2727 case IterationKind::KEY: 2728 result = StringRef::NewFromUtf8(vm, "keys"); 2729 break; 2730 case IterationKind::VALUE: 2731 result = StringRef::NewFromUtf8(vm, "values"); 2732 break; 2733 case IterationKind::KEY_AND_VALUE: 2734 result = StringRef::NewFromUtf8(vm, "entries"); 2735 break; 2736 default: 2737 break; 2738 } 2739 return result; 2740 } 2741 IsGenerator()2742 bool GeneratorFunctionRef::IsGenerator() 2743 { 2744 return IsGeneratorFunction(); 2745 } 2746 GetGeneratorState(const EcmaVM * vm)2747 Local<JSValueRef> GeneratorObjectRef::GetGeneratorState(const EcmaVM *vm) 2748 { 2749 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2750 JSHandle<JSGeneratorObject> jsGenerator(JSNApiHelper::ToJSHandle(this)); 2751 LOG_IF_SPECIAL(jsGenerator, FATAL); 2752 if (jsGenerator->GetGeneratorState() == JSGeneratorState::COMPLETED) { 2753 return StringRef::NewFromUtf8(vm, "closed"); 2754 } 2755 return StringRef::NewFromUtf8(vm, "suspended"); 2756 } 2757 GetGeneratorFunction(const EcmaVM * vm)2758 Local<JSValueRef> GeneratorObjectRef::GetGeneratorFunction(const EcmaVM *vm) 2759 { 2760 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2761 JSThread *thread = vm->GetJSThread(); 2762 JSHandle<JSGeneratorObject> jsGenerator(JSNApiHelper::ToJSHandle(this)); 2763 LOG_IF_SPECIAL(jsGenerator, FATAL); 2764 JSHandle<GeneratorContext> generatorContext(thread, jsGenerator->GetGeneratorContext()); 2765 JSTaggedValue jsTagValue = generatorContext->GetMethod(); 2766 return JSNApiHelper::ToLocal<GeneratorFunctionRef>(JSHandle<JSTaggedValue>(thread, jsTagValue)); 2767 } 2768 GetGeneratorReceiver(const EcmaVM * vm)2769 Local<JSValueRef> GeneratorObjectRef::GetGeneratorReceiver(const EcmaVM *vm) 2770 { 2771 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2772 JSThread *thread = vm->GetJSThread(); 2773 JSHandle<JSGeneratorObject> jsGenerator(JSNApiHelper::ToJSHandle(this)); 2774 LOG_IF_SPECIAL(jsGenerator, FATAL); 2775 JSHandle<GeneratorContext> generatorContext(thread, jsGenerator->GetGeneratorContext()); 2776 JSTaggedValue jsTagValue = generatorContext->GetAcc(); 2777 return JSNApiHelper::ToLocal<GeneratorObjectRef>(JSHandle<JSTaggedValue>(thread, jsTagValue)); 2778 } 2779 GetCompareFunction(const EcmaVM * vm)2780 Local<JSValueRef> CollatorRef::GetCompareFunction(const EcmaVM *vm) 2781 { 2782 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2783 JSThread *thread = vm->GetJSThread(); 2784 #ifdef ARK_SUPPORT_INTL 2785 JSHandle<JSCollator> jsCollator(JSNApiHelper::ToJSHandle(this)); 2786 LOG_IF_SPECIAL(jsCollator, FATAL); 2787 JSTaggedValue jsTagValue = jsCollator->GetBoundCompare(); 2788 return JSNApiHelper::ToLocal<CollatorRef>(JSHandle<JSTaggedValue>(thread, jsTagValue)); 2789 #else 2790 LOG_ECMA(ERROR) << "Not support arkcompiler intl"; 2791 return JSNApiHelper::ToLocal<CollatorRef>(JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined())); 2792 #endif 2793 } 2794 GetFormatFunction(const EcmaVM * vm)2795 Local<JSValueRef> DataTimeFormatRef::GetFormatFunction(const EcmaVM *vm) 2796 { 2797 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2798 JSThread *thread = vm->GetJSThread(); 2799 #ifdef ARK_SUPPORT_INTL 2800 JSHandle<JSDateTimeFormat> jsDateTimeFormat(JSNApiHelper::ToJSHandle(this)); 2801 LOG_IF_SPECIAL(jsDateTimeFormat, FATAL); 2802 JSTaggedValue jsTagValue = jsDateTimeFormat->GetBoundFormat(); 2803 return JSNApiHelper::ToLocal<DataTimeFormatRef>(JSHandle<JSTaggedValue>(thread, jsTagValue)); 2804 #else 2805 LOG_ECMA(ERROR) << "Not support arkcompiler intl"; 2806 return JSNApiHelper::ToLocal<DataTimeFormatRef>(JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined())); 2807 #endif 2808 } 2809 GetFormatFunction(const EcmaVM * vm)2810 Local<JSValueRef> NumberFormatRef::GetFormatFunction(const EcmaVM *vm) 2811 { 2812 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2813 JSThread *thread = vm->GetJSThread(); 2814 #ifdef ARK_SUPPORT_INTL 2815 JSHandle<JSNumberFormat> jsNumberFormat(JSNApiHelper::ToJSHandle(this)); 2816 LOG_IF_SPECIAL(jsNumberFormat, FATAL); 2817 JSTaggedValue jsTagValue = jsNumberFormat->GetBoundFormat(); 2818 return JSNApiHelper::ToLocal<NumberFormatRef>(JSHandle<JSTaggedValue>(thread, jsTagValue)); 2819 #else 2820 LOG_ECMA(ERROR) << "Not support arkcompiler intl"; 2821 return JSNApiHelper::ToLocal<NumberFormatRef>(JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined())); 2822 #endif 2823 } 2824 2825 // ----------------------------------- FunctionCallback --------------------------------- RegisterCallback(ecmascript::EcmaRuntimeCallInfo * ecmaRuntimeCallInfo)2826 JSTaggedValue Callback::RegisterCallback(ecmascript::EcmaRuntimeCallInfo *ecmaRuntimeCallInfo) 2827 { 2828 // Constructor 2829 JSThread *thread = ecmaRuntimeCallInfo->GetThread(); 2830 JSHandle<JSTaggedValue> constructor = BuiltinsBase::GetConstructor(ecmaRuntimeCallInfo); 2831 if (!constructor->IsJSFunction()) { 2832 return JSTaggedValue::False(); 2833 } 2834 [[maybe_unused]] LocalScope scope(thread->GetEcmaVM()); 2835 JSHandle<JSFunction> function(constructor); 2836 JSTaggedValue extraInfoValue = function->GetFunctionExtraInfo(); 2837 if (!extraInfoValue.IsJSNativePointer()) { 2838 return JSTaggedValue::False(); 2839 } 2840 JSHandle<JSNativePointer> extraInfo(thread, extraInfoValue); 2841 // callBack 2842 FunctionCallback nativeFunc = reinterpret_cast<FunctionCallback>(extraInfo->GetExternalPointer()); 2843 2844 JsiRuntimeCallInfo jsiRuntimeCallInfo(ecmaRuntimeCallInfo, extraInfo->GetData()); 2845 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER) 2846 bool getStackBeforeCallNapiSuccess = false; 2847 if (thread->GetIsProfiling() && function->IsCallNapi()) { 2848 getStackBeforeCallNapiSuccess = thread->GetEcmaVM()->GetProfiler()->GetStackBeforeCallNapi(thread); 2849 } 2850 #endif 2851 Local<JSValueRef> result = nativeFunc(&jsiRuntimeCallInfo); 2852 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER) 2853 if (thread->GetIsProfiling() && function->IsCallNapi() && getStackBeforeCallNapiSuccess) { 2854 thread->GetEcmaVM()->GetProfiler()->GetStackAfterCallNapi(thread); 2855 } 2856 #endif 2857 return JSNApiHelper::ToJSHandle(result).GetTaggedValue(); 2858 } 2859 2860 // ------------------------------------- JSExecutionScope ------------------------------ JSExecutionScope(const EcmaVM * vm)2861 JSExecutionScope::JSExecutionScope([[maybe_unused]] const EcmaVM *vm) 2862 { 2863 } 2864 ~JSExecutionScope()2865 JSExecutionScope::~JSExecutionScope() 2866 { 2867 lastCurrentThread_ = nullptr; 2868 isRevert_ = false; 2869 } 2870 2871 // ----------------------------------- JSValueRef -------------------------------------- Undefined(const EcmaVM * vm)2872 Local<PrimitiveRef> JSValueRef::Undefined(const EcmaVM *vm) 2873 { 2874 JSThread *thread = vm->GetJSThread(); 2875 const GlobalEnvConstants *constants = thread->GlobalConstants(); 2876 return JSNApiHelper::ToLocal<PrimitiveRef>(constants->GetHandledUndefined()); 2877 } 2878 Null(const EcmaVM * vm)2879 Local<PrimitiveRef> JSValueRef::Null(const EcmaVM *vm) 2880 { 2881 return JSNApiHelper::ToLocal<PrimitiveRef>(JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::Null())); 2882 } 2883 True(const EcmaVM * vm)2884 Local<PrimitiveRef> JSValueRef::True(const EcmaVM *vm) 2885 { 2886 return JSNApiHelper::ToLocal<PrimitiveRef>(JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::True())); 2887 } 2888 False(const EcmaVM * vm)2889 Local<PrimitiveRef> JSValueRef::False(const EcmaVM *vm) 2890 { 2891 return JSNApiHelper::ToLocal<PrimitiveRef>(JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::False())); 2892 } 2893 ToObject(const EcmaVM * vm)2894 Local<ObjectRef> JSValueRef::ToObject(const EcmaVM *vm) 2895 { 2896 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2897 JSThread *thread = vm->GetJSThread(); 2898 if (IsUndefined() || IsNull()) { 2899 return Undefined(vm); 2900 } 2901 JSHandle<JSTaggedValue> obj(JSTaggedValue::ToObject(thread, JSNApiHelper::ToJSHandle(this))); 2902 LOG_IF_SPECIAL(obj, ERROR); 2903 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2904 return JSNApiHelper::ToLocal<ObjectRef>(obj); 2905 } 2906 ToString(const EcmaVM * vm)2907 Local<StringRef> JSValueRef::ToString(const EcmaVM *vm) 2908 { 2909 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2910 JSThread *thread = vm->GetJSThread(); 2911 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 2912 LOG_IF_SPECIAL(obj, ERROR); 2913 if (!obj->IsString()) { 2914 obj = JSHandle<JSTaggedValue>(JSTaggedValue::ToString(thread, obj)); 2915 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2916 } 2917 return JSNApiHelper::ToLocal<StringRef>(obj); 2918 } 2919 ToNativePointer(const EcmaVM * vm)2920 Local<NativePointerRef> JSValueRef::ToNativePointer(const EcmaVM *vm) 2921 { 2922 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2923 JSThread *thread = vm->GetJSThread(); 2924 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 2925 LOG_IF_SPECIAL(obj, ERROR); 2926 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2927 return JSNApiHelper::ToLocal<NativePointerRef>(obj); 2928 } 2929 BooleaValue()2930 bool JSValueRef::BooleaValue() 2931 { 2932 return JSNApiHelper::ToJSTaggedValue(this).ToBoolean(); 2933 } 2934 IntegerValue(const EcmaVM * vm)2935 int64_t JSValueRef::IntegerValue(const EcmaVM *vm) 2936 { 2937 CHECK_HAS_PENDING_EXCEPTION(vm, 0); 2938 JSThread *thread = vm->GetJSThread(); 2939 JSHandle<JSTaggedValue> tagged = JSNApiHelper::ToJSHandle(this); 2940 LOG_IF_SPECIAL(tagged, ERROR); 2941 if (tagged->IsNumber()) { 2942 if (!NumberHelper::IsFinite(tagged.GetTaggedValue()) || NumberHelper::IsNaN(tagged.GetTaggedValue())) { 2943 return 0; 2944 } else { 2945 return NumberHelper::DoubleToInt64(tagged->GetNumber()); 2946 } 2947 } 2948 JSTaggedNumber number = JSTaggedValue::ToInteger(thread, tagged); 2949 RETURN_VALUE_IF_ABRUPT(thread, 0); 2950 return NumberHelper::DoubleToInt64(number.GetNumber()); 2951 } 2952 Uint32Value(const EcmaVM * vm)2953 uint32_t JSValueRef::Uint32Value(const EcmaVM *vm) 2954 { 2955 CHECK_HAS_PENDING_EXCEPTION(vm, 0); 2956 JSThread *thread = vm->GetJSThread(); 2957 uint32_t number = JSTaggedValue::ToUint32(thread, JSNApiHelper::ToJSHandle(this)); 2958 RETURN_VALUE_IF_ABRUPT(thread, 0); 2959 return number; 2960 } 2961 Int32Value(const EcmaVM * vm)2962 int32_t JSValueRef::Int32Value(const EcmaVM *vm) 2963 { 2964 CHECK_HAS_PENDING_EXCEPTION(vm, 0); 2965 JSThread *thread = vm->GetJSThread(); 2966 int32_t number = JSTaggedValue::ToInt32(thread, JSNApiHelper::ToJSHandle(this)); 2967 RETURN_VALUE_IF_ABRUPT(thread, 0); 2968 return number; 2969 } 2970 ToBoolean(const EcmaVM * vm)2971 Local<BooleanRef> JSValueRef::ToBoolean(const EcmaVM *vm) 2972 { 2973 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2974 JSThread *thread = vm->GetJSThread(); 2975 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 2976 LOG_IF_SPECIAL(obj, ERROR); 2977 JSHandle<JSTaggedValue> booleanObj(thread, JSTaggedValue(obj->ToBoolean())); 2978 return JSNApiHelper::ToLocal<BooleanRef>(booleanObj); 2979 } 2980 ToNumber(const EcmaVM * vm)2981 Local<NumberRef> JSValueRef::ToNumber(const EcmaVM *vm) 2982 { 2983 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 2984 JSThread *thread = vm->GetJSThread(); 2985 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 2986 LOG_IF_SPECIAL(obj, ERROR); 2987 JSHandle<JSTaggedValue> number(thread, JSTaggedValue::ToNumber(thread, obj)); 2988 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); 2989 return JSNApiHelper::ToLocal<NumberRef>(number); 2990 } 2991 IsStrictEquals(const EcmaVM * vm,Local<JSValueRef> value)2992 bool JSValueRef::IsStrictEquals(const EcmaVM *vm, Local<JSValueRef> value) 2993 { 2994 CHECK_HAS_PENDING_EXCEPTION(vm, false); 2995 JSThread *thread = vm->GetJSThread(); 2996 JSHandle<JSTaggedValue> xValue = JSNApiHelper::ToJSHandle(this); 2997 LOG_IF_SPECIAL(xValue, ERROR); 2998 JSHandle<JSTaggedValue> yValue = JSNApiHelper::ToJSHandle(value); 2999 return JSTaggedValue::StrictEqual(thread, xValue, yValue); 3000 } 3001 Typeof(const EcmaVM * vm)3002 Local<StringRef> JSValueRef::Typeof(const EcmaVM *vm) 3003 { 3004 CHECK_HAS_PENDING_EXCEPTION_RETURN_UNDEFINED(vm); 3005 JSThread *thread = vm->GetJSThread(); 3006 JSTaggedValue value = FastRuntimeStub::FastTypeOf(thread, JSNApiHelper::ToJSTaggedValue(this)); 3007 return JSNApiHelper::ToLocal<StringRef>(JSHandle<JSTaggedValue>(thread, value)); 3008 } 3009 InstanceOf(const EcmaVM * vm,Local<JSValueRef> value)3010 bool JSValueRef::InstanceOf(const EcmaVM *vm, Local<JSValueRef> value) 3011 { 3012 CHECK_HAS_PENDING_EXCEPTION(vm, false); 3013 JSThread *thread = vm->GetJSThread(); 3014 JSHandle<JSTaggedValue> origin = JSNApiHelper::ToJSHandle(this); 3015 LOG_IF_SPECIAL(origin, ERROR); 3016 JSHandle<JSTaggedValue> target = JSNApiHelper::ToJSHandle(value); 3017 bool result = JSObject::InstanceOf(thread, origin, target); 3018 RETURN_VALUE_IF_ABRUPT(thread, false); 3019 return result; 3020 } 3021 IsUndefined()3022 bool JSValueRef::IsUndefined() 3023 { 3024 return JSNApiHelper::ToJSTaggedValue(this).IsUndefined(); 3025 } 3026 IsNull()3027 bool JSValueRef::IsNull() 3028 { 3029 return JSNApiHelper::ToJSTaggedValue(this).IsNull(); 3030 } 3031 IsHole()3032 bool JSValueRef::IsHole() 3033 { 3034 return JSNApiHelper::ToJSTaggedValue(this).IsHole(); 3035 } 3036 IsTrue()3037 bool JSValueRef::IsTrue() 3038 { 3039 return JSNApiHelper::ToJSTaggedValue(this).IsTrue(); 3040 } 3041 IsFalse()3042 bool JSValueRef::IsFalse() 3043 { 3044 return JSNApiHelper::ToJSTaggedValue(this).IsFalse(); 3045 } 3046 IsNumber()3047 bool JSValueRef::IsNumber() 3048 { 3049 return JSNApiHelper::ToJSTaggedValue(this).IsNumber(); 3050 } 3051 IsBigInt()3052 bool JSValueRef::IsBigInt() 3053 { 3054 return JSNApiHelper::ToJSTaggedValue(this).IsBigInt(); 3055 } 3056 IsInt()3057 bool JSValueRef::IsInt() 3058 { 3059 return JSNApiHelper::ToJSTaggedValue(this).IsInt(); 3060 } 3061 WithinInt32()3062 bool JSValueRef::WithinInt32() 3063 { 3064 return JSNApiHelper::ToJSTaggedValue(this).WithinInt32(); 3065 } 3066 IsBoolean()3067 bool JSValueRef::IsBoolean() 3068 { 3069 return JSNApiHelper::ToJSTaggedValue(this).IsBoolean(); 3070 } 3071 IsString()3072 bool JSValueRef::IsString() 3073 { 3074 return JSNApiHelper::ToJSTaggedValue(this).IsString(); 3075 } 3076 IsSymbol()3077 bool JSValueRef::IsSymbol() 3078 { 3079 return JSNApiHelper::ToJSTaggedValue(this).IsSymbol(); 3080 } 3081 IsObject()3082 bool JSValueRef::IsObject() 3083 { 3084 return JSNApiHelper::ToJSTaggedValue(this).IsECMAObject(); 3085 } 3086 IsArray(const EcmaVM * vm)3087 bool JSValueRef::IsArray(const EcmaVM *vm) 3088 { 3089 CHECK_HAS_PENDING_EXCEPTION(vm, false); 3090 JSThread *thread = vm->GetJSThread(); 3091 return JSNApiHelper::ToJSTaggedValue(this).IsArray(thread); 3092 } 3093 IsJSArray(const EcmaVM * vm)3094 bool JSValueRef::IsJSArray(const EcmaVM *vm) 3095 { 3096 CHECK_HAS_PENDING_EXCEPTION(vm, false); 3097 return JSNApiHelper::ToJSTaggedValue(this).IsJSArray(); 3098 } 3099 IsConstructor()3100 bool JSValueRef::IsConstructor() 3101 { 3102 JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this); 3103 return value.IsHeapObject() && value.IsConstructor(); 3104 } 3105 IsFunction()3106 bool JSValueRef::IsFunction() 3107 { 3108 JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this); 3109 return value.IsHeapObject() && value.IsCallable(); 3110 } 3111 IsProxy()3112 bool JSValueRef::IsProxy() 3113 { 3114 return JSNApiHelper::ToJSTaggedValue(this).IsJSProxy(); 3115 } 3116 IsPromise()3117 bool JSValueRef::IsPromise() 3118 { 3119 return JSNApiHelper::ToJSTaggedValue(this).IsJSPromise(); 3120 } 3121 IsDataView()3122 bool JSValueRef::IsDataView() 3123 { 3124 return JSNApiHelper::ToJSTaggedValue(this).IsDataView(); 3125 } 3126 IsTypedArray()3127 bool JSValueRef::IsTypedArray() 3128 { 3129 return JSNApiHelper::ToJSTaggedValue(this).IsTypedArray(); 3130 } 3131 IsNativePointer()3132 bool JSValueRef::IsNativePointer() 3133 { 3134 return JSNApiHelper::ToJSTaggedValue(this).IsJSNativePointer(); 3135 } 3136 IsDate()3137 bool JSValueRef::IsDate() 3138 { 3139 return JSNApiHelper::ToJSTaggedValue(this).IsDate(); 3140 } 3141 IsError()3142 bool JSValueRef::IsError() 3143 { 3144 return JSNApiHelper::ToJSTaggedValue(this).IsJSError(); 3145 } 3146 IsMap()3147 bool JSValueRef::IsMap() 3148 { 3149 return JSNApiHelper::ToJSTaggedValue(this).IsJSMap(); 3150 } 3151 IsSet()3152 bool JSValueRef::IsSet() 3153 { 3154 return JSNApiHelper::ToJSTaggedValue(this).IsJSSet(); 3155 } 3156 IsWeakRef()3157 bool JSValueRef::IsWeakRef() 3158 { 3159 return JSNApiHelper::ToJSTaggedValue(this).IsJSWeakRef(); 3160 } 3161 IsWeakMap()3162 bool JSValueRef::IsWeakMap() 3163 { 3164 return JSNApiHelper::ToJSTaggedValue(this).IsJSWeakMap(); 3165 } 3166 IsWeakSet()3167 bool JSValueRef::IsWeakSet() 3168 { 3169 return JSNApiHelper::ToJSTaggedValue(this).IsJSWeakSet(); 3170 } 3171 IsRegExp()3172 bool JSValueRef::IsRegExp() 3173 { 3174 return JSNApiHelper::ToJSTaggedValue(this).IsJSRegExp(); 3175 } 3176 IsArrayIterator()3177 bool JSValueRef::IsArrayIterator() 3178 { 3179 return JSNApiHelper::ToJSTaggedValue(this).IsJSArrayIterator(); 3180 } 3181 IsStringIterator()3182 bool JSValueRef::IsStringIterator() 3183 { 3184 return JSNApiHelper::ToJSTaggedValue(this).IsStringIterator(); 3185 } 3186 IsSetIterator()3187 bool JSValueRef::IsSetIterator() 3188 { 3189 return JSNApiHelper::ToJSTaggedValue(this).IsJSSetIterator(); 3190 } 3191 IsMapIterator()3192 bool JSValueRef::IsMapIterator() 3193 { 3194 return JSNApiHelper::ToJSTaggedValue(this).IsJSMapIterator(); 3195 } 3196 IsArrayBuffer()3197 bool JSValueRef::IsArrayBuffer() 3198 { 3199 return JSNApiHelper::ToJSTaggedValue(this).IsArrayBuffer(); 3200 } 3201 IsBuffer()3202 bool JSValueRef::IsBuffer() 3203 { 3204 return JSNApiHelper::ToJSTaggedValue(this).IsArrayBuffer(); 3205 } 3206 IsUint8Array()3207 bool JSValueRef::IsUint8Array() 3208 { 3209 return JSNApiHelper::ToJSTaggedValue(this).IsJSUint8Array(); 3210 } 3211 IsInt8Array()3212 bool JSValueRef::IsInt8Array() 3213 { 3214 return JSNApiHelper::ToJSTaggedValue(this).IsJSInt8Array(); 3215 } 3216 IsUint8ClampedArray()3217 bool JSValueRef::IsUint8ClampedArray() 3218 { 3219 return JSNApiHelper::ToJSTaggedValue(this).IsJSUint8ClampedArray(); 3220 } 3221 IsInt16Array()3222 bool JSValueRef::IsInt16Array() 3223 { 3224 return JSNApiHelper::ToJSTaggedValue(this).IsJSInt16Array(); 3225 } 3226 IsUint16Array()3227 bool JSValueRef::IsUint16Array() 3228 { 3229 return JSNApiHelper::ToJSTaggedValue(this).IsJSUint16Array(); 3230 } 3231 IsInt32Array()3232 bool JSValueRef::IsInt32Array() 3233 { 3234 return JSNApiHelper::ToJSTaggedValue(this).IsJSInt32Array(); 3235 } 3236 IsUint32Array()3237 bool JSValueRef::IsUint32Array() 3238 { 3239 return JSNApiHelper::ToJSTaggedValue(this).IsJSUint32Array(); 3240 } 3241 IsFloat32Array()3242 bool JSValueRef::IsFloat32Array() 3243 { 3244 return JSNApiHelper::ToJSTaggedValue(this).IsJSFloat32Array(); 3245 } 3246 IsFloat64Array()3247 bool JSValueRef::IsFloat64Array() 3248 { 3249 return JSNApiHelper::ToJSTaggedValue(this).IsJSFloat64Array(); 3250 } 3251 IsBigInt64Array()3252 bool JSValueRef::IsBigInt64Array() 3253 { 3254 return JSNApiHelper::ToJSTaggedValue(this).IsJSBigInt64Array(); 3255 } 3256 IsBigUint64Array()3257 bool JSValueRef::IsBigUint64Array() 3258 { 3259 return JSNApiHelper::ToJSTaggedValue(this).IsJSBigUint64Array(); 3260 } 3261 IsJSPrimitiveRef()3262 bool JSValueRef::IsJSPrimitiveRef() 3263 { 3264 return JSNApiHelper::ToJSTaggedValue(this).IsJSPrimitiveRef(); 3265 } 3266 IsJSPrimitiveNumber()3267 bool JSValueRef::IsJSPrimitiveNumber() 3268 { 3269 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 3270 LOG_IF_SPECIAL(obj, FATAL); 3271 return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsNumber(); 3272 } 3273 IsJSPrimitiveInt()3274 bool JSValueRef::IsJSPrimitiveInt() 3275 { 3276 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 3277 LOG_IF_SPECIAL(obj, FATAL); 3278 return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsInt(); 3279 } 3280 IsJSPrimitiveBoolean()3281 bool JSValueRef::IsJSPrimitiveBoolean() 3282 { 3283 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 3284 LOG_IF_SPECIAL(obj, FATAL); 3285 return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsBoolean(); 3286 } 3287 IsJSPrimitiveString()3288 bool JSValueRef::IsJSPrimitiveString() 3289 { 3290 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 3291 LOG_IF_SPECIAL(obj, FATAL); 3292 return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsString(); 3293 } 3294 IsJSPrimitiveSymbol()3295 bool JSValueRef::IsJSPrimitiveSymbol() 3296 { 3297 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 3298 LOG_IF_SPECIAL(obj, FATAL); 3299 return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsSymbol(); 3300 } 3301 IsGeneratorObject()3302 bool JSValueRef::IsGeneratorObject() 3303 { 3304 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 3305 LOG_IF_SPECIAL(obj, ERROR); 3306 bool rst = obj->IsGeneratorObject(); 3307 return rst; 3308 } 3309 IsModuleNamespaceObject()3310 bool JSValueRef::IsModuleNamespaceObject() 3311 { 3312 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 3313 LOG_IF_SPECIAL(obj, ERROR); 3314 bool rst = obj->IsModuleNamespace(); 3315 return rst; 3316 } 3317 IsSharedArrayBuffer()3318 bool JSValueRef::IsSharedArrayBuffer() 3319 { 3320 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 3321 LOG_IF_SPECIAL(obj, ERROR); 3322 bool rst = obj->IsSharedArrayBuffer(); 3323 return rst; 3324 } 3325 IsJSLocale()3326 bool JSValueRef::IsJSLocale() 3327 { 3328 return JSNApiHelper::ToJSTaggedValue(this).IsJSLocale(); 3329 } 3330 IsJSDateTimeFormat()3331 bool JSValueRef::IsJSDateTimeFormat() 3332 { 3333 return JSNApiHelper::ToJSTaggedValue(this).IsJSDateTimeFormat(); 3334 } 3335 IsJSRelativeTimeFormat()3336 bool JSValueRef::IsJSRelativeTimeFormat() 3337 { 3338 return JSNApiHelper::ToJSTaggedValue(this).IsJSRelativeTimeFormat(); 3339 } 3340 IsJSIntl()3341 bool JSValueRef::IsJSIntl() 3342 { 3343 return JSNApiHelper::ToJSTaggedValue(this).IsJSIntl(); 3344 } 3345 IsJSNumberFormat()3346 bool JSValueRef::IsJSNumberFormat() 3347 { 3348 return JSNApiHelper::ToJSTaggedValue(this).IsJSNumberFormat(); 3349 } 3350 IsJSCollator()3351 bool JSValueRef::IsJSCollator() 3352 { 3353 return JSNApiHelper::ToJSTaggedValue(this).IsJSCollator(); 3354 } 3355 IsJSPluralRules()3356 bool JSValueRef::IsJSPluralRules() 3357 { 3358 return JSNApiHelper::ToJSTaggedValue(this).IsJSPluralRules(); 3359 } 3360 IsJSListFormat()3361 bool JSValueRef::IsJSListFormat() 3362 { 3363 return JSNApiHelper::ToJSTaggedValue(this).IsJSListFormat(); 3364 } 3365 IsAsyncGeneratorObject()3366 bool JSValueRef::IsAsyncGeneratorObject() 3367 { 3368 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 3369 LOG_IF_SPECIAL(obj, ERROR); 3370 return obj->IsAsyncGeneratorObject(); 3371 } 3372 IsAsyncFunction()3373 bool JSValueRef::IsAsyncFunction() 3374 { 3375 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 3376 LOG_IF_SPECIAL(obj, ERROR); 3377 bool rst = obj->IsJSAsyncFunction(); 3378 return rst; 3379 } 3380 IsArgumentsObject()3381 bool JSValueRef::IsArgumentsObject() 3382 { 3383 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 3384 LOG_IF_SPECIAL(obj, ERROR); 3385 bool rst = obj->IsArguments(); 3386 return rst; 3387 } 3388 IsGeneratorFunction()3389 bool JSValueRef::IsGeneratorFunction() 3390 { 3391 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 3392 LOG_IF_SPECIAL(obj, ERROR); 3393 bool rst = obj->IsGeneratorFunction(); 3394 return rst; 3395 } 3396 IsAsyncGeneratorFunction()3397 bool JSValueRef::IsAsyncGeneratorFunction() 3398 { 3399 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this); 3400 LOG_IF_SPECIAL(obj, ERROR); 3401 return obj->IsAsyncGeneratorFunction(); 3402 } 3403 IsArrayList()3404 bool JSValueRef::IsArrayList() 3405 { 3406 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIArrayList(); 3407 } 3408 IsDeque()3409 bool JSValueRef::IsDeque() 3410 { 3411 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIDeque(); 3412 } 3413 IsHashMap()3414 bool JSValueRef::IsHashMap() 3415 { 3416 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIHashMap(); 3417 } 3418 IsHashSet()3419 bool JSValueRef::IsHashSet() 3420 { 3421 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIHashSet(); 3422 } 3423 IsLightWeightMap()3424 bool JSValueRef::IsLightWeightMap() 3425 { 3426 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPILightWeightMap(); 3427 } 3428 IsLightWeightSet()3429 bool JSValueRef::IsLightWeightSet() 3430 { 3431 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPILightWeightSet(); 3432 } 3433 IsLinkedList()3434 bool JSValueRef::IsLinkedList() 3435 { 3436 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPILinkedList(); 3437 } 3438 IsLinkedListIterator()3439 bool JSValueRef::IsLinkedListIterator() 3440 { 3441 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPILinkedListIterator(); 3442 } 3443 IsList()3444 bool JSValueRef::IsList() 3445 { 3446 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIList(); 3447 } 3448 IsPlainArray()3449 bool JSValueRef::IsPlainArray() 3450 { 3451 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIPlainArray(); 3452 } 3453 IsQueue()3454 bool JSValueRef::IsQueue() 3455 { 3456 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIQueue(); 3457 } 3458 IsStack()3459 bool JSValueRef::IsStack() 3460 { 3461 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIStack(); 3462 } 3463 IsTreeMap()3464 bool JSValueRef::IsTreeMap() 3465 { 3466 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPITreeMap(); 3467 } 3468 IsTreeSet()3469 bool JSValueRef::IsTreeSet() 3470 { 3471 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPITreeSet(); 3472 } 3473 IsVector()3474 bool JSValueRef::IsVector() 3475 { 3476 return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIVector(); 3477 } 3478 3479 // ------------------------------------ JsiRuntimeCallInfo ----------------------------------------------- JsiRuntimeCallInfo(ecmascript::EcmaRuntimeCallInfo * ecmaInfo,void * data)3480 JsiRuntimeCallInfo::JsiRuntimeCallInfo(ecmascript::EcmaRuntimeCallInfo* ecmaInfo, void* data) 3481 : thread_(ecmaInfo->GetThread()), numArgs_(ecmaInfo->GetArgsNumber()) 3482 { 3483 stackArgs_ = ecmaInfo->GetArgs(); 3484 data_ = data; 3485 } 3486 GetVM() const3487 EcmaVM *JsiRuntimeCallInfo::GetVM() const 3488 { 3489 return thread_->GetEcmaVM(); 3490 } 3491 3492 // ---------------------------------------HotPatch--HotReload------------------------------------------- LoadPatch(EcmaVM * vm,const std::string & patchFileName,const std::string & baseFileName)3493 PatchErrorCode JSNApi::LoadPatch(EcmaVM *vm, const std::string &patchFileName, const std::string &baseFileName) 3494 { 3495 CHECK_HAS_PENDING_EXCEPTION(vm, PatchErrorCode::INTERNAL_ERROR); 3496 ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager(); 3497 JSThread *thread = vm->GetJSThread(); 3498 return quickFixManager->LoadPatch(thread, patchFileName, baseFileName); 3499 } 3500 LoadPatch(EcmaVM * vm,const std::string & patchFileName,const void * patchBuffer,size_t patchSize,const std::string & baseFileName,const void * baseBuffer,size_t baseSize)3501 PatchErrorCode JSNApi::LoadPatch(EcmaVM *vm, 3502 const std::string &patchFileName, const void *patchBuffer, size_t patchSize, 3503 const std::string &baseFileName, const void *baseBuffer, size_t baseSize) 3504 { 3505 CHECK_HAS_PENDING_EXCEPTION(vm, PatchErrorCode::INTERNAL_ERROR); 3506 ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager(); 3507 JSThread *thread = vm->GetJSThread(); 3508 return quickFixManager->LoadPatch( 3509 thread, patchFileName, patchBuffer, patchSize, baseFileName, baseBuffer, baseSize); 3510 } 3511 UnloadPatch(EcmaVM * vm,const std::string & patchFileName)3512 PatchErrorCode JSNApi::UnloadPatch(EcmaVM *vm, const std::string &patchFileName) 3513 { 3514 CHECK_HAS_PENDING_EXCEPTION(vm, PatchErrorCode::INTERNAL_ERROR); 3515 ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager(); 3516 JSThread *thread = vm->GetJSThread(); 3517 return quickFixManager->UnloadPatch(thread, patchFileName); 3518 } 3519 3520 /* 3521 * check whether the exception is caused by quickfix methods. 3522 */ IsQuickFixCausedException(EcmaVM * vm,Local<ObjectRef> exception,const std::string & patchFileName)3523 bool JSNApi::IsQuickFixCausedException(EcmaVM *vm, Local<ObjectRef> exception, const std::string &patchFileName) 3524 { 3525 if (exception.IsEmpty()) { 3526 return false; 3527 } 3528 ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager(); 3529 JSThread *thread = vm->GetJSThread(); 3530 JSHandle<JSTaggedValue> exceptionInfo = JSNApiHelper::ToJSHandle(exception); 3531 return quickFixManager->IsQuickFixCausedException(thread, exceptionInfo, patchFileName); 3532 } 3533 3534 /* 3535 * register quickfix query function. 3536 */ RegisterQuickFixQueryFunc(EcmaVM * vm,std::function<bool (std::string baseFileName,std::string & patchFileName,void ** patchBuffer,size_t & patchSize)> callBack)3537 void JSNApi::RegisterQuickFixQueryFunc(EcmaVM *vm, std::function<bool(std::string baseFileName, 3538 std::string &patchFileName, 3539 void **patchBuffer, 3540 size_t &patchSize)> callBack) 3541 { 3542 CHECK_HAS_PENDING_EXCEPTION_WITHOUT_RETURN(vm); 3543 ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager(); 3544 quickFixManager->RegisterQuickFixQueryFunc(callBack); 3545 } 3546 IsBundle(EcmaVM * vm)3547 bool JSNApi::IsBundle(EcmaVM *vm) 3548 { 3549 return vm->IsBundlePack(); 3550 } 3551 SetBundle(EcmaVM * vm,bool value)3552 void JSNApi::SetBundle(EcmaVM *vm, bool value) 3553 { 3554 vm->SetIsBundlePack(value); 3555 } 3556 3557 // note: The function SetAssetPath is a generic interface for previewing and physical machines. SetAssetPath(EcmaVM * vm,const std::string & assetPath)3558 void JSNApi::SetAssetPath(EcmaVM *vm, const std::string &assetPath) 3559 { 3560 ecmascript::CString path = assetPath.c_str(); 3561 vm->SetAssetPath(path); 3562 } 3563 SetLoop(EcmaVM * vm,void * loop)3564 void JSNApi::SetLoop(EcmaVM *vm, void *loop) 3565 { 3566 vm->SetLoop(loop); 3567 } 3568 GetAssetPath(EcmaVM * vm)3569 std::string JSNApi::GetAssetPath(EcmaVM *vm) 3570 { 3571 return vm->GetAssetPath().c_str(); 3572 } 3573 InitForConcurrentThread(EcmaVM * vm,ConcurrentCallback cb,void * data)3574 bool JSNApi::InitForConcurrentThread(EcmaVM *vm, ConcurrentCallback cb, void *data) 3575 { 3576 vm->SetConcurrentCallback(cb, data); 3577 3578 return true; 3579 } 3580 InitForConcurrentFunction(EcmaVM * vm,Local<JSValueRef> function,void * taskInfo)3581 bool JSNApi::InitForConcurrentFunction(EcmaVM *vm, Local<JSValueRef> function, void *taskInfo) 3582 { 3583 CHECK_HAS_PENDING_EXCEPTION(vm, false); 3584 [[maybe_unused]] LocalScope scope(vm); 3585 JSHandle<JSTaggedValue> funcVal = JSNApiHelper::ToJSHandle(function); 3586 JSHandle<JSFunction> transFunc = JSHandle<JSFunction>::Cast(funcVal); 3587 if (transFunc->GetFunctionKind() != ecmascript::FunctionKind::CONCURRENT_FUNCTION) { 3588 LOG_ECMA(ERROR) << "Function is not concurrent"; 3589 return false; 3590 } 3591 ecmascript::JSThread *thread = vm->GetJSThread(); 3592 transFunc->SetFunctionExtraInfo(thread, nullptr, nullptr, taskInfo); 3593 JSHandle<Method> method(thread, transFunc->GetMethod()); 3594 const JSPandaFile *jsPandaFile = method->GetJSPandaFile(); 3595 if (jsPandaFile == nullptr) { 3596 LOG_ECMA(ERROR) << "JSPandaFile is nullptr"; 3597 return false; 3598 } 3599 ecmascript::CString moduleName = jsPandaFile->GetJSPandaFileDesc(); 3600 ecmascript::CString recordName = method->GetRecordName(); 3601 3602 // for debugger, to notify the script loaded and parsed which the concurrent function is in 3603 auto *notificationMgr = vm->GetJsDebuggerManager()->GetNotificationManager(); 3604 notificationMgr->LoadModuleEvent(moduleName, recordName); 3605 3606 // check ESM or CJS 3607 ecmascript::JSRecordInfo recordInfo; 3608 bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(recordName, recordInfo); 3609 if (!hasRecord) { 3610 LOG_ECMA(ERROR) << "cannot find record '" << recordName << "', please check the request path."; 3611 return false; 3612 } 3613 if (!jsPandaFile->IsModule(recordInfo)) { 3614 LOG_ECMA(DEBUG) << "Current function is not from ES Module's file."; 3615 return true; 3616 } 3617 ecmascript::ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); 3618 JSHandle<ecmascript::JSTaggedValue> moduleRecord; 3619 // check compileMode 3620 if (jsPandaFile->IsBundlePack()) { 3621 LOG_ECMA(DEBUG) << "CompileMode is jsbundle"; 3622 moduleRecord = moduleManager->HostResolveImportedModule(moduleName); 3623 } else { 3624 LOG_ECMA(DEBUG) << "CompileMode is esmodule"; 3625 moduleRecord = moduleManager->HostResolveImportedModuleWithMerge(moduleName, recordName); 3626 if (ecmascript::AnFileDataManager::GetInstance()->IsEnable()) { 3627 thread->GetCurrentEcmaContext()->GetAOTFileManager()->LoadAiFile(jsPandaFile); 3628 } 3629 } 3630 ecmascript::SourceTextModule::Instantiate(thread, moduleRecord); 3631 JSHandle<ecmascript::SourceTextModule> module = JSHandle<ecmascript::SourceTextModule>::Cast(moduleRecord); 3632 module->SetStatus(ecmascript::ModuleStatus::INSTANTIATED); 3633 ecmascript::SourceTextModule::EvaluateForConcurrent(thread, module); 3634 transFunc->SetModule(thread, module); 3635 return true; 3636 } 3637 GetCurrentTaskInfo(const EcmaVM * vm)3638 void* JSNApi::GetCurrentTaskInfo(const EcmaVM *vm) 3639 { 3640 CHECK_HAS_PENDING_EXCEPTION(vm, nullptr); 3641 auto thread = vm->GetJSThread(); 3642 JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetCurrentFrame()); 3643 ecmascript::FrameIterator it(current, thread); 3644 for (; !it.Done(); it.Advance<ecmascript::GCVisitedFlag::VISITED>()) { 3645 if (!it.IsJSFrame()) { 3646 continue; 3647 } 3648 auto method = it.CheckAndGetMethod(); 3649 if (method == nullptr || method->IsNativeWithCallField() || 3650 method->GetFunctionKind() != ecmascript::FunctionKind::CONCURRENT_FUNCTION) { 3651 continue; 3652 } 3653 auto functionObj = it.GetFunction(); 3654 JSHandle<JSFunction> function(thread, functionObj); 3655 JSTaggedValue extraInfoValue = function->GetFunctionExtraInfo(); 3656 if (!extraInfoValue.IsJSNativePointer()) { 3657 LOG_ECMA(DEBUG) << "Concurrent function donnot have taskInfo"; 3658 continue; 3659 } 3660 JSHandle<JSNativePointer> extraInfo(thread, extraInfoValue); 3661 return extraInfo->GetData(); 3662 } 3663 LOG_ECMA(ERROR) << "TaskInfo is nullptr"; 3664 return nullptr; 3665 } 3666 SetBundleName(EcmaVM * vm,const std::string & bundleName)3667 void JSNApi::SetBundleName(EcmaVM *vm, const std::string &bundleName) 3668 { 3669 ecmascript::CString name = bundleName.c_str(); 3670 vm->SetBundleName(name); 3671 } 3672 GetBundleName(EcmaVM * vm)3673 std::string JSNApi::GetBundleName(EcmaVM *vm) 3674 { 3675 return vm->GetBundleName().c_str(); 3676 } 3677 SetModuleName(EcmaVM * vm,const std::string & moduleName)3678 void JSNApi::SetModuleName(EcmaVM *vm, const std::string &moduleName) 3679 { 3680 ecmascript::CString name = moduleName.c_str(); 3681 vm->SetModuleName(name); 3682 } 3683 GetModuleName(EcmaVM * vm)3684 std::string JSNApi::GetModuleName(EcmaVM *vm) 3685 { 3686 return vm->GetModuleName().c_str(); 3687 } 3688 3689 // Enable cross thread execution. AllowCrossThreadExecution(EcmaVM * vm)3690 void JSNApi::AllowCrossThreadExecution(EcmaVM *vm) 3691 { 3692 vm->GetAssociatedJSThread()->EnableCrossThreadExecution(); 3693 } 3694 SynchronizVMInfo(EcmaVM * vm,const EcmaVM * hostVM)3695 void JSNApi::SynchronizVMInfo(EcmaVM *vm, const EcmaVM *hostVM) 3696 { 3697 vm->SetBundleName(hostVM->GetBundleName()); 3698 vm->SetModuleName(hostVM->GetModuleName()); 3699 vm->SetAssetPath(hostVM->GetAssetPath()); 3700 vm->SetIsBundlePack(hostVM->IsBundlePack()); 3701 vm->GetAssociatedJSThread()->GetCurrentEcmaContext()->GetModuleManager()->SetExecuteMode( 3702 hostVM->GetAssociatedJSThread()->GetCurrentEcmaContext()->GetModuleManager()->GetCurrentMode()); 3703 vm->SetResolveBufferCallback(hostVM->GetResolveBufferCallback()); 3704 } 3705 3706 } // namespace panda 3707