Mercurial > pymonkey
changeset 152:80463c8c7930
Added a 'name' property to function obects. Fixed a TODO.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Sat, 29 Aug 2009 22:46:48 -0700 |
parents | 657afb7307eb |
children | 9ea6a9a566e2 |
files | src/context.cpp src/function.cpp src/function.h src/object.cpp tests/test_pymonkey.py |
diffstat | 5 files changed, 82 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/src/context.cpp Sat Aug 29 14:06:03 2009 -0700 +++ b/src/context.cpp Sat Aug 29 22:46:48 2009 -0700 @@ -564,15 +564,11 @@ } jsval rval; - - // TODO: This assumes that a JSFunction * is actually a subclass of - // a JSObject *, which may or may not be regarded as an implementation - // detail. JSBool result; Py_BEGIN_ALLOW_THREADS; - result = JS_CallFunction(self->cx, obj->obj, - (JSFunction *) fun->base.obj, - argc, argv, &rval); + result = JS_CallFunctionValue(self->cx, obj->obj, + OBJECT_TO_JSVAL(fun->base.obj), + argc, argv, &rval); Py_END_ALLOW_THREADS; PyMem_Free(argv);
--- a/src/function.cpp Sat Aug 29 14:06:03 2009 -0700 +++ b/src/function.cpp Sat Aug 29 22:46:48 2009 -0700 @@ -37,9 +37,18 @@ #include "function.h" #include "utils.h" +#include "structmember.h" + static void PYM_JSFunctionDealloc(PYM_JSFunction *self) { + self->fun = NULL; + + if (self->name) { + Py_DECREF(self->name); + self->name = NULL; + } + PYM_JSObjectType.tp_dealloc((PyObject *) self); } @@ -124,6 +133,12 @@ return JS_TRUE; } +static PyMemberDef PYM_members[] = { + {"name", T_OBJECT, offsetof(PYM_JSFunction, name), READONLY, + "Name of the function."}, + {NULL, NULL, NULL, NULL, NULL} +}; + PyTypeObject PYM_JSFunctionType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ @@ -157,7 +172,7 @@ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ - 0, /* tp_members */ + PYM_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ @@ -170,6 +185,33 @@ }; PYM_JSFunction * +PYM_newJSFunction(PYM_JSContextObject *context, + JSFunction *function) +{ + PYM_JSFunction *jsFunction = PyObject_New(PYM_JSFunction, + &PYM_JSFunctionType); + if (jsFunction == NULL) + return NULL; + + jsFunction->fun = function; + + JSString *name = JS_GetFunctionId(jsFunction->fun); + if (name == NULL) { + // It's an anonymous function. + jsFunction->name = NULL; + } else { + jsFunction->name = PYM_jsvalToPyObject(context, + STRING_TO_JSVAL(name)); + if (jsFunction->name == NULL) { + Py_DECREF((PyObject *) jsFunction); + return NULL; + } + } + + return jsFunction; +} + +PYM_JSFunction * PYM_newJSFunctionFromCallable(PYM_JSContextObject *context, PyObject *callable, const char *name) @@ -195,8 +237,7 @@ return NULL; } - PYM_JSFunction *object = PyObject_New(PYM_JSFunction, - &PYM_JSFunctionType); + PYM_JSFunction *object = PYM_newJSFunction(context, func); if (object == NULL) return NULL;
--- a/src/function.h Sat Aug 29 14:06:03 2009 -0700 +++ b/src/function.h Sat Aug 29 22:46:48 2009 -0700 @@ -45,11 +45,17 @@ typedef struct { PYM_JSObject base; + JSFunction *fun; + PyObject *name; } PYM_JSFunction; extern PyTypeObject PYM_JSFunctionType; extern PYM_JSFunction * +PYM_newJSFunction(PYM_JSContextObject *context, + JSFunction *function); + +extern PYM_JSFunction * PYM_newJSFunctionFromCallable(PYM_JSContextObject *context, PyObject *callable, const char *name);
--- a/src/object.cpp Sat Aug 29 14:06:03 2009 -0700 +++ b/src/object.cpp Sat Aug 29 22:46:48 2009 -0700 @@ -209,8 +209,10 @@ object = subclass; else { if (JS_ObjectIsFunction(context->cx, obj)) { - PYM_JSFunction *func = PyObject_New(PYM_JSFunction, - &PYM_JSFunctionType); + PYM_JSFunction *func = PYM_newJSFunction( + context, + JS_ValueToFunction(context->cx, OBJECT_TO_JSVAL(obj)) + ); object = (PYM_JSObject *) func; } else object = PyObject_New(PYM_JSObject,
--- a/tests/test_pymonkey.py Sat Aug 29 14:06:03 2009 -0700 +++ b/tests/test_pymonkey.py Sat Aug 29 22:46:48 2009 -0700 @@ -125,6 +125,7 @@ stuff['rt'].new_context) self.assertEqual(self.last_exception.args[0], 'Function called from wrong thread') + del stuff['rt'] def testClearObjectPrivateWorks(self): class Foo(object): @@ -251,6 +252,30 @@ del obj self.assertEqual(ref(), None) + def testAnonymousJsFunctionHasNullNameAttribute(self): + cx = pymonkey.Runtime().new_context() + obj = cx.new_object() + cx.init_standard_classes(obj) + jsfunc = cx.evaluate_script(obj, "(function() {})", + "<string>", 1) + self.assertEqual(jsfunc.name, None) + + def testJsFunctionHasNameAttribute(self): + cx = pymonkey.Runtime().new_context() + obj = cx.new_object() + cx.init_standard_classes(obj) + jsfunc = cx.evaluate_script(obj, "(function blarg() {})", + "<string>", 1) + self.assertEqual(jsfunc.name, "blarg") + + def testJsWrappedPythonFuncHasNameAttribute(self): + def func(cx, this, args): + return True + + cx = pymonkey.Runtime().new_context() + jsfunc = cx.new_function(func, "foo") + self.assertEqual(jsfunc.name, "foo") + def testJsWrappedPythonFuncIsGCdAtRuntimeDestruction(self): def define(cx, obj): def func(cx, this, args):