| // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ENTD_JS_OBJECT_WRAPPER_INL_H_ |
| #define ENTD_JS_OBJECT_WRAPPER_INL_H_ |
| |
| // virtual |
| template<typename T> |
| bool JSObjectWrapper<T>::Initialize() { |
| // Get the template, building it if necessary. |
| v8::Handle<v8::FunctionTemplate> t = GetTemplate(); |
| // Create a v8 Object from the template. |
| obj_ = v8::Persistent<v8::Object>::New(t->GetFunction()->NewInstance()); |
| // Associate it with the C++ Object. |
| obj_->SetPointerInInternalField(0, this); |
| return true; |
| } |
| |
| // static |
| template<typename T> |
| v8::Handle<v8::Value> JSObjectWrapper<T>::Construct( |
| const v8::Arguments& args) { |
| if (!args.IsConstructCall()) { |
| utils::ThrowV8Exception(std::string(T::GetClassName()) |
| + " must be called as a constructor."); |
| return v8::Undefined(); |
| } |
| |
| T* instance = new T(); |
| instance->Initialize(); |
| |
| v8::Handle<v8::Object> obj = instance->obj(); |
| |
| if (!instance->ParseConstructorArgs(obj, args)) { |
| // TODO(rginda): Remove this delete after we sort out a proper ownership |
| // model for these JSObjectWrapper objects. |
| delete instance; |
| return v8::Undefined(); |
| } |
| |
| return obj; |
| } |
| |
| // static |
| template<typename T> |
| T* JSObjectWrapper<T>::Unwrap(v8::Handle<v8::Object> obj) { |
| // Make sure the argument is valid |
| if (obj.IsEmpty() || !obj->IsObject()) |
| return NULL; |
| |
| // Make sure it's of the right type |
| if (!T::GetTemplate()->HasInstance(obj)) |
| return NULL; |
| |
| // Paranoia; Should always be true |
| if (obj->InternalFieldCount() < 1) |
| return NULL; |
| |
| T* result = reinterpret_cast<T*>(obj->GetPointerFromInternalField(0)); |
| return result; |
| } |
| |
| // static |
| template<typename T> |
| T* JSObjectWrapper<T>::GetFromArg(const v8::Arguments& args, int index) { |
| T* result = NULL; |
| if (args.Length() > index) { |
| // Unwrap checks that the argument is really an object |
| result = Unwrap(v8::Handle<v8::Object>::Cast(args[index])); |
| } |
| |
| return result; |
| } |
| |
| // static |
| template<typename T> |
| v8::Handle<v8::FunctionTemplate> JSObjectWrapper<T>::ManageTemplate( |
| bool build) { |
| // Store the template as a static function variable |
| // This avoids the awkwardness of dealing with static template members |
| static v8::Persistent<v8::FunctionTemplate> s_template; |
| |
| // Build the templete if necessary |
| if (build && s_template.IsEmpty()) { |
| v8::Handle<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); |
| s_template = v8::Persistent<v8::FunctionTemplate>::New(ft); |
| |
| s_template->SetClassName(v8::String::New(T::GetClassName())); |
| |
| v8::Handle<v8::ObjectTemplate> template_object = |
| s_template->InstanceTemplate(); |
| template_object->SetInternalFieldCount(1); |
| |
| T::SetTemplateBindings(template_object); |
| |
| } else if (!build && !s_template.IsEmpty()) { |
| s_template.Dispose(); |
| } |
| |
| return s_template; |
| } |
| |
| #endif // ENTD_JS_OBJECT_WRAPPER_INL_H_ |