[mapguide-commits] r7632 - sandbox/jng/node/Oem/SWIGEx/Source/Modules

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Wed Jun 19 08:04:24 PDT 2013


Author: jng
Date: 2013-06-19 08:04:24 -0700 (Wed, 19 Jun 2013)
New Revision: 7632

Modified:
   sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx
Log:
This submission includes:
 * Native class constructor overload resolution (currently naively based on argument number count checking)
 * Refactor the argument setup into reusable classes 
 * Implement codegen to return JS wrappers for methods that return MapGuide pointers (doesn't properly handle inheritance yet)


Modified: sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx
===================================================================
--- sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx	2013-06-19 06:59:08 UTC (rev 7631)
+++ sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx	2013-06-19 15:04:24 UTC (rev 7632)
@@ -1,5 +1,6 @@
 #include "swigmod.h"
 #include <vector>
+#include <map>
 #include <sstream>
 
 #define EXPORTS_VAR "exports"
@@ -113,6 +114,47 @@
     }
 };
 
+class ArgInfo
+{
+public:
+    ArgInfo(std::string sName, std::string sType, int iOffset, bool bMgPointer)
+    {
+        name = sName;
+        type = sType;
+        isMgPointer = bMgPointer;
+        offset = iOffset;
+    }
+
+    std::string name;
+    std::string type;
+    bool isMgPointer;
+    int offset;
+};
+
+class FunctionCallSetup
+{
+private:
+    std::string m_funcArgsStr;
+    std::vector<ArgInfo> m_args;
+public:
+    FunctionCallSetup()
+    {
+    }
+
+    void setFunctionArgumentString(std::string str) { m_funcArgsStr = str; }
+    const char* getFunctionArgumentString() const { return m_funcArgsStr.c_str(); }
+
+    const std::vector<ArgInfo>& getArgs() const { return m_args; }
+
+    void addArg(std::string sName, std::string sType, int argOffset, bool bMgPointer)
+    {
+        ArgInfo ai(sName, sType, argOffset, bMgPointer);
+        m_args.push_back(ai);
+    }
+};
+
+typedef std::map<std::string, std::string> StringMap;
+
 class NODEJS : public Language
 {
 private:
@@ -120,25 +162,28 @@
     String* m_currentClassName;
     File* m_fOutputFile;
     std::vector<std::string> m_classFwdDecls;
-    std::vector<std::string> m_classDecls;
+    StringMap m_classDecls;
     std::vector<std::string> m_classMethodDecls;
     std::vector<std::string> m_classExportCalls;
     std::vector<std::string> m_classInheritCalls;
     std::vector<std::string> m_classMemberExportCalls;
     std::vector<std::string> m_classSetupCalls;
+    StringMap m_ctorSetupCode;
     std::string m_currentFragment;
     std::string m_currentExportFragment;
     std::string m_currentInheritFragment;
     std::string m_currentMethodFragment;
     std::string m_currentClassSetupFragment;
     int m_indentationLevels;
-    
+    bool m_bInsertDebuggingCode;
+
 public:
     NODEJS() : 
         m_namespace(NULL),
         m_currentClassName(NULL),
         m_fOutputFile(NULL),
-        m_indentationLevels(0)
+        m_indentationLevels(0),
+        m_bInsertDebuggingCode(true)
     { }
 
     virtual void main(int argc, char* argv[])
@@ -203,24 +248,28 @@
         //
 
         Language::top(n);
+
         writeToFile("//=====================================\n");
-        writeToFile("//Forward declarations\n");
+        writeToFile("//Proxy class definitions\n");
         writeToFile("//=====================================\n");
-        for (std::vector<std::string>::iterator it = m_classFwdDecls.begin(); it != m_classFwdDecls.end(); it++)
+        for (StringMap::iterator it = m_classDecls.begin(); it != m_classDecls.end(); it++)
         {
-            std::string call = (*it);
+            std::string call = it->second;
             writeToFile(call);
             writeToFile("\n");
         }
 
         writeToFile("//=====================================\n");
-        writeToFile("//Proxy class definitions\n");
+        writeToFile("//v8 persistent Proxy class constructors\n");
         writeToFile("//=====================================\n");
-        for (std::vector<std::string>::iterator it = m_classDecls.begin(); it != m_classDecls.end(); it++)
+        for (StringMap::iterator it = m_classDecls.begin(); it != m_classDecls.end(); it++)
         {
-            std::string call = (*it);
-            writeToFile(call);
-            writeToFile("\n");
+            std::string clsName = it->first;
+            std::string proxyClassName;
+            setProxyClassName(clsName.c_str(), proxyClassName);
+
+            writeToFile(NewStringf("v8::Persistent<v8::FunctionTemplate> %s::constructor_tpl;\n", proxyClassName.c_str()));
+            writeToFile(NewStringf("v8::Persistent<v8::Function> %s::constructor;\n", proxyClassName.c_str()));
         }
 
         writeToFile("//=====================================\n");
@@ -234,6 +283,44 @@
         }
 
         writeToFile("//=====================================\n");
+        writeToFile("//Proxy class constructor definitions\n");
+        writeToFile("//=====================================\n");
+        for (StringMap::iterator it = m_classDecls.begin(); it != m_classDecls.end(); it++)
+        {
+            std::string clsName = it->first;
+            std::string proxyClsName;
+            setProxyClassName(clsName.c_str(), proxyClsName);
+            writeToFile(NewStringf("v8::Handle<v8::Value> %s::%s(const v8::Arguments& %s)\n", proxyClsName.c_str(), CLASS_PROXY_CTOR_NAME, ARGS_VAR));
+            writeToFile("{\n");
+            if (m_ctorSetupCode.find(clsName) != m_ctorSetupCode.end())
+            {
+                std::string code;
+                {
+                    Indenter ind(m_indentationLevels);
+                    FragmentWriter codeWriter(m_indentationLevels, code);
+                    {
+                        std::string mbMethodName;
+                        mbMethodName += proxyClsName;
+                        mbMethodName += "::";
+                        mbMethodName += CLASS_PROXY_CTOR_NAME;
+                        
+                        codeWriter.writeToFragment(NewStringf("Ptr<%s> %s;\n", clsName.c_str(), WRAPPED_PTR_VAR));
+                        ExceptionCodeWriter writer(codeWriter, mbMethodName);
+                        codeWriter.writeToFragment(m_ctorSetupCode[clsName]);
+                        codeWriter.writeToFragment("\n");
+                    }
+                    codeWriter.writeToFragment(NewStringf("return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Could not resolve suitable constructor for %s based on given arguments\")));\n", clsName.c_str()));
+                }
+                writeToFile(code);
+            }
+            else
+            {
+                writeToFile(NewStringf("\treturn v8::ThrowException(v8::Exception::Error(v8::String::New(\"Class %s has no public constructors\")));\n", clsName.c_str()));
+            }
+            writeToFile("}\n\n");
+        }
+
+        writeToFile("//=====================================\n");
         writeToFile("//Proxy class setup methods\n");
         writeToFile("//=====================================\n");
         for (std::vector<std::string>::iterator it = m_classSetupCalls.begin(); it != m_classSetupCalls.end(); it++)
@@ -286,16 +373,24 @@
                 Indenter ind(m_indentationLevels);
                 {
                     ExceptionCodeWriter writer(cls, proxyFuncName);
-                    std::string funcCall;
+                    FunctionCallSetup setup;
                     std::string cleanup;
-                    getFunctionArgumentAssignmentCode(parms, cls, funcCall);
-                    cls.writeToFragment(NewStringf("%s(%s);\n", name, funcCall.c_str()));
+                    getFunctionArgumentAssignmentCode(parms, proxyFuncName, cls, &setup);
+                    cls.writeToFragment(NewStringf("%s(%s);\n", name, setup.getFunctionArgumentString()));
                 }
                 cls.writeToFragment("return v8::Undefined();\n");
             }
             cls.writeToFragment("}\n");
 
             m_classMethodDecls.push_back(globalFuncFragment);
+            std::string initExportCode;
+            initExportCode += EXPORTS_VAR;
+            initExportCode += "->Set(v8::String::NewSymbol(\"";
+            initExportCode += Char(name);
+            initExportCode += "\"), v8::FunctionTemplate::New(";
+            initExportCode += proxyFuncName;
+            initExportCode += ")->GetFunction());\n";
+            m_classExportCalls.push_back(initExportCode);
         }
         else if (Strstr(name, ctorPrefix))
         {
@@ -307,6 +402,7 @@
             std::string mbName = Char(name);
             //Strip the new_ prefix
             std::string ctorName = mbName.substr(4);
+            
             std::string proxyClsName;
             setProxyClassName(ctorName.c_str(), proxyClsName);
 
@@ -314,11 +410,42 @@
             {
                 Indenter ind(m_indentationLevels);
 
-                std::string funcCall;
-                getFunctionArgumentAssignmentCode(parms, ctor, funcCall, false);
+                FunctionCallSetup setup;
+                std::string mbOvName;
+                mbOvName += Char(ovName);
+                getFunctionArgumentAssignmentCode(parms, mbOvName, ctor, &setup, false);
                 ctor.writeToFragment(NewStringf("Ptr<%s> retVal;\n", ctorName.c_str()));
-                ctor.writeToFragment(NewStringf("retVal = new %s(%s);\n", ctorName.c_str(), funcCall.c_str()));
+                ctor.writeToFragment(NewStringf("retVal = new %s(%s);\n", ctorName.c_str(), setup.getFunctionArgumentString()));
                 ctor.writeToFragment("return retVal.Detach();\n");
+
+                std::string ctorFwdCode;
+                const std::vector<ArgInfo>& args = setup.getArgs();
+                //TODO: Naive implementation (arg count). Two constructor overloads with the same number of args will
+                //break this.
+                FragmentWriter ctorCheck(m_indentationLevels, ctorFwdCode);
+                ctorCheck.writeToFragment(NewStringf("//Checking args suitability for method: %s\n", ovName));
+                ctorCheck.writeToFragment(NewStringf("if (%s.Length() == %d)\n", ARGS_VAR, args.size()));
+                ctorCheck.writeToFragment("{\n");
+                {
+                    Indenter ind2(m_indentationLevels);
+                    ctorCheck.writeToFragment("//Forward ctor call\n");
+                    ctorCheck.writeToFragment(NewStringf("%s = %s(args);\n", WRAPPED_PTR_VAR, ovName));
+                    ctorCheck.writeToFragment(NewStringf("%s* proxy = new %s(%s);\n", proxyClsName.c_str(), proxyClsName.c_str(), WRAPPED_PTR_VAR));
+                    ctorCheck.writeToFragment(NewStringf("proxy->Wrap(%s.This());\n", ARGS_VAR));
+                    ctorCheck.writeToFragment(NewStringf("return %s.This();\n", ARGS_VAR));
+                }
+                ctorCheck.writeToFragment("}\n");
+
+                if (m_ctorSetupCode.find(ctorName) == m_ctorSetupCode.end())
+                {
+                    m_ctorSetupCode[ctorName] = ctorFwdCode;
+                }
+                else
+                {
+                    std::string& code = m_ctorSetupCode[ctorName];
+                    code += "\n";
+                    code += ctorFwdCode;
+                }
             }
             ctor.writeToFragment("}\n");
             m_classMethodDecls.push_back(ctorFragment);
@@ -332,8 +459,10 @@
             {
                 Indenter ind(m_indentationLevels);
 
-                std::string funcCall;
-                getFunctionArgumentAssignmentCode(parms, dtor, funcCall);
+                FunctionCallSetup setup;
+                std::string mbName;
+                mbName += Char(name);
+                getFunctionArgumentAssignmentCode(parms, mbName, dtor, &setup);
                 
                 //TODO: Should check if node/v8 allows this. This is theoretical atm
                 //
@@ -412,6 +541,15 @@
         m_currentExportFragment = std::string();
         m_currentClassName = NewString(Getattr(n,"sym:name"));
 
+        String* baseClassName = NULL;
+        List *baselist = Getattr(n,"bases");
+        if (baselist) {
+            Iterator base = First(baselist);
+            baseClassName = NewString(Getattr(base.item,"name"));
+        } else {
+            baseClassName = NewString("");
+        }
+
         FragmentWriter cls(m_indentationLevels, m_currentFragment);
         FragmentWriter clsSetup(m_indentationLevels, m_currentClassSetupFragment);
 
@@ -420,8 +558,11 @@
         //Error object.
         if (!Strstr(m_currentClassName, "Exception"))
         {
-            cls.writeToFragment(NewStringf("//Node.js wrapper for class: %s\n", m_currentClassName));
+            cls.writeToFragment(NewStringf("//Node.js wrapper for class: %s (inherits from %s)\n", m_currentClassName, baseClassName));
 
+            std::string clsName;
+            clsName += Char(m_currentClassName);
+
             std::string proxyClsName;
             setProxyClassName(m_currentClassName, proxyClsName);
             
@@ -452,22 +593,12 @@
             
             bool isMgObject = isCurrentClassMgObject();
 
-            if (isMgObject)
-            {
-                Indenter ind(m_indentationLevels);
-                std::string ptrDecl;
-                ptrDecl += Char(m_currentClassName);
-                ptrDecl += "* m_ptr;\n";
-                cls.writeToFragment(ptrDecl);
-            }
-            else
-            {
-                Indenter ind(m_indentationLevels);
-                std::string ptrDecl = "Ptr<";
-                ptrDecl += Char(m_currentClassName);
-                ptrDecl += "> m_ptr;\n";
-                cls.writeToFragment(ptrDecl);
-            }
+            std::string ptrDecl;
+            ptrDecl += "\t";
+            ptrDecl += Char(m_currentClassName);
+            ptrDecl += "* m_ptr;\n";
+            cls.writeToFragment(ptrDecl);
+
             cls.writeToFragment("public:\n");
             std::string ctorDecl;
             ctorDecl += proxyClsName;
@@ -497,13 +628,18 @@
                 if (isMgObject) //Anything inheriting from MgObject will be MgDisposable 
                     cls.writeToFragment("\t((MgDisposable*)m_ptr)->Release();\n");
                 else
-                    cls.writeToFragment("\tm_ptr = NULL;\n");
+                    cls.writeToFragment("\tSAFE_RELEASE(m_ptr);\n");
+
+                if (m_bInsertDebuggingCode)
+                    cls.writeToFragment(NewStringf("\tprintf(\"Released instance of %s\\n\");\n", clsName.c_str()));
                 cls.writeToFragment("}\n");
             }
 
             //Stubs to be implemented further down
             {
                 Indenter ind(m_indentationLevels);
+                cls.writeToFragment("static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);\n");
+                cls.writeToFragment(NewStringf("static v8::Handle<v8::Value> CreateJsProxy(%s* ptr);\n", clsName.c_str())); 
                 cls.writeToFragment("static void Export(v8::Handle<v8::Object> exports);\n");
                 cls.writeToFragment("static void ApplyInheritanceChain(v8::Handle<v8::Object> exports);\n");
             }
@@ -517,25 +653,73 @@
             //Internal pointer accessor
             {
                 Indenter ind(m_indentationLevels);
+
+                cls.writeToFragment("//Sets the internal pointer. Pointer will be AddRef()'d. Existing pointer (if any) will be Release()'d\n");
                 if (isMgObject)
+                    cls.writeToFragment(NewStringf("void SetInternalPointer(%s* ptr) { if (m_ptr) { ((MgDisposable*)m_ptr)->Release(); }; m_ptr = SAFE_ADDREF((MgDisposable*)m_ptr); }\n", m_currentClassName));
+                else
+                    cls.writeToFragment(NewStringf("void SetInternalPointer(%s* ptr) { SAFE_RELEASE(m_ptr); m_ptr = SAFE_ADDREF(m_ptr); }\n", m_currentClassName));
+
+                cls.writeToFragment("//Returns the internal pointer. Pointer is already AddRef()'d and requires release by the caller when done (automatically if assigned to a Ptr<>)\n");
+                if (isMgObject)
                     cls.writeToFragment(NewStringf("%s* GetInternalPointer() { return SAFE_ADDREF((MgDisposable*)m_ptr); }\n", m_currentClassName));
                 else
-                    cls.writeToFragment(NewStringf("%s* GetInternalPointer() { return SAFE_ADDREF(m_ptr.p); }\n", m_currentClassName));
+                    cls.writeToFragment(NewStringf("%s* GetInternalPointer() { return SAFE_ADDREF(m_ptr); }\n", m_currentClassName));
             }
+            
+            //Function template to apply inheritance
+            {
+                Indenter ind(m_indentationLevels);
+                cls.writeToFragment(NewStringf("static v8::Persistent<v8::FunctionTemplate> constructor_tpl;\n"));
+            }
 
             cls.writeToFragment("private:\n");
             //Proxy Constructor
             {
                 Indenter ind(m_indentationLevels);
-                cls.writeToFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s) {\n", CLASS_PROXY_CTOR_NAME, ARGS_VAR));
+                cls.writeToFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s);\n", CLASS_PROXY_CTOR_NAME, ARGS_VAR));
+                cls.writeToFragment(NewStringf("static v8::Persistent<v8::Function> constructor;\n"));
+            }
+
+            //node/v8 public factory
+            {
+                Indenter ind(m_indentationLevels);
+                clsSetup.writeToFragment(NewStringf("v8::Handle<v8::Value> %s::NewInstance(const v8::Arguments& %s)\n", proxyClsName.c_str(), ARGS_VAR));
+                clsSetup.writeToFragment("{\n");
                 {
                     Indenter ind2(m_indentationLevels);
-                    cls.writeToFragment("//TODO: Parse arguments and determine which actual native constructor to invoke\n");
-                    cls.writeToFragment("return v8::Undefined();\n");
+                    clsSetup.writeToFragment("v8::HandleScope scope;\n");
+                    clsSetup.writeToFragment(NewStringf("const unsigned argc = %s.Length();\n", ARGS_VAR));
+                    clsSetup.writeToFragment("v8::Handle<v8::Value>* argv = new v8::Handle<v8::Value>[argc];\n");
+                    clsSetup.writeToFragment("for (unsigned i = 0; i < argc; i++) {\n");
+                    {
+                        Indenter ind3(m_indentationLevels);
+                        clsSetup.writeToFragment("argv[i] = args[i];\n");
+                    }
+                    clsSetup.writeToFragment("}\n");
+                    clsSetup.writeToFragment("v8::Local<v8::Object> instance = constructor->NewInstance(argc, argv);\n");
+                    clsSetup.writeToFragment("delete [] argv;\n");
+                    clsSetup.writeToFragment("return scope.Close(instance);\n");
                 }
-                cls.writeToFragment("}\n");
+                clsSetup.writeToFragment("}\n");
             }
 
+            //node/v8 wrap mg pointer factory method
+            {
+                Indenter ind(m_indentationLevels);
+                clsSetup.writeToFragment(NewStringf("v8::Handle<v8::Value> %s::CreateJsProxy(%s* ptr)\n", proxyClsName.c_str(), m_currentClassName));
+                clsSetup.writeToFragment("{\n");
+                {
+                    Indenter ind2(m_indentationLevels);
+                    clsSetup.writeToFragment("v8::HandleScope scope;\n");
+                    clsSetup.writeToFragment("v8::Local<v8::Object> instance = constructor->NewInstance();\n");
+                    clsSetup.writeToFragment(NewStringf("%s* proxyVal = new %s(ptr);\n", proxyClsName.c_str(), proxyClsName.c_str()));
+                    clsSetup.writeToFragment("proxyVal->Wrap(instance);\n");
+                    clsSetup.writeToFragment("return scope.Close(instance);\n");
+                }
+                clsSetup.writeToFragment("}\n");
+            }
+
             //node/v8 export function
             {
                 Indenter ind(m_indentationLevels);
@@ -544,11 +728,14 @@
                 {
                     Indenter ind2(m_indentationLevels);
                     clsSetup.writeToFragment(NewStringf("v8::Local<v8::FunctionTemplate> %s = v8::FunctionTemplate::New(%s::%s);\n", CLASS_EXPORT_VAR, proxyClsName.c_str(), CLASS_PROXY_CTOR_NAME));
+                    clsSetup.writeToFragment(NewStringf("constructor_tpl = v8::Persistent<v8::FunctionTemplate>::New(%s);\n", CLASS_EXPORT_VAR));
                     clsSetup.writeToFragment(NewStringf("%s->SetClassName(v8::String::NewSymbol(\"%s\"));\n", CLASS_EXPORT_VAR, m_currentClassName));
                     clsSetup.writeToFragment("//For the internal pointer\n");
                     clsSetup.writeToFragment(NewStringf("%s->InstanceTemplate()->SetInternalFieldCount(1);\n", CLASS_EXPORT_VAR));
 
-                    std::string ctorReg = "v8::Persistent<v8::Function> constructor = v8::Persistent<v8::Function>::New(";
+                    std::string ctorReg;
+                    ctorReg += proxyClsName;
+                    ctorReg += "::constructor = v8::Persistent<v8::Function>::New(";
                     ctorReg += CLASS_EXPORT_VAR;
                     ctorReg += "->GetFunction());\n";
 
@@ -556,7 +743,9 @@
                     ctorReg2 += EXPORTS_VAR;
                     ctorReg2 += "->Set(v8::String::NewSymbol(\"";
                     ctorReg2 += Char(m_currentClassName);
-                    ctorReg2 += "\"), constructor);\n";
+                    ctorReg2 += "\"), ";
+                    ctorReg2 += proxyClsName;
+                    ctorReg2 += "::constructor);\n";
 
                     m_classMemberExportCalls.push_back(ctorReg);
                     m_classMemberExportCalls.push_back(ctorReg2);
@@ -570,29 +759,39 @@
                 clsSetup.writeToFragment("}\n");
             }
 
-            //node/v8 inheritance hook
+            //node/v8 export function
             {
                 Indenter ind(m_indentationLevels);
                 clsSetup.writeToFragment(NewStringf("void %s::ApplyInheritanceChain(v8::Handle<v8::Object> %s)\n", proxyClsName.c_str(), EXPORTS_VAR));
                 clsSetup.writeToFragment("{\n");
                 {
                     Indenter ind2(m_indentationLevels);
-                    clsSetup.writeToFragment("//TODO: Apply prototype inheritance chain\n");
+                    
+                    if (Strcmp("", baseClassName) == 0)
+                    {
+                        clsSetup.writeToFragment("//This class has no base class. Nothing to do here\n");
+                    }
+                    else
+                    {
+                        std::string mbBaseClass;
+                        setProxyClassName(baseClassName, mbBaseClass);
+                        clsSetup.writeToFragment(NewStringf("%s::constructor_tpl->Inherit(%s::constructor_tpl);\n", proxyClsName.c_str(), mbBaseClass.c_str()));
+                    }
                 }
                 clsSetup.writeToFragment("}\n");
             }
-
             cls.writeToFragment("};");
 
             Delete(m_currentClassName);
             m_currentClassName = NULL;
 
-            m_classDecls.push_back(m_currentFragment);
+            m_classDecls[clsName] = m_currentFragment;
             m_classExportCalls.push_back(m_currentExportFragment);
             m_classInheritCalls.push_back(m_currentInheritFragment);
             m_classSetupCalls.push_back(m_currentClassSetupFragment);
 
         }
+        Delete(baseClassName);
         return SWIG_OK;
     }
 
@@ -673,11 +872,13 @@
                     Indenter ind2(m_indentationLevels);
                     if (parms)
                     {
-                        std::string funcCallArgsStr;
-                        getFunctionArgumentAssignmentCode(parms, meth, funcCallArgsStr);
+                        FunctionCallSetup setup;
+                        std::string mbQName;
+                        mbQName += Char(overloaded_name_qualified);
+                        getFunctionArgumentAssignmentCode(parms, mbQName, meth, &setup);
                         wrappedPtrCall += Char(name);
                         wrappedPtrCall += "(";
-                        wrappedPtrCall += funcCallArgsStr;
+                        wrappedPtrCall += setup.getFunctionArgumentString();
                         wrappedPtrCall += ");\n";
                     }
                     else
@@ -712,7 +913,9 @@
             {
                 if (isMgPointer) //Stub
                 {
-                    meth.writeToFragment("return v8::ThrowException(v8::Exception::Error(v8::String::New(\"TODO: Case not handled yet: Returning objects\")));\n");
+                    meth.writeToFragment("v8::HandleScope scope;\n");
+                    meth.writeToFragment(NewStringf("v8::Handle<v8::Value> instance = Proxy%s::CreateJsProxy(%s);\n", retTypeUnprefixed, FUNC_RET_VAR));
+                    meth.writeToFragment("return scope.Close(instance);\n");
                 }
                 else
                 {
@@ -751,159 +954,252 @@
         return SWIG_OK;
     }
 
-    void getFunctionArgumentAssignmentCode(ParmList* parms, FragmentWriter& frag, std::string& nativeMethodArgsString, bool bThrowV8Exceptions = true)
+    void writeArgumentCheckFragment(FragmentWriter& frag, std::string& callingMethodName, String* name, SwigType* type, int argNo, bool isArgMgPointer, bool bThrowV8Exceptions = true)
     {
-        int argNo = 0;
-        Parm *p;
-        for (p = parms; p; p = nextSibling(p)) 
+        if (isArgMgPointer)
         {
-            SwigType *type  = Getattr(p,"type");
-            SwigType *typeUnprefixed = SwigType_base(type);
-            String   *name  = Getattr(p,"name");
-            //String   *value = Getattr(p,"value");
-
-            bool isArgMgPointer = !SwigType_issimple(type);
-            
-            frag.writeToFragment("//Argument\n");
-            frag.writeToFragment(NewStringf("// Name - %s\n", name));
-            frag.writeToFragment(NewStringf("// Type - %s\n", type));
-            //frag.writeToFragment(NewStringf("// Value - %s\n", value));
-            
-            //Before we extract values from v8::Arguments, do basic checks on the parameters
-            if (isArgMgPointer)
+            if (bThrowV8Exceptions)
             {
-                if (bThrowV8Exceptions)
-                    frag.writeToFragment(NewStringf("if (!%s[%d]->IsObject()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not an object\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
-                else
-                    frag.writeToFragment(NewStringf("if (!%s[%d]->IsObject()) throw new MgInvalidArgumentException(L\"\", __LINE__, __WFILE__, NULL, L\"\", NULL);\n", ARGS_VAR, argNo));
+                frag.writeToFragment(NewStringf("if (!%s[%d]->IsObject()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not an object\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
             }
             else
             {
-                //Write definition check
-                if (bThrowV8Exceptions)
-                    frag.writeToFragment(NewStringf("if (%s[%d]->IsUndefined()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is undefined\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
-                else
-                    frag.writeToFragment(NewStringf("if (!%s[%d]->IsUndefined()) throw new MgInvalidArgumentException(L\"\", __LINE__, __WFILE__, NULL, L\"\", NULL);\n", ARGS_VAR, argNo));
-                //Then type check
-                if (Strcmp(type, "BYTE") == 0 ||
-                    Strcmp(type, "INT8") == 0 ||
-                    Strcmp(type, "INT16") == 0 ||
-                    Strcmp(type, "INT32") == 0 ||
-                    Strcmp(type, "STATUS") == 0 ||                    //Huh?
-                    Strcmp(type, "MgSiteInfo::MgSiteStatus") == 0 ||  //Huh? I thought MapGuide API doesn't expose enums!
-                    Strcmp(type, "MgSiteInfo::MgPortType") == 0 ||    //Huh? I thought MapGuide API doesn't expose enums!
-                    Strcmp(type, "int") == 0 ||
-                    Strcmp(type, "UINT32") == 0 ||
-                    Strcmp(type, "INT64") == 0 ||
-                    Strcmp(type, "long") == 0 ||
-                    Strcmp(type, "long long") == 0)
+                frag.writeToFragment(NewStringf("if (!%s[%d]->IsObject())\n", ARGS_VAR, argNo));
+                frag.writeToFragment("{\n");
                 {
-                    if (bThrowV8Exceptions)
-                        frag.writeToFragment(NewStringf("if (!%s[%d]->IsInt32()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a number\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
-                    else
-                        frag.writeToFragment(NewStringf("if (!%s[%d]->IsInt32()) throw new MgInvalidArgumentException(L\"\", __LINE__, __WFILE__, NULL, L\"\", NULL);\n", ARGS_VAR, argNo));
+                    Indenter ind(m_indentationLevels);
+                    frag.writeToFragment("MgStringCollection exArgs;\n");
+                    frag.writeToFragment(NewStringf("exArgs.Add(L\"Argument %d (%s: %s) is not an object\");\n", (argNo + 1), name, type));
+                    frag.writeToFragment(NewStringf("throw new MgInvalidArgumentException(L\"%s\", __LINE__, __WFILE__, NULL, L\"MgFormatInnerExceptionMessage\", &exArgs);\n", callingMethodName.c_str()));
                 }
-                else if (Strcmp(type, "double") == 0 ||
-                         Strcmp(type, "float") == 0)
+                frag.writeToFragment("}\n");
+            }
+        }
+        else
+        {
+            //Write definition check
+            if (bThrowV8Exceptions)
+            {
+                frag.writeToFragment(NewStringf("if (%s[%d]->IsUndefined()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is undefined\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
+            }
+            else
+            {
+                frag.writeToFragment(NewStringf("if (%s[%d]->IsUndefined())\n", ARGS_VAR, argNo));
+                frag.writeToFragment("{\n");
                 {
-                    if (bThrowV8Exceptions)
-                        frag.writeToFragment(NewStringf("if (!%s[%d]->IsNumber()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a number\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
-                    else
-                        frag.writeToFragment(NewStringf("if (!%s[%d]->IsNumber()) throw new MgInvalidArgumentException(L\"\", __LINE__, __WFILE__, NULL, L\"\", NULL);\n", ARGS_VAR, argNo));
+                    Indenter ind(m_indentationLevels);
+                    frag.writeToFragment("MgStringCollection exArgs;\n");
+                    frag.writeToFragment(NewStringf("exArgs.Add(L\"Argument %d (%s: %s) is undefined\");\n", (argNo + 1), name, type));
+                    frag.writeToFragment(NewStringf("throw new MgInvalidArgumentException(L\"%s\", __LINE__, __WFILE__, NULL, L\"MgFormatInnerExceptionMessage\", &exArgs);\n", callingMethodName.c_str()));
                 }
-                else if (Strcmp(type, "STRINGPARAM") == 0)
+                frag.writeToFragment("}\n");
+            }
+            //Then type check
+            if (Strcmp(type, "BYTE") == 0 ||
+                Strcmp(type, "INT8") == 0 ||
+                Strcmp(type, "INT16") == 0 ||
+                Strcmp(type, "INT32") == 0 ||
+                Strcmp(type, "STATUS") == 0 ||                    //Huh?
+                Strcmp(type, "MgSiteInfo::MgSiteStatus") == 0 ||  //Huh? I thought MapGuide API doesn't expose enums!
+                Strcmp(type, "MgSiteInfo::MgPortType") == 0 ||    //Huh? I thought MapGuide API doesn't expose enums!
+                Strcmp(type, "int") == 0 ||
+                Strcmp(type, "UINT32") == 0 ||
+                Strcmp(type, "INT64") == 0 ||
+                Strcmp(type, "long") == 0 ||
+                Strcmp(type, "long long") == 0)
+            {
+                if (bThrowV8Exceptions)
                 {
-                    if (bThrowV8Exceptions)
-                        frag.writeToFragment(NewStringf("if (!%s[%d]->IsString()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a string\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
-                    else
-                        frag.writeToFragment(NewStringf("if (!%s[%d]->IsString()) throw new MgInvalidArgumentException(L\"\", __LINE__, __WFILE__, NULL, L\"\", NULL);\n", ARGS_VAR, argNo));
+                    frag.writeToFragment(NewStringf("if (!%s[%d]->IsInt32()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a number\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
                 }
-                else if (Strcmp(type, "bool") == 0)
+                else
                 {
-                    if (bThrowV8Exceptions)
-                        frag.writeToFragment(NewStringf("if (!%s[%d]->IsBoolean()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a boolean\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
-                    else
-                        frag.writeToFragment(NewStringf("if (!%s[%d]->IsBoolean()) throw new MgInvalidArgumentException(L\"\", __LINE__, __WFILE__, NULL, L\"\", NULL);\n", ARGS_VAR, argNo));
+                    frag.writeToFragment(NewStringf("if (!%s[%d]->IsInt32())\n", ARGS_VAR, argNo));
+                    frag.writeToFragment("{\n");
+                    {
+                        Indenter ind(m_indentationLevels);
+                        frag.writeToFragment("MgStringCollection exArgs;\n");
+                        frag.writeToFragment(NewStringf("exArgs.Add(L\"Argument %d (%s: %s) is not a number\");\n", (argNo + 1), name, type));
+                        frag.writeToFragment(NewStringf("throw new MgInvalidArgumentException(L\"%s\", __LINE__, __WFILE__, NULL, L\"MgFormatInnerExceptionMessage\", &exArgs);\n", callingMethodName.c_str()));
+                    }
+                    frag.writeToFragment("}\n");
                 }
             }
-
-            bool bIsMgObject = (Strcmp(typeUnprefixed, "MgObject") == 0);
-
-            if (isArgMgPointer)
+            else if (Strcmp(type, "double") == 0 ||
+                     Strcmp(type, "float") == 0)
             {
-                std::string proxyClsName;
-                setProxyClassName(typeUnprefixed, proxyClsName);
-                if (bIsMgObject)
+                if (bThrowV8Exceptions)
                 {
-                    frag.writeToFragment(NewStringf("Ptr<MgDisposable> arg%d = NULL;\n", argNo));
+                    frag.writeToFragment(NewStringf("if (!%s[%d]->IsNumber()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a number\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
                 }
                 else
                 {
-                    frag.writeToFragment(NewStringf("Ptr<%s> arg%d = NULL;\n", typeUnprefixed, argNo));
+                    frag.writeToFragment(NewStringf("if (!%s[%d]->IsNumber())\n", ARGS_VAR, argNo));
+                    frag.writeToFragment("{\n");
+                    {
+                        Indenter ind(m_indentationLevels);
+                        frag.writeToFragment("MgStringCollection exArgs;\n");
+                        frag.writeToFragment(NewStringf("exArgs.Add(L\"Argument %d (%s: %s) is not a number\");\n", (argNo + 1), name, type));
+                        frag.writeToFragment(NewStringf("throw new MgInvalidArgumentException(L\"%s\", __LINE__, __WFILE__, NULL, L\"MgFormatInnerExceptionMessage\", &exArgs);\n", callingMethodName.c_str()));
+                    }
+                    frag.writeToFragment("}\n");
                 }
-                frag.writeToFragment(NewStringf("%s* proxyArg%d = NULL;\n", proxyClsName.c_str(), argNo));
-                frag.writeToFragment(NewStringf("if (!%s[%d]->IsUndefined())\n", ARGS_VAR, argNo));
-                frag.writeToFragment("{\n");
-                {
-                    Indenter ind(m_indentationLevels);
-                    frag.writeToFragment(NewStringf("proxyArg%d = node::ObjectWrap::Unwrap<%s>(%s[%d]->ToObject());\n", argNo, proxyClsName.c_str(), ARGS_VAR, argNo));
-                    if (bIsMgObject)
-                        frag.writeToFragment(NewStringf("arg%d = (MgDisposable*)proxyArg%d->GetInternalPointer();\n", argNo, argNo));
-                    else
-                        frag.writeToFragment(NewStringf("arg%d = proxyArg%d->GetInternalPointer();\n", argNo, argNo));
-                }
-                frag.writeToFragment("}\n");
             }
-            else
+            else if (Strcmp(type, "STRINGPARAM") == 0)
             {
-                //Then type check
-                if (Strcmp(type, "BYTE") == 0 ||
-                    Strcmp(type, "INT8") == 0 ||
-                    Strcmp(type, "INT16") == 0 ||
-                    Strcmp(type, "INT32") == 0 ||
-                    Strcmp(type, "STATUS") == 0 ||                    //Huh?
-                    Strcmp(type, "MgSiteInfo::MgSiteStatus") == 0 ||  //Huh? I thought MapGuide API doesn't expose enums!
-                    Strcmp(type, "MgSiteInfo::MgPortType") == 0 ||    //Huh? I thought MapGuide API doesn't expose enums!
-                    Strcmp(type, "int") == 0 ||
-                    Strcmp(type, "UINT32") == 0 ||
-                    Strcmp(type, "INT64") == 0 ||
-                    Strcmp(type, "long") == 0 ||
-                    Strcmp(type, "long long") == 0)
+                if (bThrowV8Exceptions)
                 {
-                    frag.writeToFragment(NewStringf("%s arg%d = (%s)%s[%d]->IntegerValue();\n", type, argNo, type, ARGS_VAR, argNo));
+                    frag.writeToFragment(NewStringf("if (!%s[%d]->IsString()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a string\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
                 }
-                else if (Strcmp(type, "double") == 0 ||
-                         Strcmp(type, "float") == 0)
+                else
                 {
-                    frag.writeToFragment(NewStringf("%s arg%d = (%s)%s[%d]->NumberValue();\n", type, argNo, type, ARGS_VAR, argNo));
+                    frag.writeToFragment(NewStringf("if (!%s[%d]->IsString())\n", ARGS_VAR, argNo));
+                    frag.writeToFragment("{\n");
+                    {
+                        Indenter ind(m_indentationLevels);
+                        frag.writeToFragment("MgStringCollection exArgs;\n");
+                        frag.writeToFragment(NewStringf("exArgs.Add(L\"Argument %d (%s: %s) is not a string\");\n", (argNo + 1), name, type));
+                        frag.writeToFragment(NewStringf("throw new MgInvalidArgumentException(L\"%s\", __LINE__, __WFILE__, NULL, L\"MgFormatInnerExceptionMessage\", &exArgs);\n", callingMethodName.c_str()));
+                    }
+                    frag.writeToFragment("}\n");
                 }
-                else if (Strcmp(type, "BYTE_ARRAY_OUT") == 0)
+            }
+            else if (Strcmp(type, "bool") == 0)
+            {
+                if (bThrowV8Exceptions)
                 {
-                    //frag.writeToFragment(NewStringf("std::string str%d = args[%d]->ToString();\n", argNo, argNo));
-                    //frag.writeToFragment(NewStringf("Ptr<MgByte> bytes%d = new MgByte((BYTE_ARRAY_IN)str%d);\n", argNo, argNo));
-                    //frag.writeToFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(args[%d]->ToString());\n", argNo, argNo));
-                    frag.writeToFragment("//TODO: Case not handled: BYTE_ARRAY_OUT\n");
-                    frag.writeToFragment(NewStringf("BYTE_ARRAY_OUT arg%d = NULL;\n", argNo));
+                    frag.writeToFragment(NewStringf("if (!%s[%d]->IsBoolean()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a boolean\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
                 }
-                else if (Strcmp(type, "BYTE_ARRAY_IN") == 0)
+                else
                 {
-                    //frag.writeToFragment(NewStringf("std::string str%d = args[%d]->ToString();\n", argNo, argNo));
-                    //frag.writeToFragment(NewStringf("Ptr<MgByte> bytes%d = new MgByte((BYTE_ARRAY_IN)str%d);\n", argNo, argNo));
-                    //frag.writeToFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(args[%d]->ToString());\n", argNo, argNo));
-                    frag.writeToFragment("//TODO: Case not handled: BYTE_ARRAY_IN\n");
-                    frag.writeToFragment(NewStringf("BYTE_ARRAY_IN arg%d = NULL;\n", argNo));
+                    frag.writeToFragment(NewStringf("if (!%s[%d]->IsBoolean())\n", ARGS_VAR, argNo));
+                    frag.writeToFragment("{\n");
+                    {
+                        Indenter ind(m_indentationLevels);
+                        frag.writeToFragment("MgStringCollection exArgs;\n");
+                        frag.writeToFragment(NewStringf("exArgs.Add(L\"Argument %d (%s: %s) is not a boolean\");\n", (argNo + 1), name, type));
+                        frag.writeToFragment(NewStringf("throw new MgInvalidArgumentException(L\"%s\", __LINE__, __WFILE__, NULL, L\"MgFormatInnerExceptionMessage\", &exArgs);\n", callingMethodName.c_str()));
+                    }
+                    frag.writeToFragment("}\n");
                 }
-                else if (Strcmp(type, "STRINGPARAM") == 0)
-                {
-                    frag.writeToFragment(NewStringf("v8::String::Utf8Value mbArg%d(%s[%d]->ToString());\n", argNo, ARGS_VAR, argNo));
-                    frag.writeToFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(std::string(*mbArg%d));\n", argNo, argNo));
-                }
-                else if (Strcmp(type, "bool") == 0)
-                {
-                    frag.writeToFragment(NewStringf("%s arg%d = %s[%d]->BooleanValue();\n", type, argNo, ARGS_VAR, argNo));
-                }
             }
+        }
+    }
+
+    void writeArgumentAssignmentCode(FragmentWriter& frag, SwigType* type, SwigType* typeUnprefixed, String* name, int argNo, bool isArgMgPointer, bool bIsMgObject)
+    {
+        if (isArgMgPointer)
+        {
+            std::string proxyClsName;
+            setProxyClassName(typeUnprefixed, proxyClsName);
+            if (bIsMgObject)
+            {
+                frag.writeToFragment(NewStringf("Ptr<MgDisposable> arg%d = NULL;\n", argNo));
+            }
+            else
+            {
+                frag.writeToFragment(NewStringf("Ptr<%s> arg%d = NULL;\n", typeUnprefixed, argNo));
+            }
+            frag.writeToFragment(NewStringf("%s* proxyArg%d = NULL;\n", proxyClsName.c_str(), argNo));
+            frag.writeToFragment(NewStringf("if (!%s[%d]->IsUndefined())\n", ARGS_VAR, argNo));
+            frag.writeToFragment("{\n");
+            {
+                Indenter ind(m_indentationLevels);
+                frag.writeToFragment(NewStringf("proxyArg%d = node::ObjectWrap::Unwrap<%s>(%s[%d]->ToObject());\n", argNo, proxyClsName.c_str(), ARGS_VAR, argNo));
+                if (bIsMgObject)
+                    frag.writeToFragment(NewStringf("arg%d = (MgDisposable*)proxyArg%d->GetInternalPointer();\n", argNo, argNo));
+                else
+                    frag.writeToFragment(NewStringf("arg%d = proxyArg%d->GetInternalPointer();\n", argNo, argNo));
+            }
+            frag.writeToFragment("}\n");
+        }
+        else
+        {
+            //Then type check
+            if (Strcmp(type, "BYTE") == 0 ||
+                Strcmp(type, "INT8") == 0 ||
+                Strcmp(type, "INT16") == 0 ||
+                Strcmp(type, "INT32") == 0 ||
+                Strcmp(type, "STATUS") == 0 ||                    //Huh?
+                Strcmp(type, "MgSiteInfo::MgSiteStatus") == 0 ||  //Huh? I thought MapGuide API doesn't expose enums!
+                Strcmp(type, "MgSiteInfo::MgPortType") == 0 ||    //Huh? I thought MapGuide API doesn't expose enums!
+                Strcmp(type, "int") == 0 ||
+                Strcmp(type, "UINT32") == 0 ||
+                Strcmp(type, "INT64") == 0 ||
+                Strcmp(type, "long") == 0 ||
+                Strcmp(type, "long long") == 0)
+            {
+                frag.writeToFragment(NewStringf("%s arg%d = (%s)%s[%d]->IntegerValue();\n", type, argNo, type, ARGS_VAR, argNo));
+            }
+            else if (Strcmp(type, "double") == 0 ||
+                     Strcmp(type, "float") == 0)
+            {
+                frag.writeToFragment(NewStringf("%s arg%d = (%s)%s[%d]->NumberValue();\n", type, argNo, type, ARGS_VAR, argNo));
+            }
+            else if (Strcmp(type, "BYTE_ARRAY_OUT") == 0)
+            {
+                //frag.writeToFragment(NewStringf("std::string str%d = args[%d]->ToString();\n", argNo, argNo));
+                //frag.writeToFragment(NewStringf("Ptr<MgByte> bytes%d = new MgByte((BYTE_ARRAY_IN)str%d);\n", argNo, argNo));
+                //frag.writeToFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(args[%d]->ToString());\n", argNo, argNo));
+                frag.writeToFragment("//TODO: Case not handled: BYTE_ARRAY_OUT\n");
+                frag.writeToFragment(NewStringf("BYTE_ARRAY_OUT arg%d = NULL;\n", argNo));
+            }
+            else if (Strcmp(type, "BYTE_ARRAY_IN") == 0)
+            {
+                //frag.writeToFragment(NewStringf("std::string str%d = args[%d]->ToString();\n", argNo, argNo));
+                //frag.writeToFragment(NewStringf("Ptr<MgByte> bytes%d = new MgByte((BYTE_ARRAY_IN)str%d);\n", argNo, argNo));
+                //frag.writeToFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(args[%d]->ToString());\n", argNo, argNo));
+                frag.writeToFragment("//TODO: Case not handled: BYTE_ARRAY_IN\n");
+                frag.writeToFragment(NewStringf("BYTE_ARRAY_IN arg%d = NULL;\n", argNo));
+            }
+            else if (Strcmp(type, "STRINGPARAM") == 0)
+            {
+                frag.writeToFragment(NewStringf("v8::String::Utf8Value mbArg%d(%s[%d]->ToString());\n", argNo, ARGS_VAR, argNo));
+                frag.writeToFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(std::string(*mbArg%d));\n", argNo, argNo));
+            }
+            else if (Strcmp(type, "bool") == 0)
+            {
+                frag.writeToFragment(NewStringf("%s arg%d = %s[%d]->BooleanValue();\n", type, argNo, ARGS_VAR, argNo));
+            }
+        }
+    }
+
+    void getFunctionArgumentAssignmentCode(ParmList* parms, std::string& callingMethodName, FragmentWriter& frag, FunctionCallSetup* setup, bool bThrowV8Exceptions = true)
+    {
+        std::string nativeMethodArgsString;
+        int argNo = 0;
+        Parm *p;
+        for (p = parms; p; p = nextSibling(p)) 
+        {
+            SwigType *type  = Getattr(p,"type");
+            SwigType *typeUnprefixed = SwigType_base(type);
+            String   *name  = Getattr(p,"name");
+            //String   *value = Getattr(p,"value");
+
+            bool isArgMgPointer = !SwigType_issimple(type);
+            std::string sName;
+            std::string sType;
+            if (isArgMgPointer)
+                sType += Char(typeUnprefixed);
+            else
+                sType += Char(type);
+            if (name)
+                sName += Char(name);
+
+            setup->addArg(sName, sType, argNo, isArgMgPointer);
             
+            frag.writeToFragment("//Argument\n");
+            frag.writeToFragment(NewStringf("// Name - %s\n", name));
+            frag.writeToFragment(NewStringf("// Type - %s\n", type));
+            //frag.writeToFragment(NewStringf("// Value - %s\n", value));
+            
+            //Before we extract values from v8::Arguments, do basic checks on the parameters
+            writeArgumentCheckFragment(frag, callingMethodName, name, type, argNo, isArgMgPointer, bThrowV8Exceptions);
+
+            bool bIsMgObject = (Strcmp(typeUnprefixed, "MgObject") == 0);
+
+            writeArgumentAssignmentCode(frag, type, typeUnprefixed, name, argNo, isArgMgPointer, bIsMgObject);
+            
             frag.writeToFragment("\n");
 
             if (!nativeMethodArgsString.empty())
@@ -915,8 +1211,10 @@
             out << argNo;
             nativeMethodArgsString += out.str();
 
+            Delete(name);
             argNo++;
         }
+        setup->setFunctionArgumentString(nativeMethodArgsString);
     }
 
     void getScopeCloseCallForBasicType(SwigType* type, std::string& str, std::string& preCloseCallCode)



More information about the mapguide-commits mailing list