diff --git a/CMakeLists.txt b/CMakeLists.txt index e7d96cc8e..1bf7a2c76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,10 +135,6 @@ add_library(modules "${SWIG_SOURCE_DIR}/Modules/allegrocl.cxx" "${SWIG_SOURCE_DIR}/Modules/guile.cxx" "${SWIG_SOURCE_DIR}/Modules/java.cxx" "${SWIG_SOURCE_DIR}/Modules/javascript.cxx" - "${SWIG_SOURCE_DIR}/Modules/javascript_emitter.h" - "${SWIG_SOURCE_DIR}/Modules/javascript_emitter.cxx" - "${SWIG_SOURCE_DIR}/Modules/javascript_v8.h" - "${SWIG_SOURCE_DIR}/Modules/javascript_v8.cxx" "${SWIG_SOURCE_DIR}/Modules/lang.cxx" "${SWIG_SOURCE_DIR}/Modules/lua.cxx" "${SWIG_SOURCE_DIR}/Modules/modula3.cxx" diff --git a/Lib/javascript/v8/javascriptcode.swg b/Lib/javascript/v8/javascriptcode.swg index a6cd18c62..d79a0c34b 100644 --- a/Lib/javascript/v8/javascriptcode.swg +++ b/Lib/javascript/v8/javascriptcode.swg @@ -111,14 +111,28 @@ fail: * ----------------------------------------------------------------------------- */ %fragment ("js_dtor", "templates") %{ -void $jswrapper(v8::Isolate *iso, v8::Persistent< v8::Object > * object, SWIGV8_Proxy *proxy) { + +#ifdef BUILDING_NODE_EXTENSION +void $jswrapper(v8::Persistent< v8::Value > object, void *parameter) +#else +void $jswrapper(v8::Isolate *isolate, v8::Persistent< v8::Object > * object, SWIGV8_Proxy *proxy) +#endif +{ if(proxy->swigCMemOwn && proxy->swigCObject) { +#ifdef SWIGRUNTIME_DEBUG + printf("Deleting wrapped instance: %s\n", proxy->info->name); +#endif $jsfree proxy->swigCObject; } delete proxy; - object->Dispose(); object->Clear(); + +#ifdef BUILDING_NODE_EXTENSION + object->Dispose(); +#else + object->Dispose(isolate); +#endif } %} @@ -266,6 +280,7 @@ fail: SWIGTYPE$jsmangledtype->clientdata = &$jsmangledname_clientData; %} + /* ----------------------------------------------------------------------------- * jsv8_inherit: template for an class inherit statement. * - $jsmangledname: mangled class name @@ -273,7 +288,17 @@ fail: * ----------------------------------------------------------------------------- */ %fragment("jsv8_inherit", "templates") %{ - $jsmangledname_class->Inherit($jsbaseclass_class); + if (SWIGTYPE_p$jsbaseclass->clientdata && !(static_cast(SWIGTYPE_p$jsbaseclass->clientdata)->class_templ.IsEmpty())) + { + $jsmangledname_class->Inherit(static_cast(SWIGTYPE_p$jsbaseclass->clientdata)->class_templ); +#ifdef SWIGRUNTIME_DEBUG + printf("Inheritance successful $jsmangledname $jsbaseclass\n"); +#endif + } else { +#ifdef SWIGRUNTIME_DEBUG + printf("Unable to inherit baseclass, it didn't exist $jsmangledname $jsbaseclass\n"); +#endif + } %} /* ----------------------------------------------------------------------------- @@ -387,9 +412,13 @@ fail: %{ extern "C" { +#ifdef BUILDING_NODE_EXTENSION +void $jsname_initialize(v8::Handle global_obj, v8::Handle /*module*/) +#else void $jsname_initialize(v8::Handle global_obj) +#endif { - SWIG_InitializeModule(0); + SWIG_InitializeModule(static_cast(&global_obj)); v8::HandleScope scope; @@ -419,8 +448,13 @@ void $jsname_initialize(v8::Handle global_obj) /* create and register namespace objects */ $jsv8registernspaces - } +#ifdef BUILDING_NODE_EXTENSION +NODE_MODULE($jsname, $jsname_initialize); +#endif + + + } // extern "C" %} diff --git a/Lib/javascript/v8/javascriptinit.swg b/Lib/javascript/v8/javascriptinit.swg index 1bca4c244..684728023 100644 --- a/Lib/javascript/v8/javascriptinit.swg +++ b/Lib/javascript/v8/javascriptinit.swg @@ -1,14 +1,42 @@ %insert(init) %{ -SWIGRUNTIME void -SWIG_V8_SetModule(swig_module_info *swig_module) {} -SWIGRUNTIME swig_module_info * -SWIG_V8_GetModule(void) { - return 0; + +SWIGRUNTIME void +SWIG_V8_SetModule(void *, swig_module_info *swig_module) { + v8::Local global_obj = v8::Context::GetCurrent()->Global(); + v8::Local mod = v8::External::New(swig_module); + assert(!mod.IsEmpty()); + global_obj->SetHiddenValue(v8::String::New("swig_module_info_data"), mod); } -#define SWIG_GetModule(clientdata) SWIG_V8_GetModule() -#define SWIG_SetModule(clientdata, pointer) SWIG_V8_SetModule(pointer) +SWIGRUNTIME swig_module_info * +SWIG_V8_GetModule(void *) { + v8::Local global_obj = v8::Context::GetCurrent()->Global(); + v8::Local moduleinfo = global_obj->GetHiddenValue(v8::String::New("swig_module_info_data")); + + if (moduleinfo.IsEmpty()) + { + // It's not yet loaded + return 0; + } + + v8::Local moduleinfo_extern = v8::Local::Cast(moduleinfo); + + if (moduleinfo_extern.IsEmpty()) + { + // Something's not right + return 0; + } + + void *ptr = moduleinfo_extern->Value(); + assert(ptr); + swig_module_info *retptr = static_cast(ptr); + assert(retptr); + return retptr; +} + +#define SWIG_GetModule(clientdata) SWIG_V8_GetModule(clientdata) +#define SWIG_SetModule(clientdata, pointer) SWIG_V8_SetModule(clientdata, pointer) %} diff --git a/Lib/javascript/v8/javascriptruntime.swg b/Lib/javascript/v8/javascriptruntime.swg index 12c274ed2..f2443ce1f 100644 --- a/Lib/javascript/v8/javascriptruntime.swg +++ b/Lib/javascript/v8/javascriptruntime.swg @@ -5,7 +5,9 @@ * ----------------------------------------------------------------------------- */ %insert(runtime) %{ + #include + #include #include %} @@ -60,7 +62,7 @@ public: %insert(runtime) %{ -// Note: to trigger the c8 gc more often one can tell v8 about the memory consumption +// Note: to trigger the v8 gc more often one can tell v8 about the memory consumption // TODO: we could add a v8 specific parameter to control this value #define SWIGV8_AVG_OBJ_SIZE 1000 @@ -71,9 +73,19 @@ public: }; ~SWIGV8_Proxy() { +#ifdef BUILDING_NODE_EXTENSION handle.ClearWeak(); +#else + handle.ClearWeak(v8::Isolate::GetCurrent()); +#endif + //handle->SetInternalField(0, v8::Undefined()); + +#ifdef BUILDING_NODE_EXTENSION handle.Dispose(); +#else + handle.Dispose(v8::Isolate::GetCurrent()); +#endif handle.Clear(); v8::V8::AdjustAmountOfExternalAllocatedMemory(-SWIGV8_AVG_OBJ_SIZE); } @@ -87,7 +99,12 @@ public: class SWIGV8_ClientData { public: v8::Persistent class_templ; - void (*dtor) (v8::Isolate *iso, v8::Persistent< v8::Object > *object, SWIGV8_Proxy *parameter); + +#ifdef BUILDING_NODE_EXTENSION + void (*dtor) (v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy); +#else + void (*dtor) (v8::Isolate *isolate, v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy); +#endif }; v8::Persistent SWIGV8_SWIGTYPE_Proxy_class_templ; @@ -101,15 +118,11 @@ int SWIG_V8_ConvertInstancePtr(v8::Handle objRef, void** ptr, swig_t return SWIG_ERROR; } if(cdata->info != info) { - bool type_valid = false; - swig_cast_info *t = info->cast; - while(t != NULL) { - if(t->type == cdata->info) { - type_valid = true; - break; - } - t = t->next; + swig_cast_info *tc = SWIG_TypeCheckStruct(cdata->info, info); + if (!tc && cdata->info->name) { + tc = SWIG_TypeCheck(cdata->info->name, info); } + bool type_valid = tc != 0; if(!type_valid) { return SWIG_TypeError; } @@ -121,8 +134,13 @@ int SWIG_V8_ConvertInstancePtr(v8::Handle objRef, void** ptr, swig_t return SWIG_OK; } -void SWIGV8_Proxy_DefaultDtor(v8::Isolate* isolate, v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy) { - delete proxy; +#ifdef BUILDING_NODE_EXTENSION +void SWIGV8_Proxy_DefaultDtor(v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy) +#else +void SWIGV8_Proxy_DefaultDtor(v8::Isolate *, v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy) +#endif +{ + delete proxy; } void SWIGV8_SetPrivateData(v8::Handle obj, void* ptr, swig_type_info *info, int flags) { @@ -132,8 +150,13 @@ void SWIGV8_SetPrivateData(v8::Handle obj, void* ptr, swig_type_info cdata->info = info; obj->SetAlignedPointerInInternalField(0, cdata); +#ifdef BUILDING_NODE_EXTENSION + #warning port me +#else cdata->handle.Reset(v8::Isolate::GetCurrent(), obj); +#endif +#ifdef BUILDING_NODE_EXTENSION // clientdata must be set for owned data as we need to register the dtor if(cdata->swigCMemOwn) { cdata->handle.MakeWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor); @@ -141,6 +164,14 @@ void SWIGV8_SetPrivateData(v8::Handle obj, void* ptr, swig_type_info cdata->handle.MakeWeak(cdata, SWIGV8_Proxy_DefaultDtor); } cdata->handle.MarkIndependent(); +#else + if(cdata->swigCMemOwn) { + cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor); + } else { + cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, SWIGV8_Proxy_DefaultDtor); + } + cdata->handle.MarkIndependent(v8::Isolate::GetCurrent()); +#endif } int SWIG_V8_ConvertPtr(v8::Handle valRef, void** ptr, swig_type_info *info, int flags) { @@ -175,4 +206,8 @@ v8::Handle SWIG_V8_NewPointerObj(void *ptr, swig_type_info *info, in #define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_V8_ConvertInstancePtr(obj, pptr, type, flags) #define SWIG_NewInstanceObj(thisvalue, type, flags) SWIG_V8_NewPointerObj(thisvalue, type, flags) +#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_V8_ConvertPtr(obj, pptr, type, 0) +#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_V8_NewPointerObj(ptr, type, 0) + %} + diff --git a/Lib/javascript/v8/node.i b/Lib/javascript/v8/node.i index 4baa5e72f..8bf9ef061 100644 --- a/Lib/javascript/v8/node.i +++ b/Lib/javascript/v8/node.i @@ -1,15 +1,12 @@ -%insert("init") %{ +%insert("begin") %{ #ifndef BUILDING_NODE_EXTENSION #define BUILDING_NODE_EXTENSION #endif - -#include %} -%define %node(moduleName) -%insert("post-init") %{ -extern "C" { - NODE_MODULE(moduleName, moduleName ## _initialize) -} +%insert("runtime") %{ +// we are including relative to the src folder because of issues +// with other files which might be named "node.h" +#include %} -%enddef + diff --git a/Lib/javascript/v8/std_pair.i b/Lib/javascript/v8/std_pair.i index fe45ee676..8d6057223 100755 --- a/Lib/javascript/v8/std_pair.i +++ b/Lib/javascript/v8/std_pair.i @@ -5,7 +5,6 @@ * ----------------------------------------------------------------------------- */ %include -%include // ------------------------------------------------------------------------ // std::pair diff --git a/Lib/javascript/v8/std_string.i b/Lib/javascript/v8/std_string.i index e3248742b..5ad1ead27 100755 --- a/Lib/javascript/v8/std_string.i +++ b/Lib/javascript/v8/std_string.i @@ -73,7 +73,7 @@ namespace std { %typemap(out, fragment="SWIGV8_stringToValue") const string & %{ - $result = SWIGV8_stringToValue($1); + $result = SWIGV8_stringToValue(*$1); %} } diff --git a/Makefile.in b/Makefile.in index 9a19d73fa..c1fc82f74 100644 --- a/Makefile.in +++ b/Makefile.in @@ -431,7 +431,8 @@ install-main: @$(INSTALL_PROGRAM) $(TARGET) $(DESTDIR)$(BIN_DIR)/`echo $(TARGET_NOEXE) | sed '$(transform)'`@EXEEXT@ lib-languages = gcj typemaps tcl perl5 python guile java mzscheme ruby php ocaml octave \ - pike chicken csharp modula3 allegrocl clisp lua cffi uffi r go d javascript javascript/jsc javascript/v8 + pike chicken csharp modula3 allegrocl clisp lua cffi uffi r go d javascript javascript/jsc \ + javascript/v8 lib-modules = std diff --git a/Source/Modules/javascript.cxx b/Source/Modules/javascript.cxx index cd562737f..4c36e838a 100644 --- a/Source/Modules/javascript.cxx +++ b/Source/Modules/javascript.cxx @@ -22,7 +22,6 @@ bool js_template_enable_debug = false; #define CTOR_DISPATCHERS "ctor_dispatchers" #define DTOR "dtor" #define ARGCOUNT "wrap:argc" -#define FUNCTION_DISPATCHERS "function_dispatchers" // variables used in code templates // ATTENTION: be aware of prefix collisions when defining those variables @@ -793,12 +792,6 @@ int JSEmitter::enterFunction(Node *n) { SetFlag(state.function(), IS_STATIC); } - /* Initialize DOH for collecting function dispatchers */ - bool is_overloaded = GetFlag(n, "sym:overloaded"); - if (is_overloaded && state.global(FUNCTION_DISPATCHERS) == 0) { - state.global(FUNCTION_DISPATCHERS, NewString("")); - } - return SWIG_OK; } @@ -1061,13 +1054,6 @@ int JSEmitter::emitFunction(Node *n, bool is_member, bool is_static) { .replace(T_ARGCOUNT, Getattr(n, ARGCOUNT)) .pretty_print(f_wrappers); - // handle function overloading - if (is_overloaded) { - Template t_dispatch_case = getTemplate("js_function_dispatch_case"); - t_dispatch_case.replace(T_WRAPPER, wrap_name) - .replace(T_ARGCOUNT, Getattr(n, ARGCOUNT)); - Append(state.global(FUNCTION_DISPATCHERS), t_dispatch_case.str()); - } DelWrapper(wrapper); @@ -1075,14 +1061,47 @@ int JSEmitter::emitFunction(Node *n, bool is_member, bool is_static) { } int JSEmitter::emitFunctionDispatcher(Node *n, bool /*is_member */ ) { + Wrapper *wrapper = NewWrapper(); + + // Generate call list, go to first node + Node *sibl = n; + + while (Getattr(sibl, "sym:previousSibling")) + sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up + + do { + String *siblname = Getattr(sibl, "wrap:name"); + + if (siblname) + { + // handle function overloading + Template t_dispatch_case = getTemplate("js_function_dispatch_case"); + t_dispatch_case.replace(T_WRAPPER, siblname) + .replace(T_ARGCOUNT, Getattr(sibl, ARGCOUNT)); + + Append(wrapper->code, t_dispatch_case.str()); + } + + } while ((sibl = Getattr(sibl, "sym:nextSibling"))); + + + Template t_function(getTemplate("js_function_dispatcher")); - Wrapper *wrapper = NewWrapper(); - String *wrap_name = Swig_name_wrapper(Getattr(n, "name")); - Setattr(n, "wrap:name", wrap_name); +// String *wrap_name = Swig_name_wrapper(Getattr(n, "name")); - Append(wrapper->code, state.global(FUNCTION_DISPATCHERS)); + + String *fun_name = Getattr(n, "sym:name"); + + Node *methodclass = Swig_methodclass(n); + String *class_name = Getattr(methodclass, "sym:name"); + + String *new_string = NewStringf("%s_%s", class_name, fun_name); + String *wrap_name = Swig_name_wrapper(new_string); + + Setattr(n, "wrap:name", wrap_name); + state.function(WRAPPER_NAME, wrap_name); t_function.replace(T_LOCALS, wrapper->locals) .replace(T_CODE, wrapper->code); @@ -1093,7 +1112,6 @@ int JSEmitter::emitFunctionDispatcher(Node *n, bool /*is_member */ ) { .pretty_print(f_wrappers); // Delete the state variable - state.global(FUNCTION_DISPATCHERS, NewString("")); DelWrapper(wrapper); return SWIG_OK; @@ -1480,7 +1498,7 @@ int JSCEmitter::exitFunction(Node *n) { // handle overloaded functions if (is_overloaded) { if (!Getattr(n, "sym:nextSibling")) { - state.function(WRAPPER_NAME, Swig_name_wrapper(Getattr(n, "name"))); + //state.function(WRAPPER_NAME, Swig_name_wrapper(Getattr(n, "name"))); // create dispatcher emitFunctionDispatcher(n, is_member); } else { @@ -1742,6 +1760,7 @@ int V8Emitter::initialize(Node *n) f_init_register_namespaces = NewString(""); // note: this is necessary for built-in generation of swig runtime code + Swig_register_filebyname("begin", f_wrap_cpp); Swig_register_filebyname("runtime", f_runtime); Swig_register_filebyname("header", f_header); Swig_register_filebyname("init", f_init); @@ -1757,7 +1776,8 @@ int V8Emitter::dump(Node *) SwigType_emit_type_table(f_runtime, f_wrappers); - emitUndefined(); + // Let's not and say we did + // emitUndefined(); Printv(f_wrap_cpp, f_runtime, "\n", 0); Printv(f_wrap_cpp, f_header, "\n", 0); @@ -1859,12 +1879,15 @@ int V8Emitter::exitClass(Node *n) // emit inheritance setup Node* baseClass = getBaseClass(n); if(baseClass) { + String *base_name = Getattr(baseClass, "name"); + Template t_inherit = getTemplate("jsv8_inherit"); - String *base_name_mangled = SwigType_manglestr(Getattr(baseClass, "name")); + + String *base_name_mangled = SwigType_manglestr(base_name); t_inherit.replace(T_NAME_MANGLED, state.clazz(NAME_MANGLED)) - .replace(T_BASECLASS, base_name_mangled) - .trim() - .pretty_print(f_init_inheritance); + .replace(T_BASECLASS, base_name_mangled) + .trim() + .pretty_print(f_init_inheritance); Delete(base_name_mangled); } @@ -1932,7 +1955,7 @@ int V8Emitter::exitFunction(Node* n) bool is_overloaded = GetFlag(n, "sym:overloaded"); if (is_overloaded) { if (!Getattr(n, "sym:nextSibling")) { - state.function(WRAPPER_NAME, Swig_name_wrapper(Getattr(n, "name"))); + //state.function(WRAPPER_NAME, Swig_name_wrapper(Getattr(n, "name"))); emitFunctionDispatcher(n, is_member); } else { //don't register wrappers of overloaded functions in function tables