changeset 52:427b01954b22

The 'this' argument for a js-wrapped python function, as well as the function's arguments, are now passed to the python function.
author Atul Varma <varmaa@toolness.com>
date Wed, 08 Jul 2009 18:45:38 -0700
parents fabd3f2271fa
children 2055d853b995
files function.c test_pymonkey.py utils.c
diffstat 3 files changed, 89 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/function.c	Wed Jul 08 09:32:31 2009 -0700
+++ b/function.c	Wed Jul 08 18:45:38 2009 -0700
@@ -64,19 +64,48 @@
   }
   PyObject *callable = (PyObject *) JSVAL_TO_PRIVATE(jsCallable);
 
-  // TODO: Convert args and 'this' parameter.
-  PyObject *args = PyTuple_New(1);
+  PYM_JSContextObject *context = (PYM_JSContextObject *)
+    JS_GetContextPrivate(cx);
+
+  jsval thisArg = OBJECT_TO_JSVAL(obj);
+  PyObject *pyThisArg = PYM_jsvalToPyObject(context, thisArg);
+  if (pyThisArg == NULL) {
+    PYM_pythonExceptionToJs(context);
+    return JS_FALSE;
+  }
+
+  PyObject *funcArgs = PyTuple_New(argc);
+  if (funcArgs == NULL) {
+    Py_DECREF(pyThisArg);
+    JS_ReportOutOfMemory(cx);
+    return JS_FALSE;
+  }
+
+  for (unsigned int i = 0; i < argc; i++) {
+    PyObject *arg = PYM_jsvalToPyObject(context, argv[i]);
+    if (arg == NULL || PyTuple_SetItem(funcArgs, i, arg)) {
+      if (arg)
+        Py_DECREF(arg);
+      Py_DECREF(funcArgs);
+      Py_DECREF(pyThisArg);
+      PYM_pythonExceptionToJs(context);
+      return JS_FALSE;
+    }
+  }
+
+  PyObject *args = PyTuple_Pack(3,
+                                (PyObject *) context,
+                                pyThisArg,
+                                funcArgs);
+  Py_DECREF(pyThisArg);
+  Py_DECREF(funcArgs);
   if (args == NULL) {
     JS_ReportOutOfMemory(cx);
     return JS_FALSE;
   }
 
-  PYM_JSContextObject *context = (PYM_JSContextObject *)
-    JS_GetContextPrivate(cx);
-  Py_INCREF(context);
-  PyTuple_SET_ITEM(args, 0, (PyObject *) context);
-
   PyObject *result = PyObject_Call(callable, args, NULL);
+  Py_DECREF(args);
   if (result == NULL) {
     PYM_pythonExceptionToJs(context);
     return JS_FALSE;
@@ -89,6 +118,7 @@
     PYM_pythonExceptionToJs(context);
     return JS_FALSE;
   }
+
   return JS_TRUE;
 }
 
--- a/test_pymonkey.py	Wed Jul 08 09:32:31 2009 -0700
+++ b/test_pymonkey.py	Wed Jul 08 18:45:38 2009 -0700
@@ -31,7 +31,7 @@
     def testJsWrappedPythonFuncPassesContext(self):
         contexts = []
 
-        def func(cx):
+        def func(cx, this, args):
             contexts.append(cx)
             return True
 
@@ -44,14 +44,52 @@
         cx.evaluate_script(obj, code, '<string>', 1)
         self.assertEqual(contexts[0], cx)
 
+    def testJsWrappedPythonFuncPassesThisArg(self):
+        thisObjs = []
+
+        def func(cx, this, args):
+            thisObjs.append(this)
+            return True
+
+        code = "func()"
+        cx = pymonkey.Runtime().new_context()
+        obj = cx.new_object()
+        cx.init_standard_classes(obj)
+        jsfunc = cx.new_function(func, func.__name__)
+        cx.define_property(obj, func.__name__, jsfunc)
+        cx.evaluate_script(obj, code, '<string>', 1)
+        self.assertEqual(thisObjs[0], obj)
+
+    def testJsWrappedPythonFuncPassesFuncArgs(self):
+        funcArgs = []
+
+        def func(cx, this, args):
+            funcArgs.append(args)
+            return True
+
+        cx = pymonkey.Runtime().new_context()
+        obj = cx.new_object()
+        cx.init_standard_classes(obj)
+        jsfunc = cx.new_function(func, func.__name__)
+        cx.define_property(obj, func.__name__, jsfunc)
+
+        cx.evaluate_script(obj, "func()", '<string>', 1)
+        self.assertEqual(len(funcArgs[0]), 0)
+        self.assertTrue(isinstance(funcArgs[0], tuple))
+
+        cx.evaluate_script(obj, "func(1, 'foo')", '<string>', 1)
+        self.assertEqual(len(funcArgs[1]), 2)
+        self.assertEqual(funcArgs[1][0], 1)
+        self.assertEqual(funcArgs[1][1], u'foo')
+
     def testJsWrappedPythonFunctionReturnsUnicode(self):
-        def hai2u(cx):
+        def hai2u(cx, this, args):
             return u"o hai"
         self.assertEqual(self._evalJsWrappedPyFunc(hai2u, 'hai2u()'),
                          u"o hai")
 
     def testJsWrappedPythonFunctionThrowsException(self):
-        def hai2u(cx):
+        def hai2u(cx, this, args):
             raise Exception("hello")
         self.assertRaises(pymonkey.error,
                           self._evalJsWrappedPyFunc,
@@ -60,43 +98,43 @@
                          "hello")
 
     def testJsWrappedPythonFunctionReturnsNone(self):
-        def hai2u(cx):
+        def hai2u(cx, this, args):
             pass
         self.assertEqual(self._evalJsWrappedPyFunc(hai2u, 'hai2u()'),
                          None)
 
     def testJsWrappedPythonFunctionReturnsTrue(self):
-        def hai2u(cx):
+        def hai2u(cx, this, args):
             return True
         self.assertEqual(self._evalJsWrappedPyFunc(hai2u, 'hai2u()'),
                          True)
 
     def testJsWrappedPythonFunctionReturnsFalse(self):
-        def hai2u(cx):
+        def hai2u(cx, this, args):
             return False
         self.assertEqual(self._evalJsWrappedPyFunc(hai2u, 'hai2u()'),
                          False)
 
     def testJsWrappedPythonFunctionReturnsSmallInt(self):
-        def hai2u(cx):
+        def hai2u(cx, this, args):
             return 5
         self.assertEqual(self._evalJsWrappedPyFunc(hai2u, 'hai2u()'),
                          5)
 
     def testJsWrappedPythonFunctionReturnsFloat(self):
-        def hai2u(cx):
+        def hai2u(cx, this, args):
             return 5.1
         self.assertEqual(self._evalJsWrappedPyFunc(hai2u, 'hai2u()'),
                          5.1)
 
     def testJsWrappedPythonFunctionReturnsNegativeInt(self):
-        def hai2u(cx):
+        def hai2u(cx, this, args):
             return -5
         self.assertEqual(self._evalJsWrappedPyFunc(hai2u, 'hai2u()'),
                          -5)
 
     def testJsWrappedPythonFunctionReturnsBigInt(self):
-        def hai2u(cx):
+        def hai2u(cx, this, args):
             return 2147483647
         self.assertEqual(self._evalJsWrappedPyFunc(hai2u, 'hai2u()'),
                          2147483647)
--- a/utils.c	Wed Jul 08 09:32:31 2009 -0700
+++ b/utils.c	Wed Jul 08 18:45:38 2009 -0700
@@ -188,11 +188,12 @@
       JS_SetPendingException(context->cx, val);
     } else
       JS_ReportError(context->cx, "Python exception occurred");
+    Py_DECREF(str);
   }
 
-  Py_DECREF(type);
-  Py_DECREF(value);
-  Py_DECREF(traceback);
+  Py_XDECREF(type);
+  Py_XDECREF(value);
+  Py_XDECREF(traceback);
 }
 
 void