11cb0ef41Sopenharmony_ci#include <string.h>
21cb0ef41Sopenharmony_ci#include <unistd.h>
31cb0ef41Sopenharmony_ci#include <algorithm>
41cb0ef41Sopenharmony_ci#include <atomic>
51cb0ef41Sopenharmony_ci#include <climits>  // INT_MAX
61cb0ef41Sopenharmony_ci#include <cmath>
71cb0ef41Sopenharmony_ci#include "v8-debug.h"
81cb0ef41Sopenharmony_ci#include "v8-internal.h"
91cb0ef41Sopenharmony_ci#include "v8-local-handle.h"
101cb0ef41Sopenharmony_ci#include "v8-primitive.h"
111cb0ef41Sopenharmony_ci#include "v8-statistics.h"
121cb0ef41Sopenharmony_ci#include "v8-version-string.h"
131cb0ef41Sopenharmony_ci#define JSVM_EXPERIMENTAL
141cb0ef41Sopenharmony_ci#include "env-inl.h"
151cb0ef41Sopenharmony_ci#include "jsvm.h"
161cb0ef41Sopenharmony_ci#include "js_native_api_v8.h"
171cb0ef41Sopenharmony_ci#include "js_native_api_v8_inspector.h"
181cb0ef41Sopenharmony_ci#include "libplatform/libplatform.h"
191cb0ef41Sopenharmony_ci#include "util-inl.h"
201cb0ef41Sopenharmony_ci#include "util.h"
211cb0ef41Sopenharmony_ci#include "sourcemap.def"
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci#ifdef ENABLE_HISYSEVENT
241cb0ef41Sopenharmony_ci#include "hisysevent.h"
251cb0ef41Sopenharmony_ci#endif
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci#define SECARGCNT   2
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci#define CHECK_MAYBE_NOTHING(env, maybe, status)                                \
301cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE((env), !((maybe).IsNothing()), (status))
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci#define CHECK_MAYBE_NOTHING_WITH_PREAMBLE(env, maybe, status)                  \
331cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE((env), !((maybe).IsNothing()), (status))
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci#define CHECK_TO_NUMBER(env, context, result, src)                             \
361cb0ef41Sopenharmony_ci  CHECK_TO_TYPE((env), Number, (context), (result), (src), JSVM_NUMBER_EXPECTED)
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci// n-api defines JSVM_AUTO_LENGTH as the indicator that a string
391cb0ef41Sopenharmony_ci// is null terminated. For V8 the equivalent is -1. The assert
401cb0ef41Sopenharmony_ci// validates that our cast of JSVM_AUTO_LENGTH results in -1 as
411cb0ef41Sopenharmony_ci// needed by V8.
421cb0ef41Sopenharmony_ci#define CHECK_NEW_FROM_UTF8_LEN(env, result, str, len)                         \
431cb0ef41Sopenharmony_ci  do {                                                                         \
441cb0ef41Sopenharmony_ci    static_assert(static_cast<int>(JSVM_AUTO_LENGTH) == -1,                    \
451cb0ef41Sopenharmony_ci                  "Casting JSVM_AUTO_LENGTH to int must result in -1");        \
461cb0ef41Sopenharmony_ci    RETURN_STATUS_IF_FALSE(                                                    \
471cb0ef41Sopenharmony_ci        (env), (len == JSVM_AUTO_LENGTH) || len <= INT_MAX, JSVM_INVALID_ARG); \
481cb0ef41Sopenharmony_ci    RETURN_STATUS_IF_FALSE((env), (str) != nullptr, JSVM_INVALID_ARG);         \
491cb0ef41Sopenharmony_ci    auto str_maybe = v8::String::NewFromUtf8((env)->isolate,                   \
501cb0ef41Sopenharmony_ci                                             (str),                            \
511cb0ef41Sopenharmony_ci                                             v8::NewStringType::kInternalized, \
521cb0ef41Sopenharmony_ci                                             static_cast<int>(len));           \
531cb0ef41Sopenharmony_ci    CHECK_MAYBE_EMPTY((env), str_maybe, JSVM_GENERIC_FAILURE);                 \
541cb0ef41Sopenharmony_ci    (result) = str_maybe.ToLocalChecked();                                     \
551cb0ef41Sopenharmony_ci  } while (0)
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci#define CHECK_NEW_FROM_UTF8(env, result, str)                                  \
581cb0ef41Sopenharmony_ci  CHECK_NEW_FROM_UTF8_LEN((env), (result), (str), JSVM_AUTO_LENGTH)
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci#define CHECK_NEW_STRING_ARGS(env, str, length, result)                        \
611cb0ef41Sopenharmony_ci  do {                                                                         \
621cb0ef41Sopenharmony_ci    CHECK_ENV_NOT_IN_GC((env));                                                \
631cb0ef41Sopenharmony_ci    if ((length) > 0) CHECK_ARG((env), (str));                                 \
641cb0ef41Sopenharmony_ci    CHECK_ARG((env), (result));                                                \
651cb0ef41Sopenharmony_ci    RETURN_STATUS_IF_FALSE(                                                    \
661cb0ef41Sopenharmony_ci        (env),                                                                 \
671cb0ef41Sopenharmony_ci        ((length) == JSVM_AUTO_LENGTH) || (length) <= INT_MAX,                 \
681cb0ef41Sopenharmony_ci        JSVM_INVALID_ARG);                                                     \
691cb0ef41Sopenharmony_ci  } while (0)
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci#define CREATE_TYPED_ARRAY(                                                    \
721cb0ef41Sopenharmony_ci    env, type, size_of_element, buffer, byteOffset, length, out)              \
731cb0ef41Sopenharmony_ci  do {                                                                         \
741cb0ef41Sopenharmony_ci    if ((size_of_element) > 1) {                                               \
751cb0ef41Sopenharmony_ci      THROW_RANGE_ERROR_IF_FALSE(                                              \
761cb0ef41Sopenharmony_ci          (env),                                                               \
771cb0ef41Sopenharmony_ci          (byteOffset) % (size_of_element) == 0,                              \
781cb0ef41Sopenharmony_ci          "ERR_JSVM_INVALID_TYPEDARRAY_ALIGNMENT",                             \
791cb0ef41Sopenharmony_ci          "start offset of " #type                                             \
801cb0ef41Sopenharmony_ci          " should be a multiple of " #size_of_element);                       \
811cb0ef41Sopenharmony_ci    }                                                                          \
821cb0ef41Sopenharmony_ci    THROW_RANGE_ERROR_IF_FALSE(                                                \
831cb0ef41Sopenharmony_ci        (env),                                                                 \
841cb0ef41Sopenharmony_ci        (length) * (size_of_element) + (byteOffset) <= buffer->ByteLength(),  \
851cb0ef41Sopenharmony_ci        "ERR_JSVM_INVALID_TYPEDARRAY_LENGTH",                                  \
861cb0ef41Sopenharmony_ci        "Invalid typed array length");                                         \
871cb0ef41Sopenharmony_ci    (out) = v8::type::New((buffer), (byteOffset), (length));                  \
881cb0ef41Sopenharmony_ci  } while (0)
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ciJSVM_Env__::JSVM_Env__(v8::Isolate* isolate, int32_t module_api_version)
911cb0ef41Sopenharmony_ci    : isolate(isolate), module_api_version(module_api_version) {
921cb0ef41Sopenharmony_ci  inspector_agent_ = new v8impl::Agent(this);
931cb0ef41Sopenharmony_ci  jsvm_clear_last_error(this);
941cb0ef41Sopenharmony_ci}
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_civoid JSVM_Env__::DeleteMe() {
971cb0ef41Sopenharmony_ci   // First we must finalize those references that have `napi_finalizer`
981cb0ef41Sopenharmony_ci   // callbacks. The reason is that addons might store other references which
991cb0ef41Sopenharmony_ci   // they delete during their `napi_finalizer` callbacks. If we deleted such
1001cb0ef41Sopenharmony_ci   // references here first, they would be doubly deleted when the
1011cb0ef41Sopenharmony_ci   // `napi_finalizer` deleted them subsequently.
1021cb0ef41Sopenharmony_ci   v8impl::RefTracker::FinalizeAll(&finalizing_reflist);
1031cb0ef41Sopenharmony_ci   v8impl::RefTracker::FinalizeAll(&reflist);
1041cb0ef41Sopenharmony_ci   {
1051cb0ef41Sopenharmony_ci       v8::Context::Scope context_scope(context());
1061cb0ef41Sopenharmony_ci       if (inspector_agent_->IsActive()) {
1071cb0ef41Sopenharmony_ci           inspector_agent_->WaitForDisconnect();
1081cb0ef41Sopenharmony_ci       }
1091cb0ef41Sopenharmony_ci       delete inspector_agent_;
1101cb0ef41Sopenharmony_ci   }
1111cb0ef41Sopenharmony_ci   delete this;
1121cb0ef41Sopenharmony_ci}
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_civoid JSVM_Env__::RunAndClearInterrupts() {
1151cb0ef41Sopenharmony_ci  while (native_immediates_interrupts_.size() > 0) {
1161cb0ef41Sopenharmony_ci    NativeImmediateQueue queue;
1171cb0ef41Sopenharmony_ci    {
1181cb0ef41Sopenharmony_ci      node::Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
1191cb0ef41Sopenharmony_ci      queue.ConcatMove(std::move(native_immediates_interrupts_));
1201cb0ef41Sopenharmony_ci    }
1211cb0ef41Sopenharmony_ci    node::DebugSealHandleScope seal_handle_scope(isolate);
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci    while (auto head = queue.Shift())
1241cb0ef41Sopenharmony_ci      head->Call(this);
1251cb0ef41Sopenharmony_ci  }
1261cb0ef41Sopenharmony_ci}
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_civoid JSVM_Env__::InvokeFinalizerFromGC(v8impl::RefTracker* finalizer) {
1291cb0ef41Sopenharmony_ci    // The experimental code calls finalizers immediately to release native
1301cb0ef41Sopenharmony_ci    // objects as soon as possible. In that state any code that may affect GC
1311cb0ef41Sopenharmony_ci    // state causes a fatal error. To work around this issue the finalizer code
1321cb0ef41Sopenharmony_ci    // can call node_api_post_finalizer.
1331cb0ef41Sopenharmony_ci    auto restore_state = node::OnScopeLeave(
1341cb0ef41Sopenharmony_ci        [this, saved = in_gc_finalizer] { in_gc_finalizer = saved; });
1351cb0ef41Sopenharmony_ci    in_gc_finalizer = true;
1361cb0ef41Sopenharmony_ci    finalizer->Finalize();
1371cb0ef41Sopenharmony_ci}
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_cinamespace v8impl {
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_cinamespace {
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_cienum IsolateDataSlot {
1441cb0ef41Sopenharmony_ci  kIsolateData = 0,
1451cb0ef41Sopenharmony_ci  kIsolateSnapshotCreatorSlot = 1,
1461cb0ef41Sopenharmony_ci};
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_cienum ContextEmbedderIndex {
1491cb0ef41Sopenharmony_ci  kContextEnvIndex = 1,
1501cb0ef41Sopenharmony_ci};
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_cistruct IsolateData {
1531cb0ef41Sopenharmony_ci  IsolateData(v8::StartupData* blob) : blob(blob) {}
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  ~IsolateData() {
1561cb0ef41Sopenharmony_ci    delete blob;
1571cb0ef41Sopenharmony_ci  }
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  v8::StartupData* blob;
1601cb0ef41Sopenharmony_ci  v8::Eternal<v8::Private> jsvm_type_tag_key;
1611cb0ef41Sopenharmony_ci  v8::Eternal<v8::Private> jsvm_wrapper_key;
1621cb0ef41Sopenharmony_ci};
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_cistatic void CreateIsolateData(v8::Isolate* isolate, v8::StartupData* blob) {
1651cb0ef41Sopenharmony_ci  auto data = new IsolateData(blob);
1661cb0ef41Sopenharmony_ci  v8::Isolate::Scope isolate_scope(isolate);
1671cb0ef41Sopenharmony_ci  v8::HandleScope handle_scope(isolate);
1681cb0ef41Sopenharmony_ci  if (blob) {
1691cb0ef41Sopenharmony_ci    // NOTE: The order of getting the data must be consistent with the order of
1701cb0ef41Sopenharmony_ci    // adding data in OH_JSVM_CreateSnapshot.
1711cb0ef41Sopenharmony_ci      auto wrapper_key = isolate->GetDataFromSnapshotOnce<v8::Private>(0);
1721cb0ef41Sopenharmony_ci      auto type_tag_key = isolate->GetDataFromSnapshotOnce<v8::Private>(1);
1731cb0ef41Sopenharmony_ci      data->jsvm_wrapper_key.Set(isolate, wrapper_key.ToLocalChecked());
1741cb0ef41Sopenharmony_ci      data->jsvm_type_tag_key.Set(isolate, type_tag_key.ToLocalChecked());
1751cb0ef41Sopenharmony_ci  } else {
1761cb0ef41Sopenharmony_ci      data->jsvm_wrapper_key.Set(isolate, v8::Private::New(isolate));
1771cb0ef41Sopenharmony_ci      data->jsvm_type_tag_key.Set(isolate, v8::Private::New(isolate));
1781cb0ef41Sopenharmony_ci  }
1791cb0ef41Sopenharmony_ci  isolate->SetData(v8impl::kIsolateData, data);
1801cb0ef41Sopenharmony_ci}
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_cistatic IsolateData* GetIsolateData(v8::Isolate* isolate) {
1831cb0ef41Sopenharmony_ci  auto data = isolate->GetData(v8impl::kIsolateData);
1841cb0ef41Sopenharmony_ci  return reinterpret_cast<IsolateData*>(data);
1851cb0ef41Sopenharmony_ci}
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_cistatic void SetIsolateSnapshotCreator(v8::Isolate* isolate,
1881cb0ef41Sopenharmony_ci                                      v8::SnapshotCreator* creator) {
1891cb0ef41Sopenharmony_ci  isolate->SetData(v8impl::kIsolateSnapshotCreatorSlot, creator);
1901cb0ef41Sopenharmony_ci}
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_cistatic v8::SnapshotCreator* GetIsolateSnapshotCreator(v8::Isolate* isolate) {
1931cb0ef41Sopenharmony_ci  auto data = isolate->GetData(v8impl::kIsolateSnapshotCreatorSlot);
1941cb0ef41Sopenharmony_ci  return reinterpret_cast<v8::SnapshotCreator*>(data);
1951cb0ef41Sopenharmony_ci}
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_cistatic void SetContextEnv(v8::Local<v8::Context> context, JSVM_Env env) {
1981cb0ef41Sopenharmony_ci  context->SetAlignedPointerInEmbedderData(kContextEnvIndex, env);
1991cb0ef41Sopenharmony_ci}
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_cistatic JSVM_Env GetContextEnv(v8::Local<v8::Context> context) {
2021cb0ef41Sopenharmony_ci  auto data = context->GetAlignedPointerFromEmbedderData(kContextEnvIndex);
2031cb0ef41Sopenharmony_ci  return reinterpret_cast<JSVM_Env>(data);
2041cb0ef41Sopenharmony_ci}
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ciclass OutputStream : public v8::OutputStream {
2071cb0ef41Sopenharmony_ci public:
2081cb0ef41Sopenharmony_ci  OutputStream(JSVM_OutputStream stream, void* data, int chunk_size = 65536)
2091cb0ef41Sopenharmony_ci    : stream_(stream), stream_data_(data), chunk_size_(chunk_size) {}
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ci  int GetChunkSize() override { return chunk_size_; }
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ci  void EndOfStream() override {
2141cb0ef41Sopenharmony_ci    stream_(nullptr, 0, stream_data_);
2151cb0ef41Sopenharmony_ci  }
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci  WriteResult WriteAsciiChunk(char* data, const int size) override {
2181cb0ef41Sopenharmony_ci    return stream_(data, size, stream_data_) ? kContinue : kAbort;
2191cb0ef41Sopenharmony_ci  }
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci private:
2221cb0ef41Sopenharmony_ci  JSVM_OutputStream stream_;
2231cb0ef41Sopenharmony_ci  void* stream_data_;
2241cb0ef41Sopenharmony_ci  int chunk_size_;
2251cb0ef41Sopenharmony_ci};
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_cistatic std::unique_ptr<v8::Platform> g_platform = v8::platform::NewDefaultPlatform();
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_cistatic std::vector<intptr_t> externalReferenceRegistry;
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_cistatic std::unordered_map<std::string, std::string> sourceMapUrlMap;
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_cistatic std::unique_ptr<v8::ArrayBuffer::Allocator> defaultArrayBufferAllocator;
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_cistatic v8::ArrayBuffer::Allocator *GetOrCreateDefaultArrayBufferAllocator() {
2361cb0ef41Sopenharmony_ci  if (!defaultArrayBufferAllocator) {
2371cb0ef41Sopenharmony_ci    defaultArrayBufferAllocator.reset(v8::ArrayBuffer::Allocator::NewDefaultAllocator());
2381cb0ef41Sopenharmony_ci  }
2391cb0ef41Sopenharmony_ci  return defaultArrayBufferAllocator.get();
2401cb0ef41Sopenharmony_ci}
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_cistatic void SetFileToSourceMapMapping(std::string &&file, std::string &&sourceMapUrl) {
2431cb0ef41Sopenharmony_ci  auto it = sourceMapUrlMap.find(file);
2441cb0ef41Sopenharmony_ci  if (it == sourceMapUrlMap.end()) {
2451cb0ef41Sopenharmony_ci    sourceMapUrlMap.emplace(file, sourceMapUrl);
2461cb0ef41Sopenharmony_ci    return;
2471cb0ef41Sopenharmony_ci  }
2481cb0ef41Sopenharmony_ci  auto &&prevSourceMapUrl = it->second;
2491cb0ef41Sopenharmony_ci  CHECK(prevSourceMapUrl == sourceMapUrl);
2501cb0ef41Sopenharmony_ci}
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_cistatic std::string GetSourceMapFromFileName(std::string &&file) {
2531cb0ef41Sopenharmony_ci  auto it = sourceMapUrlMap.find(file);
2541cb0ef41Sopenharmony_ci  if (it != sourceMapUrlMap.end()) {
2551cb0ef41Sopenharmony_ci    return it->second;
2561cb0ef41Sopenharmony_ci  }
2571cb0ef41Sopenharmony_ci  return "";
2581cb0ef41Sopenharmony_ci}
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_citemplate <typename CCharType, typename StringMaker>
2611cb0ef41Sopenharmony_ciJSVM_Status NewString(JSVM_Env env,
2621cb0ef41Sopenharmony_ci                      const CCharType* str,
2631cb0ef41Sopenharmony_ci                      size_t length,
2641cb0ef41Sopenharmony_ci                      JSVM_Value* result,
2651cb0ef41Sopenharmony_ci                      StringMaker string_maker) {
2661cb0ef41Sopenharmony_ci  CHECK_NEW_STRING_ARGS(env, str, length, result);
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ci  auto isolate = env->isolate;
2691cb0ef41Sopenharmony_ci  auto str_maybe = string_maker(isolate);
2701cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, str_maybe, JSVM_GENERIC_FAILURE);
2711cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
2721cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
2731cb0ef41Sopenharmony_ci}
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_citemplate <typename CharType, typename CreateAPI, typename StringMaker>
2761cb0ef41Sopenharmony_ciJSVM_Status NewExternalString(JSVM_Env env,
2771cb0ef41Sopenharmony_ci                              CharType* str,
2781cb0ef41Sopenharmony_ci                              size_t length,
2791cb0ef41Sopenharmony_ci                              JSVM_Finalize finalizeCallback,
2801cb0ef41Sopenharmony_ci                              void* finalizeHint,
2811cb0ef41Sopenharmony_ci                              JSVM_Value* result,
2821cb0ef41Sopenharmony_ci                              bool* copied,
2831cb0ef41Sopenharmony_ci                              CreateAPI create_api,
2841cb0ef41Sopenharmony_ci                              StringMaker string_maker) {
2851cb0ef41Sopenharmony_ci  CHECK_NEW_STRING_ARGS(env, str, length, result);
2861cb0ef41Sopenharmony_ci  JSVM_Status status;
2871cb0ef41Sopenharmony_ci#if defined(V8_ENABLE_SANDBOX)
2881cb0ef41Sopenharmony_ci  status = create_api(env, str, length, result);
2891cb0ef41Sopenharmony_ci  if (status == JSVM_OK) {
2901cb0ef41Sopenharmony_ci    if (copied != nullptr) {
2911cb0ef41Sopenharmony_ci      *copied = true;
2921cb0ef41Sopenharmony_ci    }
2931cb0ef41Sopenharmony_ci    if (finalizeCallback) {
2941cb0ef41Sopenharmony_ci      env->CallFinalizer(
2951cb0ef41Sopenharmony_ci          finalizeCallback, static_cast<CharType*>(str), finalizeHint);
2961cb0ef41Sopenharmony_ci    }
2971cb0ef41Sopenharmony_ci  }
2981cb0ef41Sopenharmony_ci#else
2991cb0ef41Sopenharmony_ci  status = NewString(env, str, length, result, string_maker);
3001cb0ef41Sopenharmony_ci  if (status == JSVM_OK && copied != nullptr) {
3011cb0ef41Sopenharmony_ci    *copied = false;
3021cb0ef41Sopenharmony_ci  }
3031cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_SANDBOX
3041cb0ef41Sopenharmony_ci  return status;
3051cb0ef41Sopenharmony_ci}
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ciclass TrackedStringResource : public Finalizer, RefTracker {
3081cb0ef41Sopenharmony_ci public:
3091cb0ef41Sopenharmony_ci  TrackedStringResource(JSVM_Env env,
3101cb0ef41Sopenharmony_ci                        JSVM_Finalize finalizeCallback,
3111cb0ef41Sopenharmony_ci                        void* data,
3121cb0ef41Sopenharmony_ci                        void* finalizeHint)
3131cb0ef41Sopenharmony_ci      : Finalizer(env, finalizeCallback, data, finalizeHint) {
3141cb0ef41Sopenharmony_ci    Link(finalizeCallback == nullptr ? &env->reflist
3151cb0ef41Sopenharmony_ci                                      : &env->finalizing_reflist);
3161cb0ef41Sopenharmony_ci  }
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ci protected:
3191cb0ef41Sopenharmony_ci  // The only time Finalize() gets called before Dispose() is if the
3201cb0ef41Sopenharmony_ci  // environment is dying. Finalize() expects that the item will be unlinked,
3211cb0ef41Sopenharmony_ci  // so we do it here. V8 will still call Dispose() on us later, so we don't do
3221cb0ef41Sopenharmony_ci  // any deleting here. We just null out env_ to avoid passing a stale pointer
3231cb0ef41Sopenharmony_ci  // to the user's finalizer when V8 does finally call Dispose().
3241cb0ef41Sopenharmony_ci  void Finalize() override {
3251cb0ef41Sopenharmony_ci    Unlink();
3261cb0ef41Sopenharmony_ci    env_ = nullptr;
3271cb0ef41Sopenharmony_ci  }
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ci  ~TrackedStringResource() {
3301cb0ef41Sopenharmony_ci    if (finalize_callback_ == nullptr) return;
3311cb0ef41Sopenharmony_ci    if (env_ == nullptr) {
3321cb0ef41Sopenharmony_ci      // The environment is dead. Call the finalizer directly.
3331cb0ef41Sopenharmony_ci      finalize_callback_(nullptr, finalize_data_, finalize_hint_);
3341cb0ef41Sopenharmony_ci    } else {
3351cb0ef41Sopenharmony_ci      // The environment is still alive. Let's remove ourselves from its list
3361cb0ef41Sopenharmony_ci      // of references and call the user's finalizer.
3371cb0ef41Sopenharmony_ci      Unlink();
3381cb0ef41Sopenharmony_ci      env_->CallFinalizer(finalize_callback_, finalize_data_, finalize_hint_);
3391cb0ef41Sopenharmony_ci    }
3401cb0ef41Sopenharmony_ci  }
3411cb0ef41Sopenharmony_ci};
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ciclass ExternalOneByteStringResource
3441cb0ef41Sopenharmony_ci    : public v8::String::ExternalOneByteStringResource,
3451cb0ef41Sopenharmony_ci      TrackedStringResource {
3461cb0ef41Sopenharmony_ci public:
3471cb0ef41Sopenharmony_ci  ExternalOneByteStringResource(JSVM_Env env,
3481cb0ef41Sopenharmony_ci                                char* string,
3491cb0ef41Sopenharmony_ci                                const size_t length,
3501cb0ef41Sopenharmony_ci                                JSVM_Finalize finalizeCallback,
3511cb0ef41Sopenharmony_ci                                void* finalizeHint)
3521cb0ef41Sopenharmony_ci      : TrackedStringResource(env, finalizeCallback, string, finalizeHint),
3531cb0ef41Sopenharmony_ci        string_(string),
3541cb0ef41Sopenharmony_ci        length_(length) {}
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ci  const char* data() const override { return string_; }
3571cb0ef41Sopenharmony_ci  size_t length() const override { return length_; }
3581cb0ef41Sopenharmony_ci
3591cb0ef41Sopenharmony_ci private:
3601cb0ef41Sopenharmony_ci  const char* string_;
3611cb0ef41Sopenharmony_ci  const size_t length_;
3621cb0ef41Sopenharmony_ci};
3631cb0ef41Sopenharmony_ci
3641cb0ef41Sopenharmony_ciclass ExternalStringResource : public v8::String::ExternalStringResource,
3651cb0ef41Sopenharmony_ci                               TrackedStringResource {
3661cb0ef41Sopenharmony_ci public:
3671cb0ef41Sopenharmony_ci  ExternalStringResource(JSVM_Env env,
3681cb0ef41Sopenharmony_ci                         char16_t* string,
3691cb0ef41Sopenharmony_ci                         const size_t length,
3701cb0ef41Sopenharmony_ci                         JSVM_Finalize finalizeCallback,
3711cb0ef41Sopenharmony_ci                         void* finalizeHint)
3721cb0ef41Sopenharmony_ci      : TrackedStringResource(env, finalizeCallback, string, finalizeHint),
3731cb0ef41Sopenharmony_ci        string_(reinterpret_cast<uint16_t*>(string)),
3741cb0ef41Sopenharmony_ci        length_(length) {}
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_ci  const uint16_t* data() const override { return string_; }
3771cb0ef41Sopenharmony_ci  size_t length() const override { return length_; }
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_ci private:
3801cb0ef41Sopenharmony_ci  const uint16_t* string_;
3811cb0ef41Sopenharmony_ci  const size_t length_;
3821cb0ef41Sopenharmony_ci};
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ciinline JSVM_Status V8NameFromPropertyDescriptor(
3851cb0ef41Sopenharmony_ci    JSVM_Env env,
3861cb0ef41Sopenharmony_ci    const JSVM_PropertyDescriptor* p,
3871cb0ef41Sopenharmony_ci    v8::Local<v8::Name>* result) {
3881cb0ef41Sopenharmony_ci  if (p->utf8name != nullptr) {
3891cb0ef41Sopenharmony_ci    CHECK_NEW_FROM_UTF8(env, *result, p->utf8name);
3901cb0ef41Sopenharmony_ci  } else {
3911cb0ef41Sopenharmony_ci    v8::Local<v8::Value> property_value =
3921cb0ef41Sopenharmony_ci        v8impl::V8LocalValueFromJsValue(p->name);
3931cb0ef41Sopenharmony_ci
3941cb0ef41Sopenharmony_ci    RETURN_STATUS_IF_FALSE(env, property_value->IsName(), JSVM_NAME_EXPECTED);
3951cb0ef41Sopenharmony_ci    *result = property_value.As<v8::Name>();
3961cb0ef41Sopenharmony_ci  }
3971cb0ef41Sopenharmony_ci
3981cb0ef41Sopenharmony_ci  return JSVM_OK;
3991cb0ef41Sopenharmony_ci}
4001cb0ef41Sopenharmony_ci
4011cb0ef41Sopenharmony_ci// convert from n-api property attributes to v8::PropertyAttribute
4021cb0ef41Sopenharmony_ciinline v8::PropertyAttribute V8PropertyAttributesFromDescriptor(
4031cb0ef41Sopenharmony_ci    const JSVM_PropertyDescriptor* descriptor) {
4041cb0ef41Sopenharmony_ci  unsigned int attribute_flags = v8::PropertyAttribute::None;
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ci  // The JSVM_WRITABLE attribute is ignored for accessor descriptors, but
4071cb0ef41Sopenharmony_ci  // V8 would throw `TypeError`s on assignment with nonexistence of a setter.
4081cb0ef41Sopenharmony_ci  if ((descriptor->getter == nullptr && descriptor->setter == nullptr) &&
4091cb0ef41Sopenharmony_ci      (descriptor->attributes & JSVM_WRITABLE) == 0) {
4101cb0ef41Sopenharmony_ci    attribute_flags |= v8::PropertyAttribute::ReadOnly;
4111cb0ef41Sopenharmony_ci  }
4121cb0ef41Sopenharmony_ci
4131cb0ef41Sopenharmony_ci  if ((descriptor->attributes & JSVM_ENUMERABLE) == 0) {
4141cb0ef41Sopenharmony_ci    attribute_flags |= v8::PropertyAttribute::DontEnum;
4151cb0ef41Sopenharmony_ci  }
4161cb0ef41Sopenharmony_ci  if ((descriptor->attributes & JSVM_CONFIGURABLE) == 0) {
4171cb0ef41Sopenharmony_ci    attribute_flags |= v8::PropertyAttribute::DontDelete;
4181cb0ef41Sopenharmony_ci  }
4191cb0ef41Sopenharmony_ci
4201cb0ef41Sopenharmony_ci  return static_cast<v8::PropertyAttribute>(attribute_flags);
4211cb0ef41Sopenharmony_ci}
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_ciinline JSVM_Deferred JsDeferredFromNodePersistent(
4241cb0ef41Sopenharmony_ci    v8impl::Persistent<v8::Value>* local) {
4251cb0ef41Sopenharmony_ci  return reinterpret_cast<JSVM_Deferred>(local);
4261cb0ef41Sopenharmony_ci}
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ciinline v8impl::Persistent<v8::Value>* NodePersistentFromJsDeferred(
4291cb0ef41Sopenharmony_ci    JSVM_Deferred local) {
4301cb0ef41Sopenharmony_ci  return reinterpret_cast<v8impl::Persistent<v8::Value>*>(local);
4311cb0ef41Sopenharmony_ci}
4321cb0ef41Sopenharmony_ci
4331cb0ef41Sopenharmony_ciclass HandleScopeWrapper {
4341cb0ef41Sopenharmony_ci public:
4351cb0ef41Sopenharmony_ci  explicit HandleScopeWrapper(v8::Isolate* isolate) : scope(isolate) {}
4361cb0ef41Sopenharmony_ci
4371cb0ef41Sopenharmony_ci private:
4381cb0ef41Sopenharmony_ci  v8::HandleScope scope;
4391cb0ef41Sopenharmony_ci};
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_ci// In node v0.10 version of v8, there is no EscapableHandleScope and the
4421cb0ef41Sopenharmony_ci// node v0.10 port use HandleScope::Close(Local<T> v) to mimic the behavior
4431cb0ef41Sopenharmony_ci// of a EscapableHandleScope::Escape(Local<T> v), but it is not the same
4441cb0ef41Sopenharmony_ci// semantics. This is an example of where the api abstraction fail to work
4451cb0ef41Sopenharmony_ci// across different versions.
4461cb0ef41Sopenharmony_ciclass EscapableHandleScopeWrapper {
4471cb0ef41Sopenharmony_ci public:
4481cb0ef41Sopenharmony_ci  explicit EscapableHandleScopeWrapper(v8::Isolate* isolate)
4491cb0ef41Sopenharmony_ci      : scope(isolate), escape_called_(false) {}
4501cb0ef41Sopenharmony_ci  bool escape_called() const { return escape_called_; }
4511cb0ef41Sopenharmony_ci  template <typename T>
4521cb0ef41Sopenharmony_ci  v8::Local<T> Escape(v8::Local<T> handle) {
4531cb0ef41Sopenharmony_ci    escape_called_ = true;
4541cb0ef41Sopenharmony_ci    return scope.Escape(handle);
4551cb0ef41Sopenharmony_ci  }
4561cb0ef41Sopenharmony_ci
4571cb0ef41Sopenharmony_ci private:
4581cb0ef41Sopenharmony_ci  v8::EscapableHandleScope scope;
4591cb0ef41Sopenharmony_ci  bool escape_called_;
4601cb0ef41Sopenharmony_ci};
4611cb0ef41Sopenharmony_ci
4621cb0ef41Sopenharmony_ciinline JSVM_HandleScope JsHandleScopeFromV8HandleScope(HandleScopeWrapper* s) {
4631cb0ef41Sopenharmony_ci  return reinterpret_cast<JSVM_HandleScope>(s);
4641cb0ef41Sopenharmony_ci}
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_ciinline HandleScopeWrapper* V8HandleScopeFromJsHandleScope(JSVM_HandleScope s) {
4671cb0ef41Sopenharmony_ci  return reinterpret_cast<HandleScopeWrapper*>(s);
4681cb0ef41Sopenharmony_ci}
4691cb0ef41Sopenharmony_ci
4701cb0ef41Sopenharmony_ciinline JSVM_EscapableHandleScope
4711cb0ef41Sopenharmony_ciJsEscapableHandleScopeFromV8EscapableHandleScope(
4721cb0ef41Sopenharmony_ci    EscapableHandleScopeWrapper* s) {
4731cb0ef41Sopenharmony_ci  return reinterpret_cast<JSVM_EscapableHandleScope>(s);
4741cb0ef41Sopenharmony_ci}
4751cb0ef41Sopenharmony_ci
4761cb0ef41Sopenharmony_ciinline EscapableHandleScopeWrapper*
4771cb0ef41Sopenharmony_ciV8EscapableHandleScopeFromJsEscapableHandleScope(
4781cb0ef41Sopenharmony_ci    JSVM_EscapableHandleScope s) {
4791cb0ef41Sopenharmony_ci  return reinterpret_cast<EscapableHandleScopeWrapper*>(s);
4801cb0ef41Sopenharmony_ci}
4811cb0ef41Sopenharmony_ci
4821cb0ef41Sopenharmony_ciinline JSVM_Status ConcludeDeferred(JSVM_Env env,
4831cb0ef41Sopenharmony_ci                                    JSVM_Deferred deferred,
4841cb0ef41Sopenharmony_ci                                    JSVM_Value result,
4851cb0ef41Sopenharmony_ci                                    bool is_resolved) {
4861cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
4871cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
4881cb0ef41Sopenharmony_ci
4891cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
4901cb0ef41Sopenharmony_ci  v8impl::Persistent<v8::Value>* deferred_ref =
4911cb0ef41Sopenharmony_ci      NodePersistentFromJsDeferred(deferred);
4921cb0ef41Sopenharmony_ci  v8::Local<v8::Value> v8_deferred =
4931cb0ef41Sopenharmony_ci      v8::Local<v8::Value>::New(env->isolate, *deferred_ref);
4941cb0ef41Sopenharmony_ci
4951cb0ef41Sopenharmony_ci  auto v8_resolver = v8_deferred.As<v8::Promise::Resolver>();
4961cb0ef41Sopenharmony_ci
4971cb0ef41Sopenharmony_ci  v8::Maybe<bool> success =
4981cb0ef41Sopenharmony_ci      is_resolved ? v8_resolver->Resolve(
4991cb0ef41Sopenharmony_ci                        context, v8impl::V8LocalValueFromJsValue(result))
5001cb0ef41Sopenharmony_ci                  : v8_resolver->Reject(
5011cb0ef41Sopenharmony_ci                        context, v8impl::V8LocalValueFromJsValue(result));
5021cb0ef41Sopenharmony_ci
5031cb0ef41Sopenharmony_ci  delete deferred_ref;
5041cb0ef41Sopenharmony_ci
5051cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, success.FromMaybe(false), JSVM_GENERIC_FAILURE);
5061cb0ef41Sopenharmony_ci
5071cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
5081cb0ef41Sopenharmony_ci}
5091cb0ef41Sopenharmony_ci
5101cb0ef41Sopenharmony_cienum UnwrapAction { KeepWrap, RemoveWrap };
5111cb0ef41Sopenharmony_ci
5121cb0ef41Sopenharmony_ciinline JSVM_Status Unwrap(JSVM_Env env,
5131cb0ef41Sopenharmony_ci                          JSVM_Value jsObject,
5141cb0ef41Sopenharmony_ci                          void** result,
5151cb0ef41Sopenharmony_ci                          UnwrapAction action) {
5161cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
5171cb0ef41Sopenharmony_ci  CHECK_ARG(env, jsObject);
5181cb0ef41Sopenharmony_ci  if (action == KeepWrap) {
5191cb0ef41Sopenharmony_ci    CHECK_ARG(env, result);
5201cb0ef41Sopenharmony_ci  }
5211cb0ef41Sopenharmony_ci
5221cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
5231cb0ef41Sopenharmony_ci
5241cb0ef41Sopenharmony_ci  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(jsObject);
5251cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, value->IsObject(), JSVM_INVALID_ARG);
5261cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj = value.As<v8::Object>();
5271cb0ef41Sopenharmony_ci
5281cb0ef41Sopenharmony_ci  auto val = obj->GetPrivate(context, JSVM_PRIVATE_KEY(env->isolate, wrapper))
5291cb0ef41Sopenharmony_ci                 .ToLocalChecked();
5301cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsExternal(), JSVM_INVALID_ARG);
5311cb0ef41Sopenharmony_ci  Reference* reference =
5321cb0ef41Sopenharmony_ci      static_cast<v8impl::Reference*>(val.As<v8::External>()->Value());
5331cb0ef41Sopenharmony_ci
5341cb0ef41Sopenharmony_ci  if (result) {
5351cb0ef41Sopenharmony_ci    *result = reference->Data();
5361cb0ef41Sopenharmony_ci  }
5371cb0ef41Sopenharmony_ci
5381cb0ef41Sopenharmony_ci  if (action == RemoveWrap) {
5391cb0ef41Sopenharmony_ci    CHECK(obj->DeletePrivate(context, JSVM_PRIVATE_KEY(env->isolate, wrapper))
5401cb0ef41Sopenharmony_ci              .FromJust());
5411cb0ef41Sopenharmony_ci    if (reference->ownership() == Ownership::kUserland) {
5421cb0ef41Sopenharmony_ci      // When the wrap is been removed, the finalizer should be reset.
5431cb0ef41Sopenharmony_ci      reference->ResetFinalizer();
5441cb0ef41Sopenharmony_ci    } else {
5451cb0ef41Sopenharmony_ci      delete reference;
5461cb0ef41Sopenharmony_ci    }
5471cb0ef41Sopenharmony_ci  }
5481cb0ef41Sopenharmony_ci
5491cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
5501cb0ef41Sopenharmony_ci}
5511cb0ef41Sopenharmony_ci
5521cb0ef41Sopenharmony_ci//=== Function JSVM_Callback wrapper =================================
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci// Use this data structure to associate callback data with each N-API function
5551cb0ef41Sopenharmony_ci// exposed to JavaScript. The structure is stored in a v8::External which gets
5561cb0ef41Sopenharmony_ci// passed into our callback wrapper. This reduces the performance impact of
5571cb0ef41Sopenharmony_ci// calling through N-API.
5581cb0ef41Sopenharmony_ci// Ref: benchmark/misc/function_call
5591cb0ef41Sopenharmony_ci// Discussion (incl. perf. data): https://github.com/nodejs/node/pull/21072
5601cb0ef41Sopenharmony_ciclass CallbackBundle {
5611cb0ef41Sopenharmony_ci public:
5621cb0ef41Sopenharmony_ci  // Creates an object to be made available to the static function callback
5631cb0ef41Sopenharmony_ci  // wrapper, used to retrieve the native callback function and data pointer.
5641cb0ef41Sopenharmony_ci  static inline v8::Local<v8::Value> New(JSVM_Env env,
5651cb0ef41Sopenharmony_ci                                         JSVM_Callback cb) {
5661cb0ef41Sopenharmony_ci    return v8::External::New(env->isolate, cb);
5671cb0ef41Sopenharmony_ci  }
5681cb0ef41Sopenharmony_ci
5691cb0ef41Sopenharmony_ci  static inline v8::Local<v8::Value> New(JSVM_Env env,
5701cb0ef41Sopenharmony_ci                                         v8impl::JSVM_PropertyHandlerCfgStruct* cb) {
5711cb0ef41Sopenharmony_ci    return v8::External::New(env->isolate, cb);
5721cb0ef41Sopenharmony_ci  }
5731cb0ef41Sopenharmony_ci};
5741cb0ef41Sopenharmony_ci
5751cb0ef41Sopenharmony_ci// Base class extended by classes that wrap V8 function and property callback
5761cb0ef41Sopenharmony_ci// info.
5771cb0ef41Sopenharmony_ciclass CallbackWrapper {
5781cb0ef41Sopenharmony_ci public:
5791cb0ef41Sopenharmony_ci  inline CallbackWrapper(JSVM_Value thisArg, size_t args_length, void* data)
5801cb0ef41Sopenharmony_ci      : _this(thisArg), _args_length(args_length), _data(data) {}
5811cb0ef41Sopenharmony_ci
5821cb0ef41Sopenharmony_ci  virtual JSVM_Value GetNewTarget() {
5831cb0ef41Sopenharmony_ci    return nullptr;
5841cb0ef41Sopenharmony_ci  };
5851cb0ef41Sopenharmony_ci  virtual void Args(JSVM_Value* buffer, size_t bufferlength) {};
5861cb0ef41Sopenharmony_ci  virtual void SetReturnValue(JSVM_Value value) = 0;
5871cb0ef41Sopenharmony_ci
5881cb0ef41Sopenharmony_ci  JSVM_Value This() { return _this; }
5891cb0ef41Sopenharmony_ci
5901cb0ef41Sopenharmony_ci  size_t ArgsLength() { return _args_length; }
5911cb0ef41Sopenharmony_ci
5921cb0ef41Sopenharmony_ci  void* Data() { return _data; }
5931cb0ef41Sopenharmony_ci
5941cb0ef41Sopenharmony_ci protected:
5951cb0ef41Sopenharmony_ci  const JSVM_Value _this;
5961cb0ef41Sopenharmony_ci  const size_t _args_length;
5971cb0ef41Sopenharmony_ci  void* _data;
5981cb0ef41Sopenharmony_ci};
5991cb0ef41Sopenharmony_ci
6001cb0ef41Sopenharmony_ciclass CallbackWrapperBase : public CallbackWrapper {
6011cb0ef41Sopenharmony_ci public:
6021cb0ef41Sopenharmony_ci  inline CallbackWrapperBase(const v8::FunctionCallbackInfo<v8::Value>& cbinfo,
6031cb0ef41Sopenharmony_ci                             const size_t args_length)
6041cb0ef41Sopenharmony_ci      : CallbackWrapper(
6051cb0ef41Sopenharmony_ci            JsValueFromV8LocalValue(cbinfo.This()), args_length, nullptr),
6061cb0ef41Sopenharmony_ci        _cbinfo(cbinfo) {
6071cb0ef41Sopenharmony_ci    _cb = (JSVM_Callback)cbinfo.Data().As<v8::External>()->Value();
6081cb0ef41Sopenharmony_ci    _data = _cb->data;
6091cb0ef41Sopenharmony_ci  }
6101cb0ef41Sopenharmony_ci
6111cb0ef41Sopenharmony_ci protected:
6121cb0ef41Sopenharmony_ci  inline void InvokeCallback() {
6131cb0ef41Sopenharmony_ci    JSVM_CallbackInfo cbinfo_wrapper = reinterpret_cast<JSVM_CallbackInfo>(
6141cb0ef41Sopenharmony_ci        static_cast<CallbackWrapper*>(this));
6151cb0ef41Sopenharmony_ci
6161cb0ef41Sopenharmony_ci    // All other pointers we need are stored in `_bundle`
6171cb0ef41Sopenharmony_ci    auto context = _cbinfo.GetIsolate()->GetCurrentContext();
6181cb0ef41Sopenharmony_ci    auto env = v8impl::GetContextEnv(context);
6191cb0ef41Sopenharmony_ci    auto cb = _cb->callback;
6201cb0ef41Sopenharmony_ci
6211cb0ef41Sopenharmony_ci    JSVM_Value result = nullptr;
6221cb0ef41Sopenharmony_ci    bool exceptionOccurred = false;
6231cb0ef41Sopenharmony_ci    env->CallIntoModule([&](JSVM_Env env) { result = cb(env, cbinfo_wrapper); },
6241cb0ef41Sopenharmony_ci                        [&](JSVM_Env env, v8::Local<v8::Value> value) {
6251cb0ef41Sopenharmony_ci                          exceptionOccurred = true;
6261cb0ef41Sopenharmony_ci                          if (env->terminatedOrTerminating()) {
6271cb0ef41Sopenharmony_ci                            return;
6281cb0ef41Sopenharmony_ci                          }
6291cb0ef41Sopenharmony_ci                          env->isolate->ThrowException(value);
6301cb0ef41Sopenharmony_ci                        });
6311cb0ef41Sopenharmony_ci
6321cb0ef41Sopenharmony_ci    if (!exceptionOccurred && (result != nullptr)) {
6331cb0ef41Sopenharmony_ci      this->SetReturnValue(result);
6341cb0ef41Sopenharmony_ci    }
6351cb0ef41Sopenharmony_ci  }
6361cb0ef41Sopenharmony_ci
6371cb0ef41Sopenharmony_ci  const v8::FunctionCallbackInfo<v8::Value>& _cbinfo;
6381cb0ef41Sopenharmony_ci  JSVM_Callback _cb;
6391cb0ef41Sopenharmony_ci};
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ciclass FunctionCallbackWrapper : public CallbackWrapperBase {
6421cb0ef41Sopenharmony_ci public:
6431cb0ef41Sopenharmony_ci  static void Invoke(const v8::FunctionCallbackInfo<v8::Value>& info) {
6441cb0ef41Sopenharmony_ci    FunctionCallbackWrapper cbwrapper(info);
6451cb0ef41Sopenharmony_ci    cbwrapper.InvokeCallback();
6461cb0ef41Sopenharmony_ci  }
6471cb0ef41Sopenharmony_ci
6481cb0ef41Sopenharmony_ci  static inline JSVM_Status NewFunction(JSVM_Env env,
6491cb0ef41Sopenharmony_ci                                        JSVM_Callback cb,
6501cb0ef41Sopenharmony_ci                                        v8::Local<v8::Function>* result) {
6511cb0ef41Sopenharmony_ci    v8::Local<v8::Value> cbdata = v8impl::CallbackBundle::New(env, cb);
6521cb0ef41Sopenharmony_ci    RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), JSVM_GENERIC_FAILURE);
6531cb0ef41Sopenharmony_ci
6541cb0ef41Sopenharmony_ci    v8::MaybeLocal<v8::Function> maybe_function =
6551cb0ef41Sopenharmony_ci        v8::Function::New(env->context(), Invoke, cbdata);
6561cb0ef41Sopenharmony_ci    CHECK_MAYBE_EMPTY(env, maybe_function, JSVM_GENERIC_FAILURE);
6571cb0ef41Sopenharmony_ci
6581cb0ef41Sopenharmony_ci    *result = maybe_function.ToLocalChecked();
6591cb0ef41Sopenharmony_ci    return jsvm_clear_last_error(env);
6601cb0ef41Sopenharmony_ci  }
6611cb0ef41Sopenharmony_ci
6621cb0ef41Sopenharmony_ci  static inline JSVM_Status NewTemplate(
6631cb0ef41Sopenharmony_ci      JSVM_Env env,
6641cb0ef41Sopenharmony_ci      JSVM_Callback cb,
6651cb0ef41Sopenharmony_ci      v8::Local<v8::FunctionTemplate>* result,
6661cb0ef41Sopenharmony_ci      v8::Local<v8::Signature> sig = v8::Local<v8::Signature>()) {
6671cb0ef41Sopenharmony_ci    v8::Local<v8::Value> cbdata = v8impl::CallbackBundle::New(env, cb);
6681cb0ef41Sopenharmony_ci    RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), JSVM_GENERIC_FAILURE);
6691cb0ef41Sopenharmony_ci
6701cb0ef41Sopenharmony_ci    *result = v8::FunctionTemplate::New(env->isolate, Invoke, cbdata, sig);
6711cb0ef41Sopenharmony_ci    return jsvm_clear_last_error(env);
6721cb0ef41Sopenharmony_ci  }
6731cb0ef41Sopenharmony_ci
6741cb0ef41Sopenharmony_ci  explicit FunctionCallbackWrapper(
6751cb0ef41Sopenharmony_ci      const v8::FunctionCallbackInfo<v8::Value>& cbinfo)
6761cb0ef41Sopenharmony_ci      : CallbackWrapperBase(cbinfo, cbinfo.Length()) {}
6771cb0ef41Sopenharmony_ci
6781cb0ef41Sopenharmony_ci  JSVM_Value GetNewTarget() override {
6791cb0ef41Sopenharmony_ci    if (_cbinfo.IsConstructCall()) {
6801cb0ef41Sopenharmony_ci      return v8impl::JsValueFromV8LocalValue(_cbinfo.NewTarget());
6811cb0ef41Sopenharmony_ci    } else {
6821cb0ef41Sopenharmony_ci      return nullptr;
6831cb0ef41Sopenharmony_ci    }
6841cb0ef41Sopenharmony_ci  }
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_ci  /*virtual*/
6871cb0ef41Sopenharmony_ci  void Args(JSVM_Value* buffer, size_t buffer_length) override {
6881cb0ef41Sopenharmony_ci    size_t i = 0;
6891cb0ef41Sopenharmony_ci    size_t min = std::min(buffer_length, _args_length);
6901cb0ef41Sopenharmony_ci
6911cb0ef41Sopenharmony_ci    for (; i < min; i += 1) {
6921cb0ef41Sopenharmony_ci      buffer[i] = v8impl::JsValueFromV8LocalValue(_cbinfo[i]);
6931cb0ef41Sopenharmony_ci    }
6941cb0ef41Sopenharmony_ci
6951cb0ef41Sopenharmony_ci    if (i < buffer_length) {
6961cb0ef41Sopenharmony_ci      JSVM_Value undefined =
6971cb0ef41Sopenharmony_ci          v8impl::JsValueFromV8LocalValue(v8::Undefined(_cbinfo.GetIsolate()));
6981cb0ef41Sopenharmony_ci      for (; i < buffer_length; i += 1) {
6991cb0ef41Sopenharmony_ci        buffer[i] = undefined;
7001cb0ef41Sopenharmony_ci      }
7011cb0ef41Sopenharmony_ci    }
7021cb0ef41Sopenharmony_ci  }
7031cb0ef41Sopenharmony_ci
7041cb0ef41Sopenharmony_ci  /*virtual*/
7051cb0ef41Sopenharmony_ci  void SetReturnValue(JSVM_Value value) override {
7061cb0ef41Sopenharmony_ci    v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
7071cb0ef41Sopenharmony_ci    _cbinfo.GetReturnValue().Set(val);
7081cb0ef41Sopenharmony_ci  }
7091cb0ef41Sopenharmony_ci};
7101cb0ef41Sopenharmony_ci
7111cb0ef41Sopenharmony_citemplate <typename T>
7121cb0ef41Sopenharmony_ciclass PropertyCallbackWrapperBase : public CallbackWrapper {
7131cb0ef41Sopenharmony_ci public:
7141cb0ef41Sopenharmony_ci  inline PropertyCallbackWrapperBase(uint32_t index, v8::Local<v8::Name> property, v8::Local<v8::Value> value,
7151cb0ef41Sopenharmony_ci    const v8::PropertyCallbackInfo<T>& cbinfo, const size_t args_length)
7161cb0ef41Sopenharmony_ci      : CallbackWrapper(
7171cb0ef41Sopenharmony_ci            JsValueFromV8LocalValue(cbinfo.This()), args_length, nullptr),
7181cb0ef41Sopenharmony_ci        _cbinfo(cbinfo), _property(property), _value(value), _index(index) {
7191cb0ef41Sopenharmony_ci    _cb = (v8impl::JSVM_PropertyHandlerCfgStruct *)_cbinfo.Data().template As<v8::External>()->Value();
7201cb0ef41Sopenharmony_ci  }
7211cb0ef41Sopenharmony_ci
7221cb0ef41Sopenharmony_ci protected:
7231cb0ef41Sopenharmony_ci  inline void NameSetterInvokeCallback() {
7241cb0ef41Sopenharmony_ci    auto context = _cbinfo.GetIsolate()->GetCurrentContext();
7251cb0ef41Sopenharmony_ci    auto env = v8impl::GetContextEnv(context);
7261cb0ef41Sopenharmony_ci    auto setterCb = _cb->namedSetterCallback_;
7271cb0ef41Sopenharmony_ci
7281cb0ef41Sopenharmony_ci    JSVM_Value innerData = nullptr;
7291cb0ef41Sopenharmony_ci    if (_cb->namedPropertyData_ != nullptr) {
7301cb0ef41Sopenharmony_ci      v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(_cb->namedPropertyData_);
7311cb0ef41Sopenharmony_ci      innerData = v8impl::JsValueFromV8LocalValue(reference->Get());
7321cb0ef41Sopenharmony_ci    }
7331cb0ef41Sopenharmony_ci
7341cb0ef41Sopenharmony_ci    bool exceptionOccurred = false;
7351cb0ef41Sopenharmony_ci    JSVM_Value result = nullptr;
7361cb0ef41Sopenharmony_ci    JSVM_Value name = JsValueFromV8LocalValue(_property);
7371cb0ef41Sopenharmony_ci    JSVM_Value value = JsValueFromV8LocalValue(_value);
7381cb0ef41Sopenharmony_ci    JSVM_Value thisArg = this->This();
7391cb0ef41Sopenharmony_ci    env->CallIntoModule([&](JSVM_Env env) {
7401cb0ef41Sopenharmony_ci                          if (setterCb) {
7411cb0ef41Sopenharmony_ci                            result = setterCb(env, name, value, thisArg, innerData);
7421cb0ef41Sopenharmony_ci                          }
7431cb0ef41Sopenharmony_ci                        },
7441cb0ef41Sopenharmony_ci                        [&](JSVM_Env env, v8::Local<v8::Value> value) {
7451cb0ef41Sopenharmony_ci                          exceptionOccurred = true;
7461cb0ef41Sopenharmony_ci                          if (env->terminatedOrTerminating()) {
7471cb0ef41Sopenharmony_ci                            return;
7481cb0ef41Sopenharmony_ci                          }
7491cb0ef41Sopenharmony_ci                          env->isolate->ThrowException(value);
7501cb0ef41Sopenharmony_ci                        });
7511cb0ef41Sopenharmony_ci    if (!exceptionOccurred && (result != nullptr)) {
7521cb0ef41Sopenharmony_ci      this->SetReturnValue(result);
7531cb0ef41Sopenharmony_ci    }
7541cb0ef41Sopenharmony_ci  }
7551cb0ef41Sopenharmony_ci
7561cb0ef41Sopenharmony_ci  inline void NameGetterInvokeCallback() {
7571cb0ef41Sopenharmony_ci    auto context = _cbinfo.GetIsolate()->GetCurrentContext();
7581cb0ef41Sopenharmony_ci    auto env = v8impl::GetContextEnv(context);
7591cb0ef41Sopenharmony_ci    auto getterCb = _cb->namedGetterCallback_;
7601cb0ef41Sopenharmony_ci
7611cb0ef41Sopenharmony_ci    JSVM_Value innerData = nullptr;
7621cb0ef41Sopenharmony_ci    if (_cb->namedPropertyData_ != nullptr) {
7631cb0ef41Sopenharmony_ci      v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(_cb->namedPropertyData_);
7641cb0ef41Sopenharmony_ci      innerData = v8impl::JsValueFromV8LocalValue(reference->Get());
7651cb0ef41Sopenharmony_ci    }
7661cb0ef41Sopenharmony_ci    bool exceptionOccurred = false;
7671cb0ef41Sopenharmony_ci    JSVM_Value result = nullptr;
7681cb0ef41Sopenharmony_ci    JSVM_Value name = JsValueFromV8LocalValue(_property);
7691cb0ef41Sopenharmony_ci    JSVM_Value thisArg = this->This();
7701cb0ef41Sopenharmony_ci    env->CallIntoModule([&](JSVM_Env env) {
7711cb0ef41Sopenharmony_ci                          if (getterCb) {
7721cb0ef41Sopenharmony_ci                            result = getterCb(env, name, thisArg, innerData);
7731cb0ef41Sopenharmony_ci                          }
7741cb0ef41Sopenharmony_ci                        },
7751cb0ef41Sopenharmony_ci                        [&](JSVM_Env env, v8::Local<v8::Value> value) {
7761cb0ef41Sopenharmony_ci                          exceptionOccurred = true;
7771cb0ef41Sopenharmony_ci                          if (env->terminatedOrTerminating()) {
7781cb0ef41Sopenharmony_ci                            return;
7791cb0ef41Sopenharmony_ci                          }
7801cb0ef41Sopenharmony_ci                          env->isolate->ThrowException(value);
7811cb0ef41Sopenharmony_ci                        });
7821cb0ef41Sopenharmony_ci    if (!exceptionOccurred && (result != nullptr)) {
7831cb0ef41Sopenharmony_ci      this->SetReturnValue(result);
7841cb0ef41Sopenharmony_ci    }
7851cb0ef41Sopenharmony_ci  }
7861cb0ef41Sopenharmony_ci
7871cb0ef41Sopenharmony_ci  inline void NameDeleterInvokeCallback() {
7881cb0ef41Sopenharmony_ci    auto context = _cbinfo.GetIsolate()->GetCurrentContext();
7891cb0ef41Sopenharmony_ci    auto env = v8impl::GetContextEnv(context);
7901cb0ef41Sopenharmony_ci    auto deleterCb = _cb->nameDeleterCallback_;
7911cb0ef41Sopenharmony_ci
7921cb0ef41Sopenharmony_ci    JSVM_Value innerData = nullptr;
7931cb0ef41Sopenharmony_ci    if (_cb->namedPropertyData_ != nullptr) {
7941cb0ef41Sopenharmony_ci      v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(_cb->namedPropertyData_);
7951cb0ef41Sopenharmony_ci      innerData = v8impl::JsValueFromV8LocalValue(reference->Get());
7961cb0ef41Sopenharmony_ci    }
7971cb0ef41Sopenharmony_ci
7981cb0ef41Sopenharmony_ci    bool exceptionOccurred = false;
7991cb0ef41Sopenharmony_ci    JSVM_Value result = nullptr;
8001cb0ef41Sopenharmony_ci    JSVM_Value name = JsValueFromV8LocalValue(_property);
8011cb0ef41Sopenharmony_ci    JSVM_Value thisArg = this->This();
8021cb0ef41Sopenharmony_ci    env->CallIntoModule([&](JSVM_Env env) {
8031cb0ef41Sopenharmony_ci                          if (deleterCb) {
8041cb0ef41Sopenharmony_ci                            result = deleterCb(env, name, thisArg, innerData);
8051cb0ef41Sopenharmony_ci                          }
8061cb0ef41Sopenharmony_ci                        },
8071cb0ef41Sopenharmony_ci                        [&](JSVM_Env env, v8::Local<v8::Value> value) {
8081cb0ef41Sopenharmony_ci                          exceptionOccurred = true;
8091cb0ef41Sopenharmony_ci                          if (env->terminatedOrTerminating()) {
8101cb0ef41Sopenharmony_ci                            return;
8111cb0ef41Sopenharmony_ci                          }
8121cb0ef41Sopenharmony_ci                          env->isolate->ThrowException(value);
8131cb0ef41Sopenharmony_ci                        });
8141cb0ef41Sopenharmony_ci    if (!exceptionOccurred && (result != nullptr)) {
8151cb0ef41Sopenharmony_ci      if (v8impl::V8LocalValueFromJsValue(result)->IsBoolean()) {
8161cb0ef41Sopenharmony_ci        this->SetReturnValue(result);
8171cb0ef41Sopenharmony_ci      }
8181cb0ef41Sopenharmony_ci    }
8191cb0ef41Sopenharmony_ci  }
8201cb0ef41Sopenharmony_ci
8211cb0ef41Sopenharmony_ci  inline void NameEnumeratorInvokeCallback() {
8221cb0ef41Sopenharmony_ci    auto context = _cbinfo.GetIsolate()->GetCurrentContext();
8231cb0ef41Sopenharmony_ci    auto env = v8impl::GetContextEnv(context);
8241cb0ef41Sopenharmony_ci    auto enumeratorCb = _cb->namedEnumeratorCallback_;
8251cb0ef41Sopenharmony_ci
8261cb0ef41Sopenharmony_ci    JSVM_Value innerData = nullptr;
8271cb0ef41Sopenharmony_ci    if (_cb->namedPropertyData_ != nullptr) {
8281cb0ef41Sopenharmony_ci      v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(_cb->namedPropertyData_);
8291cb0ef41Sopenharmony_ci      innerData = v8impl::JsValueFromV8LocalValue(reference->Get());
8301cb0ef41Sopenharmony_ci    }
8311cb0ef41Sopenharmony_ci
8321cb0ef41Sopenharmony_ci    bool exceptionOccurred = false;
8331cb0ef41Sopenharmony_ci    JSVM_Value result = nullptr;
8341cb0ef41Sopenharmony_ci    JSVM_Value thisArg = this->This();
8351cb0ef41Sopenharmony_ci    env->CallIntoModule([&](JSVM_Env env) {
8361cb0ef41Sopenharmony_ci                          if (enumeratorCb) {
8371cb0ef41Sopenharmony_ci                            result = enumeratorCb(env, thisArg, innerData);
8381cb0ef41Sopenharmony_ci                          }
8391cb0ef41Sopenharmony_ci                        },
8401cb0ef41Sopenharmony_ci                        [&](JSVM_Env env, v8::Local<v8::Value> value) {
8411cb0ef41Sopenharmony_ci                          exceptionOccurred = true;
8421cb0ef41Sopenharmony_ci                          if (env->terminatedOrTerminating()) {
8431cb0ef41Sopenharmony_ci                            return;
8441cb0ef41Sopenharmony_ci                          }
8451cb0ef41Sopenharmony_ci                          env->isolate->ThrowException(value);
8461cb0ef41Sopenharmony_ci                        });
8471cb0ef41Sopenharmony_ci    if (!exceptionOccurred && (result != nullptr)) {
8481cb0ef41Sopenharmony_ci      if (v8impl::V8LocalValueFromJsValue(result)->IsArray()) {
8491cb0ef41Sopenharmony_ci        this->SetReturnValue(result);
8501cb0ef41Sopenharmony_ci      }
8511cb0ef41Sopenharmony_ci    }
8521cb0ef41Sopenharmony_ci  }
8531cb0ef41Sopenharmony_ci
8541cb0ef41Sopenharmony_ci  inline void IndexSetterInvokeCallback() {
8551cb0ef41Sopenharmony_ci    auto context = _cbinfo.GetIsolate()->GetCurrentContext();
8561cb0ef41Sopenharmony_ci    auto env = v8impl::GetContextEnv(context);
8571cb0ef41Sopenharmony_ci    auto indexSetterCb = _cb->indexedSetterCallback_;
8581cb0ef41Sopenharmony_ci
8591cb0ef41Sopenharmony_ci    JSVM_Value innerData = nullptr;
8601cb0ef41Sopenharmony_ci    if (_cb->indexedPropertyData_ != nullptr) {
8611cb0ef41Sopenharmony_ci      v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(_cb->indexedPropertyData_);
8621cb0ef41Sopenharmony_ci      innerData = v8impl::JsValueFromV8LocalValue(reference->Get());
8631cb0ef41Sopenharmony_ci    }
8641cb0ef41Sopenharmony_ci
8651cb0ef41Sopenharmony_ci    bool exceptionOccurred = false;
8661cb0ef41Sopenharmony_ci    JSVM_Value result = nullptr;
8671cb0ef41Sopenharmony_ci    JSVM_Value index = JsValueFromV8LocalValue(v8::Integer::NewFromUnsigned(env->isolate, _index));
8681cb0ef41Sopenharmony_ci    JSVM_Value value = JsValueFromV8LocalValue(_value);
8691cb0ef41Sopenharmony_ci    JSVM_Value thisArg = this->This();
8701cb0ef41Sopenharmony_ci    env->CallIntoModule([&](JSVM_Env env) {
8711cb0ef41Sopenharmony_ci                          if (indexSetterCb) {
8721cb0ef41Sopenharmony_ci                            result = indexSetterCb(env, index, value, thisArg, innerData);
8731cb0ef41Sopenharmony_ci                          }
8741cb0ef41Sopenharmony_ci                        },
8751cb0ef41Sopenharmony_ci                        [&](JSVM_Env env, v8::Local<v8::Value> value) {
8761cb0ef41Sopenharmony_ci                          exceptionOccurred = true;
8771cb0ef41Sopenharmony_ci                          if (env->terminatedOrTerminating()) {
8781cb0ef41Sopenharmony_ci                            return;
8791cb0ef41Sopenharmony_ci                          }
8801cb0ef41Sopenharmony_ci                          env->isolate->ThrowException(value);
8811cb0ef41Sopenharmony_ci                        });
8821cb0ef41Sopenharmony_ci    if (!exceptionOccurred && (result != nullptr)) {
8831cb0ef41Sopenharmony_ci      this->SetReturnValue(result);
8841cb0ef41Sopenharmony_ci    }
8851cb0ef41Sopenharmony_ci  }
8861cb0ef41Sopenharmony_ci
8871cb0ef41Sopenharmony_ci  inline void IndexGetterInvokeCallback() {
8881cb0ef41Sopenharmony_ci    auto context = _cbinfo.GetIsolate()->GetCurrentContext();
8891cb0ef41Sopenharmony_ci    auto env = v8impl::GetContextEnv(context);
8901cb0ef41Sopenharmony_ci    auto indexGetterCb = _cb->indexedGetterCallback_;
8911cb0ef41Sopenharmony_ci
8921cb0ef41Sopenharmony_ci    JSVM_Value innerData = nullptr;
8931cb0ef41Sopenharmony_ci    if (_cb->indexedPropertyData_ != nullptr) {
8941cb0ef41Sopenharmony_ci      v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(_cb->indexedPropertyData_);
8951cb0ef41Sopenharmony_ci      innerData = v8impl::JsValueFromV8LocalValue(reference->Get());
8961cb0ef41Sopenharmony_ci    }
8971cb0ef41Sopenharmony_ci
8981cb0ef41Sopenharmony_ci    JSVM_Value result = nullptr;
8991cb0ef41Sopenharmony_ci    bool exceptionOccurred = false;
9001cb0ef41Sopenharmony_ci    JSVM_Value index = JsValueFromV8LocalValue(v8::Integer::NewFromUnsigned(env->isolate, _index));
9011cb0ef41Sopenharmony_ci    JSVM_Value thisArg = this->This();
9021cb0ef41Sopenharmony_ci    env->CallIntoModule([&](JSVM_Env env) {
9031cb0ef41Sopenharmony_ci                          if (indexGetterCb) {
9041cb0ef41Sopenharmony_ci                            result = indexGetterCb(env, index, thisArg, innerData);
9051cb0ef41Sopenharmony_ci                          }
9061cb0ef41Sopenharmony_ci                        },
9071cb0ef41Sopenharmony_ci                        [&](JSVM_Env env, v8::Local<v8::Value> value) {
9081cb0ef41Sopenharmony_ci                          exceptionOccurred = true;
9091cb0ef41Sopenharmony_ci                          if (env->terminatedOrTerminating()) {
9101cb0ef41Sopenharmony_ci                            return;
9111cb0ef41Sopenharmony_ci                          }
9121cb0ef41Sopenharmony_ci                          env->isolate->ThrowException(value);
9131cb0ef41Sopenharmony_ci                        });
9141cb0ef41Sopenharmony_ci    if (!exceptionOccurred && (result != nullptr)) {
9151cb0ef41Sopenharmony_ci      this->SetReturnValue(result);
9161cb0ef41Sopenharmony_ci    }
9171cb0ef41Sopenharmony_ci  }
9181cb0ef41Sopenharmony_ci
9191cb0ef41Sopenharmony_ci  inline void IndexDeleterInvokeCallback() {
9201cb0ef41Sopenharmony_ci    auto context = _cbinfo.GetIsolate()->GetCurrentContext();
9211cb0ef41Sopenharmony_ci    auto env = v8impl::GetContextEnv(context);
9221cb0ef41Sopenharmony_ci    auto indexDeleterCb = _cb->indexedDeleterCallback_;
9231cb0ef41Sopenharmony_ci
9241cb0ef41Sopenharmony_ci    JSVM_Value innerData = nullptr;
9251cb0ef41Sopenharmony_ci    if (_cb->indexedPropertyData_ != nullptr) {
9261cb0ef41Sopenharmony_ci      v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(_cb->indexedPropertyData_);
9271cb0ef41Sopenharmony_ci      innerData = v8impl::JsValueFromV8LocalValue(reference->Get());
9281cb0ef41Sopenharmony_ci    }
9291cb0ef41Sopenharmony_ci
9301cb0ef41Sopenharmony_ci    bool exceptionOccurred = false;
9311cb0ef41Sopenharmony_ci    JSVM_Value result = nullptr;
9321cb0ef41Sopenharmony_ci    JSVM_Value index = JsValueFromV8LocalValue(v8::Integer::NewFromUnsigned(env->isolate, _index));
9331cb0ef41Sopenharmony_ci    JSVM_Value thisArg = this->This();
9341cb0ef41Sopenharmony_ci    env->CallIntoModule([&](JSVM_Env env) {
9351cb0ef41Sopenharmony_ci                          if (indexDeleterCb) {
9361cb0ef41Sopenharmony_ci                            result = indexDeleterCb(env, index, thisArg, innerData);
9371cb0ef41Sopenharmony_ci                          }
9381cb0ef41Sopenharmony_ci                        },
9391cb0ef41Sopenharmony_ci                        [&](JSVM_Env env, v8::Local<v8::Value> value) {
9401cb0ef41Sopenharmony_ci                          exceptionOccurred = true;
9411cb0ef41Sopenharmony_ci                          if (env->terminatedOrTerminating()) {
9421cb0ef41Sopenharmony_ci                            return;
9431cb0ef41Sopenharmony_ci                          }
9441cb0ef41Sopenharmony_ci                          env->isolate->ThrowException(value);
9451cb0ef41Sopenharmony_ci                        });
9461cb0ef41Sopenharmony_ci    if (!exceptionOccurred && (result != nullptr)) {
9471cb0ef41Sopenharmony_ci      if (v8impl::V8LocalValueFromJsValue(result)->IsBoolean()) {
9481cb0ef41Sopenharmony_ci        this->SetReturnValue(result);
9491cb0ef41Sopenharmony_ci      }
9501cb0ef41Sopenharmony_ci    }
9511cb0ef41Sopenharmony_ci  }
9521cb0ef41Sopenharmony_ci
9531cb0ef41Sopenharmony_ci  inline void IndexEnumeratorInvokeCallback() {
9541cb0ef41Sopenharmony_ci    auto context = _cbinfo.GetIsolate()->GetCurrentContext();
9551cb0ef41Sopenharmony_ci    auto env = v8impl::GetContextEnv(context);
9561cb0ef41Sopenharmony_ci    auto enumeratorCb = _cb->indexedEnumeratorCallback_;
9571cb0ef41Sopenharmony_ci
9581cb0ef41Sopenharmony_ci    JSVM_Value innerData = nullptr;
9591cb0ef41Sopenharmony_ci    if (_cb->indexedPropertyData_ != nullptr) {
9601cb0ef41Sopenharmony_ci      v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(_cb->indexedPropertyData_);
9611cb0ef41Sopenharmony_ci      innerData = v8impl::JsValueFromV8LocalValue(reference->Get());
9621cb0ef41Sopenharmony_ci    }
9631cb0ef41Sopenharmony_ci
9641cb0ef41Sopenharmony_ci    bool exceptionOccurred = false;
9651cb0ef41Sopenharmony_ci    JSVM_Value result = nullptr;
9661cb0ef41Sopenharmony_ci    JSVM_Value thisArg = this->This();
9671cb0ef41Sopenharmony_ci    env->CallIntoModule([&](JSVM_Env env) {
9681cb0ef41Sopenharmony_ci                          if (enumeratorCb) {
9691cb0ef41Sopenharmony_ci                            result = enumeratorCb(env, thisArg, innerData);
9701cb0ef41Sopenharmony_ci                          }
9711cb0ef41Sopenharmony_ci                        },
9721cb0ef41Sopenharmony_ci                        [&](JSVM_Env env, v8::Local<v8::Value> value) {
9731cb0ef41Sopenharmony_ci                          exceptionOccurred = true;
9741cb0ef41Sopenharmony_ci                          if (env->terminatedOrTerminating()) {
9751cb0ef41Sopenharmony_ci                            return;
9761cb0ef41Sopenharmony_ci                          }
9771cb0ef41Sopenharmony_ci                          env->isolate->ThrowException(value);
9781cb0ef41Sopenharmony_ci                        });
9791cb0ef41Sopenharmony_ci    if (!exceptionOccurred && (result != nullptr)) {
9801cb0ef41Sopenharmony_ci      if (v8impl::V8LocalValueFromJsValue(result)->IsArray()) {
9811cb0ef41Sopenharmony_ci        this->SetReturnValue(result);
9821cb0ef41Sopenharmony_ci      }
9831cb0ef41Sopenharmony_ci    }
9841cb0ef41Sopenharmony_ci  }
9851cb0ef41Sopenharmony_ci
9861cb0ef41Sopenharmony_ci  const v8::PropertyCallbackInfo<T>& _cbinfo;
9871cb0ef41Sopenharmony_ci  JSVM_PropertyHandlerCfgStruct* _cb;
9881cb0ef41Sopenharmony_ci  v8::Local<v8::Name> _property;
9891cb0ef41Sopenharmony_ci  v8::Local<v8::Value> _value;
9901cb0ef41Sopenharmony_ci  uint32_t _index;
9911cb0ef41Sopenharmony_ci};
9921cb0ef41Sopenharmony_ci
9931cb0ef41Sopenharmony_citemplate <typename T>
9941cb0ef41Sopenharmony_ciclass PropertyCallbackWrapper : public PropertyCallbackWrapperBase<T> {
9951cb0ef41Sopenharmony_ci public:
9961cb0ef41Sopenharmony_ci  static void NameSetterInvoke(v8::Local<v8::Name> property, v8::Local<v8::Value> value,
9971cb0ef41Sopenharmony_ci    const v8::PropertyCallbackInfo<v8::Value>& info) {
9981cb0ef41Sopenharmony_ci    PropertyCallbackWrapper<v8::Value> propertyCbWrapper(property, value, info);
9991cb0ef41Sopenharmony_ci    propertyCbWrapper.NameSetterInvokeCallback();
10001cb0ef41Sopenharmony_ci  }
10011cb0ef41Sopenharmony_ci
10021cb0ef41Sopenharmony_ci  static void NameGetterInvoke(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
10031cb0ef41Sopenharmony_ci    PropertyCallbackWrapper<v8::Value> propertyCbWrapper(property, v8::Local<v8::Value>(), info);
10041cb0ef41Sopenharmony_ci    propertyCbWrapper.NameGetterInvokeCallback();
10051cb0ef41Sopenharmony_ci  }
10061cb0ef41Sopenharmony_ci
10071cb0ef41Sopenharmony_ci  static void NameDeleterInvoke(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
10081cb0ef41Sopenharmony_ci    PropertyCallbackWrapper<v8::Boolean> propertyCbWrapper(property, v8::Local<v8::Value>(), info);
10091cb0ef41Sopenharmony_ci    propertyCbWrapper.NameDeleterInvokeCallback();
10101cb0ef41Sopenharmony_ci  }
10111cb0ef41Sopenharmony_ci
10121cb0ef41Sopenharmony_ci  static void NameEnumeratorInvoke(const v8::PropertyCallbackInfo<v8::Array>& info) {
10131cb0ef41Sopenharmony_ci    PropertyCallbackWrapper<v8::Array> propertyCbWrapper(v8::Local<v8::Name>(), v8::Local<v8::Value>(), info);
10141cb0ef41Sopenharmony_ci    propertyCbWrapper.NameEnumeratorInvokeCallback();
10151cb0ef41Sopenharmony_ci  }
10161cb0ef41Sopenharmony_ci
10171cb0ef41Sopenharmony_ci  static void IndexSetterInvoke(uint32_t index, v8::Local<v8::Value> value,
10181cb0ef41Sopenharmony_ci    const v8::PropertyCallbackInfo<v8::Value>& info) {
10191cb0ef41Sopenharmony_ci    PropertyCallbackWrapper<v8::Value> propertyCbWrapper(index, value, info);
10201cb0ef41Sopenharmony_ci    propertyCbWrapper.IndexSetterInvokeCallback();
10211cb0ef41Sopenharmony_ci  }
10221cb0ef41Sopenharmony_ci
10231cb0ef41Sopenharmony_ci  static void IndexGetterInvoke(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
10241cb0ef41Sopenharmony_ci    PropertyCallbackWrapper<v8::Value> propertyCbWrapper(index, v8::Local<v8::Value>(), info);
10251cb0ef41Sopenharmony_ci    propertyCbWrapper.IndexGetterInvokeCallback();
10261cb0ef41Sopenharmony_ci  }
10271cb0ef41Sopenharmony_ci
10281cb0ef41Sopenharmony_ci  static void IndexDeleterInvoke(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
10291cb0ef41Sopenharmony_ci    PropertyCallbackWrapper<v8::Boolean> propertyCbWrapper(index, v8::Local<v8::Value>(), info);
10301cb0ef41Sopenharmony_ci    propertyCbWrapper.IndexDeleterInvokeCallback();
10311cb0ef41Sopenharmony_ci  }
10321cb0ef41Sopenharmony_ci
10331cb0ef41Sopenharmony_ci  static void IndexEnumeratorInvoke(const v8::PropertyCallbackInfo<v8::Array>& info) {
10341cb0ef41Sopenharmony_ci    PropertyCallbackWrapper<v8::Array> propertyCbWrapper(0, v8::Local<v8::Value>(), info);
10351cb0ef41Sopenharmony_ci    propertyCbWrapper.IndexEnumeratorInvokeCallback();
10361cb0ef41Sopenharmony_ci  }
10371cb0ef41Sopenharmony_ci
10381cb0ef41Sopenharmony_ci  explicit PropertyCallbackWrapper(v8::Local<v8::Name> name, v8::Local<v8::Value> value,
10391cb0ef41Sopenharmony_ci      const v8::PropertyCallbackInfo<T>& cbinfo)
10401cb0ef41Sopenharmony_ci      : PropertyCallbackWrapperBase<T>(0, name, value, cbinfo, 0), _cbInfo(cbinfo) {}
10411cb0ef41Sopenharmony_ci
10421cb0ef41Sopenharmony_ci  explicit PropertyCallbackWrapper(uint32_t index, v8::Local<v8::Value> value,
10431cb0ef41Sopenharmony_ci      const v8::PropertyCallbackInfo<T>& cbinfo)
10441cb0ef41Sopenharmony_ci      : PropertyCallbackWrapperBase<T>(index, v8::Local<v8::Name>(), value, cbinfo, 0), _cbInfo(cbinfo) {}
10451cb0ef41Sopenharmony_ci
10461cb0ef41Sopenharmony_ci  /*virtual*/
10471cb0ef41Sopenharmony_ci  void SetReturnValue(JSVM_Value value) override {
10481cb0ef41Sopenharmony_ci    v8::Local<T> val = v8impl::V8LocalValueFromJsValue(value).As<T>();
10491cb0ef41Sopenharmony_ci    _cbInfo.GetReturnValue().Set(val);
10501cb0ef41Sopenharmony_ci  }
10511cb0ef41Sopenharmony_ci
10521cb0ef41Sopenharmony_ciprotected:
10531cb0ef41Sopenharmony_ci  const v8::PropertyCallbackInfo<T>& _cbInfo;
10541cb0ef41Sopenharmony_ci};
10551cb0ef41Sopenharmony_ci
10561cb0ef41Sopenharmony_ciinline JSVM_Status Wrap(JSVM_Env env,
10571cb0ef41Sopenharmony_ci                        JSVM_Value jsObject,
10581cb0ef41Sopenharmony_ci                        void* nativeObject,
10591cb0ef41Sopenharmony_ci                        JSVM_Finalize finalizeCb,
10601cb0ef41Sopenharmony_ci                        void* finalizeHint,
10611cb0ef41Sopenharmony_ci                        JSVM_Ref* result) {
10621cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
10631cb0ef41Sopenharmony_ci  CHECK_ARG(env, jsObject);
10641cb0ef41Sopenharmony_ci
10651cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
10661cb0ef41Sopenharmony_ci
10671cb0ef41Sopenharmony_ci  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(jsObject);
10681cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, value->IsObject(), JSVM_INVALID_ARG);
10691cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj = value.As<v8::Object>();
10701cb0ef41Sopenharmony_ci
10711cb0ef41Sopenharmony_ci  // If we've already wrapped this object, we error out.
10721cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(
10731cb0ef41Sopenharmony_ci      env,
10741cb0ef41Sopenharmony_ci      !obj->HasPrivate(context, JSVM_PRIVATE_KEY(env->isolate, wrapper)).FromJust(),
10751cb0ef41Sopenharmony_ci      JSVM_INVALID_ARG);
10761cb0ef41Sopenharmony_ci
10771cb0ef41Sopenharmony_ci  v8impl::Reference* reference = nullptr;
10781cb0ef41Sopenharmony_ci  if (result != nullptr) {
10791cb0ef41Sopenharmony_ci    // The returned reference should be deleted via OH_JSVM_DeleteReference()
10801cb0ef41Sopenharmony_ci    // ONLY in response to the finalize callback invocation. (If it is deleted
10811cb0ef41Sopenharmony_ci    // before then, then the finalize callback will never be invoked.)
10821cb0ef41Sopenharmony_ci    // Therefore a finalize callback is required when returning a reference.
10831cb0ef41Sopenharmony_ci    CHECK_ARG(env, finalizeCb);
10841cb0ef41Sopenharmony_ci    reference = v8impl::Reference::New(env,
10851cb0ef41Sopenharmony_ci                                       obj,
10861cb0ef41Sopenharmony_ci                                       0,
10871cb0ef41Sopenharmony_ci                                       v8impl::Ownership::kUserland,
10881cb0ef41Sopenharmony_ci                                       finalizeCb,
10891cb0ef41Sopenharmony_ci                                       nativeObject,
10901cb0ef41Sopenharmony_ci                                       finalizeHint);
10911cb0ef41Sopenharmony_ci    *result = reinterpret_cast<JSVM_Ref>(reference);
10921cb0ef41Sopenharmony_ci  } else {
10931cb0ef41Sopenharmony_ci    // Create a self-deleting reference.
10941cb0ef41Sopenharmony_ci    reference = v8impl::Reference::New(
10951cb0ef41Sopenharmony_ci        env,
10961cb0ef41Sopenharmony_ci        obj,
10971cb0ef41Sopenharmony_ci        0,
10981cb0ef41Sopenharmony_ci        v8impl::Ownership::kRuntime,
10991cb0ef41Sopenharmony_ci        finalizeCb,
11001cb0ef41Sopenharmony_ci        nativeObject,
11011cb0ef41Sopenharmony_ci        finalizeCb == nullptr ? nullptr : finalizeHint);
11021cb0ef41Sopenharmony_ci  }
11031cb0ef41Sopenharmony_ci
11041cb0ef41Sopenharmony_ci  CHECK(obj->SetPrivate(context,
11051cb0ef41Sopenharmony_ci                        JSVM_PRIVATE_KEY(env->isolate, wrapper),
11061cb0ef41Sopenharmony_ci                        v8::External::New(env->isolate, reference))
11071cb0ef41Sopenharmony_ci            .FromJust());
11081cb0ef41Sopenharmony_ci
11091cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
11101cb0ef41Sopenharmony_ci}
11111cb0ef41Sopenharmony_ci
11121cb0ef41Sopenharmony_ci// In JavaScript, weak references can be created for object types (Object,
11131cb0ef41Sopenharmony_ci// Function, and external Object) and for local symbols that are created with
11141cb0ef41Sopenharmony_ci// the `Symbol` function call. Global symbols created with the `Symbol.for`
11151cb0ef41Sopenharmony_ci// method cannot be weak references because they are never collected.
11161cb0ef41Sopenharmony_ci//
11171cb0ef41Sopenharmony_ci// Currently, V8 has no API to detect if a symbol is local or global.
11181cb0ef41Sopenharmony_ci// Until we have a V8 API for it, we consider that all symbols can be weak.
11191cb0ef41Sopenharmony_ci// This matches the current Node-API behavior.
11201cb0ef41Sopenharmony_ciinline bool CanBeHeldWeakly(v8::Local<v8::Value> value) {
11211cb0ef41Sopenharmony_ci  return value->IsObject() || value->IsSymbol();
11221cb0ef41Sopenharmony_ci}
11231cb0ef41Sopenharmony_ci
11241cb0ef41Sopenharmony_ci}  // end of anonymous namespace
11251cb0ef41Sopenharmony_ci
11261cb0ef41Sopenharmony_civoid Finalizer::ResetFinalizer() {
11271cb0ef41Sopenharmony_ci  finalize_callback_ = nullptr;
11281cb0ef41Sopenharmony_ci  finalize_data_ = nullptr;
11291cb0ef41Sopenharmony_ci  finalize_hint_ = nullptr;
11301cb0ef41Sopenharmony_ci}
11311cb0ef41Sopenharmony_ci
11321cb0ef41Sopenharmony_ciTrackedFinalizer::TrackedFinalizer(JSVM_Env env,
11331cb0ef41Sopenharmony_ci                                   JSVM_Finalize finalizeCallback,
11341cb0ef41Sopenharmony_ci                                   void* finalizeData,
11351cb0ef41Sopenharmony_ci                                   void* finalizeHint)
11361cb0ef41Sopenharmony_ci    : Finalizer(env, finalizeCallback, finalizeData, finalizeHint),
11371cb0ef41Sopenharmony_ci      RefTracker() {
11381cb0ef41Sopenharmony_ci  Link(finalizeCallback == nullptr ? &env->reflist : &env->finalizing_reflist);
11391cb0ef41Sopenharmony_ci}
11401cb0ef41Sopenharmony_ci
11411cb0ef41Sopenharmony_ciTrackedFinalizer* TrackedFinalizer::New(JSVM_Env env,
11421cb0ef41Sopenharmony_ci                                        JSVM_Finalize finalizeCallback,
11431cb0ef41Sopenharmony_ci                                        void* finalizeData,
11441cb0ef41Sopenharmony_ci                                        void* finalizeHint) {
11451cb0ef41Sopenharmony_ci  return new TrackedFinalizer(
11461cb0ef41Sopenharmony_ci      env, finalizeCallback, finalizeData, finalizeHint);
11471cb0ef41Sopenharmony_ci}
11481cb0ef41Sopenharmony_ci
11491cb0ef41Sopenharmony_ci// When a TrackedFinalizer is being deleted, it may have been queued to call its
11501cb0ef41Sopenharmony_ci// finalizer.
11511cb0ef41Sopenharmony_ciTrackedFinalizer::~TrackedFinalizer() {
11521cb0ef41Sopenharmony_ci  // Remove from the env's tracked list.
11531cb0ef41Sopenharmony_ci  Unlink();
11541cb0ef41Sopenharmony_ci  // Try to remove the finalizer from the scheduled second pass callback.
11551cb0ef41Sopenharmony_ci  env_->DequeueFinalizer(this);
11561cb0ef41Sopenharmony_ci}
11571cb0ef41Sopenharmony_ci
11581cb0ef41Sopenharmony_civoid TrackedFinalizer::Finalize() {
11591cb0ef41Sopenharmony_ci  FinalizeCore(/*deleteMe:*/ true);
11601cb0ef41Sopenharmony_ci}
11611cb0ef41Sopenharmony_ci
11621cb0ef41Sopenharmony_civoid TrackedFinalizer::FinalizeCore(bool deleteMe) {
11631cb0ef41Sopenharmony_ci  // Swap out the field finalize_callback so that it can not be accidentally
11641cb0ef41Sopenharmony_ci  // called more than once.
11651cb0ef41Sopenharmony_ci  JSVM_Finalize finalizeCallback = finalize_callback_;
11661cb0ef41Sopenharmony_ci  void* finalizeData = finalize_data_;
11671cb0ef41Sopenharmony_ci  void* finalizeHint = finalize_hint_;
11681cb0ef41Sopenharmony_ci  ResetFinalizer();
11691cb0ef41Sopenharmony_ci
11701cb0ef41Sopenharmony_ci  // Either the RefBase is going to be deleted in the finalize_callback or not,
11711cb0ef41Sopenharmony_ci  // it should be removed from the tracked list.
11721cb0ef41Sopenharmony_ci  Unlink();
11731cb0ef41Sopenharmony_ci  // If the finalize_callback is present, it should either delete the
11741cb0ef41Sopenharmony_ci  // derived RefBase, or the RefBase ownership was set to Ownership::kRuntime
11751cb0ef41Sopenharmony_ci  // and the deleteMe parameter is true.
11761cb0ef41Sopenharmony_ci  if (finalizeCallback != nullptr) {
11771cb0ef41Sopenharmony_ci    env_->CallFinalizer(finalizeCallback, finalizeData, finalizeHint);
11781cb0ef41Sopenharmony_ci  }
11791cb0ef41Sopenharmony_ci
11801cb0ef41Sopenharmony_ci  if (deleteMe) {
11811cb0ef41Sopenharmony_ci    delete this;
11821cb0ef41Sopenharmony_ci  }
11831cb0ef41Sopenharmony_ci}
11841cb0ef41Sopenharmony_ci
11851cb0ef41Sopenharmony_ci// Wrapper around v8impl::Persistent that implements reference counting.
11861cb0ef41Sopenharmony_ciRefBase::RefBase(JSVM_Env env,
11871cb0ef41Sopenharmony_ci                 uint32_t initialRefcount,
11881cb0ef41Sopenharmony_ci                 Ownership ownership,
11891cb0ef41Sopenharmony_ci                 JSVM_Finalize finalizeCallback,
11901cb0ef41Sopenharmony_ci                 void* finalizeData,
11911cb0ef41Sopenharmony_ci                 void* finalizeHint)
11921cb0ef41Sopenharmony_ci    : TrackedFinalizer(env, finalizeCallback, finalizeData, finalizeHint),
11931cb0ef41Sopenharmony_ci      refcount_(initialRefcount),
11941cb0ef41Sopenharmony_ci      ownership_(ownership) {}
11951cb0ef41Sopenharmony_ci
11961cb0ef41Sopenharmony_ciRefBase* RefBase::New(JSVM_Env env,
11971cb0ef41Sopenharmony_ci                      uint32_t initialRefcount,
11981cb0ef41Sopenharmony_ci                      Ownership ownership,
11991cb0ef41Sopenharmony_ci                      JSVM_Finalize finalizeCallback,
12001cb0ef41Sopenharmony_ci                      void* finalizeData,
12011cb0ef41Sopenharmony_ci                      void* finalizeHint) {
12021cb0ef41Sopenharmony_ci  return new RefBase(env,
12031cb0ef41Sopenharmony_ci                     initialRefcount,
12041cb0ef41Sopenharmony_ci                     ownership,
12051cb0ef41Sopenharmony_ci                     finalizeCallback,
12061cb0ef41Sopenharmony_ci                     finalizeData,
12071cb0ef41Sopenharmony_ci                     finalizeHint);
12081cb0ef41Sopenharmony_ci}
12091cb0ef41Sopenharmony_ci
12101cb0ef41Sopenharmony_civoid* RefBase::Data() {
12111cb0ef41Sopenharmony_ci  return finalize_data_;
12121cb0ef41Sopenharmony_ci}
12131cb0ef41Sopenharmony_ci
12141cb0ef41Sopenharmony_ciuint32_t RefBase::Ref() {
12151cb0ef41Sopenharmony_ci  return ++refcount_;
12161cb0ef41Sopenharmony_ci}
12171cb0ef41Sopenharmony_ci
12181cb0ef41Sopenharmony_ciuint32_t RefBase::Unref() {
12191cb0ef41Sopenharmony_ci  if (refcount_ == 0) {
12201cb0ef41Sopenharmony_ci    return 0;
12211cb0ef41Sopenharmony_ci  }
12221cb0ef41Sopenharmony_ci  return --refcount_;
12231cb0ef41Sopenharmony_ci}
12241cb0ef41Sopenharmony_ci
12251cb0ef41Sopenharmony_ciuint32_t RefBase::RefCount() {
12261cb0ef41Sopenharmony_ci  return refcount_;
12271cb0ef41Sopenharmony_ci}
12281cb0ef41Sopenharmony_ci
12291cb0ef41Sopenharmony_civoid RefBase::Finalize() {
12301cb0ef41Sopenharmony_ci  // If the RefBase is not Ownership::kRuntime, userland code should delete it.
12311cb0ef41Sopenharmony_ci  // Delete it if it is Ownership::kRuntime.
12321cb0ef41Sopenharmony_ci  FinalizeCore(/*deleteMe:*/ ownership_ == Ownership::kRuntime);
12331cb0ef41Sopenharmony_ci}
12341cb0ef41Sopenharmony_ci
12351cb0ef41Sopenharmony_citemplate <typename... Args>
12361cb0ef41Sopenharmony_ciReference::Reference(JSVM_Env env, v8::Local<v8::Value> value, Args&&... args)
12371cb0ef41Sopenharmony_ci    : RefBase(env, std::forward<Args>(args)...),
12381cb0ef41Sopenharmony_ci      persistent_(env->isolate, value),
12391cb0ef41Sopenharmony_ci      can_be_weak_(CanBeHeldWeakly(value)),
12401cb0ef41Sopenharmony_ci      deleted_by_user(false),
12411cb0ef41Sopenharmony_ci      wait_callback(false) {
12421cb0ef41Sopenharmony_ci  if (RefCount() == 0) {
12431cb0ef41Sopenharmony_ci    SetWeak();
12441cb0ef41Sopenharmony_ci  }
12451cb0ef41Sopenharmony_ci}
12461cb0ef41Sopenharmony_ci
12471cb0ef41Sopenharmony_ciReference::~Reference() {
12481cb0ef41Sopenharmony_ci  // Reset the handle. And no weak callback will be invoked.
12491cb0ef41Sopenharmony_ci  persistent_.Reset();
12501cb0ef41Sopenharmony_ci}
12511cb0ef41Sopenharmony_ci
12521cb0ef41Sopenharmony_ciReference* Reference::New(JSVM_Env env,
12531cb0ef41Sopenharmony_ci                          v8::Local<v8::Value> value,
12541cb0ef41Sopenharmony_ci                          uint32_t initialRefcount,
12551cb0ef41Sopenharmony_ci                          Ownership ownership,
12561cb0ef41Sopenharmony_ci                          JSVM_Finalize finalizeCallback,
12571cb0ef41Sopenharmony_ci                          void* finalizeData,
12581cb0ef41Sopenharmony_ci                          void* finalizeHint) {
12591cb0ef41Sopenharmony_ci  return new Reference(env,
12601cb0ef41Sopenharmony_ci                       value,
12611cb0ef41Sopenharmony_ci                       initialRefcount,
12621cb0ef41Sopenharmony_ci                       ownership,
12631cb0ef41Sopenharmony_ci                       finalizeCallback,
12641cb0ef41Sopenharmony_ci                       finalizeData,
12651cb0ef41Sopenharmony_ci                       finalizeHint);
12661cb0ef41Sopenharmony_ci}
12671cb0ef41Sopenharmony_ci
12681cb0ef41Sopenharmony_ciuint32_t Reference::Ref() {
12691cb0ef41Sopenharmony_ci  // When the persistent_ is cleared in the WeakCallback, and a second pass
12701cb0ef41Sopenharmony_ci  // callback is pending, return 0 unconditionally.
12711cb0ef41Sopenharmony_ci  if (persistent_.IsEmpty()) {
12721cb0ef41Sopenharmony_ci    return 0;
12731cb0ef41Sopenharmony_ci  }
12741cb0ef41Sopenharmony_ci  uint32_t refcount = RefBase::Ref();
12751cb0ef41Sopenharmony_ci  if (refcount == 1 && can_be_weak_) {
12761cb0ef41Sopenharmony_ci    persistent_.ClearWeak();
12771cb0ef41Sopenharmony_ci    wait_callback = false;
12781cb0ef41Sopenharmony_ci  }
12791cb0ef41Sopenharmony_ci  return refcount;
12801cb0ef41Sopenharmony_ci}
12811cb0ef41Sopenharmony_ci
12821cb0ef41Sopenharmony_ciuint32_t Reference::Unref() {
12831cb0ef41Sopenharmony_ci  // When the persistent_ is cleared in the WeakCallback, and a second pass
12841cb0ef41Sopenharmony_ci  // callback is pending, return 0 unconditionally.
12851cb0ef41Sopenharmony_ci  if (persistent_.IsEmpty()) {
12861cb0ef41Sopenharmony_ci    return 0;
12871cb0ef41Sopenharmony_ci  }
12881cb0ef41Sopenharmony_ci  uint32_t old_refcount = RefCount();
12891cb0ef41Sopenharmony_ci  uint32_t refcount = RefBase::Unref();
12901cb0ef41Sopenharmony_ci  if (old_refcount == 1 && refcount == 0) {
12911cb0ef41Sopenharmony_ci    SetWeak();
12921cb0ef41Sopenharmony_ci  }
12931cb0ef41Sopenharmony_ci  return refcount;
12941cb0ef41Sopenharmony_ci}
12951cb0ef41Sopenharmony_ci
12961cb0ef41Sopenharmony_civ8::Local<v8::Value> Reference::Get() {
12971cb0ef41Sopenharmony_ci  if (persistent_.IsEmpty()) {
12981cb0ef41Sopenharmony_ci    return v8::Local<v8::Value>();
12991cb0ef41Sopenharmony_ci  } else {
13001cb0ef41Sopenharmony_ci    return v8::Local<v8::Value>::New(env_->isolate, persistent_);
13011cb0ef41Sopenharmony_ci  }
13021cb0ef41Sopenharmony_ci}
13031cb0ef41Sopenharmony_ci
13041cb0ef41Sopenharmony_civoid Reference::Delete() {
13051cb0ef41Sopenharmony_ci  assert(Ownership() == kUserland);
13061cb0ef41Sopenharmony_ci  if (!wait_callback) {
13071cb0ef41Sopenharmony_ci    delete this;
13081cb0ef41Sopenharmony_ci  } else {
13091cb0ef41Sopenharmony_ci    deleted_by_user = true;
13101cb0ef41Sopenharmony_ci  }
13111cb0ef41Sopenharmony_ci}
13121cb0ef41Sopenharmony_ci
13131cb0ef41Sopenharmony_civoid Reference::Finalize() {
13141cb0ef41Sopenharmony_ci  // Unconditionally reset the persistent handle so that no weak callback will
13151cb0ef41Sopenharmony_ci  // be invoked again.
13161cb0ef41Sopenharmony_ci  persistent_.Reset();
13171cb0ef41Sopenharmony_ci
13181cb0ef41Sopenharmony_ci  // Chain up to perform the rest of the finalization.
13191cb0ef41Sopenharmony_ci  RefBase::Finalize();
13201cb0ef41Sopenharmony_ci}
13211cb0ef41Sopenharmony_ci
13221cb0ef41Sopenharmony_ci// Mark the reference as weak and eligible for collection
13231cb0ef41Sopenharmony_ci// by the gc.
13241cb0ef41Sopenharmony_civoid Reference::SetWeak() {
13251cb0ef41Sopenharmony_ci  if (can_be_weak_) {
13261cb0ef41Sopenharmony_ci    wait_callback = true;
13271cb0ef41Sopenharmony_ci    persistent_.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter);
13281cb0ef41Sopenharmony_ci  } else {
13291cb0ef41Sopenharmony_ci    persistent_.Reset();
13301cb0ef41Sopenharmony_ci  }
13311cb0ef41Sopenharmony_ci}
13321cb0ef41Sopenharmony_ci
13331cb0ef41Sopenharmony_ci// The N-API finalizer callback may make calls into the engine. V8's heap is
13341cb0ef41Sopenharmony_ci// not in a consistent state during the weak callback, and therefore it does
13351cb0ef41Sopenharmony_ci// not support calls back into it. Enqueue the invocation of the finalizer.
13361cb0ef41Sopenharmony_civoid Reference::WeakCallback(const v8::WeakCallbackInfo<Reference>& data) {
13371cb0ef41Sopenharmony_ci  Reference* reference = data.GetParameter();
13381cb0ef41Sopenharmony_ci  // The reference must be reset during the weak callback as the API protocol.
13391cb0ef41Sopenharmony_ci  reference->persistent_.Reset();
13401cb0ef41Sopenharmony_ci  assert(reference->wait_callback);
13411cb0ef41Sopenharmony_ci  // For owership == kRuntime, deleted_by_user is always false.
13421cb0ef41Sopenharmony_ci  // Due to reference may be free in InvokeFinalizerFromGC, the status of
13431cb0ef41Sopenharmony_ci  // reference should be set before finalize call.
13441cb0ef41Sopenharmony_ci  bool need_delete = reference->deleted_by_user;
13451cb0ef41Sopenharmony_ci  reference->wait_callback = false;
13461cb0ef41Sopenharmony_ci  reference->env_->InvokeFinalizerFromGC(reference);
13471cb0ef41Sopenharmony_ci  if (need_delete) {
13481cb0ef41Sopenharmony_ci    delete reference;
13491cb0ef41Sopenharmony_ci  }
13501cb0ef41Sopenharmony_ci}
13511cb0ef41Sopenharmony_ci
13521cb0ef41Sopenharmony_ci}  // end of namespace v8impl
13531cb0ef41Sopenharmony_ci
13541cb0ef41Sopenharmony_civ8::Platform* JSVM_Env__::platform() {
13551cb0ef41Sopenharmony_ci  return v8impl::g_platform.get();
13561cb0ef41Sopenharmony_ci}
13571cb0ef41Sopenharmony_ci
13581cb0ef41Sopenharmony_ciconstexpr int MAX_FILE_LENGTH = 32 * 1024 * 1024;
13591cb0ef41Sopenharmony_ci
13601cb0ef41Sopenharmony_cistatic bool LoadStringFromFile(const std::string& filePath, std::string& content)
13611cb0ef41Sopenharmony_ci{
13621cb0ef41Sopenharmony_ci  std::ifstream file(filePath.c_str());
13631cb0ef41Sopenharmony_ci  if (!file.is_open()) {
13641cb0ef41Sopenharmony_ci    return false;
13651cb0ef41Sopenharmony_ci  }
13661cb0ef41Sopenharmony_ci
13671cb0ef41Sopenharmony_ci  file.seekg(0, std::ios::end);
13681cb0ef41Sopenharmony_ci  const long fileLength = file.tellg();
13691cb0ef41Sopenharmony_ci  if (fileLength > MAX_FILE_LENGTH) {
13701cb0ef41Sopenharmony_ci    return false;
13711cb0ef41Sopenharmony_ci  }
13721cb0ef41Sopenharmony_ci
13731cb0ef41Sopenharmony_ci  content.clear();
13741cb0ef41Sopenharmony_ci  file.seekg(0, std::ios::beg);
13751cb0ef41Sopenharmony_ci  std::copy(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), std::back_inserter(content));
13761cb0ef41Sopenharmony_ci  return true;
13771cb0ef41Sopenharmony_ci}
13781cb0ef41Sopenharmony_ci
13791cb0ef41Sopenharmony_cistatic bool ProcessBundleName(std::string& bundleName)
13801cb0ef41Sopenharmony_ci{
13811cb0ef41Sopenharmony_ci  int pid = getprocpid();
13821cb0ef41Sopenharmony_ci  std::string filePath = "/proc/" + std::to_string(pid) + "/cmdline";
13831cb0ef41Sopenharmony_ci  if (!LoadStringFromFile(filePath, bundleName)) {
13841cb0ef41Sopenharmony_ci    return false;
13851cb0ef41Sopenharmony_ci  }
13861cb0ef41Sopenharmony_ci  if (bundleName.empty()) {
13871cb0ef41Sopenharmony_ci    return false;
13881cb0ef41Sopenharmony_ci  }
13891cb0ef41Sopenharmony_ci  auto pos = bundleName.find(":");
13901cb0ef41Sopenharmony_ci  if (pos != std::string::npos) {
13911cb0ef41Sopenharmony_ci    bundleName = bundleName.substr(0, pos);
13921cb0ef41Sopenharmony_ci  }
13931cb0ef41Sopenharmony_ci  bundleName = bundleName.substr(0, strlen(bundleName.c_str()));
13941cb0ef41Sopenharmony_ci  return true;
13951cb0ef41Sopenharmony_ci}
13961cb0ef41Sopenharmony_ci
13971cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
13981cb0ef41Sopenharmony_ciOH_JSVM_Init(const JSVM_InitOptions* options) {
13991cb0ef41Sopenharmony_ci  static std::atomic<bool> initialized(false);
14001cb0ef41Sopenharmony_ci  if (initialized.load()) {
14011cb0ef41Sopenharmony_ci    return JSVM_GENERIC_FAILURE;
14021cb0ef41Sopenharmony_ci  }
14031cb0ef41Sopenharmony_ci  initialized.store(true);
14041cb0ef41Sopenharmony_ci#ifdef TARGET_OHOS
14051cb0ef41Sopenharmony_ci#ifdef ENABLE_HISYSEVENT
14061cb0ef41Sopenharmony_ci  std::string bundleName;
14071cb0ef41Sopenharmony_ci  if (!ProcessBundleName(bundleName)) {
14081cb0ef41Sopenharmony_ci    bundleName = "INVALID_BUNDLE_NAME";
14091cb0ef41Sopenharmony_ci  }
14101cb0ef41Sopenharmony_ci  HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::JSVM_RUNTIME, "APP_STATS",
14111cb0ef41Sopenharmony_ci                  OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
14121cb0ef41Sopenharmony_ci                  "BUNDLE_NAME", bundleName);
14131cb0ef41Sopenharmony_ci#endif
14141cb0ef41Sopenharmony_ci  v8impl::ResourceSchedule::ReportKeyThread(getuid(), getprocpid(), getproctid(),
14151cb0ef41Sopenharmony_ci    v8impl::ResourceSchedule::ResType::ThreadRole::IMPORTANT_DISPLAY);
14161cb0ef41Sopenharmony_ci#endif
14171cb0ef41Sopenharmony_ci  v8::V8::InitializePlatform(v8impl::g_platform.get());
14181cb0ef41Sopenharmony_ci
14191cb0ef41Sopenharmony_ci  if (node::ReadSystemXpmState()) {
14201cb0ef41Sopenharmony_ci    int secArgc = SECARGCNT;
14211cb0ef41Sopenharmony_ci    char *secArgv[SECARGCNT] = {const_cast<char*>("jsvm"), const_cast<char*>("--jitless")};
14221cb0ef41Sopenharmony_ci    v8::V8::SetFlagsFromCommandLine(&secArgc, secArgv, false);
14231cb0ef41Sopenharmony_ci  }
14241cb0ef41Sopenharmony_ci
14251cb0ef41Sopenharmony_ci  if (options && options->argc && options->argv) {
14261cb0ef41Sopenharmony_ci    v8::V8::SetFlagsFromCommandLine(options->argc, options->argv, options->removeFlags);
14271cb0ef41Sopenharmony_ci  }
14281cb0ef41Sopenharmony_ci  v8::V8::Initialize();
14291cb0ef41Sopenharmony_ci
14301cb0ef41Sopenharmony_ci  const auto cb = v8impl::FunctionCallbackWrapper::Invoke;
14311cb0ef41Sopenharmony_ci  v8impl::externalReferenceRegistry.push_back((intptr_t)cb);
14321cb0ef41Sopenharmony_ci  if (auto p = options ? options->externalReferences : nullptr) {
14331cb0ef41Sopenharmony_ci    for (; *p != 0; p++) {
14341cb0ef41Sopenharmony_ci      v8impl::externalReferenceRegistry.push_back(*p);
14351cb0ef41Sopenharmony_ci    }
14361cb0ef41Sopenharmony_ci  }
14371cb0ef41Sopenharmony_ci  v8impl::externalReferenceRegistry.push_back(0);
14381cb0ef41Sopenharmony_ci  return JSVM_OK;
14391cb0ef41Sopenharmony_ci}
14401cb0ef41Sopenharmony_ci
14411cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetVM(JSVM_Env env,
14421cb0ef41Sopenharmony_ci				      JSVM_VM* result) {
14431cb0ef41Sopenharmony_ci  *result = reinterpret_cast<JSVM_VM>(env->isolate);
14441cb0ef41Sopenharmony_ci  return JSVM_OK;
14451cb0ef41Sopenharmony_ci}
14461cb0ef41Sopenharmony_ci
14471cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
14481cb0ef41Sopenharmony_ciOH_JSVM_CreateVM(const JSVM_CreateVMOptions* options, JSVM_VM* result) {
14491cb0ef41Sopenharmony_ci#ifdef TARGET_OHOS
14501cb0ef41Sopenharmony_ci  v8impl::ResourceSchedule::ReportKeyThread(getuid(), getprocpid(), getproctid(),
14511cb0ef41Sopenharmony_ci    v8impl::ResourceSchedule::ResType::ThreadRole::USER_INTERACT);
14521cb0ef41Sopenharmony_ci#endif
14531cb0ef41Sopenharmony_ci  v8::Isolate::CreateParams create_params;
14541cb0ef41Sopenharmony_ci  auto externalReferences = v8impl::externalReferenceRegistry.data();
14551cb0ef41Sopenharmony_ci  create_params.external_references = externalReferences;
14561cb0ef41Sopenharmony_ci
14571cb0ef41Sopenharmony_ci  v8::StartupData* snapshotBlob = nullptr;
14581cb0ef41Sopenharmony_ci  if (options && options->snapshotBlobData) {
14591cb0ef41Sopenharmony_ci    snapshotBlob = new v8::StartupData();
14601cb0ef41Sopenharmony_ci    snapshotBlob->data = options->snapshotBlobData;
14611cb0ef41Sopenharmony_ci    snapshotBlob->raw_size = options->snapshotBlobSize;
14621cb0ef41Sopenharmony_ci
14631cb0ef41Sopenharmony_ci    if (!snapshotBlob->IsValid()) {
14641cb0ef41Sopenharmony_ci      // TODO: Is VerifyCheckSum necessay if there has been a validity check?
14651cb0ef41Sopenharmony_ci      delete snapshotBlob;
14661cb0ef41Sopenharmony_ci      return JSVM_INVALID_ARG;
14671cb0ef41Sopenharmony_ci    }
14681cb0ef41Sopenharmony_ci    create_params.snapshot_blob =  snapshotBlob;
14691cb0ef41Sopenharmony_ci  }
14701cb0ef41Sopenharmony_ci
14711cb0ef41Sopenharmony_ci  v8::Isolate* isolate;
14721cb0ef41Sopenharmony_ci  if (options && options->isForSnapshotting) {
14731cb0ef41Sopenharmony_ci    isolate = v8::Isolate::Allocate();
14741cb0ef41Sopenharmony_ci    auto creator = new v8::SnapshotCreator(isolate, externalReferences);
14751cb0ef41Sopenharmony_ci    v8impl::SetIsolateSnapshotCreator(isolate, creator);
14761cb0ef41Sopenharmony_ci  } else {
14771cb0ef41Sopenharmony_ci    create_params.array_buffer_allocator =
14781cb0ef41Sopenharmony_ci      v8impl::GetOrCreateDefaultArrayBufferAllocator();
14791cb0ef41Sopenharmony_ci    isolate = v8::Isolate::New(create_params);
14801cb0ef41Sopenharmony_ci  }
14811cb0ef41Sopenharmony_ci  v8impl::CreateIsolateData(isolate, snapshotBlob);
14821cb0ef41Sopenharmony_ci  *result = reinterpret_cast<JSVM_VM>(isolate);
14831cb0ef41Sopenharmony_ci
14841cb0ef41Sopenharmony_ci  return JSVM_OK;
14851cb0ef41Sopenharmony_ci}
14861cb0ef41Sopenharmony_ci
14871cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
14881cb0ef41Sopenharmony_ciOH_JSVM_DestroyVM(JSVM_VM vm) {
14891cb0ef41Sopenharmony_ci  if (vm == nullptr) {
14901cb0ef41Sopenharmony_ci    return JSVM_INVALID_ARG;
14911cb0ef41Sopenharmony_ci  }
14921cb0ef41Sopenharmony_ci  auto isolate = reinterpret_cast<v8::Isolate*>(vm);
14931cb0ef41Sopenharmony_ci  auto creator = v8impl::GetIsolateSnapshotCreator(isolate);
14941cb0ef41Sopenharmony_ci  auto data = v8impl::GetIsolateData(isolate);
14951cb0ef41Sopenharmony_ci
14961cb0ef41Sopenharmony_ci  if (creator != nullptr) {
14971cb0ef41Sopenharmony_ci    delete creator;
14981cb0ef41Sopenharmony_ci  } else {
14991cb0ef41Sopenharmony_ci    isolate->Dispose();
15001cb0ef41Sopenharmony_ci  }
15011cb0ef41Sopenharmony_ci  if (data != nullptr) {
15021cb0ef41Sopenharmony_ci      delete data;
15031cb0ef41Sopenharmony_ci  }
15041cb0ef41Sopenharmony_ci
15051cb0ef41Sopenharmony_ci  return JSVM_OK;
15061cb0ef41Sopenharmony_ci}
15071cb0ef41Sopenharmony_ci
15081cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_OpenVMScope(JSVM_VM vm, JSVM_VMScope* result) {
15091cb0ef41Sopenharmony_ci  auto isolate = reinterpret_cast<v8::Isolate*>(vm);
15101cb0ef41Sopenharmony_ci  auto scope = new v8::Isolate::Scope(isolate);
15111cb0ef41Sopenharmony_ci  *result = reinterpret_cast<JSVM_VMScope>(scope);
15121cb0ef41Sopenharmony_ci  return JSVM_OK;
15131cb0ef41Sopenharmony_ci}
15141cb0ef41Sopenharmony_ci
15151cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
15161cb0ef41Sopenharmony_ciOH_JSVM_CloseVMScope(JSVM_VM vm, JSVM_VMScope scope) {
15171cb0ef41Sopenharmony_ci  auto v8scope = reinterpret_cast<v8::Isolate::Scope*>(scope);
15181cb0ef41Sopenharmony_ci  delete v8scope;
15191cb0ef41Sopenharmony_ci  return JSVM_OK;
15201cb0ef41Sopenharmony_ci}
15211cb0ef41Sopenharmony_ci
15221cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
15231cb0ef41Sopenharmony_ciOH_JSVM_CreateEnv(JSVM_VM vm,
15241cb0ef41Sopenharmony_ci                size_t propertyCount,
15251cb0ef41Sopenharmony_ci                const JSVM_PropertyDescriptor* properties,
15261cb0ef41Sopenharmony_ci                JSVM_Env* result) {
15271cb0ef41Sopenharmony_ci  auto isolate = reinterpret_cast<v8::Isolate*>(vm);
15281cb0ef41Sopenharmony_ci  auto env = new JSVM_Env__(isolate, NODE_API_DEFAULT_MODULE_API_VERSION);
15291cb0ef41Sopenharmony_ci  v8::HandleScope handle_scope(isolate);
15301cb0ef41Sopenharmony_ci  auto global_template = v8::ObjectTemplate::New(isolate);
15311cb0ef41Sopenharmony_ci
15321cb0ef41Sopenharmony_ci  for (size_t i = 0; i < propertyCount; i++) {
15331cb0ef41Sopenharmony_ci    const JSVM_PropertyDescriptor* p = properties + i;
15341cb0ef41Sopenharmony_ci
15351cb0ef41Sopenharmony_ci    if ((p->attributes & JSVM_STATIC) != 0) {
15361cb0ef41Sopenharmony_ci      //Ignore static properties.
15371cb0ef41Sopenharmony_ci      continue;
15381cb0ef41Sopenharmony_ci    }
15391cb0ef41Sopenharmony_ci
15401cb0ef41Sopenharmony_ci    v8::Local<v8::Name> property_name =
15411cb0ef41Sopenharmony_ci      v8::String::NewFromUtf8(isolate, p->utf8name, v8::NewStringType::kInternalized)
15421cb0ef41Sopenharmony_ci      .ToLocalChecked();
15431cb0ef41Sopenharmony_ci
15441cb0ef41Sopenharmony_ci    v8::PropertyAttribute attributes =
15451cb0ef41Sopenharmony_ci        v8impl::V8PropertyAttributesFromDescriptor(p);
15461cb0ef41Sopenharmony_ci
15471cb0ef41Sopenharmony_ci    if (p->getter != nullptr || p->setter != nullptr) {
15481cb0ef41Sopenharmony_ci      v8::Local<v8::FunctionTemplate> getter_tpl;
15491cb0ef41Sopenharmony_ci      v8::Local<v8::FunctionTemplate> setter_tpl;
15501cb0ef41Sopenharmony_ci      if (p->getter != nullptr) {
15511cb0ef41Sopenharmony_ci        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
15521cb0ef41Sopenharmony_ci            env, p->getter, &getter_tpl));
15531cb0ef41Sopenharmony_ci      }
15541cb0ef41Sopenharmony_ci      if (p->setter != nullptr) {
15551cb0ef41Sopenharmony_ci        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
15561cb0ef41Sopenharmony_ci            env, p->setter, &setter_tpl));
15571cb0ef41Sopenharmony_ci      }
15581cb0ef41Sopenharmony_ci
15591cb0ef41Sopenharmony_ci      global_template->SetAccessorProperty(
15601cb0ef41Sopenharmony_ci          property_name, getter_tpl, setter_tpl, attributes);
15611cb0ef41Sopenharmony_ci    } else if (p->method != nullptr) {
15621cb0ef41Sopenharmony_ci      v8::Local<v8::FunctionTemplate> method_tpl;
15631cb0ef41Sopenharmony_ci      STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
15641cb0ef41Sopenharmony_ci          env, p->method, &method_tpl));
15651cb0ef41Sopenharmony_ci
15661cb0ef41Sopenharmony_ci      global_template->Set(property_name, method_tpl, attributes);
15671cb0ef41Sopenharmony_ci    } else {
15681cb0ef41Sopenharmony_ci      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
15691cb0ef41Sopenharmony_ci      global_template->Set(property_name, value, attributes);
15701cb0ef41Sopenharmony_ci    }
15711cb0ef41Sopenharmony_ci  }
15721cb0ef41Sopenharmony_ci
15731cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global_template);
15741cb0ef41Sopenharmony_ci  env->context_persistent.Reset(isolate, context);
15751cb0ef41Sopenharmony_ci  v8impl::SetContextEnv(context, env);
15761cb0ef41Sopenharmony_ci  *result = env;
15771cb0ef41Sopenharmony_ci  return JSVM_OK;
15781cb0ef41Sopenharmony_ci}
15791cb0ef41Sopenharmony_ci
15801cb0ef41Sopenharmony_ciJSVM_EXTERN JSVM_Status JSVM_CDECL
15811cb0ef41Sopenharmony_ciOH_JSVM_CreateEnvFromSnapshot(JSVM_VM vm, size_t index, JSVM_Env* result) {
15821cb0ef41Sopenharmony_ci  auto isolate = reinterpret_cast<v8::Isolate*>(vm);
15831cb0ef41Sopenharmony_ci  v8::HandleScope handle_scope(isolate);
15841cb0ef41Sopenharmony_ci  auto maybe = v8::Context::FromSnapshot(isolate, index);
15851cb0ef41Sopenharmony_ci
15861cb0ef41Sopenharmony_ci  if (maybe.IsEmpty()) {
15871cb0ef41Sopenharmony_ci    *result = nullptr;
15881cb0ef41Sopenharmony_ci    // TODO: return error message.
15891cb0ef41Sopenharmony_ci    return JSVM_GENERIC_FAILURE;
15901cb0ef41Sopenharmony_ci  }
15911cb0ef41Sopenharmony_ci
15921cb0ef41Sopenharmony_ci  auto env = new JSVM_Env__(isolate, NODE_API_DEFAULT_MODULE_API_VERSION);
15931cb0ef41Sopenharmony_ci  auto context = maybe.ToLocalChecked();
15941cb0ef41Sopenharmony_ci  env->context_persistent.Reset(isolate, context);
15951cb0ef41Sopenharmony_ci  v8impl::SetContextEnv(context, env);
15961cb0ef41Sopenharmony_ci  *result = env;
15971cb0ef41Sopenharmony_ci
15981cb0ef41Sopenharmony_ci  return JSVM_OK;
15991cb0ef41Sopenharmony_ci}
16001cb0ef41Sopenharmony_ci
16011cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
16021cb0ef41Sopenharmony_ciOH_JSVM_DestroyEnv(JSVM_Env env) {
16031cb0ef41Sopenharmony_ci  env->DeleteMe();
16041cb0ef41Sopenharmony_ci  return JSVM_OK;
16051cb0ef41Sopenharmony_ci}
16061cb0ef41Sopenharmony_ci
16071cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
16081cb0ef41Sopenharmony_ci  OH_JSVM_OpenEnvScope(JSVM_Env env, JSVM_EnvScope* result) {
16091cb0ef41Sopenharmony_ci  auto v8scope = new v8::Context::Scope(env->context());
16101cb0ef41Sopenharmony_ci  *result = reinterpret_cast<JSVM_EnvScope>(v8scope);
16111cb0ef41Sopenharmony_ci  return JSVM_OK;
16121cb0ef41Sopenharmony_ci}
16131cb0ef41Sopenharmony_ci
16141cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
16151cb0ef41Sopenharmony_ciOH_JSVM_CloseEnvScope(JSVM_Env env, JSVM_EnvScope scope) {
16161cb0ef41Sopenharmony_ci  auto v8scope = reinterpret_cast<v8::Context::Scope*>(scope);
16171cb0ef41Sopenharmony_ci  delete v8scope;
16181cb0ef41Sopenharmony_ci  return JSVM_OK;
16191cb0ef41Sopenharmony_ci}
16201cb0ef41Sopenharmony_ci
16211cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
16221cb0ef41Sopenharmony_ciOH_JSVM_CompileScript(JSVM_Env env,
16231cb0ef41Sopenharmony_ci      JSVM_Value script,
16241cb0ef41Sopenharmony_ci      const uint8_t *cachedData,
16251cb0ef41Sopenharmony_ci      size_t cachedDataLength,
16261cb0ef41Sopenharmony_ci      bool eagerCompile,
16271cb0ef41Sopenharmony_ci      bool* cacheRejected,
16281cb0ef41Sopenharmony_ci      JSVM_Script* result) {
16291cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
16301cb0ef41Sopenharmony_ci  CHECK_ARG(env, script);
16311cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
16321cb0ef41Sopenharmony_ci
16331cb0ef41Sopenharmony_ci  v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue(script);
16341cb0ef41Sopenharmony_ci
16351cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, v8_script->IsString(), JSVM_STRING_EXPECTED);
16361cb0ef41Sopenharmony_ci
16371cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
16381cb0ef41Sopenharmony_ci
16391cb0ef41Sopenharmony_ci  v8::ScriptCompiler::CachedData* cache = cachedData
16401cb0ef41Sopenharmony_ci    ? new v8::ScriptCompiler::CachedData(cachedData, cachedDataLength) : nullptr;
16411cb0ef41Sopenharmony_ci  v8::ScriptCompiler::Source scriptSource(v8_script.As<v8::String>(), cache);
16421cb0ef41Sopenharmony_ci  auto option = cache ? v8::ScriptCompiler::kConsumeCodeCache
16431cb0ef41Sopenharmony_ci    : (eagerCompile ? v8::ScriptCompiler::kEagerCompile : v8::ScriptCompiler::kNoCompileOptions);
16441cb0ef41Sopenharmony_ci
16451cb0ef41Sopenharmony_ci  auto maybe_script = v8::ScriptCompiler::Compile(context, &scriptSource, option);
16461cb0ef41Sopenharmony_ci
16471cb0ef41Sopenharmony_ci  if (cache) {
16481cb0ef41Sopenharmony_ci    delete cache;
16491cb0ef41Sopenharmony_ci  }
16501cb0ef41Sopenharmony_ci
16511cb0ef41Sopenharmony_ci  if (cache && cacheRejected) {
16521cb0ef41Sopenharmony_ci    *cacheRejected = cache->rejected;
16531cb0ef41Sopenharmony_ci  }
16541cb0ef41Sopenharmony_ci
16551cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, maybe_script, JSVM_GENERIC_FAILURE);
16561cb0ef41Sopenharmony_ci  v8::Local<v8::Script> compiled_script = maybe_script.ToLocalChecked();
16571cb0ef41Sopenharmony_ci  *result = reinterpret_cast<JSVM_Script>(env->NewJsvmData(compiled_script));
16581cb0ef41Sopenharmony_ci
16591cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
16601cb0ef41Sopenharmony_ci}
16611cb0ef41Sopenharmony_ci
16621cb0ef41Sopenharmony_civ8::ScriptOrigin CreateScriptOrigin(
16631cb0ef41Sopenharmony_ci    v8::Isolate* isolate, v8::Local<v8::String> resource_name, v8::ScriptType type) {
16641cb0ef41Sopenharmony_ci  const int kOptionsLength = 2;
16651cb0ef41Sopenharmony_ci  const uint32_t kOptionsMagicConstant = 0xF1F2F3F0;
16661cb0ef41Sopenharmony_ci  auto options = v8::PrimitiveArray::New(isolate, kOptionsLength);
16671cb0ef41Sopenharmony_ci  options->Set(isolate, 0, v8::Uint32::New(isolate, kOptionsMagicConstant));
16681cb0ef41Sopenharmony_ci  options->Set(isolate, 1, resource_name);
16691cb0ef41Sopenharmony_ci  return v8::ScriptOrigin(isolate, resource_name, 0, 0, false, -1, v8::Local<v8::Value>(),
16701cb0ef41Sopenharmony_ci      false, false, type == v8::ScriptType::kModule, options);
16711cb0ef41Sopenharmony_ci}
16721cb0ef41Sopenharmony_ci
16731cb0ef41Sopenharmony_civ8::MaybeLocal<v8::Value> PrepareStackTraceCallback(
16741cb0ef41Sopenharmony_ci    v8::Local<v8::Context> context, v8::Local<v8::Value> error, v8::Local<v8::Array> trace) {
16751cb0ef41Sopenharmony_ci  auto *isolate = context->GetIsolate();
16761cb0ef41Sopenharmony_ci  v8::TryCatch try_catch(isolate);
16771cb0ef41Sopenharmony_ci  v8::Local<v8::String> moduleName =
16781cb0ef41Sopenharmony_ci      v8::String::NewFromUtf8(isolate, "sourcemap").ToLocalChecked();
16791cb0ef41Sopenharmony_ci  v8::Local<v8::String> moduleSourceString =
16801cb0ef41Sopenharmony_ci      v8::String::NewFromUtf8(isolate, SourceMapRunner.c_str()).ToLocalChecked();
16811cb0ef41Sopenharmony_ci
16821cb0ef41Sopenharmony_ci  v8::ScriptOrigin moduleOrigin =
16831cb0ef41Sopenharmony_ci      CreateScriptOrigin(isolate, moduleName, v8::ScriptType::kClassic);
16841cb0ef41Sopenharmony_ci  v8::Local<v8::Context> moduleContext = v8::Context::New(isolate);
16851cb0ef41Sopenharmony_ci  v8::ScriptCompiler::Source moduleSource(moduleSourceString, moduleOrigin);
16861cb0ef41Sopenharmony_ci  auto script =
16871cb0ef41Sopenharmony_ci      v8::Script::Compile(moduleContext, moduleSourceString, &moduleOrigin).ToLocalChecked();
16881cb0ef41Sopenharmony_ci  auto result = script->Run(moduleContext).ToLocalChecked();
16891cb0ef41Sopenharmony_ci  auto resultFunc = v8::Local<v8::Function>::Cast(result);
16901cb0ef41Sopenharmony_ci
16911cb0ef41Sopenharmony_ci  v8::Local<v8::Value> element = trace->Get(context, 0).ToLocalChecked();
16921cb0ef41Sopenharmony_ci  std::string fileName = "";
16931cb0ef41Sopenharmony_ci  if (element->IsObject()) {
16941cb0ef41Sopenharmony_ci    auto obj = element->ToObject(context);
16951cb0ef41Sopenharmony_ci    auto getFileName = v8::String::NewFromUtf8(isolate, "getFileName", v8::NewStringType::kNormal);
16961cb0ef41Sopenharmony_ci    auto function = obj.ToLocalChecked()->Get(context, getFileName.ToLocalChecked()).ToLocalChecked();
16971cb0ef41Sopenharmony_ci    auto lineNumberFunction = v8::Local<v8::Function>::Cast(function);
16981cb0ef41Sopenharmony_ci    auto fileNameObj = lineNumberFunction->Call(context, obj.ToLocalChecked(), 0, {});
16991cb0ef41Sopenharmony_ci    fileName = std::string(*v8::String::Utf8Value(isolate, fileNameObj.ToLocalChecked()));
17001cb0ef41Sopenharmony_ci  }
17011cb0ef41Sopenharmony_ci  auto &&sourceMapUrl = (!fileName.empty()) ? v8impl::GetSourceMapFromFileName(std::move(fileName)) : "";
17021cb0ef41Sopenharmony_ci  std::ifstream sourceMapfile(sourceMapUrl);
17031cb0ef41Sopenharmony_ci  std::string content = "";
17041cb0ef41Sopenharmony_ci  if (sourceMapfile.good()) {
17051cb0ef41Sopenharmony_ci    std::stringstream buffer;
17061cb0ef41Sopenharmony_ci    buffer << sourceMapfile.rdbuf();
17071cb0ef41Sopenharmony_ci    content = buffer.str();
17081cb0ef41Sopenharmony_ci  }
17091cb0ef41Sopenharmony_ci  auto sourceMapObject = v8::String::NewFromUtf8(
17101cb0ef41Sopenharmony_ci      isolate, content.c_str(), v8::NewStringType::kNormal, content.length());
17111cb0ef41Sopenharmony_ci  v8::Local<v8::Value> args[] = { error, trace, sourceMapObject.ToLocalChecked() };
17121cb0ef41Sopenharmony_ci  return resultFunc->Call(moduleContext, v8::Undefined(isolate), node::arraysize(args), args);
17131cb0ef41Sopenharmony_ci}
17141cb0ef41Sopenharmony_ci
17151cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
17161cb0ef41Sopenharmony_ciOH_JSVM_CompileScriptWithOrigin(JSVM_Env env,
17171cb0ef41Sopenharmony_ci                                JSVM_Value script,
17181cb0ef41Sopenharmony_ci                                const uint8_t* cachedData,
17191cb0ef41Sopenharmony_ci                                size_t cachedDataLength,
17201cb0ef41Sopenharmony_ci                                bool eagerCompile,
17211cb0ef41Sopenharmony_ci                                bool* cacheRejected,
17221cb0ef41Sopenharmony_ci                                JSVM_ScriptOrigin* origin,
17231cb0ef41Sopenharmony_ci                                JSVM_Script* result) {
17241cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
17251cb0ef41Sopenharmony_ci  CHECK_ARG(env, script);
17261cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
17271cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(origin->resourceName);
17281cb0ef41Sopenharmony_ci
17291cb0ef41Sopenharmony_ci  v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue(script);
17301cb0ef41Sopenharmony_ci
17311cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, v8_script->IsString(), JSVM_STRING_EXPECTED);
17321cb0ef41Sopenharmony_ci
17331cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
17341cb0ef41Sopenharmony_ci  auto *isolate = context->GetIsolate();
17351cb0ef41Sopenharmony_ci
17361cb0ef41Sopenharmony_ci  if (origin->sourceMapUrl) {
17371cb0ef41Sopenharmony_ci    v8impl::SetFileToSourceMapMapping(origin->resourceName, origin->sourceMapUrl);
17381cb0ef41Sopenharmony_ci    isolate->SetPrepareStackTraceCallback(PrepareStackTraceCallback);
17391cb0ef41Sopenharmony_ci  }
17401cb0ef41Sopenharmony_ci  auto sourceMapUrl = !origin->sourceMapUrl ? v8::Local<v8::Value>() :
17411cb0ef41Sopenharmony_ci    v8::String::NewFromUtf8(isolate, origin->sourceMapUrl).ToLocalChecked().As<v8::Value>();
17421cb0ef41Sopenharmony_ci  auto resourceName =
17431cb0ef41Sopenharmony_ci    v8::String::NewFromUtf8(isolate, origin->resourceName).ToLocalChecked();
17441cb0ef41Sopenharmony_ci  v8::ScriptOrigin scriptOrigin(isolate, resourceName,
17451cb0ef41Sopenharmony_ci    origin->resourceLineOffset, origin->resourceColumnOffset, false, -1, sourceMapUrl);
17461cb0ef41Sopenharmony_ci
17471cb0ef41Sopenharmony_ci  v8::ScriptCompiler::CachedData* cache = cachedData
17481cb0ef41Sopenharmony_ci    ? new v8::ScriptCompiler::CachedData(cachedData, cachedDataLength) : nullptr;
17491cb0ef41Sopenharmony_ci  v8::ScriptCompiler::Source scriptSource(v8_script.As<v8::String>(), scriptOrigin, cache);
17501cb0ef41Sopenharmony_ci  auto option = cache ? v8::ScriptCompiler::kConsumeCodeCache
17511cb0ef41Sopenharmony_ci    : (eagerCompile ? v8::ScriptCompiler::kEagerCompile : v8::ScriptCompiler::kNoCompileOptions);
17521cb0ef41Sopenharmony_ci
17531cb0ef41Sopenharmony_ci  auto maybe_script = v8::ScriptCompiler::Compile(context, &scriptSource, option);
17541cb0ef41Sopenharmony_ci
17551cb0ef41Sopenharmony_ci  if (cache) {
17561cb0ef41Sopenharmony_ci    delete cache;
17571cb0ef41Sopenharmony_ci  }
17581cb0ef41Sopenharmony_ci
17591cb0ef41Sopenharmony_ci  if (cache && cacheRejected) {
17601cb0ef41Sopenharmony_ci    *cacheRejected = cache->rejected;
17611cb0ef41Sopenharmony_ci  }
17621cb0ef41Sopenharmony_ci
17631cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, maybe_script, JSVM_GENERIC_FAILURE);
17641cb0ef41Sopenharmony_ci  v8::Local<v8::Script> compiled_script = maybe_script.ToLocalChecked();
17651cb0ef41Sopenharmony_ci  *result = reinterpret_cast<JSVM_Script>(env->NewJsvmData(compiled_script));
17661cb0ef41Sopenharmony_ci
17671cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
17681cb0ef41Sopenharmony_ci}
17691cb0ef41Sopenharmony_ci
17701cb0ef41Sopenharmony_ciclass CompileOptionResolver {
17711cb0ef41Sopenharmony_ci public:
17721cb0ef41Sopenharmony_ci  CompileOptionResolver(size_t length, JSVM_CompileOptions options[], v8::Isolate *isolate) {
17731cb0ef41Sopenharmony_ci    for (size_t i = 0; i < length; i++) {
17741cb0ef41Sopenharmony_ci      switch(options[i].id) {
17751cb0ef41Sopenharmony_ci        case JSVM_COMPILE_MODE: {
17761cb0ef41Sopenharmony_ci          v8Option = static_cast<v8::ScriptCompiler::CompileOptions>(options[i].content.num);
17771cb0ef41Sopenharmony_ci          break;
17781cb0ef41Sopenharmony_ci        }
17791cb0ef41Sopenharmony_ci        case JSVM_COMPILE_CODE_CACHE: {
17801cb0ef41Sopenharmony_ci          auto cache = static_cast<JSVM_CodeCache*>(options[i].content.ptr);
17811cb0ef41Sopenharmony_ci          cachedData = cache->cache ?
17821cb0ef41Sopenharmony_ci            new v8::ScriptCompiler::CachedData(cache->cache, cache->length) : nullptr;
17831cb0ef41Sopenharmony_ci          break;
17841cb0ef41Sopenharmony_ci        }
17851cb0ef41Sopenharmony_ci        case JSVM_COMPILE_SCRIPT_ORIGIN: {
17861cb0ef41Sopenharmony_ci          jsvmOrigin = static_cast<JSVM_ScriptOrigin*>(options[i].content.ptr);
17871cb0ef41Sopenharmony_ci          break;
17881cb0ef41Sopenharmony_ci        }
17891cb0ef41Sopenharmony_ci        case JSVM_COMPILE_COMPILE_PROFILE: {
17901cb0ef41Sopenharmony_ci          profile = static_cast<JSVM_CompileProfile*>(options[i].content.ptr);
17911cb0ef41Sopenharmony_ci          break;
17921cb0ef41Sopenharmony_ci        }
17931cb0ef41Sopenharmony_ci        case JSVM_COMPILE_ENABLE_SOURCE_MAP: {
17941cb0ef41Sopenharmony_ci          enableSourceMap = options[i].content.boolean;
17951cb0ef41Sopenharmony_ci          break;
17961cb0ef41Sopenharmony_ci        }
17971cb0ef41Sopenharmony_ci        default: {
17981cb0ef41Sopenharmony_ci          continue;
17991cb0ef41Sopenharmony_ci        }
18001cb0ef41Sopenharmony_ci      }
18011cb0ef41Sopenharmony_ci    }
18021cb0ef41Sopenharmony_ci    auto sourceString = jsvmOrigin ? jsvmOrigin->resourceName :
18031cb0ef41Sopenharmony_ci      "script_" + std::to_string(compileCount++);
18041cb0ef41Sopenharmony_ci    auto sourceMapPtr = jsvmOrigin && jsvmOrigin->sourceMapUrl ?
18051cb0ef41Sopenharmony_ci      jsvmOrigin->sourceMapUrl : nullptr;
18061cb0ef41Sopenharmony_ci    auto sourceMapUrl = (jsvmOrigin && jsvmOrigin->sourceMapUrl) ?
18071cb0ef41Sopenharmony_ci      v8::String::NewFromUtf8(isolate, jsvmOrigin->sourceMapUrl).ToLocalChecked().As<v8::Value>() :
18081cb0ef41Sopenharmony_ci      v8::Local<v8::Value>();
18091cb0ef41Sopenharmony_ci    auto resourceName = v8::String::NewFromUtf8(isolate, sourceString.c_str()).ToLocalChecked();
18101cb0ef41Sopenharmony_ci    v8Origin = new v8::ScriptOrigin(isolate, resourceName,
18111cb0ef41Sopenharmony_ci      jsvmOrigin ? jsvmOrigin->resourceLineOffset : 0,
18121cb0ef41Sopenharmony_ci      jsvmOrigin ? jsvmOrigin->resourceColumnOffset : 0,
18131cb0ef41Sopenharmony_ci      false, -1, sourceMapUrl);
18141cb0ef41Sopenharmony_ci    if (enableSourceMap && sourceMapPtr) {
18151cb0ef41Sopenharmony_ci      v8impl::SetFileToSourceMapMapping(jsvmOrigin->resourceName, sourceMapPtr);
18161cb0ef41Sopenharmony_ci      isolate->SetPrepareStackTraceCallback(PrepareStackTraceCallback);
18171cb0ef41Sopenharmony_ci    }
18181cb0ef41Sopenharmony_ci    if (v8Option == v8::ScriptCompiler::kConsumeCodeCache && !cachedData) {
18191cb0ef41Sopenharmony_ci      hasInvalidOption = true;
18201cb0ef41Sopenharmony_ci    }
18211cb0ef41Sopenharmony_ci  }
18221cb0ef41Sopenharmony_ci
18231cb0ef41Sopenharmony_ci  ~CompileOptionResolver() {
18241cb0ef41Sopenharmony_ci    delete v8Origin;
18251cb0ef41Sopenharmony_ci    v8Origin = nullptr;
18261cb0ef41Sopenharmony_ci  }
18271cb0ef41Sopenharmony_ci
18281cb0ef41Sopenharmony_ci  v8::ScriptCompiler::CompileOptions v8Option =
18291cb0ef41Sopenharmony_ci    v8::ScriptCompiler::kNoCompileOptions;
18301cb0ef41Sopenharmony_ci  v8::ScriptCompiler::CachedData *cachedData = nullptr;
18311cb0ef41Sopenharmony_ci  v8::ScriptOrigin *v8Origin = nullptr;
18321cb0ef41Sopenharmony_ci  JSVM_CompileProfile *profile = nullptr;
18331cb0ef41Sopenharmony_ci  JSVM_ScriptOrigin *jsvmOrigin = nullptr;
18341cb0ef41Sopenharmony_ci  bool enableSourceMap = false;
18351cb0ef41Sopenharmony_ci  static size_t compileCount;
18361cb0ef41Sopenharmony_ci  bool hasInvalidOption = false;
18371cb0ef41Sopenharmony_ci};
18381cb0ef41Sopenharmony_ci
18391cb0ef41Sopenharmony_cisize_t CompileOptionResolver::compileCount = 0;
18401cb0ef41Sopenharmony_ci
18411cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
18421cb0ef41Sopenharmony_ciOH_JSVM_CompileScriptWithOptions(JSVM_Env env,
18431cb0ef41Sopenharmony_ci                                 JSVM_Value script,
18441cb0ef41Sopenharmony_ci                                 size_t optionCount,
18451cb0ef41Sopenharmony_ci                                 JSVM_CompileOptions options[],
18461cb0ef41Sopenharmony_ci                                 JSVM_Script* result) {
18471cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
18481cb0ef41Sopenharmony_ci  CHECK_ARG(env, script);
18491cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
18501cb0ef41Sopenharmony_ci
18511cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
18521cb0ef41Sopenharmony_ci  auto *isolate = context->GetIsolate();
18531cb0ef41Sopenharmony_ci  CompileOptionResolver optionResolver(optionCount, options, isolate);
18541cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, !optionResolver.hasInvalidOption, JSVM_INVALID_ARG);
18551cb0ef41Sopenharmony_ci
18561cb0ef41Sopenharmony_ci  v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue(script);
18571cb0ef41Sopenharmony_ci
18581cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, v8_script->IsString(), JSVM_STRING_EXPECTED);
18591cb0ef41Sopenharmony_ci
18601cb0ef41Sopenharmony_ci  v8::ScriptCompiler::Source scriptSource(v8_script.As<v8::String>(),
18611cb0ef41Sopenharmony_ci    *optionResolver.v8Origin, optionResolver.cachedData);
18621cb0ef41Sopenharmony_ci  auto maybe_script = v8::ScriptCompiler::Compile(context, &scriptSource, optionResolver.v8Option);
18631cb0ef41Sopenharmony_ci
18641cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, maybe_script, JSVM_GENERIC_FAILURE);
18651cb0ef41Sopenharmony_ci  v8::Local<v8::Script> compiled_script = maybe_script.ToLocalChecked();
18661cb0ef41Sopenharmony_ci  *result = reinterpret_cast<JSVM_Script>(*compiled_script);
18671cb0ef41Sopenharmony_ci
18681cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
18691cb0ef41Sopenharmony_ci}
18701cb0ef41Sopenharmony_ci
18711cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
18721cb0ef41Sopenharmony_ciOH_JSVM_CreateCodeCache(JSVM_Env env,
18731cb0ef41Sopenharmony_ci                       JSVM_Script script,
18741cb0ef41Sopenharmony_ci                       const uint8_t** data,
18751cb0ef41Sopenharmony_ci                       size_t* length) {
18761cb0ef41Sopenharmony_ci  CHECK_ENV(env);
18771cb0ef41Sopenharmony_ci  CHECK_ARG(env, script);
18781cb0ef41Sopenharmony_ci  CHECK_ARG(env, data);
18791cb0ef41Sopenharmony_ci  CHECK_ARG(env, length);
18801cb0ef41Sopenharmony_ci  auto jsvmData = reinterpret_cast<JSVM_Data__*>(script);
18811cb0ef41Sopenharmony_ci  auto v8script = jsvmData->ToV8Local<v8::Script>(env->isolate);
18821cb0ef41Sopenharmony_ci  v8::ScriptCompiler::CachedData* cache;
18831cb0ef41Sopenharmony_ci  cache = v8::ScriptCompiler::CreateCodeCache(v8script->GetUnboundScript());
18841cb0ef41Sopenharmony_ci
18851cb0ef41Sopenharmony_ci  if (cache == nullptr) {
18861cb0ef41Sopenharmony_ci    // TODO: return error
18871cb0ef41Sopenharmony_ci    return jsvm_set_last_error(env, JSVM_GENERIC_FAILURE);
18881cb0ef41Sopenharmony_ci  }
18891cb0ef41Sopenharmony_ci
18901cb0ef41Sopenharmony_ci  *data = cache->data;
18911cb0ef41Sopenharmony_ci  *length = cache->length;
18921cb0ef41Sopenharmony_ci  cache->buffer_policy = v8::ScriptCompiler::CachedData::BufferNotOwned;
18931cb0ef41Sopenharmony_ci  delete cache;
18941cb0ef41Sopenharmony_ci  return JSVM_OK;
18951cb0ef41Sopenharmony_ci}
18961cb0ef41Sopenharmony_ci
18971cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
18981cb0ef41Sopenharmony_ciOH_JSVM_RunScript(JSVM_Env env, JSVM_Script script, JSVM_Value* result) {
18991cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
19001cb0ef41Sopenharmony_ci  CHECK_ARG(env, script);
19011cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
19021cb0ef41Sopenharmony_ci
19031cb0ef41Sopenharmony_ci  auto jsvmData = reinterpret_cast<JSVM_Data__*>(script);
19041cb0ef41Sopenharmony_ci  auto v8script = jsvmData->ToV8Local<v8::Script>(env->isolate);
19051cb0ef41Sopenharmony_ci  auto script_result = v8script->Run(env->context());
19061cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, script_result, JSVM_GENERIC_FAILURE);
19071cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(script_result.ToLocalChecked());
19081cb0ef41Sopenharmony_ci
19091cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
19101cb0ef41Sopenharmony_ci}
19111cb0ef41Sopenharmony_ci
19121cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
19131cb0ef41Sopenharmony_ciOH_JSVM_JsonParse(JSVM_Env env, JSVM_Value json_string, JSVM_Value* result) {
19141cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
19151cb0ef41Sopenharmony_ci  CHECK_ARG(env, json_string);
19161cb0ef41Sopenharmony_ci
19171cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(json_string);
19181cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsString(), JSVM_STRING_EXPECTED);
19191cb0ef41Sopenharmony_ci
19201cb0ef41Sopenharmony_ci  auto maybe = v8::JSON::Parse(env->context(), val.As<v8::String>());
19211cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, maybe,JSVM_GENERIC_FAILURE);
19221cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
19231cb0ef41Sopenharmony_ci
19241cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
19251cb0ef41Sopenharmony_ci}
19261cb0ef41Sopenharmony_ci
19271cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
19281cb0ef41Sopenharmony_ciOH_JSVM_JsonStringify(JSVM_Env env, JSVM_Value json_object, JSVM_Value* result) {
19291cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
19301cb0ef41Sopenharmony_ci  CHECK_ARG(env, json_object);
19311cb0ef41Sopenharmony_ci
19321cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(json_object);
19331cb0ef41Sopenharmony_ci
19341cb0ef41Sopenharmony_ci  auto maybe = v8::JSON::Stringify(env->context(), val);
19351cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, maybe,JSVM_GENERIC_FAILURE);
19361cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
19371cb0ef41Sopenharmony_ci
19381cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
19391cb0ef41Sopenharmony_ci}
19401cb0ef41Sopenharmony_ci
19411cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
19421cb0ef41Sopenharmony_ciOH_JSVM_CreateSnapshot(JSVM_VM vm,
19431cb0ef41Sopenharmony_ci        size_t contextCount,
19441cb0ef41Sopenharmony_ci        const JSVM_Env* contexts,
19451cb0ef41Sopenharmony_ci        const char** blobData,
19461cb0ef41Sopenharmony_ci        size_t* blobSize) {
19471cb0ef41Sopenharmony_ci  auto isolate = reinterpret_cast<v8::Isolate*>(vm);
19481cb0ef41Sopenharmony_ci  auto creator = v8impl::GetIsolateSnapshotCreator(isolate);
19491cb0ef41Sopenharmony_ci
19501cb0ef41Sopenharmony_ci  if (creator == nullptr) {
19511cb0ef41Sopenharmony_ci    // TODO: return specific error message.
19521cb0ef41Sopenharmony_ci    return JSVM_GENERIC_FAILURE;
19531cb0ef41Sopenharmony_ci  }
19541cb0ef41Sopenharmony_ci  {
19551cb0ef41Sopenharmony_ci    v8::HandleScope scope(isolate);
19561cb0ef41Sopenharmony_ci    v8::Local<v8::Context> default_context = v8::Context::New(isolate);
19571cb0ef41Sopenharmony_ci    creator->SetDefaultContext(default_context);
19581cb0ef41Sopenharmony_ci    // NOTE: The order of the added data must be consistent with the order of
19591cb0ef41Sopenharmony_ci    // getting data in v8impl::CreateIsolateData.
19601cb0ef41Sopenharmony_ci    creator->AddData(JSVM_PRIVATE_KEY(isolate, wrapper));
19611cb0ef41Sopenharmony_ci    creator->AddData(JSVM_PRIVATE_KEY(isolate, type_tag));
19621cb0ef41Sopenharmony_ci
19631cb0ef41Sopenharmony_ci    for (size_t i = 0; i < contextCount; i++) {
19641cb0ef41Sopenharmony_ci      auto ctx = contexts[i]->context();
19651cb0ef41Sopenharmony_ci      creator->AddData(ctx, ctx);
19661cb0ef41Sopenharmony_ci      creator->AddContext(ctx);
19671cb0ef41Sopenharmony_ci    }
19681cb0ef41Sopenharmony_ci  }
19691cb0ef41Sopenharmony_ci  auto blob = creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kKeep);
19701cb0ef41Sopenharmony_ci  *blobData = blob.data;
19711cb0ef41Sopenharmony_ci  *blobSize = blob.raw_size;
19721cb0ef41Sopenharmony_ci
19731cb0ef41Sopenharmony_ci  return JSVM_OK;
19741cb0ef41Sopenharmony_ci}
19751cb0ef41Sopenharmony_ci
19761cb0ef41Sopenharmony_ciJSVM_EXTERN JSVM_Status JSVM_CDECL OH_JSVM_GetVMInfo(JSVM_VMInfo* result) {
19771cb0ef41Sopenharmony_ci  result->apiVersion = 1;
19781cb0ef41Sopenharmony_ci  result->engine = "v8";
19791cb0ef41Sopenharmony_ci  result->version = V8_VERSION_STRING;
19801cb0ef41Sopenharmony_ci  result->cachedDataVersionTag = v8::ScriptCompiler::CachedDataVersionTag();
19811cb0ef41Sopenharmony_ci  return JSVM_OK;
19821cb0ef41Sopenharmony_ci}
19831cb0ef41Sopenharmony_ci
19841cb0ef41Sopenharmony_ciJSVM_EXTERN JSVM_Status JSVM_CDECL
19851cb0ef41Sopenharmony_ciOH_JSVM_MemoryPressureNotification(JSVM_Env env,
19861cb0ef41Sopenharmony_ci                                  JSVM_MemoryPressureLevel level) {
19871cb0ef41Sopenharmony_ci  CHECK_ENV(env);
19881cb0ef41Sopenharmony_ci  env->isolate->MemoryPressureNotification(v8::MemoryPressureLevel(level));
19891cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
19901cb0ef41Sopenharmony_ci}
19911cb0ef41Sopenharmony_ci
19921cb0ef41Sopenharmony_ciJSVM_EXTERN JSVM_Status JSVM_CDECL
19931cb0ef41Sopenharmony_ciOH_JSVM_GetHeapStatistics(JSVM_VM vm, JSVM_HeapStatistics* result) {
19941cb0ef41Sopenharmony_ci  auto isolate = reinterpret_cast<v8::Isolate*>(vm);
19951cb0ef41Sopenharmony_ci  v8::HeapStatistics stats;
19961cb0ef41Sopenharmony_ci  isolate->GetHeapStatistics(&stats);
19971cb0ef41Sopenharmony_ci  result->totalHeapSize = stats.total_heap_size();
19981cb0ef41Sopenharmony_ci  result->totalHeapSizeExecutable = stats.total_heap_size_executable();
19991cb0ef41Sopenharmony_ci  result->totalPhysicalSize = stats.total_physical_size();
20001cb0ef41Sopenharmony_ci  result->totalAvailableSize = stats.total_available_size();
20011cb0ef41Sopenharmony_ci  result->usedHeapSize = stats.used_heap_size();
20021cb0ef41Sopenharmony_ci  result->heapSizeLimit = stats.heap_size_limit();
20031cb0ef41Sopenharmony_ci  result->mallocedMemory = stats.malloced_memory();
20041cb0ef41Sopenharmony_ci  result->externalMemory = stats.external_memory();
20051cb0ef41Sopenharmony_ci  result->peakMallocedMemory = stats.peak_malloced_memory();
20061cb0ef41Sopenharmony_ci  result->numberOfNativeContexts = stats.number_of_native_contexts();
20071cb0ef41Sopenharmony_ci  result->numberOfDetachedContexts = stats.number_of_detached_contexts();
20081cb0ef41Sopenharmony_ci  result->totalGlobalHandlesSize = stats.total_global_handles_size();
20091cb0ef41Sopenharmony_ci  result->usedGlobalHandlesSize = stats.used_global_handles_size();
20101cb0ef41Sopenharmony_ci  return JSVM_OK;
20111cb0ef41Sopenharmony_ci}
20121cb0ef41Sopenharmony_ci
20131cb0ef41Sopenharmony_ciJSVM_EXTERN JSVM_Status JSVM_CDECL
20141cb0ef41Sopenharmony_ciOH_JSVM_StartCpuProfiler(JSVM_VM vm, JSVM_CpuProfiler* result) {
20151cb0ef41Sopenharmony_ci  auto isolate = reinterpret_cast<v8::Isolate*>(vm);
20161cb0ef41Sopenharmony_ci  auto profiler = v8::CpuProfiler::New(isolate);
20171cb0ef41Sopenharmony_ci  v8::HandleScope scope(isolate);
20181cb0ef41Sopenharmony_ci  v8::CpuProfilingOptions options;
20191cb0ef41Sopenharmony_ci  profiler->Start(v8::String::Empty(isolate), std::move(options));
20201cb0ef41Sopenharmony_ci  *result = reinterpret_cast<JSVM_CpuProfiler>(profiler);
20211cb0ef41Sopenharmony_ci  return JSVM_OK;
20221cb0ef41Sopenharmony_ci}
20231cb0ef41Sopenharmony_ci
20241cb0ef41Sopenharmony_ciJSVM_EXTERN JSVM_Status JSVM_CDECL
20251cb0ef41Sopenharmony_ciOH_JSVM_StopCpuProfiler(JSVM_VM vm, JSVM_CpuProfiler profiler,
20261cb0ef41Sopenharmony_ci                        JSVM_OutputStream stream, void* streamData) {
20271cb0ef41Sopenharmony_ci  auto isolate = reinterpret_cast<v8::Isolate*>(vm);
20281cb0ef41Sopenharmony_ci  auto v8profiler = reinterpret_cast<v8::CpuProfiler*>(profiler);
20291cb0ef41Sopenharmony_ci  v8::HandleScope scope(isolate);
20301cb0ef41Sopenharmony_ci  auto profile = v8profiler->StopProfiling(v8::String::Empty(isolate));
20311cb0ef41Sopenharmony_ci  v8impl::OutputStream os(stream, streamData);
20321cb0ef41Sopenharmony_ci  profile->Serialize(&os);
20331cb0ef41Sopenharmony_ci  return JSVM_OK;
20341cb0ef41Sopenharmony_ci}
20351cb0ef41Sopenharmony_ci
20361cb0ef41Sopenharmony_ciJSVM_EXTERN JSVM_Status JSVM_CDECL
20371cb0ef41Sopenharmony_ciOH_JSVM_TakeHeapSnapshot(JSVM_VM vm,
20381cb0ef41Sopenharmony_ci                         JSVM_OutputStream stream, void* streamData) {
20391cb0ef41Sopenharmony_ci  auto isolate = reinterpret_cast<v8::Isolate*>(vm);
20401cb0ef41Sopenharmony_ci  auto profiler = isolate->GetHeapProfiler();
20411cb0ef41Sopenharmony_ci  auto snapshot = profiler->TakeHeapSnapshot();
20421cb0ef41Sopenharmony_ci  v8impl::OutputStream os(stream, streamData);
20431cb0ef41Sopenharmony_ci  snapshot->Serialize(&os);
20441cb0ef41Sopenharmony_ci  return JSVM_OK;
20451cb0ef41Sopenharmony_ci}
20461cb0ef41Sopenharmony_ci
20471cb0ef41Sopenharmony_ciJSVM_EXTERN JSVM_Status JSVM_CDECL
20481cb0ef41Sopenharmony_ciOH_JSVM_OpenInspector(JSVM_Env env, const char* host, uint16_t port) {
20491cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
20501cb0ef41Sopenharmony_ci
20511cb0ef41Sopenharmony_ci  std::string inspectorPath;
20521cb0ef41Sopenharmony_ci  std::string hostName(host);
20531cb0ef41Sopenharmony_ci  auto hostPort =
20541cb0ef41Sopenharmony_ci      std::make_shared<node::ExclusiveAccess<node::HostPort>>(hostName, port);
20551cb0ef41Sopenharmony_ci  env->inspector_agent()->Start(inspectorPath, hostPort, true, false);
20561cb0ef41Sopenharmony_ci
20571cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
20581cb0ef41Sopenharmony_ci}
20591cb0ef41Sopenharmony_ci
20601cb0ef41Sopenharmony_ciJSVM_EXTERN JSVM_Status JSVM_CDECL OH_JSVM_CloseInspector(JSVM_Env env) {
20611cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
20621cb0ef41Sopenharmony_ci  auto agent = env->inspector_agent();
20631cb0ef41Sopenharmony_ci  if (!agent->IsActive()) {
20641cb0ef41Sopenharmony_ci    return JSVM_GENERIC_FAILURE;
20651cb0ef41Sopenharmony_ci  }
20661cb0ef41Sopenharmony_ci  agent->Stop();
20671cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
20681cb0ef41Sopenharmony_ci}
20691cb0ef41Sopenharmony_ci
20701cb0ef41Sopenharmony_ciJSVM_EXTERN JSVM_Status JSVM_CDECL OH_JSVM_WaitForDebugger(JSVM_Env env, bool breakNextLine) {
20711cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
20721cb0ef41Sopenharmony_ci  auto agent = env->inspector_agent();
20731cb0ef41Sopenharmony_ci  if (!agent->IsActive()) {
20741cb0ef41Sopenharmony_ci    return JSVM_GENERIC_FAILURE;
20751cb0ef41Sopenharmony_ci  }
20761cb0ef41Sopenharmony_ci
20771cb0ef41Sopenharmony_ci  agent->WaitForConnect();
20781cb0ef41Sopenharmony_ci  if (breakNextLine) {
20791cb0ef41Sopenharmony_ci    agent->PauseOnNextJavascriptStatement("Break on debugger attached");
20801cb0ef41Sopenharmony_ci  }
20811cb0ef41Sopenharmony_ci
20821cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
20831cb0ef41Sopenharmony_ci}
20841cb0ef41Sopenharmony_ci
20851cb0ef41Sopenharmony_ciJSVM_EXTERN JSVM_Status JSVM_CDECL OH_JSVM_PumpMessageLoop(JSVM_VM vm, bool* result) {
20861cb0ef41Sopenharmony_ci  auto isolate = reinterpret_cast<v8::Isolate*>(vm);
20871cb0ef41Sopenharmony_ci  *result = v8::platform::PumpMessageLoop(v8impl::g_platform.get(), isolate);
20881cb0ef41Sopenharmony_ci  return JSVM_OK;
20891cb0ef41Sopenharmony_ci}
20901cb0ef41Sopenharmony_ci
20911cb0ef41Sopenharmony_ciJSVM_EXTERN JSVM_Status JSVM_CDECL OH_JSVM_PerformMicrotaskCheckpoint(JSVM_VM vm) {
20921cb0ef41Sopenharmony_ci  auto isolate = reinterpret_cast<v8::Isolate*>(vm);
20931cb0ef41Sopenharmony_ci  isolate->PerformMicrotaskCheckpoint();
20941cb0ef41Sopenharmony_ci  return JSVM_OK;
20951cb0ef41Sopenharmony_ci}
20961cb0ef41Sopenharmony_ci
20971cb0ef41Sopenharmony_ci// Warning: Keep in-sync with JSVM_Status enum
20981cb0ef41Sopenharmony_cistatic const char* error_messages[] = {
20991cb0ef41Sopenharmony_ci    nullptr,
21001cb0ef41Sopenharmony_ci    "Invalid argument",
21011cb0ef41Sopenharmony_ci    "An object was expected",
21021cb0ef41Sopenharmony_ci    "A string was expected",
21031cb0ef41Sopenharmony_ci    "A string or symbol was expected",
21041cb0ef41Sopenharmony_ci    "A function was expected",
21051cb0ef41Sopenharmony_ci    "A number was expected",
21061cb0ef41Sopenharmony_ci    "A boolean was expected",
21071cb0ef41Sopenharmony_ci    "An array was expected",
21081cb0ef41Sopenharmony_ci    "Unknown failure",
21091cb0ef41Sopenharmony_ci    "An exception is pending",
21101cb0ef41Sopenharmony_ci    "The async work item was cancelled",
21111cb0ef41Sopenharmony_ci    "OH_JSVM_EscapeHandle already called on scope",
21121cb0ef41Sopenharmony_ci    "Invalid handle scope usage",
21131cb0ef41Sopenharmony_ci    "Invalid callback scope usage",
21141cb0ef41Sopenharmony_ci    "Thread-safe function queue is full",
21151cb0ef41Sopenharmony_ci    "Thread-safe function handle is closing",
21161cb0ef41Sopenharmony_ci    "A bigint was expected",
21171cb0ef41Sopenharmony_ci    "A date was expected",
21181cb0ef41Sopenharmony_ci    "An arraybuffer was expected",
21191cb0ef41Sopenharmony_ci    "A detachable arraybuffer was expected",
21201cb0ef41Sopenharmony_ci    "Main thread would deadlock",
21211cb0ef41Sopenharmony_ci    "External buffers are not allowed",
21221cb0ef41Sopenharmony_ci    "Cannot run JavaScript",
21231cb0ef41Sopenharmony_ci};
21241cb0ef41Sopenharmony_ci
21251cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetLastErrorInfo(
21261cb0ef41Sopenharmony_ci    JSVM_Env env, const JSVM_ExtendedErrorInfo** result) {
21271cb0ef41Sopenharmony_ci  CHECK_ENV(env);
21281cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
21291cb0ef41Sopenharmony_ci
21301cb0ef41Sopenharmony_ci  // The value of the constant below must be updated to reference the last
21311cb0ef41Sopenharmony_ci  // message in the `JSVM_Status` enum each time a new error message is added.
21321cb0ef41Sopenharmony_ci  // We don't have a jsvm_status_last as this would result in an ABI
21331cb0ef41Sopenharmony_ci  // change each time a message was added.
21341cb0ef41Sopenharmony_ci  const int last_status = JSVM_CANNOT_RUN_JS;
21351cb0ef41Sopenharmony_ci
21361cb0ef41Sopenharmony_ci  static_assert(JSVM_ARRAYSIZE(error_messages) == last_status + 1,
21371cb0ef41Sopenharmony_ci                "Count of error messages must match count of error values");
21381cb0ef41Sopenharmony_ci  CHECK_LE(env->last_error.errorCode, last_status);
21391cb0ef41Sopenharmony_ci  // Wait until someone requests the last error information to fetch the error
21401cb0ef41Sopenharmony_ci  // message string
21411cb0ef41Sopenharmony_ci  env->last_error.errorMessage = error_messages[env->last_error.errorCode];
21421cb0ef41Sopenharmony_ci
21431cb0ef41Sopenharmony_ci  if (env->last_error.errorCode == JSVM_OK) {
21441cb0ef41Sopenharmony_ci    jsvm_clear_last_error(env);
21451cb0ef41Sopenharmony_ci  }
21461cb0ef41Sopenharmony_ci  *result = &(env->last_error);
21471cb0ef41Sopenharmony_ci  return JSVM_OK;
21481cb0ef41Sopenharmony_ci}
21491cb0ef41Sopenharmony_ci
21501cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateFunction(JSVM_Env env,
21511cb0ef41Sopenharmony_ci                                            const char* utf8name,
21521cb0ef41Sopenharmony_ci                                            size_t length,
21531cb0ef41Sopenharmony_ci                                            JSVM_Callback cb,
21541cb0ef41Sopenharmony_ci                                            JSVM_Value* result) {
21551cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
21561cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
21571cb0ef41Sopenharmony_ci  CHECK_ARG(env, cb);
21581cb0ef41Sopenharmony_ci
21591cb0ef41Sopenharmony_ci  v8::Local<v8::Function> return_value;
21601cb0ef41Sopenharmony_ci  v8::EscapableHandleScope scope(env->isolate);
21611cb0ef41Sopenharmony_ci  v8::Local<v8::Function> fn;
21621cb0ef41Sopenharmony_ci  STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
21631cb0ef41Sopenharmony_ci      env, cb, &fn));
21641cb0ef41Sopenharmony_ci  return_value = scope.Escape(fn);
21651cb0ef41Sopenharmony_ci
21661cb0ef41Sopenharmony_ci  if (utf8name != nullptr) {
21671cb0ef41Sopenharmony_ci    v8::Local<v8::String> name_string;
21681cb0ef41Sopenharmony_ci    CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
21691cb0ef41Sopenharmony_ci    return_value->SetName(name_string);
21701cb0ef41Sopenharmony_ci  }
21711cb0ef41Sopenharmony_ci
21721cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(return_value);
21731cb0ef41Sopenharmony_ci
21741cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
21751cb0ef41Sopenharmony_ci}
21761cb0ef41Sopenharmony_ci
21771cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateFunctionWithScript(JSVM_Env env,
21781cb0ef41Sopenharmony_ci                                                        const char* funcName,
21791cb0ef41Sopenharmony_ci                                                        size_t length,
21801cb0ef41Sopenharmony_ci                                                        size_t argc,
21811cb0ef41Sopenharmony_ci                                                        const JSVM_Value* argv,
21821cb0ef41Sopenharmony_ci                                                        JSVM_Value script,
21831cb0ef41Sopenharmony_ci                                                        JSVM_Value* result) {
21841cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
21851cb0ef41Sopenharmony_ci  CHECK_ARG(env, script);
21861cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
21871cb0ef41Sopenharmony_ci  if (argc > 0) {
21881cb0ef41Sopenharmony_ci    CHECK_ARG(env, argv);
21891cb0ef41Sopenharmony_ci    for (auto i = 0; i < argc; i++) {
21901cb0ef41Sopenharmony_ci      RETURN_STATUS_IF_FALSE(env, v8impl::V8LocalValueFromJsValue(argv[i])->IsString(),
21911cb0ef41Sopenharmony_ci          JSVM_STRING_EXPECTED);
21921cb0ef41Sopenharmony_ci    }
21931cb0ef41Sopenharmony_ci  }
21941cb0ef41Sopenharmony_ci
21951cb0ef41Sopenharmony_ci  v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue(script);
21961cb0ef41Sopenharmony_ci
21971cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, v8_script->IsString(), JSVM_STRING_EXPECTED);
21981cb0ef41Sopenharmony_ci
21991cb0ef41Sopenharmony_ci  v8::ScriptCompiler::Source scriptSource(v8_script.As<v8::String>());
22001cb0ef41Sopenharmony_ci
22011cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
22021cb0ef41Sopenharmony_ci
22031cb0ef41Sopenharmony_ci  v8::MaybeLocal<v8::Function> maybe_fun =
22041cb0ef41Sopenharmony_ci    v8::ScriptCompiler::CompileFunction(context, &scriptSource, argc,
22051cb0ef41Sopenharmony_ci    reinterpret_cast<v8::Local<v8::String>*>(const_cast<JSVM_Value*>(argv)));
22061cb0ef41Sopenharmony_ci
22071cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, maybe_fun, JSVM_GENERIC_FAILURE);
22081cb0ef41Sopenharmony_ci
22091cb0ef41Sopenharmony_ci  v8::Local<v8::Function> func = maybe_fun.ToLocalChecked();
22101cb0ef41Sopenharmony_ci
22111cb0ef41Sopenharmony_ci  if (funcName != nullptr) {
22121cb0ef41Sopenharmony_ci    v8::Local<v8::String> funcNameString;
22131cb0ef41Sopenharmony_ci    CHECK_NEW_FROM_UTF8_LEN(env, funcNameString, funcName, length);
22141cb0ef41Sopenharmony_ci    func->SetName(funcNameString);
22151cb0ef41Sopenharmony_ci  }
22161cb0ef41Sopenharmony_ci
22171cb0ef41Sopenharmony_ci  *result =
22181cb0ef41Sopenharmony_ci    v8impl::JsValueFromV8LocalValue(func);
22191cb0ef41Sopenharmony_ci
22201cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
22211cb0ef41Sopenharmony_ci}
22221cb0ef41Sopenharmony_ci
22231cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
22241cb0ef41Sopenharmony_ciOH_JSVM_DefineClass(JSVM_Env env,
22251cb0ef41Sopenharmony_ci                  const char* utf8name,
22261cb0ef41Sopenharmony_ci                  size_t length,
22271cb0ef41Sopenharmony_ci                  JSVM_Callback constructor,
22281cb0ef41Sopenharmony_ci                  size_t propertyCount,
22291cb0ef41Sopenharmony_ci                  const JSVM_PropertyDescriptor* properties,
22301cb0ef41Sopenharmony_ci                  JSVM_Value* result) {
22311cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
22321cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
22331cb0ef41Sopenharmony_ci  CHECK_ARG(env, constructor);
22341cb0ef41Sopenharmony_ci
22351cb0ef41Sopenharmony_ci  if (propertyCount > 0) {
22361cb0ef41Sopenharmony_ci    CHECK_ARG(env, properties);
22371cb0ef41Sopenharmony_ci  }
22381cb0ef41Sopenharmony_ci
22391cb0ef41Sopenharmony_ci  v8::Isolate* isolate = env->isolate;
22401cb0ef41Sopenharmony_ci
22411cb0ef41Sopenharmony_ci  v8::EscapableHandleScope scope(isolate);
22421cb0ef41Sopenharmony_ci  v8::Local<v8::FunctionTemplate> tpl;
22431cb0ef41Sopenharmony_ci  STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
22441cb0ef41Sopenharmony_ci      env, constructor, &tpl));
22451cb0ef41Sopenharmony_ci
22461cb0ef41Sopenharmony_ci  v8::Local<v8::String> name_string;
22471cb0ef41Sopenharmony_ci  CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
22481cb0ef41Sopenharmony_ci  tpl->SetClassName(name_string);
22491cb0ef41Sopenharmony_ci
22501cb0ef41Sopenharmony_ci  size_t static_property_count = 0;
22511cb0ef41Sopenharmony_ci  for (size_t i = 0; i < propertyCount; i++) {
22521cb0ef41Sopenharmony_ci    const JSVM_PropertyDescriptor* p = properties + i;
22531cb0ef41Sopenharmony_ci
22541cb0ef41Sopenharmony_ci    if ((p->attributes & JSVM_STATIC) != 0) {
22551cb0ef41Sopenharmony_ci      // Static properties are handled separately below.
22561cb0ef41Sopenharmony_ci      static_property_count++;
22571cb0ef41Sopenharmony_ci      continue;
22581cb0ef41Sopenharmony_ci    }
22591cb0ef41Sopenharmony_ci
22601cb0ef41Sopenharmony_ci    v8::Local<v8::Name> property_name;
22611cb0ef41Sopenharmony_ci    STATUS_CALL(v8impl::V8NameFromPropertyDescriptor(env, p, &property_name));
22621cb0ef41Sopenharmony_ci
22631cb0ef41Sopenharmony_ci    v8::PropertyAttribute attributes =
22641cb0ef41Sopenharmony_ci        v8impl::V8PropertyAttributesFromDescriptor(p);
22651cb0ef41Sopenharmony_ci
22661cb0ef41Sopenharmony_ci    // This code is similar to that in OH_JSVM_DefineProperties(); the
22671cb0ef41Sopenharmony_ci    // difference is it applies to a template instead of an object,
22681cb0ef41Sopenharmony_ci    // and preferred PropertyAttribute for lack of PropertyDescriptor
22691cb0ef41Sopenharmony_ci    // support on ObjectTemplate.
22701cb0ef41Sopenharmony_ci    if (p->getter != nullptr || p->setter != nullptr) {
22711cb0ef41Sopenharmony_ci      v8::Local<v8::FunctionTemplate> getter_tpl;
22721cb0ef41Sopenharmony_ci      v8::Local<v8::FunctionTemplate> setter_tpl;
22731cb0ef41Sopenharmony_ci      if (p->getter != nullptr) {
22741cb0ef41Sopenharmony_ci        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
22751cb0ef41Sopenharmony_ci            env, p->getter, &getter_tpl));
22761cb0ef41Sopenharmony_ci      }
22771cb0ef41Sopenharmony_ci      if (p->setter != nullptr) {
22781cb0ef41Sopenharmony_ci        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
22791cb0ef41Sopenharmony_ci            env, p->setter, &setter_tpl));
22801cb0ef41Sopenharmony_ci      }
22811cb0ef41Sopenharmony_ci
22821cb0ef41Sopenharmony_ci      tpl->PrototypeTemplate()->SetAccessorProperty(property_name,
22831cb0ef41Sopenharmony_ci                                                    getter_tpl,
22841cb0ef41Sopenharmony_ci                                                    setter_tpl,
22851cb0ef41Sopenharmony_ci                                                    attributes,
22861cb0ef41Sopenharmony_ci                                                    v8::AccessControl::DEFAULT);
22871cb0ef41Sopenharmony_ci    } else if (p->method != nullptr) {
22881cb0ef41Sopenharmony_ci      v8::Local<v8::FunctionTemplate> t;
22891cb0ef41Sopenharmony_ci      if (p->attributes & JSVM_NO_RECEIVER_CHECK) {
22901cb0ef41Sopenharmony_ci        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
22911cb0ef41Sopenharmony_ci            env, p->method, &t));
22921cb0ef41Sopenharmony_ci      } else {
22931cb0ef41Sopenharmony_ci        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
22941cb0ef41Sopenharmony_ci            env, p->method, &t, v8::Signature::New(isolate, tpl)));
22951cb0ef41Sopenharmony_ci      }
22961cb0ef41Sopenharmony_ci
22971cb0ef41Sopenharmony_ci      tpl->PrototypeTemplate()->Set(property_name, t, attributes);
22981cb0ef41Sopenharmony_ci    } else {
22991cb0ef41Sopenharmony_ci      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
23001cb0ef41Sopenharmony_ci      tpl->PrototypeTemplate()->Set(property_name, value, attributes);
23011cb0ef41Sopenharmony_ci    }
23021cb0ef41Sopenharmony_ci  }
23031cb0ef41Sopenharmony_ci
23041cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
23051cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(
23061cb0ef41Sopenharmony_ci      scope.Escape(tpl->GetFunction(context).ToLocalChecked()));
23071cb0ef41Sopenharmony_ci
23081cb0ef41Sopenharmony_ci  if (static_property_count > 0) {
23091cb0ef41Sopenharmony_ci    std::vector<JSVM_PropertyDescriptor> static_descriptors;
23101cb0ef41Sopenharmony_ci    static_descriptors.reserve(static_property_count);
23111cb0ef41Sopenharmony_ci
23121cb0ef41Sopenharmony_ci    for (size_t i = 0; i < propertyCount; i++) {
23131cb0ef41Sopenharmony_ci      const JSVM_PropertyDescriptor* p = properties + i;
23141cb0ef41Sopenharmony_ci      if ((p->attributes & JSVM_STATIC) != 0) {
23151cb0ef41Sopenharmony_ci        static_descriptors.push_back(*p);
23161cb0ef41Sopenharmony_ci      }
23171cb0ef41Sopenharmony_ci    }
23181cb0ef41Sopenharmony_ci
23191cb0ef41Sopenharmony_ci    STATUS_CALL(OH_JSVM_DefineProperties(
23201cb0ef41Sopenharmony_ci        env, *result, static_descriptors.size(), static_descriptors.data()));
23211cb0ef41Sopenharmony_ci  }
23221cb0ef41Sopenharmony_ci
23231cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
23241cb0ef41Sopenharmony_ci}
23251cb0ef41Sopenharmony_ci
23261cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetPropertyNames(JSVM_Env env,
23271cb0ef41Sopenharmony_ci                                               JSVM_Value object,
23281cb0ef41Sopenharmony_ci                                               JSVM_Value* result) {
23291cb0ef41Sopenharmony_ci  return OH_JSVM_GetAllPropertyNames(
23301cb0ef41Sopenharmony_ci      env,
23311cb0ef41Sopenharmony_ci      object,
23321cb0ef41Sopenharmony_ci      JSVM_KEY_INCLUDE_PROTOTYPES,
23331cb0ef41Sopenharmony_ci      static_cast<JSVM_KeyFilter>(JSVM_KEY_ENUMERABLE | JSVM_KEY_SKIP_SYMBOLS),
23341cb0ef41Sopenharmony_ci      JSVM_KEY_NUMBERS_TO_STRINGS,
23351cb0ef41Sopenharmony_ci      result);
23361cb0ef41Sopenharmony_ci}
23371cb0ef41Sopenharmony_ci
23381cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
23391cb0ef41Sopenharmony_ciOH_JSVM_GetAllPropertyNames(JSVM_Env env,
23401cb0ef41Sopenharmony_ci                            JSVM_Value object,
23411cb0ef41Sopenharmony_ci                            JSVM_KeyCollectionMode keyMode,
23421cb0ef41Sopenharmony_ci                            JSVM_KeyFilter keyFilter,
23431cb0ef41Sopenharmony_ci                            JSVM_KeyConversion keyConversion,
23441cb0ef41Sopenharmony_ci                            JSVM_Value* result) {
23451cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
23461cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
23471cb0ef41Sopenharmony_ci
23481cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
23491cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
23501cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
23511cb0ef41Sopenharmony_ci
23521cb0ef41Sopenharmony_ci  v8::PropertyFilter filter = v8::PropertyFilter::ALL_PROPERTIES;
23531cb0ef41Sopenharmony_ci  if (keyFilter & JSVM_KEY_WRITABLE) {
23541cb0ef41Sopenharmony_ci    filter = static_cast<v8::PropertyFilter>(filter |
23551cb0ef41Sopenharmony_ci                                             v8::PropertyFilter::ONLY_WRITABLE);
23561cb0ef41Sopenharmony_ci  }
23571cb0ef41Sopenharmony_ci  if (keyFilter & JSVM_KEY_ENUMERABLE) {
23581cb0ef41Sopenharmony_ci    filter = static_cast<v8::PropertyFilter>(
23591cb0ef41Sopenharmony_ci        filter | v8::PropertyFilter::ONLY_ENUMERABLE);
23601cb0ef41Sopenharmony_ci  }
23611cb0ef41Sopenharmony_ci  if (keyFilter & JSVM_KEY_CONFIGURABLE) {
23621cb0ef41Sopenharmony_ci    filter = static_cast<v8::PropertyFilter>(
23631cb0ef41Sopenharmony_ci        filter | v8::PropertyFilter::ONLY_CONFIGURABLE);
23641cb0ef41Sopenharmony_ci  }
23651cb0ef41Sopenharmony_ci  if (keyFilter & JSVM_KEY_SKIP_STRINGS) {
23661cb0ef41Sopenharmony_ci    filter = static_cast<v8::PropertyFilter>(filter |
23671cb0ef41Sopenharmony_ci                                             v8::PropertyFilter::SKIP_STRINGS);
23681cb0ef41Sopenharmony_ci  }
23691cb0ef41Sopenharmony_ci  if (keyFilter & JSVM_KEY_SKIP_SYMBOLS) {
23701cb0ef41Sopenharmony_ci    filter = static_cast<v8::PropertyFilter>(filter |
23711cb0ef41Sopenharmony_ci                                             v8::PropertyFilter::SKIP_SYMBOLS);
23721cb0ef41Sopenharmony_ci  }
23731cb0ef41Sopenharmony_ci  v8::KeyCollectionMode collection_mode;
23741cb0ef41Sopenharmony_ci  v8::KeyConversionMode conversion_mode;
23751cb0ef41Sopenharmony_ci
23761cb0ef41Sopenharmony_ci  switch (keyMode) {
23771cb0ef41Sopenharmony_ci    case JSVM_KEY_INCLUDE_PROTOTYPES:
23781cb0ef41Sopenharmony_ci      collection_mode = v8::KeyCollectionMode::kIncludePrototypes;
23791cb0ef41Sopenharmony_ci      break;
23801cb0ef41Sopenharmony_ci    case JSVM_KEY_OWN_ONLY:
23811cb0ef41Sopenharmony_ci      collection_mode = v8::KeyCollectionMode::kOwnOnly;
23821cb0ef41Sopenharmony_ci      break;
23831cb0ef41Sopenharmony_ci    default:
23841cb0ef41Sopenharmony_ci      return jsvm_set_last_error(env, JSVM_INVALID_ARG);
23851cb0ef41Sopenharmony_ci  }
23861cb0ef41Sopenharmony_ci
23871cb0ef41Sopenharmony_ci  switch (keyConversion) {
23881cb0ef41Sopenharmony_ci    case JSVM_KEY_KEEP_NUMBERS:
23891cb0ef41Sopenharmony_ci      conversion_mode = v8::KeyConversionMode::kKeepNumbers;
23901cb0ef41Sopenharmony_ci      break;
23911cb0ef41Sopenharmony_ci    case JSVM_KEY_NUMBERS_TO_STRINGS:
23921cb0ef41Sopenharmony_ci      conversion_mode = v8::KeyConversionMode::kConvertToString;
23931cb0ef41Sopenharmony_ci      break;
23941cb0ef41Sopenharmony_ci    default:
23951cb0ef41Sopenharmony_ci      return jsvm_set_last_error(env, JSVM_INVALID_ARG);
23961cb0ef41Sopenharmony_ci  }
23971cb0ef41Sopenharmony_ci
23981cb0ef41Sopenharmony_ci  v8::MaybeLocal<v8::Array> maybe_all_propertynames =
23991cb0ef41Sopenharmony_ci      obj->GetPropertyNames(context,
24001cb0ef41Sopenharmony_ci                            collection_mode,
24011cb0ef41Sopenharmony_ci                            filter,
24021cb0ef41Sopenharmony_ci                            v8::IndexFilter::kIncludeIndices,
24031cb0ef41Sopenharmony_ci                            conversion_mode);
24041cb0ef41Sopenharmony_ci
24051cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(
24061cb0ef41Sopenharmony_ci      env, maybe_all_propertynames, JSVM_GENERIC_FAILURE);
24071cb0ef41Sopenharmony_ci
24081cb0ef41Sopenharmony_ci  *result =
24091cb0ef41Sopenharmony_ci      v8impl::JsValueFromV8LocalValue(maybe_all_propertynames.ToLocalChecked());
24101cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
24111cb0ef41Sopenharmony_ci}
24121cb0ef41Sopenharmony_ci
24131cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_SetProperty(JSVM_Env env,
24141cb0ef41Sopenharmony_ci                                         JSVM_Value object,
24151cb0ef41Sopenharmony_ci                                         JSVM_Value key,
24161cb0ef41Sopenharmony_ci                                         JSVM_Value value) {
24171cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
24181cb0ef41Sopenharmony_ci  CHECK_ARG(env, key);
24191cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
24201cb0ef41Sopenharmony_ci
24211cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
24221cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
24231cb0ef41Sopenharmony_ci
24241cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
24251cb0ef41Sopenharmony_ci
24261cb0ef41Sopenharmony_ci  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
24271cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
24281cb0ef41Sopenharmony_ci
24291cb0ef41Sopenharmony_ci  v8::Maybe<bool> set_maybe = obj->Set(context, k, val);
24301cb0ef41Sopenharmony_ci
24311cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), JSVM_GENERIC_FAILURE);
24321cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
24331cb0ef41Sopenharmony_ci}
24341cb0ef41Sopenharmony_ci
24351cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_HasProperty(JSVM_Env env,
24361cb0ef41Sopenharmony_ci                                         JSVM_Value object,
24371cb0ef41Sopenharmony_ci                                         JSVM_Value key,
24381cb0ef41Sopenharmony_ci                                         bool* result) {
24391cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
24401cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
24411cb0ef41Sopenharmony_ci  CHECK_ARG(env, key);
24421cb0ef41Sopenharmony_ci
24431cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
24441cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
24451cb0ef41Sopenharmony_ci
24461cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
24471cb0ef41Sopenharmony_ci
24481cb0ef41Sopenharmony_ci  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
24491cb0ef41Sopenharmony_ci  v8::Maybe<bool> has_maybe = obj->Has(context, k);
24501cb0ef41Sopenharmony_ci
24511cb0ef41Sopenharmony_ci  CHECK_MAYBE_NOTHING(env, has_maybe, JSVM_GENERIC_FAILURE);
24521cb0ef41Sopenharmony_ci
24531cb0ef41Sopenharmony_ci  *result = has_maybe.FromMaybe(false);
24541cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
24551cb0ef41Sopenharmony_ci}
24561cb0ef41Sopenharmony_ci
24571cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetProperty(JSVM_Env env,
24581cb0ef41Sopenharmony_ci                                         JSVM_Value object,
24591cb0ef41Sopenharmony_ci                                         JSVM_Value key,
24601cb0ef41Sopenharmony_ci                                         JSVM_Value* result) {
24611cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
24621cb0ef41Sopenharmony_ci  CHECK_ARG(env, key);
24631cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
24641cb0ef41Sopenharmony_ci
24651cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
24661cb0ef41Sopenharmony_ci  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
24671cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
24681cb0ef41Sopenharmony_ci
24691cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
24701cb0ef41Sopenharmony_ci
24711cb0ef41Sopenharmony_ci  auto get_maybe = obj->Get(context, k);
24721cb0ef41Sopenharmony_ci
24731cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, get_maybe, JSVM_GENERIC_FAILURE);
24741cb0ef41Sopenharmony_ci
24751cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
24761cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(val);
24771cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
24781cb0ef41Sopenharmony_ci}
24791cb0ef41Sopenharmony_ci
24801cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_DeleteProperty(JSVM_Env env,
24811cb0ef41Sopenharmony_ci                                            JSVM_Value object,
24821cb0ef41Sopenharmony_ci                                            JSVM_Value key,
24831cb0ef41Sopenharmony_ci                                            bool* result) {
24841cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
24851cb0ef41Sopenharmony_ci  CHECK_ARG(env, key);
24861cb0ef41Sopenharmony_ci
24871cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
24881cb0ef41Sopenharmony_ci  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
24891cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
24901cb0ef41Sopenharmony_ci
24911cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
24921cb0ef41Sopenharmony_ci  v8::Maybe<bool> delete_maybe = obj->Delete(context, k);
24931cb0ef41Sopenharmony_ci  CHECK_MAYBE_NOTHING(env, delete_maybe, JSVM_GENERIC_FAILURE);
24941cb0ef41Sopenharmony_ci
24951cb0ef41Sopenharmony_ci  if (result != nullptr) *result = delete_maybe.FromMaybe(false);
24961cb0ef41Sopenharmony_ci
24971cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
24981cb0ef41Sopenharmony_ci}
24991cb0ef41Sopenharmony_ci
25001cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_HasOwnProperty(JSVM_Env env,
25011cb0ef41Sopenharmony_ci                                             JSVM_Value object,
25021cb0ef41Sopenharmony_ci                                             JSVM_Value key,
25031cb0ef41Sopenharmony_ci                                             bool* result) {
25041cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
25051cb0ef41Sopenharmony_ci  CHECK_ARG(env, key);
25061cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
25071cb0ef41Sopenharmony_ci
25081cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
25091cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
25101cb0ef41Sopenharmony_ci
25111cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
25121cb0ef41Sopenharmony_ci  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
25131cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, k->IsName(), JSVM_NAME_EXPECTED);
25141cb0ef41Sopenharmony_ci  v8::Maybe<bool> has_maybe = obj->HasOwnProperty(context, k.As<v8::Name>());
25151cb0ef41Sopenharmony_ci  CHECK_MAYBE_NOTHING(env, has_maybe, JSVM_GENERIC_FAILURE);
25161cb0ef41Sopenharmony_ci  *result = has_maybe.FromMaybe(false);
25171cb0ef41Sopenharmony_ci
25181cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
25191cb0ef41Sopenharmony_ci}
25201cb0ef41Sopenharmony_ci
25211cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_SetNamedProperty(JSVM_Env env,
25221cb0ef41Sopenharmony_ci                                               JSVM_Value object,
25231cb0ef41Sopenharmony_ci                                               const char* utf8name,
25241cb0ef41Sopenharmony_ci                                               JSVM_Value value) {
25251cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
25261cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
25271cb0ef41Sopenharmony_ci
25281cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
25291cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
25301cb0ef41Sopenharmony_ci
25311cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
25321cb0ef41Sopenharmony_ci
25331cb0ef41Sopenharmony_ci  v8::Local<v8::Name> key;
25341cb0ef41Sopenharmony_ci  CHECK_NEW_FROM_UTF8(env, key, utf8name);
25351cb0ef41Sopenharmony_ci
25361cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
25371cb0ef41Sopenharmony_ci
25381cb0ef41Sopenharmony_ci  v8::Maybe<bool> set_maybe = obj->Set(context, key, val);
25391cb0ef41Sopenharmony_ci
25401cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), JSVM_GENERIC_FAILURE);
25411cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
25421cb0ef41Sopenharmony_ci}
25431cb0ef41Sopenharmony_ci
25441cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_HasNamedProperty(JSVM_Env env,
25451cb0ef41Sopenharmony_ci                                               JSVM_Value object,
25461cb0ef41Sopenharmony_ci                                               const char* utf8name,
25471cb0ef41Sopenharmony_ci                                               bool* result) {
25481cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
25491cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
25501cb0ef41Sopenharmony_ci
25511cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
25521cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
25531cb0ef41Sopenharmony_ci
25541cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
25551cb0ef41Sopenharmony_ci
25561cb0ef41Sopenharmony_ci  v8::Local<v8::Name> key;
25571cb0ef41Sopenharmony_ci  CHECK_NEW_FROM_UTF8(env, key, utf8name);
25581cb0ef41Sopenharmony_ci
25591cb0ef41Sopenharmony_ci  v8::Maybe<bool> has_maybe = obj->Has(context, key);
25601cb0ef41Sopenharmony_ci
25611cb0ef41Sopenharmony_ci  CHECK_MAYBE_NOTHING(env, has_maybe, JSVM_GENERIC_FAILURE);
25621cb0ef41Sopenharmony_ci
25631cb0ef41Sopenharmony_ci  *result = has_maybe.FromMaybe(false);
25641cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
25651cb0ef41Sopenharmony_ci}
25661cb0ef41Sopenharmony_ci
25671cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetNamedProperty(JSVM_Env env,
25681cb0ef41Sopenharmony_ci                                               JSVM_Value object,
25691cb0ef41Sopenharmony_ci                                               const char* utf8name,
25701cb0ef41Sopenharmony_ci                                               JSVM_Value* result) {
25711cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
25721cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
25731cb0ef41Sopenharmony_ci
25741cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
25751cb0ef41Sopenharmony_ci
25761cb0ef41Sopenharmony_ci  v8::Local<v8::Name> key;
25771cb0ef41Sopenharmony_ci  CHECK_NEW_FROM_UTF8(env, key, utf8name);
25781cb0ef41Sopenharmony_ci
25791cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
25801cb0ef41Sopenharmony_ci
25811cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
25821cb0ef41Sopenharmony_ci
25831cb0ef41Sopenharmony_ci  auto get_maybe = obj->Get(context, key);
25841cb0ef41Sopenharmony_ci
25851cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, get_maybe, JSVM_GENERIC_FAILURE);
25861cb0ef41Sopenharmony_ci
25871cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
25881cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(val);
25891cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
25901cb0ef41Sopenharmony_ci}
25911cb0ef41Sopenharmony_ci
25921cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_SetElement(JSVM_Env env,
25931cb0ef41Sopenharmony_ci                                        JSVM_Value object,
25941cb0ef41Sopenharmony_ci                                        uint32_t index,
25951cb0ef41Sopenharmony_ci                                        JSVM_Value value) {
25961cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
25971cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
25981cb0ef41Sopenharmony_ci
25991cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
26001cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
26011cb0ef41Sopenharmony_ci
26021cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
26031cb0ef41Sopenharmony_ci
26041cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
26051cb0ef41Sopenharmony_ci  auto set_maybe = obj->Set(context, index, val);
26061cb0ef41Sopenharmony_ci
26071cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), JSVM_GENERIC_FAILURE);
26081cb0ef41Sopenharmony_ci
26091cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
26101cb0ef41Sopenharmony_ci}
26111cb0ef41Sopenharmony_ci
26121cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_HasElement(JSVM_Env env,
26131cb0ef41Sopenharmony_ci                                        JSVM_Value object,
26141cb0ef41Sopenharmony_ci                                        uint32_t index,
26151cb0ef41Sopenharmony_ci                                        bool* result) {
26161cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
26171cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
26181cb0ef41Sopenharmony_ci
26191cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
26201cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
26211cb0ef41Sopenharmony_ci
26221cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
26231cb0ef41Sopenharmony_ci
26241cb0ef41Sopenharmony_ci  v8::Maybe<bool> has_maybe = obj->Has(context, index);
26251cb0ef41Sopenharmony_ci
26261cb0ef41Sopenharmony_ci  CHECK_MAYBE_NOTHING(env, has_maybe, JSVM_GENERIC_FAILURE);
26271cb0ef41Sopenharmony_ci
26281cb0ef41Sopenharmony_ci  *result = has_maybe.FromMaybe(false);
26291cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
26301cb0ef41Sopenharmony_ci}
26311cb0ef41Sopenharmony_ci
26321cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetElement(JSVM_Env env,
26331cb0ef41Sopenharmony_ci                                        JSVM_Value object,
26341cb0ef41Sopenharmony_ci                                        uint32_t index,
26351cb0ef41Sopenharmony_ci                                        JSVM_Value* result) {
26361cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
26371cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
26381cb0ef41Sopenharmony_ci
26391cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
26401cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
26411cb0ef41Sopenharmony_ci
26421cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
26431cb0ef41Sopenharmony_ci
26441cb0ef41Sopenharmony_ci  auto get_maybe = obj->Get(context, index);
26451cb0ef41Sopenharmony_ci
26461cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, get_maybe, JSVM_GENERIC_FAILURE);
26471cb0ef41Sopenharmony_ci
26481cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(get_maybe.ToLocalChecked());
26491cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
26501cb0ef41Sopenharmony_ci}
26511cb0ef41Sopenharmony_ci
26521cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_DeleteElement(JSVM_Env env,
26531cb0ef41Sopenharmony_ci                                           JSVM_Value object,
26541cb0ef41Sopenharmony_ci                                           uint32_t index,
26551cb0ef41Sopenharmony_ci                                           bool* result) {
26561cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
26571cb0ef41Sopenharmony_ci
26581cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
26591cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
26601cb0ef41Sopenharmony_ci
26611cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
26621cb0ef41Sopenharmony_ci  v8::Maybe<bool> delete_maybe = obj->Delete(context, index);
26631cb0ef41Sopenharmony_ci  CHECK_MAYBE_NOTHING(env, delete_maybe, JSVM_GENERIC_FAILURE);
26641cb0ef41Sopenharmony_ci
26651cb0ef41Sopenharmony_ci  if (result != nullptr) *result = delete_maybe.FromMaybe(false);
26661cb0ef41Sopenharmony_ci
26671cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
26681cb0ef41Sopenharmony_ci}
26691cb0ef41Sopenharmony_ci
26701cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
26711cb0ef41Sopenharmony_ciOH_JSVM_DefineProperties(JSVM_Env env,
26721cb0ef41Sopenharmony_ci                       JSVM_Value object,
26731cb0ef41Sopenharmony_ci                       size_t propertyCount,
26741cb0ef41Sopenharmony_ci                       const JSVM_PropertyDescriptor* properties) {
26751cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
26761cb0ef41Sopenharmony_ci  if (propertyCount > 0) {
26771cb0ef41Sopenharmony_ci    CHECK_ARG(env, properties);
26781cb0ef41Sopenharmony_ci  }
26791cb0ef41Sopenharmony_ci
26801cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
26811cb0ef41Sopenharmony_ci
26821cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
26831cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
26841cb0ef41Sopenharmony_ci
26851cb0ef41Sopenharmony_ci  for (size_t i = 0; i < propertyCount; i++) {
26861cb0ef41Sopenharmony_ci    const JSVM_PropertyDescriptor* p = &properties[i];
26871cb0ef41Sopenharmony_ci
26881cb0ef41Sopenharmony_ci    v8::Local<v8::Name> property_name;
26891cb0ef41Sopenharmony_ci    STATUS_CALL(v8impl::V8NameFromPropertyDescriptor(env, p, &property_name));
26901cb0ef41Sopenharmony_ci
26911cb0ef41Sopenharmony_ci    if (p->getter != nullptr || p->setter != nullptr) {
26921cb0ef41Sopenharmony_ci      v8::Local<v8::Function> local_getter;
26931cb0ef41Sopenharmony_ci      v8::Local<v8::Function> local_setter;
26941cb0ef41Sopenharmony_ci
26951cb0ef41Sopenharmony_ci      if (p->getter != nullptr) {
26961cb0ef41Sopenharmony_ci        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
26971cb0ef41Sopenharmony_ci            env, p->getter, &local_getter));
26981cb0ef41Sopenharmony_ci      }
26991cb0ef41Sopenharmony_ci      if (p->setter != nullptr) {
27001cb0ef41Sopenharmony_ci        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
27011cb0ef41Sopenharmony_ci            env, p->setter, &local_setter));
27021cb0ef41Sopenharmony_ci      }
27031cb0ef41Sopenharmony_ci
27041cb0ef41Sopenharmony_ci      v8::PropertyDescriptor descriptor(local_getter, local_setter);
27051cb0ef41Sopenharmony_ci      descriptor.set_enumerable((p->attributes & JSVM_ENUMERABLE) != 0);
27061cb0ef41Sopenharmony_ci      descriptor.set_configurable((p->attributes & JSVM_CONFIGURABLE) != 0);
27071cb0ef41Sopenharmony_ci
27081cb0ef41Sopenharmony_ci      auto define_maybe =
27091cb0ef41Sopenharmony_ci          obj->DefineProperty(context, property_name, descriptor);
27101cb0ef41Sopenharmony_ci
27111cb0ef41Sopenharmony_ci      if (!define_maybe.FromMaybe(false)) {
27121cb0ef41Sopenharmony_ci        return jsvm_set_last_error(env, JSVM_INVALID_ARG);
27131cb0ef41Sopenharmony_ci      }
27141cb0ef41Sopenharmony_ci    } else if (p->method != nullptr) {
27151cb0ef41Sopenharmony_ci      v8::Local<v8::Function> method;
27161cb0ef41Sopenharmony_ci      STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
27171cb0ef41Sopenharmony_ci          env, p->method, &method));
27181cb0ef41Sopenharmony_ci      v8::PropertyDescriptor descriptor(method,
27191cb0ef41Sopenharmony_ci                                        (p->attributes & JSVM_WRITABLE) != 0);
27201cb0ef41Sopenharmony_ci      descriptor.set_enumerable((p->attributes & JSVM_ENUMERABLE) != 0);
27211cb0ef41Sopenharmony_ci      descriptor.set_configurable((p->attributes & JSVM_CONFIGURABLE) != 0);
27221cb0ef41Sopenharmony_ci
27231cb0ef41Sopenharmony_ci      auto define_maybe =
27241cb0ef41Sopenharmony_ci          obj->DefineProperty(context, property_name, descriptor);
27251cb0ef41Sopenharmony_ci
27261cb0ef41Sopenharmony_ci      if (!define_maybe.FromMaybe(false)) {
27271cb0ef41Sopenharmony_ci        return jsvm_set_last_error(env, JSVM_GENERIC_FAILURE);
27281cb0ef41Sopenharmony_ci      }
27291cb0ef41Sopenharmony_ci    } else {
27301cb0ef41Sopenharmony_ci      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
27311cb0ef41Sopenharmony_ci      bool defined_successfully = false;
27321cb0ef41Sopenharmony_ci
27331cb0ef41Sopenharmony_ci      if ((p->attributes & JSVM_ENUMERABLE) &&
27341cb0ef41Sopenharmony_ci          (p->attributes & JSVM_WRITABLE) &&
27351cb0ef41Sopenharmony_ci          (p->attributes & JSVM_CONFIGURABLE)) {
27361cb0ef41Sopenharmony_ci        // Use a fast path for this type of data property.
27371cb0ef41Sopenharmony_ci        auto define_maybe =
27381cb0ef41Sopenharmony_ci            obj->CreateDataProperty(context, property_name, value);
27391cb0ef41Sopenharmony_ci        defined_successfully = define_maybe.FromMaybe(false);
27401cb0ef41Sopenharmony_ci      } else {
27411cb0ef41Sopenharmony_ci        v8::PropertyDescriptor descriptor(value,
27421cb0ef41Sopenharmony_ci                                          (p->attributes & JSVM_WRITABLE) != 0);
27431cb0ef41Sopenharmony_ci        descriptor.set_enumerable((p->attributes & JSVM_ENUMERABLE) != 0);
27441cb0ef41Sopenharmony_ci        descriptor.set_configurable((p->attributes & JSVM_CONFIGURABLE) != 0);
27451cb0ef41Sopenharmony_ci
27461cb0ef41Sopenharmony_ci        auto define_maybe =
27471cb0ef41Sopenharmony_ci            obj->DefineProperty(context, property_name, descriptor);
27481cb0ef41Sopenharmony_ci        defined_successfully = define_maybe.FromMaybe(false);
27491cb0ef41Sopenharmony_ci      }
27501cb0ef41Sopenharmony_ci
27511cb0ef41Sopenharmony_ci      if (!defined_successfully) {
27521cb0ef41Sopenharmony_ci        return jsvm_set_last_error(env, JSVM_INVALID_ARG);
27531cb0ef41Sopenharmony_ci      }
27541cb0ef41Sopenharmony_ci    }
27551cb0ef41Sopenharmony_ci  }
27561cb0ef41Sopenharmony_ci
27571cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
27581cb0ef41Sopenharmony_ci}
27591cb0ef41Sopenharmony_ci
27601cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_ObjectFreeze(JSVM_Env env, JSVM_Value object) {
27611cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
27621cb0ef41Sopenharmony_ci
27631cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
27641cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
27651cb0ef41Sopenharmony_ci
27661cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
27671cb0ef41Sopenharmony_ci
27681cb0ef41Sopenharmony_ci  v8::Maybe<bool> set_frozen =
27691cb0ef41Sopenharmony_ci      obj->SetIntegrityLevel(context, v8::IntegrityLevel::kFrozen);
27701cb0ef41Sopenharmony_ci
27711cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(
27721cb0ef41Sopenharmony_ci      env, set_frozen.FromMaybe(false), JSVM_GENERIC_FAILURE);
27731cb0ef41Sopenharmony_ci
27741cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
27751cb0ef41Sopenharmony_ci}
27761cb0ef41Sopenharmony_ci
27771cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_ObjectSeal(JSVM_Env env, JSVM_Value object) {
27781cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
27791cb0ef41Sopenharmony_ci
27801cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
27811cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
27821cb0ef41Sopenharmony_ci
27831cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
27841cb0ef41Sopenharmony_ci
27851cb0ef41Sopenharmony_ci  v8::Maybe<bool> set_sealed =
27861cb0ef41Sopenharmony_ci      obj->SetIntegrityLevel(context, v8::IntegrityLevel::kSealed);
27871cb0ef41Sopenharmony_ci
27881cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(
27891cb0ef41Sopenharmony_ci      env, set_sealed.FromMaybe(false), JSVM_GENERIC_FAILURE);
27901cb0ef41Sopenharmony_ci
27911cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
27921cb0ef41Sopenharmony_ci}
27931cb0ef41Sopenharmony_ci
27941cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsArray(JSVM_Env env,
27951cb0ef41Sopenharmony_ci                                     JSVM_Value value,
27961cb0ef41Sopenharmony_ci                                     bool* result) {
27971cb0ef41Sopenharmony_ci  CHECK_ENV(env);
27981cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
27991cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
28001cb0ef41Sopenharmony_ci
28011cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
28021cb0ef41Sopenharmony_ci
28031cb0ef41Sopenharmony_ci  *result = val->IsArray();
28041cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
28051cb0ef41Sopenharmony_ci}
28061cb0ef41Sopenharmony_ci
28071cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsRegExp(JSVM_Env env,
28081cb0ef41Sopenharmony_ci                                        JSVM_Value value,
28091cb0ef41Sopenharmony_ci                                        bool* result) {
28101cb0ef41Sopenharmony_ci  CHECK_ENV(env);
28111cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
28121cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
28131cb0ef41Sopenharmony_ci
28141cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
28151cb0ef41Sopenharmony_ci
28161cb0ef41Sopenharmony_ci  *result = val->IsRegExp();
28171cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
28181cb0ef41Sopenharmony_ci}
28191cb0ef41Sopenharmony_ci
28201cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetArrayLength(JSVM_Env env,
28211cb0ef41Sopenharmony_ci                                             JSVM_Value value,
28221cb0ef41Sopenharmony_ci                                             uint32_t* result) {
28231cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
28241cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
28251cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
28261cb0ef41Sopenharmony_ci
28271cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
28281cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsArray(), JSVM_ARRAY_EXPECTED);
28291cb0ef41Sopenharmony_ci
28301cb0ef41Sopenharmony_ci  v8::Local<v8::Array> arr = val.As<v8::Array>();
28311cb0ef41Sopenharmony_ci  *result = arr->Length();
28321cb0ef41Sopenharmony_ci
28331cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
28341cb0ef41Sopenharmony_ci}
28351cb0ef41Sopenharmony_ci
28361cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_StrictEquals(JSVM_Env env,
28371cb0ef41Sopenharmony_ci                                          JSVM_Value lhs,
28381cb0ef41Sopenharmony_ci                                          JSVM_Value rhs,
28391cb0ef41Sopenharmony_ci                                          bool* result) {
28401cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
28411cb0ef41Sopenharmony_ci  CHECK_ARG(env, lhs);
28421cb0ef41Sopenharmony_ci  CHECK_ARG(env, rhs);
28431cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
28441cb0ef41Sopenharmony_ci
28451cb0ef41Sopenharmony_ci  v8::Local<v8::Value> a = v8impl::V8LocalValueFromJsValue(lhs);
28461cb0ef41Sopenharmony_ci  v8::Local<v8::Value> b = v8impl::V8LocalValueFromJsValue(rhs);
28471cb0ef41Sopenharmony_ci
28481cb0ef41Sopenharmony_ci  *result = a->StrictEquals(b);
28491cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
28501cb0ef41Sopenharmony_ci}
28511cb0ef41Sopenharmony_ci
28521cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_Equals(JSVM_Env env,
28531cb0ef41Sopenharmony_ci                                      JSVM_Value lhs,
28541cb0ef41Sopenharmony_ci                                      JSVM_Value rhs,
28551cb0ef41Sopenharmony_ci                                      bool* result) {
28561cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
28571cb0ef41Sopenharmony_ci  CHECK_ARG(env, lhs);
28581cb0ef41Sopenharmony_ci  CHECK_ARG(env, rhs);
28591cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
28601cb0ef41Sopenharmony_ci
28611cb0ef41Sopenharmony_ci  v8::Local<v8::Value> a = v8impl::V8LocalValueFromJsValue(lhs);
28621cb0ef41Sopenharmony_ci  v8::Local<v8::Value> b = v8impl::V8LocalValueFromJsValue(rhs);
28631cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
28641cb0ef41Sopenharmony_ci
28651cb0ef41Sopenharmony_ci  *result = a->Equals(context, b).FromJust();
28661cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
28671cb0ef41Sopenharmony_ci}
28681cb0ef41Sopenharmony_ci
28691cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetPrototype(JSVM_Env env,
28701cb0ef41Sopenharmony_ci                                          JSVM_Value object,
28711cb0ef41Sopenharmony_ci                                          JSVM_Value* result) {
28721cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
28731cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
28741cb0ef41Sopenharmony_ci
28751cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
28761cb0ef41Sopenharmony_ci
28771cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
28781cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
28791cb0ef41Sopenharmony_ci
28801cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = obj->GetPrototype();
28811cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(val);
28821cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
28831cb0ef41Sopenharmony_ci}
28841cb0ef41Sopenharmony_ci
28851cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateObject(JSVM_Env env, JSVM_Value* result) {
28861cb0ef41Sopenharmony_ci  CHECK_ENV(env);
28871cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
28881cb0ef41Sopenharmony_ci
28891cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(v8::Object::New(env->isolate));
28901cb0ef41Sopenharmony_ci
28911cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
28921cb0ef41Sopenharmony_ci}
28931cb0ef41Sopenharmony_ci
28941cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateArray(JSVM_Env env, JSVM_Value* result) {
28951cb0ef41Sopenharmony_ci  CHECK_ENV(env);
28961cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
28971cb0ef41Sopenharmony_ci
28981cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(v8::Array::New(env->isolate));
28991cb0ef41Sopenharmony_ci
29001cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
29011cb0ef41Sopenharmony_ci}
29021cb0ef41Sopenharmony_ci
29031cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateArrayWithLength(JSVM_Env env,
29041cb0ef41Sopenharmony_ci                                                     size_t length,
29051cb0ef41Sopenharmony_ci                                                     JSVM_Value* result) {
29061cb0ef41Sopenharmony_ci  CHECK_ENV(env);
29071cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
29081cb0ef41Sopenharmony_ci
29091cb0ef41Sopenharmony_ci  *result =
29101cb0ef41Sopenharmony_ci      v8impl::JsValueFromV8LocalValue(v8::Array::New(env->isolate, length));
29111cb0ef41Sopenharmony_ci
29121cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
29131cb0ef41Sopenharmony_ci}
29141cb0ef41Sopenharmony_ci
29151cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateStringLatin1(JSVM_Env env,
29161cb0ef41Sopenharmony_ci                                                 const char* str,
29171cb0ef41Sopenharmony_ci                                                 size_t length,
29181cb0ef41Sopenharmony_ci                                                 JSVM_Value* result) {
29191cb0ef41Sopenharmony_ci  return v8impl::NewString(env, str, length, result, [&](v8::Isolate* isolate) {
29201cb0ef41Sopenharmony_ci    return v8::String::NewFromOneByte(isolate,
29211cb0ef41Sopenharmony_ci                                      reinterpret_cast<const uint8_t*>(str),
29221cb0ef41Sopenharmony_ci                                      v8::NewStringType::kNormal,
29231cb0ef41Sopenharmony_ci                                      length);
29241cb0ef41Sopenharmony_ci  });
29251cb0ef41Sopenharmony_ci}
29261cb0ef41Sopenharmony_ci
29271cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateStringUtf8(JSVM_Env env,
29281cb0ef41Sopenharmony_ci                                               const char* str,
29291cb0ef41Sopenharmony_ci                                               size_t length,
29301cb0ef41Sopenharmony_ci                                               JSVM_Value* result) {
29311cb0ef41Sopenharmony_ci  return v8impl::NewString(env, str, length, result, [&](v8::Isolate* isolate) {
29321cb0ef41Sopenharmony_ci    return v8::String::NewFromUtf8(
29331cb0ef41Sopenharmony_ci        isolate, str, v8::NewStringType::kNormal, static_cast<int>(length));
29341cb0ef41Sopenharmony_ci  });
29351cb0ef41Sopenharmony_ci}
29361cb0ef41Sopenharmony_ci
29371cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateStringUtf16(JSVM_Env env,
29381cb0ef41Sopenharmony_ci                                                const char16_t* str,
29391cb0ef41Sopenharmony_ci                                                size_t length,
29401cb0ef41Sopenharmony_ci                                                JSVM_Value* result) {
29411cb0ef41Sopenharmony_ci  return v8impl::NewString(env, str, length, result, [&](v8::Isolate* isolate) {
29421cb0ef41Sopenharmony_ci    return v8::String::NewFromTwoByte(isolate,
29431cb0ef41Sopenharmony_ci                                      reinterpret_cast<const uint16_t*>(str),
29441cb0ef41Sopenharmony_ci                                      v8::NewStringType::kNormal,
29451cb0ef41Sopenharmony_ci                                      length);
29461cb0ef41Sopenharmony_ci  });
29471cb0ef41Sopenharmony_ci}
29481cb0ef41Sopenharmony_ci
29491cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateDouble(JSVM_Env env,
29501cb0ef41Sopenharmony_ci                                          double value,
29511cb0ef41Sopenharmony_ci                                          JSVM_Value* result) {
29521cb0ef41Sopenharmony_ci  CHECK_ENV(env);
29531cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
29541cb0ef41Sopenharmony_ci
29551cb0ef41Sopenharmony_ci  *result =
29561cb0ef41Sopenharmony_ci      v8impl::JsValueFromV8LocalValue(v8::Number::New(env->isolate, value));
29571cb0ef41Sopenharmony_ci
29581cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
29591cb0ef41Sopenharmony_ci}
29601cb0ef41Sopenharmony_ci
29611cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateInt32(JSVM_Env env,
29621cb0ef41Sopenharmony_ci                                         int32_t value,
29631cb0ef41Sopenharmony_ci                                         JSVM_Value* result) {
29641cb0ef41Sopenharmony_ci  CHECK_ENV(env);
29651cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
29661cb0ef41Sopenharmony_ci
29671cb0ef41Sopenharmony_ci  *result =
29681cb0ef41Sopenharmony_ci      v8impl::JsValueFromV8LocalValue(v8::Integer::New(env->isolate, value));
29691cb0ef41Sopenharmony_ci
29701cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
29711cb0ef41Sopenharmony_ci}
29721cb0ef41Sopenharmony_ci
29731cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateUint32(JSVM_Env env,
29741cb0ef41Sopenharmony_ci                                          uint32_t value,
29751cb0ef41Sopenharmony_ci                                          JSVM_Value* result) {
29761cb0ef41Sopenharmony_ci  CHECK_ENV(env);
29771cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
29781cb0ef41Sopenharmony_ci
29791cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(
29801cb0ef41Sopenharmony_ci      v8::Integer::NewFromUnsigned(env->isolate, value));
29811cb0ef41Sopenharmony_ci
29821cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
29831cb0ef41Sopenharmony_ci}
29841cb0ef41Sopenharmony_ci
29851cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateInt64(JSVM_Env env,
29861cb0ef41Sopenharmony_ci                                         int64_t value,
29871cb0ef41Sopenharmony_ci                                         JSVM_Value* result) {
29881cb0ef41Sopenharmony_ci  CHECK_ENV(env);
29891cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
29901cb0ef41Sopenharmony_ci
29911cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(
29921cb0ef41Sopenharmony_ci      v8::Number::New(env->isolate, static_cast<double>(value)));
29931cb0ef41Sopenharmony_ci
29941cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
29951cb0ef41Sopenharmony_ci}
29961cb0ef41Sopenharmony_ci
29971cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateBigintInt64(JSVM_Env env,
29981cb0ef41Sopenharmony_ci                                                int64_t value,
29991cb0ef41Sopenharmony_ci                                                JSVM_Value* result) {
30001cb0ef41Sopenharmony_ci  CHECK_ENV(env);
30011cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
30021cb0ef41Sopenharmony_ci
30031cb0ef41Sopenharmony_ci  *result =
30041cb0ef41Sopenharmony_ci      v8impl::JsValueFromV8LocalValue(v8::BigInt::New(env->isolate, value));
30051cb0ef41Sopenharmony_ci
30061cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
30071cb0ef41Sopenharmony_ci}
30081cb0ef41Sopenharmony_ci
30091cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateBigintUint64(JSVM_Env env,
30101cb0ef41Sopenharmony_ci                                                 uint64_t value,
30111cb0ef41Sopenharmony_ci                                                 JSVM_Value* result) {
30121cb0ef41Sopenharmony_ci  CHECK_ENV(env);
30131cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
30141cb0ef41Sopenharmony_ci
30151cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(
30161cb0ef41Sopenharmony_ci      v8::BigInt::NewFromUnsigned(env->isolate, value));
30171cb0ef41Sopenharmony_ci
30181cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
30191cb0ef41Sopenharmony_ci}
30201cb0ef41Sopenharmony_ci
30211cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateBigintWords(JSVM_Env env,
30221cb0ef41Sopenharmony_ci                                                int signBit,
30231cb0ef41Sopenharmony_ci                                                size_t wordCount,
30241cb0ef41Sopenharmony_ci                                                const uint64_t* words,
30251cb0ef41Sopenharmony_ci                                                JSVM_Value* result) {
30261cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
30271cb0ef41Sopenharmony_ci  CHECK_ARG(env, words);
30281cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
30291cb0ef41Sopenharmony_ci
30301cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
30311cb0ef41Sopenharmony_ci
30321cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, wordCount <= INT_MAX, JSVM_INVALID_ARG);
30331cb0ef41Sopenharmony_ci
30341cb0ef41Sopenharmony_ci  v8::MaybeLocal<v8::BigInt> b =
30351cb0ef41Sopenharmony_ci      v8::BigInt::NewFromWords(context, signBit, wordCount, words);
30361cb0ef41Sopenharmony_ci
30371cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, b, JSVM_GENERIC_FAILURE);
30381cb0ef41Sopenharmony_ci
30391cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(b.ToLocalChecked());
30401cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
30411cb0ef41Sopenharmony_ci}
30421cb0ef41Sopenharmony_ci
30431cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetBoolean(JSVM_Env env,
30441cb0ef41Sopenharmony_ci                                        bool value,
30451cb0ef41Sopenharmony_ci                                        JSVM_Value* result) {
30461cb0ef41Sopenharmony_ci  CHECK_ENV(env);
30471cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
30481cb0ef41Sopenharmony_ci
30491cb0ef41Sopenharmony_ci  v8::Isolate* isolate = env->isolate;
30501cb0ef41Sopenharmony_ci
30511cb0ef41Sopenharmony_ci  if (value) {
30521cb0ef41Sopenharmony_ci    *result = v8impl::JsValueFromV8LocalValue(v8::True(isolate));
30531cb0ef41Sopenharmony_ci  } else {
30541cb0ef41Sopenharmony_ci    *result = v8impl::JsValueFromV8LocalValue(v8::False(isolate));
30551cb0ef41Sopenharmony_ci  }
30561cb0ef41Sopenharmony_ci
30571cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
30581cb0ef41Sopenharmony_ci}
30591cb0ef41Sopenharmony_ci
30601cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateSymbol(JSVM_Env env,
30611cb0ef41Sopenharmony_ci                                          JSVM_Value description,
30621cb0ef41Sopenharmony_ci                                          JSVM_Value* result) {
30631cb0ef41Sopenharmony_ci  CHECK_ENV(env);
30641cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
30651cb0ef41Sopenharmony_ci
30661cb0ef41Sopenharmony_ci  v8::Isolate* isolate = env->isolate;
30671cb0ef41Sopenharmony_ci
30681cb0ef41Sopenharmony_ci  if (description == nullptr) {
30691cb0ef41Sopenharmony_ci    *result = v8impl::JsValueFromV8LocalValue(v8::Symbol::New(isolate));
30701cb0ef41Sopenharmony_ci  } else {
30711cb0ef41Sopenharmony_ci    v8::Local<v8::Value> desc = v8impl::V8LocalValueFromJsValue(description);
30721cb0ef41Sopenharmony_ci    RETURN_STATUS_IF_FALSE(env, desc->IsString(), JSVM_STRING_EXPECTED);
30731cb0ef41Sopenharmony_ci
30741cb0ef41Sopenharmony_ci    *result = v8impl::JsValueFromV8LocalValue(
30751cb0ef41Sopenharmony_ci        v8::Symbol::New(isolate, desc.As<v8::String>()));
30761cb0ef41Sopenharmony_ci  }
30771cb0ef41Sopenharmony_ci
30781cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
30791cb0ef41Sopenharmony_ci}
30801cb0ef41Sopenharmony_ci
30811cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_SymbolFor(JSVM_Env env,
30821cb0ef41Sopenharmony_ci                                           const char* utf8description,
30831cb0ef41Sopenharmony_ci                                           size_t length,
30841cb0ef41Sopenharmony_ci                                           JSVM_Value* result) {
30851cb0ef41Sopenharmony_ci  CHECK_ENV(env);
30861cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
30871cb0ef41Sopenharmony_ci
30881cb0ef41Sopenharmony_ci  JSVM_Value js_description_string;
30891cb0ef41Sopenharmony_ci  STATUS_CALL(OH_JSVM_CreateStringUtf8(
30901cb0ef41Sopenharmony_ci      env, utf8description, length, &js_description_string));
30911cb0ef41Sopenharmony_ci  v8::Local<v8::String> description_string =
30921cb0ef41Sopenharmony_ci      v8impl::V8LocalValueFromJsValue(js_description_string).As<v8::String>();
30931cb0ef41Sopenharmony_ci
30941cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(
30951cb0ef41Sopenharmony_ci      v8::Symbol::For(env->isolate, description_string));
30961cb0ef41Sopenharmony_ci
30971cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
30981cb0ef41Sopenharmony_ci}
30991cb0ef41Sopenharmony_ci
31001cb0ef41Sopenharmony_cistatic inline JSVM_Status set_error_code(JSVM_Env env,
31011cb0ef41Sopenharmony_ci                                         v8::Local<v8::Value> error,
31021cb0ef41Sopenharmony_ci                                         JSVM_Value code,
31031cb0ef41Sopenharmony_ci                                         const char* code_cstring) {
31041cb0ef41Sopenharmony_ci  if ((code != nullptr) || (code_cstring != nullptr)) {
31051cb0ef41Sopenharmony_ci    v8::Local<v8::Context> context = env->context();
31061cb0ef41Sopenharmony_ci    v8::Local<v8::Object> err_object = error.As<v8::Object>();
31071cb0ef41Sopenharmony_ci
31081cb0ef41Sopenharmony_ci    v8::Local<v8::Value> code_value = v8impl::V8LocalValueFromJsValue(code);
31091cb0ef41Sopenharmony_ci    if (code != nullptr) {
31101cb0ef41Sopenharmony_ci      code_value = v8impl::V8LocalValueFromJsValue(code);
31111cb0ef41Sopenharmony_ci      RETURN_STATUS_IF_FALSE(env, code_value->IsString(), JSVM_STRING_EXPECTED);
31121cb0ef41Sopenharmony_ci    } else {
31131cb0ef41Sopenharmony_ci      CHECK_NEW_FROM_UTF8(env, code_value, code_cstring);
31141cb0ef41Sopenharmony_ci    }
31151cb0ef41Sopenharmony_ci
31161cb0ef41Sopenharmony_ci    v8::Local<v8::Name> code_key;
31171cb0ef41Sopenharmony_ci    CHECK_NEW_FROM_UTF8(env, code_key, "code");
31181cb0ef41Sopenharmony_ci
31191cb0ef41Sopenharmony_ci    v8::Maybe<bool> set_maybe = err_object->Set(context, code_key, code_value);
31201cb0ef41Sopenharmony_ci    RETURN_STATUS_IF_FALSE(
31211cb0ef41Sopenharmony_ci        env, set_maybe.FromMaybe(false), JSVM_GENERIC_FAILURE);
31221cb0ef41Sopenharmony_ci  }
31231cb0ef41Sopenharmony_ci  return JSVM_OK;
31241cb0ef41Sopenharmony_ci}
31251cb0ef41Sopenharmony_ci
31261cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateError(JSVM_Env env,
31271cb0ef41Sopenharmony_ci                                         JSVM_Value code,
31281cb0ef41Sopenharmony_ci                                         JSVM_Value msg,
31291cb0ef41Sopenharmony_ci                                         JSVM_Value* result) {
31301cb0ef41Sopenharmony_ci  CHECK_ENV(env);
31311cb0ef41Sopenharmony_ci  CHECK_ARG(env, msg);
31321cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
31331cb0ef41Sopenharmony_ci
31341cb0ef41Sopenharmony_ci  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
31351cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), JSVM_STRING_EXPECTED);
31361cb0ef41Sopenharmony_ci
31371cb0ef41Sopenharmony_ci  v8::Local<v8::Value> error_obj =
31381cb0ef41Sopenharmony_ci      v8::Exception::Error(message_value.As<v8::String>());
31391cb0ef41Sopenharmony_ci  STATUS_CALL(set_error_code(env, error_obj, code, nullptr));
31401cb0ef41Sopenharmony_ci
31411cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(error_obj);
31421cb0ef41Sopenharmony_ci
31431cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
31441cb0ef41Sopenharmony_ci}
31451cb0ef41Sopenharmony_ci
31461cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateTypeError(JSVM_Env env,
31471cb0ef41Sopenharmony_ci                                              JSVM_Value code,
31481cb0ef41Sopenharmony_ci                                              JSVM_Value msg,
31491cb0ef41Sopenharmony_ci                                              JSVM_Value* result) {
31501cb0ef41Sopenharmony_ci  CHECK_ENV(env);
31511cb0ef41Sopenharmony_ci  CHECK_ARG(env, msg);
31521cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
31531cb0ef41Sopenharmony_ci
31541cb0ef41Sopenharmony_ci  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
31551cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), JSVM_STRING_EXPECTED);
31561cb0ef41Sopenharmony_ci
31571cb0ef41Sopenharmony_ci  v8::Local<v8::Value> error_obj =
31581cb0ef41Sopenharmony_ci      v8::Exception::TypeError(message_value.As<v8::String>());
31591cb0ef41Sopenharmony_ci  STATUS_CALL(set_error_code(env, error_obj, code, nullptr));
31601cb0ef41Sopenharmony_ci
31611cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(error_obj);
31621cb0ef41Sopenharmony_ci
31631cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
31641cb0ef41Sopenharmony_ci}
31651cb0ef41Sopenharmony_ci
31661cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateRangeError(JSVM_Env env,
31671cb0ef41Sopenharmony_ci                                               JSVM_Value code,
31681cb0ef41Sopenharmony_ci                                               JSVM_Value msg,
31691cb0ef41Sopenharmony_ci                                               JSVM_Value* result) {
31701cb0ef41Sopenharmony_ci  CHECK_ENV(env);
31711cb0ef41Sopenharmony_ci  CHECK_ARG(env, msg);
31721cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
31731cb0ef41Sopenharmony_ci
31741cb0ef41Sopenharmony_ci  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
31751cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), JSVM_STRING_EXPECTED);
31761cb0ef41Sopenharmony_ci
31771cb0ef41Sopenharmony_ci  v8::Local<v8::Value> error_obj =
31781cb0ef41Sopenharmony_ci      v8::Exception::RangeError(message_value.As<v8::String>());
31791cb0ef41Sopenharmony_ci  STATUS_CALL(set_error_code(env, error_obj, code, nullptr));
31801cb0ef41Sopenharmony_ci
31811cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(error_obj);
31821cb0ef41Sopenharmony_ci
31831cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
31841cb0ef41Sopenharmony_ci}
31851cb0ef41Sopenharmony_ci
31861cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateSyntaxError(JSVM_Env env,
31871cb0ef41Sopenharmony_ci                                                    JSVM_Value code,
31881cb0ef41Sopenharmony_ci                                                    JSVM_Value msg,
31891cb0ef41Sopenharmony_ci                                                    JSVM_Value* result) {
31901cb0ef41Sopenharmony_ci  CHECK_ENV(env);
31911cb0ef41Sopenharmony_ci  CHECK_ARG(env, msg);
31921cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
31931cb0ef41Sopenharmony_ci
31941cb0ef41Sopenharmony_ci  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
31951cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), JSVM_STRING_EXPECTED);
31961cb0ef41Sopenharmony_ci
31971cb0ef41Sopenharmony_ci  v8::Local<v8::Value> error_obj =
31981cb0ef41Sopenharmony_ci      v8::Exception::SyntaxError(message_value.As<v8::String>());
31991cb0ef41Sopenharmony_ci  STATUS_CALL(set_error_code(env, error_obj, code, nullptr));
32001cb0ef41Sopenharmony_ci
32011cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(error_obj);
32021cb0ef41Sopenharmony_ci
32031cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
32041cb0ef41Sopenharmony_ci}
32051cb0ef41Sopenharmony_ci
32061cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_Typeof(JSVM_Env env,
32071cb0ef41Sopenharmony_ci                                   JSVM_Value value,
32081cb0ef41Sopenharmony_ci                                   JSVM_ValueType* result) {
32091cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
32101cb0ef41Sopenharmony_ci  // JS exceptions.
32111cb0ef41Sopenharmony_ci  CHECK_ENV(env);
32121cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
32131cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
32141cb0ef41Sopenharmony_ci
32151cb0ef41Sopenharmony_ci  v8::Local<v8::Value> v = v8impl::V8LocalValueFromJsValue(value);
32161cb0ef41Sopenharmony_ci
32171cb0ef41Sopenharmony_ci  if (v->IsNumber()) {
32181cb0ef41Sopenharmony_ci    *result = JSVM_NUMBER;
32191cb0ef41Sopenharmony_ci  } else if (v->IsBigInt()) {
32201cb0ef41Sopenharmony_ci    *result = JSVM_BIGINT;
32211cb0ef41Sopenharmony_ci  } else if (v->IsString()) {
32221cb0ef41Sopenharmony_ci    *result = JSVM_STRING;
32231cb0ef41Sopenharmony_ci  } else if (v->IsFunction()) {
32241cb0ef41Sopenharmony_ci    // This test has to come before IsObject because IsFunction
32251cb0ef41Sopenharmony_ci    // implies IsObject
32261cb0ef41Sopenharmony_ci    *result = JSVM_FUNCTION;
32271cb0ef41Sopenharmony_ci  } else if (v->IsExternal()) {
32281cb0ef41Sopenharmony_ci    // This test has to come before IsObject because IsExternal
32291cb0ef41Sopenharmony_ci    // implies IsObject
32301cb0ef41Sopenharmony_ci    *result = JSVM_EXTERNAL;
32311cb0ef41Sopenharmony_ci  } else if (v->IsObject()) {
32321cb0ef41Sopenharmony_ci    *result = JSVM_OBJECT;
32331cb0ef41Sopenharmony_ci  } else if (v->IsBoolean()) {
32341cb0ef41Sopenharmony_ci    *result = JSVM_BOOLEAN;
32351cb0ef41Sopenharmony_ci  } else if (v->IsUndefined()) {
32361cb0ef41Sopenharmony_ci    *result = JSVM_UNDEFINED;
32371cb0ef41Sopenharmony_ci  } else if (v->IsSymbol()) {
32381cb0ef41Sopenharmony_ci    *result = JSVM_SYMBOL;
32391cb0ef41Sopenharmony_ci  } else if (v->IsNull()) {
32401cb0ef41Sopenharmony_ci    *result = JSVM_NULL;
32411cb0ef41Sopenharmony_ci  } else {
32421cb0ef41Sopenharmony_ci    // Should not get here unless V8 has added some new kind of value.
32431cb0ef41Sopenharmony_ci    return jsvm_set_last_error(env, JSVM_INVALID_ARG);
32441cb0ef41Sopenharmony_ci  }
32451cb0ef41Sopenharmony_ci
32461cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
32471cb0ef41Sopenharmony_ci}
32481cb0ef41Sopenharmony_ci
32491cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetUndefined(JSVM_Env env, JSVM_Value* result) {
32501cb0ef41Sopenharmony_ci  CHECK_ENV(env);
32511cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
32521cb0ef41Sopenharmony_ci
32531cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(v8::Undefined(env->isolate));
32541cb0ef41Sopenharmony_ci
32551cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
32561cb0ef41Sopenharmony_ci}
32571cb0ef41Sopenharmony_ci
32581cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetNull(JSVM_Env env, JSVM_Value* result) {
32591cb0ef41Sopenharmony_ci  CHECK_ENV(env);
32601cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
32611cb0ef41Sopenharmony_ci
32621cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(v8::Null(env->isolate));
32631cb0ef41Sopenharmony_ci
32641cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
32651cb0ef41Sopenharmony_ci}
32661cb0ef41Sopenharmony_ci
32671cb0ef41Sopenharmony_ci// Gets all callback info in a single call. (Ugly, but faster.)
32681cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetCbInfo(
32691cb0ef41Sopenharmony_ci    JSVM_Env env,               // [in] JSVM environment handle
32701cb0ef41Sopenharmony_ci    JSVM_CallbackInfo cbinfo,  // [in] Opaque callback-info handle
32711cb0ef41Sopenharmony_ci    size_t* argc,      // [in-out] Specifies the size of the provided argv array
32721cb0ef41Sopenharmony_ci                       // and receives the actual count of args.
32731cb0ef41Sopenharmony_ci    JSVM_Value* argv,  // [out] Array of values
32741cb0ef41Sopenharmony_ci    JSVM_Value* thisArg,  // [out] Receives the JS 'this' arg for the call
32751cb0ef41Sopenharmony_ci    void** data) {         // [out] Receives the data pointer for the callback.
32761cb0ef41Sopenharmony_ci  CHECK_ENV(env);
32771cb0ef41Sopenharmony_ci  CHECK_ARG(env, cbinfo);
32781cb0ef41Sopenharmony_ci
32791cb0ef41Sopenharmony_ci  v8impl::CallbackWrapper* info =
32801cb0ef41Sopenharmony_ci      reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
32811cb0ef41Sopenharmony_ci
32821cb0ef41Sopenharmony_ci  if (argv != nullptr) {
32831cb0ef41Sopenharmony_ci    CHECK_ARG(env, argc);
32841cb0ef41Sopenharmony_ci    info->Args(argv, *argc);
32851cb0ef41Sopenharmony_ci  }
32861cb0ef41Sopenharmony_ci  if (argc != nullptr) {
32871cb0ef41Sopenharmony_ci    *argc = info->ArgsLength();
32881cb0ef41Sopenharmony_ci  }
32891cb0ef41Sopenharmony_ci  if (thisArg != nullptr) {
32901cb0ef41Sopenharmony_ci    *thisArg = info->This();
32911cb0ef41Sopenharmony_ci  }
32921cb0ef41Sopenharmony_ci  if (data != nullptr) {
32931cb0ef41Sopenharmony_ci    *data = info->Data();
32941cb0ef41Sopenharmony_ci  }
32951cb0ef41Sopenharmony_ci
32961cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
32971cb0ef41Sopenharmony_ci}
32981cb0ef41Sopenharmony_ci
32991cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetNewTarget(JSVM_Env env,
33001cb0ef41Sopenharmony_ci                                           JSVM_CallbackInfo cbinfo,
33011cb0ef41Sopenharmony_ci                                           JSVM_Value* result) {
33021cb0ef41Sopenharmony_ci  CHECK_ENV(env);
33031cb0ef41Sopenharmony_ci  CHECK_ARG(env, cbinfo);
33041cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
33051cb0ef41Sopenharmony_ci
33061cb0ef41Sopenharmony_ci  v8impl::CallbackWrapper* info =
33071cb0ef41Sopenharmony_ci      reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
33081cb0ef41Sopenharmony_ci
33091cb0ef41Sopenharmony_ci  *result = info->GetNewTarget();
33101cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
33111cb0ef41Sopenharmony_ci}
33121cb0ef41Sopenharmony_ci
33131cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CallFunction(JSVM_Env env,
33141cb0ef41Sopenharmony_ci                                          JSVM_Value recv,
33151cb0ef41Sopenharmony_ci                                          JSVM_Value func,
33161cb0ef41Sopenharmony_ci                                          size_t argc,
33171cb0ef41Sopenharmony_ci                                          const JSVM_Value* argv,
33181cb0ef41Sopenharmony_ci                                          JSVM_Value* result) {
33191cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
33201cb0ef41Sopenharmony_ci  CHECK_ARG(env, recv);
33211cb0ef41Sopenharmony_ci  if (argc > 0) {
33221cb0ef41Sopenharmony_ci    CHECK_ARG(env, argv);
33231cb0ef41Sopenharmony_ci  }
33241cb0ef41Sopenharmony_ci
33251cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
33261cb0ef41Sopenharmony_ci
33271cb0ef41Sopenharmony_ci  v8::Local<v8::Value> v8recv = v8impl::V8LocalValueFromJsValue(recv);
33281cb0ef41Sopenharmony_ci
33291cb0ef41Sopenharmony_ci  v8::Local<v8::Function> v8func;
33301cb0ef41Sopenharmony_ci  CHECK_TO_FUNCTION(env, v8func, func);
33311cb0ef41Sopenharmony_ci
33321cb0ef41Sopenharmony_ci  auto maybe = v8func->Call(
33331cb0ef41Sopenharmony_ci      context,
33341cb0ef41Sopenharmony_ci      v8recv,
33351cb0ef41Sopenharmony_ci      argc,
33361cb0ef41Sopenharmony_ci      reinterpret_cast<v8::Local<v8::Value>*>(const_cast<JSVM_Value*>(argv)));
33371cb0ef41Sopenharmony_ci
33381cb0ef41Sopenharmony_ci  if (try_catch.HasCaught()) {
33391cb0ef41Sopenharmony_ci    return jsvm_set_last_error(env, JSVM_PENDING_EXCEPTION);
33401cb0ef41Sopenharmony_ci  } else {
33411cb0ef41Sopenharmony_ci    if (result != nullptr) {
33421cb0ef41Sopenharmony_ci      CHECK_MAYBE_EMPTY(env, maybe, JSVM_GENERIC_FAILURE);
33431cb0ef41Sopenharmony_ci      *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
33441cb0ef41Sopenharmony_ci    }
33451cb0ef41Sopenharmony_ci    return jsvm_clear_last_error(env);
33461cb0ef41Sopenharmony_ci  }
33471cb0ef41Sopenharmony_ci}
33481cb0ef41Sopenharmony_ci
33491cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetGlobal(JSVM_Env env, JSVM_Value* result) {
33501cb0ef41Sopenharmony_ci  CHECK_ENV(env);
33511cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
33521cb0ef41Sopenharmony_ci
33531cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(env->context()->Global());
33541cb0ef41Sopenharmony_ci
33551cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
33561cb0ef41Sopenharmony_ci}
33571cb0ef41Sopenharmony_ci
33581cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_Throw(JSVM_Env env, JSVM_Value error) {
33591cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
33601cb0ef41Sopenharmony_ci  CHECK_ARG(env, error);
33611cb0ef41Sopenharmony_ci
33621cb0ef41Sopenharmony_ci  v8::Isolate* isolate = env->isolate;
33631cb0ef41Sopenharmony_ci
33641cb0ef41Sopenharmony_ci  isolate->ThrowException(v8impl::V8LocalValueFromJsValue(error));
33651cb0ef41Sopenharmony_ci  // any VM calls after this point and before returning
33661cb0ef41Sopenharmony_ci  // to the javascript invoker will fail
33671cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
33681cb0ef41Sopenharmony_ci}
33691cb0ef41Sopenharmony_ci
33701cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_ThrowError(JSVM_Env env,
33711cb0ef41Sopenharmony_ci                                        const char* code,
33721cb0ef41Sopenharmony_ci                                        const char* msg) {
33731cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
33741cb0ef41Sopenharmony_ci
33751cb0ef41Sopenharmony_ci  v8::Isolate* isolate = env->isolate;
33761cb0ef41Sopenharmony_ci  v8::Local<v8::String> str;
33771cb0ef41Sopenharmony_ci  CHECK_NEW_FROM_UTF8(env, str, msg);
33781cb0ef41Sopenharmony_ci
33791cb0ef41Sopenharmony_ci  v8::Local<v8::Value> error_obj = v8::Exception::Error(str);
33801cb0ef41Sopenharmony_ci  STATUS_CALL(set_error_code(env, error_obj, nullptr, code));
33811cb0ef41Sopenharmony_ci
33821cb0ef41Sopenharmony_ci  isolate->ThrowException(error_obj);
33831cb0ef41Sopenharmony_ci  // any VM calls after this point and before returning
33841cb0ef41Sopenharmony_ci  // to the javascript invoker will fail
33851cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
33861cb0ef41Sopenharmony_ci}
33871cb0ef41Sopenharmony_ci
33881cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_ThrowTypeError(JSVM_Env env,
33891cb0ef41Sopenharmony_ci                                             const char* code,
33901cb0ef41Sopenharmony_ci                                             const char* msg) {
33911cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
33921cb0ef41Sopenharmony_ci
33931cb0ef41Sopenharmony_ci  v8::Isolate* isolate = env->isolate;
33941cb0ef41Sopenharmony_ci  v8::Local<v8::String> str;
33951cb0ef41Sopenharmony_ci  CHECK_NEW_FROM_UTF8(env, str, msg);
33961cb0ef41Sopenharmony_ci
33971cb0ef41Sopenharmony_ci  v8::Local<v8::Value> error_obj = v8::Exception::TypeError(str);
33981cb0ef41Sopenharmony_ci  STATUS_CALL(set_error_code(env, error_obj, nullptr, code));
33991cb0ef41Sopenharmony_ci
34001cb0ef41Sopenharmony_ci  isolate->ThrowException(error_obj);
34011cb0ef41Sopenharmony_ci  // any VM calls after this point and before returning
34021cb0ef41Sopenharmony_ci  // to the javascript invoker will fail
34031cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
34041cb0ef41Sopenharmony_ci}
34051cb0ef41Sopenharmony_ci
34061cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_ThrowRangeError(JSVM_Env env,
34071cb0ef41Sopenharmony_ci                                              const char* code,
34081cb0ef41Sopenharmony_ci                                              const char* msg) {
34091cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
34101cb0ef41Sopenharmony_ci
34111cb0ef41Sopenharmony_ci  v8::Isolate* isolate = env->isolate;
34121cb0ef41Sopenharmony_ci  v8::Local<v8::String> str;
34131cb0ef41Sopenharmony_ci  CHECK_NEW_FROM_UTF8(env, str, msg);
34141cb0ef41Sopenharmony_ci
34151cb0ef41Sopenharmony_ci  v8::Local<v8::Value> error_obj = v8::Exception::RangeError(str);
34161cb0ef41Sopenharmony_ci  STATUS_CALL(set_error_code(env, error_obj, nullptr, code));
34171cb0ef41Sopenharmony_ci
34181cb0ef41Sopenharmony_ci  isolate->ThrowException(error_obj);
34191cb0ef41Sopenharmony_ci  // any VM calls after this point and before returning
34201cb0ef41Sopenharmony_ci  // to the javascript invoker will fail
34211cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
34221cb0ef41Sopenharmony_ci}
34231cb0ef41Sopenharmony_ci
34241cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_ThrowSyntaxError(JSVM_Env env,
34251cb0ef41Sopenharmony_ci                                                   const char* code,
34261cb0ef41Sopenharmony_ci                                                   const char* msg) {
34271cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
34281cb0ef41Sopenharmony_ci
34291cb0ef41Sopenharmony_ci  v8::Isolate* isolate = env->isolate;
34301cb0ef41Sopenharmony_ci  v8::Local<v8::String> str;
34311cb0ef41Sopenharmony_ci  CHECK_NEW_FROM_UTF8(env, str, msg);
34321cb0ef41Sopenharmony_ci
34331cb0ef41Sopenharmony_ci  v8::Local<v8::Value> error_obj = v8::Exception::SyntaxError(str);
34341cb0ef41Sopenharmony_ci  STATUS_CALL(set_error_code(env, error_obj, nullptr, code));
34351cb0ef41Sopenharmony_ci
34361cb0ef41Sopenharmony_ci  isolate->ThrowException(error_obj);
34371cb0ef41Sopenharmony_ci  // any VM calls after this point and before returning
34381cb0ef41Sopenharmony_ci  // to the javascript invoker will fail
34391cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
34401cb0ef41Sopenharmony_ci}
34411cb0ef41Sopenharmony_ci
34421cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsError(JSVM_Env env,
34431cb0ef41Sopenharmony_ci                                     JSVM_Value value,
34441cb0ef41Sopenharmony_ci                                     bool* result) {
34451cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot
34461cb0ef41Sopenharmony_ci  // throw JS exceptions.
34471cb0ef41Sopenharmony_ci  CHECK_ENV(env);
34481cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
34491cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
34501cb0ef41Sopenharmony_ci
34511cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
34521cb0ef41Sopenharmony_ci  *result = val->IsNativeError();
34531cb0ef41Sopenharmony_ci
34541cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
34551cb0ef41Sopenharmony_ci}
34561cb0ef41Sopenharmony_ci
34571cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetValueDouble(JSVM_Env env,
34581cb0ef41Sopenharmony_ci                                             JSVM_Value value,
34591cb0ef41Sopenharmony_ci                                             double* result) {
34601cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
34611cb0ef41Sopenharmony_ci  // JS exceptions.
34621cb0ef41Sopenharmony_ci  CHECK_ENV(env);
34631cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
34641cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
34651cb0ef41Sopenharmony_ci
34661cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
34671cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsNumber(), JSVM_NUMBER_EXPECTED);
34681cb0ef41Sopenharmony_ci
34691cb0ef41Sopenharmony_ci  *result = val.As<v8::Number>()->Value();
34701cb0ef41Sopenharmony_ci
34711cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
34721cb0ef41Sopenharmony_ci}
34731cb0ef41Sopenharmony_ci
34741cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetValueInt32(JSVM_Env env,
34751cb0ef41Sopenharmony_ci                                            JSVM_Value value,
34761cb0ef41Sopenharmony_ci                                            int32_t* result) {
34771cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
34781cb0ef41Sopenharmony_ci  // JS exceptions.
34791cb0ef41Sopenharmony_ci  CHECK_ENV(env);
34801cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
34811cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
34821cb0ef41Sopenharmony_ci
34831cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
34841cb0ef41Sopenharmony_ci
34851cb0ef41Sopenharmony_ci  if (val->IsInt32()) {
34861cb0ef41Sopenharmony_ci    *result = val.As<v8::Int32>()->Value();
34871cb0ef41Sopenharmony_ci  } else {
34881cb0ef41Sopenharmony_ci    RETURN_STATUS_IF_FALSE(env, val->IsNumber(), JSVM_NUMBER_EXPECTED);
34891cb0ef41Sopenharmony_ci
34901cb0ef41Sopenharmony_ci    // Empty context: https://github.com/nodejs/node/issues/14379
34911cb0ef41Sopenharmony_ci    v8::Local<v8::Context> context;
34921cb0ef41Sopenharmony_ci    *result = val->Int32Value(context).FromJust();
34931cb0ef41Sopenharmony_ci  }
34941cb0ef41Sopenharmony_ci
34951cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
34961cb0ef41Sopenharmony_ci}
34971cb0ef41Sopenharmony_ci
34981cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetValueUint32(JSVM_Env env,
34991cb0ef41Sopenharmony_ci                                             JSVM_Value value,
35001cb0ef41Sopenharmony_ci                                             uint32_t* result) {
35011cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
35021cb0ef41Sopenharmony_ci  // JS exceptions.
35031cb0ef41Sopenharmony_ci  CHECK_ENV(env);
35041cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
35051cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
35061cb0ef41Sopenharmony_ci
35071cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
35081cb0ef41Sopenharmony_ci
35091cb0ef41Sopenharmony_ci  if (val->IsUint32()) {
35101cb0ef41Sopenharmony_ci    *result = val.As<v8::Uint32>()->Value();
35111cb0ef41Sopenharmony_ci  } else {
35121cb0ef41Sopenharmony_ci    RETURN_STATUS_IF_FALSE(env, val->IsNumber(), JSVM_NUMBER_EXPECTED);
35131cb0ef41Sopenharmony_ci
35141cb0ef41Sopenharmony_ci    // Empty context: https://github.com/nodejs/node/issues/14379
35151cb0ef41Sopenharmony_ci    v8::Local<v8::Context> context;
35161cb0ef41Sopenharmony_ci    *result = val->Uint32Value(context).FromJust();
35171cb0ef41Sopenharmony_ci  }
35181cb0ef41Sopenharmony_ci
35191cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
35201cb0ef41Sopenharmony_ci}
35211cb0ef41Sopenharmony_ci
35221cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetValueInt64(JSVM_Env env,
35231cb0ef41Sopenharmony_ci                                            JSVM_Value value,
35241cb0ef41Sopenharmony_ci                                            int64_t* result) {
35251cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
35261cb0ef41Sopenharmony_ci  // JS exceptions.
35271cb0ef41Sopenharmony_ci  CHECK_ENV(env);
35281cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
35291cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
35301cb0ef41Sopenharmony_ci
35311cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
35321cb0ef41Sopenharmony_ci
35331cb0ef41Sopenharmony_ci  // This is still a fast path very likely to be taken.
35341cb0ef41Sopenharmony_ci  if (val->IsInt32()) {
35351cb0ef41Sopenharmony_ci    *result = val.As<v8::Int32>()->Value();
35361cb0ef41Sopenharmony_ci    return jsvm_clear_last_error(env);
35371cb0ef41Sopenharmony_ci  }
35381cb0ef41Sopenharmony_ci
35391cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsNumber(), JSVM_NUMBER_EXPECTED);
35401cb0ef41Sopenharmony_ci
35411cb0ef41Sopenharmony_ci  // v8::Value::IntegerValue() converts NaN, +Inf, and -Inf to INT64_MIN,
35421cb0ef41Sopenharmony_ci  // inconsistent with v8::Value::Int32Value() which converts those values to 0.
35431cb0ef41Sopenharmony_ci  // Special-case all non-finite values to match that behavior.
35441cb0ef41Sopenharmony_ci  double doubleValue = val.As<v8::Number>()->Value();
35451cb0ef41Sopenharmony_ci  if (std::isfinite(doubleValue)) {
35461cb0ef41Sopenharmony_ci    // Empty context: https://github.com/nodejs/node/issues/14379
35471cb0ef41Sopenharmony_ci    v8::Local<v8::Context> context;
35481cb0ef41Sopenharmony_ci    *result = val->IntegerValue(context).FromJust();
35491cb0ef41Sopenharmony_ci  } else {
35501cb0ef41Sopenharmony_ci    *result = 0;
35511cb0ef41Sopenharmony_ci  }
35521cb0ef41Sopenharmony_ci
35531cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
35541cb0ef41Sopenharmony_ci}
35551cb0ef41Sopenharmony_ci
35561cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetValueBigintInt64(JSVM_Env env,
35571cb0ef41Sopenharmony_ci                                                   JSVM_Value value,
35581cb0ef41Sopenharmony_ci                                                   int64_t* result,
35591cb0ef41Sopenharmony_ci                                                   bool* lossless) {
35601cb0ef41Sopenharmony_ci  CHECK_ENV(env);
35611cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
35621cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
35631cb0ef41Sopenharmony_ci  CHECK_ARG(env, lossless);
35641cb0ef41Sopenharmony_ci
35651cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
35661cb0ef41Sopenharmony_ci
35671cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), JSVM_BIGINT_EXPECTED);
35681cb0ef41Sopenharmony_ci
35691cb0ef41Sopenharmony_ci  *result = val.As<v8::BigInt>()->Int64Value(lossless);
35701cb0ef41Sopenharmony_ci
35711cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
35721cb0ef41Sopenharmony_ci}
35731cb0ef41Sopenharmony_ci
35741cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetValueBigintUint64(JSVM_Env env,
35751cb0ef41Sopenharmony_ci                                                    JSVM_Value value,
35761cb0ef41Sopenharmony_ci                                                    uint64_t* result,
35771cb0ef41Sopenharmony_ci                                                    bool* lossless) {
35781cb0ef41Sopenharmony_ci  CHECK_ENV(env);
35791cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
35801cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
35811cb0ef41Sopenharmony_ci  CHECK_ARG(env, lossless);
35821cb0ef41Sopenharmony_ci
35831cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
35841cb0ef41Sopenharmony_ci
35851cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), JSVM_BIGINT_EXPECTED);
35861cb0ef41Sopenharmony_ci
35871cb0ef41Sopenharmony_ci  *result = val.As<v8::BigInt>()->Uint64Value(lossless);
35881cb0ef41Sopenharmony_ci
35891cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
35901cb0ef41Sopenharmony_ci}
35911cb0ef41Sopenharmony_ci
35921cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetValueBigintWords(JSVM_Env env,
35931cb0ef41Sopenharmony_ci                                                   JSVM_Value value,
35941cb0ef41Sopenharmony_ci                                                   int* signBit,
35951cb0ef41Sopenharmony_ci                                                   size_t* wordCount,
35961cb0ef41Sopenharmony_ci                                                   uint64_t* words) {
35971cb0ef41Sopenharmony_ci  CHECK_ENV(env);
35981cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
35991cb0ef41Sopenharmony_ci  CHECK_ARG(env, wordCount);
36001cb0ef41Sopenharmony_ci
36011cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
36021cb0ef41Sopenharmony_ci
36031cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), JSVM_BIGINT_EXPECTED);
36041cb0ef41Sopenharmony_ci
36051cb0ef41Sopenharmony_ci  v8::Local<v8::BigInt> big = val.As<v8::BigInt>();
36061cb0ef41Sopenharmony_ci
36071cb0ef41Sopenharmony_ci  int word_count_int = *wordCount;
36081cb0ef41Sopenharmony_ci
36091cb0ef41Sopenharmony_ci  if (signBit == nullptr && words == nullptr) {
36101cb0ef41Sopenharmony_ci    word_count_int = big->WordCount();
36111cb0ef41Sopenharmony_ci  } else {
36121cb0ef41Sopenharmony_ci    CHECK_ARG(env, signBit);
36131cb0ef41Sopenharmony_ci    CHECK_ARG(env, words);
36141cb0ef41Sopenharmony_ci    big->ToWordsArray(signBit, &word_count_int, words);
36151cb0ef41Sopenharmony_ci  }
36161cb0ef41Sopenharmony_ci
36171cb0ef41Sopenharmony_ci  *wordCount = word_count_int;
36181cb0ef41Sopenharmony_ci
36191cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
36201cb0ef41Sopenharmony_ci}
36211cb0ef41Sopenharmony_ci
36221cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetValueBool(JSVM_Env env,
36231cb0ef41Sopenharmony_ci                                           JSVM_Value value,
36241cb0ef41Sopenharmony_ci                                           bool* result) {
36251cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
36261cb0ef41Sopenharmony_ci  // JS exceptions.
36271cb0ef41Sopenharmony_ci  CHECK_ENV(env);
36281cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
36291cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
36301cb0ef41Sopenharmony_ci
36311cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
36321cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsBoolean(), JSVM_BOOLEAN_EXPECTED);
36331cb0ef41Sopenharmony_ci
36341cb0ef41Sopenharmony_ci  *result = val.As<v8::Boolean>()->Value();
36351cb0ef41Sopenharmony_ci
36361cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
36371cb0ef41Sopenharmony_ci}
36381cb0ef41Sopenharmony_ci
36391cb0ef41Sopenharmony_ci// Copies a JavaScript string into a LATIN-1 string buffer. The result is the
36401cb0ef41Sopenharmony_ci// number of bytes (excluding the null terminator) copied into buf.
36411cb0ef41Sopenharmony_ci// A sufficient buffer size should be greater than the length of string,
36421cb0ef41Sopenharmony_ci// reserving space for null terminator.
36431cb0ef41Sopenharmony_ci// If bufsize is insufficient, the string will be truncated and null terminated.
36441cb0ef41Sopenharmony_ci// If buf is NULL, this method returns the length of the string (in bytes)
36451cb0ef41Sopenharmony_ci// via the result parameter.
36461cb0ef41Sopenharmony_ci// The result argument is optional unless buf is NULL.
36471cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetValueStringLatin1(
36481cb0ef41Sopenharmony_ci    JSVM_Env env, JSVM_Value value, char* buf, size_t bufsize, size_t* result) {
36491cb0ef41Sopenharmony_ci  CHECK_ENV(env);
36501cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
36511cb0ef41Sopenharmony_ci
36521cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
36531cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsString(), JSVM_STRING_EXPECTED);
36541cb0ef41Sopenharmony_ci
36551cb0ef41Sopenharmony_ci  if (!buf) {
36561cb0ef41Sopenharmony_ci    CHECK_ARG(env, result);
36571cb0ef41Sopenharmony_ci    *result = val.As<v8::String>()->Length();
36581cb0ef41Sopenharmony_ci  } else if (bufsize != 0) {
36591cb0ef41Sopenharmony_ci    int copied =
36601cb0ef41Sopenharmony_ci        val.As<v8::String>()->WriteOneByte(env->isolate,
36611cb0ef41Sopenharmony_ci                                           reinterpret_cast<uint8_t*>(buf),
36621cb0ef41Sopenharmony_ci                                           0,
36631cb0ef41Sopenharmony_ci                                           bufsize - 1,
36641cb0ef41Sopenharmony_ci                                           v8::String::NO_NULL_TERMINATION);
36651cb0ef41Sopenharmony_ci
36661cb0ef41Sopenharmony_ci    buf[copied] = '\0';
36671cb0ef41Sopenharmony_ci    if (result != nullptr) {
36681cb0ef41Sopenharmony_ci      *result = copied;
36691cb0ef41Sopenharmony_ci    }
36701cb0ef41Sopenharmony_ci  } else if (result != nullptr) {
36711cb0ef41Sopenharmony_ci    *result = 0;
36721cb0ef41Sopenharmony_ci  }
36731cb0ef41Sopenharmony_ci
36741cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
36751cb0ef41Sopenharmony_ci}
36761cb0ef41Sopenharmony_ci
36771cb0ef41Sopenharmony_ci// Copies a JavaScript string into a UTF-8 string buffer. The result is the
36781cb0ef41Sopenharmony_ci// number of bytes (excluding the null terminator) copied into buf.
36791cb0ef41Sopenharmony_ci// A sufficient buffer size should be greater than the length of string,
36801cb0ef41Sopenharmony_ci// reserving space for null terminator.
36811cb0ef41Sopenharmony_ci// If bufsize is insufficient, the string will be truncated and null terminated.
36821cb0ef41Sopenharmony_ci// If buf is NULL, this method returns the length of the string (in bytes)
36831cb0ef41Sopenharmony_ci// via the result parameter.
36841cb0ef41Sopenharmony_ci// The result argument is optional unless buf is NULL.
36851cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetValueStringUtf8(
36861cb0ef41Sopenharmony_ci    JSVM_Env env, JSVM_Value value, char* buf, size_t bufsize, size_t* result) {
36871cb0ef41Sopenharmony_ci  CHECK_ENV(env);
36881cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
36891cb0ef41Sopenharmony_ci
36901cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
36911cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsString(), JSVM_STRING_EXPECTED);
36921cb0ef41Sopenharmony_ci
36931cb0ef41Sopenharmony_ci  if (!buf) {
36941cb0ef41Sopenharmony_ci    CHECK_ARG(env, result);
36951cb0ef41Sopenharmony_ci    *result = val.As<v8::String>()->Utf8Length(env->isolate);
36961cb0ef41Sopenharmony_ci  } else if (bufsize != 0) {
36971cb0ef41Sopenharmony_ci    int copied = val.As<v8::String>()->WriteUtf8(
36981cb0ef41Sopenharmony_ci        env->isolate,
36991cb0ef41Sopenharmony_ci        buf,
37001cb0ef41Sopenharmony_ci        bufsize - 1,
37011cb0ef41Sopenharmony_ci        nullptr,
37021cb0ef41Sopenharmony_ci        v8::String::REPLACE_INVALID_UTF8 | v8::String::NO_NULL_TERMINATION);
37031cb0ef41Sopenharmony_ci
37041cb0ef41Sopenharmony_ci    buf[copied] = '\0';
37051cb0ef41Sopenharmony_ci    if (result != nullptr) {
37061cb0ef41Sopenharmony_ci      *result = copied;
37071cb0ef41Sopenharmony_ci    }
37081cb0ef41Sopenharmony_ci  } else if (result != nullptr) {
37091cb0ef41Sopenharmony_ci    *result = 0;
37101cb0ef41Sopenharmony_ci  }
37111cb0ef41Sopenharmony_ci
37121cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
37131cb0ef41Sopenharmony_ci}
37141cb0ef41Sopenharmony_ci
37151cb0ef41Sopenharmony_ci// Copies a JavaScript string into a UTF-16 string buffer. The result is the
37161cb0ef41Sopenharmony_ci// number of 2-byte code units (excluding the null terminator) copied into buf.
37171cb0ef41Sopenharmony_ci// A sufficient buffer size should be greater than the length of string,
37181cb0ef41Sopenharmony_ci// reserving space for null terminator.
37191cb0ef41Sopenharmony_ci// If bufsize is insufficient, the string will be truncated and null terminated.
37201cb0ef41Sopenharmony_ci// If buf is NULL, this method returns the length of the string (in 2-byte
37211cb0ef41Sopenharmony_ci// code units) via the result parameter.
37221cb0ef41Sopenharmony_ci// The result argument is optional unless buf is NULL.
37231cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetValueStringUtf16(JSVM_Env env,
37241cb0ef41Sopenharmony_ci                                                   JSVM_Value value,
37251cb0ef41Sopenharmony_ci                                                   char16_t* buf,
37261cb0ef41Sopenharmony_ci                                                   size_t bufsize,
37271cb0ef41Sopenharmony_ci                                                   size_t* result) {
37281cb0ef41Sopenharmony_ci  CHECK_ENV(env);
37291cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
37301cb0ef41Sopenharmony_ci
37311cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
37321cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsString(), JSVM_STRING_EXPECTED);
37331cb0ef41Sopenharmony_ci
37341cb0ef41Sopenharmony_ci  if (!buf) {
37351cb0ef41Sopenharmony_ci    CHECK_ARG(env, result);
37361cb0ef41Sopenharmony_ci    // V8 assumes UTF-16 length is the same as the number of characters.
37371cb0ef41Sopenharmony_ci    *result = val.As<v8::String>()->Length();
37381cb0ef41Sopenharmony_ci  } else if (bufsize != 0) {
37391cb0ef41Sopenharmony_ci    int copied = val.As<v8::String>()->Write(env->isolate,
37401cb0ef41Sopenharmony_ci                                             reinterpret_cast<uint16_t*>(buf),
37411cb0ef41Sopenharmony_ci                                             0,
37421cb0ef41Sopenharmony_ci                                             bufsize - 1,
37431cb0ef41Sopenharmony_ci                                             v8::String::NO_NULL_TERMINATION);
37441cb0ef41Sopenharmony_ci
37451cb0ef41Sopenharmony_ci    buf[copied] = '\0';
37461cb0ef41Sopenharmony_ci    if (result != nullptr) {
37471cb0ef41Sopenharmony_ci      *result = copied;
37481cb0ef41Sopenharmony_ci    }
37491cb0ef41Sopenharmony_ci  } else if (result != nullptr) {
37501cb0ef41Sopenharmony_ci    *result = 0;
37511cb0ef41Sopenharmony_ci  }
37521cb0ef41Sopenharmony_ci
37531cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
37541cb0ef41Sopenharmony_ci}
37551cb0ef41Sopenharmony_ci
37561cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CoerceToBool(JSVM_Env env,
37571cb0ef41Sopenharmony_ci                                           JSVM_Value value,
37581cb0ef41Sopenharmony_ci                                           JSVM_Value* result) {
37591cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
37601cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
37611cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
37621cb0ef41Sopenharmony_ci
37631cb0ef41Sopenharmony_ci  v8::Isolate* isolate = env->isolate;
37641cb0ef41Sopenharmony_ci  v8::Local<v8::Boolean> b =
37651cb0ef41Sopenharmony_ci      v8impl::V8LocalValueFromJsValue(value)->ToBoolean(isolate);
37661cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(b);
37671cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
37681cb0ef41Sopenharmony_ci}
37691cb0ef41Sopenharmony_ci
37701cb0ef41Sopenharmony_ci#define GEN_COERCE_FUNCTION(UpperCaseName, MixedCaseName, LowerCaseName)       \
37711cb0ef41Sopenharmony_ci  JSVM_Status JSVM_CDECL OH_JSVM_CoerceTo##MixedCaseName(                       \
37721cb0ef41Sopenharmony_ci      JSVM_Env env, JSVM_Value value, JSVM_Value* result) {                    \
37731cb0ef41Sopenharmony_ci    JSVM_PREAMBLE(env);                                                        \
37741cb0ef41Sopenharmony_ci    CHECK_ARG(env, value);                                                     \
37751cb0ef41Sopenharmony_ci    CHECK_ARG(env, result);                                                    \
37761cb0ef41Sopenharmony_ci                                                                               \
37771cb0ef41Sopenharmony_ci    v8::Local<v8::Context> context = env->context();                           \
37781cb0ef41Sopenharmony_ci    v8::Local<v8::MixedCaseName> str;                                          \
37791cb0ef41Sopenharmony_ci                                                                               \
37801cb0ef41Sopenharmony_ci    CHECK_TO_##UpperCaseName(env, context, str, value);                        \
37811cb0ef41Sopenharmony_ci                                                                               \
37821cb0ef41Sopenharmony_ci    *result = v8impl::JsValueFromV8LocalValue(str);                            \
37831cb0ef41Sopenharmony_ci    return GET_RETURN_STATUS(env);                                             \
37841cb0ef41Sopenharmony_ci  }
37851cb0ef41Sopenharmony_ci
37861cb0ef41Sopenharmony_ciGEN_COERCE_FUNCTION(NUMBER, Number, number)
37871cb0ef41Sopenharmony_ciGEN_COERCE_FUNCTION(OBJECT, Object, object)
37881cb0ef41Sopenharmony_ciGEN_COERCE_FUNCTION(STRING, String, string)
37891cb0ef41Sopenharmony_ciGEN_COERCE_FUNCTION(BIGINT, BigInt, bigint)
37901cb0ef41Sopenharmony_ci
37911cb0ef41Sopenharmony_ci#undef GEN_COERCE_FUNCTION
37921cb0ef41Sopenharmony_ci
37931cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_Wrap(JSVM_Env env,
37941cb0ef41Sopenharmony_ci                                 JSVM_Value jsObject,
37951cb0ef41Sopenharmony_ci                                 void* nativeObject,
37961cb0ef41Sopenharmony_ci                                 JSVM_Finalize finalizeCb,
37971cb0ef41Sopenharmony_ci                                 void* finalizeHint,
37981cb0ef41Sopenharmony_ci                                 JSVM_Ref* result) {
37991cb0ef41Sopenharmony_ci  return v8impl::Wrap(
38001cb0ef41Sopenharmony_ci      env, jsObject, nativeObject, finalizeCb, finalizeHint, result);
38011cb0ef41Sopenharmony_ci}
38021cb0ef41Sopenharmony_ci
38031cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_Unwrap(JSVM_Env env,
38041cb0ef41Sopenharmony_ci                                   JSVM_Value obj,
38051cb0ef41Sopenharmony_ci                                   void** result) {
38061cb0ef41Sopenharmony_ci  return v8impl::Unwrap(env, obj, result, v8impl::KeepWrap);
38071cb0ef41Sopenharmony_ci}
38081cb0ef41Sopenharmony_ci
38091cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_RemoveWrap(JSVM_Env env,
38101cb0ef41Sopenharmony_ci                                        JSVM_Value obj,
38111cb0ef41Sopenharmony_ci                                        void** result) {
38121cb0ef41Sopenharmony_ci  return v8impl::Unwrap(env, obj, result, v8impl::RemoveWrap);
38131cb0ef41Sopenharmony_ci}
38141cb0ef41Sopenharmony_ci
38151cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateExternal(JSVM_Env env,
38161cb0ef41Sopenharmony_ci                                            void* data,
38171cb0ef41Sopenharmony_ci                                            JSVM_Finalize finalizeCb,
38181cb0ef41Sopenharmony_ci                                            void* finalizeHint,
38191cb0ef41Sopenharmony_ci                                            JSVM_Value* result) {
38201cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
38211cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
38221cb0ef41Sopenharmony_ci
38231cb0ef41Sopenharmony_ci  v8::Isolate* isolate = env->isolate;
38241cb0ef41Sopenharmony_ci
38251cb0ef41Sopenharmony_ci  v8::Local<v8::Value> external_value = v8::External::New(isolate, data);
38261cb0ef41Sopenharmony_ci
38271cb0ef41Sopenharmony_ci  if (finalizeCb) {
38281cb0ef41Sopenharmony_ci    // The Reference object will delete itself after invoking the finalizer
38291cb0ef41Sopenharmony_ci    // callback.
38301cb0ef41Sopenharmony_ci    v8impl::Reference::New(env,
38311cb0ef41Sopenharmony_ci                           external_value,
38321cb0ef41Sopenharmony_ci                           0,
38331cb0ef41Sopenharmony_ci                           v8impl::Ownership::kRuntime,
38341cb0ef41Sopenharmony_ci                           finalizeCb,
38351cb0ef41Sopenharmony_ci                           data,
38361cb0ef41Sopenharmony_ci                           finalizeHint);
38371cb0ef41Sopenharmony_ci  }
38381cb0ef41Sopenharmony_ci
38391cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(external_value);
38401cb0ef41Sopenharmony_ci
38411cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
38421cb0ef41Sopenharmony_ci}
38431cb0ef41Sopenharmony_ci
38441cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_TypeTagObject(JSVM_Env env,
38451cb0ef41Sopenharmony_ci                                            JSVM_Value object,
38461cb0ef41Sopenharmony_ci                                            const JSVM_TypeTag* typeTag) {
38471cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
38481cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
38491cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
38501cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT_WITH_PREAMBLE(env, context, obj, object);
38511cb0ef41Sopenharmony_ci  CHECK_ARG_WITH_PREAMBLE(env, typeTag);
38521cb0ef41Sopenharmony_ci
38531cb0ef41Sopenharmony_ci  auto key = JSVM_PRIVATE_KEY(env->isolate, type_tag);
38541cb0ef41Sopenharmony_ci  auto maybe_has = obj->HasPrivate(context, key);
38551cb0ef41Sopenharmony_ci  CHECK_MAYBE_NOTHING_WITH_PREAMBLE(env, maybe_has, JSVM_GENERIC_FAILURE);
38561cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(
38571cb0ef41Sopenharmony_ci      env, !maybe_has.FromJust(), JSVM_INVALID_ARG);
38581cb0ef41Sopenharmony_ci
38591cb0ef41Sopenharmony_ci  auto tag = v8::BigInt::NewFromWords(
38601cb0ef41Sopenharmony_ci      context, 0, 2, reinterpret_cast<const uint64_t*>(typeTag));
38611cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, tag, JSVM_GENERIC_FAILURE);
38621cb0ef41Sopenharmony_ci
38631cb0ef41Sopenharmony_ci  auto maybe_set = obj->SetPrivate(context, key, tag.ToLocalChecked());
38641cb0ef41Sopenharmony_ci  CHECK_MAYBE_NOTHING_WITH_PREAMBLE(env, maybe_set, JSVM_GENERIC_FAILURE);
38651cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(
38661cb0ef41Sopenharmony_ci      env, maybe_set.FromJust(), JSVM_GENERIC_FAILURE);
38671cb0ef41Sopenharmony_ci
38681cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
38691cb0ef41Sopenharmony_ci}
38701cb0ef41Sopenharmony_ci
38711cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CheckObjectTypeTag(JSVM_Env env,
38721cb0ef41Sopenharmony_ci                                                  JSVM_Value object,
38731cb0ef41Sopenharmony_ci                                                  const JSVM_TypeTag* typeTag,
38741cb0ef41Sopenharmony_ci                                                  bool* result) {
38751cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
38761cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
38771cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
38781cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT_WITH_PREAMBLE(env, context, obj, object);
38791cb0ef41Sopenharmony_ci  CHECK_ARG_WITH_PREAMBLE(env, typeTag);
38801cb0ef41Sopenharmony_ci  CHECK_ARG_WITH_PREAMBLE(env, result);
38811cb0ef41Sopenharmony_ci
38821cb0ef41Sopenharmony_ci  auto maybe_value =
38831cb0ef41Sopenharmony_ci      obj->GetPrivate(context, JSVM_PRIVATE_KEY(env->isolate, type_tag));
38841cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, maybe_value, JSVM_GENERIC_FAILURE);
38851cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = maybe_value.ToLocalChecked();
38861cb0ef41Sopenharmony_ci
38871cb0ef41Sopenharmony_ci  // We consider the type check to have failed unless we reach the line below
38881cb0ef41Sopenharmony_ci  // where we set whether the type check succeeded or not based on the
38891cb0ef41Sopenharmony_ci  // comparison of the two type tags.
38901cb0ef41Sopenharmony_ci  *result = false;
38911cb0ef41Sopenharmony_ci  if (val->IsBigInt()) {
38921cb0ef41Sopenharmony_ci    int sign;
38931cb0ef41Sopenharmony_ci    int size = 2;
38941cb0ef41Sopenharmony_ci    JSVM_TypeTag tag;
38951cb0ef41Sopenharmony_ci    val.As<v8::BigInt>()->ToWordsArray(
38961cb0ef41Sopenharmony_ci        &sign, &size, reinterpret_cast<uint64_t*>(&tag));
38971cb0ef41Sopenharmony_ci    if (sign == 0) {
38981cb0ef41Sopenharmony_ci      if (size == 2) {
38991cb0ef41Sopenharmony_ci        *result =
39001cb0ef41Sopenharmony_ci            (tag.lower == typeTag->lower && tag.upper == typeTag->upper);
39011cb0ef41Sopenharmony_ci      } else if (size == 1) {
39021cb0ef41Sopenharmony_ci        *result = (tag.lower == typeTag->lower && 0 == typeTag->upper);
39031cb0ef41Sopenharmony_ci      } else if (size == 0) {
39041cb0ef41Sopenharmony_ci        *result = (0 == typeTag->lower && 0 == typeTag->upper);
39051cb0ef41Sopenharmony_ci      }
39061cb0ef41Sopenharmony_ci    }
39071cb0ef41Sopenharmony_ci  }
39081cb0ef41Sopenharmony_ci
39091cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
39101cb0ef41Sopenharmony_ci}
39111cb0ef41Sopenharmony_ci
39121cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetValueExternal(JSVM_Env env,
39131cb0ef41Sopenharmony_ci                                               JSVM_Value value,
39141cb0ef41Sopenharmony_ci                                               void** result) {
39151cb0ef41Sopenharmony_ci  CHECK_ENV(env);
39161cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
39171cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
39181cb0ef41Sopenharmony_ci
39191cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
39201cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsExternal(), JSVM_INVALID_ARG);
39211cb0ef41Sopenharmony_ci
39221cb0ef41Sopenharmony_ci  v8::Local<v8::External> external_value = val.As<v8::External>();
39231cb0ef41Sopenharmony_ci  *result = external_value->Value();
39241cb0ef41Sopenharmony_ci
39251cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
39261cb0ef41Sopenharmony_ci}
39271cb0ef41Sopenharmony_ci
39281cb0ef41Sopenharmony_ci// Set initialRefcount to 0 for a weak reference, >0 for a strong reference.
39291cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateReference(JSVM_Env env,
39301cb0ef41Sopenharmony_ci                                             JSVM_Value value,
39311cb0ef41Sopenharmony_ci                                             uint32_t initialRefcount,
39321cb0ef41Sopenharmony_ci                                             JSVM_Ref* result) {
39331cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
39341cb0ef41Sopenharmony_ci  // JS exceptions.
39351cb0ef41Sopenharmony_ci  CHECK_ENV(env);
39361cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
39371cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
39381cb0ef41Sopenharmony_ci
39391cb0ef41Sopenharmony_ci  v8::Local<v8::Value> v8_value = v8impl::V8LocalValueFromJsValue(value);
39401cb0ef41Sopenharmony_ci  v8impl::Reference* reference = v8impl::Reference::New(
39411cb0ef41Sopenharmony_ci      env, v8_value, initialRefcount, v8impl::Ownership::kUserland);
39421cb0ef41Sopenharmony_ci
39431cb0ef41Sopenharmony_ci  *result = reinterpret_cast<JSVM_Ref>(reference);
39441cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
39451cb0ef41Sopenharmony_ci}
39461cb0ef41Sopenharmony_ci
39471cb0ef41Sopenharmony_ci// Deletes a reference. The referenced value is released, and may be GC'd unless
39481cb0ef41Sopenharmony_ci// there are other references to it.
39491cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_DeleteReference(JSVM_Env env, JSVM_Ref ref) {
39501cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
39511cb0ef41Sopenharmony_ci  // JS exceptions.
39521cb0ef41Sopenharmony_ci  CHECK_ENV(env);
39531cb0ef41Sopenharmony_ci  CHECK_ARG(env, ref);
39541cb0ef41Sopenharmony_ci
39551cb0ef41Sopenharmony_ci  reinterpret_cast<v8impl::Reference*>(ref)->Delete();
39561cb0ef41Sopenharmony_ci
39571cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
39581cb0ef41Sopenharmony_ci}
39591cb0ef41Sopenharmony_ci
39601cb0ef41Sopenharmony_ci// Increments the reference count, optionally returning the resulting count.
39611cb0ef41Sopenharmony_ci// After this call the reference will be a strong reference because its
39621cb0ef41Sopenharmony_ci// refcount is >0, and the referenced object is effectively "pinned".
39631cb0ef41Sopenharmony_ci// Calling this when the refcount is 0 and the object is unavailable
39641cb0ef41Sopenharmony_ci// results in an error.
39651cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_ReferenceRef(JSVM_Env env,
39661cb0ef41Sopenharmony_ci                                          JSVM_Ref ref,
39671cb0ef41Sopenharmony_ci                                          uint32_t* result) {
39681cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
39691cb0ef41Sopenharmony_ci  // JS exceptions.
39701cb0ef41Sopenharmony_ci  CHECK_ENV(env);
39711cb0ef41Sopenharmony_ci  CHECK_ARG(env, ref);
39721cb0ef41Sopenharmony_ci
39731cb0ef41Sopenharmony_ci  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
39741cb0ef41Sopenharmony_ci  if (reference->HasDeletedByUser()) {
39751cb0ef41Sopenharmony_ci    return jsvm_set_last_error(env, JSVM_GENERIC_FAILURE);
39761cb0ef41Sopenharmony_ci  }
39771cb0ef41Sopenharmony_ci  uint32_t count = reference->Ref();
39781cb0ef41Sopenharmony_ci
39791cb0ef41Sopenharmony_ci  if (result != nullptr) {
39801cb0ef41Sopenharmony_ci    *result = count;
39811cb0ef41Sopenharmony_ci  }
39821cb0ef41Sopenharmony_ci
39831cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
39841cb0ef41Sopenharmony_ci}
39851cb0ef41Sopenharmony_ci
39861cb0ef41Sopenharmony_ci// Decrements the reference count, optionally returning the resulting count. If
39871cb0ef41Sopenharmony_ci// the result is 0 the reference is now weak and the object may be GC'd at any
39881cb0ef41Sopenharmony_ci// time if there are no other references. Calling this when the refcount is
39891cb0ef41Sopenharmony_ci// already 0 results in an error.
39901cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_ReferenceUnref(JSVM_Env env,
39911cb0ef41Sopenharmony_ci                                            JSVM_Ref ref,
39921cb0ef41Sopenharmony_ci                                            uint32_t* result) {
39931cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
39941cb0ef41Sopenharmony_ci  // JS exceptions.
39951cb0ef41Sopenharmony_ci  CHECK_ENV(env);
39961cb0ef41Sopenharmony_ci  CHECK_ARG(env, ref);
39971cb0ef41Sopenharmony_ci
39981cb0ef41Sopenharmony_ci  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
39991cb0ef41Sopenharmony_ci
40001cb0ef41Sopenharmony_ci  if (reference->RefCount() == 0 || reference->HasDeletedByUser()) {
40011cb0ef41Sopenharmony_ci    return jsvm_set_last_error(env, JSVM_GENERIC_FAILURE);
40021cb0ef41Sopenharmony_ci  }
40031cb0ef41Sopenharmony_ci
40041cb0ef41Sopenharmony_ci  uint32_t count = reference->Unref();
40051cb0ef41Sopenharmony_ci
40061cb0ef41Sopenharmony_ci  if (result != nullptr) {
40071cb0ef41Sopenharmony_ci    *result = count;
40081cb0ef41Sopenharmony_ci  }
40091cb0ef41Sopenharmony_ci
40101cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
40111cb0ef41Sopenharmony_ci}
40121cb0ef41Sopenharmony_ci
40131cb0ef41Sopenharmony_ci// Attempts to get a referenced value. If the reference is weak, the value might
40141cb0ef41Sopenharmony_ci// no longer be available, in that case the call is still successful but the
40151cb0ef41Sopenharmony_ci// result is NULL.
40161cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetReferenceValue(JSVM_Env env,
40171cb0ef41Sopenharmony_ci                                                JSVM_Ref ref,
40181cb0ef41Sopenharmony_ci                                                JSVM_Value* result) {
40191cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
40201cb0ef41Sopenharmony_ci  // JS exceptions.
40211cb0ef41Sopenharmony_ci  CHECK_ENV(env);
40221cb0ef41Sopenharmony_ci  CHECK_ARG(env, ref);
40231cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
40241cb0ef41Sopenharmony_ci
40251cb0ef41Sopenharmony_ci  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
40261cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(reference->Get());
40271cb0ef41Sopenharmony_ci
40281cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
40291cb0ef41Sopenharmony_ci}
40301cb0ef41Sopenharmony_ci
40311cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_OpenHandleScope(JSVM_Env env,
40321cb0ef41Sopenharmony_ci                                              JSVM_HandleScope* result) {
40331cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
40341cb0ef41Sopenharmony_ci  // JS exceptions.
40351cb0ef41Sopenharmony_ci  CHECK_ENV(env);
40361cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
40371cb0ef41Sopenharmony_ci
40381cb0ef41Sopenharmony_ci  *result = v8impl::JsHandleScopeFromV8HandleScope(
40391cb0ef41Sopenharmony_ci      new v8impl::HandleScopeWrapper(env->isolate));
40401cb0ef41Sopenharmony_ci  env->open_handle_scopes++;
40411cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
40421cb0ef41Sopenharmony_ci}
40431cb0ef41Sopenharmony_ci
40441cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CloseHandleScope(JSVM_Env env,
40451cb0ef41Sopenharmony_ci                                               JSVM_HandleScope scope) {
40461cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
40471cb0ef41Sopenharmony_ci  // JS exceptions.
40481cb0ef41Sopenharmony_ci  CHECK_ENV(env);
40491cb0ef41Sopenharmony_ci  CHECK_ARG(env, scope);
40501cb0ef41Sopenharmony_ci  if (env->open_handle_scopes == 0) {
40511cb0ef41Sopenharmony_ci    return JSVM_HANDLE_SCOPE_MISMATCH;
40521cb0ef41Sopenharmony_ci  }
40531cb0ef41Sopenharmony_ci
40541cb0ef41Sopenharmony_ci  env->ReleaseJsvmData();
40551cb0ef41Sopenharmony_ci  env->open_handle_scopes--;
40561cb0ef41Sopenharmony_ci  delete v8impl::V8HandleScopeFromJsHandleScope(scope);
40571cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
40581cb0ef41Sopenharmony_ci}
40591cb0ef41Sopenharmony_ci
40601cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_OpenEscapableHandleScope(
40611cb0ef41Sopenharmony_ci    JSVM_Env env, JSVM_EscapableHandleScope* result) {
40621cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
40631cb0ef41Sopenharmony_ci  // JS exceptions.
40641cb0ef41Sopenharmony_ci  CHECK_ENV(env);
40651cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
40661cb0ef41Sopenharmony_ci
40671cb0ef41Sopenharmony_ci  *result = v8impl::JsEscapableHandleScopeFromV8EscapableHandleScope(
40681cb0ef41Sopenharmony_ci      new v8impl::EscapableHandleScopeWrapper(env->isolate));
40691cb0ef41Sopenharmony_ci  env->open_handle_scopes++;
40701cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
40711cb0ef41Sopenharmony_ci}
40721cb0ef41Sopenharmony_ci
40731cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CloseEscapableHandleScope(
40741cb0ef41Sopenharmony_ci    JSVM_Env env, JSVM_EscapableHandleScope scope) {
40751cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
40761cb0ef41Sopenharmony_ci  // JS exceptions.
40771cb0ef41Sopenharmony_ci  CHECK_ENV(env);
40781cb0ef41Sopenharmony_ci  CHECK_ARG(env, scope);
40791cb0ef41Sopenharmony_ci  if (env->open_handle_scopes == 0) {
40801cb0ef41Sopenharmony_ci    return JSVM_HANDLE_SCOPE_MISMATCH;
40811cb0ef41Sopenharmony_ci  }
40821cb0ef41Sopenharmony_ci
40831cb0ef41Sopenharmony_ci  delete v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope);
40841cb0ef41Sopenharmony_ci  env->open_handle_scopes--;
40851cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
40861cb0ef41Sopenharmony_ci}
40871cb0ef41Sopenharmony_ci
40881cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_EscapeHandle(JSVM_Env env,
40891cb0ef41Sopenharmony_ci                                          JSVM_EscapableHandleScope scope,
40901cb0ef41Sopenharmony_ci                                          JSVM_Value escapee,
40911cb0ef41Sopenharmony_ci                                          JSVM_Value* result) {
40921cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
40931cb0ef41Sopenharmony_ci  // JS exceptions.
40941cb0ef41Sopenharmony_ci  CHECK_ENV(env);
40951cb0ef41Sopenharmony_ci  CHECK_ARG(env, scope);
40961cb0ef41Sopenharmony_ci  CHECK_ARG(env, escapee);
40971cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
40981cb0ef41Sopenharmony_ci
40991cb0ef41Sopenharmony_ci  v8impl::EscapableHandleScopeWrapper* s =
41001cb0ef41Sopenharmony_ci      v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope);
41011cb0ef41Sopenharmony_ci  if (!s->escape_called()) {
41021cb0ef41Sopenharmony_ci    *result = v8impl::JsValueFromV8LocalValue(
41031cb0ef41Sopenharmony_ci        s->Escape(v8impl::V8LocalValueFromJsValue(escapee)));
41041cb0ef41Sopenharmony_ci    return jsvm_clear_last_error(env);
41051cb0ef41Sopenharmony_ci  }
41061cb0ef41Sopenharmony_ci  return jsvm_set_last_error(env, JSVM_ESCAPE_CALLED_TWICE);
41071cb0ef41Sopenharmony_ci}
41081cb0ef41Sopenharmony_ci
41091cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_NewInstance(JSVM_Env env,
41101cb0ef41Sopenharmony_ci                                         JSVM_Value constructor,
41111cb0ef41Sopenharmony_ci                                         size_t argc,
41121cb0ef41Sopenharmony_ci                                         const JSVM_Value* argv,
41131cb0ef41Sopenharmony_ci                                         JSVM_Value* result) {
41141cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
41151cb0ef41Sopenharmony_ci  CHECK_ARG(env, constructor);
41161cb0ef41Sopenharmony_ci  if (argc > 0) {
41171cb0ef41Sopenharmony_ci    CHECK_ARG(env, argv);
41181cb0ef41Sopenharmony_ci  }
41191cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
41201cb0ef41Sopenharmony_ci
41211cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
41221cb0ef41Sopenharmony_ci
41231cb0ef41Sopenharmony_ci  v8::Local<v8::Function> ctor;
41241cb0ef41Sopenharmony_ci  CHECK_TO_FUNCTION(env, ctor, constructor);
41251cb0ef41Sopenharmony_ci
41261cb0ef41Sopenharmony_ci  auto maybe = ctor->NewInstance(
41271cb0ef41Sopenharmony_ci      context,
41281cb0ef41Sopenharmony_ci      argc,
41291cb0ef41Sopenharmony_ci      reinterpret_cast<v8::Local<v8::Value>*>(const_cast<JSVM_Value*>(argv)));
41301cb0ef41Sopenharmony_ci
41311cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, maybe, JSVM_PENDING_EXCEPTION);
41321cb0ef41Sopenharmony_ci
41331cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
41341cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
41351cb0ef41Sopenharmony_ci}
41361cb0ef41Sopenharmony_ci
41371cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_Instanceof(JSVM_Env env,
41381cb0ef41Sopenharmony_ci                                       JSVM_Value object,
41391cb0ef41Sopenharmony_ci                                       JSVM_Value constructor,
41401cb0ef41Sopenharmony_ci                                       bool* result) {
41411cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
41421cb0ef41Sopenharmony_ci  CHECK_ARG(env, object);
41431cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
41441cb0ef41Sopenharmony_ci
41451cb0ef41Sopenharmony_ci  *result = false;
41461cb0ef41Sopenharmony_ci
41471cb0ef41Sopenharmony_ci  v8::Local<v8::Object> ctor;
41481cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
41491cb0ef41Sopenharmony_ci
41501cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, ctor, constructor);
41511cb0ef41Sopenharmony_ci
41521cb0ef41Sopenharmony_ci  if (!ctor->IsFunction()) {
41531cb0ef41Sopenharmony_ci    OH_JSVM_ThrowTypeError(
41541cb0ef41Sopenharmony_ci        env, "ERR_NAPI_CONS_FUNCTION", "Constructor must be a function");
41551cb0ef41Sopenharmony_ci
41561cb0ef41Sopenharmony_ci    return jsvm_set_last_error(env, JSVM_FUNCTION_EXPECTED);
41571cb0ef41Sopenharmony_ci  }
41581cb0ef41Sopenharmony_ci
41591cb0ef41Sopenharmony_ci  JSVM_Status status = JSVM_GENERIC_FAILURE;
41601cb0ef41Sopenharmony_ci
41611cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(object);
41621cb0ef41Sopenharmony_ci  auto maybe_result = val->InstanceOf(context, ctor);
41631cb0ef41Sopenharmony_ci  CHECK_MAYBE_NOTHING(env, maybe_result, status);
41641cb0ef41Sopenharmony_ci  *result = maybe_result.FromJust();
41651cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
41661cb0ef41Sopenharmony_ci}
41671cb0ef41Sopenharmony_ci
41681cb0ef41Sopenharmony_ci// Methods to support catching exceptions
41691cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsExceptionPending(JSVM_Env env, bool* result) {
41701cb0ef41Sopenharmony_ci  // JSVM_PREAMBLE is not used here: this function must execute when there is a
41711cb0ef41Sopenharmony_ci  // pending exception.
41721cb0ef41Sopenharmony_ci  CHECK_ENV(env);
41731cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
41741cb0ef41Sopenharmony_ci
41751cb0ef41Sopenharmony_ci  *result = !env->last_exception.IsEmpty();
41761cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
41771cb0ef41Sopenharmony_ci}
41781cb0ef41Sopenharmony_ci
41791cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetAndClearLastException(JSVM_Env env,
41801cb0ef41Sopenharmony_ci                                                         JSVM_Value* result) {
41811cb0ef41Sopenharmony_ci  // JSVM_PREAMBLE is not used here: this function must execute when there is a
41821cb0ef41Sopenharmony_ci  // pending exception.
41831cb0ef41Sopenharmony_ci  CHECK_ENV(env);
41841cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
41851cb0ef41Sopenharmony_ci
41861cb0ef41Sopenharmony_ci  if (env->last_exception.IsEmpty()) {
41871cb0ef41Sopenharmony_ci    return OH_JSVM_GetUndefined(env, result);
41881cb0ef41Sopenharmony_ci  } else {
41891cb0ef41Sopenharmony_ci    *result = v8impl::JsValueFromV8LocalValue(
41901cb0ef41Sopenharmony_ci        v8::Local<v8::Value>::New(env->isolate, env->last_exception));
41911cb0ef41Sopenharmony_ci    env->last_exception.Reset();
41921cb0ef41Sopenharmony_ci  }
41931cb0ef41Sopenharmony_ci
41941cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
41951cb0ef41Sopenharmony_ci}
41961cb0ef41Sopenharmony_ci
41971cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsArraybuffer(JSVM_Env env,
41981cb0ef41Sopenharmony_ci                                           JSVM_Value value,
41991cb0ef41Sopenharmony_ci                                           bool* result) {
42001cb0ef41Sopenharmony_ci  CHECK_ENV(env);
42011cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
42021cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
42031cb0ef41Sopenharmony_ci
42041cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
42051cb0ef41Sopenharmony_ci  *result = val->IsArrayBuffer();
42061cb0ef41Sopenharmony_ci
42071cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
42081cb0ef41Sopenharmony_ci}
42091cb0ef41Sopenharmony_ci
42101cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateArraybuffer(JSVM_Env env,
42111cb0ef41Sopenharmony_ci                                               size_t byteLength,
42121cb0ef41Sopenharmony_ci                                               void** data,
42131cb0ef41Sopenharmony_ci                                               JSVM_Value* result) {
42141cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
42151cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
42161cb0ef41Sopenharmony_ci
42171cb0ef41Sopenharmony_ci  v8::Isolate* isolate = env->isolate;
42181cb0ef41Sopenharmony_ci  v8::Local<v8::ArrayBuffer> buffer =
42191cb0ef41Sopenharmony_ci      v8::ArrayBuffer::New(isolate, byteLength);
42201cb0ef41Sopenharmony_ci
42211cb0ef41Sopenharmony_ci  // Optionally return a pointer to the buffer's data, to avoid another call to
42221cb0ef41Sopenharmony_ci  // retrieve it.
42231cb0ef41Sopenharmony_ci  if (data != nullptr) {
42241cb0ef41Sopenharmony_ci    *data = buffer->Data();
42251cb0ef41Sopenharmony_ci  }
42261cb0ef41Sopenharmony_ci
42271cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(buffer);
42281cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
42291cb0ef41Sopenharmony_ci}
42301cb0ef41Sopenharmony_ci
42311cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_AllocateArrayBufferBackingStoreData(size_t byteLength,
42321cb0ef41Sopenharmony_ci                                                                   JSVM_InitializedFlag initialized,
42331cb0ef41Sopenharmony_ci                                                                   void **data) {
42341cb0ef41Sopenharmony_ci  if (!data) {
42351cb0ef41Sopenharmony_ci    return JSVM_INVALID_ARG;
42361cb0ef41Sopenharmony_ci  }
42371cb0ef41Sopenharmony_ci  auto allocator = v8impl::GetOrCreateDefaultArrayBufferAllocator();
42381cb0ef41Sopenharmony_ci  *data = (initialized == JSVM_ZERO_INITIALIZED) ?
42391cb0ef41Sopenharmony_ci    allocator->Allocate(byteLength) :
42401cb0ef41Sopenharmony_ci    allocator->AllocateUninitialized(byteLength);
42411cb0ef41Sopenharmony_ci  return *data ? JSVM_OK : JSVM_GENERIC_FAILURE;
42421cb0ef41Sopenharmony_ci}
42431cb0ef41Sopenharmony_ci
42441cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_FreeArrayBufferBackingStoreData(void *data) {
42451cb0ef41Sopenharmony_ci  if (!data) {
42461cb0ef41Sopenharmony_ci    return JSVM_INVALID_ARG;
42471cb0ef41Sopenharmony_ci  }
42481cb0ef41Sopenharmony_ci  auto allocator = v8impl::GetOrCreateDefaultArrayBufferAllocator();
42491cb0ef41Sopenharmony_ci  allocator->Free(data, JSVM_AUTO_LENGTH);
42501cb0ef41Sopenharmony_ci  return JSVM_OK;
42511cb0ef41Sopenharmony_ci}
42521cb0ef41Sopenharmony_ci
42531cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateArrayBufferFromBackingStoreData(JSVM_Env env,
42541cb0ef41Sopenharmony_ci                                                                     void *data,
42551cb0ef41Sopenharmony_ci                                                                     size_t backingStoreSize,
42561cb0ef41Sopenharmony_ci                                                                     size_t offset,
42571cb0ef41Sopenharmony_ci                                                                     size_t arrayBufferSize,
42581cb0ef41Sopenharmony_ci                                                                     JSVM_Value *result) {
42591cb0ef41Sopenharmony_ci  CHECK_ENV(env);
42601cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
42611cb0ef41Sopenharmony_ci  CHECK_ARG(env, data);
42621cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
42631cb0ef41Sopenharmony_ci  CHECK_ARG_NOT_ZERO(env, backingStoreSize);
42641cb0ef41Sopenharmony_ci  CHECK_ARG_NOT_ZERO(env, arrayBufferSize);
42651cb0ef41Sopenharmony_ci  void *dataPtr = static_cast<uint8_t*>(data) + offset;
42661cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, offset + arrayBufferSize <= backingStoreSize, JSVM_INVALID_ARG);
42671cb0ef41Sopenharmony_ci  auto backingStore = v8::ArrayBuffer::NewBackingStore(
42681cb0ef41Sopenharmony_ci    dataPtr, arrayBufferSize, v8::BackingStore::EmptyDeleter, nullptr);
42691cb0ef41Sopenharmony_ci  v8::Local<v8::ArrayBuffer> arrayBuffer =
42701cb0ef41Sopenharmony_ci    v8::ArrayBuffer::New(env->isolate, std::move(backingStore));
42711cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(arrayBuffer);
42721cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
42731cb0ef41Sopenharmony_ci}
42741cb0ef41Sopenharmony_ci
42751cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
42761cb0ef41Sopenharmony_ciOH_JSVM_CreateExternalArraybuffer(JSVM_Env env,
42771cb0ef41Sopenharmony_ci                                 void* externalData,
42781cb0ef41Sopenharmony_ci                                 size_t byteLength,
42791cb0ef41Sopenharmony_ci                                 JSVM_Finalize finalizeCb,
42801cb0ef41Sopenharmony_ci                                 void* finalizeHint,
42811cb0ef41Sopenharmony_ci                                 JSVM_Value* result) {
42821cb0ef41Sopenharmony_ci  // The API contract here is that the cleanup function runs on the JS thread,
42831cb0ef41Sopenharmony_ci  // and is able to use JSVM_Env. Implementing that properly is hard, so use the
42841cb0ef41Sopenharmony_ci  // `Buffer` variant for easier implementation.
42851cb0ef41Sopenharmony_ci  JSVM_Value buffer;
42861cb0ef41Sopenharmony_ci  STATUS_CALL(OH_JSVM_CreateExternal_buffer(
42871cb0ef41Sopenharmony_ci      env, byteLength, externalData, finalizeCb, finalizeHint, &buffer));
42881cb0ef41Sopenharmony_ci  return OH_JSVM_GetTypedarrayInfo(
42891cb0ef41Sopenharmony_ci      env, buffer, nullptr, nullptr, nullptr, result, nullptr);
42901cb0ef41Sopenharmony_ci}
42911cb0ef41Sopenharmony_ci
42921cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetArraybufferInfo(JSVM_Env env,
42931cb0ef41Sopenharmony_ci                                                 JSVM_Value arraybuffer,
42941cb0ef41Sopenharmony_ci                                                 void** data,
42951cb0ef41Sopenharmony_ci                                                 size_t* byteLength) {
42961cb0ef41Sopenharmony_ci  CHECK_ENV(env);
42971cb0ef41Sopenharmony_ci  CHECK_ARG(env, arraybuffer);
42981cb0ef41Sopenharmony_ci
42991cb0ef41Sopenharmony_ci  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
43001cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), JSVM_INVALID_ARG);
43011cb0ef41Sopenharmony_ci
43021cb0ef41Sopenharmony_ci  v8::Local<v8::ArrayBuffer> ab = value.As<v8::ArrayBuffer>();
43031cb0ef41Sopenharmony_ci
43041cb0ef41Sopenharmony_ci  if (data != nullptr) {
43051cb0ef41Sopenharmony_ci    *data = ab->Data();
43061cb0ef41Sopenharmony_ci  }
43071cb0ef41Sopenharmony_ci
43081cb0ef41Sopenharmony_ci  if (byteLength != nullptr) {
43091cb0ef41Sopenharmony_ci    *byteLength = ab->ByteLength();
43101cb0ef41Sopenharmony_ci  }
43111cb0ef41Sopenharmony_ci
43121cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
43131cb0ef41Sopenharmony_ci}
43141cb0ef41Sopenharmony_ci
43151cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsTypedarray(JSVM_Env env,
43161cb0ef41Sopenharmony_ci                                          JSVM_Value value,
43171cb0ef41Sopenharmony_ci                                          bool* result) {
43181cb0ef41Sopenharmony_ci  CHECK_ENV(env);
43191cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
43201cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
43211cb0ef41Sopenharmony_ci
43221cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
43231cb0ef41Sopenharmony_ci  *result = val->IsTypedArray();
43241cb0ef41Sopenharmony_ci
43251cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
43261cb0ef41Sopenharmony_ci}
43271cb0ef41Sopenharmony_ci
43281cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateTypedarray(JSVM_Env env,
43291cb0ef41Sopenharmony_ci                                              JSVM_TypedarrayType type,
43301cb0ef41Sopenharmony_ci                                              size_t length,
43311cb0ef41Sopenharmony_ci                                              JSVM_Value arraybuffer,
43321cb0ef41Sopenharmony_ci                                              size_t byteOffset,
43331cb0ef41Sopenharmony_ci                                              JSVM_Value* result) {
43341cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
43351cb0ef41Sopenharmony_ci  CHECK_ARG(env, arraybuffer);
43361cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
43371cb0ef41Sopenharmony_ci
43381cb0ef41Sopenharmony_ci  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
43391cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), JSVM_INVALID_ARG);
43401cb0ef41Sopenharmony_ci
43411cb0ef41Sopenharmony_ci  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
43421cb0ef41Sopenharmony_ci  v8::Local<v8::TypedArray> typedArray;
43431cb0ef41Sopenharmony_ci
43441cb0ef41Sopenharmony_ci  switch (type) {
43451cb0ef41Sopenharmony_ci    case JSVM_INT8_ARRAY:
43461cb0ef41Sopenharmony_ci      CREATE_TYPED_ARRAY(
43471cb0ef41Sopenharmony_ci          env, Int8Array, 1, buffer, byteOffset, length, typedArray);
43481cb0ef41Sopenharmony_ci      break;
43491cb0ef41Sopenharmony_ci    case JSVM_UINT8_ARRAY:
43501cb0ef41Sopenharmony_ci      CREATE_TYPED_ARRAY(
43511cb0ef41Sopenharmony_ci          env, Uint8Array, 1, buffer, byteOffset, length, typedArray);
43521cb0ef41Sopenharmony_ci      break;
43531cb0ef41Sopenharmony_ci    case JSVM_UINT8_CLAMPED_ARRAY:
43541cb0ef41Sopenharmony_ci      CREATE_TYPED_ARRAY(
43551cb0ef41Sopenharmony_ci          env, Uint8ClampedArray, 1, buffer, byteOffset, length, typedArray);
43561cb0ef41Sopenharmony_ci      break;
43571cb0ef41Sopenharmony_ci    case JSVM_INT16_ARRAY:
43581cb0ef41Sopenharmony_ci      CREATE_TYPED_ARRAY(
43591cb0ef41Sopenharmony_ci          env, Int16Array, 2, buffer, byteOffset, length, typedArray);
43601cb0ef41Sopenharmony_ci      break;
43611cb0ef41Sopenharmony_ci    case JSVM_UINT16_ARRAY:
43621cb0ef41Sopenharmony_ci      CREATE_TYPED_ARRAY(
43631cb0ef41Sopenharmony_ci          env, Uint16Array, 2, buffer, byteOffset, length, typedArray);
43641cb0ef41Sopenharmony_ci      break;
43651cb0ef41Sopenharmony_ci    case JSVM_INT32_ARRAY:
43661cb0ef41Sopenharmony_ci      CREATE_TYPED_ARRAY(
43671cb0ef41Sopenharmony_ci          env, Int32Array, 4, buffer, byteOffset, length, typedArray);
43681cb0ef41Sopenharmony_ci      break;
43691cb0ef41Sopenharmony_ci    case JSVM_UINT32_ARRAY:
43701cb0ef41Sopenharmony_ci      CREATE_TYPED_ARRAY(
43711cb0ef41Sopenharmony_ci          env, Uint32Array, 4, buffer, byteOffset, length, typedArray);
43721cb0ef41Sopenharmony_ci      break;
43731cb0ef41Sopenharmony_ci    case JSVM_FLOAT32_ARRAY:
43741cb0ef41Sopenharmony_ci      CREATE_TYPED_ARRAY(
43751cb0ef41Sopenharmony_ci          env, Float32Array, 4, buffer, byteOffset, length, typedArray);
43761cb0ef41Sopenharmony_ci      break;
43771cb0ef41Sopenharmony_ci    case JSVM_FLOAT64_ARRAY:
43781cb0ef41Sopenharmony_ci      CREATE_TYPED_ARRAY(
43791cb0ef41Sopenharmony_ci          env, Float64Array, 8, buffer, byteOffset, length, typedArray);
43801cb0ef41Sopenharmony_ci      break;
43811cb0ef41Sopenharmony_ci    case JSVM_BIGINT64_ARRAY:
43821cb0ef41Sopenharmony_ci      CREATE_TYPED_ARRAY(
43831cb0ef41Sopenharmony_ci          env, BigInt64Array, 8, buffer, byteOffset, length, typedArray);
43841cb0ef41Sopenharmony_ci      break;
43851cb0ef41Sopenharmony_ci    case JSVM_BIGUINT64_ARRAY:
43861cb0ef41Sopenharmony_ci      CREATE_TYPED_ARRAY(
43871cb0ef41Sopenharmony_ci          env, BigUint64Array, 8, buffer, byteOffset, length, typedArray);
43881cb0ef41Sopenharmony_ci      break;
43891cb0ef41Sopenharmony_ci    default:
43901cb0ef41Sopenharmony_ci      return jsvm_set_last_error(env, JSVM_INVALID_ARG);
43911cb0ef41Sopenharmony_ci  }
43921cb0ef41Sopenharmony_ci
43931cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(typedArray);
43941cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
43951cb0ef41Sopenharmony_ci}
43961cb0ef41Sopenharmony_ci
43971cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetTypedarrayInfo(JSVM_Env env,
43981cb0ef41Sopenharmony_ci                                                JSVM_Value typedarray,
43991cb0ef41Sopenharmony_ci                                                JSVM_TypedarrayType* type,
44001cb0ef41Sopenharmony_ci                                                size_t* length,
44011cb0ef41Sopenharmony_ci                                                void** data,
44021cb0ef41Sopenharmony_ci                                                JSVM_Value* arraybuffer,
44031cb0ef41Sopenharmony_ci                                                size_t* byteOffset) {
44041cb0ef41Sopenharmony_ci  CHECK_ENV(env);
44051cb0ef41Sopenharmony_ci  CHECK_ARG(env, typedarray);
44061cb0ef41Sopenharmony_ci
44071cb0ef41Sopenharmony_ci  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(typedarray);
44081cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, value->IsTypedArray(), JSVM_INVALID_ARG);
44091cb0ef41Sopenharmony_ci
44101cb0ef41Sopenharmony_ci  v8::Local<v8::TypedArray> array = value.As<v8::TypedArray>();
44111cb0ef41Sopenharmony_ci
44121cb0ef41Sopenharmony_ci  if (type != nullptr) {
44131cb0ef41Sopenharmony_ci    if (value->IsInt8Array()) {
44141cb0ef41Sopenharmony_ci      *type = JSVM_INT8_ARRAY;
44151cb0ef41Sopenharmony_ci    } else if (value->IsUint8Array()) {
44161cb0ef41Sopenharmony_ci      *type = JSVM_UINT8_ARRAY;
44171cb0ef41Sopenharmony_ci    } else if (value->IsUint8ClampedArray()) {
44181cb0ef41Sopenharmony_ci      *type = JSVM_UINT8_CLAMPED_ARRAY;
44191cb0ef41Sopenharmony_ci    } else if (value->IsInt16Array()) {
44201cb0ef41Sopenharmony_ci      *type = JSVM_INT16_ARRAY;
44211cb0ef41Sopenharmony_ci    } else if (value->IsUint16Array()) {
44221cb0ef41Sopenharmony_ci      *type = JSVM_UINT16_ARRAY;
44231cb0ef41Sopenharmony_ci    } else if (value->IsInt32Array()) {
44241cb0ef41Sopenharmony_ci      *type = JSVM_INT32_ARRAY;
44251cb0ef41Sopenharmony_ci    } else if (value->IsUint32Array()) {
44261cb0ef41Sopenharmony_ci      *type = JSVM_UINT32_ARRAY;
44271cb0ef41Sopenharmony_ci    } else if (value->IsFloat32Array()) {
44281cb0ef41Sopenharmony_ci      *type = JSVM_FLOAT32_ARRAY;
44291cb0ef41Sopenharmony_ci    } else if (value->IsFloat64Array()) {
44301cb0ef41Sopenharmony_ci      *type = JSVM_FLOAT64_ARRAY;
44311cb0ef41Sopenharmony_ci    } else if (value->IsBigInt64Array()) {
44321cb0ef41Sopenharmony_ci      *type = JSVM_BIGINT64_ARRAY;
44331cb0ef41Sopenharmony_ci    } else if (value->IsBigUint64Array()) {
44341cb0ef41Sopenharmony_ci      *type = JSVM_BIGUINT64_ARRAY;
44351cb0ef41Sopenharmony_ci    }
44361cb0ef41Sopenharmony_ci  }
44371cb0ef41Sopenharmony_ci
44381cb0ef41Sopenharmony_ci  if (length != nullptr) {
44391cb0ef41Sopenharmony_ci    *length = array->Length();
44401cb0ef41Sopenharmony_ci  }
44411cb0ef41Sopenharmony_ci
44421cb0ef41Sopenharmony_ci  v8::Local<v8::ArrayBuffer> buffer;
44431cb0ef41Sopenharmony_ci  if (data != nullptr || arraybuffer != nullptr) {
44441cb0ef41Sopenharmony_ci    // Calling Buffer() may have the side effect of allocating the buffer,
44451cb0ef41Sopenharmony_ci    // so only do this when it's needed.
44461cb0ef41Sopenharmony_ci    buffer = array->Buffer();
44471cb0ef41Sopenharmony_ci  }
44481cb0ef41Sopenharmony_ci
44491cb0ef41Sopenharmony_ci  if (data != nullptr) {
44501cb0ef41Sopenharmony_ci    *data = static_cast<uint8_t*>(buffer->Data()) + array->ByteOffset();
44511cb0ef41Sopenharmony_ci  }
44521cb0ef41Sopenharmony_ci
44531cb0ef41Sopenharmony_ci  if (arraybuffer != nullptr) {
44541cb0ef41Sopenharmony_ci    *arraybuffer = v8impl::JsValueFromV8LocalValue(buffer);
44551cb0ef41Sopenharmony_ci  }
44561cb0ef41Sopenharmony_ci
44571cb0ef41Sopenharmony_ci  if (byteOffset != nullptr) {
44581cb0ef41Sopenharmony_ci    *byteOffset = array->ByteOffset();
44591cb0ef41Sopenharmony_ci  }
44601cb0ef41Sopenharmony_ci
44611cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
44621cb0ef41Sopenharmony_ci}
44631cb0ef41Sopenharmony_ci
44641cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateDataview(JSVM_Env env,
44651cb0ef41Sopenharmony_ci                                            size_t byteLength,
44661cb0ef41Sopenharmony_ci                                            JSVM_Value arraybuffer,
44671cb0ef41Sopenharmony_ci                                            size_t byteOffset,
44681cb0ef41Sopenharmony_ci                                            JSVM_Value* result) {
44691cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
44701cb0ef41Sopenharmony_ci  CHECK_ARG(env, arraybuffer);
44711cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
44721cb0ef41Sopenharmony_ci
44731cb0ef41Sopenharmony_ci  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
44741cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), JSVM_INVALID_ARG);
44751cb0ef41Sopenharmony_ci
44761cb0ef41Sopenharmony_ci  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
44771cb0ef41Sopenharmony_ci  if (byteLength + byteOffset > buffer->ByteLength()) {
44781cb0ef41Sopenharmony_ci    OH_JSVM_ThrowRangeError(env,
44791cb0ef41Sopenharmony_ci                           "ERR_JSVM_INVALID_DATAVIEW_ARGS",
44801cb0ef41Sopenharmony_ci                           "byteOffset + byteLength should be less than or "
44811cb0ef41Sopenharmony_ci                           "equal to the size in bytes of the array passed in");
44821cb0ef41Sopenharmony_ci    return jsvm_set_last_error(env, JSVM_PENDING_EXCEPTION);
44831cb0ef41Sopenharmony_ci  }
44841cb0ef41Sopenharmony_ci  v8::Local<v8::DataView> DataView =
44851cb0ef41Sopenharmony_ci      v8::DataView::New(buffer, byteOffset, byteLength);
44861cb0ef41Sopenharmony_ci
44871cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(DataView);
44881cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
44891cb0ef41Sopenharmony_ci}
44901cb0ef41Sopenharmony_ci
44911cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsDataview(JSVM_Env env,
44921cb0ef41Sopenharmony_ci                                        JSVM_Value value,
44931cb0ef41Sopenharmony_ci                                        bool* result) {
44941cb0ef41Sopenharmony_ci  CHECK_ENV(env);
44951cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
44961cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
44971cb0ef41Sopenharmony_ci
44981cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
44991cb0ef41Sopenharmony_ci  *result = val->IsDataView();
45001cb0ef41Sopenharmony_ci
45011cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
45021cb0ef41Sopenharmony_ci}
45031cb0ef41Sopenharmony_ci
45041cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetDataviewInfo(JSVM_Env env,
45051cb0ef41Sopenharmony_ci                                              JSVM_Value dataview,
45061cb0ef41Sopenharmony_ci                                              size_t* byteLength,
45071cb0ef41Sopenharmony_ci                                              void** data,
45081cb0ef41Sopenharmony_ci                                              JSVM_Value* arraybuffer,
45091cb0ef41Sopenharmony_ci                                              size_t* byteOffset) {
45101cb0ef41Sopenharmony_ci  CHECK_ENV(env);
45111cb0ef41Sopenharmony_ci  CHECK_ARG(env, dataview);
45121cb0ef41Sopenharmony_ci
45131cb0ef41Sopenharmony_ci  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(dataview);
45141cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, value->IsDataView(), JSVM_INVALID_ARG);
45151cb0ef41Sopenharmony_ci
45161cb0ef41Sopenharmony_ci  v8::Local<v8::DataView> array = value.As<v8::DataView>();
45171cb0ef41Sopenharmony_ci
45181cb0ef41Sopenharmony_ci  if (byteLength != nullptr) {
45191cb0ef41Sopenharmony_ci    *byteLength = array->ByteLength();
45201cb0ef41Sopenharmony_ci  }
45211cb0ef41Sopenharmony_ci
45221cb0ef41Sopenharmony_ci  v8::Local<v8::ArrayBuffer> buffer;
45231cb0ef41Sopenharmony_ci  if (data != nullptr || arraybuffer != nullptr) {
45241cb0ef41Sopenharmony_ci    // Calling Buffer() may have the side effect of allocating the buffer,
45251cb0ef41Sopenharmony_ci    // so only do this when it's needed.
45261cb0ef41Sopenharmony_ci    buffer = array->Buffer();
45271cb0ef41Sopenharmony_ci  }
45281cb0ef41Sopenharmony_ci
45291cb0ef41Sopenharmony_ci  if (data != nullptr) {
45301cb0ef41Sopenharmony_ci    *data = static_cast<uint8_t*>(buffer->Data()) + array->ByteOffset();
45311cb0ef41Sopenharmony_ci  }
45321cb0ef41Sopenharmony_ci
45331cb0ef41Sopenharmony_ci  if (arraybuffer != nullptr) {
45341cb0ef41Sopenharmony_ci    *arraybuffer = v8impl::JsValueFromV8LocalValue(buffer);
45351cb0ef41Sopenharmony_ci  }
45361cb0ef41Sopenharmony_ci
45371cb0ef41Sopenharmony_ci  if (byteOffset != nullptr) {
45381cb0ef41Sopenharmony_ci    *byteOffset = array->ByteOffset();
45391cb0ef41Sopenharmony_ci  }
45401cb0ef41Sopenharmony_ci
45411cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
45421cb0ef41Sopenharmony_ci}
45431cb0ef41Sopenharmony_ci
45441cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetVersion(JSVM_Env env, uint32_t* result) {
45451cb0ef41Sopenharmony_ci  CHECK_ENV(env);
45461cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
45471cb0ef41Sopenharmony_ci  *result = NAPI_VERSION;
45481cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
45491cb0ef41Sopenharmony_ci}
45501cb0ef41Sopenharmony_ci
45511cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreatePromise(JSVM_Env env,
45521cb0ef41Sopenharmony_ci                                           JSVM_Deferred* deferred,
45531cb0ef41Sopenharmony_ci                                           JSVM_Value* promise) {
45541cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
45551cb0ef41Sopenharmony_ci  CHECK_ARG(env, deferred);
45561cb0ef41Sopenharmony_ci  CHECK_ARG(env, promise);
45571cb0ef41Sopenharmony_ci
45581cb0ef41Sopenharmony_ci  auto maybe = v8::Promise::Resolver::New(env->context());
45591cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, maybe, JSVM_GENERIC_FAILURE);
45601cb0ef41Sopenharmony_ci
45611cb0ef41Sopenharmony_ci  auto v8_resolver = maybe.ToLocalChecked();
45621cb0ef41Sopenharmony_ci  auto v8_deferred = new v8impl::Persistent<v8::Value>();
45631cb0ef41Sopenharmony_ci  v8_deferred->Reset(env->isolate, v8_resolver);
45641cb0ef41Sopenharmony_ci
45651cb0ef41Sopenharmony_ci  *deferred = v8impl::JsDeferredFromNodePersistent(v8_deferred);
45661cb0ef41Sopenharmony_ci  *promise = v8impl::JsValueFromV8LocalValue(v8_resolver->GetPromise());
45671cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
45681cb0ef41Sopenharmony_ci}
45691cb0ef41Sopenharmony_ci
45701cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_ResolveDeferred(JSVM_Env env,
45711cb0ef41Sopenharmony_ci                                             JSVM_Deferred deferred,
45721cb0ef41Sopenharmony_ci                                             JSVM_Value resolution) {
45731cb0ef41Sopenharmony_ci  return v8impl::ConcludeDeferred(env, deferred, resolution, true);
45741cb0ef41Sopenharmony_ci}
45751cb0ef41Sopenharmony_ci
45761cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_RejectDeferred(JSVM_Env env,
45771cb0ef41Sopenharmony_ci                                            JSVM_Deferred deferred,
45781cb0ef41Sopenharmony_ci                                            JSVM_Value resolution) {
45791cb0ef41Sopenharmony_ci  return v8impl::ConcludeDeferred(env, deferred, resolution, false);
45801cb0ef41Sopenharmony_ci}
45811cb0ef41Sopenharmony_ci
45821cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsPromise(JSVM_Env env,
45831cb0ef41Sopenharmony_ci                                       JSVM_Value value,
45841cb0ef41Sopenharmony_ci                                       bool* is_promise) {
45851cb0ef41Sopenharmony_ci  CHECK_ENV(env);
45861cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
45871cb0ef41Sopenharmony_ci  CHECK_ARG(env, is_promise);
45881cb0ef41Sopenharmony_ci
45891cb0ef41Sopenharmony_ci  *is_promise = v8impl::V8LocalValueFromJsValue(value)->IsPromise();
45901cb0ef41Sopenharmony_ci
45911cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
45921cb0ef41Sopenharmony_ci}
45931cb0ef41Sopenharmony_ci
45941cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateDate(JSVM_Env env,
45951cb0ef41Sopenharmony_ci                                        double time,
45961cb0ef41Sopenharmony_ci                                        JSVM_Value* result) {
45971cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
45981cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
45991cb0ef41Sopenharmony_ci
46001cb0ef41Sopenharmony_ci  v8::MaybeLocal<v8::Value> maybe_date = v8::Date::New(env->context(), time);
46011cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, maybe_date, JSVM_GENERIC_FAILURE);
46021cb0ef41Sopenharmony_ci
46031cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(maybe_date.ToLocalChecked());
46041cb0ef41Sopenharmony_ci
46051cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
46061cb0ef41Sopenharmony_ci}
46071cb0ef41Sopenharmony_ci
46081cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsDate(JSVM_Env env,
46091cb0ef41Sopenharmony_ci                                    JSVM_Value value,
46101cb0ef41Sopenharmony_ci                                    bool* isDate) {
46111cb0ef41Sopenharmony_ci  CHECK_ENV(env);
46121cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
46131cb0ef41Sopenharmony_ci  CHECK_ARG(env, isDate);
46141cb0ef41Sopenharmony_ci
46151cb0ef41Sopenharmony_ci  *isDate = v8impl::V8LocalValueFromJsValue(value)->IsDate();
46161cb0ef41Sopenharmony_ci
46171cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
46181cb0ef41Sopenharmony_ci}
46191cb0ef41Sopenharmony_ci
46201cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetDateValue(JSVM_Env env,
46211cb0ef41Sopenharmony_ci                                           JSVM_Value value,
46221cb0ef41Sopenharmony_ci                                           double* result) {
46231cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
46241cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
46251cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
46261cb0ef41Sopenharmony_ci
46271cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
46281cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsDate(), JSVM_DATE_EXPECTED);
46291cb0ef41Sopenharmony_ci
46301cb0ef41Sopenharmony_ci  v8::Local<v8::Date> date = val.As<v8::Date>();
46311cb0ef41Sopenharmony_ci  *result = date->ValueOf();
46321cb0ef41Sopenharmony_ci
46331cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
46341cb0ef41Sopenharmony_ci}
46351cb0ef41Sopenharmony_ci
46361cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_AddFinalizer(JSVM_Env env,
46371cb0ef41Sopenharmony_ci                                          JSVM_Value jsObject,
46381cb0ef41Sopenharmony_ci                                          void* finalizeData,
46391cb0ef41Sopenharmony_ci                                          JSVM_Finalize finalizeCb,
46401cb0ef41Sopenharmony_ci                                          void* finalizeHint,
46411cb0ef41Sopenharmony_ci                                          JSVM_Ref* result) {
46421cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
46431cb0ef41Sopenharmony_ci  // JS exceptions.
46441cb0ef41Sopenharmony_ci  CHECK_ENV(env);
46451cb0ef41Sopenharmony_ci  CHECK_ARG(env, jsObject);
46461cb0ef41Sopenharmony_ci  CHECK_ARG(env, finalizeCb);
46471cb0ef41Sopenharmony_ci
46481cb0ef41Sopenharmony_ci  v8::Local<v8::Value> v8_value = v8impl::V8LocalValueFromJsValue(jsObject);
46491cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, v8_value->IsObject(), JSVM_INVALID_ARG);
46501cb0ef41Sopenharmony_ci
46511cb0ef41Sopenharmony_ci  // Create a self-deleting reference if the optional out-param result is not
46521cb0ef41Sopenharmony_ci  // set.
46531cb0ef41Sopenharmony_ci  v8impl::Ownership ownership = result == nullptr
46541cb0ef41Sopenharmony_ci                                    ? v8impl::Ownership::kRuntime
46551cb0ef41Sopenharmony_ci                                    : v8impl::Ownership::kUserland;
46561cb0ef41Sopenharmony_ci  v8impl::Reference* reference = v8impl::Reference::New(
46571cb0ef41Sopenharmony_ci      env, v8_value, 0, ownership, finalizeCb, finalizeData, finalizeHint);
46581cb0ef41Sopenharmony_ci
46591cb0ef41Sopenharmony_ci  if (result != nullptr) {
46601cb0ef41Sopenharmony_ci    *result = reinterpret_cast<JSVM_Ref>(reference);
46611cb0ef41Sopenharmony_ci  }
46621cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
46631cb0ef41Sopenharmony_ci}
46641cb0ef41Sopenharmony_ci
46651cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_AdjustExternalMemory(JSVM_Env env,
46661cb0ef41Sopenharmony_ci                                                   int64_t changeInBytes,
46671cb0ef41Sopenharmony_ci                                                   int64_t* adjustedValue) {
46681cb0ef41Sopenharmony_ci  CHECK_ENV(env);
46691cb0ef41Sopenharmony_ci  CHECK_ARG(env, adjustedValue);
46701cb0ef41Sopenharmony_ci
46711cb0ef41Sopenharmony_ci  *adjustedValue =
46721cb0ef41Sopenharmony_ci      env->isolate->AdjustAmountOfExternalAllocatedMemory(changeInBytes);
46731cb0ef41Sopenharmony_ci
46741cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
46751cb0ef41Sopenharmony_ci}
46761cb0ef41Sopenharmony_ci
46771cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_SetInstanceData(JSVM_Env env,
46781cb0ef41Sopenharmony_ci                                              void* data,
46791cb0ef41Sopenharmony_ci                                              JSVM_Finalize finalizeCb,
46801cb0ef41Sopenharmony_ci                                              void* finalizeHint) {
46811cb0ef41Sopenharmony_ci  CHECK_ENV(env);
46821cb0ef41Sopenharmony_ci
46831cb0ef41Sopenharmony_ci  v8impl::RefBase* old_data = static_cast<v8impl::RefBase*>(env->instance_data);
46841cb0ef41Sopenharmony_ci  if (old_data != nullptr) {
46851cb0ef41Sopenharmony_ci    // Our contract so far has been to not finalize any old data there may be.
46861cb0ef41Sopenharmony_ci    // So we simply delete it.
46871cb0ef41Sopenharmony_ci    delete old_data;
46881cb0ef41Sopenharmony_ci  }
46891cb0ef41Sopenharmony_ci
46901cb0ef41Sopenharmony_ci  env->instance_data = v8impl::RefBase::New(
46911cb0ef41Sopenharmony_ci      env, 0, v8impl::Ownership::kRuntime, finalizeCb, data, finalizeHint);
46921cb0ef41Sopenharmony_ci
46931cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
46941cb0ef41Sopenharmony_ci}
46951cb0ef41Sopenharmony_ci
46961cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_GetInstanceData(JSVM_Env env, void** data) {
46971cb0ef41Sopenharmony_ci  CHECK_ENV(env);
46981cb0ef41Sopenharmony_ci  CHECK_ARG(env, data);
46991cb0ef41Sopenharmony_ci
47001cb0ef41Sopenharmony_ci  v8impl::RefBase* idata = static_cast<v8impl::RefBase*>(env->instance_data);
47011cb0ef41Sopenharmony_ci
47021cb0ef41Sopenharmony_ci  *data = (idata == nullptr ? nullptr : idata->Data());
47031cb0ef41Sopenharmony_ci
47041cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
47051cb0ef41Sopenharmony_ci}
47061cb0ef41Sopenharmony_ci
47071cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_DetachArraybuffer(JSVM_Env env,
47081cb0ef41Sopenharmony_ci                                                 JSVM_Value arraybuffer) {
47091cb0ef41Sopenharmony_ci  CHECK_ENV(env);
47101cb0ef41Sopenharmony_ci  CHECK_ARG(env, arraybuffer);
47111cb0ef41Sopenharmony_ci
47121cb0ef41Sopenharmony_ci  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
47131cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(
47141cb0ef41Sopenharmony_ci      env, value->IsArrayBuffer() || value->IsSharedArrayBuffer(), JSVM_ARRAYBUFFER_EXPECTED);
47151cb0ef41Sopenharmony_ci
47161cb0ef41Sopenharmony_ci  v8::Local<v8::ArrayBuffer> it = value.As<v8::ArrayBuffer>();
47171cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(
47181cb0ef41Sopenharmony_ci      env, it->IsDetachable(), JSVM_DETACHABLE_ARRAYBUFFER_EXPECTED);
47191cb0ef41Sopenharmony_ci
47201cb0ef41Sopenharmony_ci  it->Detach();
47211cb0ef41Sopenharmony_ci
47221cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
47231cb0ef41Sopenharmony_ci}
47241cb0ef41Sopenharmony_ci
47251cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsDetachedArraybuffer(JSVM_Env env,
47261cb0ef41Sopenharmony_ci                                                    JSVM_Value arraybuffer,
47271cb0ef41Sopenharmony_ci                                                    bool* result) {
47281cb0ef41Sopenharmony_ci  CHECK_ENV(env);
47291cb0ef41Sopenharmony_ci  CHECK_ARG(env, arraybuffer);
47301cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
47311cb0ef41Sopenharmony_ci
47321cb0ef41Sopenharmony_ci  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
47331cb0ef41Sopenharmony_ci
47341cb0ef41Sopenharmony_ci  *result =
47351cb0ef41Sopenharmony_ci      value->IsArrayBuffer() && value.As<v8::ArrayBuffer>()->WasDetached();
47361cb0ef41Sopenharmony_ci
47371cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
47381cb0ef41Sopenharmony_ci}
47391cb0ef41Sopenharmony_ci
47401cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL
47411cb0ef41Sopenharmony_ciOH_JSVM_DefineClassWithPropertyHandler(JSVM_Env env,
47421cb0ef41Sopenharmony_ci                                       const char* utf8name,
47431cb0ef41Sopenharmony_ci                                       size_t length,
47441cb0ef41Sopenharmony_ci                                       JSVM_Callback constructor,
47451cb0ef41Sopenharmony_ci                                       size_t propertyCount,
47461cb0ef41Sopenharmony_ci                                       const JSVM_PropertyDescriptor* properties,
47471cb0ef41Sopenharmony_ci                                       JSVM_PropertyHandlerCfg propertyHandlerCfg,
47481cb0ef41Sopenharmony_ci                                       JSVM_Callback callAsFunctionCallback,
47491cb0ef41Sopenharmony_ci                                       JSVM_Value* result) {
47501cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
47511cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
47521cb0ef41Sopenharmony_ci  CHECK_ARG(env, constructor);
47531cb0ef41Sopenharmony_ci  CHECK_ARG(env, constructor->callback);
47541cb0ef41Sopenharmony_ci  CHECK_ARG(env, propertyHandlerCfg);
47551cb0ef41Sopenharmony_ci
47561cb0ef41Sopenharmony_ci  if (propertyCount > 0) {
47571cb0ef41Sopenharmony_ci    CHECK_ARG(env, properties);
47581cb0ef41Sopenharmony_ci  }
47591cb0ef41Sopenharmony_ci
47601cb0ef41Sopenharmony_ci  v8::Isolate* isolate = env->isolate;
47611cb0ef41Sopenharmony_ci  v8::EscapableHandleScope scope(isolate);
47621cb0ef41Sopenharmony_ci  v8::Local<v8::FunctionTemplate> tpl;
47631cb0ef41Sopenharmony_ci  STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
47641cb0ef41Sopenharmony_ci      env, constructor, &tpl));
47651cb0ef41Sopenharmony_ci
47661cb0ef41Sopenharmony_ci  v8::Local<v8::String> name_string;
47671cb0ef41Sopenharmony_ci  CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
47681cb0ef41Sopenharmony_ci  tpl->SetClassName(name_string);
47691cb0ef41Sopenharmony_ci
47701cb0ef41Sopenharmony_ci  size_t static_property_count = 0;
47711cb0ef41Sopenharmony_ci  for (size_t i = 0; i < propertyCount; i++) {
47721cb0ef41Sopenharmony_ci    const JSVM_PropertyDescriptor* p = properties + i;
47731cb0ef41Sopenharmony_ci
47741cb0ef41Sopenharmony_ci    if ((p->attributes & JSVM_STATIC) != 0) { // attributes
47751cb0ef41Sopenharmony_ci      // Static properties are handled separately below.
47761cb0ef41Sopenharmony_ci      static_property_count++;
47771cb0ef41Sopenharmony_ci      continue;
47781cb0ef41Sopenharmony_ci    }
47791cb0ef41Sopenharmony_ci
47801cb0ef41Sopenharmony_ci    v8::Local<v8::Name> property_name;
47811cb0ef41Sopenharmony_ci    STATUS_CALL(v8impl::V8NameFromPropertyDescriptor(env, p, &property_name));
47821cb0ef41Sopenharmony_ci    v8::PropertyAttribute attributes = v8impl::V8PropertyAttributesFromDescriptor(p);
47831cb0ef41Sopenharmony_ci
47841cb0ef41Sopenharmony_ci    // This code is similar to that in OH_JSVM_DefineProperties(); the
47851cb0ef41Sopenharmony_ci    // difference is it applies to a template instead of an object,
47861cb0ef41Sopenharmony_ci    // and preferred PropertyAttribute for lack of PropertyDescriptor
47871cb0ef41Sopenharmony_ci    // support on ObjectTemplate.
47881cb0ef41Sopenharmony_ci    if (p->getter != nullptr || p->setter != nullptr) {
47891cb0ef41Sopenharmony_ci      v8::Local<v8::FunctionTemplate> getter_tpl;
47901cb0ef41Sopenharmony_ci      v8::Local<v8::FunctionTemplate> setter_tpl;
47911cb0ef41Sopenharmony_ci      if (p->getter != nullptr) {
47921cb0ef41Sopenharmony_ci        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
47931cb0ef41Sopenharmony_ci            env, p->getter, &getter_tpl));
47941cb0ef41Sopenharmony_ci      }
47951cb0ef41Sopenharmony_ci      if (p->setter != nullptr) {
47961cb0ef41Sopenharmony_ci        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
47971cb0ef41Sopenharmony_ci            env, p->setter, &setter_tpl));
47981cb0ef41Sopenharmony_ci      }
47991cb0ef41Sopenharmony_ci
48001cb0ef41Sopenharmony_ci      tpl->PrototypeTemplate()->SetAccessorProperty(property_name,
48011cb0ef41Sopenharmony_ci                                                    getter_tpl,
48021cb0ef41Sopenharmony_ci                                                    setter_tpl,
48031cb0ef41Sopenharmony_ci                                                    attributes,
48041cb0ef41Sopenharmony_ci                                                    v8::AccessControl::DEFAULT);
48051cb0ef41Sopenharmony_ci    } else if (p->method != nullptr) {
48061cb0ef41Sopenharmony_ci      v8::Local<v8::FunctionTemplate> t;
48071cb0ef41Sopenharmony_ci      if (p->attributes & JSVM_NO_RECEIVER_CHECK) {
48081cb0ef41Sopenharmony_ci        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
48091cb0ef41Sopenharmony_ci            env, p->method, &t));
48101cb0ef41Sopenharmony_ci      } else {
48111cb0ef41Sopenharmony_ci        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
48121cb0ef41Sopenharmony_ci            env, p->method, &t, v8::Signature::New(isolate, tpl)));
48131cb0ef41Sopenharmony_ci      }
48141cb0ef41Sopenharmony_ci
48151cb0ef41Sopenharmony_ci      tpl->PrototypeTemplate()->Set(property_name, t, attributes);
48161cb0ef41Sopenharmony_ci    } else {
48171cb0ef41Sopenharmony_ci      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
48181cb0ef41Sopenharmony_ci      tpl->PrototypeTemplate()->Set(property_name, value, attributes);
48191cb0ef41Sopenharmony_ci    }
48201cb0ef41Sopenharmony_ci  }
48211cb0ef41Sopenharmony_ci
48221cb0ef41Sopenharmony_ci  /* register property handler for instance object */
48231cb0ef41Sopenharmony_ci  v8impl::JSVM_PropertyHandlerCfgStruct* propertyHandleCfg = v8impl::CreatePropertyCfg(env, propertyHandlerCfg);
48241cb0ef41Sopenharmony_ci  if (propertyHandleCfg == nullptr) {
48251cb0ef41Sopenharmony_ci    return JSVM_Status::JSVM_GENERIC_FAILURE;
48261cb0ef41Sopenharmony_ci  }
48271cb0ef41Sopenharmony_ci  v8::Local<v8::Value> cbdata = v8impl::CallbackBundle::New(env, propertyHandleCfg);
48281cb0ef41Sopenharmony_ci
48291cb0ef41Sopenharmony_ci  // register named property handler
48301cb0ef41Sopenharmony_ci  v8::NamedPropertyHandlerConfiguration namedPropertyHandler;
48311cb0ef41Sopenharmony_ci  if (propertyHandlerCfg->genericNamedPropertyGetterCallback) {
48321cb0ef41Sopenharmony_ci    namedPropertyHandler.getter = v8impl::PropertyCallbackWrapper<v8::Value>::NameGetterInvoke;
48331cb0ef41Sopenharmony_ci  }
48341cb0ef41Sopenharmony_ci  if (propertyHandlerCfg->genericNamedPropertySetterCallback) {
48351cb0ef41Sopenharmony_ci    namedPropertyHandler.setter = v8impl::PropertyCallbackWrapper<v8::Value>::NameSetterInvoke;
48361cb0ef41Sopenharmony_ci  }
48371cb0ef41Sopenharmony_ci  if (propertyHandlerCfg->genericNamedPropertyDeleterCallback) {
48381cb0ef41Sopenharmony_ci    namedPropertyHandler.deleter = v8impl::PropertyCallbackWrapper<v8::Boolean>::NameDeleterInvoke;
48391cb0ef41Sopenharmony_ci  }
48401cb0ef41Sopenharmony_ci  if (propertyHandlerCfg->genericNamedPropertyEnumeratorCallback) {
48411cb0ef41Sopenharmony_ci    namedPropertyHandler.enumerator = v8impl::PropertyCallbackWrapper<v8::Array>::NameEnumeratorInvoke;
48421cb0ef41Sopenharmony_ci  }
48431cb0ef41Sopenharmony_ci  namedPropertyHandler.data = cbdata;
48441cb0ef41Sopenharmony_ci  tpl->InstanceTemplate()->SetHandler(namedPropertyHandler);
48451cb0ef41Sopenharmony_ci
48461cb0ef41Sopenharmony_ci  // register indexed property handle
48471cb0ef41Sopenharmony_ci  v8::IndexedPropertyHandlerConfiguration indexPropertyHandler;
48481cb0ef41Sopenharmony_ci  if (propertyHandlerCfg->genericIndexedPropertyGetterCallback) {
48491cb0ef41Sopenharmony_ci    indexPropertyHandler.getter = v8impl::PropertyCallbackWrapper<v8::Value>::IndexGetterInvoke;
48501cb0ef41Sopenharmony_ci  }
48511cb0ef41Sopenharmony_ci  if (propertyHandlerCfg->genericIndexedPropertySetterCallback) {
48521cb0ef41Sopenharmony_ci    indexPropertyHandler.setter = v8impl::PropertyCallbackWrapper<v8::Value>::IndexSetterInvoke;
48531cb0ef41Sopenharmony_ci  }
48541cb0ef41Sopenharmony_ci  if (propertyHandlerCfg->genericIndexedPropertyDeleterCallback) {
48551cb0ef41Sopenharmony_ci    indexPropertyHandler.deleter = v8impl::PropertyCallbackWrapper<v8::Boolean>::IndexDeleterInvoke;
48561cb0ef41Sopenharmony_ci  }
48571cb0ef41Sopenharmony_ci  if (propertyHandlerCfg->genericIndexedPropertyEnumeratorCallback) {
48581cb0ef41Sopenharmony_ci    indexPropertyHandler.enumerator = v8impl::PropertyCallbackWrapper<v8::Array>::IndexEnumeratorInvoke;
48591cb0ef41Sopenharmony_ci  }
48601cb0ef41Sopenharmony_ci  indexPropertyHandler.data = cbdata;
48611cb0ef41Sopenharmony_ci  tpl->InstanceTemplate()->SetHandler(indexPropertyHandler);
48621cb0ef41Sopenharmony_ci
48631cb0ef41Sopenharmony_ci  // register call as function
48641cb0ef41Sopenharmony_ci  if (callAsFunctionCallback && callAsFunctionCallback->callback) {
48651cb0ef41Sopenharmony_ci    v8::Local<v8::Value> funcCbdata = v8impl::CallbackBundle::New(env, callAsFunctionCallback);
48661cb0ef41Sopenharmony_ci    tpl->InstanceTemplate()->SetCallAsFunctionHandler(v8impl::FunctionCallbackWrapper::Invoke, funcCbdata);
48671cb0ef41Sopenharmony_ci  }
48681cb0ef41Sopenharmony_ci
48691cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
48701cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(
48711cb0ef41Sopenharmony_ci      scope.Escape(tpl->GetFunction(context).ToLocalChecked()));
48721cb0ef41Sopenharmony_ci
48731cb0ef41Sopenharmony_ci  v8impl::Reference::New(env, v8impl::V8LocalValueFromJsValue(*result), 0, v8impl::Ownership::kRuntime,
48741cb0ef41Sopenharmony_ci    v8impl::CfgFinalizedCallback, propertyHandleCfg, nullptr);
48751cb0ef41Sopenharmony_ci
48761cb0ef41Sopenharmony_ci  if (static_property_count > 0) {
48771cb0ef41Sopenharmony_ci    std::vector<JSVM_PropertyDescriptor> static_descriptors;
48781cb0ef41Sopenharmony_ci    static_descriptors.reserve(static_property_count);
48791cb0ef41Sopenharmony_ci
48801cb0ef41Sopenharmony_ci    for (size_t i = 0; i < propertyCount; i++) {
48811cb0ef41Sopenharmony_ci      const JSVM_PropertyDescriptor* p = properties + i;
48821cb0ef41Sopenharmony_ci      if ((p->attributes & JSVM_STATIC) != 0) {
48831cb0ef41Sopenharmony_ci        static_descriptors.push_back(*p);
48841cb0ef41Sopenharmony_ci      }
48851cb0ef41Sopenharmony_ci    }
48861cb0ef41Sopenharmony_ci
48871cb0ef41Sopenharmony_ci    STATUS_CALL(OH_JSVM_DefineProperties(
48881cb0ef41Sopenharmony_ci        env, *result, static_descriptors.size(), static_descriptors.data()));
48891cb0ef41Sopenharmony_ci  }
48901cb0ef41Sopenharmony_ci
48911cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
48921cb0ef41Sopenharmony_ci}
48931cb0ef41Sopenharmony_ci
48941cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsLocked(JSVM_Env env,
48951cb0ef41Sopenharmony_ci                                        bool* isLocked) {
48961cb0ef41Sopenharmony_ci  CHECK_ENV(env);
48971cb0ef41Sopenharmony_ci  CHECK_ARG(env, isLocked);
48981cb0ef41Sopenharmony_ci
48991cb0ef41Sopenharmony_ci  *isLocked = v8::Locker::IsLocked(env->isolate);
49001cb0ef41Sopenharmony_ci
49011cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
49021cb0ef41Sopenharmony_ci}
49031cb0ef41Sopenharmony_ci
49041cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_AcquireLock(JSVM_Env env) {
49051cb0ef41Sopenharmony_ci  CHECK_ENV(env);
49061cb0ef41Sopenharmony_ci
49071cb0ef41Sopenharmony_ci  bool isLocked = v8::Locker::IsLocked(env->isolate);
49081cb0ef41Sopenharmony_ci  if (!isLocked) {
49091cb0ef41Sopenharmony_ci    env->locker = new v8::Locker(env->isolate);
49101cb0ef41Sopenharmony_ci  }
49111cb0ef41Sopenharmony_ci
49121cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
49131cb0ef41Sopenharmony_ci}
49141cb0ef41Sopenharmony_ci
49151cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_ReleaseLock(JSVM_Env env) {
49161cb0ef41Sopenharmony_ci  CHECK_ENV(env);
49171cb0ef41Sopenharmony_ci
49181cb0ef41Sopenharmony_ci  bool isLocked = v8::Locker::IsLocked(env->isolate);
49191cb0ef41Sopenharmony_ci  if (isLocked && env->locker != nullptr) {
49201cb0ef41Sopenharmony_ci    delete env->locker;
49211cb0ef41Sopenharmony_ci    env->locker = nullptr;
49221cb0ef41Sopenharmony_ci  }
49231cb0ef41Sopenharmony_ci
49241cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
49251cb0ef41Sopenharmony_ci}
49261cb0ef41Sopenharmony_ci
49271cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsCallable(JSVM_Env env,
49281cb0ef41Sopenharmony_ci                                          JSVM_Value value,
49291cb0ef41Sopenharmony_ci                                          bool* isCallable) {
49301cb0ef41Sopenharmony_ci  CHECK_ENV(env);
49311cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
49321cb0ef41Sopenharmony_ci  CHECK_ARG(env, isCallable);
49331cb0ef41Sopenharmony_ci
49341cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
49351cb0ef41Sopenharmony_ci
49361cb0ef41Sopenharmony_ci  *isCallable = val->IsFunction();
49371cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
49381cb0ef41Sopenharmony_ci}
49391cb0ef41Sopenharmony_ci
49401cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsUndefined(JSVM_Env env,
49411cb0ef41Sopenharmony_ci                                           JSVM_Value value,
49421cb0ef41Sopenharmony_ci                                           bool* isUndefined) {
49431cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8
49441cb0ef41Sopenharmony_ci  // calls here cannot throw JS exceptions.
49451cb0ef41Sopenharmony_ci  CHECK_ENV(env);
49461cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
49471cb0ef41Sopenharmony_ci  CHECK_ARG(env, isUndefined);
49481cb0ef41Sopenharmony_ci
49491cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
49501cb0ef41Sopenharmony_ci  *isUndefined = val->IsUndefined();
49511cb0ef41Sopenharmony_ci
49521cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
49531cb0ef41Sopenharmony_ci}
49541cb0ef41Sopenharmony_ci
49551cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsNull(JSVM_Env env,
49561cb0ef41Sopenharmony_ci                                      JSVM_Value value,
49571cb0ef41Sopenharmony_ci                                      bool* isNull) {
49581cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8
49591cb0ef41Sopenharmony_ci  // calls here cannot throw JS exceptions.
49601cb0ef41Sopenharmony_ci  CHECK_ENV(env);
49611cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
49621cb0ef41Sopenharmony_ci  CHECK_ARG(env, isNull);
49631cb0ef41Sopenharmony_ci
49641cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
49651cb0ef41Sopenharmony_ci  *isNull = val->IsNull();
49661cb0ef41Sopenharmony_ci
49671cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
49681cb0ef41Sopenharmony_ci}
49691cb0ef41Sopenharmony_ci
49701cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsNullOrUndefined(JSVM_Env env,
49711cb0ef41Sopenharmony_ci                                                 JSVM_Value value,
49721cb0ef41Sopenharmony_ci                                                 bool* isNullOrUndefined) {
49731cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8
49741cb0ef41Sopenharmony_ci  // calls here cannot throw JS exceptions.
49751cb0ef41Sopenharmony_ci  CHECK_ENV(env);
49761cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
49771cb0ef41Sopenharmony_ci  CHECK_ARG(env, isNullOrUndefined);
49781cb0ef41Sopenharmony_ci
49791cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
49801cb0ef41Sopenharmony_ci  *isNullOrUndefined = val->IsNullOrUndefined();
49811cb0ef41Sopenharmony_ci
49821cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
49831cb0ef41Sopenharmony_ci}
49841cb0ef41Sopenharmony_ci
49851cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsBoolean(JSVM_Env env,
49861cb0ef41Sopenharmony_ci                                         JSVM_Value value,
49871cb0ef41Sopenharmony_ci                                         bool* isBoolean) {
49881cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8
49891cb0ef41Sopenharmony_ci  // calls here cannot throw JS exceptions.
49901cb0ef41Sopenharmony_ci  CHECK_ENV(env);
49911cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
49921cb0ef41Sopenharmony_ci  CHECK_ARG(env, isBoolean);
49931cb0ef41Sopenharmony_ci
49941cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
49951cb0ef41Sopenharmony_ci  *isBoolean = val->IsBoolean();
49961cb0ef41Sopenharmony_ci
49971cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
49981cb0ef41Sopenharmony_ci}
49991cb0ef41Sopenharmony_ci
50001cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsNumber(JSVM_Env env,
50011cb0ef41Sopenharmony_ci                                        JSVM_Value value,
50021cb0ef41Sopenharmony_ci                                        bool* isNumber) {
50031cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8
50041cb0ef41Sopenharmony_ci  // calls here cannot throw JS exceptions.
50051cb0ef41Sopenharmony_ci  CHECK_ENV(env);
50061cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
50071cb0ef41Sopenharmony_ci  CHECK_ARG(env, isNumber);
50081cb0ef41Sopenharmony_ci
50091cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
50101cb0ef41Sopenharmony_ci  *isNumber = val->IsNumber();
50111cb0ef41Sopenharmony_ci
50121cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
50131cb0ef41Sopenharmony_ci}
50141cb0ef41Sopenharmony_ci
50151cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsString(JSVM_Env env,
50161cb0ef41Sopenharmony_ci                                        JSVM_Value value,
50171cb0ef41Sopenharmony_ci                                        bool* isString) {
50181cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8
50191cb0ef41Sopenharmony_ci  // calls here cannot throw JS exceptions.
50201cb0ef41Sopenharmony_ci  CHECK_ENV(env);
50211cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
50221cb0ef41Sopenharmony_ci  CHECK_ARG(env, isString);
50231cb0ef41Sopenharmony_ci
50241cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
50251cb0ef41Sopenharmony_ci  *isString = val->IsString();
50261cb0ef41Sopenharmony_ci
50271cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
50281cb0ef41Sopenharmony_ci}
50291cb0ef41Sopenharmony_ci
50301cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsSymbol(JSVM_Env env,
50311cb0ef41Sopenharmony_ci                                        JSVM_Value value,
50321cb0ef41Sopenharmony_ci                                        bool* isSymbol) {
50331cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8
50341cb0ef41Sopenharmony_ci  // calls here cannot throw JS exceptions.
50351cb0ef41Sopenharmony_ci  CHECK_ENV(env);
50361cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
50371cb0ef41Sopenharmony_ci  CHECK_ARG(env, isSymbol);
50381cb0ef41Sopenharmony_ci
50391cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
50401cb0ef41Sopenharmony_ci  *isSymbol = val->IsSymbol();
50411cb0ef41Sopenharmony_ci
50421cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
50431cb0ef41Sopenharmony_ci}
50441cb0ef41Sopenharmony_ci
50451cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsFunction(JSVM_Env env,
50461cb0ef41Sopenharmony_ci                                          JSVM_Value value,
50471cb0ef41Sopenharmony_ci                                          bool* isFunction) {
50481cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8
50491cb0ef41Sopenharmony_ci  // calls here cannot throw JS exceptions.
50501cb0ef41Sopenharmony_ci  CHECK_ENV(env);
50511cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
50521cb0ef41Sopenharmony_ci  CHECK_ARG(env, isFunction);
50531cb0ef41Sopenharmony_ci
50541cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
50551cb0ef41Sopenharmony_ci  *isFunction = val->IsFunction();
50561cb0ef41Sopenharmony_ci
50571cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
50581cb0ef41Sopenharmony_ci}
50591cb0ef41Sopenharmony_ci
50601cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsObject(JSVM_Env env,
50611cb0ef41Sopenharmony_ci                                        JSVM_Value value,
50621cb0ef41Sopenharmony_ci                                        bool* isObject) {
50631cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8
50641cb0ef41Sopenharmony_ci  // calls here cannot throw JS exceptions.
50651cb0ef41Sopenharmony_ci  CHECK_ENV(env);
50661cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
50671cb0ef41Sopenharmony_ci  CHECK_ARG(env, isObject);
50681cb0ef41Sopenharmony_ci
50691cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
50701cb0ef41Sopenharmony_ci  *isObject = val->IsObject();
50711cb0ef41Sopenharmony_ci
50721cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
50731cb0ef41Sopenharmony_ci}
50741cb0ef41Sopenharmony_ci
50751cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsBigInt(JSVM_Env env,
50761cb0ef41Sopenharmony_ci                                        JSVM_Value value,
50771cb0ef41Sopenharmony_ci                                        bool* isBigInt) {
50781cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8
50791cb0ef41Sopenharmony_ci  // calls here cannot throw JS exceptions.
50801cb0ef41Sopenharmony_ci  CHECK_ENV(env);
50811cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
50821cb0ef41Sopenharmony_ci  CHECK_ARG(env, isBigInt);
50831cb0ef41Sopenharmony_ci
50841cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
50851cb0ef41Sopenharmony_ci  *isBigInt = val->IsBigInt();
50861cb0ef41Sopenharmony_ci
50871cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
50881cb0ef41Sopenharmony_ci}
50891cb0ef41Sopenharmony_ci
50901cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsConstructor(JSVM_Env env,
50911cb0ef41Sopenharmony_ci                                             JSVM_Value value,
50921cb0ef41Sopenharmony_ci                                             bool* isConstructor) {
50931cb0ef41Sopenharmony_ci  CHECK_ENV(env);
50941cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
50951cb0ef41Sopenharmony_ci  CHECK_ARG(env, isConstructor);
50961cb0ef41Sopenharmony_ci
50971cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
50981cb0ef41Sopenharmony_ci  if (!val->IsObject()) {
50991cb0ef41Sopenharmony_ci    *isConstructor = false;
51001cb0ef41Sopenharmony_ci    return jsvm_clear_last_error(env);
51011cb0ef41Sopenharmony_ci  }
51021cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj = val.As<v8::Object>();
51031cb0ef41Sopenharmony_ci  *isConstructor = obj->IsConstructor();
51041cb0ef41Sopenharmony_ci
51051cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
51061cb0ef41Sopenharmony_ci}
51071cb0ef41Sopenharmony_ci
51081cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateSet(JSVM_Env env,
51091cb0ef41Sopenharmony_ci                                         JSVM_Value* result) {
51101cb0ef41Sopenharmony_ci  CHECK_ENV(env);
51111cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
51121cb0ef41Sopenharmony_ci
51131cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(v8::Set::New(env->isolate));
51141cb0ef41Sopenharmony_ci
51151cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
51161cb0ef41Sopenharmony_ci}
51171cb0ef41Sopenharmony_ci
51181cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateRegExp(JSVM_Env env,
51191cb0ef41Sopenharmony_ci                                            JSVM_Value value,
51201cb0ef41Sopenharmony_ci                                            JSVM_RegExpFlags flags,
51211cb0ef41Sopenharmony_ci                                            JSVM_Value* result) {
51221cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
51231cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
51241cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
51251cb0ef41Sopenharmony_ci
51261cb0ef41Sopenharmony_ci  v8::Local<v8::Value> pattern = v8impl::V8LocalValueFromJsValue(value);
51271cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, pattern->IsString(), JSVM_STRING_EXPECTED);
51281cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
51291cb0ef41Sopenharmony_ci  v8::MaybeLocal<v8::RegExp> regExp = v8::RegExp::New(context, pattern.As<v8::String>(),
51301cb0ef41Sopenharmony_ci                                                      static_cast<v8::RegExp::Flags>(flags));
51311cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, regExp, JSVM_GENERIC_FAILURE);
51321cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(regExp.ToLocalChecked());
51331cb0ef41Sopenharmony_ci
51341cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
51351cb0ef41Sopenharmony_ci}
51361cb0ef41Sopenharmony_ci
51371cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateMap(JSVM_Env env, JSVM_Value* result) {
51381cb0ef41Sopenharmony_ci  CHECK_ENV(env);
51391cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
51401cb0ef41Sopenharmony_ci
51411cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(v8::Map::New(env->isolate));
51421cb0ef41Sopenharmony_ci
51431cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
51441cb0ef41Sopenharmony_ci}
51451cb0ef41Sopenharmony_ci
51461cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsMap(JSVM_Env env,
51471cb0ef41Sopenharmony_ci                                     JSVM_Value value,
51481cb0ef41Sopenharmony_ci                                     bool* isMap) {
51491cb0ef41Sopenharmony_ci  CHECK_ENV(env);
51501cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
51511cb0ef41Sopenharmony_ci  CHECK_ARG(env, isMap);
51521cb0ef41Sopenharmony_ci
51531cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
51541cb0ef41Sopenharmony_ci
51551cb0ef41Sopenharmony_ci  *isMap = val->IsMap();
51561cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
51571cb0ef41Sopenharmony_ci}
51581cb0ef41Sopenharmony_ci
51591cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsSet(JSVM_Env env,
51601cb0ef41Sopenharmony_ci                                     JSVM_Value value,
51611cb0ef41Sopenharmony_ci                                     bool* isSet) {
51621cb0ef41Sopenharmony_ci  CHECK_ENV(env);
51631cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
51641cb0ef41Sopenharmony_ci  CHECK_ARG(env, isSet);
51651cb0ef41Sopenharmony_ci
51661cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
51671cb0ef41Sopenharmony_ci  *isSet = val->IsSet();
51681cb0ef41Sopenharmony_ci
51691cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
51701cb0ef41Sopenharmony_ci}
51711cb0ef41Sopenharmony_ci
51721cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_ObjectGetPrototypeOf(JSVM_Env env,
51731cb0ef41Sopenharmony_ci                                                    JSVM_Value object,
51741cb0ef41Sopenharmony_ci                                                    JSVM_Value* result) {
51751cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
51761cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
51771cb0ef41Sopenharmony_ci
51781cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
51791cb0ef41Sopenharmony_ci
51801cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
51811cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
51821cb0ef41Sopenharmony_ci
51831cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = obj->GetPrototypeV2();
51841cb0ef41Sopenharmony_ci  *result = v8impl::JsValueFromV8LocalValue(val);
51851cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
51861cb0ef41Sopenharmony_ci}
51871cb0ef41Sopenharmony_ci
51881cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_ObjectSetPrototypeOf(JSVM_Env env,
51891cb0ef41Sopenharmony_ci                                                    JSVM_Value object,
51901cb0ef41Sopenharmony_ci                                                    JSVM_Value prototype) {
51911cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
51921cb0ef41Sopenharmony_ci  CHECK_ARG(env, prototype);
51931cb0ef41Sopenharmony_ci
51941cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context = env->context();
51951cb0ef41Sopenharmony_ci
51961cb0ef41Sopenharmony_ci  v8::Local<v8::Object> obj;
51971cb0ef41Sopenharmony_ci  CHECK_TO_OBJECT(env, context, obj, object);
51981cb0ef41Sopenharmony_ci
51991cb0ef41Sopenharmony_ci  v8::Local<v8::Value> type = v8impl::V8LocalValueFromJsValue(prototype);
52001cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, type->IsObject(), JSVM_INVALID_ARG);
52011cb0ef41Sopenharmony_ci  v8::Maybe<bool> set_maybe = obj->SetPrototypeV2(context, type);
52021cb0ef41Sopenharmony_ci
52031cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), JSVM_GENERIC_FAILURE);
52041cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
52051cb0ef41Sopenharmony_ci}
52061cb0ef41Sopenharmony_ci
52071cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_RetainScript(JSVM_Env env, JSVM_Script script) {
52081cb0ef41Sopenharmony_ci  CHECK_ENV(env);
52091cb0ef41Sopenharmony_ci  auto jsvmData = reinterpret_cast<JSVM_Data__ *>(script);
52101cb0ef41Sopenharmony_ci
52111cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, jsvmData && !jsvmData->isGlobal, JSVM_INVALID_ARG);
52121cb0ef41Sopenharmony_ci
52131cb0ef41Sopenharmony_ci  jsvmData->taggedPointer = v8::Global<v8::Script>(
52141cb0ef41Sopenharmony_ci    env->isolate, jsvmData->ToV8Local<v8::Script>(env->isolate));
52151cb0ef41Sopenharmony_ci
52161cb0ef41Sopenharmony_ci  jsvmData->isGlobal = true;
52171cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
52181cb0ef41Sopenharmony_ci}
52191cb0ef41Sopenharmony_ci
52201cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_ReleaseScript(JSVM_Env env, JSVM_Script script) {
52211cb0ef41Sopenharmony_ci  CHECK_ENV(env);
52221cb0ef41Sopenharmony_ci  auto jsvmData = reinterpret_cast<JSVM_Data__ *>(script);
52231cb0ef41Sopenharmony_ci
52241cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, jsvmData && jsvmData->isGlobal, JSVM_INVALID_ARG);
52251cb0ef41Sopenharmony_ci
52261cb0ef41Sopenharmony_ci  std::get<v8::Global<v8::Script>>(jsvmData->taggedPointer).Reset();
52271cb0ef41Sopenharmony_ci  delete jsvmData;
52281cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
52291cb0ef41Sopenharmony_ci}
52301cb0ef41Sopenharmony_ci
52311cb0ef41Sopenharmony_ciint FindAvailablePort() {
52321cb0ef41Sopenharmony_ci  constexpr int startPort = 9229;
52331cb0ef41Sopenharmony_ci  constexpr int endPort = 9999;
52341cb0ef41Sopenharmony_ci  constexpr int invalidPort = -1;
52351cb0ef41Sopenharmony_ci  int sockfd = -1;
52361cb0ef41Sopenharmony_ci
52371cb0ef41Sopenharmony_ci  for (auto port = startPort; port <= endPort; ++port) {
52381cb0ef41Sopenharmony_ci    sockfd = socket(AF_INET, SOCK_STREAM, 0);
52391cb0ef41Sopenharmony_ci    if (sockfd < 0) {
52401cb0ef41Sopenharmony_ci      continue;
52411cb0ef41Sopenharmony_ci    }
52421cb0ef41Sopenharmony_ci    struct sockaddr_in addr;
52431cb0ef41Sopenharmony_ci    addr.sin_family = AF_INET;
52441cb0ef41Sopenharmony_ci    addr.sin_addr.s_addr = htonl(INADDR_ANY);
52451cb0ef41Sopenharmony_ci    addr.sin_port = htons(port);
52461cb0ef41Sopenharmony_ci
52471cb0ef41Sopenharmony_ci    if (bind(sockfd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
52481cb0ef41Sopenharmony_ci      close(sockfd);
52491cb0ef41Sopenharmony_ci      if (errno == EADDRINUSE) {
52501cb0ef41Sopenharmony_ci        continue;
52511cb0ef41Sopenharmony_ci      } else {
52521cb0ef41Sopenharmony_ci        break;
52531cb0ef41Sopenharmony_ci      }
52541cb0ef41Sopenharmony_ci    }
52551cb0ef41Sopenharmony_ci    close(sockfd);
52561cb0ef41Sopenharmony_ci    return port;
52571cb0ef41Sopenharmony_ci  }
52581cb0ef41Sopenharmony_ci  return invalidPort;
52591cb0ef41Sopenharmony_ci}
52601cb0ef41Sopenharmony_ci
52611cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_OpenInspectorWithName(JSVM_Env env,
52621cb0ef41Sopenharmony_ci                                                     int pid,
52631cb0ef41Sopenharmony_ci                                                     const char* name) {
52641cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
52651cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, !name || strlen(name) < SIZE_MAX , JSVM_INVALID_ARG);
52661cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, pid >= 0, JSVM_INVALID_ARG);
52671cb0ef41Sopenharmony_ci  std::string path(name ? name : "jsvm");
52681cb0ef41Sopenharmony_ci  auto port = FindAvailablePort();
52691cb0ef41Sopenharmony_ci  auto hostPort =
52701cb0ef41Sopenharmony_ci    std::make_shared<node::ExclusiveAccess<node::HostPort>>("localhost", port, pid);
52711cb0ef41Sopenharmony_ci  env->inspector_agent()->Start(path, hostPort, true, false);
52721cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
52731cb0ef41Sopenharmony_ci}
52741cb0ef41Sopenharmony_ci
52751cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CompileWasmModule(JSVM_Env env,
52761cb0ef41Sopenharmony_ci                                                 const uint8_t *wasmBytecode,
52771cb0ef41Sopenharmony_ci                                                 size_t wasmBytecodeLength,
52781cb0ef41Sopenharmony_ci                                                 const uint8_t *cacheData,
52791cb0ef41Sopenharmony_ci                                                 size_t cacheDataLength,
52801cb0ef41Sopenharmony_ci                                                 bool *cacheRejected,
52811cb0ef41Sopenharmony_ci                                                 JSVM_Value *wasmModule) {
52821cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
52831cb0ef41Sopenharmony_ci  CHECK_ARG(env, wasmBytecode);
52841cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, wasmBytecodeLength > 0, JSVM_INVALID_ARG);
52851cb0ef41Sopenharmony_ci  v8::MaybeLocal<v8::WasmModuleObject> maybe_module;
52861cb0ef41Sopenharmony_ci  if (cacheData == nullptr) {
52871cb0ef41Sopenharmony_ci    maybe_module = v8::WasmModuleObject::Compile(env->isolate, {wasmBytecode, wasmBytecodeLength});
52881cb0ef41Sopenharmony_ci  } else {
52891cb0ef41Sopenharmony_ci    RETURN_STATUS_IF_FALSE(env, cacheDataLength > 0, JSVM_INVALID_ARG);
52901cb0ef41Sopenharmony_ci    bool rejected;
52911cb0ef41Sopenharmony_ci    maybe_module = v8::WasmModuleObject::DeserializeOrCompile(
52921cb0ef41Sopenharmony_ci      env->isolate, {wasmBytecode, wasmBytecodeLength}, {cacheData, cacheDataLength}, rejected);
52931cb0ef41Sopenharmony_ci    if (cacheRejected != nullptr) {
52941cb0ef41Sopenharmony_ci      *cacheRejected = rejected;
52951cb0ef41Sopenharmony_ci    }
52961cb0ef41Sopenharmony_ci  }
52971cb0ef41Sopenharmony_ci  // To avoid the status code caused by exception being override, check exception once v8 API finished
52981cb0ef41Sopenharmony_ci  if (try_catch.HasCaught()) {
52991cb0ef41Sopenharmony_ci    return jsvm_set_last_error(env, JSVM_PENDING_EXCEPTION);
53001cb0ef41Sopenharmony_ci  }
53011cb0ef41Sopenharmony_ci  CHECK_MAYBE_EMPTY(env, maybe_module, JSVM_GENERIC_FAILURE);
53021cb0ef41Sopenharmony_ci  *wasmModule = v8impl::JsValueFromV8LocalValue(maybe_module.ToLocalChecked());
53031cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
53041cb0ef41Sopenharmony_ci}
53051cb0ef41Sopenharmony_ci
53061cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CompileWasmFunction(JSVM_Env env,
53071cb0ef41Sopenharmony_ci                                                   JSVM_Value wasmModule,
53081cb0ef41Sopenharmony_ci                                                   uint32_t functionIndex,
53091cb0ef41Sopenharmony_ci                                                   JSVM_WasmOptLevel optLevel) {
53101cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
53111cb0ef41Sopenharmony_ci  CHECK_ARG(env, wasmModule);
53121cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(wasmModule);
53131cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsWasmModuleObject(), JSVM_INVALID_ARG);
53141cb0ef41Sopenharmony_ci
53151cb0ef41Sopenharmony_ci  v8::Local<v8::WasmModuleObject> v8WasmModule = val.As<v8::WasmModuleObject>();
53161cb0ef41Sopenharmony_ci  v8::WasmExecutionTier tier = v8::WasmExecutionTier::kNone;
53171cb0ef41Sopenharmony_ci  if (optLevel == JSVM_WASM_OPT_BASELINE) {
53181cb0ef41Sopenharmony_ci    // v8 liftoff has bug, keep BASELINE same as HIGH.
53191cb0ef41Sopenharmony_ci    tier = v8::WasmExecutionTier::kTurbofan;
53201cb0ef41Sopenharmony_ci  } else if (optLevel == JSVM_WASM_OPT_HIGH) {
53211cb0ef41Sopenharmony_ci    tier = v8::WasmExecutionTier::kTurbofan;
53221cb0ef41Sopenharmony_ci  } else {
53231cb0ef41Sopenharmony_ci    // Unsupported optLevel
53241cb0ef41Sopenharmony_ci    return jsvm_set_last_error(env, JSVM_INVALID_ARG);
53251cb0ef41Sopenharmony_ci  }
53261cb0ef41Sopenharmony_ci  bool compileSuccess = v8WasmModule->CompileFunction(env->isolate, functionIndex, tier);
53271cb0ef41Sopenharmony_ci  // To avoid the status code caused by exception being override, check exception once v8 API finished
53281cb0ef41Sopenharmony_ci  if (try_catch.HasCaught()) {
53291cb0ef41Sopenharmony_ci    return jsvm_set_last_error(env, JSVM_PENDING_EXCEPTION);
53301cb0ef41Sopenharmony_ci  }
53311cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, compileSuccess, JSVM_GENERIC_FAILURE);
53321cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
53331cb0ef41Sopenharmony_ci}
53341cb0ef41Sopenharmony_ci
53351cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_IsWasmModuleObject(JSVM_Env env,
53361cb0ef41Sopenharmony_ci                                                  JSVM_Value value,
53371cb0ef41Sopenharmony_ci                                                  bool* result) {
53381cb0ef41Sopenharmony_ci  // Omit JSVM_PREAMBLE and GET_RETURN_STATUS because V8
53391cb0ef41Sopenharmony_ci  // calls here cannot throw JS exceptions.
53401cb0ef41Sopenharmony_ci  CHECK_ENV(env);
53411cb0ef41Sopenharmony_ci  CHECK_ARG(env, value);
53421cb0ef41Sopenharmony_ci  CHECK_ARG(env, result);
53431cb0ef41Sopenharmony_ci
53441cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
53451cb0ef41Sopenharmony_ci  *result = val->IsWasmModuleObject();
53461cb0ef41Sopenharmony_ci
53471cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
53481cb0ef41Sopenharmony_ci}
53491cb0ef41Sopenharmony_ci
53501cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_CreateWasmCache(JSVM_Env env,
53511cb0ef41Sopenharmony_ci                                               JSVM_Value wasmModule,
53521cb0ef41Sopenharmony_ci                                               const uint8_t** data,
53531cb0ef41Sopenharmony_ci                                               size_t* length) {
53541cb0ef41Sopenharmony_ci  JSVM_PREAMBLE(env);
53551cb0ef41Sopenharmony_ci  CHECK_ARG(env, wasmModule);
53561cb0ef41Sopenharmony_ci  CHECK_ARG(env, data);
53571cb0ef41Sopenharmony_ci  CHECK_ARG(env, length);
53581cb0ef41Sopenharmony_ci
53591cb0ef41Sopenharmony_ci  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(wasmModule);
53601cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, val->IsWasmModuleObject(), JSVM_INVALID_ARG);
53611cb0ef41Sopenharmony_ci
53621cb0ef41Sopenharmony_ci  v8::Local<v8::WasmModuleObject> v8WasmModule = val.As<v8::WasmModuleObject>();
53631cb0ef41Sopenharmony_ci  v8::CompiledWasmModule compiledWasmModule = v8WasmModule->GetCompiledModule();
53641cb0ef41Sopenharmony_ci  v8::OwnedBuffer serialized_bytes = compiledWasmModule.Serialize();
53651cb0ef41Sopenharmony_ci  // To avoid the status code caused by exception being override, check exception once v8 API finished
53661cb0ef41Sopenharmony_ci  if (try_catch.HasCaught()) {
53671cb0ef41Sopenharmony_ci    return jsvm_set_last_error(env, JSVM_PENDING_EXCEPTION);
53681cb0ef41Sopenharmony_ci  }
53691cb0ef41Sopenharmony_ci  // If buffer size is 0, create wasm cache failed.
53701cb0ef41Sopenharmony_ci  RETURN_STATUS_IF_FALSE(env, serialized_bytes.size > 0, JSVM_GENERIC_FAILURE);
53711cb0ef41Sopenharmony_ci  *data = serialized_bytes.buffer.get();
53721cb0ef41Sopenharmony_ci  *length = serialized_bytes.size;
53731cb0ef41Sopenharmony_ci  // Release the ownership of buffer, OH_JSVM_ReleaseCache must be called explicitly to release the buffer
53741cb0ef41Sopenharmony_ci  serialized_bytes.buffer.release();
53751cb0ef41Sopenharmony_ci
53761cb0ef41Sopenharmony_ci  return GET_RETURN_STATUS(env);
53771cb0ef41Sopenharmony_ci}
53781cb0ef41Sopenharmony_ci
53791cb0ef41Sopenharmony_ciJSVM_Status JSVM_CDECL OH_JSVM_ReleaseCache(JSVM_Env env,
53801cb0ef41Sopenharmony_ci                                            const uint8_t* cacheData,
53811cb0ef41Sopenharmony_ci                                            JSVM_CacheType cacheType) {
53821cb0ef41Sopenharmony_ci  CHECK_ENV(env);
53831cb0ef41Sopenharmony_ci  CHECK_ARG(env, cacheData);
53841cb0ef41Sopenharmony_ci  if (cacheType == JSVM_CACHE_TYPE_JS) {
53851cb0ef41Sopenharmony_ci    // The release behavior MUST match the memory allocation of OH_JSVM_CreateCodeCache.
53861cb0ef41Sopenharmony_ci    delete[] cacheData;
53871cb0ef41Sopenharmony_ci  } else if (cacheType == JSVM_CACHE_TYPE_WASM) {
53881cb0ef41Sopenharmony_ci    // The release behavior MUST match the memory allocation of OH_JSVM_CreateWasmCache.
53891cb0ef41Sopenharmony_ci    delete[] cacheData;
53901cb0ef41Sopenharmony_ci  } else {
53911cb0ef41Sopenharmony_ci    // Unsupported cacheType
53921cb0ef41Sopenharmony_ci    return jsvm_set_last_error(env, JSVM_INVALID_ARG);
53931cb0ef41Sopenharmony_ci  }
53941cb0ef41Sopenharmony_ci  return jsvm_clear_last_error(env);
53951cb0ef41Sopenharmony_ci}
5396