// 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 "gin/per_isolate_data.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); gin::PerIsolateData::From(isolate)->SetFunctionTemplate( &kWrapperInfo, templ); } static v8::Local GetConstructor(v8::Isolate* isolate) { // Fill the object template. auto data = gin::PerIsolateData::From(isolate); auto templ = data->GetFunctionTemplate(&kWrapperInfo); if (templ.IsEmpty()) { templ = v8::FunctionTemplate::New(isolate); templ->InstanceTemplate()->SetInternalFieldCount(1); T::BuildPrototype(isolate, templ); data->SetFunctionTemplate(&kWrapperInfo, templ); } return 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 gin::WrapperInfo kWrapperInfo; DISALLOW_COPY_AND_ASSIGN(Wrappable); }; // static template gin::WrapperInfo Wrappable::kWrapperInfo = { gin::kEmbedderNativeGin }; // 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_