Mercurial > pymonkey
changeset 22:988a8998c75f
JS objects reflected into Python are now identity-preserving, though the implementation for this is pretty bad right now.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Sun, 28 Jun 2009 21:49:07 -0700 |
parents | fc04e5f1c675 |
children | 951ad1b15587 |
files | object.c object.h runtime.c runtime.h test_pymonkey.py |
diffstat | 5 files changed, 90 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/object.c Sun Jun 28 20:40:18 2009 -0700 +++ b/object.c Sun Jun 28 21:49:07 2009 -0700 @@ -1,5 +1,6 @@ #include "object.h" #include "runtime.h" +#include "utils.h" JSClass PYM_JS_ObjectClass = { "PymonkeyObject", JSCLASS_GLOBAL_FLAGS, @@ -11,16 +12,26 @@ static void PYM_JSObjectDealloc(PYM_JSObject *self) { - // JS_RemoveRoot() always returns JS_TRUE, so don't - // bother checking its return value. + if (self->weakrefList) + PyObject_ClearWeakRefs((PyObject *) self); if (self->obj) { + if (PyDict_DelItem(self->runtime->objects, + self->uniqueId) == -1) + PySys_WriteStderr("WARNING: PyDict_DelItem() failed.\n"); + Py_DECREF(self->uniqueId); + self->uniqueId = NULL; + + // JS_RemoveRoot() always returns JS_TRUE, so don't + // bother checking its return value. JS_RemoveRootRT(self->runtime->rt, &self->obj); self->obj = NULL; } - Py_DECREF(self->runtime); - self->runtime = NULL; + if (self->runtime) { + Py_DECREF(self->runtime); + self->runtime = NULL; + } } PyTypeObject PYM_JSObjectType = { @@ -51,7 +62,8 @@ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ + /* tp_weaklistoffset */ + offsetof(PYM_JSObject, weakrefList), 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ @@ -69,15 +81,56 @@ PYM_JSObject *PYM_newJSObject(PYM_JSContextObject *context, JSObject *obj) { + jsid uniqueId; + if (!JS_GetObjectId(context->cx, obj, &uniqueId)) { + PyErr_SetString(PYM_error, "JS_GetObjectId() failed"); + return NULL; + } + PyObject *pyUniqueId = PyLong_FromLong(uniqueId); + if (pyUniqueId == NULL) + return NULL; + + PYM_JSRuntimeObject *runtime = context->runtime; + PyObject *cachedObject = PyDict_GetItem(runtime->objects, + pyUniqueId); + if (cachedObject) { + cachedObject = PyWeakref_GetObject(cachedObject); + Py_INCREF(cachedObject); + Py_DECREF(pyUniqueId); + return (PYM_JSObject *) cachedObject; + } + PYM_JSObject *object = PyObject_New(PYM_JSObject, &PYM_JSObjectType); - if (object == NULL) + if (object == NULL) { + Py_DECREF(pyUniqueId); return NULL; + } + + object->runtime = NULL; + object->obj = NULL; + object->uniqueId = NULL; + object->weakrefList = NULL; + + PyObject *weakref = PyWeakref_NewRef((PyObject *) object, NULL); + if (weakref == NULL) { + Py_DECREF(object); + Py_DECREF(pyUniqueId); + return NULL; + } + + if (PyDict_SetItem(runtime->objects, pyUniqueId, weakref) == -1) { + Py_DECREF(weakref); + Py_DECREF(object); + Py_DECREF(pyUniqueId); + return NULL; + } object->runtime = context->runtime; Py_INCREF(object->runtime); object->obj = obj; + object->uniqueId = pyUniqueId; JS_AddNamedRootRT(object->runtime->rt, &object->obj, "Pymonkey-Generated Object");
--- a/object.h Sun Jun 28 20:40:18 2009 -0700 +++ b/object.h Sun Jun 28 21:49:07 2009 -0700 @@ -12,6 +12,8 @@ PyObject_HEAD PYM_JSRuntimeObject *runtime; JSObject *obj; + PyObject *uniqueId; + PyObject *weakrefList; } PYM_JSObject; extern PyTypeObject PYM_JSObjectType;
--- a/runtime.c Sun Jun 28 20:40:18 2009 -0700 +++ b/runtime.c Sun Jun 28 21:49:07 2009 -0700 @@ -10,12 +10,22 @@ self = (PYM_JSRuntimeObject *) type->tp_alloc(type, 0); if (self != NULL) { - self->rt = JS_NewRuntime(8L * 1024L * 1024L); - if (!self->rt) { - PyErr_SetString(PYM_error, "JS_NewRuntime() failed"); + self->rt = NULL; + + self->objects = PyDict_New(); + if (self->objects == NULL) { 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; + } + } } return (PyObject *) self; @@ -24,6 +34,11 @@ static void PYM_JSRuntimeDealloc(PYM_JSRuntimeObject *self) { + if (self->objects) { + Py_DECREF(self->objects); + self->objects = NULL; + } + if (self->rt) { JS_DestroyRuntime(self->rt); self->rt = NULL;
--- a/runtime.h Sun Jun 28 20:40:18 2009 -0700 +++ b/runtime.h Sun Jun 28 21:49:07 2009 -0700 @@ -7,6 +7,7 @@ typedef struct { PyObject_HEAD JSRuntime *rt; + PyObject *objects; } PYM_JSRuntimeObject; extern PyTypeObject PYM_JSRuntimeType;
--- a/test_pymonkey.py Sun Jun 28 20:40:18 2009 -0700 +++ b/test_pymonkey.py Sun Jun 28 21:49:07 2009 -0700 @@ -9,6 +9,16 @@ cx.init_standard_classes(obj) return cx.evaluate_script(obj, code, '<string>', 1) + def testObjectIsIdentityPreserving(self): + cx = pymonkey.Runtime().new_context() + obj = cx.new_object() + cx.init_standard_classes(obj) + cx.evaluate_script(obj, 'foo = {bar: 1}', '<string>', 1) + self.assertTrue(isinstance(cx.get_property(obj, "foo"), + pymonkey.Object)) + self.assertTrue(cx.get_property(obj, "foo") is + cx.get_property(obj, "foo")) + def testObjectGetattrWorks(self): cx = pymonkey.Runtime().new_context() obj = cx.new_object()