#2469 (Javascript) Method Funcs

SlimerDude Tue 22 Sep 2015

MethodFunc.js needed a bit of love to get arity(), callOn(), callList(), params(), and typeof() working:

EDIT: Updated patch as it erroneously defined Func.$typeof and not MethodFunc.$typeof

diff -r 56d95b6fa8ad src/sys/js/fan/MethodFunc.js
--- a/src/sys/js/fan/MethodFunc.js	Tue Sep 22 09:31:42 2015 -0400
+++ b/src/sys/js/fan/MethodFunc.js	Wed Sep 23 01:34:29 2015 +0100
@@ -14,6 +14,7 @@
 {
   this.m_method = method;
   this.m_returns = returns;
+  this.m_type = null;
 }
 fan.sys.MethodFunc.prototype.returns = function() { return this.m_returns; }
 fan.sys.MethodFunc.prototype.arity = function() { return this.params().size(); }
@@ -27,8 +28,8 @@
     if ((this.m_method.m_flags & (fan.sys.FConst.Static|fan.sys.FConst.Ctor)) == 0)
     {
       var temp = [];
-      temp[0] = new fan.sys.Param("this", this.m_parent, 0);
-      fparams = fan.sys.List.make(fan.sys.Param.$typeof, temp.concat(mparams));
+      temp[0] = new fan.sys.Param("this", this.m_method.m_parent, 0);
+      fparams = fan.sys.List.make(fan.sys.Param.$type, temp.concat(mparams.m_values));
     }
     this.m_fparams = fparams.ro();
   }
@@ -37,6 +38,20 @@
 fan.sys.MethodFunc.prototype.method = function() { return this.m_method; }
 fan.sys.MethodFunc.prototype.isImmutable = function() { return true; }
 
+fan.sys.MethodFunc.prototype.$typeof = function()
+{
+  // lazy load type and params
+  if (this.m_type == null)
+  {
+    var params = this.params();
+    var types = [];
+    for (var i=0; i<params.size(); i++)
+      types.push(params.get(i).m_type);
+    this.m_type = new fan.sys.FuncType(types, this.m_returns);
+  }
+  return this.m_type;
+}
+
 fan.sys.MethodFunc.prototype.call = function()
 {
   return this.m_method.call.apply(this.m_method, arguments);
@@ -44,13 +59,10 @@
 
 fan.sys.MethodFunc.prototype.callList = function(args)
 {
-  println("### MethodFunc.callList");
-  return this.m_func.apply(null, args.m_values);
+  return this.m_method.callList.apply(this.m_method, arguments);
 }
 
 fan.sys.MethodFunc.prototype.callOn = function(obj, args)
 {
-  println("### MethodFunc.callOn");
-  return this.m_func.apply(obj, args.m_values);
+  return this.m_method.callOn.apply(this.m_method, arguments);
 }
-

Note I kept the lazy loading of params when calculating the func type.

Some unit tests:

diff -r 56d95b6fa8ad src/testSys/fan/FuncTest.fan
--- a/src/testSys/fan/FuncTest.fan	Tue Sep 22 09:31:42 2015 -0400
+++ b/src/testSys/fan/FuncTest.fan	Tue Sep 22 23:27:07 2015 +0100
@@ -320,6 +320,31 @@
     verifyEq(BindDef#make.func.bind([7, 8, 9]).call(10)->list, [7, 8, 9])
   }
 
+//////////////////////////////////////////////////////////////////////////
+// Method Func
+//////////////////////////////////////////////////////////////////////////
+
+  Void testMethodFunc()
+  {
+    func := #staticJudge.func
+    verifyEq(func.call("Dredd"), "Dredd")
+    verifyEq(func.callOn(null, ["Hershey"]), "Hershey")
+    verifyEq(func.callList(["Anderson"]), "Anderson")
+    verifyEq(func.arity, 1)
+    
+    func = #judge.func
+    verifyEq(func.call(this, "Dredd"), "Dredd")
+    verifyEq(func.callOn(this, ["Hershey"]), "Hershey")
+    verifyEq(func.callList([this, "Anderson"]), "Anderson")
+    verifyEq(func.arity, 2)
+    
+    echo("params -> ${func.params}")
+    echo("typeof -> ${func.typeof}")
+    echo("toStr  -> ${func}")
+  }
+  
+  Str judge(Str who) { who }
+  static Str staticJudge(Str who) { who }
 }
 
 @Js internal class BindDef

Output:

C:\>fant -js testSys::FuncTest.testMethodFunc

-- Run: testSys::FuncTest.testMethodFunc...

params -> [sys::Param, sys::Param]
typeof -> |testSys::FuncTest,sys::Str->sys::Str|
toStr  -> undefined

   Pass: testSys::FuncTest.testMethodFunc  [8]

Time: 34ms

***
*** All tests passed! [1 tests, 1 methods, 8 verifies]
***

Note that the output is different in Java:

params -> [sys::Str who]
typeof -> sys::Func
toStr  -> fan.sys.Method$MethodFunc@2c641e9a

For typeof I find the signature displayed by Javascript to be more informative - could non-generic types in Java be updated to display their signature?

andy Wed 23 Sep 2015

Login or Signup to reply.