• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef JSVM_VALUE_H
17 #define JSVM_VALUE_H
18 #include <variant>
19 
20 #include "jsvm_util.h"
21 
22 struct JSVM_Script_Data__ {
23 public:
24     using SourcePtr = std::variant<v8::Local<v8::Script>, v8::Global<v8::Script>>;
25     using DataType = enum { kJsvmScript };
26 
27     template<typename T>
28     JSVM_Script_Data__(T ptr, bool retained, DataType type = kJsvmScript)
taggedPointerJSVM_Script_Data__29         : taggedPointer(ptr), isGlobal(retained), type(type)
30     {}
31 
32     template<class T>
ToV8LocalJSVM_Script_Data__33     v8::Local<T> ToV8Local(v8::Isolate* isolate)
34     {
35         if (isGlobal) {
36             return v8::Local<T>::New(isolate, std::get<v8::Global<T>>(taggedPointer));
37         } else {
38             return std::get<v8::Local<T>>(taggedPointer);
39         }
40     }
41 
42     SourcePtr taggedPointer;
43     bool isGlobal = false;
44     DataType type;
45 };
46 
47 namespace v8impl {
48 // This asserts v8::Local<> will always be implemented with a single
49 // pointer field so that we can pass it around as a void*.
50 static_assert(sizeof(v8::Local<v8::Data>) == sizeof(JSVM_Data),
51               "Cannot convert between v8::Local<v8::Data> and JSVM_Data");
52 
JsDataFromV8LocalData(v8::Local<v8::Data> local)53 inline JSVM_Data JsDataFromV8LocalData(v8::Local<v8::Data> local)
54 {
55     return reinterpret_cast<JSVM_Data>(*local);
56 }
57 
V8LocalDataFromJsData(JSVM_Data data)58 inline v8::Local<v8::Data> V8LocalDataFromJsData(JSVM_Data data)
59 {
60     v8::Local<v8::Data> local;
61     *reinterpret_cast<JSVM_Data*>(&local) = data;
62     return local;
63 }
64 
65 // This asserts v8::Local<> will always be implemented with a single
66 // pointer field so that we can pass it around as a void*.
67 static_assert(sizeof(v8::Local<v8::Value>) == sizeof(JSVM_Value),
68               "Cannot convert between v8::Local<v8::Value> and JSVM_Value");
69 
JsValueFromV8LocalValue(v8::Local<v8::Value> local)70 inline JSVM_Value JsValueFromV8LocalValue(v8::Local<v8::Value> local)
71 {
72     return reinterpret_cast<JSVM_Value>(*local);
73 }
74 
V8LocalValueFromJsValue(JSVM_Value value)75 inline v8::Local<v8::Value> V8LocalValueFromJsValue(JSVM_Value value)
76 {
77     v8::Local<v8::Value> local;
78     *reinterpret_cast<JSVM_Value*>(&local) = value;
79     return local;
80 }
81 
JsDeferredFromPersistent(v8impl::Persistent<v8::Value> * local)82 inline JSVM_Deferred JsDeferredFromPersistent(v8impl::Persistent<v8::Value>* local)
83 {
84     return reinterpret_cast<JSVM_Deferred>(local);
85 }
86 
PersistentFromJsDeferred(JSVM_Deferred local)87 inline v8impl::Persistent<v8::Value>* PersistentFromJsDeferred(JSVM_Deferred local)
88 {
89     return reinterpret_cast<v8impl::Persistent<v8::Value>*>(local);
90 }
91 
92 class HandleScopeWrapper {
93 public:
HandleScopeWrapper(v8::Isolate * isolate)94     explicit HandleScopeWrapper(v8::Isolate* isolate) : scope(isolate) {}
95 
96 private:
97     v8::HandleScope scope;
98 };
99 
100 class EscapableHandleScopeWrapper {
101 public:
EscapableHandleScopeWrapper(v8::Isolate * isolate)102     explicit EscapableHandleScopeWrapper(v8::Isolate* isolate) : scope(isolate), escapeCalled(false) {}
IsEscapeCalled()103     bool IsEscapeCalled() const
104     {
105         return escapeCalled;
106     }
107     template<typename T>
Escape(v8::Local<T> handle)108     v8::Local<T> Escape(v8::Local<T> handle)
109     {
110         escapeCalled = true;
111         return scope.Escape(handle);
112     }
113 
114 private:
115     v8::EscapableHandleScope scope;
116     bool escapeCalled;
117 };
118 
JsHandleScopeFromV8HandleScope(HandleScopeWrapper * s)119 inline JSVM_HandleScope JsHandleScopeFromV8HandleScope(HandleScopeWrapper* s)
120 {
121     return reinterpret_cast<JSVM_HandleScope>(s);
122 }
123 
V8HandleScopeFromJsHandleScope(JSVM_HandleScope s)124 inline HandleScopeWrapper* V8HandleScopeFromJsHandleScope(JSVM_HandleScope s)
125 {
126     return reinterpret_cast<HandleScopeWrapper*>(s);
127 }
128 
JsEscapableHandleScopeFromV8EscapableHandleScope(EscapableHandleScopeWrapper * s)129 inline JSVM_EscapableHandleScope JsEscapableHandleScopeFromV8EscapableHandleScope(EscapableHandleScopeWrapper* s)
130 {
131     return reinterpret_cast<JSVM_EscapableHandleScope>(s);
132 }
133 
V8EscapableHandleScopeFromJsEscapableHandleScope(JSVM_EscapableHandleScope s)134 inline EscapableHandleScopeWrapper* V8EscapableHandleScopeFromJsEscapableHandleScope(JSVM_EscapableHandleScope s)
135 {
136     return reinterpret_cast<EscapableHandleScopeWrapper*>(s);
137 }
138 
139 // Convert a v8::PersistentBase, e.g. v8::Global, to a Local, with an extra
140 // optimization for strong persistent handles.
141 class PersistentToLocal {
142 public:
143     // Convert v8::Global to v8::Local
144     template<class TypeName>
Default(v8::Isolate * isolate,const v8::PersistentBase<TypeName> & persistent)145     static inline v8::Local<TypeName> Default(v8::Isolate* isolate, const v8::PersistentBase<TypeName>& persistent)
146     {
147         if (persistent.IsWeak()) {
148             return PersistentToLocal::Weak(isolate, persistent);
149         } else {
150             return PersistentToLocal::Strong(persistent);
151         }
152     }
153 
154     template<class TypeName>
Strong(const v8::PersistentBase<TypeName> & persistent)155     static inline v8::Local<TypeName> Strong(const v8::PersistentBase<TypeName>& persistent)
156     {
157         DCHECK(!persistent.IsWeak());
158         return *reinterpret_cast<v8::Local<TypeName>*>(const_cast<v8::PersistentBase<TypeName>*>(&persistent));
159     }
160 
161     template<class TypeName>
Weak(v8::Isolate * isolate,const v8::PersistentBase<TypeName> & persistent)162     static inline v8::Local<TypeName> Weak(v8::Isolate* isolate, const v8::PersistentBase<TypeName>& persistent)
163     {
164         return v8::Local<TypeName>::New(isolate, persistent);
165     }
166 };
167 } // namespace v8impl
168 
169 #endif