// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE.chromium file. #ifndef NATIVE_MATE_WRAPPABLE_H_ #define NATIVE_MATE_WRAPPABLE_H_ #include "base/bind.h" #include "native_mate/compat.h" #include "native_mate/converter.h" #include "native_mate/constructor.h" #include "native_mate/template_util.h" namespace mate { namespace internal { void* FromV8Impl(v8::Isolate* isolate, v8::Local val); } // namespace internal template class Wrappable : public WrappableBase { public: Wrappable() {} template static void SetConstructor(v8::Isolate* isolate, const base::Callback& constructor) { v8::Local templ = CreateFunctionTemplate( isolate, base::Bind(&internal::InvokeNew, constructor)); templ->InstanceTemplate()->SetInternalFieldCount(1); T::BuildPrototype(isolate, templ); templ_ = new v8::Global(isolate, templ); } static v8::Local GetConstructor(v8::Isolate* isolate) { // Fill the object template. if (!templ_) { v8::Local templ = v8::FunctionTemplate::New(isolate); templ->InstanceTemplate()->SetInternalFieldCount(1); T::BuildPrototype(isolate, templ); templ_ = new v8::Global(isolate, templ); } return v8::Local::New(isolate, *templ_); } protected: // Init the class with T::BuildPrototype. void Init(v8::Isolate* isolate) { v8::Local templ = GetConstructor(isolate); // |wrapper| may be empty in some extreme cases, e.g., when // Object.prototype.constructor is overwritten. v8::Local wrapper; if (!templ->InstanceTemplate()->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_; // Leaked on purpose DISALLOW_COPY_AND_ASSIGN(Wrappable); }; // static template v8::Global* Wrappable::templ_ = nullptr; // This converter handles any subclass of Wrappable. template struct Converter::value>::type> { static v8::Local ToV8(v8::Isolate* isolate, T* val) { if (val) return val->GetWrapper(); else return v8::Null(isolate); } static bool FromV8(v8::Isolate* isolate, v8::Local val, T** out) { *out = static_cast(static_cast( internal::FromV8Impl(isolate, val))); return *out != nullptr; } }; } // namespace mate #endif // NATIVE_MATE_WRAPPABLE_H_