Home | History | Annotate | Download | only in gin
      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 
     13 WrappableBase::WrappableBase() {
     14 }
     15 
     16 WrappableBase::~WrappableBase() {
     17   wrapper_.Reset();
     18 }
     19 
     20 ObjectTemplateBuilder WrappableBase::GetObjectTemplateBuilder(
     21     v8::Isolate* isolate) {
     22   return ObjectTemplateBuilder(isolate);
     23 }
     24 
     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 
     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 
     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