RTBKit  0.9
Open-source framework to create real-time ad bidding systems.
soa/js/js_wrapped.h
00001 /* js_wrapped.h                                                    -*- C++ -*-
00002    Jeremy Barnes, 15 July 2010
00003    Copyright (c) 2010 Datacratic Inc.  All rights reserved.
00004 
00005    Some code is from node_object_wrap.h, from node.js.  Its license is
00006    included here:
00007 
00008    Copyright 2009, 2010 Ryan Lienhart Dahl. All rights reserved.
00009    Permission is hereby granted, free of charge, to any person obtaining a copy
00010    of this software and associated documentation files (the "Software"), to
00011    deal in the Software without restriction, including without limitation the
00012    rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
00013    sell copies of the Software, and to permit persons to whom the Software is
00014    furnished to do so, subject to the following conditions:
00015    
00016    The above copyright notice and this permission notice shall be included in
00017    all copies or substantial portions of the Software.
00018    
00019    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00020    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00021    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00022    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00023    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00024    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
00025    IN THE SOFTWARE. 
00026 */
00027 
00028 #pragma once
00029 
00030 #include "jml/utils/exc_assert.h"
00031 #include "jml/arch/demangle.h"
00032 #include "jml/compiler/compiler.h"
00033 #include "jml/utils/string_functions.h"
00034 #include "jml/arch/backtrace.h"
00035 #include "jml/utils/smart_ptr_utils.h"
00036 #include <node/node.h>
00037 #include <v8/v8.h>
00038 #include <boost/shared_ptr.hpp>
00039 #include <boost/type_traits/is_base_of.hpp>
00040 #include <boost/static_assert.hpp>
00041 #include <boost/utility/enable_if.hpp>
00042 #include <iostream>
00043 #include "js_utils.h"
00044 #include "js_registry.h"
00045 
00046 
00047 namespace Datacratic {
00048 namespace JS {
00049 
00050 
00053 const std::type_info & getWrapperTypeInfo(v8::Handle<v8::Value> handle);
00054 
00055 
00056 /*****************************************************************************/
00057 /* JSWRAPPEDBASE                                                             */
00058 /*****************************************************************************/
00059 
00060 class JSWrappedBase {
00061 public:
00062     JSWrappedBase()
00063         : refs_(0), size_in_bytes_(0)
00064     {
00065     }
00066     
00067     virtual ~JSWrappedBase();
00068 
00069     template <class T>
00070     static inline T * unwrap(const v8::Handle<v8::Object> & handle)
00071     {
00072         ExcAssert(!handle.IsEmpty());
00073         ExcAssert(handle->InternalFieldCount() == 2);
00074         return static_cast<T*>(v8::Handle<v8::External>::Cast
00075                                (handle->GetInternalField(0))->Value());
00076     }
00077 
00078     v8::Persistent<v8::Object> js_object_;
00079 
00083     std::shared_ptr<void> owner_;
00084 
00085 protected:
00088     void wrap(v8::Handle<v8::Object> handle,
00089               size_t object_size,
00090               const std::type_info & wrappedType);
00091 
00094     void registerForGarbageCollection();
00095     
00096     /* Ref() marks the object as being attached to an event loop.
00097      * Refed objects will not be garbage collected, even if
00098      * all references are lost.
00099      */
00100     virtual void ref();
00101     
00102     /* Unref() marks an object as detached from the event loop.  This is its
00103      * default state.  When an object with a "weak" reference changes from
00104      * attached to detached state it will be freed. Be careful not to access
00105      * the object after making this call as it might be gone!
00106      * (A "weak reference" means an object that only has a
00107      * persistant handle.)
00108      *
00109      * DO NOT CALL THIS FROM DESTRUCTOR
00110      */
00111     virtual void unref();
00112     
00117     virtual void dispose();
00118 
00122     virtual v8::WeakReferenceCallback getGarbageCollectionCallback() const;
00123 
00124     virtual std::string getJsTypeName() const
00125     {
00126         return "UNKNOWN";
00127     }
00128 
00129     static void
00130     Setup(const v8::Persistent<v8::FunctionTemplate> & ft,
00131           const std::string & name,
00132           const v8::Handle<v8::Object> & target)
00133     {
00134         using namespace v8;
00135 
00136         //using namespace std;
00137         //cerr << "setup " << name << " ft = " << *ft << endl;
00138 
00139         // Get the context
00140         HandleScope scope;
00141         v8::Local<v8::Context> context = v8::Context::GetCurrent();
00142         v8::Local<v8::Object> global = context->Global();
00143 
00144         // Check for the stash
00145         v8::Local<v8::Value> stash
00146             = global->Get(v8::String::NewSymbol("__cpp_stash__"));
00147         v8::Local<v8::Object> stash_obj;
00148         if (!stash.IsEmpty())
00149             stash_obj = v8::Object::Cast(*stash);
00150 
00151         if (stash_obj.IsEmpty()
00152             || stash_obj->IsUndefined() || stash_obj->IsNull()) {
00153             //cerr << "*** Creating stash" << endl;
00154             v8::Local<v8::Object> new_stash = v8::Object::New();
00155             global->Set(v8::String::NewSymbol("__cpp_stash__"), new_stash);
00156             stash_obj = new_stash;
00157         }
00158 
00159         v8::Local<v8::Value> fn
00160             = stash_obj->Get(v8::String::NewSymbol(name.c_str()));
00161         v8::Local<v8::Function> f;
00162         if (fn.IsEmpty() || !fn->IsFunction()) {
00163             //cerr << "  creating function " << name << endl;
00164             f = ft->GetFunction();
00165             stash_obj->Set(v8::String::NewSymbol(name.c_str()), f);
00166         }
00167         else f = v8::Function::Cast(*fn);
00168         
00169         // Create the function from the template
00170         //Local<v8::Function> f = ft->GetFunction();
00171 
00172         // Finally, add the new object into the target object under the
00173         // given name
00174         target->Set(String::NewSymbol(name.c_str()), f);
00175     }
00176 
00183     template<typename Wrapper>
00184     static v8::Handle<v8::Value>
00185     createExtendedObject(const v8::Arguments & args)
00186     {
00187         // Create the new object
00188         v8::Handle<v8::Value> res = Wrapper::New(args);
00189 
00190         // Get the function we inherit from
00191         v8::Local<v8::Function> fn(v8::Function::Cast(*args.Data()));
00192         if (fn.IsEmpty())
00193             throw ML::Exception("could not extract prototype from " + cstr(args.Data()));
00194         
00195         // Run the constructor
00196         v8::Handle<v8::Value> args2[args.Length()];
00197         for (unsigned i = 0;  i < args.Length();  ++i)
00198             args2[i] = args[i];
00199 
00200         fn->Call(args.This(), args.Length(), args2);
00201 
00202         auto newPrototype = fn->Get(v8::String::NewSymbol("prototype"));
00203         args.This()->SetPrototype(newPrototype);
00204         
00205         return args.This();
00206     }
00207     
00212     template<typename Wrapper>
00213     static v8::Handle<v8::Value>
00214     extendImpl(const v8::Arguments & args)
00215     {
00216         // called with a single argument, which is the function (class) to
00217         // extend from.
00218 
00219         // Find things to inherit with
00220         v8::Local<v8::Function> fn(v8::Function::Cast(*args[0]));
00221         if (fn.IsEmpty())
00222             throw ML::Exception("call to non-function for score: " + cstr(args[0]));
00223 
00224         // Create a new function template for our result
00225         v8::Local<v8::FunctionTemplate> result
00226             (v8::FunctionTemplate::New(&createExtendedObject<Wrapper>, fn));
00227 
00228         result->InstanceTemplate()->SetInternalFieldCount(2);
00229 
00230         if (!args[1]->IsUndefined()) {
00231             v8::Local<v8::String> name(v8::String::Cast(*args[1]));
00232             if (!name.IsEmpty()) {
00233                 result->SetClassName(name);
00234             }
00235         }
00236         else {
00237             v8::Local<v8::String> name(v8::String::Cast(*fn->GetName()));
00238             if (!name.IsEmpty()) {
00239                 result->SetClassName(name);
00240             }
00241         }
00242 
00243         // Make it inherit from the JS recommendation scorer
00244         result->Inherit(Wrapper::tmpl);
00245 
00246         // Finally return the fuction
00247         v8::Handle<v8::Value> res = result->GetFunction();
00248 
00249         // Make our function inherit from this result function
00250         //...
00251         auto fnPrototype = toObject(fn->Get(v8::String::NewSymbol("prototype")));
00252         auto resPrototype = toObject(toObject(res)->Get(v8::String::NewSymbol("prototype")));
00253         fnPrototype->SetPrototype(resPrototype);
00254     
00255         return res;
00256     }
00257 
00258     static v8::Persistent<v8::FunctionTemplate>
00259     RegisterBase(const char * name,
00260                  const char * module,
00261                  v8::InvocationCallback constructor,
00262                  SetupFunction setup = Setup)
00263     {
00264         using namespace v8;
00265         
00266         Persistent<FunctionTemplate> t
00267             = v8::Persistent<FunctionTemplate>
00268             ::New(FunctionTemplate::New(constructor));
00269 
00270         t->InstanceTemplate()->SetInternalFieldCount(2);
00271         t->SetClassName(v8::String::NewSymbol(name));
00272 
00273         registry.get_to_know(name, module, t, setup);
00274 
00275         return t;
00276     }
00277 
00278     
00279 private:
00280     // Called back once an object is garbage collected.
00281     static void garbageCollectionCallback
00282         (v8::Persistent<v8::Value> value, void *data);
00283 
00284     int refs_; // ro
00285     size_t size_in_bytes_; 
00286 };
00287 
00288 
00289 /*****************************************************************************/
00290 /* JSWRAPPED                                                                 */
00291 /*****************************************************************************/
00292 
00293 template<typename Shared>
00294 struct JSWrapped : public JSWrappedBase {
00295 
00296     typedef JSWrapped root_type;
00297     typedef Shared root_shared_type;
00298     
00299     JSWrapped()
00300     {
00301         ++created;
00302     }
00303 
00304     virtual ~JSWrapped()
00305     {
00306         ++destroyed;
00307     }
00308 
00309     static uint64_t created, destroyed;
00310 
00311     virtual size_t memusage(void * object) const
00312     {
00313         return sizeof(Shared) + sizeof(*this);
00314     }
00315 
00316     void wrap(v8::Handle<v8::Object> handle, Shared * object)
00317     {
00318         //if (!object)
00319         //    throw ML::Exception("wrapping null pointer");
00320         JSWrappedBase::wrap(handle, memusage(object), typeid(*this));
00321         shared_.reset(object);
00322     }
00323 
00324     void wrap(v8::Handle<v8::Object> handle, std::shared_ptr<Shared> object)
00325     {
00326         //if (!object)
00327         //    throw ML::Exception("wrapping null pointer");
00328         JSWrappedBase::wrap(handle, memusage(object.get()), typeid(*this));
00329         setWrappedObject(object);
00330     }
00331 
00332     static inline JSWrapped *
00333     getWrapper(v8::Handle<v8::Value> handle,
00334                v8::Persistent<v8::FunctionTemplate> tmpl,
00335                const char * className,
00336                const char * module)
00337     {
00338         if (!tmpl->HasInstance(handle)) {
00339             //ML::backtrace();
00340             throw ML::Exception("we're not the right object: wanted C++ "
00341                                 + ML::type_name<Shared>() + " got JS "
00342                                 + cstr(handle));
00343         }
00344 
00345         JSWrapped * result
00346             = JSWrappedBase::unwrap<JSWrapped>(toObject(handle));
00347         if (!result)
00348             throw ML::Exception("unrwapped closed object");
00349         return result;
00350     }
00351 
00352     static inline JSWrapped *
00353     getWrapper(const v8::Arguments & args,
00354                v8::Persistent<v8::FunctionTemplate> tmpl,
00355                const char * className,
00356                const char * module)
00357     {
00358         return getWrapper(args.This(), className, module);
00359     }
00360 
00361     static void unwrappedException(const char * className, const char * module)
00362     {
00363         throw ML::Exception("Using close()d or partially constructed "
00364                             "object of type %s: either you called close() "
00365                             "or you used \"new %s\" when you needed "
00366                             "constructor arguments or to use a factory "
00367                             "function (in module %s)", className, className,
00368                             module);
00369     }
00370 
00371     static inline Shared *
00372     getShared(v8::Handle<v8::Value> handle,
00373               v8::Persistent<v8::FunctionTemplate> tmpl,
00374               const char * className, const char * module)
00375     {
00376         Shared * result = getWrapper(handle, tmpl, className, module)
00377             ->shared_.get();
00378         if (!result) unwrappedException(className, module);
00379         return result;
00380     }
00381 
00382     static inline Shared *
00383     getShared(const v8::Arguments & args,
00384               v8::Persistent<v8::FunctionTemplate> tmpl,
00385               const char * className, const char * module)
00386     {
00387         return getShared(args.This(), tmpl, className, module);
00388     }
00389 
00390     static inline std::shared_ptr<Shared>
00391     getSharedPtr(v8::Handle<v8::Value> handle,
00392                  v8::Persistent<v8::FunctionTemplate> tmpl,
00393                  const char * className, const char * module)
00394     {
00395         std::shared_ptr<Shared> result
00396             = getWrapper(handle, tmpl, className, module)->shared_;
00397         if (!result) unwrappedException(className, module);
00398         return result;
00399     }
00400 
00401     static inline std::shared_ptr<Shared>
00402     getSharedPtr(const v8::Arguments & args,
00403                  v8::Persistent<v8::FunctionTemplate> tmpl,
00404                  const char * className, const char * module)
00405     {
00406         return getSharedPtr(args.This(), tmpl, className, module);
00407     }
00408 
00409     static inline void
00410     setShared(v8::Handle<v8::Value> handle,
00411               v8::Persistent<v8::FunctionTemplate> tmpl,
00412               const char * className,
00413               const char * module,
00414               const std::shared_ptr<Shared> & shared)
00415     {
00416         ExcAssert(shared);
00417         getWrapper(handle, tmpl, className, module)->setWrappedObject(shared);
00418     }
00419 
00420     static v8::Handle<v8::Value>
00421     ObjectStats(const v8::Arguments & args)
00422     {
00423         v8::HandleScope scope;
00424         try {
00425             v8::Local<v8::Object> result = v8::Object::New();
00426             result->Set(v8::String::NewSymbol("created"),
00427                         v8::Integer::New(created));
00428             result->Set(v8::String::NewSymbol("destroyed"),
00429                         v8::Integer::New(destroyed));
00430             return scope.Close(result);
00431         } HANDLE_JS_EXCEPTIONS;
00432     }
00433     
00434     static v8::Handle<v8::Value>
00435     cppDetach(const v8::Arguments & args)
00436     {
00437         try {
00438             JSWrapped * me = JSWrappedBase::unwrap<JSWrapped>(args.This());
00439             me->shared_.reset();
00440             return v8::Undefined();
00441         } HANDLE_JS_EXCEPTIONS;
00442     }
00443 
00444     static v8::Handle<v8::Value>
00445     cppType(const v8::Arguments & args)
00446     {
00447         v8::HandleScope scope;
00448         try {
00449             JSWrapped * me = JSWrappedBase::unwrap<JSWrapped>(args.This());
00450             if (!me || !me->shared_)
00451                 throw ML::Exception("cppType() called on unwrapped or closed"
00452                                     "object");
00453 
00454             //std::cerr << "args.This() = " << cstr(args.This()) << std::endl;
00455             //std::cerr << "me = " << me << std::endl;
00456             //std::cerr << "me->shared_ = " << me->shared_ << std::endl;
00457             //std::cerr << "type_name(*me) = " << ML::type_name(*me) << std::endl;
00458 
00459             return scope.Close
00460                 (v8::String::NewSymbol(ML::type_name(*me->shared_).c_str()));
00461         } HANDLE_JS_EXCEPTIONS;
00462     }
00463 
00464     static v8::Handle<v8::Value>
00465     noConstructorError(const char * class_name = 0, const char * module = 0)
00466     {
00467         std::string msg;
00468         if (!class_name)
00469             msg = "Class does not have a constructor";
00470         else msg = ML::format("Class %s does not have a constructor",
00471                               class_name);
00472         return v8::ThrowException
00473             (injectBacktrace
00474              (v8::Exception::Error
00475               (v8::String::New(msg.c_str()))));
00476     }
00477 
00478     static v8::Handle<v8::Value>
00479     NoConstructor(const v8::Arguments & args)
00480     {
00481         return noConstructorError();
00482     }
00483 
00484     static v8::Persistent<v8::FunctionTemplate>
00485     RegisterBase(const char * name,
00486                  const char * module,
00487                  v8::InvocationCallback constructor,
00488                  SetupFunction setup = Setup)
00489     {
00490         using namespace v8;
00491 
00492         Persistent<FunctionTemplate> t
00493             = JSWrappedBase::RegisterBase(name, module, constructor, setup);
00494         
00495         // Class methods
00496         t->Set(String::NewSymbol("objectStats"),
00497                FunctionTemplate::New(ObjectStats));
00498 
00499         // Instance methods
00500         // Detach the JS object from its backing CPP object
00501         NODE_SET_PROTOTYPE_METHOD(t, "cppDetach", cppDetach);
00502 
00503         NODE_SET_PROTOTYPE_METHOD(t, "cppType", cppType);
00504 
00505         registry.get_to_know(name, module, t, setup);
00506 
00507         return t;
00508     }
00509 
00510     const std::shared_ptr<Shared> & getWrappedObject() const
00511     {
00512         return shared_;
00513     }
00514 
00519     void setWrappedObject(const std::shared_ptr<Shared> & newObject)
00520     {
00521         if (newObject == shared_) return;
00522         if (shared_)
00523             onResetWrappedObject(js_object_, shared_);
00524         shared_ = newObject;
00525         if (newObject)
00526             onSetWrappedObject(js_object_, newObject);
00527     }
00528 
00529 protected:
00537     virtual void
00538     onSetWrappedObject(const v8::Handle<v8::Object> & This,
00539                        const std::shared_ptr<Shared> & newObject)
00540     {
00541     }
00542 
00548     virtual void
00549     onResetWrappedObject(const v8::Handle<v8::Object> & This,
00550                          const std::shared_ptr<Shared> & oldObject)
00551     {
00552     }
00553     
00554 private:
00555     std::shared_ptr<Shared> shared_;
00556 };
00557 
00558 template<typename Shared>
00559 uint64_t JSWrapped<Shared>::created = 0;
00560 
00561 template<typename Shared>
00562 uint64_t JSWrapped<Shared>::destroyed = 0;
00563 
00564 struct DoInitialize {
00565     template<typename Fn>
00566     DoInitialize(Fn fn, void (*dfn) (void) = 0)
00567         : dfn(dfn)
00568     {
00569         fn();
00570     }
00571 
00572     void (*dfn) (void);
00573 
00574     ~DoInitialize()
00575     {
00576         if (dfn) dfn();
00577     }
00578 
00579     operator int () const { return (size_t)this; }
00580 };
00581 
00582 
00583 /*****************************************************************************/
00584 /* JSWRAPPED2                                                                */
00585 /*****************************************************************************/
00586 
00587 // WARNING: the Wrapper object MUST inherit from JSWrapped2 as the FIRST
00588 // object in its inheritence, as we don't do a dynamic cast that could
00589 // fix up the pointers for a different configuration.
00590 template<typename Shared, typename Wrapper,
00591          const char * const & ClassNameT,
00592          const char * const & ModuleT,
00593          bool defaultWrapper = true>
00594 struct JSWrapped2 : public JSWrapped<Shared> {
00595 
00596     typedef Shared shared_type;
00597     typedef Shared base_shared_type;
00598     typedef JSWrapped<Shared> base_type;
00599 
00600     typedef base_type root_type;
00601     typedef Shared root_shared_type;
00602 
00603     static const char * const & ClassName;
00604     static const char * const & Module;
00605     
00606     static v8::Persistent<v8::FunctionTemplate> tmpl;
00607 
00608     typedef JSWrapped2<Shared, Wrapper, ClassNameT, ModuleT, defaultWrapper>
00609          WrapperType;
00610 
00611     JSWrapped2()
00612     {
00613         int x JML_UNUSED = initializer;
00614     }
00615 
00616     static void check_tmpl()
00617     {
00618         if (*tmpl) return;
00619         std::cerr << "&tmpl = " << &tmpl << " *tmpl = " << *tmpl << std::endl;
00620         throw ML::Exception("template for class " + std::string(ClassNameT)
00621                             + " isn't initialized");
00622     }
00623 
00624     static v8::Local<v8::Object>
00625     toJS(const std::shared_ptr<Shared> & shared)
00626     {
00627         check_tmpl();
00628         v8::Local<v8::Object> result = tmpl->GetFunction()->NewInstance();
00629         if (result.IsEmpty()) throw JSPassException();
00630         setShared(result, shared);
00631         return result;
00632     }
00633 
00634     static v8::Local<v8::Object>
00635     toJS(Shared & shared, const std::shared_ptr<void> & owner)
00636     {
00637         check_tmpl();
00638         v8::Local<v8::Object> result = tmpl->GetFunction()->NewInstance();
00639         if (result.IsEmpty()) throw JSPassException();
00640         setShared(result, shared, owner);
00641         return result;
00642     }
00643 
00644     static std::shared_ptr<Shared>
00645     fromJS(v8::Handle<v8::Object> obj)
00646     {
00647         return getSharedPtr(obj);
00648     }
00649 
00650     virtual size_t memusage(void * object) const
00651     {
00652         return sizeof(Shared) + sizeof(Wrapper);
00653     }
00654 
00655     static inline Wrapper * getWrapper(v8::Handle<v8::Value> handle)
00656     {
00657         check_tmpl();
00658         if (!tmpl->HasInstance(handle)) {
00659             //ML::backtrace();
00660             throw ML::Exception("we're not the right object: wanted C++ "
00661                                 + ML::type_name<Shared>() + " got JS "
00662                                 + cstr(handle));
00663         }
00664 
00665         Wrapper * result = JSWrappedBase::unwrap<Wrapper>(toObject(handle));
00666         if (!result)
00667             throw ML::Exception("unwrapped closed object");
00668         return result;
00669     }
00670 
00671     static inline Wrapper * getWrapper(const v8::Arguments & args)
00672     {
00673         return getWrapper(args.This());
00674     }
00675 
00676     static inline Shared *
00677     getShared(v8::Handle<v8::Value> handle)
00678     {
00679         return base_type::getShared(handle, tmpl, ClassName, Module);
00680     }
00681 
00682     static inline Shared *
00683     getShared(const v8::Arguments & args)
00684     {
00685         return base_type::getShared(args, tmpl, ClassName, Module);
00686     }
00687 
00688     static inline std::shared_ptr<Shared>
00689     getSharedPtr(v8::Handle<v8::Value> handle)
00690     {
00691         return base_type::getSharedPtr(handle, tmpl, ClassName, Module);
00692     }
00693 
00694     static inline std::shared_ptr<Shared>
00695     getSharedPtr(const v8::Arguments & args)
00696     {
00697         return base_type::getSharedPtr(args, tmpl, ClassName, Module);
00698     }
00699 
00700     static inline void
00701     setShared(v8::Handle<v8::Value> handle,
00702               const std::shared_ptr<Shared> & shared)
00703     {
00704         JSWrapped<Shared>::setShared(handle, tmpl, ClassName, Module, shared);
00705     }
00706 
00707     // setShared when we also want to record a shared pointer of an owning
00708     // object that guarantees that the shared object isn't deleted
00709     template<typename Owner>
00710     static inline void
00711     setShared(v8::Handle<v8::Value> handle,
00712               Shared & shared,
00713               const std::shared_ptr<Owner> & owner)
00714     {
00715         auto sharedPtr = ML::make_unowned_std_sp(shared);
00716         JSWrapped<Shared>::setShared(handle, tmpl, ClassName, Module,
00717                                      sharedPtr);
00718         getWrapper(handle)->owner_ = owner;
00719     }
00720 
00721     static v8::Handle<v8::Value>
00722     NoConstructor(const v8::Arguments & args)
00723     {
00724         return JSWrapped<Shared>::noConstructorError(ClassName, Module);
00725     }
00726 
00727     static v8::Handle<v8::Value>
00728     wrapperType(const v8::Arguments & args)
00729     {
00730 
00731         try {
00732             return JS::toJS(ClassName);
00733         } HANDLE_JS_EXCEPTIONS;
00734     }
00735 
00736     virtual std::string getJsTypeName() const
00737     {
00738         return std::string(ModuleT) + "." + std::string(ClassNameT);
00739     }
00740 
00741     static void addMethods()
00742     {
00743         using namespace v8;
00744         NODE_SET_PROTOTYPE_METHOD(tmpl, "wrapperType", wrapperType);
00745         //tmpl->Set(String::NewSymbol("wrapperType"),
00746         //          FunctionTemplate::New(wrapperType));
00747     }
00748 
00749     static v8::Persistent<v8::FunctionTemplate>
00750     Register(SetupFunction setup = JSWrapped<Shared>::Setup)
00751     {
00752         //std::cerr << "Register " << ClassName << " tmpl = "
00753         //          << &tmpl << std::endl;
00754         tmpl = JSWrapped<Shared>::
00755             RegisterBase(ClassName, Module, NoConstructor, setup);
00756         //std::cerr << "    *tmpl = " << *tmpl << std::endl;
00757         addMethods();
00758         check_tmpl();
00759         return tmpl;
00760         //return v8::Persistent<v8::FunctionTemplate>
00761         //    ::New(tmpl);
00762     }
00763     
00764     static v8::Persistent<v8::FunctionTemplate>
00765     Register(v8::InvocationCallback constructor,
00766              SetupFunction setup = JSWrapped<Shared>::Setup)
00767     {
00768         //std::cerr << "Register " << ClassName << " tmpl = "
00769         //          << &tmpl << std::endl;
00770         tmpl = JSWrapped<Shared>::
00771             RegisterBase(ClassName, Module, constructor, setup);
00772         //std::cerr << "    *tmpl = " << *tmpl << std::endl;
00773         addMethods();
00774         check_tmpl();
00775         return tmpl;
00776         //return v8::Persistent<v8::FunctionTemplate>
00777         //    ::New(tmpl);
00778     }
00779 
00788     static v8::Local<v8::Object>
00789     constructMe(void * smart_ptr, const void * object)
00790     {
00791         // Change the pointer
00792         *(const void **)smart_ptr = object;
00793 
00794         // Cast to the correct type (it's guaranteed to be that)
00795         std::shared_ptr<Shared> & sp
00796             = *(std::shared_ptr<Shared> *)smart_ptr;
00797 
00798         return toJS(sp);
00799     }
00800 
00801     static void
00802     unwrapMe(const v8::Handle<v8::Value> & wrapper,
00803              void * outputPtr,
00804              const std::type_info & wrapperType)
00805     {
00806         /* Check that it is possible to convert our type into the given
00807            wrapper type. */
00808         
00809         throw ML::Exception("unwrapMe");
00810     }
00811 
00812     static void InitializeFunction()
00813     {
00814         registry.introduce(ClassNameT, Module, Wrapper::Initialize);
00815         if (defaultWrapper)
00816             registry.isWrapper<Shared, Wrapper>(constructMe, unwrapMe);
00817     }
00818 
00819     static void DestructionFunction()
00820     {
00821     }
00822 
00823     static DoInitialize initializer;
00824 
00825     template<typename T, typename Obj>
00826     static void registerRWProperty(T (Obj::* ptr), const char * name,
00827                                    unsigned options = v8::DontDelete)
00828     {
00829         tmpl->InstanceTemplate()
00830             ->SetAccessor(v8::String::NewSymbol(name),
00831                           PropertyGetter<T, Obj, JSWrapped2>::getter,
00832                           PropertySetter<T, Obj, JSWrapped2>::setter,
00833                           pmToValue(ptr),
00834                           v8::DEFAULT,
00835                           v8::PropertyAttribute(options));
00836     }
00837 
00838     template<typename T, typename Obj>
00839     static void registerROProperty(T (Obj::* ptr), const char * name,
00840                                    unsigned options
00841                                    = v8::DontDelete | v8::ReadOnly)
00842     {
00843         tmpl->InstanceTemplate()
00844             ->SetAccessor(v8::String::NewSymbol(name),
00845                           PropertyGetter<T, Obj, JSWrapped2>::getter,
00846                           0,
00847                           pmToValue(ptr),
00848                           v8::DEFAULT,
00849                           v8::PropertyAttribute(options));
00850     }
00851 
00853     template<typename T, typename Obj>
00854     static void registerROProperty(T (Obj::* pmf) () const,
00855                                    const char * name,
00856                                    unsigned options
00857                                    = v8::DontDelete | v8::ReadOnly)
00858     {
00859         tmpl->InstanceTemplate()
00860             ->SetAccessor(v8::String::NewSymbol(name),
00861                           PropertyGetter<T, Obj, JSWrapped2>::pmfGetter,
00862                           0,
00863                           pmfToValue(pmf),
00864                           v8::DEFAULT,
00865                           v8::PropertyAttribute(options));
00866     }
00867 
00868 #if 0
00869 
00870     template<typename T, typename Obj>
00871     static void registerRWPropertyGetterSetter
00872         (T (Obj::* setter) () const,
00873          void (Obj::* getter) (const T &),
00874          const char * name,
00875          unsigned options = v8::DontDelete | v8::ReadOnly)
00876     {
00877         tmpl->InstanceTemplate()
00878             ->SetAccessor(v8::String::NewSymbol(name),
00879                           PropertyGetter<T, Obj, JSWrapped2>::pmfGetterPair,
00880                           PropertySetter<T, Obj, JSWrapped2>::pmfSetterPair,
00881                           setterGetterToValue(setter, getter),
00882                           v8::DEFAULT,
00883                           v8::PropertyAttribute(options));
00884     }
00885 #endif
00886 
00887     template<typename Fn>
00888     static void registerROProperty(const Fn & lambda,
00889                                    const char * name,
00890                                    unsigned options
00891                                    = v8::DontDelete | v8::ReadOnly,
00892                                    decltype(lambda(*(Shared *)0))* = 0)
00893     {
00894         typedef decltype(lambda(*(Shared *)0)) RT;
00895 
00896         boost::function<RT (const Shared &)> fn
00897             = lambda;
00898 
00899         tmpl->InstanceTemplate()
00900             ->SetAccessor(v8::String::NewSymbol(name),
00901                           &lambdaGetter<Shared, JSWrapped2, RT>,
00902                           0,
00903                           lambdaToValue(fn),
00904                           v8::DEFAULT,
00905                           v8::PropertyAttribute(options));
00906     }
00907 
00908     static void registerROProperty(const std::string & getterFn,
00909                                    const char * name,
00910                                    unsigned options
00911                                    = v8::DontDelete | v8::ReadOnly)
00912     {
00913         // TODO: set this up directly by calling on the prototype so we
00914         // don't have a trip through C++ to deal with
00915         tmpl->InstanceTemplate()
00916             ->SetAccessor(v8::String::NewSymbol(name),
00917                           &callGetterFn,
00918                           0,
00919                           getFunction(getterFn),
00920                           v8::DEFAULT,
00921                           v8::PropertyAttribute(options));
00922     }
00923 
00924     static void registerROProperty(const std::string & getterFn,
00925                                    unsigned options
00926                                    = v8::DontDelete | v8::ReadOnly)
00927     {
00928         v8::Handle<v8::Function> fn = getFunction("(" + getterFn + ")");
00929         v8::Handle<v8::String> name = fn->GetName()->ToString();
00930         if (name.IsEmpty())
00931             throw ML::Exception("Function name was not a string");
00932 
00933         // TODO: set this up directly by calling on the prototype so we
00934         // don't have a trip through C++ to deal with
00935         tmpl->InstanceTemplate()
00936             ->SetAccessor(name,
00937                           &callGetterFn,
00938                           0,
00939                           fn,
00940                           v8::DEFAULT,
00941                           v8::PropertyAttribute(options));
00942     }
00943 
00967     template<typename R, typename Obj, typename... Args>
00968     static void registerAsyncCallback(boost::function<R (Args...)> (Obj::* ptr),
00969                                       const char * name,
00970                                       unsigned options = v8::DontDelete)
00971     {
00972         typedef boost::function<R (Args...)> T;
00973 
00974         tmpl->InstanceTemplate()
00975             ->SetAccessor(v8::String::NewSymbol(name),
00976                           PropertyGetter<T, Obj, JSWrapped2>::getter,
00977                           AsyncCallbackSetter<T, Obj, JSWrapped2>::setter,
00978                           pmToValue(ptr),
00979                           v8::DEFAULT,
00980                           v8::PropertyAttribute(options));
00981     }
00982 
00983     template<typename R, typename Obj, typename... Args, typename... Defaults>
00984     static void registerMemberFn(R (Obj::* pmf) (Args... args) const,
00985                                  const char * name,
00986                                  Defaults... defaults)
00987     {
00988         // Set it up so that the member function is called when we
00989         // call the JS version
00990 
00991         v8::Local<v8::Signature> sig = v8::Signature::New(tmpl);
00992         v8::Local<v8::FunctionTemplate> cb
00993             =  v8::FunctionTemplate::New
00994             (MemberFunctionCaller<R, const Obj, JSWrapped2, Args...>::call,
00995              pmfToValue(pmf, defaults...), sig);
00996         tmpl->PrototypeTemplate()->Set(v8::String::NewSymbol(name),
00997                                        cb);
00998     }
00999 
01000     template<typename R, typename Obj, typename... Args, typename... Defaults>
01001     static void registerMemberFn(R (Obj::* pmf) (Args... args),
01002                                  const char * name,
01003                                  Defaults... defaults)
01004     {
01005         // Set it up so that the member function is called when we
01006         // call the JS version
01007 
01008         v8::Local<v8::Signature> sig = v8::Signature::New(tmpl);
01009         v8::Local<v8::FunctionTemplate> cb
01010             =  v8::FunctionTemplate::New
01011             (MemberFunctionCaller<R, Obj, JSWrapped2, Args...>::call,
01012              pmfToValue(pmf, defaults...), sig);
01013         tmpl->PrototypeTemplate()->Set(v8::String::NewSymbol(name),
01014                                        cb);
01015     }
01016 
01017     static void addMemberFn(const std::string & functionSource,
01018                             const char * name,
01019                             unsigned options = v8::DontDelete | v8::ReadOnly)
01020     {
01021         v8::Handle<v8::Function> fn = getFunction("(" + functionSource + ")");
01022         tmpl->PrototypeTemplate()->Set(v8::String::NewSymbol(name), fn);
01023     }
01024 
01025     static void addMemberFn(const std::string & functionSource,
01026                             unsigned options = v8::DontDelete | v8::ReadOnly)
01027     {
01028         v8::Handle<v8::Function> fn = getFunction("(" + functionSource + ")");
01029         v8::Handle<v8::String> name = fn->GetName()->ToString();
01030         if (name.IsEmpty())
01031             throw ML::Exception("Function name was not a string");
01032         tmpl->PrototypeTemplate()->Set(name, fn);
01033     }
01034 
01035     static v8::Handle<v8::Value>
01036     extend(const v8::Arguments & args)
01037     {
01038         return JSWrappedBase::extendImpl<Wrapper>(args);
01039     }
01040 };
01041 
01042 template<typename Shared, typename Wrapper,
01043          const char * const & ClassNameT, const char * const & ModuleNameT,
01044          bool defaultWrapper>
01045 const char * const &
01046 JSWrapped2<Shared, Wrapper, ClassNameT, ModuleNameT, defaultWrapper>::
01047 ClassName = ClassNameT;
01048 
01049 template<typename Shared, typename Wrapper,
01050          const char * const & ClassNameT, const char * const & ModuleNameT,
01051          bool defaultWrapper>
01052 const char * const &
01053 JSWrapped2<Shared, Wrapper, ClassNameT, ModuleNameT, defaultWrapper>::
01054 Module = ModuleNameT;
01055 
01056 template<typename Shared, typename Wrapper,
01057          const char * const & ClassNameT, const char * const & ModuleNameT,
01058          bool defaultWrapper>
01059 DoInitialize
01060 JSWrapped2<Shared, Wrapper, ClassNameT, ModuleNameT, defaultWrapper>::
01061 initializer(InitializeFunction, DestructionFunction);
01062 
01063 template<typename Shared, typename Wrapper,
01064          const char * const & ClassNameT, const char * const & ModuleNameT,
01065          bool defaultWrapper>
01066 v8::Persistent<v8::FunctionTemplate>
01067 JSWrapped2<Shared, Wrapper, ClassNameT, ModuleNameT, defaultWrapper>::tmpl;
01068 
01069 
01070 /*****************************************************************************/
01071 /* JSWRAPPED3                                                                */
01072 /*****************************************************************************/
01073 
01095 template<typename Shared, typename Wrapper, typename Base,
01096          const char * const & ClassNameT,
01097          const char * const & ModuleNameT,
01098          bool defaultWrapper = true>
01099 struct JSWrapped3 : public Base {
01100 
01101     static const char * const & ClassName;
01102     static const char * const & Module;
01103 
01104     typedef Shared shared_type;
01105     typedef typename Base::base_shared_type base_shared_type;
01106 
01107     typedef typename Base::root_type root_type;
01108     typedef typename Base::root_shared_type root_shared_type;
01109 
01110     typedef boost::is_base_of<Base, Wrapper>
01111     WrapperIsDerivedFromBase;
01112 
01113     typedef boost::is_base_of<typename Base::shared_type, Shared>
01114     SharedIsDerivedFromBaseShared;
01115 
01116     static v8::Persistent<v8::FunctionTemplate> tmpl;
01117 
01118     typedef JSWrapped3<Shared, Wrapper, Base, ClassNameT, ModuleNameT,
01119                        defaultWrapper>
01120          WrapperType;
01121 
01122     JSWrapped3()
01123     {
01124         int x JML_UNUSED = initializer;
01125         BOOST_STATIC_ASSERT(WrapperIsDerivedFromBase::value);
01126         BOOST_STATIC_ASSERT(SharedIsDerivedFromBaseShared::value);
01127     }
01128 
01129     static v8::Local<v8::Object>
01130     toJS(const std::shared_ptr<Shared> & shared)
01131     {
01132         v8::Local<v8::Object> result = tmpl->GetFunction()->NewInstance();
01133         if (result.IsEmpty()) throw JSPassException();
01134         setShared(result, shared);
01135         return result;
01136     }
01137 
01138     template<typename Owner>
01139     static v8::Local<v8::Object>
01140     toJS(Shared & shared, const std::shared_ptr<Owner> & owner)
01141     {
01142         v8::Local<v8::Object> result = tmpl->GetFunction()->NewInstance();
01143         if (result.IsEmpty()) throw JSPassException();
01144         setShared(result, shared, owner);
01145         return result;
01146     }
01147 
01148     static std::shared_ptr<Shared>
01149     fromJS(v8::Handle<v8::Object> obj)
01150     {
01151         return getSharedPtr(obj);
01152     }
01153 
01154     virtual size_t memusage(void * object) const
01155     {
01156         return sizeof(Shared) + sizeof(Wrapper);
01157     }
01158 
01159     static inline Wrapper * getWrapper(v8::Handle<v8::Value> handle)
01160     {
01161         if (!tmpl->HasInstance(handle)) {
01162             //ML::backtrace();
01163             throw ML::Exception("we're not the right object: wanted C++ "
01164                                 + ML::type_name<Shared>() + " got JS "
01165                                 + cstr(handle));
01166         }
01167 
01168         Base * base = Base::getWrapper(handle);
01169         ExcAssert(base);
01170         Wrapper * result = dynamic_cast<Wrapper *>(base);
01171         if (!result)
01172             throw ML::Exception("1Base object " + ML::type_name<Base>()
01173                                 + " is not an instance of "
01174                                 + ML::type_name<Wrapper>()
01175                                 + " (it's a " + ML::type_name(*base) + ")");
01176         return result;
01177     }
01178 
01179     static inline Wrapper * getWrapper(const v8::Arguments & args)
01180     {
01181         return getWrapper(args.This());
01182     }
01183 
01184     static inline Shared * getShared(v8::Handle<v8::Value> handle)
01185     {
01186         root_shared_type * base = root_type::getShared(handle, tmpl, ClassName,
01187                                                        Module);
01188         ExcAssert(base);
01189         Shared * result = dynamic_cast<Shared *>(base);
01190         if (!result)
01191             throw ML::Exception("2Base shared object "
01192                                 + ML::type_name<typename Base::shared_type>()
01193                                 + " is not an instance of "
01194                                 + ML::type_name<Shared>()
01195                                 + " (it's a " + ML::type_name(*base) + ")");
01196         return result;
01197     }
01198 
01199     static inline Shared * getShared(const v8::Arguments & args)
01200     {
01201         return getShared(args.This());
01202     }
01203 
01204     static inline std::shared_ptr<Shared>
01205     getSharedPtr(v8::Handle<v8::Value> handle)
01206     {
01207         std::shared_ptr<typename Base::base_shared_type> base
01208             = Base::getWrapper(handle)->getWrappedObject();
01209         if (!base)
01210             throw ML::Exception("unrwapped closed object");
01211 
01212         std::shared_ptr<Shared> result
01213             = std::dynamic_pointer_cast<Shared>(base);
01214         if (!result)
01215             throw ML::Exception("Base shared object "
01216                                 + ML::type_name<typename Base::shared_type>()
01217                                 + " is not an instance of "
01218                                 + ML::type_name<Shared>()
01219                                 + " (it's a " + ML::type_name(*base) + ")");
01220         
01221         return result;
01222     }
01223 
01224     static inline std::shared_ptr<Shared>
01225     getSharedPtr(const v8::Arguments & args)
01226     {
01227         return getSharedPtr(args.This());
01228     }
01229 
01230     static inline void
01231     setShared(v8::Handle<v8::Value> handle,
01232               const std::shared_ptr<Shared> & shared)
01233     {
01234         ExcAssert(shared);
01235         getWrapper(handle)->setWrappedObject(shared);
01236     }
01237 
01238     // setShared when we also want to record a shared pointer of an owning
01239     // object that guarantees that the shared object isn't deleted
01240     template<typename Owner>
01241     static inline void
01242     setShared(v8::Handle<v8::Value> handle,
01243               Shared & shared,
01244               const std::shared_ptr<Owner> & owner)
01245     {
01246         ExcAssert(shared);
01247         auto sharedPtr = ML::make_unowned_std_sp(shared);
01248         getWrapper(handle)->setWrappedObject(sharedPtr);
01249         getWrapper(handle)->owner_ = owner;
01250     }
01251 
01252     static v8::Handle<v8::Value>
01253     NoConstructor(const v8::Arguments & args)
01254     {
01255         return Base::noConstructorError(ClassName, Module);
01256     }
01257 
01258     static v8::Handle<v8::Value>
01259     wrapperType(const v8::Arguments & args)
01260     {
01261         try {
01262             return JS::toJS(ClassName);
01263         } HANDLE_JS_EXCEPTIONS;
01264     }
01265 
01266     static void addMethods()
01267     {
01268         using namespace v8;
01269         NODE_SET_PROTOTYPE_METHOD(tmpl, "wrapperType", wrapperType);
01270     }
01271 
01272     static v8::Persistent<v8::FunctionTemplate>
01273     Register(SetupFunction setup = Base::Setup)
01274     {
01275         return Register(NoConstructor, setup);
01276     }
01277 
01278     static v8::Persistent<v8::FunctionTemplate>
01279     Register(v8::InvocationCallback constructor,
01280              SetupFunction setup = Base::Setup)
01281     {
01282         //std::cerr << "Register " << ClassName << " tmpl = "
01283         //          << &tmpl << std::endl;
01284 
01285         using namespace v8;
01286         
01287         Persistent<FunctionTemplate> t
01288             = Base::RegisterBase(ClassName, Module, constructor, setup);
01289         
01290         Persistent<FunctionTemplate> base = registry[Base::ClassName];
01291         t->Inherit(base);
01292 
01293         tmpl = t;
01294 
01295         using namespace std;
01296         //cerr << "    &tmpl = " << &tmpl << " *tmpl = " << *tmpl << endl;
01297 
01298         addMethods();
01299 
01300         return tmpl;
01301     }
01302 
01311     static v8::Local<v8::Object>
01312     constructMe(void * smart_ptr, const void * object)
01313     {
01314         // Change the pointer
01315         *(const void **)smart_ptr = object;
01316 
01317         // Cast to the correct type (it's guaranteed to be that)
01318         std::shared_ptr<Shared> & sp
01319             = *(std::shared_ptr<Shared> *)smart_ptr;
01320 
01321         return toJS(sp);
01322     }
01323 
01324     static void
01325     unwrapMe(const v8::Handle<v8::Value> & wrapper,
01326              void * outputPtr,
01327              const std::type_info & wrapperType)
01328     {
01329         /* Check that it is possible to convert our type into the given
01330            wrapper type. */
01331         
01332         throw ML::Exception("unwrapMe");
01333     }
01334 
01335     static void InitializeFunction()
01336     {
01337         registry.introduce(ClassNameT, ModuleNameT, Wrapper::Initialize,
01338                            Base::ClassName);
01339 ;
01340         if (defaultWrapper)
01341             registry.isWrapper<Shared, Wrapper>(constructMe, unwrapMe);
01342         registry.isBase<Base, Shared>();
01343     }
01344 
01345     static void DestructionFunction()
01346     {
01347     }
01348 
01349     static DoInitialize initializer;
01350 
01351     template<typename T, typename Obj>
01352     static void registerRWProperty(T (Obj::* ptr), const char * name,
01353                                    unsigned options = v8::DontDelete)
01354     {
01355         tmpl->InstanceTemplate()
01356             ->SetAccessor(v8::String::NewSymbol(name),
01357                           PropertyGetter<T, Obj, JSWrapped3>::getter,
01358                           PropertySetter<T, Obj, JSWrapped3>::setter,
01359                           pmToValue(ptr),
01360                           v8::DEFAULT,
01361                           v8::PropertyAttribute(options));
01362     }
01363 
01364     template<typename T, typename Obj>
01365     static void registerROProperty(T (Obj::* ptr), const char * name,
01366                                    unsigned options
01367                                    = v8::DontDelete | v8::ReadOnly)
01368     {
01369         tmpl->InstanceTemplate()
01370             ->SetAccessor(v8::String::NewSymbol(name),
01371                           PropertyGetter<T, Obj, JSWrapped3>::getter,
01372                           0,
01373                           pmToValue(ptr),
01374                           v8::DEFAULT,
01375                           v8::PropertyAttribute(options));
01376     }
01377 
01378     template<typename T, typename Obj>
01379     static void registerROProperty(T (Obj::* pmf) () const,
01380                                    const char * name,
01381                                    unsigned options
01382                                    = v8::DontDelete | v8::ReadOnly)
01383     {
01384         tmpl->InstanceTemplate()
01385             ->SetAccessor(v8::String::NewSymbol(name),
01386                           PropertyGetter<T, Obj, JSWrapped3>::pmfGetter,
01387                           0,
01388                           pmfToValue(pmf),
01389                           v8::DEFAULT,
01390                           v8::PropertyAttribute(options));
01391     }
01392 
01393     template<typename R, typename Obj, typename... Args>
01394     static void registerAsyncCallback(boost::function<R (Args...)> (Obj::* ptr),
01395                                       const char * name,
01396                                       unsigned options = v8::DontDelete)
01397     {
01398         typedef boost::function<R (Args...)> T;
01399 
01400         tmpl->InstanceTemplate()
01401             ->SetAccessor(v8::String::NewSymbol(name),
01402                           PropertyGetter<T, Obj, JSWrapped3>::getter,
01403                           AsyncCallbackSetter<T, Obj, JSWrapped3>::setter,
01404                           pmToValue(ptr),
01405                           v8::DEFAULT,
01406                           v8::PropertyAttribute(options));
01407     }
01408 
01409     template<typename R, typename Obj, typename... Args>
01410     static void registerMemberFn(R (Obj::* pmf) (Args... args) const,
01411                                  const char * name)
01412     {
01413         // Set it up so that the member function is called when we
01414         // call the JS version
01415 
01416         v8::Local<v8::Signature> sig = v8::Signature::New(tmpl);
01417         v8::Local<v8::FunctionTemplate> cb
01418             =  v8::FunctionTemplate::New
01419             (MemberFunctionCaller<R, Obj, JSWrapped3, Args...>::call,
01420              pmfToValue(pmf), sig);
01421         tmpl->PrototypeTemplate()->Set(v8::String::NewSymbol(name),
01422                                        cb);
01423     }
01424 
01425     template<typename R, typename Obj, typename... Args>
01426     static void registerMemberFn(R (Obj::* pmf) (Args... args),
01427                                  const char * name)
01428     {
01429         // Set it up so that the member function is called when we
01430         // call the JS version
01431 
01432         v8::Local<v8::Signature> sig = v8::Signature::New(tmpl);
01433         v8::Local<v8::FunctionTemplate> cb
01434             =  v8::FunctionTemplate::New
01435             (MemberFunctionCaller<R, Obj, JSWrapped3, Args...>::call,
01436              pmfToValue(pmf), sig);
01437         tmpl->PrototypeTemplate()->Set(v8::String::NewSymbol(name),
01438                                        cb);
01439     }
01440 
01441     static v8::Handle<v8::Value>
01442     extend(const v8::Arguments & args)
01443     {
01444         return JSWrappedBase::extendImpl<Wrapper>(args);
01445     }
01446 };
01447 
01448 template<typename Shared, typename Wrapper, typename Base,
01449          const char * const & ClassNameT, const char * const & ModuleNameT,
01450          bool defaultWrapper>
01451 const char * const &
01452 JSWrapped3<Shared, Wrapper, Base, ClassNameT, ModuleNameT, defaultWrapper>::
01453 ClassName = ClassNameT;
01454 
01455 template<typename Shared, typename Wrapper, typename Base,
01456          const char * const & ClassNameT, const char * const & ModuleNameT,
01457          bool defaultWrapper>
01458 const char * const &
01459 JSWrapped3<Shared, Wrapper, Base, ClassNameT, ModuleNameT, defaultWrapper>::
01460 Module = ModuleNameT;
01461 
01462 template<typename Shared, typename Wrapper, typename Base,
01463          const char * const & ClassNameT, const char * const & ModuleNameT,
01464          bool defaultWrapper>
01465 DoInitialize
01466 JSWrapped3<Shared, Wrapper, Base, ClassNameT, ModuleNameT, defaultWrapper>::
01467 initializer(InitializeFunction, DestructionFunction);
01468 
01469 template<typename Shared, typename Wrapper, typename Base,
01470          const char * const & ClassNameT, const char * const & ModuleNameT,
01471          bool defaultWrapper>
01472 v8::Persistent<v8::FunctionTemplate>
01473 JSWrapped3<Shared, Wrapper, Base, ClassNameT, ModuleNameT, defaultWrapper>::
01474 tmpl;
01475 
01476 } // namespace JS
01477 } // namespace Datacratic
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator