changeset 96:3570ab12747b

Renamed .c files to .cpp, since we use minor amounts of C++ code in pymonkey.
author Atul Varma <varmaa@toolness.com>
date Sat, 15 Aug 2009 10:24:17 -0700
parents 0701aee1b0cd
children 409cff0c7afb
files context.c context.cpp function.c function.cpp manage.py object.c object.cpp pymonkey.c pymonkey.cpp runtime.c runtime.cpp undefined.c undefined.cpp utils.c utils.cpp
diffstat 15 files changed, 1613 insertions(+), 1613 deletions(-) [+]
line wrap: on
line diff
--- a/context.c	Sat Aug 15 00:50:55 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,534 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Pymonkey.
- *
- * The Initial Developer of the Original Code is Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Atul Varma <atul@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "context.h"
-#include "object.h"
-#include "function.h"
-#include "utils.h"
-
-// This is the default JSOperationCallback for pymonkey-owned JS contexts,
-// when they've defined one in Python.
-static JSBool
-PYM_operationCallback(JSContext *cx)
-{
-  PYM_PyAutoEnsureGIL gil;
-  PYM_JSContextObject *context = (PYM_JSContextObject *)
-    JS_GetContextPrivate(cx);
-
-  PyObject *callable = context->opCallback;
-  PyObject *args = PyTuple_Pack(1, (PyObject *) context);
-  if (args == NULL) {
-    JS_ReportOutOfMemory(cx);
-    return JS_FALSE;
-  }
-  PyObject *result = PyObject_Call(callable, args, NULL);
-  Py_DECREF(args);
-  if (result == NULL) {
-    PYM_pythonExceptionToJs(context);
-    return JS_FALSE;
-  }
-
-  Py_DECREF(result);
-  return JS_TRUE;
-}
-
-// This is the default JSErrorReporter for pymonkey-owned JS contexts.
-static void
-PYM_reportError(JSContext *cx, const char *message, JSErrorReport *report)
-{
-  PYM_PyAutoEnsureGIL gil;
-
-  // Convert JS warnings into Python warnings.
-  if (JSREPORT_IS_WARNING(report->flags)) {
-    if (report->filename)
-      PyErr_WarnExplicit(NULL, message, report->filename, report->lineno,
-                         NULL, NULL);
-    else
-      PyErr_Warn(NULL, message);
-  } else
-    // TODO: Not sure if this will ever get called, but we should know
-    // if it is.
-    PyErr_Warn(NULL, "A JS error was reported.");
-}
-
-static void
-PYM_JSContextDealloc(PYM_JSContextObject *self)
-{
-  if (self->opCallback) {
-    Py_DECREF(self->opCallback);
-    self->opCallback = NULL;
-  }
-
-  if (self->cx) {
-    JS_DestroyContext(self->cx);
-    self->cx = NULL;
-  }
-
-  Py_DECREF(self->runtime);
-  self->runtime = NULL;
-
-  self->ob_type->tp_free((PyObject *) self);
-}
-
-static PyObject *
-PYM_getRuntime(PYM_JSContextObject *self, PyObject *args)
-{
-  Py_INCREF(self->runtime);
-  return (PyObject *) self->runtime;
-}
-
-static PyObject *
-PYM_getObjectPrivate(PYM_JSContextObject *self, PyObject *args)
-{
-  PYM_SANITY_CHECK(self->runtime);
-  PYM_JSObject *object;
-
-  if (!PyArg_ParseTuple(args, "O!", &PYM_JSObjectType, &object))
-    return NULL;
-
-  PYM_ENSURE_RUNTIME_MATCH(self->runtime, object->runtime);
-
-  JSObject *obj = object->obj;
-
-  if (JS_ObjectIsFunction(self->cx, obj)) {
-    jsval functionHolder;
-    if (!JS_GetReservedSlot(self->cx, obj, 0, &functionHolder)) {
-      JS_ClearPendingException(self->cx);
-      Py_RETURN_NONE;
-    }
-    if (!JSVAL_IS_OBJECT(functionHolder))
-      Py_RETURN_NONE;
-    obj = JSVAL_TO_OBJECT(functionHolder);
-  }
-
-  JSClass *klass = JS_GET_CLASS(self->cx, obj);
-  if (klass != &PYM_JS_ObjectClass)
-    Py_RETURN_NONE;
-
-  PyObject *pyObject;
-
-  if (!PYM_JS_getPrivatePyObject(self->cx, obj, &pyObject)) {
-    PYM_jsExceptionToPython(self);
-    return NULL;
-  }
-
-  if (pyObject == NULL)
-    pyObject = Py_None;
-
-  Py_INCREF(pyObject);
-  return pyObject;
-}
-
-static PyObject *
-PYM_clearObjectPrivate(PYM_JSContextObject *self, PyObject *args)
-{
-  PYM_SANITY_CHECK(self->runtime);
-  PYM_JSObject *object;
-
-  if (!PyArg_ParseTuple(args, "O!", &PYM_JSObjectType, &object))
-    return NULL;
-
-  PYM_ENSURE_RUNTIME_MATCH(self->runtime, object->runtime);
-
-  JSObject *obj = object->obj;
-
-  if (JS_ObjectIsFunction(self->cx, obj)) {
-    jsval functionHolder;
-    if (!JS_GetReservedSlot(self->cx, obj, 0, &functionHolder)) {
-      JS_ClearPendingException(self->cx);
-      Py_RETURN_NONE;
-    }
-    if (!JSVAL_IS_OBJECT(functionHolder))
-      Py_RETURN_NONE;
-    obj = JSVAL_TO_OBJECT(functionHolder);
-  }
-
-  JSClass *klass = JS_GET_CLASS(self->cx, obj);
-  if (klass != &PYM_JS_ObjectClass)
-    Py_RETURN_NONE;
-
-  if (!PYM_JS_setPrivatePyObject(self->cx, obj, Py_None)) {
-    PYM_jsExceptionToPython(self);
-    return NULL;
-  }
-
-  Py_RETURN_NONE;
-}
-
-static PyObject *
-PYM_newObject(PYM_JSContextObject *self, PyObject *args)
-{
-  PYM_SANITY_CHECK(self->runtime);
-  PyObject *privateObj = NULL;
-
-  if (!PyArg_ParseTuple(args, "|O", &privateObj))
-    return NULL;
-
-  JSObject *obj = PYM_JS_newObject(self->cx, privateObj);
-  if (obj == NULL) {
-    PyErr_SetString(PYM_error, "PYM_JS_newObject() failed");
-    return NULL;
-  }
-
-  // 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, NULL);
-}
-
-static PyObject *
-PYM_getProperty(PYM_JSContextObject *self, PyObject *args)
-{
-  PYM_SANITY_CHECK(self->runtime);
-  PYM_JSObject *object;
-  char *buffer = NULL;
-  int size;
-
-  if (!PyArg_ParseTuple(args, "O!es#", &PYM_JSObjectType, &object,
-                        "utf-16", &buffer, &size))
-    return NULL;
-
-  if (self->runtime != object->runtime) {
-    PyMem_Free(buffer);
-    PYM_ENSURE_RUNTIME_MATCH(self->runtime, object->runtime);
-  }
-
-  jsval val;
-  JSBool result;
-  Py_BEGIN_ALLOW_THREADS;
-  // Note that we're manipulating buffer and size here to get rid of
-  // the BOM.
-  result = JS_GetUCProperty(self->cx, object->obj, (jschar *) (buffer + 2),
-                            (size / 2) - 1, &val);
-  Py_END_ALLOW_THREADS;
-
-  PyMem_Free(buffer);
-
-  if (!result) {
-    PYM_jsExceptionToPython(self);
-    return NULL;
-  }
-
-  return PYM_jsvalToPyObject(self, val);
-}
-
-static PyObject *
-PYM_gc(PYM_JSContextObject *self, PyObject *args)
-{
-  PYM_SANITY_CHECK(self->runtime);
-  JS_GC(self->cx);
-  Py_RETURN_NONE;
-}
-
-static PyObject *
-PYM_initStandardClasses(PYM_JSContextObject *self, PyObject *args)
-{
-  PYM_SANITY_CHECK(self->runtime);
-  PYM_JSObject *object;
-
-  if (!PyArg_ParseTuple(args, "O!", &PYM_JSObjectType, &object))
-    return NULL;
-
-  PYM_ENSURE_RUNTIME_MATCH(self->runtime, object->runtime);
-
-  if (!JS_InitStandardClasses(self->cx, object->obj)) {
-    PyErr_SetString(PYM_error, "JS_InitStandardClasses() failed");
-    return NULL;
-  }
-
-  Py_RETURN_NONE;
-}
-
-static PyObject *
-PYM_evaluateScript(PYM_JSContextObject *self, PyObject *args)
-{
-  PYM_SANITY_CHECK(self->runtime);
-  PYM_JSObject *object;
-  const char *source;
-  int sourceLen;
-  const char *filename;
-  int lineNo;
-
-  if (!PyArg_ParseTuple(args, "O!s#si", &PYM_JSObjectType, &object,
-                        &source, &sourceLen, &filename, &lineNo))
-    return NULL;
-
-  PYM_ENSURE_RUNTIME_MATCH(self->runtime, object->runtime);
-
-  jsval rval;
-  JSBool result;
-  Py_BEGIN_ALLOW_THREADS;
-  result = JS_EvaluateScript(self->cx, object->obj, source, sourceLen,
-                             filename, lineNo, &rval);
-  Py_END_ALLOW_THREADS;
-
-  if (!result) {
-    PYM_jsExceptionToPython(self);
-    return NULL;
-  }
-
-  PyObject *pyRval = PYM_jsvalToPyObject(self, rval);
-  return pyRval;
-}
-
-static PyObject *
-PYM_defineProperty(PYM_JSContextObject *self, PyObject *args)
-{
-  PYM_SANITY_CHECK(self->runtime);
-  PYM_JSObject *object;
-  PyObject *value;
-  const char *name;
-
-  if (!PyArg_ParseTuple(args, "O!sO", &PYM_JSObjectType, &object,
-                        &name, &value))
-    return NULL;
-
-  PYM_ENSURE_RUNTIME_MATCH(self->runtime, object->runtime);
-  jsval jsValue;
-
-  if (PYM_pyObjectToJsval(self, 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;
-  }
-
-  Py_RETURN_NONE;
-}
-
-static PyObject *
-PYM_callFunction(PYM_JSContextObject *self, PyObject *args)
-{
-  PYM_SANITY_CHECK(self->runtime);
-  PYM_JSObject *obj;
-  PYM_JSFunction *fun;
-  PyObject *funcArgs;
-
-  if (!PyArg_ParseTuple(args, "O!O!O!", &PYM_JSObjectType, &obj,
-                        &PYM_JSFunctionType, &fun,
-                        &PyTuple_Type, &funcArgs))
-    return NULL;
-
-  PYM_ENSURE_RUNTIME_MATCH(self->runtime, obj->runtime);
-  PYM_ENSURE_RUNTIME_MATCH(self->runtime, fun->base.runtime);
-
-  uintN argc = PyTuple_Size(funcArgs);
-  jsval argv[argc];
-  jsval *currArg = argv;
-
-  for (unsigned int i = 0; i < argc; i++) {
-    PyObject *item = PyTuple_GET_ITEM(funcArgs, i);
-    if (item == NULL ||
-        PYM_pyObjectToJsval(self, item, currArg) == -1)
-      return NULL;
-    currArg++;
-  }
-
-  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);
-  Py_END_ALLOW_THREADS;
-
-  if (!result) {
-    PYM_jsExceptionToPython(self);
-    return NULL;
-  }
-
-  return PYM_jsvalToPyObject(self, rval);
-}
-
-static PyObject *
-PYM_newFunction(PYM_JSContextObject *self, PyObject *args)
-{
-  PYM_SANITY_CHECK(self->runtime);
-  PyObject *callable;
-  const char *name;
-
-  if (!PyArg_ParseTuple(args, "Os", &callable, &name))
-    return NULL;
-
-  return (PyObject *) PYM_newJSFunctionFromCallable(self, callable, name);
-}
-
-static PyObject *
-PYM_setOperationCallback(PYM_JSContextObject *self, PyObject *args)
-{
-  PYM_SANITY_CHECK(self->runtime);
-  PyObject *callable;
-
-  if (!PyArg_ParseTuple(args, "O", &callable))
-    return NULL;
-
-  if (!PyCallable_Check(callable)) {
-    PyErr_SetString(PyExc_TypeError, "Callable must be callable");
-    return NULL;
-  }
-
-  JS_SetOperationCallback(self->cx, PYM_operationCallback);
-
-  Py_INCREF(callable);
-  if (self->opCallback)
-    Py_DECREF(self->opCallback);
-  self->opCallback = callable;
-
-  Py_RETURN_NONE;
-}
-
-static PyObject *
-PYM_triggerOperationCallback(PYM_JSContextObject *self, PyObject *args)
-{
-  JS_TriggerOperationCallback(self->cx);
-  Py_RETURN_NONE;
-}
-
-static PyMethodDef PYM_JSContextMethods[] = {
-  {"get_runtime", (PyCFunction) PYM_getRuntime, METH_VARARGS,
-   "Get the JavaScript runtime associated with this context."},
-  {"new_object", (PyCFunction) PYM_newObject, METH_VARARGS,
-   "Create a new JavaScript object."},
-  {"init_standard_classes",
-   (PyCFunction) PYM_initStandardClasses, METH_VARARGS,
-   "Add standard classes and functions to the given object."},
-  {"evaluate_script",
-   (PyCFunction) PYM_evaluateScript, METH_VARARGS,
-   "Evaluate the given JavaScript code in the context of the given "
-   "global object, using the given filename"
-   "and line number information."},
-  {"call_function",
-   (PyCFunction) PYM_callFunction, METH_VARARGS,
-   "Calls a JS function."},
-  {"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."},
-  {"gc", (PyCFunction) PYM_gc, METH_VARARGS,
-   "Performs garbage collection on the context's runtime."},
-  {"set_operation_callback", (PyCFunction) PYM_setOperationCallback,
-   METH_VARARGS,
-   "Sets the operation callback for the context."},
-  {"trigger_operation_callback", (PyCFunction) PYM_triggerOperationCallback,
-   METH_VARARGS,
-   "Triggers the operation callback for the context."},
-  {"get_object_private", (PyCFunction) PYM_getObjectPrivate, METH_VARARGS,
-   "Returns the private Python object stored in the JavaScript object."},
-  {"clear_object_private", (PyCFunction) PYM_clearObjectPrivate, METH_VARARGS,
-   "Clears any private Python object stored in the JavaScript object."},
-  {NULL, NULL, 0, NULL}
-};
-
-PyTypeObject PYM_JSContextType = {
-  PyObject_HEAD_INIT(NULL)
-  0,                           /*ob_size*/
-  "pymonkey.Context",          /*tp_name*/
-  sizeof(PYM_JSContextObject), /*tp_basicsize*/
-  0,                           /*tp_itemsize*/
-  /*tp_dealloc*/
-  (destructor) PYM_JSContextDealloc,
-  0,                           /*tp_print*/
-  0,                           /*tp_getattr*/
-  0,                           /*tp_setattr*/
-  0,                           /*tp_compare*/
-  0,                           /*tp_repr*/
-  0,                           /*tp_as_number*/
-  0,                           /*tp_as_sequence*/
-  0,                           /*tp_as_mapping*/
-  0,                           /*tp_hash */
-  0,                           /*tp_call*/
-  0,                           /*tp_str*/
-  0,                           /*tp_getattro*/
-  0,                           /*tp_setattro*/
-  0,                           /*tp_as_buffer*/
-  Py_TPFLAGS_DEFAULT,          /*tp_flags*/
-  /* tp_doc */
-  "JavaScript Context.",
-  0,		               /* tp_traverse */
-  0,		               /* tp_clear */
-  0,		               /* tp_richcompare */
-  0,		               /* tp_weaklistoffset */
-  0,		               /* tp_iter */
-  0,		               /* tp_iternext */
-  PYM_JSContextMethods,        /* tp_methods */
-  0,                           /* tp_members */
-  0,                           /* tp_getset */
-  0,                           /* tp_base */
-  0,                           /* tp_dict */
-  0,                           /* tp_descr_get */
-  0,                           /* tp_descr_set */
-  0,                           /* tp_dictoffset */
-  0,                           /* tp_init */
-  0,                           /* tp_alloc */
-  0,                           /* tp_new */
-};
-
-extern PYM_JSContextObject *
-PYM_newJSContextObject(PYM_JSRuntimeObject *runtime, JSContext *cx)
-{
-  PYM_JSContextObject *context = PyObject_New(PYM_JSContextObject,
-                                              &PYM_JSContextType);
-  if (context == NULL)
-    return NULL;
-
-  context->opCallback = NULL;
-  context->runtime = runtime;
-  Py_INCREF(runtime);
-
-  context->cx = cx;
-  JS_SetContextPrivate(cx, context);
-  JS_SetErrorReporter(cx, PYM_reportError);
-
-#ifdef JS_GC_ZEAL
-  // TODO: Consider exposing JS_SetGCZeal() to Python instead of
-  // hard-coding it here.
-  JS_SetGCZeal(cx, 2);
-#endif
-
-  return context;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/context.cpp	Sat Aug 15 10:24:17 2009 -0700
@@ -0,0 +1,534 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Pymonkey.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Atul Varma <atul@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "context.h"
+#include "object.h"
+#include "function.h"
+#include "utils.h"
+
+// This is the default JSOperationCallback for pymonkey-owned JS contexts,
+// when they've defined one in Python.
+static JSBool
+PYM_operationCallback(JSContext *cx)
+{
+  PYM_PyAutoEnsureGIL gil;
+  PYM_JSContextObject *context = (PYM_JSContextObject *)
+    JS_GetContextPrivate(cx);
+
+  PyObject *callable = context->opCallback;
+  PyObject *args = PyTuple_Pack(1, (PyObject *) context);
+  if (args == NULL) {
+    JS_ReportOutOfMemory(cx);
+    return JS_FALSE;
+  }
+  PyObject *result = PyObject_Call(callable, args, NULL);
+  Py_DECREF(args);
+  if (result == NULL) {
+    PYM_pythonExceptionToJs(context);
+    return JS_FALSE;
+  }
+
+  Py_DECREF(result);
+  return JS_TRUE;
+}
+
+// This is the default JSErrorReporter for pymonkey-owned JS contexts.
+static void
+PYM_reportError(JSContext *cx, const char *message, JSErrorReport *report)
+{
+  PYM_PyAutoEnsureGIL gil;
+
+  // Convert JS warnings into Python warnings.
+  if (JSREPORT_IS_WARNING(report->flags)) {
+    if (report->filename)
+      PyErr_WarnExplicit(NULL, message, report->filename, report->lineno,
+                         NULL, NULL);
+    else
+      PyErr_Warn(NULL, message);
+  } else
+    // TODO: Not sure if this will ever get called, but we should know
+    // if it is.
+    PyErr_Warn(NULL, "A JS error was reported.");
+}
+
+static void
+PYM_JSContextDealloc(PYM_JSContextObject *self)
+{
+  if (self->opCallback) {
+    Py_DECREF(self->opCallback);
+    self->opCallback = NULL;
+  }
+
+  if (self->cx) {
+    JS_DestroyContext(self->cx);
+    self->cx = NULL;
+  }
+
+  Py_DECREF(self->runtime);
+  self->runtime = NULL;
+
+  self->ob_type->tp_free((PyObject *) self);
+}
+
+static PyObject *
+PYM_getRuntime(PYM_JSContextObject *self, PyObject *args)
+{
+  Py_INCREF(self->runtime);
+  return (PyObject *) self->runtime;
+}
+
+static PyObject *
+PYM_getObjectPrivate(PYM_JSContextObject *self, PyObject *args)
+{
+  PYM_SANITY_CHECK(self->runtime);
+  PYM_JSObject *object;
+
+  if (!PyArg_ParseTuple(args, "O!", &PYM_JSObjectType, &object))
+    return NULL;
+
+  PYM_ENSURE_RUNTIME_MATCH(self->runtime, object->runtime);
+
+  JSObject *obj = object->obj;
+
+  if (JS_ObjectIsFunction(self->cx, obj)) {
+    jsval functionHolder;
+    if (!JS_GetReservedSlot(self->cx, obj, 0, &functionHolder)) {
+      JS_ClearPendingException(self->cx);
+      Py_RETURN_NONE;
+    }
+    if (!JSVAL_IS_OBJECT(functionHolder))
+      Py_RETURN_NONE;
+    obj = JSVAL_TO_OBJECT(functionHolder);
+  }
+
+  JSClass *klass = JS_GET_CLASS(self->cx, obj);
+  if (klass != &PYM_JS_ObjectClass)
+    Py_RETURN_NONE;
+
+  PyObject *pyObject;
+
+  if (!PYM_JS_getPrivatePyObject(self->cx, obj, &pyObject)) {
+    PYM_jsExceptionToPython(self);
+    return NULL;
+  }
+
+  if (pyObject == NULL)
+    pyObject = Py_None;
+
+  Py_INCREF(pyObject);
+  return pyObject;
+}
+
+static PyObject *
+PYM_clearObjectPrivate(PYM_JSContextObject *self, PyObject *args)
+{
+  PYM_SANITY_CHECK(self->runtime);
+  PYM_JSObject *object;
+
+  if (!PyArg_ParseTuple(args, "O!", &PYM_JSObjectType, &object))
+    return NULL;
+
+  PYM_ENSURE_RUNTIME_MATCH(self->runtime, object->runtime);
+
+  JSObject *obj = object->obj;
+
+  if (JS_ObjectIsFunction(self->cx, obj)) {
+    jsval functionHolder;
+    if (!JS_GetReservedSlot(self->cx, obj, 0, &functionHolder)) {
+      JS_ClearPendingException(self->cx);
+      Py_RETURN_NONE;
+    }
+    if (!JSVAL_IS_OBJECT(functionHolder))
+      Py_RETURN_NONE;
+    obj = JSVAL_TO_OBJECT(functionHolder);
+  }
+
+  JSClass *klass = JS_GET_CLASS(self->cx, obj);
+  if (klass != &PYM_JS_ObjectClass)
+    Py_RETURN_NONE;
+
+  if (!PYM_JS_setPrivatePyObject(self->cx, obj, Py_None)) {
+    PYM_jsExceptionToPython(self);
+    return NULL;
+  }
+
+  Py_RETURN_NONE;
+}
+
+static PyObject *
+PYM_newObject(PYM_JSContextObject *self, PyObject *args)
+{
+  PYM_SANITY_CHECK(self->runtime);
+  PyObject *privateObj = NULL;
+
+  if (!PyArg_ParseTuple(args, "|O", &privateObj))
+    return NULL;
+
+  JSObject *obj = PYM_JS_newObject(self->cx, privateObj);
+  if (obj == NULL) {
+    PyErr_SetString(PYM_error, "PYM_JS_newObject() failed");
+    return NULL;
+  }
+
+  // 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, NULL);
+}
+
+static PyObject *
+PYM_getProperty(PYM_JSContextObject *self, PyObject *args)
+{
+  PYM_SANITY_CHECK(self->runtime);
+  PYM_JSObject *object;
+  char *buffer = NULL;
+  int size;
+
+  if (!PyArg_ParseTuple(args, "O!es#", &PYM_JSObjectType, &object,
+                        "utf-16", &buffer, &size))
+    return NULL;
+
+  if (self->runtime != object->runtime) {
+    PyMem_Free(buffer);
+    PYM_ENSURE_RUNTIME_MATCH(self->runtime, object->runtime);
+  }
+
+  jsval val;
+  JSBool result;
+  Py_BEGIN_ALLOW_THREADS;
+  // Note that we're manipulating buffer and size here to get rid of
+  // the BOM.
+  result = JS_GetUCProperty(self->cx, object->obj, (jschar *) (buffer + 2),
+                            (size / 2) - 1, &val);
+  Py_END_ALLOW_THREADS;
+
+  PyMem_Free(buffer);
+
+  if (!result) {
+    PYM_jsExceptionToPython(self);
+    return NULL;
+  }
+
+  return PYM_jsvalToPyObject(self, val);
+}
+
+static PyObject *
+PYM_gc(PYM_JSContextObject *self, PyObject *args)
+{
+  PYM_SANITY_CHECK(self->runtime);
+  JS_GC(self->cx);
+  Py_RETURN_NONE;
+}
+
+static PyObject *
+PYM_initStandardClasses(PYM_JSContextObject *self, PyObject *args)
+{
+  PYM_SANITY_CHECK(self->runtime);
+  PYM_JSObject *object;
+
+  if (!PyArg_ParseTuple(args, "O!", &PYM_JSObjectType, &object))
+    return NULL;
+
+  PYM_ENSURE_RUNTIME_MATCH(self->runtime, object->runtime);
+
+  if (!JS_InitStandardClasses(self->cx, object->obj)) {
+    PyErr_SetString(PYM_error, "JS_InitStandardClasses() failed");
+    return NULL;
+  }
+
+  Py_RETURN_NONE;
+}
+
+static PyObject *
+PYM_evaluateScript(PYM_JSContextObject *self, PyObject *args)
+{
+  PYM_SANITY_CHECK(self->runtime);
+  PYM_JSObject *object;
+  const char *source;
+  int sourceLen;
+  const char *filename;
+  int lineNo;
+
+  if (!PyArg_ParseTuple(args, "O!s#si", &PYM_JSObjectType, &object,
+                        &source, &sourceLen, &filename, &lineNo))
+    return NULL;
+
+  PYM_ENSURE_RUNTIME_MATCH(self->runtime, object->runtime);
+
+  jsval rval;
+  JSBool result;
+  Py_BEGIN_ALLOW_THREADS;
+  result = JS_EvaluateScript(self->cx, object->obj, source, sourceLen,
+                             filename, lineNo, &rval);
+  Py_END_ALLOW_THREADS;
+
+  if (!result) {
+    PYM_jsExceptionToPython(self);
+    return NULL;
+  }
+
+  PyObject *pyRval = PYM_jsvalToPyObject(self, rval);
+  return pyRval;
+}
+
+static PyObject *
+PYM_defineProperty(PYM_JSContextObject *self, PyObject *args)
+{
+  PYM_SANITY_CHECK(self->runtime);
+  PYM_JSObject *object;
+  PyObject *value;
+  const char *name;
+
+  if (!PyArg_ParseTuple(args, "O!sO", &PYM_JSObjectType, &object,
+                        &name, &value))
+    return NULL;
+
+  PYM_ENSURE_RUNTIME_MATCH(self->runtime, object->runtime);
+  jsval jsValue;
+
+  if (PYM_pyObjectToJsval(self, 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;
+  }
+
+  Py_RETURN_NONE;
+}
+
+static PyObject *
+PYM_callFunction(PYM_JSContextObject *self, PyObject *args)
+{
+  PYM_SANITY_CHECK(self->runtime);
+  PYM_JSObject *obj;
+  PYM_JSFunction *fun;
+  PyObject *funcArgs;
+
+  if (!PyArg_ParseTuple(args, "O!O!O!", &PYM_JSObjectType, &obj,
+                        &PYM_JSFunctionType, &fun,
+                        &PyTuple_Type, &funcArgs))
+    return NULL;
+
+  PYM_ENSURE_RUNTIME_MATCH(self->runtime, obj->runtime);
+  PYM_ENSURE_RUNTIME_MATCH(self->runtime, fun->base.runtime);
+
+  uintN argc = PyTuple_Size(funcArgs);
+  jsval argv[argc];
+  jsval *currArg = argv;
+
+  for (unsigned int i = 0; i < argc; i++) {
+    PyObject *item = PyTuple_GET_ITEM(funcArgs, i);
+    if (item == NULL ||
+        PYM_pyObjectToJsval(self, item, currArg) == -1)
+      return NULL;
+    currArg++;
+  }
+
+  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);
+  Py_END_ALLOW_THREADS;
+
+  if (!result) {
+    PYM_jsExceptionToPython(self);
+    return NULL;
+  }
+
+  return PYM_jsvalToPyObject(self, rval);
+}
+
+static PyObject *
+PYM_newFunction(PYM_JSContextObject *self, PyObject *args)
+{
+  PYM_SANITY_CHECK(self->runtime);
+  PyObject *callable;
+  const char *name;
+
+  if (!PyArg_ParseTuple(args, "Os", &callable, &name))
+    return NULL;
+
+  return (PyObject *) PYM_newJSFunctionFromCallable(self, callable, name);
+}
+
+static PyObject *
+PYM_setOperationCallback(PYM_JSContextObject *self, PyObject *args)
+{
+  PYM_SANITY_CHECK(self->runtime);
+  PyObject *callable;
+
+  if (!PyArg_ParseTuple(args, "O", &callable))
+    return NULL;
+
+  if (!PyCallable_Check(callable)) {
+    PyErr_SetString(PyExc_TypeError, "Callable must be callable");
+    return NULL;
+  }
+
+  JS_SetOperationCallback(self->cx, PYM_operationCallback);
+
+  Py_INCREF(callable);
+  if (self->opCallback)
+    Py_DECREF(self->opCallback);
+  self->opCallback = callable;
+
+  Py_RETURN_NONE;
+}
+
+static PyObject *
+PYM_triggerOperationCallback(PYM_JSContextObject *self, PyObject *args)
+{
+  JS_TriggerOperationCallback(self->cx);
+  Py_RETURN_NONE;
+}
+
+static PyMethodDef PYM_JSContextMethods[] = {
+  {"get_runtime", (PyCFunction) PYM_getRuntime, METH_VARARGS,
+   "Get the JavaScript runtime associated with this context."},
+  {"new_object", (PyCFunction) PYM_newObject, METH_VARARGS,
+   "Create a new JavaScript object."},
+  {"init_standard_classes",
+   (PyCFunction) PYM_initStandardClasses, METH_VARARGS,
+   "Add standard classes and functions to the given object."},
+  {"evaluate_script",
+   (PyCFunction) PYM_evaluateScript, METH_VARARGS,
+   "Evaluate the given JavaScript code in the context of the given "
+   "global object, using the given filename"
+   "and line number information."},
+  {"call_function",
+   (PyCFunction) PYM_callFunction, METH_VARARGS,
+   "Calls a JS function."},
+  {"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."},
+  {"gc", (PyCFunction) PYM_gc, METH_VARARGS,
+   "Performs garbage collection on the context's runtime."},
+  {"set_operation_callback", (PyCFunction) PYM_setOperationCallback,
+   METH_VARARGS,
+   "Sets the operation callback for the context."},
+  {"trigger_operation_callback", (PyCFunction) PYM_triggerOperationCallback,
+   METH_VARARGS,
+   "Triggers the operation callback for the context."},
+  {"get_object_private", (PyCFunction) PYM_getObjectPrivate, METH_VARARGS,
+   "Returns the private Python object stored in the JavaScript object."},
+  {"clear_object_private", (PyCFunction) PYM_clearObjectPrivate, METH_VARARGS,
+   "Clears any private Python object stored in the JavaScript object."},
+  {NULL, NULL, 0, NULL}
+};
+
+PyTypeObject PYM_JSContextType = {
+  PyObject_HEAD_INIT(NULL)
+  0,                           /*ob_size*/
+  "pymonkey.Context",          /*tp_name*/
+  sizeof(PYM_JSContextObject), /*tp_basicsize*/
+  0,                           /*tp_itemsize*/
+  /*tp_dealloc*/
+  (destructor) PYM_JSContextDealloc,
+  0,                           /*tp_print*/
+  0,                           /*tp_getattr*/
+  0,                           /*tp_setattr*/
+  0,                           /*tp_compare*/
+  0,                           /*tp_repr*/
+  0,                           /*tp_as_number*/
+  0,                           /*tp_as_sequence*/
+  0,                           /*tp_as_mapping*/
+  0,                           /*tp_hash */
+  0,                           /*tp_call*/
+  0,                           /*tp_str*/
+  0,                           /*tp_getattro*/
+  0,                           /*tp_setattro*/
+  0,                           /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,          /*tp_flags*/
+  /* tp_doc */
+  "JavaScript Context.",
+  0,		               /* tp_traverse */
+  0,		               /* tp_clear */
+  0,		               /* tp_richcompare */
+  0,		               /* tp_weaklistoffset */
+  0,		               /* tp_iter */
+  0,		               /* tp_iternext */
+  PYM_JSContextMethods,        /* tp_methods */
+  0,                           /* tp_members */
+  0,                           /* tp_getset */
+  0,                           /* tp_base */
+  0,                           /* tp_dict */
+  0,                           /* tp_descr_get */
+  0,                           /* tp_descr_set */
+  0,                           /* tp_dictoffset */
+  0,                           /* tp_init */
+  0,                           /* tp_alloc */
+  0,                           /* tp_new */
+};
+
+extern PYM_JSContextObject *
+PYM_newJSContextObject(PYM_JSRuntimeObject *runtime, JSContext *cx)
+{
+  PYM_JSContextObject *context = PyObject_New(PYM_JSContextObject,
+                                              &PYM_JSContextType);
+  if (context == NULL)
+    return NULL;
+
+  context->opCallback = NULL;
+  context->runtime = runtime;
+  Py_INCREF(runtime);
+
+  context->cx = cx;
+  JS_SetContextPrivate(cx, context);
+  JS_SetErrorReporter(cx, PYM_reportError);
+
+#ifdef JS_GC_ZEAL
+  // TODO: Consider exposing JS_SetGCZeal() to Python instead of
+  // hard-coding it here.
+  JS_SetGCZeal(cx, 2);
+#endif
+
+  return context;
+}
--- a/function.c	Sat Aug 15 00:50:55 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,224 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Pymonkey.
- *
- * The Initial Developer of the Original Code is Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Atul Varma <atul@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "function.h"
-#include "utils.h"
-
-static void
-PYM_JSFunctionDealloc(PYM_JSFunction *self)
-{
-  PYM_JSObjectType.tp_dealloc((PyObject *) self);
-}
-
-static JSBool
-PYM_dispatchJSFunctionToPython(JSContext *cx,
-                               JSObject *obj,
-                               uintN argc,
-                               jsval *argv,
-                               jsval *rval)
-{
-  PYM_PyAutoEnsureGIL gil;
-  jsval callee = JS_ARGV_CALLEE(argv);
-  jsval functionHolder;
-  if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(callee), 0, &functionHolder))
-    return JS_FALSE;
-
-  PyObject *callable;
-  if (!PYM_JS_getPrivatePyObject(cx, JSVAL_TO_OBJECT(functionHolder),
-                                 &callable))
-    return JS_FALSE;
-
-  if (callable == Py_None) {
-    JS_ReportError(cx, "Wrapped Python function no longer exists");
-    return JS_FALSE;
-  }
-
-  PYM_JSContextObject *context = (PYM_JSContextObject *)
-    JS_GetContextPrivate(cx);
-
-  jsval thisArg = OBJECT_TO_JSVAL(obj);
-  PyObject *pyThisArg = PYM_jsvalToPyObject(context, thisArg);
-  if (pyThisArg == NULL) {
-    PYM_pythonExceptionToJs(context);
-    return JS_FALSE;
-  }
-
-  PyObject *funcArgs = PyTuple_New(argc);
-  if (funcArgs == NULL) {
-    Py_DECREF(pyThisArg);
-    JS_ReportOutOfMemory(cx);
-    return JS_FALSE;
-  }
-
-  for (unsigned int i = 0; i < argc; i++) {
-    PyObject *arg = PYM_jsvalToPyObject(context, argv[i]);
-    if (arg == NULL || PyTuple_SetItem(funcArgs, i, arg)) {
-      if (arg)
-        Py_DECREF(arg);
-      Py_DECREF(funcArgs);
-      Py_DECREF(pyThisArg);
-      PYM_pythonExceptionToJs(context);
-      return JS_FALSE;
-    }
-  }
-
-  PyObject *args = PyTuple_Pack(3,
-                                (PyObject *) context,
-                                pyThisArg,
-                                funcArgs);
-  Py_DECREF(pyThisArg);
-  Py_DECREF(funcArgs);
-  if (args == NULL) {
-    JS_ReportOutOfMemory(cx);
-    return JS_FALSE;
-  }
-
-  PyObject *result = PyObject_Call(callable, args, NULL);
-  Py_DECREF(args);
-  if (result == NULL) {
-    PYM_pythonExceptionToJs(context);
-    return JS_FALSE;
-  }
-
-  int error = PYM_pyObjectToJsval(context, result, rval);
-  Py_DECREF(result);
-
-  if (error) {
-    PYM_pythonExceptionToJs(context);
-    return JS_FALSE;
-  }
-
-  return JS_TRUE;
-}
-
-PyTypeObject PYM_JSFunctionType = {
-  PyObject_HEAD_INIT(NULL)
-  0,                           /*ob_size*/
-  "pymonkey.Function",         /*tp_name*/
-  sizeof(PYM_JSFunction),      /*tp_basicsize*/
-  0,                           /*tp_itemsize*/
-  /*tp_dealloc*/
-  (destructor) PYM_JSFunctionDealloc,
-  0,                           /*tp_print*/
-  0,                           /*tp_getattr*/
-  0,                           /*tp_setattr*/
-  0,                           /*tp_compare*/
-  0,                           /*tp_repr*/
-  0,                           /*tp_as_number*/
-  0,                           /*tp_as_sequence*/
-  0,                           /*tp_as_mapping*/
-  0,                           /*tp_hash */
-  0,                           /*tp_call*/
-  0,                           /*tp_str*/
-  0,                           /*tp_getattro*/
-  0,                           /*tp_setattro*/
-  0,                           /*tp_as_buffer*/
-  /*tp_flags*/
-  Py_TPFLAGS_DEFAULT,
-  /* tp_doc */
-  "JavaScript Function.",
-  0,		               /* tp_traverse */
-  0,		               /* tp_clear */
-  0,		               /* tp_richcompare */
-  0,                           /* tp_weaklistoffset */
-  0,		               /* tp_iter */
-  0,		               /* tp_iternext */
-  0,                           /* tp_methods */
-  0,                           /* tp_members */
-  0,                           /* tp_getset */
-  0,                           /* tp_base */
-  0,                           /* tp_dict */
-  0,                           /* tp_descr_get */
-  0,                           /* tp_descr_set */
-  0,                           /* tp_dictoffset */
-  0,                           /* tp_init */
-  0,                           /* tp_alloc */
-  0,                           /* tp_new */
-};
-
-PYM_JSFunction *
-PYM_newJSFunctionFromCallable(PYM_JSContextObject *context,
-                              PyObject *callable,
-                              const char *name)
-{
-  if (!PyCallable_Check(callable)) {
-    PyErr_SetString(PyExc_TypeError, "Callable must be callable");
-    return NULL;
-  }
-
-  JSFunction *func = JS_NewFunction(context->cx,
-                                    PYM_dispatchJSFunctionToPython, 0,
-                                    0, NULL, name);
-
-  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;
-  }
-
-  PYM_JSFunction *object = PyObject_New(PYM_JSFunction,
-                                        &PYM_JSFunctionType);
-  if (object == NULL)
-    return NULL;
-
-  if (PYM_newJSObject(context, funcObj,
-                      (PYM_JSObject *) object) == NULL)
-    // Note that our object's reference count will have already
-    // been decremented by PYM_newJSObject().
-    return NULL;
-
-  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;
-  }
-
-  if (!JS_SetReservedSlot(context->cx, funcObj, 0,
-                          OBJECT_TO_JSVAL(functionHolder))) {
-    Py_DECREF((PyObject *) object);
-    PyErr_SetString(PYM_error, "JS_SetReservedSlot() failed");
-    return NULL;
-  }
-
-  return object;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/function.cpp	Sat Aug 15 10:24:17 2009 -0700
@@ -0,0 +1,224 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Pymonkey.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Atul Varma <atul@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "function.h"
+#include "utils.h"
+
+static void
+PYM_JSFunctionDealloc(PYM_JSFunction *self)
+{
+  PYM_JSObjectType.tp_dealloc((PyObject *) self);
+}
+
+static JSBool
+PYM_dispatchJSFunctionToPython(JSContext *cx,
+                               JSObject *obj,
+                               uintN argc,
+                               jsval *argv,
+                               jsval *rval)
+{
+  PYM_PyAutoEnsureGIL gil;
+  jsval callee = JS_ARGV_CALLEE(argv);
+  jsval functionHolder;
+  if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(callee), 0, &functionHolder))
+    return JS_FALSE;
+
+  PyObject *callable;
+  if (!PYM_JS_getPrivatePyObject(cx, JSVAL_TO_OBJECT(functionHolder),
+                                 &callable))
+    return JS_FALSE;
+
+  if (callable == Py_None) {
+    JS_ReportError(cx, "Wrapped Python function no longer exists");
+    return JS_FALSE;
+  }
+
+  PYM_JSContextObject *context = (PYM_JSContextObject *)
+    JS_GetContextPrivate(cx);
+
+  jsval thisArg = OBJECT_TO_JSVAL(obj);
+  PyObject *pyThisArg = PYM_jsvalToPyObject(context, thisArg);
+  if (pyThisArg == NULL) {
+    PYM_pythonExceptionToJs(context);
+    return JS_FALSE;
+  }
+
+  PyObject *funcArgs = PyTuple_New(argc);
+  if (funcArgs == NULL) {
+    Py_DECREF(pyThisArg);
+    JS_ReportOutOfMemory(cx);
+    return JS_FALSE;
+  }
+
+  for (unsigned int i = 0; i < argc; i++) {
+    PyObject *arg = PYM_jsvalToPyObject(context, argv[i]);
+    if (arg == NULL || PyTuple_SetItem(funcArgs, i, arg)) {
+      if (arg)
+        Py_DECREF(arg);
+      Py_DECREF(funcArgs);
+      Py_DECREF(pyThisArg);
+      PYM_pythonExceptionToJs(context);
+      return JS_FALSE;
+    }
+  }
+
+  PyObject *args = PyTuple_Pack(3,
+                                (PyObject *) context,
+                                pyThisArg,
+                                funcArgs);
+  Py_DECREF(pyThisArg);
+  Py_DECREF(funcArgs);
+  if (args == NULL) {
+    JS_ReportOutOfMemory(cx);
+    return JS_FALSE;
+  }
+
+  PyObject *result = PyObject_Call(callable, args, NULL);
+  Py_DECREF(args);
+  if (result == NULL) {
+    PYM_pythonExceptionToJs(context);
+    return JS_FALSE;
+  }
+
+  int error = PYM_pyObjectToJsval(context, result, rval);
+  Py_DECREF(result);
+
+  if (error) {
+    PYM_pythonExceptionToJs(context);
+    return JS_FALSE;
+  }
+
+  return JS_TRUE;
+}
+
+PyTypeObject PYM_JSFunctionType = {
+  PyObject_HEAD_INIT(NULL)
+  0,                           /*ob_size*/
+  "pymonkey.Function",         /*tp_name*/
+  sizeof(PYM_JSFunction),      /*tp_basicsize*/
+  0,                           /*tp_itemsize*/
+  /*tp_dealloc*/
+  (destructor) PYM_JSFunctionDealloc,
+  0,                           /*tp_print*/
+  0,                           /*tp_getattr*/
+  0,                           /*tp_setattr*/
+  0,                           /*tp_compare*/
+  0,                           /*tp_repr*/
+  0,                           /*tp_as_number*/
+  0,                           /*tp_as_sequence*/
+  0,                           /*tp_as_mapping*/
+  0,                           /*tp_hash */
+  0,                           /*tp_call*/
+  0,                           /*tp_str*/
+  0,                           /*tp_getattro*/
+  0,                           /*tp_setattro*/
+  0,                           /*tp_as_buffer*/
+  /*tp_flags*/
+  Py_TPFLAGS_DEFAULT,
+  /* tp_doc */
+  "JavaScript Function.",
+  0,		               /* tp_traverse */
+  0,		               /* tp_clear */
+  0,		               /* tp_richcompare */
+  0,                           /* tp_weaklistoffset */
+  0,		               /* tp_iter */
+  0,		               /* tp_iternext */
+  0,                           /* tp_methods */
+  0,                           /* tp_members */
+  0,                           /* tp_getset */
+  0,                           /* tp_base */
+  0,                           /* tp_dict */
+  0,                           /* tp_descr_get */
+  0,                           /* tp_descr_set */
+  0,                           /* tp_dictoffset */
+  0,                           /* tp_init */
+  0,                           /* tp_alloc */
+  0,                           /* tp_new */
+};
+
+PYM_JSFunction *
+PYM_newJSFunctionFromCallable(PYM_JSContextObject *context,
+                              PyObject *callable,
+                              const char *name)
+{
+  if (!PyCallable_Check(callable)) {
+    PyErr_SetString(PyExc_TypeError, "Callable must be callable");
+    return NULL;
+  }
+
+  JSFunction *func = JS_NewFunction(context->cx,
+                                    PYM_dispatchJSFunctionToPython, 0,
+                                    0, NULL, name);
+
+  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;
+  }
+
+  PYM_JSFunction *object = PyObject_New(PYM_JSFunction,
+                                        &PYM_JSFunctionType);
+  if (object == NULL)
+    return NULL;
+
+  if (PYM_newJSObject(context, funcObj,
+                      (PYM_JSObject *) object) == NULL)
+    // Note that our object's reference count will have already
+    // been decremented by PYM_newJSObject().
+    return NULL;
+
+  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;
+  }
+
+  if (!JS_SetReservedSlot(context->cx, funcObj, 0,
+                          OBJECT_TO_JSVAL(functionHolder))) {
+    Py_DECREF((PyObject *) object);
+    PyErr_SetString(PYM_error, "JS_SetReservedSlot() failed");
+    return NULL;
+  }
+
+  return object;
+}
--- a/manage.py	Sat Aug 15 00:50:55 2009 -0700
+++ b/manage.py	Sat Aug 15 10:24:17 2009 -0700
@@ -75,13 +75,13 @@
             "-Wall",
             "-o", "pymonkey.so",
             "-dynamiclib",
-            "pymonkey.c",
-            "utils.c",
-            "object.c",
-            "function.c",
-            "undefined.c",
-            "context.c",
-            "runtime.c"]
+            "pymonkey.cpp",
+            "utils.cpp",
+            "object.cpp",
+            "function.cpp",
+            "undefined.cpp",
+            "context.cpp",
+            "runtime.cpp"]
 
     if options.get("static"):
         args.append(os.path.join(objdir, "libjs_static.a"))
--- a/object.c	Sat Aug 15 00:50:55 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Pymonkey.
- *
- * The Initial Developer of the Original Code is Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Atul Varma <atul@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "object.h"
-#include "function.h"
-#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_SetPrivate(cx, obj, pyObject))
-      return NULL;
-    Py_XINCREF(pyObject);
-  }
-  return obj;
-}
-
-JSBool
-PYM_JS_setPrivatePyObject(JSContext *cx, JSObject *obj, PyObject *pyObject)
-{
-  PyObject *old;
-  if (!PYM_JS_getPrivatePyObject(cx, obj, &old))
-    return JS_FALSE;
-  if (!JS_SetPrivate(cx, obj, 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;
-  }
-
-  *pyObject = (PyObject *) JS_GetPrivate(cx, obj);
-  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 | JSCLASS_HAS_PRIVATE,
-  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, PYM_JS_finalizeObject,
-  JSCLASS_NO_OPTIONAL_MEMBERS
-};
-
-static void
-PYM_JSObjectDealloc(PYM_JSObject *self)
-{
-  if (self->obj) {
-    JS_DHashTableOperate(&self->runtime->objects,
-                         (void *) self->obj,
-                         JS_DHASH_REMOVE);
-
-    // JS_RemoveRoot() always returns JS_TRUE, so don't
-    // bother checking its return value.
-    JS_RemoveRootRT(self->runtime->rt, &self->obj);
-    self->obj = NULL;
-  }
-
-  if (self->runtime) {
-    Py_DECREF(self->runtime);
-    self->runtime = NULL;
-  }
-
-  self->ob_type->tp_free((PyObject *) self);
-}
-
-static PyObject *
-PYM_getRuntime(PYM_JSObject *self, PyObject *args)
-{
-  Py_INCREF(self->runtime);
-  return (PyObject *) self->runtime;
-}
-
-static PyMethodDef PYM_JSObjectMethods[] = {
-  {"get_runtime", (PyCFunction) PYM_getRuntime, METH_VARARGS,
-   "Get the JavaScript runtime associated with this object."},
-  {NULL, NULL, 0, NULL}
-};
-
-PyTypeObject PYM_JSObjectType = {
-  PyObject_HEAD_INIT(NULL)
-  0,                           /*ob_size*/
-  "pymonkey.Object",           /*tp_name*/
-  sizeof(PYM_JSObject),        /*tp_basicsize*/
-  0,                           /*tp_itemsize*/
-  /*tp_dealloc*/
-  (destructor) PYM_JSObjectDealloc,
-  0,                           /*tp_print*/
-  0,                           /*tp_getattr*/
-  0,                           /*tp_setattr*/
-  0,                           /*tp_compare*/
-  0,                           /*tp_repr*/
-  0,                           /*tp_as_number*/
-  0,                           /*tp_as_sequence*/
-  0,                           /*tp_as_mapping*/
-  0,                           /*tp_hash */
-  0,                           /*tp_call*/
-  0,                           /*tp_str*/
-  0,                           /*tp_getattro*/
-  0,                           /*tp_setattro*/
-  0,                           /*tp_as_buffer*/
-  /*tp_flags*/
-  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-  /* tp_doc */
-  "JavaScript Object.",
-  0,		               /* tp_traverse */
-  0,		               /* tp_clear */
-  0,		               /* tp_richcompare */
-  0,                           /* tp_weaklistoffset */
-  0,		               /* tp_iter */
-  0,		               /* tp_iternext */
-  PYM_JSObjectMethods,         /* tp_methods */
-  0,                           /* tp_members */
-  0,                           /* tp_getset */
-  0,                           /* tp_base */
-  0,                           /* tp_dict */
-  0,                           /* tp_descr_get */
-  0,                           /* tp_descr_set */
-  0,                           /* tp_dictoffset */
-  0,                           /* tp_init */
-  0,                           /* tp_alloc */
-  0,                           /* tp_new */
-};
-
-PYM_JSObject *PYM_newJSObject(PYM_JSContextObject *context,
-                              JSObject *obj,
-                              PYM_JSObject *subclass) {
-  PYM_JSRuntimeObject *runtime = context->runtime;
-  PYM_HashEntry *cached = (PYM_HashEntry *) JS_DHashTableOperate(
-    &runtime->objects,
-    (void *) obj,
-    JS_DHASH_LOOKUP
-    );
-
-  if (JS_DHASH_ENTRY_IS_BUSY((JSDHashEntryHdr *) cached)) {
-    Py_INCREF((PyObject *) cached->value);
-    return (PYM_JSObject *) cached->value;
-  }
-
-  PYM_JSObject *object;
-
-  if (subclass)
-    object = subclass;
-  else {
-    if (JS_ObjectIsFunction(context->cx, obj)) {
-      PYM_JSFunction *func = PyObject_New(PYM_JSFunction,
-                                          &PYM_JSFunctionType);
-      object = (PYM_JSObject *) func;
-    } else
-      object = PyObject_New(PYM_JSObject,
-                            &PYM_JSObjectType);
-  }
-
-  if (object == NULL)
-    return NULL;
-
-  object->runtime = NULL;
-  object->obj = NULL;
-
-  cached = (PYM_HashEntry *) JS_DHashTableOperate(&runtime->objects,
-                                                  (void *) obj,
-                                                  JS_DHASH_ADD);
-  if (cached == NULL) {
-    Py_DECREF(object);
-    PyErr_SetString(PYM_error, "JS_DHashTableOperate() failed");
-    return NULL;
-  }
-
-  cached->base.key = (void *) obj;
-  cached->value = object;
-
-  object->runtime = context->runtime;
-  Py_INCREF(object->runtime);
-
-  object->obj = obj;
-
-  JS_AddNamedRootRT(object->runtime->rt, &object->obj,
-                    "Pymonkey-Generated Object");
-
-  return object;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/object.cpp	Sat Aug 15 10:24:17 2009 -0700
@@ -0,0 +1,238 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Pymonkey.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Atul Varma <atul@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "object.h"
+#include "function.h"
+#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_SetPrivate(cx, obj, pyObject))
+      return NULL;
+    Py_XINCREF(pyObject);
+  }
+  return obj;
+}
+
+JSBool
+PYM_JS_setPrivatePyObject(JSContext *cx, JSObject *obj, PyObject *pyObject)
+{
+  PyObject *old;
+  if (!PYM_JS_getPrivatePyObject(cx, obj, &old))
+    return JS_FALSE;
+  if (!JS_SetPrivate(cx, obj, 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;
+  }
+
+  *pyObject = (PyObject *) JS_GetPrivate(cx, obj);
+  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 | JSCLASS_HAS_PRIVATE,
+  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, PYM_JS_finalizeObject,
+  JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static void
+PYM_JSObjectDealloc(PYM_JSObject *self)
+{
+  if (self->obj) {
+    JS_DHashTableOperate(&self->runtime->objects,
+                         (void *) self->obj,
+                         JS_DHASH_REMOVE);
+
+    // JS_RemoveRoot() always returns JS_TRUE, so don't
+    // bother checking its return value.
+    JS_RemoveRootRT(self->runtime->rt, &self->obj);
+    self->obj = NULL;
+  }
+
+  if (self->runtime) {
+    Py_DECREF(self->runtime);
+    self->runtime = NULL;
+  }
+
+  self->ob_type->tp_free((PyObject *) self);
+}
+
+static PyObject *
+PYM_getRuntime(PYM_JSObject *self, PyObject *args)
+{
+  Py_INCREF(self->runtime);
+  return (PyObject *) self->runtime;
+}
+
+static PyMethodDef PYM_JSObjectMethods[] = {
+  {"get_runtime", (PyCFunction) PYM_getRuntime, METH_VARARGS,
+   "Get the JavaScript runtime associated with this object."},
+  {NULL, NULL, 0, NULL}
+};
+
+PyTypeObject PYM_JSObjectType = {
+  PyObject_HEAD_INIT(NULL)
+  0,                           /*ob_size*/
+  "pymonkey.Object",           /*tp_name*/
+  sizeof(PYM_JSObject),        /*tp_basicsize*/
+  0,                           /*tp_itemsize*/
+  /*tp_dealloc*/
+  (destructor) PYM_JSObjectDealloc,
+  0,                           /*tp_print*/
+  0,                           /*tp_getattr*/
+  0,                           /*tp_setattr*/
+  0,                           /*tp_compare*/
+  0,                           /*tp_repr*/
+  0,                           /*tp_as_number*/
+  0,                           /*tp_as_sequence*/
+  0,                           /*tp_as_mapping*/
+  0,                           /*tp_hash */
+  0,                           /*tp_call*/
+  0,                           /*tp_str*/
+  0,                           /*tp_getattro*/
+  0,                           /*tp_setattro*/
+  0,                           /*tp_as_buffer*/
+  /*tp_flags*/
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+  /* tp_doc */
+  "JavaScript Object.",
+  0,		               /* tp_traverse */
+  0,		               /* tp_clear */
+  0,		               /* tp_richcompare */
+  0,                           /* tp_weaklistoffset */
+  0,		               /* tp_iter */
+  0,		               /* tp_iternext */
+  PYM_JSObjectMethods,         /* tp_methods */
+  0,                           /* tp_members */
+  0,                           /* tp_getset */
+  0,                           /* tp_base */
+  0,                           /* tp_dict */
+  0,                           /* tp_descr_get */
+  0,                           /* tp_descr_set */
+  0,                           /* tp_dictoffset */
+  0,                           /* tp_init */
+  0,                           /* tp_alloc */
+  0,                           /* tp_new */
+};
+
+PYM_JSObject *PYM_newJSObject(PYM_JSContextObject *context,
+                              JSObject *obj,
+                              PYM_JSObject *subclass) {
+  PYM_JSRuntimeObject *runtime = context->runtime;
+  PYM_HashEntry *cached = (PYM_HashEntry *) JS_DHashTableOperate(
+    &runtime->objects,
+    (void *) obj,
+    JS_DHASH_LOOKUP
+    );
+
+  if (JS_DHASH_ENTRY_IS_BUSY((JSDHashEntryHdr *) cached)) {
+    Py_INCREF((PyObject *) cached->value);
+    return (PYM_JSObject *) cached->value;
+  }
+
+  PYM_JSObject *object;
+
+  if (subclass)
+    object = subclass;
+  else {
+    if (JS_ObjectIsFunction(context->cx, obj)) {
+      PYM_JSFunction *func = PyObject_New(PYM_JSFunction,
+                                          &PYM_JSFunctionType);
+      object = (PYM_JSObject *) func;
+    } else
+      object = PyObject_New(PYM_JSObject,
+                            &PYM_JSObjectType);
+  }
+
+  if (object == NULL)
+    return NULL;
+
+  object->runtime = NULL;
+  object->obj = NULL;
+
+  cached = (PYM_HashEntry *) JS_DHashTableOperate(&runtime->objects,
+                                                  (void *) obj,
+                                                  JS_DHASH_ADD);
+  if (cached == NULL) {
+    Py_DECREF(object);
+    PyErr_SetString(PYM_error, "JS_DHashTableOperate() failed");
+    return NULL;
+  }
+
+  cached->base.key = (void *) obj;
+  cached->value = object;
+
+  object->runtime = context->runtime;
+  Py_INCREF(object->runtime);
+
+  object->obj = obj;
+
+  JS_AddNamedRootRT(object->runtime->rt, &object->obj,
+                    "Pymonkey-Generated Object");
+
+  return object;
+}
--- a/pymonkey.c	Sat Aug 15 00:50:55 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Pymonkey.
- *
- * The Initial Developer of the Original Code is Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Atul Varma <atul@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "undefined.h"
-#include "runtime.h"
-#include "context.h"
-#include "object.h"
-#include "function.h"
-#include "utils.h"
-
-static PyMethodDef PYM_methods[] = {
-  {NULL, NULL, 0, NULL}
-};
-
-PyMODINIT_FUNC
-initpymonkey(void)
-{
-  PyObject *module;
-
-  module = Py_InitModule("pymonkey", PYM_methods);
-  if (module == NULL)
-    return;
-
-  if (PyType_Ready(&PYM_undefinedType) < 0)
-    return;
-
-  PYM_undefined = PyObject_New(PYM_undefinedObject, &PYM_undefinedType);
-  if (PYM_undefined == NULL)
-    return;
-  Py_INCREF(PYM_undefined);
-  PyModule_AddObject(module, "undefined", (PyObject *) PYM_undefined);
-
-  PYM_error = PyErr_NewException("pymonkey.error", NULL, NULL);
-  Py_INCREF(PYM_error);
-  PyModule_AddObject(module, "error", PYM_error);
-
-  if (!PyType_Ready(&PYM_JSRuntimeType) < 0)
-    return;
-
-  Py_INCREF(&PYM_JSRuntimeType);
-  PyModule_AddObject(module, "Runtime", (PyObject *) &PYM_JSRuntimeType);
-
-  if (!PyType_Ready(&PYM_JSContextType) < 0)
-    return;
-
-  Py_INCREF(&PYM_JSContextType);
-  PyModule_AddObject(module, "Context", (PyObject *) &PYM_JSContextType);
-
-  if (!PyType_Ready(&PYM_JSObjectType) < 0)
-    return;
-
-  Py_INCREF(&PYM_JSObjectType);
-  PyModule_AddObject(module, "Object", (PyObject *) &PYM_JSObjectType);
-
-  PYM_JSFunctionType.tp_base = &PYM_JSObjectType;
-  if (!PyType_Ready(&PYM_JSFunctionType) < 0)
-    return;
-
-  Py_INCREF(&PYM_JSFunctionType);
-  PyModule_AddObject(module, "Function", (PyObject *) &PYM_JSFunctionType);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pymonkey.cpp	Sat Aug 15 10:24:17 2009 -0700
@@ -0,0 +1,94 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Pymonkey.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Atul Varma <atul@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "undefined.h"
+#include "runtime.h"
+#include "context.h"
+#include "object.h"
+#include "function.h"
+#include "utils.h"
+
+static PyMethodDef PYM_methods[] = {
+  {NULL, NULL, 0, NULL}
+};
+
+PyMODINIT_FUNC
+initpymonkey(void)
+{
+  PyObject *module;
+
+  module = Py_InitModule("pymonkey", PYM_methods);
+  if (module == NULL)
+    return;
+
+  if (PyType_Ready(&PYM_undefinedType) < 0)
+    return;
+
+  PYM_undefined = PyObject_New(PYM_undefinedObject, &PYM_undefinedType);
+  if (PYM_undefined == NULL)
+    return;
+  Py_INCREF(PYM_undefined);
+  PyModule_AddObject(module, "undefined", (PyObject *) PYM_undefined);
+
+  PYM_error = PyErr_NewException("pymonkey.error", NULL, NULL);
+  Py_INCREF(PYM_error);
+  PyModule_AddObject(module, "error", PYM_error);
+
+  if (!PyType_Ready(&PYM_JSRuntimeType) < 0)
+    return;
+
+  Py_INCREF(&PYM_JSRuntimeType);
+  PyModule_AddObject(module, "Runtime", (PyObject *) &PYM_JSRuntimeType);
+
+  if (!PyType_Ready(&PYM_JSContextType) < 0)
+    return;
+
+  Py_INCREF(&PYM_JSContextType);
+  PyModule_AddObject(module, "Context", (PyObject *) &PYM_JSContextType);
+
+  if (!PyType_Ready(&PYM_JSObjectType) < 0)
+    return;
+
+  Py_INCREF(&PYM_JSObjectType);
+  PyModule_AddObject(module, "Object", (PyObject *) &PYM_JSObjectType);
+
+  PYM_JSFunctionType.tp_base = &PYM_JSObjectType;
+  if (!PyType_Ready(&PYM_JSFunctionType) < 0)
+    return;
+
+  Py_INCREF(&PYM_JSFunctionType);
+  PyModule_AddObject(module, "Function", (PyObject *) &PYM_JSFunctionType);
+}
--- a/runtime.c	Sat Aug 15 00:50:55 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Pymonkey.
- *
- * The Initial Developer of the Original Code is Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Atul Varma <atul@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "runtime.h"
-#include "context.h"
-#include "utils.h"
-
-static PyObject *
-PYM_JSRuntimeNew(PyTypeObject *type, PyObject *args,
-                 PyObject *kwds)
-{
-  PYM_JSRuntimeObject *self;
-
-  self = (PYM_JSRuntimeObject *) type->tp_alloc(type, 0);
-  if (self != NULL) {
-    self->thread = PyThread_get_thread_ident();
-    self->rt = NULL;
-    self->cx = NULL;
-    self->objects.ops = NULL;
-
-    if (!JS_DHashTableInit(&self->objects,
-                           JS_DHashGetStubOps(),
-                           NULL,
-                           sizeof(PYM_HashEntry),
-                           JS_DHASH_DEFAULT_CAPACITY(100))) {
-      PyErr_SetString(PYM_error, "JS_DHashTableInit() failed");
-      type->tp_dealloc((PyObject *) self);
-      self = NULL;
-    }
-
-    if (self != NULL) {
-      self->rt = JS_NewRuntime(8L * 1024L * 1024L);
-      if (!self->rt) {
-        PyErr_SetString(PYM_error, "JS_NewRuntime() failed");
-        type->tp_dealloc((PyObject *) self);
-        self = NULL;
-      } else {
-        self->cx = JS_NewContext(self->rt, 8192);
-        if (!self->cx) {
-          PyErr_SetString(PYM_error, "JS_NewContext() failed");
-          type->tp_dealloc((PyObject *) self);
-          self = NULL;
-        }
-      }
-    }
-  }
-
-  return (PyObject *) self;
-}
-
-static void
-PYM_JSRuntimeDealloc(PYM_JSRuntimeObject *self)
-{
-  if (self->objects.ops) {
-    JS_DHashTableFinish(&self->objects);
-    self->objects.ops = NULL;
-  }
-
-  if (self->cx) {
-    // Note that this will also force GC of any remaining objects
-    // in the runtime.
-    JS_DestroyContext(self->cx);
-    self->cx = NULL;
-  }
-
-  if (self->rt) {
-    JS_DestroyRuntime(self->rt);
-    self->rt = NULL;
-  }
-
-  self->ob_type->tp_free((PyObject *) self);
-}
-
-static PyObject *
-PYM_newContext(PYM_JSRuntimeObject *self, PyObject *args)
-{
-  PYM_SANITY_CHECK(self);
-  JSContext *cx = JS_NewContext(self->rt, 8192);
-  if (cx == NULL) {
-    PyErr_SetString(PYM_error, "JS_NewContext() failed");
-    return NULL;
-  }
-
-  JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_DONT_REPORT_UNCAUGHT |
-                JSOPTION_ATLINE | JSOPTION_STRICT);
-  JS_SetVersion(cx, JSVERSION_LATEST);
-
-  PyObject *retval = (PyObject *) PYM_newJSContextObject(self, cx);
-
-  if (retval == NULL)
-    JS_DestroyContext(cx);
-
-  return retval;
-}
-
-static PyMethodDef PYM_JSRuntimeMethods[] = {
-  {"new_context", (PyCFunction) PYM_newContext, METH_VARARGS,
-   "Create a new JavaScript context."},
-  {NULL, NULL, 0, NULL}
-};
-
-PyTypeObject PYM_JSRuntimeType = {
-  PyObject_HEAD_INIT(NULL)
-  0,                           /*ob_size*/
-  "pymonkey.Runtime",          /*tp_name*/
-  sizeof(PYM_JSRuntimeObject), /*tp_basicsize*/
-  0,                           /*tp_itemsize*/
-  /*tp_dealloc*/
-  (destructor) PYM_JSRuntimeDealloc,
-  0,                           /*tp_print*/
-  0,                           /*tp_getattr*/
-  0,                           /*tp_setattr*/
-  0,                           /*tp_compare*/
-  0,                           /*tp_repr*/
-  0,                           /*tp_as_number*/
-  0,                           /*tp_as_sequence*/
-  0,                           /*tp_as_mapping*/
-  0,                           /*tp_hash */
-  0,                           /*tp_call*/
-  0,                           /*tp_str*/
-  0,                           /*tp_getattro*/
-  0,                           /*tp_setattro*/
-  0,                           /*tp_as_buffer*/
-  Py_TPFLAGS_DEFAULT,          /*tp_flags*/
-  /* tp_doc */
-  "JavaScript Runtime.",
-  0,		               /* tp_traverse */
-  0,		               /* tp_clear */
-  0,		               /* tp_richcompare */
-  0,		               /* tp_weaklistoffset */
-  0,		               /* tp_iter */
-  0,		               /* tp_iternext */
-  PYM_JSRuntimeMethods,        /* tp_methods */
-  0,                           /* tp_members */
-  0,                           /* tp_getset */
-  0,                           /* tp_base */
-  0,                           /* tp_dict */
-  0,                           /* tp_descr_get */
-  0,                           /* tp_descr_set */
-  0,                           /* tp_dictoffset */
-  0,                           /* tp_init */
-  0,                           /* tp_alloc */
-  PYM_JSRuntimeNew,            /* tp_new */
-};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime.cpp	Sat Aug 15 10:24:17 2009 -0700
@@ -0,0 +1,177 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Pymonkey.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Atul Varma <atul@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "runtime.h"
+#include "context.h"
+#include "utils.h"
+
+static PyObject *
+PYM_JSRuntimeNew(PyTypeObject *type, PyObject *args,
+                 PyObject *kwds)
+{
+  PYM_JSRuntimeObject *self;
+
+  self = (PYM_JSRuntimeObject *) type->tp_alloc(type, 0);
+  if (self != NULL) {
+    self->thread = PyThread_get_thread_ident();
+    self->rt = NULL;
+    self->cx = NULL;
+    self->objects.ops = NULL;
+
+    if (!JS_DHashTableInit(&self->objects,
+                           JS_DHashGetStubOps(),
+                           NULL,
+                           sizeof(PYM_HashEntry),
+                           JS_DHASH_DEFAULT_CAPACITY(100))) {
+      PyErr_SetString(PYM_error, "JS_DHashTableInit() failed");
+      type->tp_dealloc((PyObject *) self);
+      self = NULL;
+    }
+
+    if (self != NULL) {
+      self->rt = JS_NewRuntime(8L * 1024L * 1024L);
+      if (!self->rt) {
+        PyErr_SetString(PYM_error, "JS_NewRuntime() failed");
+        type->tp_dealloc((PyObject *) self);
+        self = NULL;
+      } else {
+        self->cx = JS_NewContext(self->rt, 8192);
+        if (!self->cx) {
+          PyErr_SetString(PYM_error, "JS_NewContext() failed");
+          type->tp_dealloc((PyObject *) self);
+          self = NULL;
+        }
+      }
+    }
+  }
+
+  return (PyObject *) self;
+}
+
+static void
+PYM_JSRuntimeDealloc(PYM_JSRuntimeObject *self)
+{
+  if (self->objects.ops) {
+    JS_DHashTableFinish(&self->objects);
+    self->objects.ops = NULL;
+  }
+
+  if (self->cx) {
+    // Note that this will also force GC of any remaining objects
+    // in the runtime.
+    JS_DestroyContext(self->cx);
+    self->cx = NULL;
+  }
+
+  if (self->rt) {
+    JS_DestroyRuntime(self->rt);
+    self->rt = NULL;
+  }
+
+  self->ob_type->tp_free((PyObject *) self);
+}
+
+static PyObject *
+PYM_newContext(PYM_JSRuntimeObject *self, PyObject *args)
+{
+  PYM_SANITY_CHECK(self);
+  JSContext *cx = JS_NewContext(self->rt, 8192);
+  if (cx == NULL) {
+    PyErr_SetString(PYM_error, "JS_NewContext() failed");
+    return NULL;
+  }
+
+  JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_DONT_REPORT_UNCAUGHT |
+                JSOPTION_ATLINE | JSOPTION_STRICT);
+  JS_SetVersion(cx, JSVERSION_LATEST);
+
+  PyObject *retval = (PyObject *) PYM_newJSContextObject(self, cx);
+
+  if (retval == NULL)
+    JS_DestroyContext(cx);
+
+  return retval;
+}
+
+static PyMethodDef PYM_JSRuntimeMethods[] = {
+  {"new_context", (PyCFunction) PYM_newContext, METH_VARARGS,
+   "Create a new JavaScript context."},
+  {NULL, NULL, 0, NULL}
+};
+
+PyTypeObject PYM_JSRuntimeType = {
+  PyObject_HEAD_INIT(NULL)
+  0,                           /*ob_size*/
+  "pymonkey.Runtime",          /*tp_name*/
+  sizeof(PYM_JSRuntimeObject), /*tp_basicsize*/
+  0,                           /*tp_itemsize*/
+  /*tp_dealloc*/
+  (destructor) PYM_JSRuntimeDealloc,
+  0,                           /*tp_print*/
+  0,                           /*tp_getattr*/
+  0,                           /*tp_setattr*/
+  0,                           /*tp_compare*/
+  0,                           /*tp_repr*/
+  0,                           /*tp_as_number*/
+  0,                           /*tp_as_sequence*/
+  0,                           /*tp_as_mapping*/
+  0,                           /*tp_hash */
+  0,                           /*tp_call*/
+  0,                           /*tp_str*/
+  0,                           /*tp_getattro*/
+  0,                           /*tp_setattro*/
+  0,                           /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,          /*tp_flags*/
+  /* tp_doc */
+  "JavaScript Runtime.",
+  0,		               /* tp_traverse */
+  0,		               /* tp_clear */
+  0,		               /* tp_richcompare */
+  0,		               /* tp_weaklistoffset */
+  0,		               /* tp_iter */
+  0,		               /* tp_iternext */
+  PYM_JSRuntimeMethods,        /* tp_methods */
+  0,                           /* tp_members */
+  0,                           /* tp_getset */
+  0,                           /* tp_base */
+  0,                           /* tp_dict */
+  0,                           /* tp_descr_get */
+  0,                           /* tp_descr_set */
+  0,                           /* tp_dictoffset */
+  0,                           /* tp_init */
+  0,                           /* tp_alloc */
+  PYM_JSRuntimeNew,            /* tp_new */
+};
--- a/undefined.c	Sat Aug 15 00:50:55 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Pymonkey.
- *
- * The Initial Developer of the Original Code is Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Atul Varma <atul@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "undefined.h"
-
-static Py_ssize_t PYM_undefinedLength(PyObject *o) {
-  return 0;
-};
-
-static PyMappingMethods PYM_undefinedAsMapping = {
-  PYM_undefinedLength,         /*mp_length*/
-  0,                           /*mp_subscript*/
-  0                            /*mp_ass_subscript*/
-};
-
-static PyObject *PYM_undefinedRepr(PyObject *o) {
-  return PyString_FromString("pymonkey.undefined");
-}
-
-// TODO: We should make this behave as much like JavaScript's
-// "undefined" value as possible; e.g., its string value should
-// be "undefined", the singleton should be falsy, etc.
-PyTypeObject PYM_undefinedType = {
-  PyObject_HEAD_INIT(NULL)
-  0,                           /*ob_size*/
-  "pymonkey.undefined",        /*tp_name*/
-  sizeof(PYM_undefinedObject), /*tp_basicsize*/
-  0,                           /*tp_itemsize*/
-  0,                           /*tp_dealloc*/
-  0,                           /*tp_print*/
-  0,                           /*tp_getattr*/
-  0,                           /*tp_setattr*/
-  0,                           /*tp_compare*/
-  PYM_undefinedRepr,           /*tp_repr*/
-  0,                           /*tp_as_number*/
-  0,                           /*tp_as_sequence*/
-  &PYM_undefinedAsMapping,     /*tp_as_mapping*/
-  0,                           /*tp_hash */
-  0,                           /*tp_call*/
-  PYM_undefinedRepr,           /*tp_str*/
-  0,                           /*tp_getattro*/
-  0,                           /*tp_setattro*/
-  0,                           /*tp_as_buffer*/
-  Py_TPFLAGS_DEFAULT,          /*tp_flags*/
-  /* tp_doc */
-  "Pythonic equivalent of JavaScript's 'undefined' value",
-};
-
-PYM_undefinedObject *PYM_undefined;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/undefined.cpp	Sat Aug 15 10:24:17 2009 -0700
@@ -0,0 +1,82 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Pymonkey.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Atul Varma <atul@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "undefined.h"
+
+static Py_ssize_t PYM_undefinedLength(PyObject *o) {
+  return 0;
+};
+
+static PyMappingMethods PYM_undefinedAsMapping = {
+  PYM_undefinedLength,         /*mp_length*/
+  0,                           /*mp_subscript*/
+  0                            /*mp_ass_subscript*/
+};
+
+static PyObject *PYM_undefinedRepr(PyObject *o) {
+  return PyString_FromString("pymonkey.undefined");
+}
+
+// TODO: We should make this behave as much like JavaScript's
+// "undefined" value as possible; e.g., its string value should
+// be "undefined", the singleton should be falsy, etc.
+PyTypeObject PYM_undefinedType = {
+  PyObject_HEAD_INIT(NULL)
+  0,                           /*ob_size*/
+  "pymonkey.undefined",        /*tp_name*/
+  sizeof(PYM_undefinedObject), /*tp_basicsize*/
+  0,                           /*tp_itemsize*/
+  0,                           /*tp_dealloc*/
+  0,                           /*tp_print*/
+  0,                           /*tp_getattr*/
+  0,                           /*tp_setattr*/
+  0,                           /*tp_compare*/
+  PYM_undefinedRepr,           /*tp_repr*/
+  0,                           /*tp_as_number*/
+  0,                           /*tp_as_sequence*/
+  &PYM_undefinedAsMapping,     /*tp_as_mapping*/
+  0,                           /*tp_hash */
+  0,                           /*tp_call*/
+  PYM_undefinedRepr,           /*tp_str*/
+  0,                           /*tp_getattro*/
+  0,                           /*tp_setattro*/
+  0,                           /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,          /*tp_flags*/
+  /* tp_doc */
+  "Pythonic equivalent of JavaScript's 'undefined' value",
+};
+
+PYM_undefinedObject *PYM_undefined;
--- a/utils.c	Sat Aug 15 00:50:55 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Pymonkey.
- *
- * The Initial Developer of the Original Code is Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Atul Varma <atul@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "utils.h"
-#include "undefined.h"
-#include "object.h"
-
-PyObject *PYM_error;
-
-static int
-PYM_doubleToJsval(PYM_JSContextObject *context,
-                  double number,
-                  jsval *rval)
-{
-  jsdouble *numberAsJsdouble = JS_NewDouble(context->cx, number);
-  if (numberAsJsdouble == NULL) {
-    PyErr_SetString(PYM_error, "JS_NewDouble() failed");
-    return -1;
-  }
-  *rval = DOUBLE_TO_JSVAL(numberAsJsdouble);
-  return 0;
-}
-
-int
-PYM_pyObjectToJsval(PYM_JSContextObject *context,
-                    PyObject *object,
-                    jsval *rval)
-{
-  if (PyString_Check(object) || PyUnicode_Check(object)) {
-    PyObject *unicode;
-    if (PyString_Check(object)) {
-      unicode = PyUnicode_FromObject(object);
-      if (unicode == NULL)
-        return -1;
-    } else {
-      unicode = object;
-      Py_INCREF(unicode);
-    }
-
-    PyObject *string = PyUnicode_AsUTF16String(unicode);
-    Py_DECREF(unicode);
-    if (string == NULL)
-      return -1;
-
-    char *buffer = PyString_AS_STRING(string);
-    Py_ssize_t size = PyString_GET_SIZE(string);
-
-    // Note that we're manipulating buffer and size here to get rid of
-    // the BOM.
-    JSString *jsString = JS_NewUCStringCopyN(context->cx,
-                                             (const jschar *) (buffer + 2),
-                                             (size / 2) - 1);
-    Py_DECREF(string);
-    if (jsString == NULL) {
-      PyErr_SetString(PYM_error, "JS_NewUCStringCopyN() failed");
-      return -1;
-    }
-
-    *rval = STRING_TO_JSVAL(jsString);
-    return 0;
-  }
-
-  if (PyInt_Check(object)) {
-    long number = PyInt_AS_LONG(object);
-    if (INT_FITS_IN_JSVAL(number)) {
-      *rval = INT_TO_JSVAL(number);
-      return 0;
-    } else
-      return PYM_doubleToJsval(context, number, rval);
-  }
-
-  if (PyFloat_Check(object))
-    return PYM_doubleToJsval(context, PyFloat_AS_DOUBLE(object), rval);
-
-  if (PyObject_TypeCheck(object, &PYM_JSObjectType)) {
-    PYM_JSObject *jsObject = (PYM_JSObject *) object;
-    JSRuntime *rt = JS_GetRuntime(context->cx);
-    if (rt != jsObject->runtime->rt) {
-      PyErr_SetString(PyExc_ValueError,
-                      "JS object and JS context are from different "
-                      "JS runtimes");
-      return -1;
-    }
-    *rval = OBJECT_TO_JSVAL(jsObject->obj);
-    return 0;
-  }
-
-  if (object == Py_True) {
-    *rval = JSVAL_TRUE;
-    return 0;
-  }
-
-  if (object == Py_False) {
-    *rval = JSVAL_FALSE;
-    return 0;
-  }
-
-  if (object == Py_None) {
-    *rval = JSVAL_NULL;
-    return 0;
-  }
-
-  // TODO: Support more types.
-  PyErr_SetString(PyExc_NotImplementedError,
-                  "Data type conversion not implemented.");
-  return -1;
-}
-
-PyObject *
-PYM_jsvalToPyObject(PYM_JSContextObject *context,
-                    jsval value) {
-  if (JSVAL_IS_INT(value))
-    return PyInt_FromLong(JSVAL_TO_INT(value));
-
-  if (JSVAL_IS_DOUBLE(value)) {
-    jsdouble *doubleRef = JSVAL_TO_DOUBLE(value);
-    return PyFloat_FromDouble(*doubleRef);
-  }
-
-  if (value == JSVAL_FALSE)
-    Py_RETURN_FALSE;
-
-  if (value == JSVAL_TRUE)
-    Py_RETURN_TRUE;
-
-  if (JSVAL_IS_NULL(value))
-    Py_RETURN_NONE;
-
-  if (JSVAL_IS_VOID(value))
-    Py_RETURN_UNDEFINED;
-
-  if (JSVAL_IS_STRING(value)) {
-    // Strings in JS are funky: think of them as 16-bit versions of
-    // Python 2.x's 'str' type.  Whether or not they're valid UTF-16
-    // is entirely up to the client code.
-
-    // TODO: Instead of ignoring errors, consider actually treating
-    // the string as a raw character buffer.
-    JSString *str = JSVAL_TO_STRING(value);
-    const char *chars = (const char *) JS_GetStringChars(str);
-    size_t length = JS_GetStringLength(str);
-
-    // We're multiplying length by two since Python wants the number
-    // of bytes, not the number of 16-bit characters.
-    return PyUnicode_DecodeUTF16(chars, length * 2, "ignore", NULL);
-  }
-
-  if (JSVAL_IS_OBJECT(value))
-    return (PyObject *) PYM_newJSObject(context, JSVAL_TO_OBJECT(value),
-                                        NULL);
-
-  // TODO: Support more types.
-  PyErr_SetString(PyExc_NotImplementedError,
-                  "Data type conversion not implemented.");
-  return NULL;
-}
-
-void
-PYM_pythonExceptionToJs(PYM_JSContextObject *context)
-{
-  PyObject *type;
-  PyObject *value;
-  PyObject *traceback;
-
-  PyErr_Fetch(&type, &value, &traceback);
-
-  if (type == PYM_error && value &&
-      PyObject_HasAttrString(value, "message")) {
-    jsval val;
-    PyObject *message = PyObject_GetAttrString(value, "message");
-    if (message && PYM_pyObjectToJsval(context, message, &val) == 0) {
-      JS_SetPendingException(context->cx, val);
-    } else
-      JS_ReportError(context->cx,
-                     "Python exception occurred, but exception "
-                     "couldn't be converted");
-    Py_XDECREF(message);
-  } else {
-    if (value) {
-      JSObject *exception = PYM_JS_newObject(context->cx, value);
-      if (exception)
-        JS_SetPendingException(context->cx, OBJECT_TO_JSVAL(exception));
-      else
-        JS_ReportOutOfMemory(context->cx);
-    } else
-      JS_ReportError(context->cx, "Python exception occurred");
-  }
-
-  Py_XDECREF(type);
-  Py_XDECREF(value);
-  Py_XDECREF(traceback);
-}
-
-void
-PYM_jsExceptionToPython(PYM_JSContextObject *context)
-{
-  if (!JS_IsExceptionPending(context->cx) &&
-      PyErr_Occurred())
-    return;
-
-  jsval val;
-  if (JS_GetPendingException(context->cx, &val)) {
-    PyObject *obj = PYM_jsvalToPyObject(context, val);
-    if (obj) {
-      PyErr_SetObject(PYM_error, obj);
-      Py_DECREF(obj);
-    } else {
-      PyErr_Clear();
-
-      JSString *str = NULL;
-
-      Py_BEGIN_ALLOW_THREADS;
-      str = JS_ValueToString(context->cx, val);
-      Py_END_ALLOW_THREADS;
-
-      if (str != NULL) {
-        const char *chars = JS_GetStringBytes(str);
-        PyErr_SetString(PYM_error, chars);
-      } else
-        PyErr_SetString(PYM_error, "JS exception occurred");
-    }
-  } else
-    PyErr_SetString(PYM_error, "JS_GetPendingException() failed");
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils.cpp	Sat Aug 15 10:24:17 2009 -0700
@@ -0,0 +1,257 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Pymonkey.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Atul Varma <atul@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "utils.h"
+#include "undefined.h"
+#include "object.h"
+
+PyObject *PYM_error;
+
+static int
+PYM_doubleToJsval(PYM_JSContextObject *context,
+                  double number,
+                  jsval *rval)
+{
+  jsdouble *numberAsJsdouble = JS_NewDouble(context->cx, number);
+  if (numberAsJsdouble == NULL) {
+    PyErr_SetString(PYM_error, "JS_NewDouble() failed");
+    return -1;
+  }
+  *rval = DOUBLE_TO_JSVAL(numberAsJsdouble);
+  return 0;
+}
+
+int
+PYM_pyObjectToJsval(PYM_JSContextObject *context,
+                    PyObject *object,
+                    jsval *rval)
+{
+  if (PyString_Check(object) || PyUnicode_Check(object)) {
+    PyObject *unicode;
+    if (PyString_Check(object)) {
+      unicode = PyUnicode_FromObject(object);
+      if (unicode == NULL)
+        return -1;
+    } else {
+      unicode = object;
+      Py_INCREF(unicode);
+    }
+
+    PyObject *string = PyUnicode_AsUTF16String(unicode);
+    Py_DECREF(unicode);
+    if (string == NULL)
+      return -1;
+
+    char *buffer = PyString_AS_STRING(string);
+    Py_ssize_t size = PyString_GET_SIZE(string);
+
+    // Note that we're manipulating buffer and size here to get rid of
+    // the BOM.
+    JSString *jsString = JS_NewUCStringCopyN(context->cx,
+                                             (const jschar *) (buffer + 2),
+                                             (size / 2) - 1);
+    Py_DECREF(string);
+    if (jsString == NULL) {
+      PyErr_SetString(PYM_error, "JS_NewUCStringCopyN() failed");
+      return -1;
+    }
+
+    *rval = STRING_TO_JSVAL(jsString);
+    return 0;
+  }
+
+  if (PyInt_Check(object)) {
+    long number = PyInt_AS_LONG(object);
+    if (INT_FITS_IN_JSVAL(number)) {
+      *rval = INT_TO_JSVAL(number);
+      return 0;
+    } else
+      return PYM_doubleToJsval(context, number, rval);
+  }
+
+  if (PyFloat_Check(object))
+    return PYM_doubleToJsval(context, PyFloat_AS_DOUBLE(object), rval);
+
+  if (PyObject_TypeCheck(object, &PYM_JSObjectType)) {
+    PYM_JSObject *jsObject = (PYM_JSObject *) object;
+    JSRuntime *rt = JS_GetRuntime(context->cx);
+    if (rt != jsObject->runtime->rt) {
+      PyErr_SetString(PyExc_ValueError,
+                      "JS object and JS context are from different "
+                      "JS runtimes");
+      return -1;
+    }
+    *rval = OBJECT_TO_JSVAL(jsObject->obj);
+    return 0;
+  }
+
+  if (object == Py_True) {
+    *rval = JSVAL_TRUE;
+    return 0;
+  }
+
+  if (object == Py_False) {
+    *rval = JSVAL_FALSE;
+    return 0;
+  }
+
+  if (object == Py_None) {
+    *rval = JSVAL_NULL;
+    return 0;
+  }
+
+  // TODO: Support more types.
+  PyErr_SetString(PyExc_NotImplementedError,
+                  "Data type conversion not implemented.");
+  return -1;
+}
+
+PyObject *
+PYM_jsvalToPyObject(PYM_JSContextObject *context,
+                    jsval value) {
+  if (JSVAL_IS_INT(value))
+    return PyInt_FromLong(JSVAL_TO_INT(value));
+
+  if (JSVAL_IS_DOUBLE(value)) {
+    jsdouble *doubleRef = JSVAL_TO_DOUBLE(value);
+    return PyFloat_FromDouble(*doubleRef);
+  }
+
+  if (value == JSVAL_FALSE)
+    Py_RETURN_FALSE;
+
+  if (value == JSVAL_TRUE)
+    Py_RETURN_TRUE;
+
+  if (JSVAL_IS_NULL(value))
+    Py_RETURN_NONE;
+
+  if (JSVAL_IS_VOID(value))
+    Py_RETURN_UNDEFINED;
+
+  if (JSVAL_IS_STRING(value)) {
+    // Strings in JS are funky: think of them as 16-bit versions of
+    // Python 2.x's 'str' type.  Whether or not they're valid UTF-16
+    // is entirely up to the client code.
+
+    // TODO: Instead of ignoring errors, consider actually treating
+    // the string as a raw character buffer.
+    JSString *str = JSVAL_TO_STRING(value);
+    const char *chars = (const char *) JS_GetStringChars(str);
+    size_t length = JS_GetStringLength(str);
+
+    // We're multiplying length by two since Python wants the number
+    // of bytes, not the number of 16-bit characters.
+    return PyUnicode_DecodeUTF16(chars, length * 2, "ignore", NULL);
+  }
+
+  if (JSVAL_IS_OBJECT(value))
+    return (PyObject *) PYM_newJSObject(context, JSVAL_TO_OBJECT(value),
+                                        NULL);
+
+  // TODO: Support more types.
+  PyErr_SetString(PyExc_NotImplementedError,
+                  "Data type conversion not implemented.");
+  return NULL;
+}
+
+void
+PYM_pythonExceptionToJs(PYM_JSContextObject *context)
+{
+  PyObject *type;
+  PyObject *value;
+  PyObject *traceback;
+
+  PyErr_Fetch(&type, &value, &traceback);
+
+  if (type == PYM_error && value &&
+      PyObject_HasAttrString(value, "message")) {
+    jsval val;
+    PyObject *message = PyObject_GetAttrString(value, "message");
+    if (message && PYM_pyObjectToJsval(context, message, &val) == 0) {
+      JS_SetPendingException(context->cx, val);
+    } else
+      JS_ReportError(context->cx,
+                     "Python exception occurred, but exception "
+                     "couldn't be converted");
+    Py_XDECREF(message);
+  } else {
+    if (value) {
+      JSObject *exception = PYM_JS_newObject(context->cx, value);
+      if (exception)
+        JS_SetPendingException(context->cx, OBJECT_TO_JSVAL(exception));
+      else
+        JS_ReportOutOfMemory(context->cx);
+    } else
+      JS_ReportError(context->cx, "Python exception occurred");
+  }
+
+  Py_XDECREF(type);
+  Py_XDECREF(value);
+  Py_XDECREF(traceback);
+}
+
+void
+PYM_jsExceptionToPython(PYM_JSContextObject *context)
+{
+  if (!JS_IsExceptionPending(context->cx) &&
+      PyErr_Occurred())
+    return;
+
+  jsval val;
+  if (JS_GetPendingException(context->cx, &val)) {
+    PyObject *obj = PYM_jsvalToPyObject(context, val);
+    if (obj) {
+      PyErr_SetObject(PYM_error, obj);
+      Py_DECREF(obj);
+    } else {
+      PyErr_Clear();
+
+      JSString *str = NULL;
+
+      Py_BEGIN_ALLOW_THREADS;
+      str = JS_ValueToString(context->cx, val);
+      Py_END_ALLOW_THREADS;
+
+      if (str != NULL) {
+        const char *chars = JS_GetStringBytes(str);
+        PyErr_SetString(PYM_error, chars);
+      } else
+        PyErr_SetString(PYM_error, "JS exception occurred");
+    }
+  } else
+    PyErr_SetString(PYM_error, "JS_GetPendingException() failed");
+}