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 SRC_JSVM_REFERENCE_ 17 #define SRC_JSVM_REFERENCE_ 18 #include <cstdint> 19 20 #include "jsvm_types.h" 21 #include "jsvm_util.h" 22 23 namespace v8impl { 24 class RefTracker; 25 using RefList = RefTracker; 26 27 class RefTracker { 28 public: RefTracker()29 RefTracker() : next(nullptr), prev(nullptr) {} 30 31 virtual ~RefTracker() = default; 32 33 static void FinalizeAll(RefList* list); 34 35 protected: 36 virtual void Finalize(); 37 38 inline void Link(RefList* list); 39 Unlink()40 inline void Unlink() 41 { 42 if (prev != nullptr) { 43 prev->next = next; 44 } 45 if (next != nullptr) { 46 next->prev = prev; 47 } 48 prev = nullptr; 49 next = nullptr; 50 } 51 52 private: 53 RefList* next; 54 RefList* prev; 55 }; 56 57 class UserReference final : public RefTracker { 58 public: 59 static UserReference* New(JSVM_Env env, v8::Local<v8::Value> value, uint32_t initialRefcount); 60 61 static UserReference* NewData(JSVM_Env env, v8::Local<v8::Data> data, uint32_t initialRefcount); 62 63 ~UserReference() override; 64 65 // Increase and decrease reference 66 uint32_t Ref(); 67 uint32_t Unref(); 68 uint32_t RefCount(); 69 70 // Get v8::Local value 71 v8::Local<v8::Value> Get(); 72 v8::Local<v8::Data> GetData(); 73 IsValue()74 bool IsValue() 75 { 76 return isValue; 77 } 78 79 protected: 80 UserReference(JSVM_Env env, v8::Local<v8::Data> value, bool isValue, uint32_t initialRefcount); 81 82 void Finalize() override; 83 84 private: 85 void SetWeak(); 86 87 private: 88 v8impl::Persistent<v8::Data> persistent; 89 bool isValue; 90 JSVM_Env env; 91 uint32_t refcount; 92 bool canBeWeak; 93 }; 94 95 class FinalizerTracker : public RefTracker { 96 protected: 97 FinalizerTracker(JSVM_Env env, JSVM_Finalize cb, void* data, void* hint); 98 99 public: 100 static FinalizerTracker* New(JSVM_Env env, JSVM_Finalize cb, void* finalizeData, void* finalizeHint); 101 102 ~FinalizerTracker() override; 103 GetData()104 void* GetData() 105 { 106 return data; 107 } 108 109 protected: 110 void ResetFinalizer(); 111 112 void CallFinalizer(); 113 114 void Finalize() override; 115 ResetEnv()116 void ResetEnv() 117 { 118 env = nullptr; 119 } 120 121 private: 122 JSVM_Env env; 123 JSVM_Finalize cb; 124 void* data; 125 void* hint; 126 }; 127 128 class RuntimeReference : public FinalizerTracker { 129 protected: 130 RuntimeReference(JSVM_Env env, v8::Local<v8::Value> value, JSVM_Finalize cb, void* data, void* hint); 131 132 public: 133 static RuntimeReference* New(JSVM_Env env, v8::Local<v8::Value> value, void* data); 134 static RuntimeReference* New(JSVM_Env env, v8::Local<v8::Value> value, JSVM_Finalize cb, void* data, void* hint); 135 static void DeleteReference(RuntimeReference* ref); 136 137 private: 138 inline void SetWeak(bool needSecondPass); 139 static void FirstPassCallback(const v8::WeakCallbackInfo<RuntimeReference>& data); 140 static void SecondPassCallback(const v8::WeakCallbackInfo<RuntimeReference>& data); 141 static void FirstPassCallbackWithoutFinalizer(const v8::WeakCallbackInfo<RuntimeReference>& data); 142 143 private: 144 v8impl::Persistent<v8::Value> persistent; 145 }; 146 147 class TrackedStringResource : public FinalizerTracker { 148 public: TrackedStringResource(JSVM_Env env,JSVM_Finalize finalizeCallback,void * data,void * finalizeHint)149 TrackedStringResource(JSVM_Env env, JSVM_Finalize finalizeCallback, void* data, void* finalizeHint) 150 : FinalizerTracker(env, finalizeCallback, data, finalizeHint) 151 {} 152 153 protected: 154 // The only time Finalize() gets called before Dispose() is if the 155 // environment is dying. Finalize() expects that the item will be unlinked, 156 // so we do it here. V8 will still call Dispose() on us later, so we don't do 157 // any deleting here. We just null out env_ to avoid passing a stale pointer 158 // to the user's finalizer when V8 does finally call Dispose(). Finalize()159 void Finalize() override 160 { 161 Unlink(); 162 ResetEnv(); 163 } 164 ~TrackedStringResource()165 ~TrackedStringResource() override 166 { 167 CallFinalizer(); 168 } 169 }; 170 171 class ExternalOneByteStringResource : public v8::String::ExternalOneByteStringResource, TrackedStringResource { 172 public: ExternalOneByteStringResource(JSVM_Env env,char * string,const size_t length,JSVM_Finalize finalizeCallback,void * finalizeHint)173 ExternalOneByteStringResource(JSVM_Env env, 174 char* string, 175 const size_t length, 176 JSVM_Finalize finalizeCallback, 177 void* finalizeHint) 178 : TrackedStringResource(env, finalizeCallback, string, finalizeHint), string_(string), length_(length) 179 {} 180 data()181 const char* data() const override 182 { 183 return string_; 184 } length()185 size_t length() const override 186 { 187 return length_; 188 } 189 190 private: 191 const char* string_; 192 const size_t length_; 193 }; 194 195 class ExternalStringResource : public v8::String::ExternalStringResource, TrackedStringResource { 196 public: ExternalStringResource(JSVM_Env env,char16_t * string,const size_t length,JSVM_Finalize finalizeCallback,void * finalizeHint)197 ExternalStringResource(JSVM_Env env, 198 char16_t* string, 199 const size_t length, 200 JSVM_Finalize finalizeCallback, 201 void* finalizeHint) 202 : TrackedStringResource(env, finalizeCallback, string, finalizeHint), 203 string_(reinterpret_cast<uint16_t*>(string)), length_(length) 204 {} 205 data()206 const uint16_t* data() const override 207 { 208 return string_; 209 } length()210 size_t length() const override 211 { 212 return length_; 213 } 214 215 private: 216 const uint16_t* string_; 217 const size_t length_; 218 }; 219 220 } // namespace v8impl 221 222 #endif