diff --git a/Lib/javascript/v8/javascriptcode.swg b/Lib/javascript/v8/javascriptcode.swg index 59b071c89..c2b6819d3 100644 --- a/Lib/javascript/v8/javascriptcode.swg +++ b/Lib/javascript/v8/javascriptcode.swg @@ -1,5 +1,5 @@ %fragment("JS_ctordefn", "templates") %{ -v8::Handle $jsmangledname_new(const v8::Arguments& args) { +v8::Handle $jswrapper(const v8::Arguments& args) { v8::HandleScope scope; v8::Handle self = args.Holder(); $jslocals @@ -8,13 +8,21 @@ v8::Handle $jsmangledname_new(const v8::Arguments& args) { return scope.Close(self); goto fail; fail: - return scope.Close(v8::Undefined); + return scope.Close(v8::Undefined()); +}%} + +%fragment ("JS_veto_ctor", "templates") +%{ +v8::Handle $jsctor(const v8::Arguments& args) { + v8::HandleScope scope; + SWIG_exception(SWIG_ERROR, "Class $jsname can not be instantiated"); + return scope.Close(v8::Undefined()); }%} %fragment("JS_getproperty", "templates") %{ v8::Handle $jsgetter(v8::Local property, const v8::AccessorInfo& info) { v8::HandleScope scope; - v8::Handle jsresult; + v8::Handle jsresult; $jslocals $jscode return scope.Close(jsresult); @@ -36,7 +44,7 @@ fail: %fragment("JS_functionwrapper", "templates") %{ v8::Handle $jswrapper(const v8::Arguments &args) { v8::HandleScope scope; - v8::Handle jsresult; + v8::Handle jsresult; $jslocals $jscode return scope.Close(jsresult); @@ -45,7 +53,6 @@ fail: return scope.Close(v8::Undefined()); }%} -// TODO: implement ctor overloading properly! %fragment ("JS_mainctordefn", "templates") %{ // TODO: implement JS_mainctordefn @@ -61,41 +68,41 @@ fail: // TODO: implement JS_destructordefn %} -%fragment("jsv8_declare_class_template", "templates") %{ -v8::Persistent SWIGV8_$jsmangledname;%} +%fragment("jsv8_declare_class_template", "templates") +%{v8::Persistent SWIGV8_$jsmangledname;%} -%fragment("jsv8_define_class_template", "templates") %{ -SWIGV8_$jsmangledname = SWIGV8_CreateClassTemplate("$jsname" , $jsmangledname_new);%} +%fragment("jsv8_define_class_template", "templates") +%{SWIGV8_$jsmangledname = SWIGV8_CreateClassTemplate("$jsname" , $jsctor);%} -%fragment("jsv8_create_class_instance", "templates") %{ -v8::Handle class_$jsmangledname = SWIGV8_$jsmangledname->GetFunction();%} +%fragment("jsv8_create_class_instance", "templates") +%{v8::Handle class_$jsmangledname = SWIGV8_$jsmangledname->GetFunction();%} -%fragment("jsv8_inherit", "templates") %{ -SWIGV8_$jsmangledname->Inherit(SWIGV8_$jsbaseclass);%} +%fragment("jsv8_inherit", "templates") +%{SWIGV8_$jsmangledname->Inherit(SWIGV8_$jsbaseclass);%} -%fragment("jsv8_register_class", "templates") %{ -$jsparent->Set(v8::String::NewSymbol("$jsname"), class_$jsmangledname);%} +%fragment("jsv8_register_class", "templates") +%{$jsparent->Set(v8::String::NewSymbol("$jsname"), class_$jsmangledname);%} -%fragment("jsv8_create_namespace", "templates") %{ -v8::Handle $jsmangledname = v8::ObjectTemplate::New();%} +%fragment("jsv8_create_namespace", "templates") +%{v8::Handle $jsmangledname = v8::ObjectTemplate::New();%} -%fragment("jsv8_register_member_function", "templates") %{ -SWIGV8_AddMemberFunction(SWIGV8_$jsmangledname, "$jsname", $jswrapper);%} +%fragment("jsv8_register_member_function", "templates") +%{SWIGV8_AddMemberFunction(SWIGV8_$jsmangledname, "$jsname", $jswrapper);%} -%fragment("jsv8_register_static_function", "templates") %{ -SWIGV8_AddGlobalFunction($jsparent, "$jsname", $jswrapper);%} +%fragment("jsv8_register_static_function", "templates") +%{SWIGV8_AddGlobalFunction(SWIGV8_$jsparent, "$jsname", $jswrapper);%} -%fragment("jsv8_register_member_variable", "templates") %{ -SWIGV8_AddMemberVariable(SWIGV8_$jsmangledname, "$jsname", $jsgetter, $jssetter);%} +%fragment("jsv8_register_member_variable", "templates") +%{SWIGV8_AddMemberVariable(SWIGV8_$jsmangledname, "$jsname", $jsgetter, $jssetter);%} -%fragment("jsv8_register_static_variable", "templates") %{ -SWIGV8_AddGlobalVariable($jsparent, "$jsname", $jsgetter, $jssetter);%} +%fragment("jsv8_register_static_variable", "templates") +%{SWIGV8_AddGlobalVariable(SWIGV8_$jsparent, "$jsname", $jsgetter, $jssetter);%} -%fragment("jsv8_register_namespace", "templates") %{ -$jsparent->Set(v8::String::NewSymbol("$jsname", $jsmangledname->NewInstance()));%} - -%fragment("JS_initializer", "templates") %{ +%fragment("jsv8_register_namespace", "templates") +%{$jsparent->Set(v8::String::NewSymbol("$jsname"), $jsmangledname->NewInstance());%} +%fragment("JS_initializer", "templates") +%{ extern "C" { void $jsname_initialize(v8::Handle context) @@ -115,12 +122,12 @@ void $jsname_initialize(v8::Handle context) /* setup inheritances */ $jsv8inheritance - /* class instances */ - $jsv8classinstances - /* add static class functions and variables */ $jsv8staticwrappers + /* class instances */ + $jsv8classinstances + /* register classes */ $jsv8registerclasses diff --git a/Lib/javascript/v8/javascripthelpers.swg b/Lib/javascript/v8/javascripthelpers.swg index 1159f7ef3..bd103702c 100644 --- a/Lib/javascript/v8/javascripthelpers.swg +++ b/Lib/javascript/v8/javascripthelpers.swg @@ -24,10 +24,12 @@ void SWIGV8_AddMemberFunction(v8::Handle class_templ, cons /** * Registers a class method with given name for a given class template. */ -void SWIGV8_AddGlobalFunction(v8::Handle obj_templ, const char* symbol, v8::InvocationCallback _func) { - obj_templ->Set(v8::String::NewSymbol(symbol), v8::FunctionTemplate::New(_func)->GetFunction()); +void SWIGV8_AddGlobalFunction(v8::Handle class_templ, const char* symbol, v8::InvocationCallback _func) { + v8::Handle obj_templ = class_templ->InstanceTemplate(); + obj_templ->Set(v8::String::NewSymbol(symbol), v8::FunctionTemplate::New(_func)->GetFunction()); } + /** * Registers a class property with given name for a given class template. */ @@ -39,7 +41,8 @@ void SWIGV8_AddMemberVariable(v8::Handle class_templ, cons /** * Registers a class method with given name for a given class template. */ -void SWIGV8_AddGlobalVariable(v8::Handle obj_templ, const char* symbol, v8::AccessorGetter getter, v8::AccessorSetter setter) { - obj_templ->SetAccessor(v8::String::NewSymbol(symbol), getter, setter); +void SWIGV8_AddGlobalVariable(v8::Handle class_templ, const char* symbol, v8::AccessorGetter getter, v8::AccessorSetter setter) { + v8::Handle obj_templ = class_templ->InstanceTemplate(); + obj_templ->SetAccessor(v8::String::NewSymbol(symbol), getter, setter); } %} // v8_helper_functions diff --git a/Lib/javascript/v8/javascriptruntime.swg b/Lib/javascript/v8/javascriptruntime.swg index 15d8a35fc..e8b26892c 100644 --- a/Lib/javascript/v8/javascriptruntime.swg +++ b/Lib/javascript/v8/javascriptruntime.swg @@ -24,7 +24,7 @@ typedef struct { bool swigCMemOwn; void *swigCObject; swig_type_info *info; -}SWIG_PRV_DATA; +} SWIG_PRV_DATA; %} %insert(runtime) %{ @@ -88,8 +88,27 @@ int SWIG_V8_ConvertPtr(v8::Handle valRef, void** ptr, swig_type_info } v8::Handle SWIG_V8_NewPointerObj(void *ptr, swig_type_info *info, int flags) { - // TODO: wrap ptr into an v8 object - return v8::Undefined(); + v8::HandleScope scope; + + v8::Local class_templ; + if(info->clientdata == NULL) { + // TODO: get class template for unknown types + //class_templ = _SwigObject_classRef; + } else { + class_templ = *((v8::Local*) info->clientdata); + } + + v8::Handle inst_templ = class_templ->InstanceTemplate(); + v8::Local result = inst_templ->NewInstance(); + + SWIG_PRV_DATA* cdata = (SWIG_PRV_DATA*) new SWIG_PRV_DATA; + cdata->swigCObject = ptr; + cdata->swigCMemOwn = (flags & SWIG_POINTER_OWN) ? 1 : 0; + cdata->info = info; + + result->SetInternalField(0, v8::External::New(cdata)); + + return scope.Close(result); } #define SWIG_ConvertPtr(obj, ptr, info, flags) SWIG_V8_ConvertPtr(obj, ptr, info, flags) diff --git a/Source/Modules/javascript.cxx b/Source/Modules/javascript.cxx index 3ccc9ffa4..14b2e7859 100644 --- a/Source/Modules/javascript.cxx +++ b/Source/Modules/javascript.cxx @@ -1708,21 +1708,29 @@ int V8Emitter::enterClass(Node *n) t_decl_class.replace(T_NAME_MANGLED, state.clazz(NAME_MANGLED)) .pretty_print(f_class_templates); - // emit definition of v8 class template - Template t_def_class(getTemplate("jsv8_define_class_template")); - t_def_class.replace(T_NAME_MANGLED, state.clazz(NAME_MANGLED)) - .replace(T_NAME, state.clazz(NAME)) - .pretty_print(f_init_class_templates); - - Template t_class_instance(getTemplate("jsv8_create_class_instance")); - t_class_instance.replace(T_NAME_MANGLED, state.clazz(NAME_MANGLED)) - .pretty_print(f_init_class_instances); - return SWIG_OK; } int V8Emitter::exitClass(Node *n) { + if(GetFlag(state.clazz(), IS_ABSTRACT)) { + Template t_veto_ctor(getTemplate("JS_veto_ctor")); + t_veto_ctor.replace(T_CTOR, state.clazz(CTOR)) + .replace(T_NAME, state.clazz(NAME)) + .pretty_print(f_wrappers); + } + + // emit definition of v8 class template + Template t_def_class(getTemplate("jsv8_define_class_template")); + t_def_class.replace(T_NAME_MANGLED, state.clazz(NAME_MANGLED)) + .replace(T_NAME, state.clazz(NAME)) + .replace(T_CTOR, state.clazz(CTOR)) + .pretty_print(f_init_class_templates); + + Template t_class_instance(getTemplate("jsv8_create_class_instance")); + t_class_instance.replace(T_NAME_MANGLED, state.clazz(NAME_MANGLED)) + .pretty_print(f_init_class_instances); + // emit inheritance setup Node* baseClass = getBaseClass(n); if(baseClass) { @@ -1759,14 +1767,11 @@ int V8Emitter::exitVariable(Node* n) if(GetFlag(n, "ismember")) { if(GetFlag(state.variable(), IS_STATIC)) { Template t_register(getTemplate("jsv8_register_static_variable")); - String *class_instance = NewString(""); - Printf(class_instance, "class_%s", state.clazz(NAME_MANGLED)); - t_register.replace(T_PARENT, class_instance) + t_register.replace(T_PARENT, state.clazz(NAME_MANGLED)) .replace(T_NAME, state.variable(NAME)) .replace(T_GETTER, state.variable(GETTER)) .replace(T_SETTER, state.variable(SETTER)) .pretty_print(f_init_static_wrappers); - Delete(class_instance); } else { Template t_register(getTemplate("jsv8_register_member_variable")); t_register.replace(T_NAME_MANGLED, state.clazz(NAME_MANGLED)) @@ -1779,7 +1784,7 @@ int V8Emitter::exitVariable(Node* n) // Note: a global variable is treated like a static variable // with the parent being a nspace object (instead of class object) Template t_register(getTemplate("jsv8_register_static_variable")); - t_register.replace(T_PARENT, Getattr(current_namespace, "name")) + t_register.replace(T_PARENT, Getattr(current_namespace, NAME)) .replace(T_NAME, state.variable(NAME)) .replace(T_GETTER, state.variable(GETTER)) .replace(T_SETTER, state.variable(SETTER)) @@ -1802,16 +1807,13 @@ int V8Emitter::exitFunction(Node* n) if(GetFlag(n, "ismember")) { if(GetFlag(state.function(), IS_STATIC)) { Template t_register(getTemplate("jsv8_register_static_function")); - String *class_instance = NewString(""); - Printf(class_instance, "class_%s", state.clazz(NAME_MANGLED)); - t_register.replace(T_PARENT, class_instance) + t_register.replace(T_PARENT, state.clazz(NAME_MANGLED)) .replace(T_NAME, state.function(NAME)) .replace(T_WRAPPER, Getattr(n, "wrap:name")); Printv(f_init_static_wrappers, t_register.str(), 0); - Delete(class_instance); } else { Template t_register(getTemplate("jsv8_register_member_function")); - t_register.replace(T_PARENT, state.clazz(NAME_MANGLED)) + t_register.replace(T_NAME_MANGLED, state.clazz(NAME_MANGLED)) .replace(T_NAME, state.function(NAME)) .replace(T_WRAPPER, Getattr(n, "wrap:name")); Printv(f_init_wrappers, t_register.str(), "\n", 0); @@ -1820,7 +1822,7 @@ int V8Emitter::exitFunction(Node* n) // Note: a global function is treated like a static function // with the parent being a nspace object instead of class object Template t_register(getTemplate("jsv8_register_static_function")); - t_register.replace(T_PARENT, Getattr(current_namespace, "name")) + t_register.replace(T_PARENT, Getattr(current_namespace, NAME)) .replace(T_NAME, state.function(NAME)) .replace(T_WRAPPER, Getattr(n, "wrap:name")); Printv(f_init_wrappers, t_register.str(), 0); @@ -1881,21 +1883,27 @@ void V8Emitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, Mar } int V8Emitter::emitNamespaces() { -// TODO: handle namespaces: -/* - // create namespace object and register it to the parent scope - Template t_create_ns(getTemplate(V8_CREATE_NAMESPACE)); - t_create_ns.Replace(V8_MANGLED_NAME, scope_mangled); - - Template t_register_ns(getTemplate(V8_REGISTER_NAMESPACE)); - t_register_ns.Replace(V8_MANGLED_NAME, scope_mangled) - .Replace(V8_CONTEXT, parent_scope_mangled) - .Replace(V8_UNQUALIFIED_NAME, scope_unqualified); + Iterator it; + for (it = First(namespaces); it.item; it = Next(it)) { + Hash *entry = it.item; + String *name = Getattr(entry, NAME); + String *name_mangled = Getattr(entry, NAME_MANGLED); + String *parent = Getattr(entry, PARENT); + String *parent_mangled = Swig_name_mangle(parent); - Printv(f_init_namespaces, t_create_ns.str(), 0); + // create namespace object and register it to the parent scope + Template t_create_ns(getTemplate("jsv8_create_namespace")); + t_create_ns.replace(T_NAME_MANGLED, name_mangled) + .pretty_print(f_init_namespaces); + + Template t_register_ns(getTemplate("jsv8_register_namespace")); + t_register_ns.replace(T_NAME_MANGLED, name_mangled) + .replace(T_NAME, name) + .replace(T_PARENT, parent_mangled); + // prepend in order to achieve reversed order of registration statements Insert(f_init_register_namespaces, 0, t_register_ns.str()); -*/ + } return SWIG_OK; } @@ -2044,9 +2052,9 @@ String *Template::str() { String *pre_code = NewString(""); String *post_code = NewString(""); String *debug_code = NewString(""); - Printf(pre_code, "//begin fragment(\"%s\")\n", templateName); - Printf(post_code, "//end fragment(\"%s\")\n", templateName); - Printf(debug_code, "%s\n%s\n%s", pre_code, code, post_code); + Printf(pre_code, "/* begin fragment(\"%s\") */", templateName); + Printf(post_code, "/* end fragment(\"%s\") */", templateName); + Printf(debug_code, "%s\n%s\n%s\n", pre_code, code, post_code); Delete(code); Delete(pre_code);