/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef JSVM_VALUE_H #define JSVM_VALUE_H #include #include "jsvm_util.h" struct JSVM_Script_Data__ { public: using SourcePtr = std::variant, v8::Global>; using DataType = enum { kJsvmScript }; template JSVM_Script_Data__(T ptr, bool retained, DataType type = kJsvmScript) : taggedPointer(ptr), isGlobal(retained), type(type) {} template v8::Local ToV8Local(v8::Isolate* isolate) { if (isGlobal) { return v8::Local::New(isolate, std::get>(taggedPointer)); } else { return std::get>(taggedPointer); } } SourcePtr taggedPointer; bool isGlobal = false; DataType type; }; namespace v8impl { // This asserts v8::Local<> will always be implemented with a single // pointer field so that we can pass it around as a void*. static_assert(sizeof(v8::Local) == sizeof(JSVM_Data), "Cannot convert between v8::Local and JSVM_Data"); inline JSVM_Data JsDataFromV8LocalData(v8::Local local) { return reinterpret_cast(*local); } inline v8::Local V8LocalDataFromJsData(JSVM_Data data) { v8::Local local; *reinterpret_cast(&local) = data; return local; } // This asserts v8::Local<> will always be implemented with a single // pointer field so that we can pass it around as a void*. static_assert(sizeof(v8::Local) == sizeof(JSVM_Value), "Cannot convert between v8::Local and JSVM_Value"); inline JSVM_Value JsValueFromV8LocalValue(v8::Local local) { return reinterpret_cast(*local); } inline v8::Local V8LocalValueFromJsValue(JSVM_Value value) { v8::Local local; *reinterpret_cast(&local) = value; return local; } inline JSVM_Deferred JsDeferredFromPersistent(v8impl::Persistent* local) { return reinterpret_cast(local); } inline v8impl::Persistent* PersistentFromJsDeferred(JSVM_Deferred local) { return reinterpret_cast*>(local); } class HandleScopeWrapper { public: explicit HandleScopeWrapper(v8::Isolate* isolate) : scope(isolate) {} private: v8::HandleScope scope; }; class EscapableHandleScopeWrapper { public: explicit EscapableHandleScopeWrapper(v8::Isolate* isolate) : scope(isolate), escapeCalled(false) {} bool IsEscapeCalled() const { return escapeCalled; } template v8::Local Escape(v8::Local handle) { escapeCalled = true; return scope.Escape(handle); } private: v8::EscapableHandleScope scope; bool escapeCalled; }; inline JSVM_HandleScope JsHandleScopeFromV8HandleScope(HandleScopeWrapper* s) { return reinterpret_cast(s); } inline HandleScopeWrapper* V8HandleScopeFromJsHandleScope(JSVM_HandleScope s) { return reinterpret_cast(s); } inline JSVM_EscapableHandleScope JsEscapableHandleScopeFromV8EscapableHandleScope(EscapableHandleScopeWrapper* s) { return reinterpret_cast(s); } inline EscapableHandleScopeWrapper* V8EscapableHandleScopeFromJsEscapableHandleScope(JSVM_EscapableHandleScope s) { return reinterpret_cast(s); } // Convert a v8::PersistentBase, e.g. v8::Global, to a Local, with an extra // optimization for strong persistent handles. class PersistentToLocal { public: // Convert v8::Global to v8::Local template static inline v8::Local Default(v8::Isolate* isolate, const v8::PersistentBase& persistent) { if (persistent.IsWeak()) { return PersistentToLocal::Weak(isolate, persistent); } else { return PersistentToLocal::Strong(persistent); } } template static inline v8::Local Strong(const v8::PersistentBase& persistent) { DCHECK(!persistent.IsWeak()); return *reinterpret_cast*>(const_cast*>(&persistent)); } template static inline v8::Local Weak(v8::Isolate* isolate, const v8::PersistentBase& persistent) { return v8::Local::New(isolate, persistent); } }; } // namespace v8impl #endif