// 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 ELECTRON_SHELL_COMMON_GIN_HELPER_WRAPPABLE_H_ #define ELECTRON_SHELL_COMMON_GIN_HELPER_WRAPPABLE_H_ #include "base/bind.h" #include "gin/per_isolate_data.h" #include "shell/common/gin_helper/constructor.h" namespace gin_helper { namespace internal { void* FromV8Impl(v8::Isolate* isolate, v8::Local val); } // namespace internal template class Wrappable : public WrappableBase { public: Wrappable() = default; template static void SetConstructor(v8::Isolate* isolate, const base::RepeatingCallback& constructor) { v8::Local templ = gin_helper::CreateFunctionTemplate( isolate, base::BindRepeating(&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; }; // static template gin::WrapperInfo Wrappable::kWrapperInfo = {gin::kEmbedderNativeGin}; } // namespace gin_helper namespace gin { template struct Converter< T*, typename std::enable_if< std::is_convertible::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( gin_helper::internal::FromV8Impl(isolate, val))); return *out != nullptr; } }; } // namespace gin #endif // ELECTRON_SHELL_COMMON_GIN_HELPER_WRAPPABLE_H_