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