Mercurial > pymonkey
changeset 70:b0360c0ed546
Factored the JS FunctionHolder class into the JS PymonkeyObject class, so that any PymonkeyObject can contain a private Python object if it needs to.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Mon, 27 Jul 2009 04:47:33 -0700 |
parents | c2972e58fbb6 |
children | 9b3f4e53e365 |
files | context.c function.c object.c object.h |
diffstat | 4 files changed, 80 insertions(+), 59 deletions(-) [+] |
line wrap: on
line diff
--- a/context.c Sun Jul 26 16:44:12 2009 -0700 +++ b/context.c Mon Jul 27 04:47:33 2009 -0700 @@ -113,9 +113,9 @@ static PyObject * PYM_newObject(PYM_JSContextObject *self, PyObject *args) { - JSObject *obj = JS_NewObject(self->cx, &PYM_JS_ObjectClass, NULL, NULL); + JSObject *obj = PYM_JS_newObject(self->cx, NULL); if (obj == NULL) { - PyErr_SetString(PYM_error, "JS_NewObject() failed"); + PyErr_SetString(PYM_error, "PYM_JS_newObject() failed"); return NULL; }
--- a/function.c Sun Jul 26 16:44:12 2009 -0700 +++ b/function.c Mon Jul 27 04:47:33 2009 -0700 @@ -37,56 +37,6 @@ #include "function.h" #include "utils.h" -static JSBool -PYM_getHeldFunction(JSContext *cx, JSObject *obj, PyObject **callable) -{ - jsval jsCallable; - if (!JS_GetReservedSlot(cx, obj, 0, &jsCallable)) { - JS_ReportError(cx, "JS_GetReservedSlot() failed."); - return JS_FALSE; - } - *callable = (PyObject *) JSVAL_TO_PRIVATE(jsCallable); - return JS_TRUE; -} - -static void -PYM_finalizeFunctionHolder(JSContext *cx, JSObject *obj) -{ - PYM_PyAutoEnsureGIL gil; - PyObject *callable; - if (PYM_getHeldFunction(cx, obj, &callable)) - Py_DECREF(callable); -} - -// This "Python function holder" JSClass just exists so that it can hold -// a reference to a Python function for as long as the Python function is -// callable from JS-land. As soon as it's garbage collected by the JS -// interpreter, it releases its reference on the Python function. -static JSClass PYM_JS_FunctionHolderClass = { - "PymonkeyFunctionHolder", JSCLASS_HAS_RESERVED_SLOTS(1), - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, - PYM_finalizeFunctionHolder, - JSCLASS_NO_OPTIONAL_MEMBERS -}; - -static JSObject * -PYM_newFunctionHolder(JSContext *cx, PyObject *callable) -{ - JSObject *obj = JS_NewObject(cx, &PYM_JS_FunctionHolderClass, NULL, NULL); - if (obj) { - if (JS_SetReservedSlot(cx, obj, 0, PRIVATE_TO_JSVAL(callable))) - Py_INCREF(callable); - else { - obj = NULL; - PyErr_SetString(PYM_error, "JS_SetReservedSlot() failed"); - } - } else { - PyErr_SetString(PYM_error, "JS_NewObject() failed"); - } - return obj; -} - static void PYM_JSFunctionDealloc(PYM_JSFunction *self) { @@ -103,13 +53,12 @@ PYM_PyAutoEnsureGIL gil; jsval callee = JS_ARGV_CALLEE(argv); jsval functionHolder; - if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(callee), 0, &functionHolder)) { - JS_ReportError(cx, "JS_GetReservedSlot() failed."); + if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(callee), 0, &functionHolder)) return JS_FALSE; - } PyObject *callable; - if (!PYM_getHeldFunction(cx, JSVAL_TO_OBJECT(functionHolder), &callable)) + if (!PYM_JS_getPrivatePyObject(cx, JSVAL_TO_OBJECT(functionHolder), + &callable)) return JS_FALSE; PYM_JSContextObject *context = (PYM_JSContextObject *) @@ -252,9 +201,10 @@ // been decremented by PYM_newJSObject(). return NULL; - JSObject *functionHolder = PYM_newFunctionHolder(context->cx, callable); + JSObject *functionHolder = PYM_JS_newObject(context->cx, callable); if (functionHolder == NULL) { Py_DECREF((PyObject *) object); + PyErr_SetString(PYM_error, "PYM_JS_newObject() failed"); return NULL; }
--- a/object.c Sun Jul 26 16:44:12 2009 -0700 +++ b/object.c Mon Jul 27 04:47:33 2009 -0700 @@ -39,10 +39,72 @@ #include "runtime.h" #include "utils.h" +JSObject * +PYM_JS_newObject(JSContext *cx, PyObject *pyObject) +{ + JSObject *obj = JS_NewObject(cx, &PYM_JS_ObjectClass, NULL, NULL); + if (obj) { + if (!JS_SetReservedSlot(cx, obj, 0, PRIVATE_TO_JSVAL(pyObject))) + return NULL; + Py_XINCREF(pyObject); + } + return obj; +} + +JSBool +PYM_JS_setPrivatePyObject(JSContext *cx, JSObject *obj, PyObject *pyObject) +{ + JSClass *klass = JS_GET_CLASS(cx, obj); + if (klass != &PYM_JS_ObjectClass) { + JS_ReportError(cx, "Object is not an instance of PymonkeyObject"); + return JS_FALSE; + } + + PyObject *old; + if (!PYM_JS_getPrivatePyObject(cx, obj, &old)) + return JS_FALSE; + if (!JS_SetReservedSlot(cx, obj, 0, PRIVATE_TO_JSVAL(pyObject))) + return JS_FALSE; + Py_INCREF(pyObject); + Py_XDECREF(old); + return JS_TRUE; +} + +JSBool +PYM_JS_getPrivatePyObject(JSContext *cx, JSObject *obj, PyObject **pyObject) +{ + JSClass *klass = JS_GET_CLASS(cx, obj); + if (klass != &PYM_JS_ObjectClass) { + JS_ReportError(cx, "Object is not an instance of PymonkeyObject"); + return JS_FALSE; + } + + jsval val; + if (!JS_GetReservedSlot(cx, obj, 0, &val)) + return JS_FALSE; + *pyObject = (PyObject *) JSVAL_TO_PRIVATE(val); + return JS_TRUE; +} + +static void +PYM_JS_finalizeObject(JSContext *cx, JSObject *obj) +{ + PYM_PyAutoEnsureGIL gil; + PyObject *pyObject; + // TODO: What if this fails? + if (PYM_JS_getPrivatePyObject(cx, obj, &pyObject)) + Py_XDECREF(pyObject); +} + +// This one-size-fits-all JSClass is used for any JS objects created +// in Python. It can hold a reference to a Python object for as long as +// its parent JS object is accessible from JS-land. As soon as it's +// garbage collected by the JS interpreter, it releases its reference on +// the Python object. JSClass PYM_JS_ObjectClass = { - "PymonkeyObject", JSCLASS_GLOBAL_FLAGS, + "PymonkeyObject", JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_RESERVED_SLOTS(1), JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, PYM_JS_finalizeObject, JSCLASS_NO_OPTIONAL_MEMBERS };
--- a/object.h Sun Jul 26 16:44:12 2009 -0700 +++ b/object.h Mon Jul 27 04:47:33 2009 -0700 @@ -42,6 +42,15 @@ #include <jsapi.h> #include <Python/Python.h> +extern JSObject * +PYM_JS_newObject(JSContext *cx, PyObject *pyObject); + +extern JSBool +PYM_JS_setPrivatePyObject(JSContext *cx, JSObject *obj, PyObject *pyObject); + +extern JSBool +PYM_JS_getPrivatePyObject(JSContext *cx, JSObject *obj, PyObject **pyObject); + extern JSClass PYM_JS_ObjectClass; typedef struct {