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