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