chore: move gin::Handle to gin_helper (#48016)

chore: move gin::Handle to gin_helper (#47959)

* chore: move gin::Handle to gin_helper

* chore: fix lint

Co-authored-by: Robo <hop2deep@gmail.com>
This commit is contained in:
Calvin
2025-08-10 13:46:37 -06:00
committed by GitHub
parent 89d5b6cd5b
commit e3f358a45a
95 changed files with 555 additions and 419 deletions

View File

@@ -4,11 +4,11 @@
#include <vector>
#include "gin/handle.h"
#include "shell/common/asar/archive.h"
#include "shell/common/asar/asar_util.h"
#include "shell/common/gin_converters/file_path_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/handle.h"
#include "shell/common/node_includes.h"
namespace {

View File

@@ -16,7 +16,6 @@
#include "base/strings/pattern.h"
#include "base/strings/utf_string_conversions.h"
#include "gin/arguments.h"
#include "gin/handle.h"
#include "gin/object_template_builder.h"
#include "gin/per_isolate_data.h"
#include "net/base/data_url.h"
@@ -29,6 +28,7 @@
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/error_thrower.h"
#include "shell/common/gin_helper/function_template_extensions.h"
#include "shell/common/gin_helper/handle.h"
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/node_includes.h"
#include "shell/common/node_util.h"
@@ -338,8 +338,8 @@ float NativeImage::GetAspectRatio(const std::optional<float> scale_factor) {
return static_cast<float>(size.width()) / static_cast<float>(size.height());
}
gin::Handle<NativeImage> NativeImage::Resize(gin::Arguments* args,
base::Value::Dict options) {
gin_helper::Handle<NativeImage> NativeImage::Resize(gin::Arguments* args,
base::Value::Dict options) {
float scale_factor = GetScaleFactorFromOptions(args);
gfx::Size size = GetSize(scale_factor);
@@ -375,8 +375,8 @@ gin::Handle<NativeImage> NativeImage::Resize(gin::Arguments* args,
image_.AsImageSkia(), method, size)});
}
gin::Handle<NativeImage> NativeImage::Crop(v8::Isolate* isolate,
const gfx::Rect& rect) {
gin_helper::Handle<NativeImage> NativeImage::Crop(v8::Isolate* isolate,
const gfx::Rect& rect) {
return Create(isolate, gfx::Image{gfx::ImageSkiaOperations::ExtractSubset(
image_.AsImageSkia(), rect)});
}
@@ -424,18 +424,18 @@ bool NativeImage::IsTemplateImage() {
#endif
// static
gin::Handle<NativeImage> NativeImage::CreateEmpty(v8::Isolate* isolate) {
gin_helper::Handle<NativeImage> NativeImage::CreateEmpty(v8::Isolate* isolate) {
return Create(isolate, gfx::Image{});
}
// static
gin::Handle<NativeImage> NativeImage::Create(v8::Isolate* isolate,
const gfx::Image& image) {
return gin::CreateHandle(isolate, new NativeImage(isolate, image));
gin_helper::Handle<NativeImage> NativeImage::Create(v8::Isolate* isolate,
const gfx::Image& image) {
return gin_helper::CreateHandle(isolate, new NativeImage(isolate, image));
}
// static
gin::Handle<NativeImage> NativeImage::CreateFromPNG(
gin_helper::Handle<NativeImage> NativeImage::CreateFromPNG(
v8::Isolate* isolate,
const base::span<const uint8_t> data) {
gfx::ImageSkia image_skia;
@@ -444,7 +444,7 @@ gin::Handle<NativeImage> NativeImage::CreateFromPNG(
}
// static
gin::Handle<NativeImage> NativeImage::CreateFromJPEG(
gin_helper::Handle<NativeImage> NativeImage::CreateFromJPEG(
v8::Isolate* isolate,
const base::span<const uint8_t> buffer) {
gfx::ImageSkia image_skia;
@@ -453,19 +453,20 @@ gin::Handle<NativeImage> NativeImage::CreateFromJPEG(
}
// static
gin::Handle<NativeImage> NativeImage::CreateFromPath(
gin_helper::Handle<NativeImage> NativeImage::CreateFromPath(
v8::Isolate* isolate,
const base::FilePath& path) {
base::FilePath image_path = NormalizePath(path);
#if BUILDFLAG(IS_WIN)
if (image_path.MatchesExtension(FILE_PATH_LITERAL(".ico"))) {
return gin::CreateHandle(isolate, new NativeImage(isolate, image_path));
return gin_helper::CreateHandle(isolate,
new NativeImage(isolate, image_path));
}
#endif
gfx::ImageSkia image_skia;
electron::util::PopulateImageSkiaRepsFromPath(&image_skia, image_path);
gfx::Image image(image_skia);
gin::Handle<NativeImage> handle = Create(isolate, image);
gin_helper::Handle<NativeImage> handle = Create(isolate, image);
#if BUILDFLAG(IS_MAC)
if (IsTemplateFilename(image_path))
handle->SetTemplateImage(true);
@@ -474,7 +475,7 @@ gin::Handle<NativeImage> NativeImage::CreateFromPath(
}
// static
gin::Handle<NativeImage> NativeImage::CreateFromBitmap(
gin_helper::Handle<NativeImage> NativeImage::CreateFromBitmap(
gin_helper::ErrorThrower thrower,
v8::Local<v8::Value> buffer,
const gin_helper::Dictionary& options) {
@@ -520,7 +521,7 @@ gin::Handle<NativeImage> NativeImage::CreateFromBitmap(
}
// static
gin::Handle<NativeImage> NativeImage::CreateFromBuffer(
gin_helper::Handle<NativeImage> NativeImage::CreateFromBuffer(
gin_helper::ErrorThrower thrower,
v8::Local<v8::Value> buffer,
gin::Arguments* args) {
@@ -548,8 +549,9 @@ gin::Handle<NativeImage> NativeImage::CreateFromBuffer(
}
// static
gin::Handle<NativeImage> NativeImage::CreateFromDataURL(v8::Isolate* isolate,
const GURL& url) {
gin_helper::Handle<NativeImage> NativeImage::CreateFromDataURL(
v8::Isolate* isolate,
const GURL& url) {
std::string mime_type, charset, data;
if (net::DataURL::Parse(url, &mime_type, &charset, &data)) {
if (mime_type == "image/png")
@@ -562,8 +564,9 @@ gin::Handle<NativeImage> NativeImage::CreateFromDataURL(v8::Isolate* isolate,
}
#if !BUILDFLAG(IS_MAC)
gin::Handle<NativeImage> NativeImage::CreateFromNamedImage(gin::Arguments* args,
std::string name) {
gin_helper::Handle<NativeImage> NativeImage::CreateFromNamedImage(
gin::Arguments* args,
std::string name) {
return CreateEmpty(args->isolate());
}
#endif

View File

@@ -34,14 +34,13 @@ class Size;
namespace gin {
class Arguments;
template <typename T>
class Handle;
} // namespace gin
namespace gin_helper {
class Dictionary;
class ErrorThrower;
template <typename T>
class Handle;
} // namespace gin_helper
namespace electron::api {
@@ -58,28 +57,31 @@ class NativeImage final : public gin_helper::DeprecatedWrappable<NativeImage> {
NativeImage(const NativeImage&) = delete;
NativeImage& operator=(const NativeImage&) = delete;
static gin::Handle<NativeImage> CreateEmpty(v8::Isolate* isolate);
static gin::Handle<NativeImage> Create(v8::Isolate* isolate,
const gfx::Image& image);
static gin::Handle<NativeImage> CreateFromPNG(v8::Isolate* isolate,
base::span<const uint8_t> data);
static gin::Handle<NativeImage> CreateFromJPEG(
static gin_helper::Handle<NativeImage> CreateEmpty(v8::Isolate* isolate);
static gin_helper::Handle<NativeImage> Create(v8::Isolate* isolate,
const gfx::Image& image);
static gin_helper::Handle<NativeImage> CreateFromPNG(
v8::Isolate* isolate,
base::span<const uint8_t> data);
static gin::Handle<NativeImage> CreateFromPath(v8::Isolate* isolate,
const base::FilePath& path);
static gin::Handle<NativeImage> CreateFromBitmap(
static gin_helper::Handle<NativeImage> CreateFromJPEG(
v8::Isolate* isolate,
base::span<const uint8_t> data);
static gin_helper::Handle<NativeImage> CreateFromPath(
v8::Isolate* isolate,
const base::FilePath& path);
static gin_helper::Handle<NativeImage> CreateFromBitmap(
gin_helper::ErrorThrower thrower,
v8::Local<v8::Value> buffer,
const gin_helper::Dictionary& options);
static gin::Handle<NativeImage> CreateFromBuffer(
static gin_helper::Handle<NativeImage> CreateFromBuffer(
gin_helper::ErrorThrower thrower,
v8::Local<v8::Value> buffer,
gin::Arguments* args);
static gin::Handle<NativeImage> CreateFromDataURL(v8::Isolate* isolate,
const GURL& url);
static gin::Handle<NativeImage> CreateFromNamedImage(gin::Arguments* args,
std::string name);
static gin_helper::Handle<NativeImage> CreateFromDataURL(v8::Isolate* isolate,
const GURL& url);
static gin_helper::Handle<NativeImage> CreateFromNamedImage(
gin::Arguments* args,
std::string name);
#if !BUILDFLAG(IS_LINUX)
static v8::Local<v8::Promise> CreateThumbnailFromPath(
v8::Isolate* isolate,
@@ -114,9 +116,10 @@ class NativeImage final : public gin_helper::DeprecatedWrappable<NativeImage> {
std::vector<float> GetScaleFactors();
v8::Local<v8::Value> GetBitmap(gin::Arguments* args);
v8::Local<v8::Value> GetNativeHandle(gin_helper::ErrorThrower thrower);
gin::Handle<NativeImage> Resize(gin::Arguments* args,
base::Value::Dict options);
gin::Handle<NativeImage> Crop(v8::Isolate* isolate, const gfx::Rect& rect);
gin_helper::Handle<NativeImage> Resize(gin::Arguments* args,
base::Value::Dict options);
gin_helper::Handle<NativeImage> Crop(v8::Isolate* isolate,
const gfx::Rect& rect);
std::string ToDataURL(gin::Arguments* args);
bool IsEmpty();
gfx::Size GetSize(const std::optional<float> scale_factor);

View File

@@ -16,8 +16,8 @@
#include "base/strings/sys_string_conversions.h"
#include "base/task/bind_post_task.h"
#include "gin/arguments.h"
#include "gin/handle.h"
#include "shell/common/gin_converters/image_converter.h"
#include "shell/common/gin_helper/handle.h"
#include "shell/common/gin_helper/promise.h"
#include "shell/common/mac_util.h"
#include "ui/gfx/color_utils.h"
@@ -103,8 +103,9 @@ v8::Local<v8::Promise> NativeImage::CreateThumbnailFromPath(
return handle;
}
gin::Handle<NativeImage> NativeImage::CreateFromNamedImage(gin::Arguments* args,
std::string name) {
gin_helper::Handle<NativeImage> NativeImage::CreateFromNamedImage(
gin::Arguments* args,
std::string name) {
@autoreleasepool {
std::vector<double> hsl_shift;

View File

@@ -4,7 +4,6 @@
#include <string>
#include "gin/handle.h"
#include "net/base/filename_util.h"
#include "net/base/network_change_notifier.h"
#include "net/http/http_util.h"
@@ -17,6 +16,7 @@
#include "shell/common/gin_converters/net_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/error_thrower.h"
#include "shell/common/gin_helper/handle.h"
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/gin_helper/promise.h"
#include "shell/common/node_includes.h"

View File

@@ -17,7 +17,6 @@
#include "base/memory/raw_ptr.h"
#include "base/notreached.h"
#include "base/sequence_checker.h"
#include "gin/handle.h"
#include "gin/object_template_builder.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe_producer.h"
@@ -43,6 +42,7 @@
#include "shell/common/gin_converters/gurl_converter.h"
#include "shell/common/gin_converters/net_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/handle.h"
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/gin_helper/promise.h"
#include "shell/common/node_includes.h"
@@ -167,12 +167,12 @@ class JSChunkedDataPipeGetter final
: public gin_helper::DeprecatedWrappable<JSChunkedDataPipeGetter>,
public network::mojom::ChunkedDataPipeGetter {
public:
static gin::Handle<JSChunkedDataPipeGetter> Create(
static gin_helper::Handle<JSChunkedDataPipeGetter> Create(
v8::Isolate* isolate,
v8::Local<v8::Function> body_func,
mojo::PendingReceiver<network::mojom::ChunkedDataPipeGetter>
chunked_data_pipe_getter) {
return gin::CreateHandle(
return gin_helper::CreateHandle(
isolate, new JSChunkedDataPipeGetter(
isolate, body_func, std::move(chunked_data_pipe_getter)));
}
@@ -390,7 +390,8 @@ void SimpleURLLoaderWrapper::Start() {
void SimpleURLLoaderWrapper::Pin() {
// Prevent ourselves from being GC'd until the request is complete. Must be
// called after gin::CreateHandle, otherwise the wrapper isn't initialized.
// called after gin_helper::CreateHandle, otherwise the wrapper isn't
// initialized.
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
pinned_wrapper_.Reset(isolate, GetWrapper(isolate).ToLocalChecked());
}
@@ -522,7 +523,7 @@ SimpleURLLoaderWrapper::GetURLLoaderFactoryForURL(const GURL& url) {
}
// static
gin::Handle<SimpleURLLoaderWrapper> SimpleURLLoaderWrapper::Create(
gin_helper::Handle<SimpleURLLoaderWrapper> SimpleURLLoaderWrapper::Create(
gin::Arguments* args) {
gin_helper::Dictionary opts;
if (!args->GetNext(&opts)) {
@@ -697,7 +698,7 @@ gin::Handle<SimpleURLLoaderWrapper> SimpleURLLoaderWrapper::Create(
ElectronBrowserContext* browser_context = nullptr;
if (electron::IsBrowserProcess()) {
std::string partition;
gin::Handle<Session> session;
gin_helper::Handle<Session> session;
if (!opts.Get("session", &session)) {
if (opts.Get("partition", &partition))
session = Session::FromPartition(args->isolate(), partition);
@@ -707,7 +708,7 @@ gin::Handle<SimpleURLLoaderWrapper> SimpleURLLoaderWrapper::Create(
browser_context = session->browser_context();
}
auto ret = gin::CreateHandle(
auto ret = gin_helper::CreateHandle(
args->isolate(),
new SimpleURLLoaderWrapper(browser_context, std::move(request), options));
ret->Pin();

View File

@@ -27,9 +27,12 @@
namespace gin {
class Arguments;
} // namespace gin
namespace gin_helper {
template <typename T>
class Handle;
} // namespace gin
} // namespace gin_helper
namespace net {
class AuthChallengeInfo;
@@ -56,7 +59,8 @@ class SimpleURLLoaderWrapper final
private network::mojom::URLLoaderNetworkServiceObserver {
public:
~SimpleURLLoaderWrapper() override;
static gin::Handle<SimpleURLLoaderWrapper> Create(gin::Arguments* args);
static gin_helper::Handle<SimpleURLLoaderWrapper> Create(
gin::Arguments* args);
void Cancel();

View File

@@ -4,9 +4,9 @@
#include "shell/common/gin_converters/image_converter.h"
#include "gin/handle.h"
#include "shell/common/api/electron_api_native_image.h"
#include "shell/common/gin_converters/file_path_converter.h"
#include "shell/common/gin_helper/handle.h"
#include "ui/gfx/image/image_skia.h"
namespace gin {

View File

@@ -15,7 +15,6 @@
#include "base/values.h"
#include "gin/converter.h"
#include "gin/dictionary.h"
#include "gin/handle.h"
#include "gin/object_template_builder.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
@@ -32,6 +31,7 @@
#include "shell/common/gin_converters/gurl_converter.h"
#include "shell/common/gin_converters/std_converter.h"
#include "shell/common/gin_converters/value_converter.h"
#include "shell/common/gin_helper/handle.h"
#include "shell/common/gin_helper/promise.h"
#include "shell/common/node_includes.h"
#include "shell/common/node_util.h"
@@ -259,12 +259,13 @@ namespace {
class ChunkedDataPipeReadableStream final
: public gin_helper::DeprecatedWrappable<ChunkedDataPipeReadableStream> {
public:
static gin::Handle<ChunkedDataPipeReadableStream> Create(
static gin_helper::Handle<ChunkedDataPipeReadableStream> Create(
v8::Isolate* isolate,
network::ResourceRequestBody* request,
network::DataElementChunkedDataPipe* data_element) {
return gin::CreateHandle(isolate, new ChunkedDataPipeReadableStream(
isolate, request, data_element));
return gin_helper::CreateHandle(
isolate,
new ChunkedDataPipeReadableStream(isolate, request, data_element));
}
// gin_helper::Wrappable

View File

@@ -23,7 +23,7 @@ class EventEmitterMixin;
// class Example : public gin_helper::DeprecatedWrappable<Example>,
// public gin_helper::Constructible<Example> {
// public:
// static gin::Handle<Example> New(...usual gin method arguments...);
// static gin_helper::Handle<Example> New(...usual gin method arguments...);
// static void FillObjectTemplate(
// v8::Isolate*,
// v8::Local<v8::ObjectTemplate>);

View File

@@ -4,14 +4,14 @@
#include "shell/common/gin_helper/event.h"
#include "gin/dictionary.h"
#include "gin/handle.h"
#include "gin/object_template_builder.h"
#include "shell/common/gin_helper/handle.h"
namespace gin_helper::internal {
// static
gin::Handle<Event> Event::New(v8::Isolate* isolate) {
return gin::CreateHandle(isolate, new Event());
gin_helper::Handle<Event> Event::New(v8::Isolate* isolate) {
return gin_helper::CreateHandle(isolate, new Event());
}
// static
v8::Local<v8::ObjectTemplate> Event::FillObjectTemplate(

View File

@@ -8,10 +8,10 @@
#include "shell/common/gin_helper/constructible.h"
#include "shell/common/gin_helper/wrappable.h"
namespace gin {
namespace gin_helper {
template <typename T>
class Handle;
} // namespace gin
} // namespace gin_helper
namespace v8 {
class Isolate;
@@ -27,7 +27,7 @@ class Event final : public gin_helper::DeprecatedWrappable<Event>,
public gin_helper::Constructible<Event> {
public:
// gin_helper::Constructible
static gin::Handle<Event> New(v8::Isolate* isolate);
static gin_helper::Handle<Event> New(v8::Isolate* isolate);
static v8::Local<v8::ObjectTemplate> FillObjectTemplate(
v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype);

View File

@@ -8,9 +8,9 @@
#include <string_view>
#include <utility>
#include "gin/handle.h"
#include "shell/common/gin_helper/event.h"
#include "shell/common/gin_helper/event_emitter_caller.h"
#include "shell/common/gin_helper/handle.h"
#include "shell/common/gin_helper/wrappable.h"
namespace content {
@@ -31,7 +31,7 @@ class EventEmitter : public gin_helper::Wrappable<T> {
v8::Local<v8::Object> wrapper = this->GetWrapper();
if (wrapper.IsEmpty())
return false;
gin::Handle<internal::Event> event = internal::Event::New(isolate);
gin_helper::Handle<internal::Event> event = internal::Event::New(isolate);
// It's possible that |this| will be deleted by EmitEvent, so save anything
// we need from |this| before calling EmitEvent.
EmitEvent(isolate, wrapper, name, event, std::forward<Args>(args)...);

View File

@@ -0,0 +1,77 @@
// Copyright (c) 2025 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ELECTRON_SHELL_COMMON_GIN_HELPER_HANDLE_H_
#define ELECTRON_SHELL_COMMON_GIN_HELPER_HANDLE_H_
#include "base/memory/raw_ptr.h"
#include "gin/converter.h"
namespace gin_helper {
// You can use gin_helper::Handle on the stack to retain a gin_helper::Wrappable
// object. Currently we don't have a mechanism for retaining a
// gin_helper::Wrappable object in the C++ heap because strong references from
// C++ to V8 can cause memory leaks. Copied from
// https://chromium-review.googlesource.com/c/chromium/src/+/6734440 Should be
// removed once https://github.com/electron/electron/issues/47922 is complete.
template <typename T>
class Handle {
public:
Handle() : object_(nullptr) {}
Handle(v8::Local<v8::Value> wrapper, T* object)
: wrapper_(wrapper), object_(object) {}
bool IsEmpty() const { return !object_; }
void Clear() {
wrapper_.Clear();
object_ = NULL;
}
T* operator->() const { return object_; }
v8::Local<v8::Value> ToV8() const { return wrapper_; }
T* get() const { return object_; }
private:
v8::Local<v8::Value> wrapper_;
raw_ptr<T> object_;
};
// This function is a convenient way to create a handle from a raw pointer
// without having to write out the type of the object explicitly.
template <typename T>
gin_helper::Handle<T> CreateHandle(v8::Isolate* isolate, T* object) {
v8::Local<v8::Object> wrapper;
if (!object->GetWrapper(isolate).ToLocal(&wrapper) || wrapper.IsEmpty())
return gin_helper::Handle<T>();
return gin_helper::Handle<T>(wrapper, object);
}
} // namespace gin_helper
namespace gin {
template <typename T>
struct Converter<gin_helper::Handle<T>> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const gin_helper::Handle<T>& val) {
return val.ToV8();
}
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gin_helper::Handle<T>* out) {
T* object = NULL;
if (!Converter<T*>::FromV8(isolate, val, &object)) {
return false;
}
*out = gin_helper::Handle<T>(val, object);
return true;
}
};
} // namespace gin
#endif // ELECTRON_SHELL_COMMON_GIN_HELPER_HANDLE_H_

View File

@@ -6,18 +6,19 @@
#include "base/debug/stack_trace.h"
#include "gin/data_object_builder.h"
#include "gin/handle.h"
#include "gin/object_template_builder.h"
#include "shell/browser/javascript_environment.h"
#include "shell/common/gin_converters/blink_converter.h"
#include "shell/common/gin_helper/handle.h"
namespace gin_helper::internal {
// static
using InvokeCallback = electron::mojom::ElectronApiIPC::InvokeCallback;
gin::Handle<ReplyChannel> ReplyChannel::Create(v8::Isolate* isolate,
InvokeCallback callback) {
return gin::CreateHandle(isolate, new ReplyChannel(std::move(callback)));
gin_helper::Handle<ReplyChannel> ReplyChannel::Create(v8::Isolate* isolate,
InvokeCallback callback) {
return gin_helper::CreateHandle(isolate,
new ReplyChannel(std::move(callback)));
}
gin::ObjectTemplateBuilder ReplyChannel::GetObjectTemplateBuilder(

View File

@@ -8,10 +8,10 @@
#include "shell/common/api/api.mojom.h"
#include "shell/common/gin_helper/wrappable.h"
namespace gin {
namespace gin_helper {
template <typename T>
class Handle;
} // namespace gin
} // namespace gin_helper
namespace v8 {
class Isolate;
@@ -29,8 +29,8 @@ namespace gin_helper::internal {
class ReplyChannel : public gin_helper::DeprecatedWrappable<ReplyChannel> {
public:
using InvokeCallback = electron::mojom::ElectronApiIPC::InvokeCallback;
static gin::Handle<ReplyChannel> Create(v8::Isolate* isolate,
InvokeCallback callback);
static gin_helper::Handle<ReplyChannel> Create(v8::Isolate* isolate,
InvokeCallback callback);
// gin_helper::Wrappable
static gin::DeprecatedWrapperInfo kWrapperInfo;

View File

@@ -17,7 +17,7 @@ struct DeprecatedWrapperInfo;
namespace gin_helper {
// Wrappable is a base class for C++ objects that have corresponding v8 wrapper
// objects. To retain a Wrappable object on the stack, use a gin::Handle.
// objects. To retain a Wrappable object on the stack, use a gin_helper::Handle.
//
// USAGE:
// // my_class.h
@@ -27,9 +27,9 @@ namespace gin_helper {
// };
//
// Subclasses should also typically have private constructors and expose a
// static Create function that returns a gin::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
// static Create function that returns a gin_helper::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 WrappableBase {