Browse Source

Merge pull request #446 from LumaDigital/master

Support for static class functions in JSBind. A version of ToString that takes an explicit vs_args parameter.
JoshEngebretson 10 years ago
parent
commit
f8b674c14d

+ 2 - 0
AUTHORS.md

@@ -19,6 +19,8 @@
 
 
 - Jay Sistar (https://github.com/type1j)
 - Jay Sistar (https://github.com/type1j)
 
 
+- Matt Benic (https://github.com/mattbenic)
+
 ### Contribution Copyright and Licensing
 ### Contribution Copyright and Licensing
 
 
 Atomic Game Engine contribution copyrights are held by their authors.  Each author retains the copyright to their contribution and agrees to irrevocably license the contribution under the Atomic Game Engine Contribution License `CONTRIBUTION_LICENSE.md`.  Please see `CONTRIBUTING.md` for more details.
 Atomic Game Engine contribution copyrights are held by their authors.  Each author retains the copyright to their contribution and agrees to irrevocably license the contribution under the Atomic Game Engine Contribution License `CONTRIBUTION_LICENSE.md`.  Please see `CONTRIBUTING.md` for more details.

+ 7 - 0
Source/Atomic/Core/StringUtils.cpp

@@ -647,6 +647,13 @@ String ToString(const char* formatString, ...)
     return ret;
     return ret;
 }
 }
 
 
+String ToStringVariadic(const char* formatString, va_list args)
+{
+    String ret;
+    ret.AppendWithFormatArgs(formatString, args);
+    return ret;
+}
+
 bool IsAlpha(unsigned ch)
 bool IsAlpha(unsigned ch)
 {
 {
     return ch < 256 ? isalpha(ch) != 0 : false;
     return ch < 256 ? isalpha(ch) != 0 : false;

+ 2 - 0
Source/Atomic/Core/StringUtils.h

@@ -113,6 +113,8 @@ ATOMIC_API unsigned GetStringListIndex(const char* value, const String* strings,
 ATOMIC_API unsigned GetStringListIndex(const char* value, const char** strings, unsigned defaultIndex, bool caseSensitive = false);
 ATOMIC_API unsigned GetStringListIndex(const char* value, const char** strings, unsigned defaultIndex, bool caseSensitive = false);
 /// Return a formatted string.
 /// Return a formatted string.
 ATOMIC_API String ToString(const char* formatString, ...);
 ATOMIC_API String ToString(const char* formatString, ...);
+/// Return a formatted string.
+ATOMIC_API String ToStringVariadic(const char* formatString, va_list args);
 /// Return whether a char is an alphabet letter.
 /// Return whether a char is an alphabet letter.
 ATOMIC_API bool IsAlpha(unsigned ch);
 ATOMIC_API bool IsAlpha(unsigned ch);
 /// Return whether a char is a digit.
 /// Return whether a char is a digit.

+ 5 - 1
Source/ToolCore/JSBind/JSBFunction.h

@@ -118,7 +118,8 @@ public:
     JSBFunction(JSBClass* klass) : class_(klass), returnType_(0),
     JSBFunction(JSBClass* klass) : class_(klass), returnType_(0),
                                    isConstructor_(false), isDestructor_(false),
                                    isConstructor_(false), isDestructor_(false),
                                    isGetter_(false), isSetter_(false),
                                    isGetter_(false), isSetter_(false),
-                                   isOverload_(false), skip_(false), isVirtual_(false)
+                                   isOverload_(false), skip_(false), 
+                                   isVirtual_(false), isStatic_(false)
     {
     {
 
 
     }
     }
@@ -133,6 +134,7 @@ public:
     bool IsGetter() { return isGetter_; }
     bool IsGetter() { return isGetter_; }
     bool IsOverload() { return isOverload_; }
     bool IsOverload() { return isOverload_; }
     bool IsVirtual() { return isVirtual_; }
     bool IsVirtual() { return isVirtual_; }
+    bool IsStatic() { return isStatic_; }
     bool Skip() { return skip_; }
     bool Skip() { return skip_; }
 
 
     JSBClass* GetClass() { return class_; }
     JSBClass* GetClass() { return class_; }
@@ -153,6 +155,7 @@ public:
     void SetGetter(bool value = true) { isGetter_ = value; }
     void SetGetter(bool value = true) { isGetter_ = value; }
     void SetOverload(bool value = true) { isOverload_ = value; }
     void SetOverload(bool value = true) { isOverload_ = value; }
     void SetVirtual(bool value = true) { isVirtual_ = value; }
     void SetVirtual(bool value = true) { isVirtual_ = value; }
+    void SetStatic(bool value = true) { isStatic_ = value; }
     void SetSkip(bool value) { skip_ = value; }
     void SetSkip(bool value) { skip_ = value; }
     void SetReturnType(JSBFunctionType* retType) { returnType_ = retType; }
     void SetReturnType(JSBFunctionType* retType) { returnType_ = retType; }
     void SetDocString(const String& docString) { docString_ = docString; }
     void SetDocString(const String& docString) { docString_ = docString; }
@@ -224,6 +227,7 @@ private:
     bool isSetter_;
     bool isSetter_;
     bool isOverload_;
     bool isOverload_;
     bool isVirtual_;
     bool isVirtual_;
+    bool isStatic_;
     bool skip_;
     bool skip_;
 
 
 };
 };

+ 3 - 0
Source/ToolCore/JSBind/JSBHeaderVisitor.h

@@ -281,6 +281,9 @@ public:
         if (function->isVirtual())
         if (function->isVirtual())
             jfunction->SetVirtual(true);
             jfunction->SetVirtual(true);
 
 
+        if (function->isStatic())
+            jfunction->SetStatic(true);
+
         // see if we support return type
         // see if we support return type
         if (function->hasReturnType() && !function->returnType().type()->isVoidType())
         if (function->hasReturnType() && !function->returnType().type()->isVoidType())
         {
         {

+ 6 - 1
Source/ToolCore/JSBind/JSBTypeScript.cpp

@@ -108,7 +108,12 @@ void JSBTypeScript::ExportFunction(JSBFunction* function)
     if (function->GetDocString().Length())
     if (function->GetDocString().Length())
         source_ += "      //" + function->GetDocString() + "\n";
         source_ += "      //" + function->GetDocString() + "\n";
 
 
-    source_ += "      " + scriptName + "(";
+    source_ += "      ";
+
+    if (function->IsStatic())
+        source_ += "static ";
+
+    source_ += scriptName + "(";
 
 
     Vector<JSBFunctionType*>& parameters = function->GetParameters();
     Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
 

+ 51 - 7
Source/ToolCore/JSBind/JavaScript/JSClassWriter.cpp

@@ -57,7 +57,20 @@ void JSClassWriter::GenerateSource(String& sourceOut)
 
 
     source.AppendWithFormat("static void jsb_class_define_%s(JSVM* vm)\n{\n", klass_->GetName().CString());
     source.AppendWithFormat("static void jsb_class_define_%s(JSVM* vm)\n{\n", klass_->GetName().CString());
     source.Append("duk_context* ctx = vm->GetJSContext();\n");
     source.Append("duk_context* ctx = vm->GetJSContext();\n");
-    source.AppendWithFormat("js_class_get_prototype(ctx, \"%s\", \"%s\");\n", packageName.CString(), klass_->GetName().CString());
+
+    GenerateStaticFunctionsSource(source, packageName);
+
+    GenerateNonStaticFunctionsSource(source, packageName);
+
+    source.Append("}\n");
+
+    sourceOut += source;
+
+}
+
+void JSClassWriter::GenerateStaticFunctionsSource(String& source, String& packageName)
+{
+    source.AppendWithFormat("js_class_get_constructor(ctx, \"%s\", \"%s\");\n", packageName.CString(), klass_->GetName().CString());
 
 
     for (unsigned i = 0; i < klass_->functions_.Size(); i++)
     for (unsigned i = 0; i < klass_->functions_.Size(); i++)
     {
     {
@@ -69,27 +82,58 @@ void JSClassWriter::GenerateSource(String& sourceOut)
         if (function->IsConstructor() || function->IsDestructor())
         if (function->IsConstructor() || function->IsDestructor())
             continue;
             continue;
 
 
+        if (!function->IsStatic())
+            continue;
+
         if (function->FirstDefaultParameter() != -1)
         if (function->FirstDefaultParameter() != -1)
         {
         {
             source.AppendWithFormat("duk_push_c_function(ctx, jsb_class_%s_%s, DUK_VARARGS);\n", klass_->GetName().CString(), function->GetName().CString());
             source.AppendWithFormat("duk_push_c_function(ctx, jsb_class_%s_%s, DUK_VARARGS);\n", klass_->GetName().CString(), function->GetName().CString());
         }
         }
         else
         else
         {
         {
-            source.AppendWithFormat("duk_push_c_function(ctx, jsb_class_%s_%s, %i);\n", klass_->GetName().CString(), function->GetName().CString(), (int) function->GetParameters().Size());
+            source.AppendWithFormat("duk_push_c_function(ctx, jsb_class_%s_%s, %i);\n", klass_->GetName().CString(), function->GetName().CString(), (int)function->GetParameters().Size());
         }
         }
 
 
-        String scriptName =  function->GetName();
+        String scriptName = function->GetName();
         scriptName[0] = tolower(scriptName[0]);
         scriptName[0] = tolower(scriptName[0]);
         source.AppendWithFormat("duk_put_prop_string(ctx, -2, \"%s\");\n", scriptName.CString());
         source.AppendWithFormat("duk_put_prop_string(ctx, -2, \"%s\");\n", scriptName.CString());
-
     }
     }
-
     source.Append("duk_pop(ctx);\n");
     source.Append("duk_pop(ctx);\n");
-    source.Append("}\n");
+}
 
 
+void JSClassWriter::GenerateNonStaticFunctionsSource(String& source, String& packageName)
+{
+    source.AppendWithFormat("js_class_get_prototype(ctx, \"%s\", \"%s\");\n", packageName.CString(), klass_->GetName().CString());
 
 
-    sourceOut += source;
+    for (unsigned i = 0; i < klass_->functions_.Size(); i++)
+    {
+        JSBFunction* function = klass_->functions_.At(i);
 
 
+        if (function->Skip())
+            continue;
+
+        if (function->IsConstructor() || function->IsDestructor())
+            continue;
+
+        if (function->IsStatic())
+            continue;
+
+        if (function->FirstDefaultParameter() != -1)
+        {
+            source.AppendWithFormat("duk_push_c_function(ctx, jsb_class_%s_%s, DUK_VARARGS);\n", klass_->GetName().CString(), function->GetName().CString());
+        }
+        else
+        {
+            source.AppendWithFormat("duk_push_c_function(ctx, jsb_class_%s_%s, %i);\n", klass_->GetName().CString(), function->GetName().CString(), (int)function->GetParameters().Size());
+        }
+
+        String scriptName = function->GetName();
+        scriptName[0] = tolower(scriptName[0]);
+        source.AppendWithFormat("duk_put_prop_string(ctx, -2, \"%s\");\n", scriptName.CString());
+
+    }
+    source.Append("duk_pop(ctx);\n");
 }
 }
 
 
+
 }
 }

+ 2 - 0
Source/ToolCore/JSBind/JavaScript/JSClassWriter.h

@@ -31,6 +31,8 @@ public:
 private:
 private:
 
 
     void WriteFunctions(String& source);
     void WriteFunctions(String& source);
+    void GenerateStaticFunctionsSource(String& source, String& packageName);
+    void GenerateNonStaticFunctionsSource(String& source, String& packageName);
 
 
 };
 };
 
 

+ 13 - 3
Source/ToolCore/JSBind/JavaScript/JSFunctionWriter.cpp

@@ -349,8 +349,11 @@ void JSFunctionWriter::WriteFunction(String& source)
 
 
     WriteParameterMarshal(source);
     WriteParameterMarshal(source);
 
 
-    source.Append("duk_push_this(ctx);\n");
-    source.AppendWithFormat("%s* native = js_to_class_instance<%s>(ctx, -1, 0);\n", klass->GetNativeName().CString(), klass->GetNativeName().CString());
+    if (!function_->IsStatic())
+    {
+        source.Append("duk_push_this(ctx);\n");
+        source.AppendWithFormat("%s* native = js_to_class_instance<%s>(ctx, -1, 0);\n", klass->GetNativeName().CString(), klass->GetNativeName().CString());
+    }
 
 
     // declare return value;
     // declare return value;
     bool returnDeclared = false;
     bool returnDeclared = false;
@@ -420,7 +423,14 @@ void JSFunctionWriter::WriteFunction(String& source)
 
 
     }
     }
 
 
-    source.AppendWithFormat("native->%s(", function_->name_.CString());
+    if (function_->IsStatic())
+    {
+        source.AppendWithFormat("%s::%s(", klass->GetNativeName().CString(), function_->name_.CString());
+    }
+    else
+    {
+        source.AppendWithFormat("native->%s(", function_->name_.CString());
+    }
 
 
     Vector<JSBFunctionType*>& parameters = function_->GetParameters();
     Vector<JSBFunctionType*>& parameters = function_->GetParameters();