blob: f7d82b0d5a71953cdc84ecec013d9094d5237848 [file] [log] [blame]
[email protected]93f9f3602013-11-21 18:38:511// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef GIN_WRAPPABLE_H_
6#define GIN_WRAPPABLE_H_
7
[email protected]cf76c84a2013-12-06 14:07:078#include "base/template_util.h"
[email protected]93f9f3602013-11-21 18:38:519#include "gin/converter.h"
[email protected]48c21632013-12-12 21:32:3410#include "gin/gin_export.h"
[email protected]93f9f3602013-11-21 18:38:5111#include "gin/public/wrapper_info.h"
12
13namespace gin {
14
[email protected]6fe56102013-12-08 07:10:5815// Wrappable is a base class for C++ objects that have corresponding v8 wrapper
16// objects. To retain a Wrappable object on the stack, use a gin::Handle.
17//
18// USAGE:
19// // my_class.h
20// class MyClass : Wrappable<MyClass> {
[email protected]cb6c2bb2013-12-17 21:47:0421// public:
22// static WrapperInfo kWrapperInfo;
23//
24// // Optional, only required if non-empty template should be used.
[email protected]75a20902013-12-19 15:18:0425// virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
[email protected]cb6c2bb2013-12-17 21:47:0426// v8::Isolate* isolate);
[email protected]6fe56102013-12-08 07:10:5827// ...
28// };
29//
30// // my_class.cc
[email protected]75a20902013-12-19 15:18:0431// WrapperInfo MyClass::kWrapperInfo = {kEmbedderNativeGin};
[email protected]cb6c2bb2013-12-17 21:47:0432//
[email protected]75a20902013-12-19 15:18:0433// gin::ObjectTemplateBuilder MyClass::GetObjectTemplateBuilder(
[email protected]cb6c2bb2013-12-17 21:47:0434// v8::Isolate* isolate) {
[email protected]75a20902013-12-19 15:18:0435// return Wrappable<MyClass>::GetObjectTemplateBuilder(isolate)
36// .SetValue("foobar", 42);
[email protected]cb6c2bb2013-12-17 21:47:0437// }
[email protected]6fe56102013-12-08 07:10:5838//
39// Subclasses should also typically have private constructors and expose a
40// static Create function that returns a gin::Handle. Forcing creators through
41// this static Create function will enforce that clients actually create a
42// wrapper for the object. If clients fail to create a wrapper for a wrappable
43// object, the object will leak because we use the weak callback from the
44// wrapper as the signal to delete the wrapped object.
tommycli425d69652015-06-11 22:20:1445//
46// Wrappable<T> explicitly does not support further subclassing of T.
47// Subclasses of Wrappable<T> should be declared final. Because Wrappable<T>
48// caches the object template using &T::kWrapperInfo as the key, all subclasses
49// would share a single object template. This will lead to hard to debug crashes
50// that look like use-after-free errors.
51
52namespace internal {
53
54GIN_EXPORT void* FromV8Impl(v8::Isolate* isolate,
55 v8::Local<v8::Value> val,
56 WrapperInfo* info);
57
58} // namespace internal
[email protected]6fe56102013-12-08 07:10:5859
[email protected]13c977e62013-12-19 00:52:4460class ObjectTemplateBuilder;
[email protected]6fe56102013-12-08 07:10:5861
62// Non-template base class to share code between templates instances.
[email protected]48c21632013-12-12 21:32:3463class GIN_EXPORT WrappableBase {
[email protected]6fe56102013-12-08 07:10:5864 protected:
65 WrappableBase();
[email protected]695af7f52013-12-11 19:41:0166 virtual ~WrappableBase();
[email protected]cb6c2bb2013-12-17 21:47:0467
tommycli425d69652015-06-11 22:20:1468 // Overrides of this method should be declared final and not overridden again.
[email protected]13c977e62013-12-19 00:52:4469 virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate);
[email protected]cb6c2bb2013-12-17 21:47:0470
deepak.sfaaa1b62015-04-30 07:30:4871 v8::Local<v8::Object> GetWrapperImpl(v8::Isolate* isolate,
[email protected]13c977e62013-12-19 00:52:4472 WrapperInfo* wrapper_info);
[email protected]6fe56102013-12-08 07:10:5873
74 private:
dcarney99ade9082015-04-22 09:55:4275 static void FirstWeakCallback(
76 const v8::WeakCallbackInfo<WrappableBase>& data);
77 static void SecondWeakCallback(
78 const v8::WeakCallbackInfo<WrappableBase>& data);
[email protected]6fe56102013-12-08 07:10:5879
dcarney99ade9082015-04-22 09:55:4280 v8::Global<v8::Object> wrapper_; // Weak
[email protected]cb6c2bb2013-12-17 21:47:0481
[email protected]6fe56102013-12-08 07:10:5882 DISALLOW_COPY_AND_ASSIGN(WrappableBase);
83};
84
85
86template<typename T>
87class Wrappable : public WrappableBase {
88 public:
[email protected]60531d52013-11-27 02:10:1589 // Retrieve (or create) the v8 wrapper object cooresponding to this object.
deepak.sfaaa1b62015-04-30 07:30:4890 v8::Local<v8::Object> GetWrapper(v8::Isolate* isolate) {
[email protected]13c977e62013-12-19 00:52:4491 return GetWrapperImpl(isolate, &T::kWrapperInfo);
[email protected]6fe56102013-12-08 07:10:5892 }
[email protected]d379b0c2013-12-05 05:48:0193
[email protected]93f9f3602013-11-21 18:38:5194 protected:
[email protected]6fe56102013-12-08 07:10:5895 Wrappable() {}
[email protected]695af7f52013-12-11 19:41:0196 virtual ~Wrappable() {}
97
98 private:
[email protected]93f9f3602013-11-21 18:38:5199 DISALLOW_COPY_AND_ASSIGN(Wrappable);
100};
101
[email protected]6fe56102013-12-08 07:10:58102
[email protected]cf76c84a2013-12-06 14:07:07103// This converter handles any subclass of Wrappable.
[email protected]93f9f3602013-11-21 18:38:51104template<typename T>
[email protected]cf76c84a2013-12-06 14:07:07105struct Converter<T*, typename base::enable_if<
[email protected]13c977e62013-12-19 00:52:44106 base::is_convertible<T*, WrappableBase*>::value>::type> {
deepak.sfaaa1b62015-04-30 07:30:48107 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, T* val) {
[email protected]cf76c84a2013-12-06 14:07:07108 return val->GetWrapper(isolate);
[email protected]93f9f3602013-11-21 18:38:51109 }
[email protected]cf76c84a2013-12-06 14:07:07110
deepak.sfaaa1b62015-04-30 07:30:48111 static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val, T** out) {
[email protected]75a20902013-12-19 15:18:04112 *out = static_cast<T*>(static_cast<WrappableBase*>(
113 internal::FromV8Impl(isolate, val, &T::kWrapperInfo)));
[email protected]6fe56102013-12-08 07:10:58114 return *out != NULL;
[email protected]93f9f3602013-11-21 18:38:51115 }
116};
117
118} // namespace gin
119
120#endif // GIN_WRAPPABLE_H_