• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 #include "gin/wrappable.h"
6 
7 #include "base/logging.h"
8 #include "gin/object_template_builder.h"
9 #include "gin/per_isolate_data.h"
10 
11 namespace gin {
12 
WrappableBase()13 WrappableBase::WrappableBase() {
14 }
15 
~WrappableBase()16 WrappableBase::~WrappableBase() {
17   wrapper_.Reset();
18 }
19 
GetObjectTemplateBuilder(v8::Isolate * isolate)20 ObjectTemplateBuilder WrappableBase::GetObjectTemplateBuilder(
21     v8::Isolate* isolate) {
22   return ObjectTemplateBuilder(isolate);
23 }
24 
WeakCallback(const v8::WeakCallbackData<v8::Object,WrappableBase> & data)25 void WrappableBase::WeakCallback(
26     const v8::WeakCallbackData<v8::Object, WrappableBase>& data) {
27   WrappableBase* wrappable = data.GetParameter();
28   wrappable->wrapper_.Reset();
29   delete wrappable;
30 }
31 
GetWrapperImpl(v8::Isolate * isolate,WrapperInfo * info)32 v8::Handle<v8::Object> WrappableBase::GetWrapperImpl(v8::Isolate* isolate,
33                                                      WrapperInfo* info) {
34   if (!wrapper_.IsEmpty()) {
35     return v8::Local<v8::Object>::New(isolate, wrapper_);
36   }
37 
38   PerIsolateData* data = PerIsolateData::From(isolate);
39   v8::Local<v8::ObjectTemplate> templ = data->GetObjectTemplate(info);
40   if (templ.IsEmpty()) {
41     templ = GetObjectTemplateBuilder(isolate).Build();
42     CHECK(!templ.IsEmpty());
43     data->SetObjectTemplate(info, templ);
44   }
45   CHECK_EQ(kNumberOfInternalFields, templ->InternalFieldCount());
46   v8::Handle<v8::Object> wrapper = templ->NewInstance();
47   // |wrapper| may be empty in some extreme cases, e.g., when
48   // Object.prototype.constructor is overwritten.
49   if (wrapper.IsEmpty()) {
50     // The current wrappable object will be no longer managed by V8. Delete this
51     // now.
52     delete this;
53     return wrapper;
54   }
55   wrapper->SetAlignedPointerInInternalField(kWrapperInfoIndex, info);
56   wrapper->SetAlignedPointerInInternalField(kEncodedValueIndex, this);
57   wrapper_.Reset(isolate, wrapper);
58   wrapper_.SetWeak(this, WeakCallback);
59   return wrapper;
60 }
61 
62 namespace internal {
63 
FromV8Impl(v8::Isolate * isolate,v8::Handle<v8::Value> val,WrapperInfo * wrapper_info)64 void* FromV8Impl(v8::Isolate* isolate, v8::Handle<v8::Value> val,
65                  WrapperInfo* wrapper_info) {
66   if (!val->IsObject())
67     return NULL;
68   v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(val);
69   WrapperInfo* info = WrapperInfo::From(obj);
70 
71   // If this fails, the object is not managed by Gin. It is either a normal JS
72   // object that's not wrapping any external C++ object, or it is wrapping some
73   // C++ object, but that object isn't managed by Gin (maybe Blink).
74   if (!info)
75     return NULL;
76 
77   // If this fails, the object is managed by Gin, but it's not wrapping an
78   // instance of the C++ class associated with wrapper_info.
79   if (info != wrapper_info)
80     return NULL;
81 
82   return obj->GetAlignedPointerFromInternalField(kEncodedValueIndex);
83 }
84 
85 }  // namespace internal
86 
87 }  // namespace gin
88