• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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