<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>LICENSE</filename>
    </added>
    <added>
      <filename>README.md</filename>
    </added>
    <added>
      <filename>spidermonkey/jsbool.pxi</filename>
    </added>
    <added>
      <filename>spidermonkey/spidermonkey.c</filename>
    </added>
    <added>
      <filename>spidermonkey/spidermonkey.dep</filename>
    </added>
    <added>
      <filename>tests/bind_test.py</filename>
    </added>
    <added>
      <filename>tests/bind_test.pyc</filename>
    </added>
    <added>
      <filename>tests/class_test.py</filename>
    </added>
    <added>
      <filename>tests/class_test.pyc</filename>
    </added>
    <added>
      <filename>tests/context_test.py</filename>
    </added>
    <added>
      <filename>tests/context_test.pyc</filename>
    </added>
    <added>
      <filename>tests/define_function_test.py</filename>
    </added>
    <added>
      <filename>tests/define_function_test.pyc</filename>
    </added>
    <added>
      <filename>tests/error_test.py</filename>
    </added>
    <added>
      <filename>tests/error_test.pyc</filename>
    </added>
    <added>
      <filename>tests/roundtrip_test.py</filename>
    </added>
    <added>
      <filename>tests/roundtrip_test.pyc</filename>
    </added>
    <added>
      <filename>tests/test.pyc</filename>
    </added>
    <added>
      <filename>tests/to_python_test.py</filename>
    </added>
    <added>
      <filename>tests/to_python_test.pyc</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,9 +1,8 @@
 include MANIFEST.in
-include COPYING
+include LICENSE
 include README
-include ChangeLog
-include *.pyx
+include spidermonkey/*.c
+include spidermonkey/*.pyx
+include spidermonkey/*.pxi
 include setup.py
-include test.py
-include support.c
-include spidermonkey.c
+include tests/*.py</diff>
      <filename>MANIFEST.in</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,15 @@
+&quot;&quot;&quot;\
+Python/JavaScript bridge module, making use of Mozilla's spidermonkey
+JavaScript implementation.  Allows implementation of JavaScript classes,
+objects and functions in Python, and evaluation and calling of JavaScript
+scripts and functions respectively.  Borrows heavily from Claes Jacobssen's
+Javascript Perl module, in turn based on Mozilla's 'PerlConnect' Perl binding.
+&quot;&quot;&quot;,
+
 import os
-import sys
-import glob
-from distutils.core import setup, Extension
-from distutils.command.clean import clean
-from distutils.command.install import install
-from distutils.file_util import copy_file
+import ez_setup
+ez_setup.use_setuptools()
+from setuptools import setup, Extension
 
 try:
     import Pyrex.Compiler.Main as Compiler
@@ -12,32 +17,55 @@ try:
 except ImportError:
     print &quot;Pyrex not found: Skipping source generation.&quot;
 
-arch = os.uname()[0].lower()
-jslib = {&quot;darin&quot;: &quot;js&quot;, &quot;linux&quot;: &quot;mozjs&quot;}.get(arch, &quot;js&quot;)
-if not jslib:
-    sys.stderr.write(&quot;Failed to guess what JavaScript lib you might be using.&quot;)
+def get_js_lib():
+    arch = os.uname()[0].lower()
+    jslib = {
+        &quot;darwin&quot;: &quot;js&quot;,
+        &quot;linux&quot;: &quot;mozjs&quot;
+    }.get(arch, None)
+    if not jslib:
+        print &quot;Failed to guess what JavaScript lib you might be using.&quot;
+    return jslib
 
-setup(name = &quot;spidermonkey&quot;,
-    version = &quot;0.0.1a&quot;,
-    license = &quot;GPL&quot;,
-    author = &quot;John J. Lee&quot;,
-    author_email = &quot;jjl@pobox.com&quot;,
+setup(
+    name = &quot;spidermonkey&quot;,
+    version = &quot;0.1&quot;,
+    license = &quot;MIT&quot;,
+    author = &quot;Paul J. Davis&quot;,
+    author_email = &quot;paul.joseph.davis@gmail.com&quot;,
     description = &quot;JavaScript / Python bridge.&quot;,
-    url = &quot;http://code.google.com/p/python-spidermonkey/&quot;,
-    long_description = &quot;&quot;&quot;\
-Python/JavaScript bridge module, making use of Mozilla's spidermonkey
-JavaScript implementation.  Allows implementation of JavaScript classes,
-objects and functions in Python, and evaluation and calling of JavaScript
-scripts and functions respectively.  Borrows heavily from Claes Jacobssen's
-Javascript Perl module, in turn based on Mozilla's 'PerlConnect' Perl binding.
-&quot;&quot;&quot;,
+    long_description = __doc__,
+    url = &quot;http://github.com/davisp/python-spidermonkey&quot;,
+    zip_safe = False
+    
+    classifiers = [
+        'Development Status :: 3 - Alpha',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: MIT License',
+        'Operating System :: OS Independent',
+        'Programming Language :: Python',
+        'Programming Lnaguage :: JavaScript',
+        'Topic :: Software Development :: Libraries :: Python Modules',
+    ],
+
+    setup_requires = [
+        'setuptools&gt;=0.6c8'
+    ],
+
+    install_requires = [
+        'couchdb', 
+        'Hypy',
+        'spidermonkey',
+    ],
+    
     ext_modules =  [
-        Extension(&quot;spidermonkey&quot;,
+        Extension(
+            &quot;spidermonkey&quot;,
             sources=[&quot;spidermonkey/spidermonkey.c&quot;],
             extra_compile_args=[&quot;-DXP_UNIX&quot;, &quot;-DJS_THREADSAFE&quot;],
             include_dirs=[&quot;/usr/include/js&quot;, &quot;/usr/local/include/js&quot;, &quot;/usr/include/mozjs&quot;, &quot;/opt/local/include/js&quot;],
             library_dirs=[&quot;/usr/lib&quot;, &quot;/usr/local/lib&quot;, &quot;/opt/local/lib&quot;],
-            libraries=[&quot;m&quot;, &quot;pthread&quot;, jslib]
+            libraries=[&quot;m&quot;, &quot;pthread&quot;, get_js_lib()]
         )
     ]
 )</diff>
      <filename>setup.py</filename>
    </modified>
    <modified>
      <diff>@@ -15,6 +15,9 @@ ELSE:
     ctypedef int jsval
 ctypedef int JSBool
 
+cdef extern from &quot;stdio.h&quot;:
+    cdef int printf(char* format, ...)
+
 cdef extern from &quot;string.h&quot;:
     cdef char* strcpy(char* restrict, char* restrict)
 
@@ -216,6 +219,7 @@ cdef extern from &quot;jsapi.h&quot;:
     )
     
     cdef JSClass* JS_GetClass(JSContext* cx, JSObject* obj)
+    cdef JSObject* JS_GetPrototype(JSContext* cx, JSObject* obj)
     cdef JSIdArray* JS_Enumerate(JSContext* cx, JSObject* obj)
     cdef void* JS_GetPrivate(JSContext* cx, JSObject* obj)
     cdef JSBool JS_SetPrivate(JSContext* cx, JSObject* obj, void* data)
@@ -223,6 +227,7 @@ cdef extern from &quot;jsapi.h&quot;:
     # Property Methods
     cdef JSBool JS_GetProperty(JSContext* cx, JSObject* obj, char* name, jsval* vp)
     cdef JSBool JS_SetProperty(JSContext* cx, JSObject* obj, char* name, jsval* vp)
+    cdef JSBool JS_DeleteProperty(JSContext* cx, JSObject* obj, char* name)
 
     cdef JSBool JS_DefineProperty(
         JSContext* cx,
@@ -257,6 +262,12 @@ cdef extern from &quot;jsapi.h&quot;:
     cdef JSObject* JS_GetFunctionObject(JSFunction* fun)
     cdef JSFunction* JS_ValueToFunction(JSContext* cx, jsval v)
     
+    # Not necessarily specific to functions, but used for the undocumented
+    # reserved slots.
+    JSBool JS_GetReservedSlot(JSContext* cx, JSObject* obj, uint32 index, jsval* vp)
+    JSBool JS_SetReservedSlot(JSContext* cx, JSObject* obj, uint32 index, jsval v)
+    
+    
     # Set a list of functions on an object
     cdef JSBool JS_DefineFunctions(JSContext* cx, JSObject* obj, JSFunctionSpec* fs)
     
@@ -306,8 +317,7 @@ cdef extern from &quot;jsapi.h&quot;:
     cdef size_t JS_GetStringLength(JSString* str)
 
     # Double Functions
-    cdef jsdouble* JS_NewDouble(JSContext* cx, jsdouble d)
-    cdef JSBool JS_NewDoubleValue(JSContext* cx, jsdouble d, jsval* rval)
+    cdef JSBool JS_NewNumberValue(JSContext* cx, jsdouble d, jsval* rval)
 
     # IdArray Functions
     cdef JSBool JS_IdToValue(JSContext* cx, jsid id, jsval* vp)
@@ -346,12 +356,19 @@ cdef extern from &quot;jshelpers.c&quot;:
     cdef JSObject* js_make_global_object(JSContext *cx)
 
     cdef void js_context_attach(JSContext* cx, PyObject* obj)
+    cdef JSBool js_context_has_data(JSContext* cx)
     cdef object js_context_fetch(JSContext* cx)
     cdef object js_context_destroy(JSContext* cx)
 
-    cdef void js_object_attach(JSObject* js_obj, PyObject* obj)
-    cdef object js_object_fetch(JSObject* js_obj)
-    cdef object js_object_destroy(JSObject* js_obj)
+    cdef void js_object_attach(JSContext* cx, JSObject* js_obj, PyObject* obj)
+    cdef JSBool js_object_has_data(JSContext* cx, JSObject* js_obj)
+    cdef object js_object_fetch(JSContext* cx, JSObject* js_obj)
+    cdef object js_object_destroy(JSContext* cx, JSObject* js_obj)
+
+    cdef void js_function_attach(JSContext* cx, JSObject* js_obj, PyObject* obj)
+    cdef JSBool js_function_has_data(JSContext* cx, JSObject* js_obj)
+    cdef object js_function_fetch(JSContext* cx, JSObject* js_obj)
+    cdef object js_function_destroy(JSContext* cx, JSObject* js_obj)
 
 cdef void *xmalloc(size_t size) except NULL:
     cdef void *mem
@@ -370,6 +387,18 @@ cdef class Value
 # Python -&gt; JavaScript
 cdef class ClassAdapter
 cdef class ObjectAdapter
-
-class JSError(Exception): pass
+cdef class FunctionAdapter
+
+import inspect
+import sys
+import traceback
+import types
+
+class JSError(Exception):
+    def __init__(self, mesg):
+        self.mesg = mesg
+    def __str__(self):
+        return repr(self)
+    def __repr__(self):
+        return &quot;JavaScript Error: %s&quot; % self.mesg
 </diff>
      <filename>spidermonkey/jsapi.pxi</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 
 def js_is_array(Context cx, jsval v):
     cdef JSObject* obj
-    if not JSVAL_ISOBJECT(v):
+    if not JSVAL_IS_OBJECT(v):
         return False
     obj = JSVAL_TO_OBJECT(v)
     return JS_IsArrayObject(cx.cx, obj)
@@ -17,7 +17,7 @@ cdef object js2py_array(Context cx, jsval v):
     cdef list ret
     
     jsobj = JSVAL_TO_OBJECT(v)
-    nr_elems = JS_GetArrayLength(cx.cx, jsobj, &amp;nr_elems)
+    JS_GetArrayLength(cx.cx, jsobj, &amp;nr_elems)
     ret = [None] * nr_elems
 
     for i from 0 &lt;= i &lt; nr_elems:</diff>
      <filename>spidermonkey/jsarray.pxi</filename>
    </modified>
    <modified>
      <diff>@@ -1,34 +1,42 @@
 
-cdef JSBool __constructor_callback__(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval):
+cdef JSBool __constructor_callback__(JSContext* cx, JSObject* js_obj, uintN argc, jsval* argv, jsval* rval):
     cdef Context pycx
     cdef ClassAdapter adapter
-    cdef ObjectAdapter objadapter
-    cdef JSObject* instobj
+    cdef ObjectAdapter oa
+    cdef JSObject* proto
     cdef int i
     
     try:
+        if not js_context_has_data(cx):
+            raise JSError(&quot;Unknown JSContext object.&quot;)
+        
+        proto = JS_GetPrototype(cx, js_obj)
+        if proto == NULL:
+            raise JSError(&quot;Object has no prototype.&quot;)
+        
+        if not js_object_has_data(cx, proto):
+            raise JSError(&quot;Unknown constructor callback.&quot;)
+        
         pycx = js_context_fetch(cx)
-        adapter = js_object_fetch(obj)
+        adapter = js_object_fetch(cx, proto)
         
         args = []
         for i from 0 &lt;= i &lt; argc:
             args.append(js2py(pycx, argv[i]))
 
-        if hasattr(adaptor, &quot;__jsinit__&quot;):
-            py_rval = adaptor.py_class.__jsinit__(pycx, *args)
+        if hasattr(adapter.py_class, &quot;__jsinit__&quot;):
+            py_rval = adapter.py_class.__jsinit__(pycx, *args)
         else:
-            py_rval = adaptor.py_class(pycx, *args)
+            py_rval = adapter.py_class(*args)
 
         rval[0] = py2js(pycx, py_rval, NULL)
 
         # Register after conversion so we don't keep it around
         # if conversion fails.
         if JSVAL_IS_OBJECT(rval[0]):
-            objadapter = ObjectAdapter(pycx, adapter, None, py_rval)
-            instobj = JSVAL_TO_OBJECT(rval[0])
-            js_object_attach(instobj, &lt;PyObject*&gt; py_rval)
-            objadapter.js_obj = instobj
-        pycx.register(py_rval)
+            oa = ObjectAdapter(pycx, adapter, None, py_rval)
+            oa.js_obj = js_obj
+            js_object_attach(cx, js_obj, &lt;PyObject*&gt; oa)
         
         return JS_TRUE
     except:
@@ -40,12 +48,19 @@ cdef JSBool __resolve_global_callback__(JSContext* cx, JSObject* js_obj, jsval j
     cdef object py_obj
     cdef object key
     cdef int i
-
+    
     try:
+        if not js_context_has_data(cx):
+            raise JSError(&quot;Unknown JSContext object.&quot;)
+
         pycx = js_context_fetch(cx)
-        adapter = js_object_fetch(js_obj)
-        py_obj = adapter.obj
         key = js2py(pycx, jsv)
+                    
+        if not js_object_has_data(cx, js_obj):
+            return JS_TRUE;
+        
+        adapter = js_object_fetch(cx, js_obj)
+        py_obj = adapter.py_obj
         
         if isinstance(key, types.StringTypes) and hasattr(py_obj, key):
             # Bind to root object.
@@ -54,6 +69,7 @@ cdef JSBool __resolve_global_callback__(JSContext* cx, JSObject* js_obj, jsval j
 
         return JS_TRUE
     except:
+        traceback.print_exc()
         return report_python_error(cx)
 
 cdef JSBool __get_property_callback__(JSContext* cx, JSObject* js_obj, jsval jsv, jsval* rval):
@@ -64,25 +80,33 @@ cdef JSBool __get_property_callback__(JSContext* cx, JSObject* js_obj, jsval jsv
     cdef object attr
 
     try:
+        if not js_context_has_data(cx):
+            raise JSError(&quot;Unknown JSContext object.&quot;)
+
         pycx = js_context_fetch(cx)
-        adapter = js_object_fetch(js_obj)
-        py_obj = adapter.obj
         key = js2py(pycx, jsv)
         
+        if not js_object_has_data(cx, js_obj):
+            return JS_TRUE
+        
+        adapter = js_object_fetch(cx, js_obj)
+        py_obj = adapter.py_obj
+        
         if isinstance(key, (types.IntType, types.LongType)):
             try:
-                attr = getattr(py_obj, key)
-                rval[0] = py2js(pycx, attr, NULL)
-                pycx.register_py(attr)
+                attr = py_obj[key]
             except:
-                rval[0] = JS_VOID
-        elif isinstance(key, types.StringTypes) and hasattr(py_obj, key):
-            try:
-                attr = getattr(py_obj, key)
+                pass
+            else:
                 rval[0] = py2js(pycx, attr, NULL)
-                pycx.register_py(attr)
-            except:
-                rval[0] = JS_VOID
+        elif isinstance(key, types.StringTypes):
+            if key[:1] != &quot;_&quot;:
+                try:
+                    attr = getattr(py_obj, key)
+                except:
+                    pass
+                else:
+                    rval[0] = py2js(pycx, attr, js_obj)
         elif key is None:
             rval[0] = JS_VOID
         else:
@@ -90,6 +114,7 @@ cdef JSBool __get_property_callback__(JSContext* cx, JSObject* js_obj, jsval jsv
             
         return JS_TRUE
     except:
+        traceback.print_exc()
         return report_python_error(cx)
 
 cdef JSBool __set_property_callback__(JSContext* cx, JSObject* js_obj, jsval jsv, jsval rval[0]):
@@ -100,23 +125,32 @@ cdef JSBool __set_property_callback__(JSContext* cx, JSObject* js_obj, jsval jsv
     cdef object val
 
     try:
+        if not js_context_has_data(cx):
+            raise JSError(&quot;Unknown JSContext object.&quot;)
+
         pycx = js_context_fetch(cx)
-        adapter = js_object_fetch(js_obj)
-        py_obj = adapter.py_obj
         key = js2py(pycx, jsv)
         value = js2py(pycx, rval[0])
+        
+        if not js_object_has_data(cx, js_obj):
+            return JS_TRUE
+        
+        adapter = js_object_fetch(cx, js_obj)
+        py_obj = adapter.py_obj
 
         if isinstance(key, (types.IntType, types.LongType)):
             py_obj[key] = value
-        elif isinstance(key, types.StringTypes) and hasattr(py_obj, key):
-            attr = getattr(py_obj, key)
-            if not callable(attr):
-                setattr(py_obj, key, value)
+        elif isinstance(key, types.StringTypes):
+            if key[:1] != &quot;_&quot; and hasattr(py_obj, key):
+                attr = getattr(py_obj, key)
+                if not callable(attr):
+                    setattr(py_obj, key, value)
         else:
             raise AssertionError(&quot;Invalid key: %r&quot; % key)
 
         return JS_TRUE
     except:
+        traceback.print_exc()
         return report_python_error(cx)
 
 
@@ -125,8 +159,14 @@ cdef void __finalize_callback__(JSContext* cx, JSObject* js_obj):
     cdef ObjectAdapter py_obj
 
     try:
+        if not js_context_has_data(cx):
+            raise JSError(&quot;Unknown JSContext object.&quot;)
+        
+        if not js_object_has_data(cx, js_obj):
+            raise JSError(&quot;Unknown JSObject.&quot;)
+        
         pycx = js_context_fetch(cx)
-        py_obj = js_object_destroy(js_obj)
+        py_obj = js_object_destroy(cx, js_obj)
     except:
         report_python_error(cx)
 
@@ -142,20 +182,23 @@ cdef class ClassAdapter:
     cdef JSClass* js_class
     cdef object py_class
 
-    def __cinit__(ClassAdapter self, Context cx, ObjectAdapter parent, py_class, bind_constructur, is_global, flags):
-        cdef JSObject* obj
+    def __cinit__(ClassAdapter self, Context cx, ObjectAdapter parent, py_class, bind_constructor, is_global, flags):
+        cdef JSObject* proto
         
         self.cx = cx
         self.parent = parent
         self.py_class = py_class
         
-        name = js_classname(py_class)
+        if hasattr(py_class, &quot;__jsname__&quot;):
+            name = py_class.__jsname__
+        else:
+            name = js_classname(py_class)
 
         self.js_class = &lt;JSClass*&gt; xmalloc(sizeof(JSClass))
         self.js_class.name = &lt;char*&gt; xmalloc((len(name) + 1) * sizeof(char))
         strcpy(self.js_class.name, name)
 
-        self.js_class.flags = flags
+        self.js_class.flags = flags | JSCLASS_HAS_PRIVATE
         self.js_class.addProperty = JS_PropertyStub
         self.js_class.delProperty = JS_PropertyStub
         self.js_class.getProperty = __get_property_callback__
@@ -178,27 +221,17 @@ cdef class ClassAdapter:
             self.js_class.resolve = JS_ResolveStub
         
         if bind_constructor:
-            if JS_InitClass(self.cx.cx, parent.js_obj, NULL, self.js_class,
-                            __constructor_callback__, 0, NULL, NULL, NULL, NULL) == NULL: 
+            proto = JS_InitClass(self.cx.cx, parent.js_obj, NULL, self.js_class,
+                            __constructor_callback__, 0, NULL, NULL, NULL, NULL)
+            if proto == NULL:
                 raise JSError(&quot;Failed to bind Python adapter class.&quot;)
+            js_object_attach(cx.cx, proto, &lt;PyObject*&gt; self)
 
-        js_object_attach(obj, &lt;PyObject*&gt; self)
+    def __repr__(self):
+        return &quot;&lt;spidermonkey.ClassAdapter: %r&gt;&quot; % self.py_class
 
     def __dealloc__(self):
-        free(self.js_class.name)
-        free(self.js_class)
-
-    def as_value(Context self):
-        cdef JSObject* obj
-        obj = JS_GetClassObject(self.js_class)
-        return js_create_value(OBJECT_TO_JSVAL(obj))
-
-
-
-
-
-
-
-
-
-
+        if self.js_class:
+            if self.js_class.name:
+                free(self.js_class.name)
+            free(self.js_class)</diff>
      <filename>spidermonkey/jsclass.pxi</filename>
    </modified>
    <modified>
      <diff>@@ -1,11 +1,15 @@
 
+class JSRootObject(object):
+    pass
+
 cdef class Context:
     cdef JSContext* cx
     cdef Runtime rt
     cdef ObjectAdapter root
     cdef GC gc
     cdef object reg
-    cdef object err
+    cdef object classes
+    cdef object error
 
     def __cinit__(self, Runtime rt, root):
         self.rt = rt
@@ -17,30 +21,29 @@ cdef class Context:
             raise JSError(&quot;Failed to create Context&quot;)
 
     def __init__(Context self, Runtime rt, root):
-        cdef JSObject* obj
+        cdef ClassAdapter ca
+        cdef JSObject* js_obj
+        cdef PyObject* py_obj
 
         self.gc = GC(self)
-        self.reg = Registry()
-        self.err = None
-
         self.reg = {}
+        self.classes = {}
+        self.error = None
 
         js_context_attach(self.cx, &lt;PyObject*&gt; self)
 
-        if root:
-            ca = self.install_class(root.__class__, False, True)
-            self.root = ObjectAdapter(self, ca, None)
-            if not self.root:
-                raise JSError(&quot;Failed to bind global object.&quot;)
-        else:
-            obj = js_make_global_object(self.cx)
-            self.root = ObjectAdapter(self, None, None, None)
-            js_object_attach(obj, &lt;PyObject*&gt; None)
-            self.root.js_obj = obj
-            if not self.root:
-                raise JSError(&quot;Failed to create default global object.&quot;)
+        if not root:
+            root = JSRootObject()
+    
+        ca = self.install_class(root.__class__, False, True)
+        js_obj = JS_NewObject(self.cx, ca.js_class, NULL, NULL)
+        if js_obj == NULL:
+            raise JSError(&quot;Failed to create root object.&quot;)
+        self.root = ObjectAdapter(self, ca, None, root)
+        self.root.js_obj = js_obj
+        js_object_attach(self.cx, self.root.js_obj, &lt;PyObject*&gt; self.root)
         
-        if not JS_InitStandardClasses(self.cx, self.root.js_obj):
+        if not JS_InitStandardClasses(self.cx, js_obj):
             raise JSError(&quot;Failed to initialize standard classes.&quot;)
         
         JS_SetErrorReporter(self.cx, __report_error_callback__)
@@ -52,16 +55,19 @@ cdef class Context:
         &quot;&quot;&quot;\
         Install a Python class into the JavaScript runtime.
         &quot;&quot;&quot;
-        if not inspect.isclass(klass):
-            raise TypeError(&quot;Unable to install %r as a class.&quot; % klass)
-        if not isinteger(flags):
+        if not inspect.isclass(py_class):
+            raise TypeError(&quot;Unable to install %r as a class.&quot; % py_class)
+        if not isinstance(flags, (types.IntType, types.LongType)):
             raise TypeError(&quot;Flags is not an integer.&quot;)
 
-        c = ClassAdaptor(self, python_class, bind_constructor, is_global, flags)
-        self.classes[c.to_value()] = c
-        return c
+        if py_class in self.classes:
+            return self.classes[py_class]
+        
+        ca = ClassAdapter(self, self.root, py_class, bind_constructor, is_global, flags)
+        self.classes[py_class] = ca
+        return ca
 
-    def bind(Context self, name, obj, parent=None):
+    def bind(Context self, name, obj):
         &quot;&quot;&quot;\
         Attach a Python object to the JavaScript runtime.
         
@@ -81,12 +87,18 @@ cdef class Context:
         if not isinstance(name, types.StringTypes):
             raise TypeError(&quot;Name must be a string.&quot;)
 
-        ca = self.install_class(obj)
+        ca = self.install_class(obj.__class__)
         jsv = py2js(self, obj, self.root.js_obj)
         if not JS_DefineProperty(self.cx, self.root.js_obj, name, jsv,
                                     __get_property_callback__, __set_property_callback__, 0):
             raise JSError(&quot;Failed to bind Python object to the global object.&quot;)
 
+    def unbind(Context self, name):
+        ret = self.execute(&quot;%s;&quot; % name)
+        if not JS_DeleteProperty(self.cx, self.root.js_obj, name):
+            raise JSError(&quot;Failed to unbind property: %s&quot; % name)
+        return ret
+
     def execute(Context self, object script):
         &quot;&quot;&quot;\
         Execute JavaScript source code.
@@ -97,24 +109,13 @@ cdef class Context:
                 raise TypeError(&quot;Script must be a string.&quot;)
 
             if not JS_EvaluateScript(self.cx, self.root.js_obj, script, len(script), &quot;Python&quot;, 0, &amp;rval):
-                raise JSError(&quot;Failed to execute script: %s&quot; % self._error)
+                raise JSError(self.error)
         
             return js2py(self, rval)
         finally:
-            self._gc.maybe()
+            self.gc.run_maybe()
 
-    def register(Context self, object obj):
-        &quot;&quot;&quot;\
-        Register a Python object in the context so that it doesn't
-        get garbage collected.
-        &quot;&quot;&quot;
-        val = id(obj)
-        assert val not in self.reg, &quot;Objected previously registered.&quot;
-        self.reg[val] = obj
+    def set_error(self, mesg):
+        self.error = mesg
     
-    def unregister(Context self, object obj):
-        val = id(obj)
-        assert val in self.reg, &quot;Objected not registered.&quot;
-        del self.reg[val]
     
-    
\ No newline at end of file</diff>
      <filename>spidermonkey/jscontext.pxi</filename>
    </modified>
    <modified>
      <diff>@@ -10,6 +10,6 @@ cdef object js2py_double(Context cx, jsval jsv):
 
 cdef jsval py2js_double(Context cx, double py_obj, JSObject* parent):
     cdef jsval ret
-    if not JS_NewDoubleValue(cx.cx, py_obj, &amp;ret):
-        raise JSError(&quot;Failed to convert double to JavaScript&quot;)
+    if not JS_NewNumberValue(cx.cx, py_obj, &amp;ret):
+        raise JSError(&quot;Failed to convert double.&quot;)
     return ret</diff>
      <filename>spidermonkey/jsdouble.pxi</filename>
    </modified>
    <modified>
      <diff>@@ -1,32 +1,30 @@
 
 
 cdef JSBool report_python_error(JSContext* cx):
-    tb = traceback.print_exc()
+    tb = traceback.format_exc()
     JS_ReportError(cx, tb)
     return JS_FALSE
 
 cdef void __report_error_callback__(JSContext* cx, char* message, JSErrorReport* report):
     cdef Context pycx
-    pycx = js_context_fetch(cx)
-
-    lines = report.linebuf
-    lines = lines.split(&quot;\n&quot;)
-
-    if len(lines) == 0:
-        msg = [&quot;%s:\n&lt;no code&gt;&quot; % message]
-    else:
-        i = report.lineno
-        n = 2  # lines of context on either side of where error occurred
-
-        start, end = max(i-n, 0), min(i+n+1, len(lines))
-
-        msg = []
-        for ln in lines[start:i]:
-            msg.append(&quot;   %s&quot; % ln)
-        msg.append(&quot;-&gt; %s\n&quot; % lines[i])
-        for ln in lines[i+1:end]:
-            msg.append(&quot;   %s&quot; % ln)
-        msg.append(&quot;&quot;)
-        msg.append('JavaScript error at line %d: &quot;%s&quot;' % (report.lineno, message))
-    context.set_error(&quot;\n&quot;.join(mesg))
-
+    
+    try:
+        if not js_context_has_data(cx):
+            sys.stderr.write(&quot;Attempting to report error for an unknown JSContext.&quot;)
+            return
+        pycx = js_context_fetch(cx)
+        
+        filename = &quot;Unknown&quot;
+        lineno = &quot;Unknown&quot;
+        msg = &quot;Unknown&quot;
+        
+        if report != NULL:
+            if report.filename != NULL:
+                filename = report.filename
+            lineno = report.lineno
+        if message != NULL:
+            msg = message
+        
+        pycx.set_error(&quot;%s(%d): %s&quot; % (filename, lineno, message))
+    except:
+        traceback.print_exc()</diff>
      <filename>spidermonkey/jserror.pxi</filename>
    </modified>
    <modified>
      <diff>@@ -6,11 +6,6 @@ cdef class Function:
     def __init__(Function self, Context cx):
         self.cx = cx
     
-    def __hash__(self):
-        cdef int ret
-        ret = self.func
-        return ret
-    
     def __call__(Function self, *args):
         cdef jsval* argv
         cdef jsval rval
@@ -25,56 +20,144 @@ cdef class Function:
                 argv[i] = jsarg
 
             if not JS_CallFunctionValue(self.cx.cx, self.cx.root.js_obj, self.func, nr_args, argv, &amp;rval):
-                raise JSError(&quot;Failed to execute function: %s&quot; % self.cx._error)
+                raise JSError(self.cx.error)
         finally:
             free(argv)
 
         retval = js2py(self.cx, rval)
-        self.cx.gc.maybe()
+        self.cx.gc.run_maybe()
         return retval
 
     def __dealloc__(Function self):
         JS_RemoveRoot(self.cx.cx, &amp;self.func)
 
-cdef JSBool __function_callback__(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval):
+
+cdef class FunctionAdapter:
+    cdef Context cx
+    cdef JSObject* js_obj
+    cdef object py_obj
+
+    def __cinit__(FunctionAdapter self, Context cx, object obj):
+        self.cx = cx
+        self.py_obj = obj
+
+    def __repr__(self):
+        return &quot;&lt;spidermonkey.FunctionAdapter: %r&gt;&quot; % self.py_obj
+
+
+cdef JSBool __bound_method_callback__(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval):
     cdef Context pycx
-    cdef jsval jsfunc
+    cdef ObjectAdapter oa
+    cdef JSFunction* jsfunc
     cdef int i
 
     try:
+        if not js_context_has_data(cx):
+            raise JSError(&quot;Unknown JSContext object.&quot;)
+        
         pycx = js_context_fetch(cx)
-        callback = pycx.get_function(js_create_value(argv[-2]))
+        
+        if not js_object_has_data(cx, obj):
+            return JS_FALSE
+        
+        oa = js_object_fetch(cx, obj)
+        
+        jsfunc = JS_ValueToFunction(cx, argv[-2])
+        method_name = JS_GetFunctionName(jsfunc)
+        method = getattr(oa.py_obj, method_name)
 
         args = [None] * argc
         for i from 0 &lt;= i &lt; argc:
             args[i] = js2py(pycx, argv[i])
 
-        py_rval = callback(*args)
+        py_rval = method(*args)
         rval[0] = py2js(pycx, py_rval, obj)
+
+        return JS_TRUE
     except:
         return report_python_error(cx)
 
-    return JS_TRUE
+cdef JSBool __function_callback__(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval):
+    cdef Context pycx
+    cdef FunctionAdapter fa
+    cdef JSFunction* jsfunc
+    cdef JSObject* jsobj
+    cdef int i
+
+    try:        
+        if not js_context_has_data(cx):
+            raise JSError(&quot;Unknown JSContext object.&quot;)
+
+        pycx = js_context_fetch(cx)
+        jsfunc = JS_ValueToFunction(cx, argv[-2])
+        jsobj = JS_GetFunctionObject(jsfunc)
+
+        if not js_function_has_data(cx, jsobj):
+            raise JSError(&quot;Function call back without attached functor.&quot;)
+        
+        fa = js_function_fetch(cx, jsobj)
+        
+        args = [None] * argc
+        for i from 0 &lt;= i &lt; argc:
+            args[i] = js2py(pycx, argv[i])
+
+        py_rval = fa.py_obj(*args)
+        rval[0] = py2js(pycx, py_rval, obj)
+
+        return JS_TRUE
+    except:
+        return report_python_error(cx)
 
 def js_is_function(Context cx, jsval jsv):
     return JS_TypeOfValue(cx.cx, jsv) == JSTYPE_FUNCTION
 
 def py_is_function(Context cx, object py_obj):
-    return callable(py_obj)
+    return isinstance(py_obj, (types.FunctionType, types.LambdaType))
+
+def py_is_bound_method(Context cx, object py_obj):
+    return isinstance(py_obj, types.MethodType)
 
 cdef object js2py_function(Context cx, jsval jsv):
     cdef Function ret
     ret = Function(cx)
     ret.func = jsv
-    cx.gc.add_root(&amp;jsv)
+    JS_AddRoot(cx.cx, &amp;ret.func)
     return ret
 
-cdef jsval py2js_function(Context cx, object py_obj, JSObject* parent):
+cdef jsval py2js_bound_method(Context cx, object py_obj, JSObject* parent):
+    cdef FunctionAdapter fa
     cdef JSFunction* func
     cdef JSObject* obj
-    cdef jsval rval
     
-    func = JS_NewFunction(cx.cx, __function_callback__, 0, 0, parent, NULL)
+    if hasattr(py_obj, &quot;func_name&quot;):
+        name = py_obj.func_name
+    elif hasattr(py_obj, &quot;im_fun&quot;) and hasattr(py_obj.im_fun, &quot;func_name&quot;):
+        name = py_obj.im_fun.func_name
+    else:
+        raise JSError(&quot;Failed to find function name.&quot;)
+
+    func = JS_NewFunction(cx.cx, __bound_method_callback__, 0, 0, NULL, name)
     obj = JS_GetFunctionObject(func)
-    js_object_attach(obj, &lt;PyObject*&gt; py_obj)
     return OBJECT_TO_JSVAL(obj)
+
+cdef jsval py2js_function(Context cx, object py_obj, JSObject* parent):
+    cdef FunctionAdapter fa
+    cdef JSFunction* func
+    cdef JSObject* obj
+    cdef jsval slot
+    
+    if hasattr(py_obj, &quot;func_name&quot;):
+        name = py_obj.func_name
+    elif hasattr(py_obj, &quot;im_fun&quot;) and hasattr(py_obj.im_fun, &quot;func_name&quot;):
+        name = py_obj.im_fun.func_name
+    else:
+        raise JSError(&quot;Failed to find function name.&quot;)
+    
+    func = JS_NewFunction(cx.cx, __function_callback__, 0, 0, NULL, name)
+    fa = FunctionAdapter(cx, py_obj)
+    fa.js_obj = JS_GetFunctionObject(func)
+    
+    js_function_attach(cx.cx, fa.js_obj, &lt;PyObject*&gt; fa)
+
+    return OBJECT_TO_JSVAL(fa.js_obj)
+    
\ No newline at end of file</diff>
      <filename>spidermonkey/jsfunction.pxi</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,7 @@ cdef class GC:
     cdef void run(GC self):
         JS_GC(self.cx.cx)
     
-    cdef void run_mayb(GC self):
+    cdef void run_maybe(GC self):
         JS_MaybeGC(self.cx.cx)
     
     cdef void add_root(GC self, void* rp):</diff>
      <filename>spidermonkey/jsgc.pxi</filename>
    </modified>
    <modified>
      <diff>@@ -27,11 +27,11 @@ cdef object js2py_hash(Context cx, jsval v):
             if not JS_IdToValue(cx.cx, (props.vector)[i], &amp;jskey):
                 raise JSError(&quot;Failed to convert dict to JavaScript.&quot;)
         
-            if js_is_string(jskey):
+            if js_is_string(cx, jskey):
                 key = js2py_string(cx, jskey)
                 if not JS_GetProperty(cx.cx, hash, key, &amp;jsv):
                     raise JSError(&quot;Faield to retrieve textual hash property.&quot;)
-            elif js_is_int(jskey):
+            elif js_is_int(cx, jskey):
                 key = js2py_int(cx, jskey)
                 if not JS_GetElement(cx.cx, hash, key, &amp;jsv):
                     raise JSError(&quot;Failed to retrive numeric hash property.&quot;)</diff>
      <filename>spidermonkey/jshash.pxi</filename>
    </modified>
    <modified>
      <diff>@@ -1,15 +1,26 @@
 void
 js_context_attach(JSContext* cx, PyObject* obj)
 {
-    Py_INCREF(obj);
+    Py_XINCREF(obj);
     JS_SetContextPrivate(cx, (void*) obj);
 }
 
+JSBool
+js_context_has_data(JSContext* cx)
+{
+    if(JS_GetContextPrivate(cx) == NULL)
+    {
+        return JS_FALSE;
+    }
+    
+    return JS_TRUE;
+}
+
 PyObject* 
 js_context_fetch(JSContext* cx)
 {
     PyObject* obj = (PyObject*) JS_GetContextPrivate(cx);
-    Py_INCREF(obj);
+    Py_XINCREF(obj);
     return obj;
 }
 
@@ -22,16 +33,28 @@ js_context_destroy(JSContext* cx)
 
 void
 js_object_attach(JSContext* cx, JSObject* js_obj, PyObject* py_obj)
-{
-    Py_INCREF(py_obj);
+{   
+    Py_XINCREF(py_obj);
     JS_SetPrivate(cx, js_obj, (void*) py_obj);
 }
 
+JSBool
+js_object_has_data(JSContext* cx, JSObject* js_obj)
+{
+    void* data = JS_GetPrivate(cx, js_obj);
+    if(data == NULL)
+    {
+        return JS_FALSE;
+    }
+    
+    return JS_TRUE;
+}
+
 PyObject*
 js_object_fetch(JSContext* cx, JSObject* js_obj)
 {
     PyObject* py_obj = (PyObject*) JS_GetPrivate(cx, js_obj);
-    Py_INCREF(py_obj);
+    Py_XINCREF(py_obj);
     return py_obj;
 }
 
@@ -41,6 +64,60 @@ js_object_destroy(JSContext* cx, JSObject* js_obj)
     return (PyObject*) JS_GetPrivate(cx, js_obj);
 }
 
+void
+js_function_attach(JSContext* cx, JSObject* js_obj, PyObject* py_obj)
+{   
+    Py_XINCREF(py_obj);
+    jsval slot = PRIVATE_TO_JSVAL(py_obj);
+    JS_SetReservedSlot(cx, js_obj, 0, slot);
+}
+
+JSBool
+js_function_has_data(JSContext* cx, JSObject* js_obj)
+{
+    jsval slot;
+    if(JS_GetReservedSlot(cx, js_obj, 0, &amp;slot) != JS_TRUE)
+    {
+        return JS_FALSE;
+    }
+    
+    void* data = JSVAL_TO_PRIVATE(slot);
+    
+    if(data == NULL)
+    {
+        return JS_FALSE;
+    }
+    
+    return JS_TRUE;
+}
+
+PyObject*
+js_function_fetch(JSContext* cx, JSObject* js_obj)
+{
+    jsval slot;
+    if(JS_GetReservedSlot(cx, js_obj, 0, &amp;slot) != JS_TRUE)
+    {
+        return JS_FALSE;
+    }
+    
+    PyObject* py_obj = (PyObject*) JSVAL_TO_PRIVATE(slot);
+    Py_XINCREF(py_obj);
+    return py_obj;
+}
+
+PyObject*
+js_function_destroy(JSContext* cx, JSObject* js_obj)
+{
+    jsval slot;
+    if(JS_GetReservedSlot(cx, js_obj, 0, &amp;slot) != JS_TRUE)
+    {
+        return JS_FALSE;
+    }
+    
+    PyObject* py_obj = (PyObject*) JSVAL_TO_PRIVATE(slot);
+    return py_obj;
+}
+
 static JSClass js_global_class =
 {
     &quot;RootObjectClass&quot;,
@@ -59,5 +136,5 @@ static JSClass js_global_class =
 JSObject *
 js_make_global_object(JSContext *cx)
 {
-    return JS_NewObject(cx, &amp;global_class, 0, 0);
+    return JS_NewObject(cx, &amp;js_global_class, 0, 0);
 }</diff>
      <filename>spidermonkey/jshelpers.c</filename>
    </modified>
    <modified>
      <diff>@@ -13,4 +13,49 @@ cdef class ObjectAdapter:
         self.js_obj = NULL
         self.py_obj = obj
 
+    def __repr__(self):
+        return &quot;&lt;spidermonkey.ObjectAdapter: %r&gt;&quot; % self.py_obj
 
+def js_is_object(Context cx, jsval jsv):
+    if not JSVAL_IS_OBJECT(jsv):
+        return False
+    if not js_object_has_data(cx.cx, JSVAL_TO_OBJECT(jsv)):
+        return False
+    return True
+
+def py_is_object(Context cx, object py_obj):
+    return not isinstance(py_obj, types.TypeType)
+
+cdef object js2py_object(Context cx, jsval jsv):
+    cdef ClassAdapter ca
+    cdef ObjectAdapter oa
+    cdef FunctionAdapter fa
+    
+    tmp = js_object_fetch(cx.cx, JSVAL_TO_OBJECT(jsv))
+    if isinstance(tmp, ClassAdapter):
+        ca = tmp
+        return ca.py_obj
+    elif isinstance(tmp, ObjectAdapter):
+        oa = tmp
+        return oa.py_obj
+    elif isinstance(tmp, FunctionAdapter):
+        fa = tmp
+        return fa.py_obj
+    else:
+        raise JSError(&quot;Failed to unwrap Python object.&quot;)
+
+cdef jsval py2js_object(Context cx, object py_obj, JSObject* parent):
+    cdef ClassAdapter ca
+    cdef ObjectAdapter oa
+    cdef JSObject* js_obj
+    cdef jsval rval
+
+    ca = cx.install_class(py_obj.__class__)
+    js_obj = JS_NewObject(cx.cx, ca.js_class, NULL, NULL)
+    if js_obj == NULL:
+        raise JSError(&quot;Failed to create object.&quot;)
+    oa = ObjectAdapter(cx, ca, None, py_obj)
+    oa.js_obj = js_obj
+    js_object_attach(cx.cx, oa.js_obj, &lt;PyObject*&gt; oa)
+
+    return OBJECT_TO_JSVAL(js_obj)</diff>
      <filename>spidermonkey/jsobject.pxi</filename>
    </modified>
    <modified>
      <diff>@@ -8,6 +8,7 @@ cdef class Runtime:
             raise JSError(&quot;Failed to create JavaScript Runtime.&quot;)
 
     def __dealloc__(self):
+        sys.stderr.write(&quot;DESTROYING RUNTIME\n&quot;)
         JS_DestroyRuntime(self.rt)
 
     def create_context(self, root=None):</diff>
      <filename>spidermonkey/jsruntime.pxi</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,8 @@
 cdef jsval py2js(Context cx, object py_obj, JSObject* parent) except 0:
     if py_is_void(cx, py_obj):
         return py2js_void(cx, py_obj, parent)
+    elif py_is_bool(cx, py_obj):
+        return py2js_bool(cx, py_obj, parent)
     elif py_is_int(cx, py_obj):
         return py2js_int(cx, py_obj, parent)
     elif py_is_double(cx, py_obj):
@@ -12,10 +14,12 @@ cdef jsval py2js(Context cx, object py_obj, JSObject* parent) except 0:
         return py2js_array(cx, py_obj, parent)
     elif py_is_hash(cx, py_obj):
         return py2js_hash(cx, py_obj, parent)
+    elif py_is_bound_method(cx, py_obj):
+        return py2js_bound_method(cx, py_obj, parent)
     elif py_is_function(cx, py_obj):
         return py2js_function(cx, py_obj, parent)
-    #elif py_is_object(cx, py_obj):
-    #    return py2js_object(cx, py_obj, parent)
+    elif py_is_object(cx, py_obj):
+        return py2js_object(cx, py_obj, parent)
     #elif py_is_class(cx, py_obj):
     #    return py2js_class(cx, py_obj, parent)
     else:
@@ -24,6 +28,8 @@ cdef jsval py2js(Context cx, object py_obj, JSObject* parent) except 0:
 cdef object js2py(Context cx, jsval jsv):
     if js_is_void(cx, jsv):
         return js2py_void(cx, jsv)
+    elif js_is_bool(cx, jsv):
+        return js2py_bool(cx, jsv)
     elif js_is_int(cx, jsv):
         return js2py_int(cx, jsv)
     elif js_is_double(cx, jsv):
@@ -32,7 +38,7 @@ cdef object js2py(Context cx, jsval jsv):
         return js2py_string(cx, jsv)
     elif js_is_array(cx, jsv):
         return js2py_array(cx, jsv)
-    elif js_is_function(cx, jsv):
+    elif js_is_function(cx, jsv): 
         return js2py_function(cx, jsv)
     elif js_is_object(cx, jsv):
         return js2py_object(cx, jsv)</diff>
      <filename>spidermonkey/jsvalue.pxi</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 
 def js_is_void(Context cx, jsval jsv):
-    return JSVAL_IS_VOID(jsv)
+    return JSVAL_IS_VOID(jsv) or jsv == 0
 
 def py_is_void(Context cx, object py_obj):
     return isinstance(py_obj, (types.NoneType))
@@ -9,4 +9,4 @@ cdef object js2py_void(Context cx, jsval jsv):
     return None
 
 cdef jsval py2js_void(Context cx, object py_obj, JSObject* parent):
-    return JS_VOID
+    return JSVAL_VOID</diff>
      <filename>spidermonkey/jsvoid.pxi</filename>
    </modified>
    <modified>
      <diff>@@ -17,6 +17,7 @@ include &quot;jsfunction.pxi&quot;
 
 # Type Conversions
 include &quot;jsarray.pxi&quot;
+include &quot;jsbool.pxi&quot;
 include &quot;jsdouble.pxi&quot;
 include &quot;jshash.pxi&quot;
 include &quot;jsint.pxi&quot;</diff>
      <filename>spidermonkey/spidermonkey.pyx</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>ChangeLog</filename>
    </removed>
    <removed>
      <filename>README</filename>
    </removed>
    <removed>
      <filename>spidermonkey.c</filename>
    </removed>
    <removed>
      <filename>spidermonkey.pyx</filename>
    </removed>
    <removed>
      <filename>support.c</filename>
    </removed>
    <removed>
      <filename>test.py</filename>
    </removed>
    <removed>
      <filename>tests/test.py</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>ce3a39c9cf73600539e4b9e1fbca071311b35b97</id>
    </parent>
  </parents>
  <author>
    <name>davisp</name>
    <email>davisp@davis2318.l3u.neb.com</email>
  </author>
  <url>http://github.com/davisp/python-spidermonkey/commit/734bb93c4e923aa5a60d2f323ecb48d87ed24d45</url>
  <id>734bb93c4e923aa5a60d2f323ecb48d87ed24d45</id>
  <committed-date>2009-01-28T04:03:52-08:00</committed-date>
  <authored-date>2009-01-28T04:03:52-08:00</authored-date>
  <message>Yeah, bad commit policy. But hey, it works now.</message>
  <tree>2561947cf9de65b930d0848ee4ee36085a98b886</tree>
  <committer>
    <name>davisp</name>
    <email>davisp@davis2318.l3u.neb.com</email>
  </committer>
</commit>
