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

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Tue Jun 18 09:29:43 PDT 2013


Author: jng
Date: 2013-06-18 09:29:43 -0700 (Tue, 18 Jun 2013)
New Revision: 7628

Modified:
   sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx
Log:
This submission includes:
 * Fragment and exception handling code generation with RAII semantics allowing for formatted codegen in an intuitive fashion.
 * Refactor the function argument call checking and marshalling to be re-usable for constructor calls
 * Implement codegen for "delete_" methods

Modified: sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx
===================================================================
--- sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx	2013-06-18 14:37:13 UTC (rev 7627)
+++ sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx	2013-06-18 16:29:43 UTC (rev 7628)
@@ -23,6 +23,96 @@
     ~Indenter() { m_level--; }
 };
 
+class FragmentWriter
+{
+private:
+    std::string& m_fragment;
+    int& m_indent;
+
+public:
+    FragmentWriter(int& indentLevel, std::string& fragment) : m_indent(indentLevel), m_fragment(fragment)
+    {
+    }
+
+    int& indent() { return m_indent; }
+
+    void writeTabs() 
+    {
+        if (m_indent > 0)
+        {
+            for (int i = 0; i < m_indent; i++)
+            {
+                m_fragment += "\t";
+            }
+        }
+    }
+
+    void writeToFragment(String* str, bool bDelete = true)
+    {
+        writeTabs();
+        m_fragment += Char(str);
+        if (bDelete)
+            Delete(str);
+    }
+
+    void writeToFragment(const std::string& str)
+    {
+        writeTabs();
+        m_fragment += str;
+    }
+
+    void writeToFragment(const char* str)
+    {
+        writeTabs();
+        m_fragment += str;
+    }
+};
+
+class ExceptionCodeWriter
+{
+private:
+    FragmentWriter& m_frag;
+    std::string m_try_macro;
+    std::string m_catch_macro;
+    std::string m_methodName;
+    bool m_bIncludeRawPointerCleanup;
+
+public:
+    ExceptionCodeWriter(FragmentWriter& frag, 
+                        std::string methodName, 
+                        std::string tryMacro = "MG_TRY", 
+                        std::string catchMacro = "MG_CATCH",
+                        bool bIncludeRawPointerCleanup = false) 
+        : m_frag(frag),
+          m_try_macro(tryMacro),
+          m_catch_macro(catchMacro),
+          m_methodName(methodName),
+          m_bIncludeRawPointerCleanup(bIncludeRawPointerCleanup)
+    {
+        m_frag.writeToFragment(NewStringf("%s()\n", m_try_macro.c_str()));
+    }
+
+    ~ExceptionCodeWriter()
+    {
+        m_frag.writeToFragment(NewStringf("%s(L\"%s\")\n", m_catch_macro.c_str(), m_methodName.c_str()));
+        m_frag.writeToFragment("if (mgException != NULL)\n");
+        m_frag.writeToFragment("{\n");
+        {
+            Indenter ind2(m_frag.indent());
+            m_frag.writeToFragment("//NOTE: Unlike previous iterations of the MapGuide API, MgException::GetDetails() finally gives us *everything*\n");
+            m_frag.writeToFragment("STRING details = mgException->GetDetails();\n");
+            m_frag.writeToFragment("std::string mbDetails = MgUtil::WideCharToMultiByte(details);\n");
+            m_frag.writeToFragment("v8::Local<v8::Value> v8ex = v8::Exception::Error(v8::String::New(mbDetails.c_str()));\n");
+            m_frag.writeToFragment("//Release our MgException before throwing the v8 one\n");
+            m_frag.writeToFragment("mgException = NULL;\n");
+            if (m_bIncludeRawPointerCleanup)
+                m_frag.writeToFragment(NewStringf("if (%s) { ((MgDisposable*)%s)->Release(); %s = NULL; }\n", WRAPPED_PTR_VAR, WRAPPED_PTR_VAR, WRAPPED_PTR_VAR));
+            m_frag.writeToFragment("return v8::ThrowException(v8ex);\n");
+        }
+        m_frag.writeToFragment("}\n");
+    }
+};
+
 class NODEJS : public Language
 {
 private:
@@ -186,138 +276,82 @@
         String* dtorPrefix = NewString("delete_");
         if (Strstr(name, entry))
         {
-            writeToFile(NewStringf("//Global Function: %s\n", name));
-            writeToFile(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s) {\n", name, ARGS_VAR));
+            std::string globalFuncFragment;
+            FragmentWriter cls(m_indentationLevels, globalFuncFragment);
+            cls.writeToFragment(NewStringf("//Global Function: %s\n", name));
+            std::string proxyFuncName;
+            setProxyClassName(name, proxyFuncName);
+            cls.writeToFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s) {\n", proxyFuncName.c_str(), ARGS_VAR));
             {
                 Indenter ind(m_indentationLevels);
-                //writeToFile("v8::HandleScope scope;\n");
-                //writeToFile("return scope.Close();\n");
-                writeToFile("return v8::Undefined();\n");
+                {
+                    ExceptionCodeWriter writer(cls, proxyFuncName);
+                    std::string funcCall;
+                    std::string cleanup;
+                    getFunctionArgumentAssignmentCode(parms, cls, funcCall);
+                    cls.writeToFragment(NewStringf("%s(%s);\n", name, funcCall.c_str()));
+                }
+                cls.writeToFragment("return v8::Undefined();\n");
             }
-            writeToFile("}\n");
+            cls.writeToFragment("}\n");
+
+            m_classMethodDecls.push_back(globalFuncFragment);
         }
         else if (Strstr(name, ctorPrefix))
         {
+            std::string ctorFragment;
+            FragmentWriter ctor(m_indentationLevels, ctorFragment);
             String* ovName = getOverloadedName(n);
-            writeToCurrentClassFragment(NewStringf("//ctor Function Wrapper: %s\n", name));
-            writeToCurrentClassFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s) {\n", ovName, ARGS_VAR));
+            ctor.writeToFragment(NewStringf("//ctor Function Wrapper: %s\n", name));
+
+            std::string mbName = Char(name);
+            //Strip the new_ prefix
+            std::string ctorName = mbName.substr(4);
+            std::string proxyClsName;
+            setProxyClassName(ctorName.c_str(), proxyClsName);
+
+            ctor.writeToFragment(NewStringf("static %s* %s(const v8::Arguments& %s) {\n", ctorName.c_str(), ovName, ARGS_VAR));
             {
                 Indenter ind(m_indentationLevels);
-                //writeToCurrentClassFragment("v8::HandleScope scope;\n");
-                //writeToCurrentClassFragment("return scope.Close();\n");
-                writeToCurrentClassFragment("return v8::Undefined();\n");
+
+                std::string funcCall;
+                getFunctionArgumentAssignmentCode(parms, ctor, funcCall, 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("return retVal.Detach();\n");
             }
-            writeToCurrentClassFragment("}\n");
+            ctor.writeToFragment("}\n");
+            m_classMethodDecls.push_back(ctorFragment);
         }
         else if (Strstr(name, dtorPrefix))
         {
-            writeToCurrentClassFragment(NewStringf("//dtor Function Wrapper: %s\n", name));
-            writeToCurrentClassFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s) {\n", name, ARGS_VAR));
+            std::string dtorFragment;
+            FragmentWriter dtor(m_indentationLevels, dtorFragment);
+            dtor.writeToFragment(NewStringf("//dtor Function Wrapper: %s\n", name));
+            dtor.writeToFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s) {\n", name, ARGS_VAR));
             {
                 Indenter ind(m_indentationLevels);
-                //writeToCurrentClassFragment("v8::HandleScope scope;\n");
-                //writeToCurrentClassFragment("return scope.Close();\n");
-                writeToCurrentClassFragment("return v8::Undefined();\n");
+
+                std::string funcCall;
+                getFunctionArgumentAssignmentCode(parms, dtor, funcCall);
+                
+                //TODO: Should check if node/v8 allows this. This is theoretical atm
+                //
+                //There'll only be one argument, the pointer to release
+                //Argument marshalling will create a Ptr<> of the internal pointer
+                //and a Proxy pointer that wraps another Ptr<> of the same pointer
+                //
+                //Thus deleting the proxy pointer will trigger the internal Ptr<> to
+                //release it
+                dtor.writeToFragment("delete proxyArg0;\n");
             }
-            writeToCurrentClassFragment("}\n");
+            dtor.writeToFragment("}\n");
+            m_classMethodDecls.push_back(dtorFragment);
         }
         Language::functionWrapper(n);
         return SWIG_OK;
     }
 
-    void writeTabsToCurrentClassSetupFragment() 
-    {
-        if (m_indentationLevels > 0)
-        {
-            for (int i = 0; i < m_indentationLevels; i++)
-            {
-                m_currentClassSetupFragment += "\t";
-            }
-        }
-    }
-
-    void writeToCurrentClassSetupFragment(String* str, bool bDelete = true)
-    {
-        writeTabsToCurrentClassSetupFragment();
-        m_currentClassSetupFragment += Char(str);
-        if (bDelete)
-            Delete(str);
-    }
-
-    void writeToCurrentClassSetupFragment(const std::string& str)
-    {
-        writeTabsToCurrentClassSetupFragment();
-        m_currentClassSetupFragment += str;
-    }
-
-    void writeToCurrentClassSetupFragment(const char* str)
-    {
-        writeTabsToCurrentClassSetupFragment();
-        m_currentClassSetupFragment += str;
-    }
-
-    void writeTabsToCurrentMethodFragment() 
-    {
-        if (m_indentationLevels > 0)
-        {
-            for (int i = 0; i < m_indentationLevels; i++)
-            {
-                m_currentMethodFragment += "\t";
-            }
-        }
-    }
-
-    void writeToCurrentMethodFragment(String* str, bool bDelete = true)
-    {
-        writeTabsToCurrentMethodFragment();
-        m_currentMethodFragment += Char(str);
-        if (bDelete)
-            Delete(str);
-    }
-
-    void writeToCurrentMethodFragment(const std::string& str)
-    {
-        writeTabsToCurrentMethodFragment();
-        m_currentMethodFragment += str;
-    }
-
-    void writeToCurrentMethodFragment(const char* str)
-    {
-        writeTabsToCurrentMethodFragment();
-        m_currentMethodFragment += str;
-    }
-
-    void writeTabsToCurrentClassFragment() 
-    {
-        if (m_indentationLevels > 0)
-        {
-            for (int i = 0; i < m_indentationLevels; i++)
-            {
-                m_currentFragment += "\t";
-            }
-        }
-    }
-
-    void writeToCurrentClassFragment(String* str, bool bDelete = true)
-    {
-        writeTabsToCurrentClassFragment();
-        m_currentFragment += Char(str);
-        if (bDelete)
-            Delete(str);
-    }
-
-    void writeToCurrentClassFragment(const std::string& str)
-    {
-        writeTabsToCurrentClassFragment();
-        m_currentFragment += str;
-    }
-
-    void writeToCurrentClassFragment(const char* str)
-    {
-        writeTabsToCurrentClassFragment();
-        m_currentFragment += str;
-    }
-
     void writeTabsToFile() 
     {
         if (m_indentationLevels > 0)
@@ -349,6 +383,12 @@
         Printf(m_fOutputFile, str);
     }
 
+    static void setProxyClassName(const char* clsName, std::string& sOut)
+    {
+        sOut = "Proxy";
+        sOut += clsName;
+    }
+
     static void setProxyClassName(String* clsName, std::string& sOut)
     {
         sOut = "Proxy";
@@ -372,12 +412,15 @@
         m_currentExportFragment = std::string();
         m_currentClassName = NewString(Getattr(n,"sym:name"));
 
+        FragmentWriter cls(m_indentationLevels, m_currentFragment);
+        FragmentWriter clsSetup(m_indentationLevels, m_currentClassSetupFragment);
+
         //NOTE: We currently don't export MgException classes, they're unusable in JavaScript, any exceptions that
         //any MapGuide API will throw will be caught by this node.js extension and re-thrown as a JavaScript
         //Error object.
         if (!Strstr(m_currentClassName, "Exception"))
         {
-            writeToCurrentClassFragment(NewStringf("//Node.js wrapper for class: %s\n", m_currentClassName));
+            cls.writeToFragment(NewStringf("//Node.js wrapper for class: %s\n", m_currentClassName));
 
             std::string proxyClsName;
             setProxyClassName(m_currentClassName, proxyClsName);
@@ -393,19 +436,19 @@
             
             //Export call
             m_currentExportFragment += proxyClsName;
-            m_currentExportFragment += "_Export(";
+            m_currentExportFragment += "::Export(";
             m_currentExportFragment += EXPORTS_VAR;
             m_currentExportFragment += ");";
 
             m_currentInheritFragment += proxyClsName;
-            m_currentInheritFragment += "_ApplyInheritanceChain(";
+            m_currentInheritFragment += "::ApplyInheritanceChain(";
             m_currentInheritFragment += EXPORTS_VAR;
             m_currentInheritFragment += ");";
 
             //Unmanaged pointer member
-            writeToCurrentClassFragment(clsHead);
-            writeToCurrentClassFragment("{\n");
-            writeToCurrentClassFragment("protected:\n");
+            cls.writeToFragment(clsHead);
+            cls.writeToFragment("{\n");
+            cls.writeToFragment("protected:\n");
             
             bool isMgObject = isCurrentClassMgObject();
 
@@ -415,7 +458,7 @@
                 std::string ptrDecl;
                 ptrDecl += Char(m_currentClassName);
                 ptrDecl += "* m_ptr;\n";
-                writeToCurrentClassFragment(ptrDecl);
+                cls.writeToFragment(ptrDecl);
             }
             else
             {
@@ -423,9 +466,9 @@
                 std::string ptrDecl = "Ptr<";
                 ptrDecl += Char(m_currentClassName);
                 ptrDecl += "> m_ptr;\n";
-                writeToCurrentClassFragment(ptrDecl);
+                cls.writeToFragment(ptrDecl);
             }
-            writeToCurrentClassFragment("public:\n");
+            cls.writeToFragment("public:\n");
             std::string ctorDecl;
             ctorDecl += proxyClsName;
             ctorDecl += "(";
@@ -434,13 +477,13 @@
             //ctor
             {
                 Indenter ind(m_indentationLevels);
-                writeToCurrentClassFragment(ctorDecl);
-                writeToCurrentClassFragment("{\n");
+                cls.writeToFragment(ctorDecl);
+                cls.writeToFragment("{\n");
                 if (isMgObject) //Anything inheriting from MgObject will be MgDisposable
-                    writeToCurrentClassFragment("\tm_ptr = SAFE_ADDREF((MgDisposable*)ptr);\n");
+                    cls.writeToFragment("\tm_ptr = SAFE_ADDREF((MgDisposable*)ptr);\n");
                 else
-                    writeToCurrentClassFragment("\tm_ptr = SAFE_ADDREF(ptr);\n");
-                writeToCurrentClassFragment("}\n");
+                    cls.writeToFragment("\tm_ptr = SAFE_ADDREF(ptr);\n");
+                cls.writeToFragment("}\n");
             }
             std::string dtorDecl;
             dtorDecl += "~";
@@ -449,15 +492,22 @@
             //dtor
             {
                 Indenter ind(m_indentationLevels);
-                writeToCurrentClassFragment(dtorDecl);
-                writeToCurrentClassFragment("{\n");
+                cls.writeToFragment(dtorDecl);
+                cls.writeToFragment("{\n");
                 if (isMgObject) //Anything inheriting from MgObject will be MgDisposable 
-                    writeToCurrentClassFragment("\t((MgDisposable*)m_ptr)->Release();\n");
+                    cls.writeToFragment("\t((MgDisposable*)m_ptr)->Release();\n");
                 else
-                    writeToCurrentClassFragment("\tm_ptr = NULL;\n");
-                writeToCurrentClassFragment("}\n");
+                    cls.writeToFragment("\tm_ptr = NULL;\n");
+                cls.writeToFragment("}\n");
             }
 
+            //Stubs to be implemented further down
+            {
+                Indenter ind(m_indentationLevels);
+                cls.writeToFragment("static void Export(v8::Handle<v8::Object> exports);\n");
+                cls.writeToFragment("static void ApplyInheritanceChain(v8::Handle<v8::Object> exports);\n");
+            }
+
             //Class body
             {
                 Indenter ind(m_indentationLevels);
@@ -468,32 +518,35 @@
             {
                 Indenter ind(m_indentationLevels);
                 if (isMgObject)
-                    writeToCurrentClassFragment(NewStringf("%s* GetInternalPointer() { return SAFE_ADDREF((MgDisposable*)m_ptr); }\n", m_currentClassName));
+                    cls.writeToFragment(NewStringf("%s* GetInternalPointer() { return SAFE_ADDREF((MgDisposable*)m_ptr); }\n", m_currentClassName));
                 else
-                    writeToCurrentClassFragment(NewStringf("%s* GetInternalPointer() { return SAFE_ADDREF(m_ptr.p); }\n", m_currentClassName));
+                    cls.writeToFragment(NewStringf("%s* GetInternalPointer() { return SAFE_ADDREF(m_ptr.p); }\n", m_currentClassName));
             }
 
+            cls.writeToFragment("private:\n");
             //Proxy Constructor
             {
                 Indenter ind(m_indentationLevels);
-                writeToCurrentClassFragment(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));
                 {
                     Indenter ind2(m_indentationLevels);
-                    writeToCurrentClassFragment("//TODO: Parse arguments and determine which actual native constructor to invoke\n");
-                    writeToCurrentClassFragment("return v8::Undefined();\n");
+                    cls.writeToFragment("//TODO: Parse arguments and determine which actual native constructor to invoke\n");
+                    cls.writeToFragment("return v8::Undefined();\n");
                 }
-                writeToCurrentClassFragment("}\n");
+                cls.writeToFragment("}\n");
             }
 
             //node/v8 export function
             {
                 Indenter ind(m_indentationLevels);
-                writeToCurrentClassSetupFragment(NewStringf("static void %s_Export(v8::Handle<v8::Object> %s)\n", proxyClsName.c_str(), EXPORTS_VAR));
-                writeToCurrentClassSetupFragment("{\n");
+                clsSetup.writeToFragment(NewStringf("void %s::Export(v8::Handle<v8::Object> %s)\n", proxyClsName.c_str(), EXPORTS_VAR));
+                clsSetup.writeToFragment("{\n");
                 {
                     Indenter ind2(m_indentationLevels);
-                    writeToCurrentClassSetupFragment(NewStringf("v8::Local<v8::FunctionTemplate> %s = v8::FunctionTemplate::New(%s::%s);\n", CLASS_EXPORT_VAR, proxyClsName.c_str(), CLASS_PROXY_CTOR_NAME));
-                    writeToCurrentClassSetupFragment(NewStringf("%s->SetClassName(v8::String::NewSymbol(\"%s\"));\n", CLASS_EXPORT_VAR, m_currentClassName));
+                    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("%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(";
                     ctorReg += CLASS_EXPORT_VAR;
@@ -510,26 +563,26 @@
 
                     for (std::vector<std::string>::iterator it = m_classMemberExportCalls.begin(); it != m_classMemberExportCalls.end(); it++)
                     {
-                        writeToCurrentClassSetupFragment((*it));
-                        writeToCurrentClassSetupFragment("\n");
+                        clsSetup.writeToFragment((*it));
+                        clsSetup.writeToFragment("\n");
                     }
                 }
-                writeToCurrentClassSetupFragment("}\n");
+                clsSetup.writeToFragment("}\n");
             }
 
             //node/v8 inheritance hook
             {
                 Indenter ind(m_indentationLevels);
-                writeToCurrentClassSetupFragment(NewStringf("static void %s_ApplyInheritanceChain(v8::Handle<v8::Object> %s)\n", proxyClsName.c_str(), EXPORTS_VAR));
-                writeToCurrentClassSetupFragment("{\n");
+                clsSetup.writeToFragment(NewStringf("void %s::ApplyInheritanceChain(v8::Handle<v8::Object> %s)\n", proxyClsName.c_str(), EXPORTS_VAR));
+                clsSetup.writeToFragment("{\n");
                 {
                     Indenter ind2(m_indentationLevels);
-                    writeToCurrentClassSetupFragment("//TODO: Apply prototype inheritance chain\n");
+                    clsSetup.writeToFragment("//TODO: Apply prototype inheritance chain\n");
                 }
-                writeToCurrentClassSetupFragment("}\n");
+                clsSetup.writeToFragment("}\n");
             }
 
-            writeToCurrentClassFragment("};");
+            cls.writeToFragment("};");
 
             Delete(m_currentClassName);
             m_currentClassName = NULL;
@@ -546,7 +599,8 @@
     virtual int memberconstantHandler(Node* n)
     {
         String* name = Getattr(n, "sym:name");
-        writeToCurrentClassFragment(NewStringf("//\tMember Constant: %s::%s\n", m_currentClassName, name));
+        FragmentWriter frag(m_indentationLevels, m_currentFragment);
+        frag.writeToFragment(NewStringf("//\tMember Constant: %s::%s\n", m_currentClassName, name));
         String* swExpCall = NewStringf("//TODO: Export constant %s::%s", m_currentClassName, name);
         std::string expCall = Char(swExpCall);
         Delete(swExpCall);
@@ -571,29 +625,30 @@
 
         m_currentMethodFragment = std::string();
 
+        FragmentWriter meth(m_indentationLevels, m_currentMethodFragment);
         //Proxy method is encoded as ClassName_SwigQualifiedMethodName
 
-        writeToCurrentMethodFragment(NewStringf("//\tMember Function: %s::%s\n", m_currentClassName, overloaded_name));
-        writeToCurrentMethodFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s) {\n", overloaded_name_qualified, ARGS_VAR));
+        meth.writeToFragment(NewStringf("//\tMember Function: %s::%s\n", m_currentClassName, overloaded_name));
+        meth.writeToFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s) {\n", overloaded_name_qualified, ARGS_VAR));
         {
             Indenter ind(m_indentationLevels);
 
             std::string wrappedPtrCall;
-            writeToCurrentMethodFragment(NewStringf("//Return type - %s (pointer? %s)\n", retType, (isMgPointer ? "true" : "false")));
+            meth.writeToFragment(NewStringf("//Return type - %s (pointer? %s)\n", retType, (isMgPointer ? "true" : "false")));
             
             if (isVoid)
             {
-                writeToCurrentMethodFragment("//Function is void and does not return a value\n");
+                meth.writeToFragment("//Function is void and does not return a value\n");
             }
             else
             {
                 if (isMgPointer)
                 {
-                    writeToCurrentMethodFragment(NewStringf("Ptr<%s> %s;\n", retTypeUnprefixed, FUNC_RET_VAR));
+                    meth.writeToFragment(NewStringf("Ptr<%s> %s;\n", retTypeUnprefixed, FUNC_RET_VAR));
                 }
                 else
                 {
-                    writeToCurrentMethodFragment(NewStringf("%s %s;\n", retType, FUNC_RET_VAR));
+                    meth.writeToFragment(NewStringf("%s %s;\n", retType, FUNC_RET_VAR));
                 }
             }
 
@@ -606,73 +661,64 @@
             wrappedPtrCall += "->";
             
             if (isCurrentClassMgObject())
-                writeToCurrentMethodFragment(NewStringf("%s* %s = NULL;\n", m_currentClassName, WRAPPED_PTR_VAR));
+                meth.writeToFragment(NewStringf("%s* %s = NULL;\n", m_currentClassName, WRAPPED_PTR_VAR));
             else
-                writeToCurrentMethodFragment(NewStringf("Ptr<%s> %s;\n", m_currentClassName, WRAPPED_PTR_VAR));
-            writeToCurrentMethodFragment("MG_TRY()\n");
+                meth.writeToFragment(NewStringf("Ptr<%s> %s;\n", m_currentClassName, WRAPPED_PTR_VAR));
             
-            if (parms)
+            
             {
-                std::string funcCallArgsStr;
-                getFunctionArgumentAssignmentCode(parms, funcCallArgsStr);
-                wrappedPtrCall += Char(name);
-                wrappedPtrCall += "(";
-                wrappedPtrCall += funcCallArgsStr;
-                wrappedPtrCall += ");\n";
-            }
-            else
-            {
-                writeToCurrentMethodFragment("//Function has no arguments\n");
-                wrappedPtrCall += Char(name);
-                wrappedPtrCall += "();\n";
-            }
-            
-            writeToCurrentMethodFragment(NewStringf("%s* proxy = node::ObjectWrap::Unwrap<%s>(%s.This());\n", proxyClsName.c_str(), proxyClsName.c_str(), ARGS_VAR));
-            writeToCurrentMethodFragment(NewStringf("%s = proxy->GetInternalPointer();\n", WRAPPED_PTR_VAR));
-            
-            //Here's the actual call
-            writeToCurrentMethodFragment("//Do your thing\n");
-            writeToCurrentMethodFragment(wrappedPtrCall);
-            writeToCurrentMethodFragment("\n");
+                std::string mbMethodName = Char(overloaded_name_qualified);
+                ExceptionCodeWriter writer(meth, mbMethodName, "MG_TRY", "MG_CATCH", true);   
+                {
+                    Indenter ind2(m_indentationLevels);
+                    if (parms)
+                    {
+                        std::string funcCallArgsStr;
+                        getFunctionArgumentAssignmentCode(parms, meth, funcCallArgsStr);
+                        wrappedPtrCall += Char(name);
+                        wrappedPtrCall += "(";
+                        wrappedPtrCall += funcCallArgsStr;
+                        wrappedPtrCall += ");\n";
+                    }
+                    else
+                    {
+                        meth.writeToFragment("//Function has no arguments\n");
+                        wrappedPtrCall += Char(name);
+                        wrappedPtrCall += "();\n";
+                    }
+                    
+                    meth.writeToFragment(NewStringf("%s* proxy = node::ObjectWrap::Unwrap<%s>(%s.This());\n", proxyClsName.c_str(), proxyClsName.c_str(), ARGS_VAR));
+                    meth.writeToFragment(NewStringf("%s = proxy->GetInternalPointer();\n", WRAPPED_PTR_VAR));
+                    
+                    //Here's the actual call
+                    meth.writeToFragment("//Do your thing\n");
+                    meth.writeToFragment(wrappedPtrCall);
+                    meth.writeToFragment("\n");
 
-            writeToCurrentMethodFragment(NewStringf("MG_CATCH(L\"%s::%s\")\n", proxyClsName.c_str(), overloaded_name_qualified));
-            writeToCurrentMethodFragment("if (mgException != NULL)\n");
-            writeToCurrentMethodFragment("{\n");
-            {
-                Indenter ind2(m_indentationLevels);
-                writeToCurrentMethodFragment("//NOTE: Unlike previous iterations of the MapGuide API, MgException::GetDetails() finally gives us *everything*\n");
-                writeToCurrentMethodFragment("STRING details = mgException->GetDetails();\n");
-                writeToCurrentMethodFragment("std::string mbDetails = MgUtil::WideCharToMultiByte(details);\n");
-                writeToCurrentMethodFragment("v8::Local<v8::Value> v8ex = v8::Exception::Error(v8::String::New(mbDetails.c_str()));\n");
-                writeToCurrentMethodFragment("//Release our MgException before throwing the v8 one\n");
-                writeToCurrentMethodFragment("mgException = NULL;\n");
-                if (isCurrentClassMgObject())
-                    writeToCurrentMethodFragment(NewStringf("if (%s) { ((MgDisposable*)%s)->Release(); %s = NULL; }\n", WRAPPED_PTR_VAR, WRAPPED_PTR_VAR, WRAPPED_PTR_VAR));
-                writeToCurrentMethodFragment("return v8::ThrowException(v8ex);\n");
+                }
             }
-            writeToCurrentMethodFragment("}\n");
             if (isCurrentClassMgObject())
-                writeToCurrentMethodFragment(NewStringf("if (%s) { ((MgDisposable*)%s)->Release(); %s = NULL; }\n", WRAPPED_PTR_VAR, WRAPPED_PTR_VAR, WRAPPED_PTR_VAR));
-            //writeToCurrentMethodFragment("v8::HandleScope scope;\n");
-            //writeToCurrentMethodFragment("return scope.Close();\n");
+                meth.writeToFragment(NewStringf("if (%s) { ((MgDisposable*)%s)->Release(); %s = NULL; }\n", WRAPPED_PTR_VAR, WRAPPED_PTR_VAR, WRAPPED_PTR_VAR));
+            //meth.writeToFragment("v8::HandleScope scope;\n");
+            //meth.writeToFragment("return scope.Close();\n");
 
-            writeToCurrentMethodFragment("\n");
-            writeToCurrentMethodFragment("//Return value to javascript\n");
+            meth.writeToFragment("\n");
+            meth.writeToFragment("//Return value to javascript\n");
             if (isVoid)
             {
-                writeToCurrentMethodFragment("return v8::Undefined();\n");
+                meth.writeToFragment("return v8::Undefined();\n");
             }
             else
             {
                 if (isMgPointer) //Stub
                 {
-                    writeToCurrentMethodFragment("return v8::ThrowException(v8::Exception::Error(v8::String::New(\"TODO: Case not handled yet: Returning objects\")));\n");
+                    meth.writeToFragment("return v8::ThrowException(v8::Exception::Error(v8::String::New(\"TODO: Case not handled yet: Returning objects\")));\n");
                 }
                 else
                 {
                     std::string scopeCloseCall;
                     std::string preCloseCallCode;
-                    writeToCurrentMethodFragment("v8::HandleScope scope;\n");
+                    meth.writeToFragment("v8::HandleScope scope;\n");
                     if (isMgPointer)
                     {
                          
@@ -682,12 +728,12 @@
                         getScopeCloseCallForBasicType(retType, scopeCloseCall, preCloseCallCode);
                     }
                     if (!preCloseCallCode.empty())
-                        writeToCurrentMethodFragment(preCloseCallCode);
-                    writeToCurrentMethodFragment(NewStringf("return scope.Close(%s);\n", scopeCloseCall.c_str()));
+                        meth.writeToFragment(preCloseCallCode);
+                    meth.writeToFragment(NewStringf("return scope.Close(%s);\n", scopeCloseCall.c_str()));
                 }
             }
         }
-        writeToCurrentMethodFragment("}\n");
+        meth.writeToFragment("}\n");
 
         String* regCall = NewStringf(
             "%s->PrototypeTemplate()->Set(v8::String::NewSymbol(\"%s\"), v8::FunctionTemplate::New(%s)->GetFunction());\n",
@@ -705,7 +751,7 @@
         return SWIG_OK;
     }
 
-    void getFunctionArgumentAssignmentCode(ParmList* parms, std::string& nativeMethodArgsString)
+    void getFunctionArgumentAssignmentCode(ParmList* parms, FragmentWriter& frag, std::string& nativeMethodArgsString, bool bThrowV8Exceptions = true)
     {
         int argNo = 0;
         Parm *p;
@@ -718,21 +764,26 @@
 
             bool isArgMgPointer = !SwigType_issimple(type);
             
-            writeToCurrentMethodFragment("//Argument\n");
-            writeToCurrentMethodFragment(NewStringf("// Name - %s\n", name));
-            writeToCurrentMethodFragment(NewStringf("// Type - %s\n", type));
-            //writeToCurrentMethodFragment(NewStringf("// Value - %s\n", value));
+            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 primitive
-            //types
+            //Before we extract values from v8::Arguments, do basic checks on the parameters
             if (isArgMgPointer)
             {
-                writeToCurrentMethodFragment(NewStringf("if (!args[%d]->IsObject()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not an object\")));\n", argNo, (argNo + 1), name, type));
+                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));
             }
             else
             {
                 //Write definition check
-                writeToCurrentMethodFragment(NewStringf("if (args[%d]->IsUndefined()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is undefined\")));\n", argNo, (argNo + 1), name, type));
+                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 ||
@@ -747,37 +798,61 @@
                     Strcmp(type, "long") == 0 ||
                     Strcmp(type, "long long") == 0)
                 {
-                    writeToCurrentMethodFragment(NewStringf("if (!args[%d]->IsInt32()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a number\")));\n", argNo, (argNo + 1), name, type));
+                    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));
                 }
                 else if (Strcmp(type, "double") == 0 ||
                          Strcmp(type, "float") == 0)
                 {
-                    writeToCurrentMethodFragment(NewStringf("if (!args[%d]->IsNumber()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a number\")));\n", argNo, (argNo + 1), name, type));
+                    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));
                 }
                 else if (Strcmp(type, "STRINGPARAM") == 0)
                 {
-                    writeToCurrentMethodFragment(NewStringf("if (!args[%d]->IsString()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a string\")));\n", argNo, (argNo + 1), name, type));
+                    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));
                 }
                 else if (Strcmp(type, "bool") == 0)
                 {
-                    writeToCurrentMethodFragment(NewStringf("if (!args[%d]->IsBoolean()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a boolean\")));\n", argNo, (argNo + 1), name, type));
+                    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));
                 }
             }
 
+            bool bIsMgObject = (Strcmp(typeUnprefixed, "MgObject") == 0);
+
             if (isArgMgPointer)
             {
                 std::string proxyClsName;
                 setProxyClassName(typeUnprefixed, proxyClsName);
-                writeToCurrentMethodFragment(NewStringf("Ptr<%s> arg%d = NULL;\n", typeUnprefixed, argNo));
-                writeToCurrentMethodFragment(NewStringf("%s* proxyArg%d = NULL;\n", proxyClsName.c_str(), argNo));
-                writeToCurrentMethodFragment(NewStringf("if (!args[%d]->IsUndefined())\n", argNo));
-                writeToCurrentMethodFragment("{\n");
+                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);
-                    writeToCurrentMethodFragment(NewStringf("proxyArg%d = node::ObjectWrap::Unwrap<%s>(args[%d]->ToObject());\n", argNo, proxyClsName.c_str(), argNo));
-                    writeToCurrentMethodFragment(NewStringf("arg%d = proxyArg%d->GetInternalPointer();\n", argNo, argNo));
+                    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));
                 }
-                writeToCurrentMethodFragment("}\n");
+                frag.writeToFragment("}\n");
             }
             else
             {
@@ -795,33 +870,41 @@
                     Strcmp(type, "long") == 0 ||
                     Strcmp(type, "long long") == 0)
                 {
-                    writeToCurrentMethodFragment(NewStringf("%s arg%d = (%s)args[%d]->IntegerValue();\n", type, argNo, type, argNo));
+                    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)
                 {
-                    writeToCurrentMethodFragment(NewStringf("%s arg%d = (%s)args[%d]->NumberValue();\n", type, argNo, type, argNo));
+                    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)
                 {
-                    //writeToCurrentMethodFragment(NewStringf("std::string str%d = args[%d]->ToString();\n", argNo, argNo));
-                    //writeToCurrentMethodFragment(NewStringf("Ptr<MgByte> bytes%d = new MgByte((BYTE_ARRAY_IN)str%d);\n", argNo, argNo));
-                    //writeToCurrentMethodFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(args[%d]->ToString());\n", argNo, argNo));
-                    writeToCurrentMethodFragment("//TODO: Case not handled: BYTE_ARRAY_OUT\n");
-                    writeToCurrentMethodFragment(NewStringf("BYTE_ARRAY_OUT arg%d = NULL;\n", argNo));
+                    //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)
                 {
-                    writeToCurrentMethodFragment(NewStringf("v8::String::Utf8Value mbArg%d(args[%d]->ToString());\n", argNo, argNo));
-                    writeToCurrentMethodFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(std::string(*mbArg%d));\n", argNo, argNo));
+                    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)
                 {
-                    writeToCurrentMethodFragment(NewStringf("%s arg%d = args[%d]->BooleanValue();\n", type, argNo, argNo));
+                    frag.writeToFragment(NewStringf("%s arg%d = %s[%d]->BooleanValue();\n", type, argNo, ARGS_VAR, argNo));
                 }
             }
             
-            writeToCurrentMethodFragment("\n");
+            frag.writeToFragment("\n");
 
             if (!nativeMethodArgsString.empty())
                 nativeMethodArgsString += ", ";
@@ -881,7 +964,8 @@
     virtual int membervariableHandler(Node* n)
     {
         String* name = Getattr(n, "sym:name");
-        writeToCurrentClassFragment(NewStringf("//\tMember Variable: %s::%s\n", m_currentClassName, name));
+        FragmentWriter frag(m_indentationLevels, m_currentFragment);
+        frag.writeToFragment(NewStringf("//\tMember Variable: %s::%s\n", m_currentClassName, name));
         
         String* swExpCall = NewStringf("//TODO: Export member variable %s::%s", m_currentClassName, name);
         std::string expCall = Char(swExpCall);



More information about the mapguide-commits mailing list