1 // Copyright Joyent, Inc. and other Node contributors. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a 4 // copy of this software and associated documentation files (the 5 // "Software"), to deal in the Software without restriction, including 6 // without limitation the rights to use, copy, modify, merge, publish, 7 // distribute, sublicense, and/or sell copies of the Software, and to permit 8 // persons to whom the Software is furnished to do so, subject to the 9 // following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included 12 // in all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22 #ifndef SRC_NODE_OBJECT_WRAP_H_ 23 #define SRC_NODE_OBJECT_WRAP_H_ 24 25 #include "v8.h" 26 #include <cassert> 27 28 29 namespace node { 30 31 class ObjectWrap { 32 public: ObjectWrap()33 ObjectWrap() { 34 refs_ = 0; 35 } 36 37 ~ObjectWrap()38 virtual ~ObjectWrap() { 39 if (persistent().IsEmpty()) 40 return; 41 persistent().ClearWeak(); 42 persistent().Reset(); 43 } 44 45 46 template <class T> Unwrap(v8::Local<v8::Object> handle)47 static inline T* Unwrap(v8::Local<v8::Object> handle) { 48 assert(!handle.IsEmpty()); 49 assert(handle->InternalFieldCount() > 0); 50 // Cast to ObjectWrap before casting to T. A direct cast from void 51 // to T won't work right when T has more than one base class. 52 void* ptr = handle->GetAlignedPointerFromInternalField(0); 53 ObjectWrap* wrap = static_cast<ObjectWrap*>(ptr); 54 return static_cast<T*>(wrap); 55 } 56 57 handle()58 inline v8::Local<v8::Object> handle() { 59 return handle(v8::Isolate::GetCurrent()); 60 } 61 62 handle(v8::Isolate * isolate)63 inline v8::Local<v8::Object> handle(v8::Isolate* isolate) { 64 return v8::Local<v8::Object>::New(isolate, persistent()); 65 } 66 67 68 // NOLINTNEXTLINE(runtime/v8_persistent) persistent()69 inline v8::Persistent<v8::Object>& persistent() { 70 return handle_; 71 } 72 73 74 protected: Wrap(v8::Local<v8::Object> handle)75 inline void Wrap(v8::Local<v8::Object> handle) { 76 assert(persistent().IsEmpty()); 77 assert(handle->InternalFieldCount() > 0); 78 handle->SetAlignedPointerInInternalField(0, this); 79 persistent().Reset(v8::Isolate::GetCurrent(), handle); 80 MakeWeak(); 81 } 82 83 MakeWeak()84 inline void MakeWeak() { 85 persistent().SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter); 86 } 87 88 /* Ref() marks the object as being attached to an event loop. 89 * Refed objects will not be garbage collected, even if 90 * all references are lost. 91 */ Ref()92 virtual void Ref() { 93 assert(!persistent().IsEmpty()); 94 persistent().ClearWeak(); 95 refs_++; 96 } 97 98 /* Unref() marks an object as detached from the event loop. This is its 99 * default state. When an object with a "weak" reference changes from 100 * attached to detached state it will be freed. Be careful not to access 101 * the object after making this call as it might be gone! 102 * (A "weak reference" means an object that only has a 103 * persistent handle.) 104 * 105 * DO NOT CALL THIS FROM DESTRUCTOR 106 */ Unref()107 virtual void Unref() { 108 assert(!persistent().IsEmpty()); 109 assert(!persistent().IsWeak()); 110 assert(refs_ > 0); 111 if (--refs_ == 0) 112 MakeWeak(); 113 } 114 115 int refs_; // ro 116 117 private: WeakCallback(const v8::WeakCallbackInfo<ObjectWrap> & data)118 static void WeakCallback( 119 const v8::WeakCallbackInfo<ObjectWrap>& data) { 120 ObjectWrap* wrap = data.GetParameter(); 121 assert(wrap->refs_ == 0); 122 wrap->handle_.Reset(); 123 delete wrap; 124 } 125 126 // NOLINTNEXTLINE(runtime/v8_persistent) 127 v8::Persistent<v8::Object> handle_; 128 }; 129 130 } // namespace node 131 132 #endif // SRC_NODE_OBJECT_WRAP_H_ 133