Commits

Paul J. Davis  committed 0d79dc7

More rewriting.

Changed the implementation of PyXDR<T> on advice from Mark Hammond.

  • Participants
  • Parent commits b2211e2

Comments (0)

Files changed (15)

File spidermonkey/convert/function.cpp

 
-#include "convert.h"
+#include <spidermonkey.h>
 
 PyObject*
 js2py_function(Context* cx, jsval val, jsval parent)
 {
-    Function* ret = NULL;
-
     if(parent == JSVAL_VOID || !JSVAL_IS_OBJECT(parent))
     {
         PyErr_BadInternalCall();
-        goto error;
+        return NULL;
     }
     
-    ret = (Function*) make_object(FunctionType, cx, val);
-    if(ret == NULL) goto error;
+    PyXDR<Function> ret = (Function*) make_object(FunctionType, cx, val);
+    if(!ret) return NULL;
 
     ret->parent = parent;
     if(!JS_AddRoot(cx->cx, &(ret->parent)))
     {
         PyErr_SetString(PyExc_RuntimeError, "Failed to add GC root.");
-        goto error;
+        return NULL;
     }
 
-    goto success;
-
-error:
-    Py_XDECREF((PyObject*)ret);
-    ret = NULL; // In case of AddRoot error.
-success:
-    return (PyObject*) ret;
+    Function* ptr = ret.get();
+    ret.release(); // no decref on success
+    return (PyObject*) ptr;
 }

File spidermonkey/convert/integer.cpp

 jsval
 long2js_integer(Context* cx, long pyval)
 {
-    jsval ret = JSVAL_VOID;
-
-    if(INT_FITS_IN_JSVAL(pyval))
-    {
-        ret = INT_TO_JSVAL(pyval);
-        goto done;
-    }
+    if(INT_FITS_IN_JSVAL(pyval)) return INT_TO_JSVAL(pyval);
     
-    if(!JS_NewNumberValue(cx->cx, pyval, &ret))
-    {
-        PyErr_SetString(PyExc_ValueError, "Failed to convert number.");
-        goto done;
-    }
-
-done:
-    return ret;
+    jsval ret;
+    if(JS_NewNumberValue(cx->cx, pyval, &ret)) return ret;
+    
+    PyErr_SetString(PyExc_ValueError, "Failed to convert number.");
+    return JSVAL_VOID;
 }
 
 PyObject*
 js2py_integer(Context* cx, jsval val)
 {
-    int32 rval;
+    int32 ret;
+    if(JS_ValueToInt32(cx->cx, val, &ret)) return PyInt_FromLong(ret);
 
-    if(!JS_ValueToInt32(cx->cx, val, &rval))
-    {
-        PyErr_SetString(PyExc_TypeError, "Invalid JS integer value.");
-        return NULL;
-    }
-
-    return PyInt_FromLong(rval);
+    PyErr_SetString(PyExc_TypeError, "Invalid JS integer value.");
+    return NULL;
 }

File spidermonkey/convert/object.cpp

 
-#include "convert.h"
-#include "javascript/javascript.h"
+#include <spidermonkey.h>
 
 jsval
 py2js_object(Context* cx, PyObject* pyobj)
 {
-    PyObject* hashable = NULL;
-    PyObject* attached = NULL;
-    JSClass* klass = NULL;
-    JSObject* jsobj = NULL;
-    jsval pyval;
-    jsval ret = JSVAL_VOID;
+    // PyObject* hashable = NULL;
+    // PyObject* attached = NULL;
+    // JSClass* klass = NULL;
+    // JSObject* jsobj = NULL;
+    // jsval pyval;
+    // jsval ret = JSVAL_VOID;
    
-    klass = create_class(cx, pyobj);
-    if(klass == NULL) goto error;
+    JSClass* klass = create_class(cx, pyobj);
+    if(klass == NULL)
+    {
+        PyErr_SetString(PyExc_RuntimeError, "Failed to create JS class.");
+        return JSVAL_VOID;
+    }
 
-    jsobj = JS_NewObject(cx->cx, klass, NULL, NULL);
+    JSObject* jsobj = JS_NewObject(cx->cx, klass, NULL, NULL);
     if(jsobj == NULL)
     {
         PyErr_SetString(PyExc_RuntimeError, "Failed to create JS object.");
-        goto error;
+        return JSVAL_VOID;
     }
 
-    // do the attached = pyobj dance to only DECREF if we get passed INCREF
-    attached = pyobj;
-    // INCREF for the value stored in JS
-    Py_INCREF(attached);
-    pyval = PRIVATE_TO_JSVAL(attached);
+    PyObjectXDR attached = pyobj;
+    Py_INCREF(attached.get());
+    jsval pyval = PRIVATE_TO_JSVAL(attached.get());
     if(!JS_SetReservedSlot(cx->cx, jsobj, 0, pyval))
     {
         PyErr_SetString(PyExc_RuntimeError, "Failed to store ref'ed object.");
-        goto error;
+        return JSVAL_VOID;
     }
 
-    hashable = HashCObj_FromVoidPtr(attached);
-    if(hashable == NULL)
+    PyObject* hashable = HashCObj_FromVoidPtr(attached.get());
+    if(!hashable)
     {
         PyErr_SetString(PyExc_RuntimeError, "Failed to make hashable pointer.");
-        goto error;
+        return JSVAL_VOID;
     }
 
     if(Context_add_object(cx, hashable) < 0)
     {
         PyErr_SetString(PyExc_RuntimeError, "Failed to store reference.");
-        goto error;
+        return JSVAL_VOID;
     }
 
-    ret = OBJECT_TO_JSVAL(jsobj);
-    goto success;
-
-error:
-    Py_XDECREF(attached);
-success:
-    return ret;
+    attached.release(); // No decref on success
+    return OBJECT_TO_JSVAL(jsobj);
 }
 
 PyObject*

File spidermonkey/convert/string.cpp

  *
  */
 
-#include "convert.h"
+#include <spidermonkey.h>
 
 JSString*
 py2js_string_obj(Context* cx, PyObject* str)
 {
-    PyObject* conv = NULL;
-    PyObject* encoded = NULL;
-    JSString* ret = NULL;
-    char* bytes;
-    Py_ssize_t len;
-
+    PyObjectXDR conv;
     if(PyString_Check(str))
     {
-        conv = PyUnicode_FromEncodedObject(str, "utf-8", "replace");
-        if(conv == NULL) goto error;
-        str = conv;
+        conv.set(PyUnicode_FromEncodedObject(str, "utf-8", "replace"));
+        if(!conv) return NULL;
+        str = conv.get();
     }
     else if(!PyUnicode_Check(str))
     {
         PyErr_SetString(PyExc_TypeError, "Invalid string conversion.");
-        goto error;
+        return NULL;
     }
 
-    encoded = PyUnicode_AsEncodedString(str, "utf-16", "strict");
-    if(encoded == NULL) goto error;
-    if(PyString_AsStringAndSize(encoded, &bytes, &len) < 0) goto error;
+    PyObjectXDR enc = PyUnicode_AsEncodedString(str, "utf-16", "strict");
+    if(!enc) return NULL;
+
+    char* bytes;
+    Py_ssize_t len;
+    if(PyString_AsStringAndSize(enc.get(), &bytes, &len) < 0)return NULL;
+
     if(len < 2)
     {
         PyErr_SetString(PyExc_ValueError, "Failed to find byte-order mark.");
-        goto error;
+        return NULL;
     }
 
     if(((unsigned short*) bytes)[0] != 0xFEFF)
     {
         PyErr_SetString(PyExc_ValueError, "Invalid UTF-16 BOM");
-        goto error;
+        return NULL;
     }
 
-    ret = JS_NewUCStringCopyN(cx->cx, (jschar*) (bytes+2), (len/2)-1);
-    
-    goto success;
-
-error:
-success:
-    Py_XDECREF(conv);
-    Py_XDECREF(encoded);
-    return ret;
+    return JS_NewUCStringCopyN(cx->cx, (jschar*) (bytes+2), (len/2)-1);
 }
 
 jsval

File spidermonkey/javascript/error.cpp

 
     // This is a borrowed reference, hence no PyObjectXDR so we
     // don't decref it.
-    PyPtr<PyObject> glbl = PyModule_GetDict(SpidermonkeyModule);
+    PyObject* glbl = PyModule_GetDict(SpidermonkeyModule);
 
     if(!src || !func || !glbl || !tpl || !str) return;
 
     if(!code) return;
    
     PyFrameXDR frame = PyFrame_New(
-        PyThreadState_Get(), code.get(), glbl.get(), NULL
+        PyThreadState_Get(), code.get(), glbl, NULL
     );
     if(!frame) return;
     

File spidermonkey/javascript/global.cpp

 JSBool
 del_prop(JSContext* jscx, JSObject* jsobj, jsval key, jsval* rval)
 {
-    PyPtr<Context> pycx = (Context*) JS_GetContextPrivate(jscx);
+    Context* pycx = (Context*) JS_GetContextPrivate(jscx);
     if(!pycx) return js_error(jscx, "Failed to get Python context.");
 
     if(pycx->pyglobal == NULL) return JS_TRUE;
     if(!PyObject_HasAttrString(pycx->pyglobal, "__delitem__")) return JS_TRUE;
 
-    PyObjectXDR pykey = js2py(pycx.get(), key);
+    PyObjectXDR pykey = js2py(pycx, key);
     if(!pykey) return js_error(jscx, "Failed to covert key.");
 
-    if(Context_has_access(pycx.get(), jscx, pycx->pyglobal, pykey.get()) <= 0)
+    if(Context_has_access(pycx, jscx, pycx->pyglobal, pykey.get()) <= 0)
         return js_error(jscx, "Access denied.");
     
     if(PyObject_DelItem(pycx->pyglobal, pykey.get()) < 0)
 JSBool
 get_prop(JSContext* jscx, JSObject* jsobj, jsval key, jsval* rval)
 {
-    PyPtr<Context> pycx = (Context*) JS_GetContextPrivate(jscx);
+    Context* pycx = (Context*) JS_GetContextPrivate(jscx);
     if(!pycx) return js_error(jscx, "Failed to get Python context.");
     
     if(pycx->pyglobal == NULL) return JS_TRUE;
     
-    PyObjectXDR pykey = js2py(pycx.get(), key);
+    PyObjectXDR pykey = js2py(pycx, key);
     if(!pykey) return js_error(jscx, "Failed to convert key.");
     
-    if(Context_has_access(pycx.get(), jscx, pycx->pyglobal, pykey.get()) <= 0)
+    if(Context_has_access(pycx, jscx, pycx->pyglobal, pykey.get()) <= 0)
         return js_error(jscx, "Access denied.");
 
     PyObjectXDR pyval = PyObject_GetItem(pycx->pyglobal, pykey.get());
         return js_error(jscx, "Failed to get value.");
     }
 
-    *rval = py2js(pycx.get(), pyval.get());
+    *rval = py2js(pycx, pyval.get());
     if(*rval == JSVAL_VOID)
         return js_error(jscx, "Failed to convert value.");
     
 JSBool
 set_prop(JSContext* jscx, JSObject* jsobj, jsval key, jsval* rval)
 {
-    PyPtr<Context> pycx = (Context*) JS_GetContextPrivate(jscx);
+    Context* pycx = (Context*) JS_GetContextPrivate(jscx);
     if(!pycx) return js_error(jscx, "Failed to get Python context.");
     
     if(pycx->pyglobal == NULL) return JS_TRUE;
 
-    PyObjectXDR pykey = js2py(pycx.get(), key);
+    PyObjectXDR pykey = js2py(pycx, key);
     if(!pykey) return js_error(jscx, "Failed to convert key.");
 
-    if(Context_has_access(pycx.get(), jscx, pycx->pyglobal, pykey.get()) <= 0)
+    if(Context_has_access(pycx, jscx, pycx->pyglobal, pykey.get()) <= 0)
         return js_error(jscx, "Access denied.");
 
-    PyObjectXDR pyval = js2py(pycx.get(), *rval);
+    PyObjectXDR pyval = js2py(pycx, *rval);
     if(!pyval) return js_error(jscx, "Failed to convert value.");
 
     if(PyObject_SetItem(pycx->pyglobal, pykey.get(), pyval.get()) < 0)
 {
     jsid pid;
 
-    PyPtr<Context> pycx = (Context*) JS_GetContextPrivate(jscx);
+    Context* pycx = (Context*) JS_GetContextPrivate(jscx);
     if(!pycx) return js_error(jscx, "Failed to get Python context.");
 
     if(pycx->pyglobal == NULL) return JS_TRUE;
     
-    PyObjectXDR pykey = js2py(pycx.get(), key);
+    PyObjectXDR pykey = js2py(pycx, key);
     if(!pykey) return js_error(jscx, "Failed to convert key.");
     
-    if(Context_has_access(pycx.get(), jscx, pycx->pyglobal, pykey.get()) <= 0)
+    if(Context_has_access(pycx, jscx, pycx->pyglobal, pykey.get()) <= 0)
         return js_error(jscx, "Access denied.");
 
     if(!PyMapping_HasKey(pycx->pyglobal, pykey.get())) return JS_TRUE;

File spidermonkey/javascript/iterator.cpp

 void
 finalize(JSContext* jscx, JSObject* jsobj)
 {
-    PyPtr<Context> pycx = (Context*) JS_GetContextPrivate(jscx);
+    Context* pycx = (Context*) JS_GetContextPrivate(jscx);
     if(!pycx)
     {
         fprintf(stderr, "*** NO PYTHON CONTEXT ***\n");
 
     Py_DECREF(get_js_slot(jscx, jsobj, 0));
     Py_DECREF(get_js_slot(jscx, jsobj, 1));
-    Py_DECREF(pycx.get());
+    Py_DECREF(pycx);
 }
 
 JSBool
     JSObject* glbl = JS_GetGlobalObject(jscx);
     jsval exc = JSVAL_VOID;
     
-    PyPtr<Context> pycx = (Context*) JS_GetContextPrivate(jscx);
+    Context* pycx = (Context*) JS_GetContextPrivate(jscx);
     if(!pycx) return js_error(jscx, "Failed to get Python context.");
 
-    PyPtr<PyObject> iter = get_js_slot(jscx, jsobj, 1);
-    if(!PyIter_Check(iter.get()))
+    PyObject* iter = get_js_slot(jscx, jsobj, 1);
+    if(!PyIter_Check(iter))
         return js_error(jscx, "Object is not an iterator.");
     
-    PyPtr<PyObject> pyobj = get_js_slot(jscx, jsobj, 0);
+    PyObject* pyobj = get_js_slot(jscx, jsobj, 0);
     if(!pyobj) return js_error(jscx, "Failed to find iterated object.");
 
-    PyObjectXDR next = PyIter_Next(iter.get());
+    PyObjectXDR next = PyIter_Next(iter);
     if(!next && PyErr_Occurred())
         return js_error(jscx, "Failed to get iterator's next value.");
     
     if(!is_for_each(jscx, jsobj, &foreach))
         return js_error(jscx, "Failed to get iterator flag.");
 
-    if(PyMapping_Check(pyobj.get()) && foreach)
+    if(PyMapping_Check(pyobj) && foreach)
     {
-        PyObjectXDR value = PyObject_GetItem(pyobj.get(), next.get());
+        PyObjectXDR value = PyObject_GetItem(pyobj, next.get());
         if(!value) return js_error(jscx, "Failed to get value in 'for each'");
-        *rval = py2js(pycx.get(), value.get());
+        *rval = py2js(pycx, value.get());
     }
     else
     {
-        *rval = py2js(pycx.get(), next.get());
+        *rval = py2js(pycx, next.get());
     }
 
     if(*rval == JSVAL_VOID)
     JSObject* glbl = JS_GetGlobalObject(jscx);
     jsval exc = JSVAL_VOID;
 
-    PyPtr<Context> pycx = (Context*) JS_GetContextPrivate(jscx);
+    Context* pycx = (Context*) JS_GetContextPrivate(jscx);
     if(!pycx) return js_error(jscx, "Failed to get Python context.");
     
-    PyPtr<PyObject> pyobj = get_js_slot(jscx, jsobj, 0);
+    PyObject* pyobj = get_js_slot(jscx, jsobj, 0);
     if(!pyobj) return js_error(jscx, "Failed to get iterated object.");
-    if(!PySequence_Check(pyobj.get()))
+    if(!PySequence_Check(pyobj))
         return js_error(jscx, "Object is not a sequence.");
 
-    long maxval = PyObject_Length(pyobj.get());
+    long maxval = PyObject_Length(pyobj);
     if(maxval < 0) return js_error(jscx, "Failed to get sequence length.");
 
-    PyPtr<PyObject> iter = get_js_slot(jscx, jsobj, 1);
+    PyObject* iter = get_js_slot(jscx, jsobj, 1);
     if(!iter) return js_error(jscx, "Failed to get iteration state.");
-    if(!PyInt_Check(iter.get()))
+    if(!PyInt_Check(iter))
         return js_error(jscx, "Invalid iteration state object.");
 
-    long currval = PyInt_AsLong(iter.get());
+    long currval = PyInt_AsLong(iter);
     if(currval == -1 && PyErr_Occurred())
         return js_error(jscx, "Failed to get iteration state value.");
 
     if(!JS_SetReservedSlot(jscx, jsobj, 1, PRIVATE_TO_JSVAL(next.get())))
         return js_error(jscx, "Failed to store iterator value.");
     Py_INCREF(next.get());
-    Py_DECREF(iter.get());
+    Py_DECREF(iter);
 
     JSBool foreach;
     if(!is_for_each(jscx, jsobj, &foreach))
 
     if(foreach)
     {
-        PyObjectXDR value = PyObject_GetItem(pyobj.get(), iter.get());
+        PyObjectXDR value = PyObject_GetItem(pyobj, iter);
         if(!value) return js_error(jscx, "Failed to get element in 'for each'");
-        *rval = py2js(pycx.get(), value.get());
+        *rval = py2js(pycx, value.get());
     }
     else
     {
-        *rval = py2js(pycx.get(), iter.get());
+        *rval = py2js(pycx, iter);
     }
 
     if(*rval == JSVAL_VOID)
     *rval = OBJECT_TO_JSVAL(jsiter);
 
     // Keep attached alive on success.
-    attached.reset();
+    attached.release();
     return JS_TRUE;
 }
 

File spidermonkey/javascript/object.cpp

 JSBool
 js_del_prop(JSContext* jscx, JSObject* jsobj, jsval key, jsval* rval)
 {
-    PyPtr<Context> pycx = (Context*) JS_GetContextPrivate(jscx);
+    Context* pycx = (Context*) JS_GetContextPrivate(jscx);
     if(!pycx) return js_error(jscx, "Failed to get Python context.");
     
-    PyPtr<PyObject> pyobj = get_py_obj(jscx, jsobj);
+    PyObject* pyobj = get_py_obj(jscx, jsobj);
     if(!pyobj) return js_error(jscx, "Failed to get Python object.");
     
-    PyObjectXDR pykey = js2py(pycx.get(), key);
+    PyObjectXDR pykey = js2py(pycx, key);
     if(!pykey) return js_error(jscx, "Failed to covert object key.");
 
-    if(Context_has_access(pycx.get(), jscx, pyobj.get(), pykey.get()) <= 0)
+    if(Context_has_access(pycx, jscx, pyobj, pykey.get()) <= 0)
         return js_error(jscx, "Access denied.");
 
-    if(PyObject_DelItem(pyobj.get(), pykey.get()) < 0)
+    if(PyObject_DelItem(pyobj, pykey.get()) < 0)
     {
         PyErr_Clear();
-        if(PyObject_DelAttr(pyobj.get(), pykey.get()) < 0)
+        if(PyObject_DelAttr(pyobj, pykey.get()) < 0)
         {
             PyErr_Clear();
             *rval = JSVAL_FALSE;
 JSBool
 js_get_prop(JSContext* jscx, JSObject* jsobj, jsval key, jsval* rval)
 {
-    PyPtr<Context> pycx = (Context*) JS_GetContextPrivate(jscx);
+    Context* pycx = (Context*) JS_GetContextPrivate(jscx);
     if(!pycx) return js_error(jscx, "Failed to get Python context.");
 
-    PyPtr<PyObject> pyobj = get_py_obj(jscx, jsobj);
+    PyObject* pyobj = get_py_obj(jscx, jsobj);
     if(!pyobj) return js_error(jscx, "Failed to get Python object.");
     
-    PyObjectXDR pykey = js2py(pycx.get(), key);
+    PyObjectXDR pykey = js2py(pycx, key);
     if(!pykey) return js_error(jscx, "Failed to convert key.");
     
-    if(Context_has_access(pycx.get(), jscx, pyobj.get(), pykey.get()) <= 0)
+    if(Context_has_access(pycx, jscx, pyobj, pykey.get()) <= 0)
         return js_error(jscx, "Access denied.");
     
     // Yeah. It's ugly as sin.
 
         if(strcmp("__iterator__", data) == 0)
         {
-            if(!new_py_iter(pycx.get(), pyobj.get(), rval))
+            if(!new_py_iter(pycx, pyobj, rval))
                 return JS_FALSE;
             
             if(*rval != JSVAL_VOID)
         }
     }
 
-    PyObjectXDR pyval = PyObject_GetItem(pyobj.get(), pykey.get());
+    PyObjectXDR pyval = PyObject_GetItem(pyobj, pykey.get());
     if(!pyval)
     {        
         PyErr_Clear();
-        pyval = PyObject_GetAttr(pyobj.get(), pykey.get());
+        pyval = PyObject_GetAttr(pyobj, pykey.get());
         if(!pyval)
         {
             PyErr_Clear();
         }
     }
 
-    *rval = py2js(pycx.get(), pyval.get());
+    *rval = py2js(pycx, pyval.get());
     if(*rval == JSVAL_VOID)
         return JS_FALSE;
     

File spidermonkey/python/array.cpp

 Py_ssize_t
 Array_length(Object* self)
 {
-    Py_ssize_t ret = -1;
+    JSRequest req(self->cx->cx);
+
     jsuint length;
-
-    JS_BeginRequest(self->cx->cx);
-
     if(!JS_GetArrayLength(self->cx->cx, self->obj, &length))
     {
         PyErr_SetString(PyExc_AttributeError, "Failed to get array length.");
-        goto done;
+        return -1;
     }
 
-     ret = (Py_ssize_t) length;
-    
-done:
-    JS_EndRequest(self->cx->cx);
-    return ret;
+    return (Py_ssize_t) length;
 }
 
 PyObject*
 Array_get_item(Object* self, Py_ssize_t idx)
 {
-    PyObject* ret = NULL;
-    jsval rval;
-    jsint pos = (jsint) idx;
-
-    JS_BeginRequest(self->cx->cx);
-
+    JSRequest req(self->cx->cx);
+    
     if(idx >= Array_length(self))
     {
         PyErr_SetString(PyExc_IndexError, "List index out of range.");
-        goto done;
+        return NULL;
     }
 
-    if(!JS_GetElement(self->cx->cx, self->obj, pos, &rval))
+    jsval rval;
+    if(!JS_GetElement(self->cx->cx, self->obj, (jsint) idx, &rval))
     {
         PyErr_SetString(PyExc_AttributeError, "Failed to get array item.");
-        goto done;
+        return NULL;
     }
 
-    ret = js2py(self->cx, rval);
-
-done:
-    JS_EndRequest(self->cx->cx);
-    return ret;
+    return js2py(self->cx, rval);
 }
 
 int
 Array_set_item(Object* self, Py_ssize_t idx, PyObject* val)
 {
-    int ret = -1;
-    jsval pval;
-    jsint pos = (jsint) idx;
+    JSRequest req(self->cx->cx);
+    
+    jsval pval = py2js(self->cx, val);
+    if(pval == JSVAL_VOID) return -1;
 
-    JS_BeginRequest(self->cx->cx);
-
-    pval = py2js(self->cx, val);
-    if(pval == JSVAL_VOID) goto done;
-
-    if(!JS_SetElement(self->cx->cx, self->obj, pos, &pval))
+    if(!JS_SetElement(self->cx->cx, self->obj, (jsint) idx, &pval))
     {
         PyErr_SetString(PyExc_AttributeError, "Failed to set array item.");
-        goto done;
+        return -1;
     }
 
-    ret = 0;
-
-done:
-    JS_EndRequest(self->cx->cx);
-    return ret;
+    return 0;
 }
 
 PyObject*

File spidermonkey/python/context.cpp

 int
 Context_has_access(Context* pycx, JSContext* jscx, PyObject* obj, PyObject* key)
 {
-    PyObject* tpl = NULL;
-    PyObject* tmp = NULL;
-    int res = -1;
+    if(pycx->access == NULL) return 1;
 
-    if(pycx->access == NULL)
+    PyObjectXDR tpl = Py_BuildValue("(OO)", obj, key);
+    if(!tpl)
     {
-        res = 1;
-        goto done;
+        PyErr_Clear();
+        return -1;
     }
 
-    tpl = Py_BuildValue("(OO)", obj, key);
-    if(tpl == NULL) goto done;
-
-    tmp = PyObject_Call(pycx->access, tpl, NULL);
-    res = PyObject_IsTrue(tmp);
-
-done:
-    Py_XDECREF(tpl);
-    Py_XDECREF(tmp);
-
-    if(res < 0)
+    PyObjectXDR tmp = PyObject_Call(pycx->access, tpl.get(), NULL);
+    if(!tmp)
     {
         PyErr_Clear();
-        JS_ReportError(jscx, "Failed to check python access.");
+        return -1;
     }
-    else if(res == 0)
-    {
-        JS_ReportError(jscx, "Python access prohibited.");
-    }
-
-    return res;
+    
+    int ret = PyObject_IsTrue(tmp.get());
+    if(ret == 0) JS_ReportError(jscx, "Access denied.");
+    return ret;
 }
 
 PyObject*

File spidermonkey/python/function.cpp

 {
     if(self->parent != JSVAL_VOID)
     {
-        JS_BeginRequest(self->obj.cx->cx);
+        JSRequest req(self->obj.cx->cx);
         JS_RemoveRoot(self->obj.cx->cx, &(self->parent));
-        JS_EndRequest(self->obj.cx->cx);
     }
 
     ObjectType->tp_dealloc((PyObject*) self);

File spidermonkey/python/hashcobj.cpp

 PyObject*
 HashCObj_FromVoidPtr(void *cobj)
 {
-    HashCObj* self = NULL;
-
-    self = PyObject_NEW(HashCObj, HashCObjType);
-    if(self == NULL) goto error;
+    HashCObj* self = PyObject_NEW(HashCObj, HashCObjType);
+    if(self == NULL) return NULL;
     self->cobj = cobj;
-
-    goto success;
-
-error:
-success:
     return (PyObject*) self;
 }
 
     if(!PyObject_TypeCheck(self, HashCObjType))
     {
         PyErr_SetString(PyExc_ValueError, "Invalid comparison object.");
-        goto error;
+        return -1;
     }
 
     if(!PyObject_TypeCheck(other, HashCObjType))
     {
         PyErr_SetString(PyExc_ValueError, "Invalid comparison object 2.");
-        goto error;
+        return -1;
     }
     
     if(((HashCObj*)self)->cobj == ((HashCObj*)other)->cobj)
-    {
-        ret = 0;
-    }
+        return 0;
     else
-    {
-        ret = 1;
-    }
-
-    goto success;
-
-error:
-success:
-    return ret;
+        return 1;
 }
 
 PyObject*
 HashCObj_repr(PyObject* self)
 {
-    return PyString_FromFormat("<%s Ptr: %p>",
-            self->ob_type->tp_name,
-            ((HashCObj*)self)->cobj);
+    return PyString_FromFormat(
+        "<%s Ptr: %p>",
+        self->ob_type->tp_name,
+        ((HashCObj*)self)->cobj
+    );
 }
 
 long

File spidermonkey/python/iterator.cpp

 #include <spidermonkey.h>
 
 PyObject*
-Iterator_Wrap(Context* cx, JSObject* obj)
-{
-    Iterator* self = NULL;
-    PyObject* tpl = NULL;
-    PyObject* ret = NULL;
-
-    JS_BeginRequest(cx->cx);
-
-    // Build our new python object.
-    tpl = Py_BuildValue("(O)", cx);
-    if(tpl == NULL) goto error;
-    
-    self = (Iterator*) PyObject_CallObject((PyObject*) IteratorType, tpl);
-    if(self == NULL) goto error;
-    
-    // Attach a JS property iterator.
-    self->iter = JS_NewPropertyIterator(cx->cx, obj);
-    if(self->iter == NULL) goto error;
-
-    self->root = OBJECT_TO_JSVAL(self->iter);
-    if(!JS_AddRoot(cx->cx, &(self->root)))
-    {
-        PyErr_SetString(PyExc_RuntimeError, "Failed to set GC root.");
-        goto error;
-    }
-
-    ret = (PyObject*) self;
-    goto success;
-
-error:
-    Py_XDECREF(self);
-    ret = NULL; // In case it was AddRoot
-success:
-    Py_XDECREF(tpl);
-    JS_EndRequest(cx->cx);
-    return (PyObject*) ret;
-}
-
-PyObject*
 Iterator_new(PyTypeObject* type, PyObject* args, PyObject* kwargs)
 {
     Context* cx = NULL;
     0,                                          /*tp_alloc*/
     Iterator_new,                               /*tp_new*/
 };
+
+PyObject*
+Iterator_Wrap(Context* cx, JSObject* obj)
+{
+    Iterator* self = NULL;
+    PyObject* tpl = NULL;
+    PyObject* ret = NULL;
+
+    JS_BeginRequest(cx->cx);
+
+    // Build our new python object.
+    tpl = Py_BuildValue("(O)", cx);
+    if(tpl == NULL) goto error;
+    
+    self = (Iterator*) PyObject_CallObject((PyObject*) IteratorType, tpl);
+    if(self == NULL) goto error;
+    
+    // Attach a JS property iterator.
+    self->iter = JS_NewPropertyIterator(cx->cx, obj);
+    if(self->iter == NULL) goto error;
+
+    self->root = OBJECT_TO_JSVAL(self->iter);
+    if(!JS_AddRoot(cx->cx, &(self->root)))
+    {
+        PyErr_SetString(PyExc_RuntimeError, "Failed to set GC root.");
+        goto error;
+    }
+
+    ret = (PyObject*) self;
+    goto success;
+
+error:
+    Py_XDECREF(self);
+    ret = NULL; // In case it was AddRoot
+success:
+    Py_XDECREF(tpl);
+    JS_EndRequest(cx->cx);
+    return (PyObject*) ret;
+}

File spidermonkey/python/object.cpp

 #include <jsobj.h>
 
 PyObject*
-make_object(PyTypeObject* type, Context* cx, jsval val)
-{
-    Object* wrapped = NULL;
-    PyObject* tpl = NULL;
-    PyObject* hashable = NULL;
-    PyObject* ret = NULL;
-    void* raw = NULL;
-    uint32 flags = JSCLASS_HAS_RESERVED_SLOTS(1);
-    JSClass* klass = NULL;
-    JSObject* obj = NULL;
-    jsval priv;
-    int found;
-
-    JS_BeginRequest(cx->cx);
-
-    // Unwrapping if its wrapped.
-    obj = JSVAL_TO_OBJECT(val);
-    klass = JS_GetClass(cx->cx, obj);
-    if(klass != NULL && (klass->flags & flags) == flags)
-    {
-        if(JS_GetReservedSlot(cx->cx, obj, 0, &priv))
-        {
-            raw = (PyObject*) JSVAL_TO_PRIVATE(priv);
-            hashable = HashCObj_FromVoidPtr(raw);
-            if(hashable == NULL) goto error;
-
-            found = Context_has_object(cx, hashable);
-            if(found < 0) goto error;
-            if(found > 0)
-            {
-                ret = (PyObject*) raw;
-                Py_INCREF(ret);
-                goto success;
-            }
-        }
-    }
-
-    // Wrap JS value
-    tpl = Py_BuildValue("(O)", cx);
-    if(tpl == NULL) goto error;
-    
-    wrapped = (Object*) PyObject_CallObject((PyObject*) type, tpl);
-    if(wrapped == NULL) goto error;
-    
-    wrapped->val = val;
-    wrapped->obj = obj;
-
-    if(!JS_AddRoot(cx->cx, &(wrapped->val)))
-    {
-        PyErr_SetString(PyExc_RuntimeError, "Failed to set GC root.");
-        goto error;
-    }
-
-    ret = (PyObject*) wrapped;
-    goto success;
-
-error:
-    Py_XDECREF(wrapped);
-    ret = NULL; // In case it was AddRoot
-
-success:
-    Py_XDECREF(tpl);
-    JS_EndRequest(cx->cx);
-    return (PyObject*) ret;
-}
-
-PyObject*
 Object_new(PyTypeObject* type, PyObject* args, PyObject* kwargs)
 {
     Object* self = NULL;
     0,                                          /*tp_alloc*/
     Object_new,                                 /*tp_new*/
 };
+
+PyObject*
+make_object(PyTypeObject* type, Context* cx, jsval val)
+{
+    Object* wrapped = NULL;
+    PyObject* tpl = NULL;
+    PyObject* hashable = NULL;
+    PyObject* ret = NULL;
+    void* raw = NULL;
+    uint32 flags = JSCLASS_HAS_RESERVED_SLOTS(1);
+    JSClass* klass = NULL;
+    JSObject* obj = NULL;
+    jsval priv;
+    int found;
+
+    JS_BeginRequest(cx->cx);
+
+    // Unwrapping if its wrapped.
+    obj = JSVAL_TO_OBJECT(val);
+    klass = JS_GetClass(cx->cx, obj);
+    if(klass != NULL && (klass->flags & flags) == flags)
+    {
+        if(JS_GetReservedSlot(cx->cx, obj, 0, &priv))
+        {
+            raw = (PyObject*) JSVAL_TO_PRIVATE(priv);
+            hashable = HashCObj_FromVoidPtr(raw);
+            if(hashable == NULL) goto error;
+
+            found = Context_has_object(cx, hashable);
+            if(found < 0) goto error;
+            if(found > 0)
+            {
+                ret = (PyObject*) raw;
+                Py_INCREF(ret);
+                goto success;
+            }
+        }
+    }
+
+    // Wrap JS value
+    tpl = Py_BuildValue("(O)", cx);
+    if(tpl == NULL) goto error;
+    
+    wrapped = (Object*) PyObject_CallObject((PyObject*) type, tpl);
+    if(wrapped == NULL) goto error;
+    
+    wrapped->val = val;
+    wrapped->obj = obj;
+
+    if(!JS_AddRoot(cx->cx, &(wrapped->val)))
+    {
+        PyErr_SetString(PyExc_RuntimeError, "Failed to set GC root.");
+        goto error;
+    }
+
+    ret = (PyObject*) wrapped;
+    goto success;
+
+error:
+    Py_XDECREF(wrapped);
+    ret = NULL; // In case it was AddRoot
+
+success:
+    Py_XDECREF(tpl);
+    JS_EndRequest(cx->cx);
+    return (PyObject*) ret;
+}

File spidermonkey/utils/utils.h

 
 #include <iostream>
 
-template<class T> class PyPtr {
-    public:
-        PyPtr(T* p = 0)
-        {
-            this->data = p;
-        }
-        
-        ~PyPtr() {}
-
-        T*
-        get() const
-        {
-            return this->data;
-        }
-        
-        void
-        reset()
-        {
-            this->data = NULL;
-        }
-
-        T*
-        operator->()
-        {
-            return this->data;
-        }
-        
-        PyPtr<T>&
-        operator=(T* p)
-        {
-            this->data = p;
-            return *this;
-        }
-        
-        PyPtr<T>&
-        operator=(PyPtr<T>& p)
-        {
-            this->data = p.data;
-            p.reset();
-            return *this;
-        }
-    
-        operator bool () const
-        {
-            return this->data != NULL;
-        }
-        
-    protected:
-        T*   data;
-};
-
-template <class T> class PyXDR : public PyPtr<T> {
+template <class T> class PyXDR {
     public:
         PyXDR(T* p = 0)
         {
         {
             Py_XDECREF(this->data);
         }
-        
-        PyXDR<T>&
-        operator=(T* p)
+
+        PyXDR<T>& operator=(T* p)
         {
             this->data = p;
             return *this;
         }
+
+        T* operator->()
+        {
+            return this->data;
+        }
+        
+        operator bool () const
+        {
+            return this->data != NULL;
+        }
+        
+        T* get() const
+        {
+            return this->data;
+        }
+        
+        void set(T* p)
+        {
+            this->data = p;
+        }
+        
+        void release()
+        {
+            this->data = NULL;
+        }
+
+    protected:
+        T* data;
+
 };
 
 typedef PyXDR<PyObject> PyObjectXDR;