• 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