![]() |
RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
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