diff --git a/native_mate/constructor.h b/native_mate/constructor.h index 98cd62bde89d..65c16c335988 100644 --- a/native_mate/constructor.h +++ b/native_mate/constructor.h @@ -16,59 +16,59 @@ namespace mate { -class Wrappable; +class WrappableBase; namespace internal { // This set of templates invokes a base::Callback by converting the Arguments // into native types. It relies on the function_template.h to provide helper // templates. -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { return callback.Run(); }; template -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; if (!GetNextArgument(args, 0, true, &a1)) - return NULL; + return nullptr; return callback.Run(a1); }; template -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; if (!GetNextArgument(args, 0, true, &a1) || !GetNextArgument(args, 0, false, &a2)) - return NULL; + return nullptr; return callback.Run(a1, a2); }; template -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; if (!GetNextArgument(args, 0, true, &a1) || !GetNextArgument(args, 0, false, &a2) || !GetNextArgument(args, 0, false, &a3)) - return NULL; + return nullptr; return callback.Run(a1, a2, a3); }; template -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; @@ -77,14 +77,14 @@ inline Wrappable* InvokeFactory( !GetNextArgument(args, 0, false, &a2) || !GetNextArgument(args, 0, false, &a3) || !GetNextArgument(args, 0, false, &a4)) - return NULL; + return nullptr; return callback.Run(a1, a2, a3, a4); }; template -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; @@ -95,15 +95,15 @@ inline Wrappable* InvokeFactory( !GetNextArgument(args, 0, false, &a3) || !GetNextArgument(args, 0, false, &a4) || !GetNextArgument(args, 0, false, &a5)) - return NULL; + return nullptr; return callback.Run(a1, a2, a3, a4, a5); }; template -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { typename CallbackParamTraits::LocalType a1; typename CallbackParamTraits::LocalType a2; typename CallbackParamTraits::LocalType a3; @@ -116,7 +116,7 @@ inline Wrappable* InvokeFactory( !GetNextArgument(args, 0, false, &a4) || !GetNextArgument(args, 0, false, &a5) || !GetNextArgument(args, 0, false, &a6)) - return NULL; + return nullptr; return callback.Run(a1, a2, a3, a4, a5, a6); }; @@ -156,7 +156,7 @@ class Constructor { MATE_METHOD_RETURN_UNDEFINED(); } - Wrappable* object; + WrappableBase* object; { // Don't continue if the constructor throws an exception. v8::TryCatch try_catch; @@ -168,7 +168,7 @@ class Constructor { } if (object) - object->Wrap(isolate, args->GetThis()); + object->InitWith(isolate, args->GetThis()); else args->ThrowError(); @@ -176,14 +176,14 @@ class Constructor { } base::StringPiece name_; - v8::UniquePersistent constructor_; + v8::Global constructor_; DISALLOW_COPY_AND_ASSIGN(Constructor); }; template -Wrappable* NewOperatorFactory() { +WrappableBase* NewOperatorFactory() { return new T; } diff --git a/native_mate/constructor.h.pump b/native_mate/constructor.h.pump index ec4944f4eb2f..540493ccd530 100644 --- a/native_mate/constructor.h.pump +++ b/native_mate/constructor.h.pump @@ -19,7 +19,7 @@ $var MAX_ARITY = 6 namespace mate { -class Wrappable; +class WrappableBase; namespace internal { @@ -37,9 +37,9 @@ $if ARITY == 0 [[ template<$for ARG , [[typename P$(ARG)]]> ]] -inline Wrappable* InvokeFactory( +inline WrappableBase* InvokeFactory( Arguments* args, - const base::Callback& callback) { + const base::Callback& callback) { $if ARITY != 0 [[ @@ -48,7 +48,7 @@ $for ARG [[ typename CallbackParamTraits::LocalType a$(ARG); ]] if ($for ARG || [[!GetNextArgument(args, 0, $if ARG == 1 [[true]] $else [[false]], &a$(ARG))]]) - return NULL; + return nullptr; ]] return callback.Run($for ARG , [[a$(ARG)]]); @@ -92,7 +92,7 @@ class Constructor { MATE_METHOD_RETURN_UNDEFINED(); } - Wrappable* object; + WrappableBase* object; { // Don't continue if the constructor throws an exception. v8::TryCatch try_catch; @@ -104,7 +104,7 @@ class Constructor { } if (object) - object->Wrap(isolate, args->GetThis()); + object->InitWith(isolate, args->GetThis()); else args->ThrowError(); @@ -112,14 +112,14 @@ class Constructor { } base::StringPiece name_; - v8::UniquePersistent constructor_; + v8::Global constructor_; DISALLOW_COPY_AND_ASSIGN(Constructor); }; template -Wrappable* NewOperatorFactory() { +WrappableBase* NewOperatorFactory() { return new T; } diff --git a/native_mate/function_template.h b/native_mate/function_template.h index b1d0764688a1..0a607c0da05a 100644 --- a/native_mate/function_template.h +++ b/native_mate/function_template.h @@ -22,7 +22,8 @@ namespace internal { struct Destroyable { static void Destroy(Arguments* args) { v8::Local holder = args->GetHolder(); - delete static_cast(holder->GetAlignedPointerFromInternalField(0)); + delete static_cast( + holder->GetAlignedPointerFromInternalField(0)); holder->SetAlignedPointerInInternalField(0, nullptr); } static bool IsDestroyed(Arguments* args) { diff --git a/native_mate/handle.h b/native_mate/handle.h index 15e0bb5bb8f6..0fbd171319a8 100644 --- a/native_mate/handle.h +++ b/native_mate/handle.h @@ -60,7 +60,7 @@ struct Converter > { // without having to write out the type of the object explicitly. template mate::Handle CreateHandle(v8::Isolate* isolate, T* object) { - return mate::Handle(object->GetWrapper(isolate), object); + return mate::Handle(object->GetWrapper(), object); } } // namespace mate diff --git a/native_mate/wrappable.cc b/native_mate/wrappable.cc index 3edb3b6d3f0f..c42bc96dab64 100644 --- a/native_mate/wrappable.cc +++ b/native_mate/wrappable.cc @@ -10,21 +10,25 @@ namespace mate { -Wrappable::Wrappable() : isolate_(NULL) { +WrappableBase::WrappableBase() + : isolate_(nullptr) { } -Wrappable::~Wrappable() { +WrappableBase::~WrappableBase() { if (!wrapper_.IsEmpty()) - GetWrapper(isolate())->SetAlignedPointerInInternalField(0, nullptr); + GetWrapper()->SetAlignedPointerInInternalField(0, nullptr); wrapper_.Reset(); } -void Wrappable::Wrap(v8::Isolate* isolate, v8::Local wrapper) { - if (!wrapper_.IsEmpty()) - return; +v8::Local WrappableBase::GetWrapper() { + CHECK(!wrapper_.IsEmpty()); + return v8::Local::New(isolate_, wrapper_); +} +void WrappableBase::InitWith(v8::Isolate* isolate, + v8::Local wrapper) { + CHECK(wrapper_.IsEmpty()); isolate_ = isolate; - wrapper->SetAlignedPointerInInternalField(0, this); wrapper_.Reset(isolate, wrapper); wrapper_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter); @@ -38,57 +42,29 @@ void Wrappable::Wrap(v8::Isolate* isolate, v8::Local wrapper) { } // static -void Wrappable::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { -} - -ObjectTemplateBuilder Wrappable::GetObjectTemplateBuilder( - v8::Isolate* isolate) { - return ObjectTemplateBuilder(isolate); -} - -void Wrappable::FirstWeakCallback(const v8::WeakCallbackInfo& data) { - Wrappable* wrappable = data.GetParameter(); +void WrappableBase::FirstWeakCallback( + const v8::WeakCallbackInfo& data) { + WrappableBase* wrappable = data.GetParameter(); wrappable->wrapper_.Reset(); data.SetSecondPassCallback(SecondWeakCallback); } -void Wrappable::SecondWeakCallback( - const v8::WeakCallbackInfo& data) { - Wrappable* wrappable = data.GetParameter(); +// static +void WrappableBase::SecondWeakCallback( + const v8::WeakCallbackInfo& data) { + WrappableBase* wrappable = data.GetParameter(); delete wrappable; } -v8::Local Wrappable::GetWrapper(v8::Isolate* isolate) { - if (!wrapper_.IsEmpty()) - return MATE_PERSISTENT_TO_LOCAL(v8::Object, isolate, wrapper_); - - v8::Local templ = - GetObjectTemplateBuilder(isolate).Build(); - CHECK(!templ.IsEmpty()); - CHECK_EQ(1, templ->InternalFieldCount()); - v8::Local wrapper; - // |wrapper| may be empty in some extreme cases, e.g., when - // Object.prototype.constructor is overwritten. - if (!templ->NewInstance(isolate->GetCurrentContext()).ToLocal(&wrapper)) { - // The current wrappable object will be no longer managed by V8. Delete this - // now. - delete this; - return wrapper; - } - Wrap(isolate, wrapper); - return wrapper; -} - namespace internal { void* FromV8Impl(v8::Isolate* isolate, v8::Local val) { if (!val->IsObject()) - return NULL; + return nullptr; v8::Local obj = v8::Local::Cast(val); if (obj->InternalFieldCount() != 1) - return NULL; - return MATE_GET_INTERNAL_FIELD_POINTER(obj, 0); + return nullptr; + return obj->GetAlignedPointerFromInternalField(0); } } // namespace internal diff --git a/native_mate/wrappable.h b/native_mate/wrappable.h index 25338399b37d..0cc1e3b8e127 100644 --- a/native_mate/wrappable.h +++ b/native_mate/wrappable.h @@ -27,83 +27,102 @@ void* FromV8Impl(v8::Isolate* isolate, v8::Local val); // // my_class.h // class MyClass : Wrappable { // public: -// // Optional, only required if non-empty template should be used. -// virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder( -// v8::Isolate* isolate); // ... // }; // -// // my_class.cc -// gin::ObjectTemplateBuilder MyClass::GetObjectTemplateBuilder( -// v8::Isolate* isolate) { -// return Wrappable::GetObjectTemplateBuilder(isolate) -// .SetValue("foobar", 42); -// } -// // Subclasses should also typically have private constructors and expose a // static Create function that returns a mate::Handle. Forcing creators through // this static Create function will enforce that clients actually create a // wrapper for the object. If clients fail to create a wrapper for a wrappable // object, the object will leak because we use the weak callback from the // wrapper as the signal to delete the wrapped object. -class ObjectTemplateBuilder; - -class Wrappable { +class WrappableBase { public: - // Retrieve (or create) the v8 wrapper object cooresponding to this object. - // If the type is created via the Constructor, then the GetWrapper would - // return the constructed object, otherwise it would try to create a new - // object constructed by GetObjectTemplateBuilder. - v8::Local GetWrapper(v8::Isolate* isolate); + WrappableBase(); + virtual ~WrappableBase(); + + // Retrieve the v8 wrapper object cooresponding to this object. + v8::Local GetWrapper(); // Returns the Isolate this object is created in. v8::Isolate* isolate() const { return isolate_; } // Bind the C++ class to the JS wrapper. - void Wrap(v8::Isolate* isolate, v8::Local wrapper); - - // The user should define T::BuildPrototype if they want to use Constructor - // to build a constructor function for this type. - static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + void InitWith(v8::Isolate* isolate, v8::Local wrapper); protected: - Wrappable(); - virtual ~Wrappable(); - - virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate); - // Called after the "_init" method gets called in JavaScript. + // FIXME(zcbenz): Should remove this. virtual void AfterInit(v8::Isolate* isolate) {} private: friend struct internal::Destroyable; - static void FirstWeakCallback(const v8::WeakCallbackInfo& data); - static void SecondWeakCallback(const v8::WeakCallbackInfo& data); + static void FirstWeakCallback( + const v8::WeakCallbackInfo& data); + static void SecondWeakCallback( + const v8::WeakCallbackInfo& data); v8::Isolate* isolate_; - v8::UniquePersistent wrapper_; // Weak + v8::Global wrapper_; // Weak + + DISALLOW_COPY_AND_ASSIGN(WrappableBase); +}; + +template +class Wrappable : public WrappableBase { + public: + Wrappable() {} + + // Init the class with T::BuildPrototype. + void Init(v8::Isolate* isolate) { + // Fill the object template. + if (templ_.IsEmpty()) { + v8::Local templ = v8::ObjectTemplate::New(isolate); + T::BuildPrototype(isolate, templ); + templ_.Reset(isolate, templ); + } + + v8::Local wrapper; + v8::Local templ = v8::Local::New( + isolate, templ_); + // |wrapper| may be empty in some extreme cases, e.g., when + // Object.prototype.constructor is overwritten. + if (!templ->NewInstance(isolate->GetCurrentContext()).ToLocal(&wrapper)) { + // The current wrappable object will be no longer managed by V8. Delete + // this now. + delete this; + return; + } + InitWith(isolate, wrapper); + } + + private: + static v8::Global templ_; DISALLOW_COPY_AND_ASSIGN(Wrappable); }; +// static +template +v8::Global Wrappable::templ_; // This converter handles any subclass of Wrappable. -template -struct Converter::value>::type> { +template +struct Converter::value>::type> { static v8::Local ToV8(v8::Isolate* isolate, T* val) { if (val) - return val->GetWrapper(isolate); + return val->GetWrapper(); else return v8::Null(isolate); } static bool FromV8(v8::Isolate* isolate, v8::Local val, T** out) { - *out = static_cast(static_cast( + *out = static_cast(static_cast( internal::FromV8Impl(isolate, val))); - return *out != NULL; + return *out != nullptr; } };