diff context.c @ 37:d4efcbb06964

Added a new PYM_JSFunction type, PYM_JSContext.define_property(), and PYM_JSContext.new_function(). Also fixed a memory leak.
author Atul Varma <varmaa@toolness.com>
date Thu, 02 Jul 2009 22:42:31 -0700
parents 3f8a2db496f5
children 6cd870a2b81e
line wrap: on
line diff
--- a/context.c	Thu Jul 02 15:29:07 2009 -0700
+++ b/context.c	Thu Jul 02 22:42:31 2009 -0700
@@ -1,5 +1,6 @@
 #include "context.h"
 #include "object.h"
+#include "function.h"
 #include "utils.h"
 
 static void
@@ -34,7 +35,7 @@
 
   // If this fails, we don't need to worry about cleaning up
   // obj because it'll get cleaned up at the next GC.
-  return (PyObject *) PYM_newJSObject(self, obj);
+  return (PyObject *) PYM_newJSObject(self, obj, NULL);
 }
 
 static PyObject *
@@ -121,87 +122,44 @@
   return pyRval;
 }
 
-static JSBool dispatchJSFunctionToPython(JSContext *cx,
-                                         JSObject *obj,
-                                         uintN argc,
-                                         jsval *argv,
-                                         jsval *rval)
+static PyObject *
+PYM_defineProperty(PYM_JSContextObject *self, PyObject *args)
 {
-  jsval callee = JS_ARGV_CALLEE(argv);
-  jsval jsCallable;
-  if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(callee), 0, &jsCallable)) {
-    JS_ReportError(cx, "JS_GetReservedSlot() failed.");
-    return JS_FALSE;
-  }
-  PyObject *callable = (PyObject *) JSVAL_TO_PRIVATE(jsCallable);
+  PYM_JSObject *object;
+  PyObject *value;
+  const char *name;
+
+  if (!PyArg_ParseTuple(args, "O!sO", &PYM_JSObjectType, &object,
+                        &name, &value))
+    return NULL;
+
+  jsval jsValue;
 
-  // TODO: Convert args and 'this' parameter.
-  PyObject *args = PyTuple_New(0);
-  if (args == NULL) {
-    JS_ReportOutOfMemory(cx);
-    return JS_FALSE;
+  if (PYM_pyObjectToJsval(self->cx, value, &jsValue) == -1)
+    return NULL;
+
+  // TODO: Support unicode naming.
+  if (!JS_DefineProperty(self->cx, object->obj, name, jsValue,
+                         NULL, NULL, JSPROP_ENUMERATE)) {
+    // TODO: There's probably an exception pending on self->cx,
+    // what should we do about it?
+    PyErr_SetString(PYM_error, "JS_DefineProperty() failed");
+    return NULL;
   }
 
-  PyObject *result = PyObject_Call(callable, args, NULL);
-  if (result == NULL) {
-    // TODO: Get the actual exception.
-    JS_ReportError(cx, "Python function failed.");
-    return JS_FALSE;
-  }
-
-  int error = PYM_pyObjectToJsval(cx, result, rval);
-  Py_DECREF(result);
-
-  if (error) {
-    // TODO: Get the actual exception.
-    JS_ReportError(cx, "Python function failed.");
-    return JS_FALSE;
-  }
-  return JS_TRUE;
+  Py_RETURN_NONE;
 }
 
 static PyObject *
-PYM_defineFunction(PYM_JSContextObject *self, PyObject *args)
+PYM_newFunction(PYM_JSContextObject *self, PyObject *args)
 {
-  PYM_JSObject *object;
   PyObject *callable;
   const char *name;
 
-  if (!PyArg_ParseTuple(args, "O!Os", &PYM_JSObjectType, &object,
-                        &callable, &name))
+  if (!PyArg_ParseTuple(args, "Os", &callable, &name))
     return NULL;
 
-  if (!PyCallable_Check(callable)) {
-    PyErr_SetString(PyExc_TypeError, "Callable must be callable");
-    return NULL;
-  }
-
-  // TODO: Support unicode naming.
-  JSFunction *func = JS_DefineFunction(self->cx, object->obj, name,
-                                       dispatchJSFunctionToPython,
-                                       0, JSPROP_ENUMERATE);
-  if (func == NULL) {
-    PyErr_SetString(PYM_error, "JS_DefineFunction() failed");
-    return NULL;
-  }
-
-  JSObject *funcObj = JS_GetFunctionObject(func);
-
-  if (funcObj == NULL) {
-    PyErr_SetString(PYM_error, "JS_GetFunctionObject() failed");
-    return NULL;
-  }
-
-  if (!JS_SetReservedSlot(self->cx, funcObj, 0,
-                          PRIVATE_TO_JSVAL(callable))) {
-    PyErr_SetString(PYM_error, "JS_SetReservedSlot() failed");
-    return NULL;
-  }
-
-  // TODO: When to decref?
-  Py_INCREF(callable);
-
-  Py_RETURN_NONE;
+  return (PyObject *) PYM_newJSFunction(self, callable, name);
 }
 
 static PyMethodDef PYM_JSContextMethods[] = {
@@ -217,9 +175,12 @@
    "Evaluate the given JavaScript code in the context of the given "
    "global object, using the given filename"
    "and line number information."},
-  {"define_function",
-   (PyCFunction) PYM_defineFunction, METH_VARARGS,
-   "Defines a function callable from JS."},
+  {"new_function",
+   (PyCFunction) PYM_newFunction, METH_VARARGS,
+   "Creates a new function callable from JS."},
+  {"define_property",
+   (PyCFunction) PYM_defineProperty, METH_VARARGS,
+   "Defines a property on an object."},
   {"get_property", (PyCFunction) PYM_getProperty, METH_VARARGS,
    "Gets the given property for the given JavaScript object."},
   {NULL, NULL, 0, NULL}