Mercurial > pymonkey
comparison object.cpp @ 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 | object.c@9e8e56b4de6f |
children |
comparison
equal
deleted
inserted
replaced
95:0701aee1b0cd | 96:3570ab12747b |
---|---|
1 /* ***** BEGIN LICENSE BLOCK ***** | |
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | |
3 * | |
4 * The contents of this file are subject to the Mozilla Public License Version | |
5 * 1.1 (the "License"); you may not use this file except in compliance with | |
6 * the License. You may obtain a copy of the License at | |
7 * http://www.mozilla.org/MPL/ | |
8 * | |
9 * Software distributed under the License is distributed on an "AS IS" basis, | |
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
11 * for the specific language governing rights and limitations under the | |
12 * License. | |
13 * | |
14 * The Original Code is Pymonkey. | |
15 * | |
16 * The Initial Developer of the Original Code is Mozilla. | |
17 * Portions created by the Initial Developer are Copyright (C) 2007 | |
18 * the Initial Developer. All Rights Reserved. | |
19 * | |
20 * Contributor(s): | |
21 * Atul Varma <atul@mozilla.com> | |
22 * | |
23 * Alternatively, the contents of this file may be used under the terms of | |
24 * either the GNU General Public License Version 2 or later (the "GPL"), or | |
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | |
26 * in which case the provisions of the GPL or the LGPL are applicable instead | |
27 * of those above. If you wish to allow use of your version of this file only | |
28 * under the terms of either the GPL or the LGPL, and not to allow others to | |
29 * use your version of this file under the terms of the MPL, indicate your | |
30 * decision by deleting the provisions above and replace them with the notice | |
31 * and other provisions required by the GPL or the LGPL. If you do not delete | |
32 * the provisions above, a recipient may use your version of this file under | |
33 * the terms of any one of the MPL, the GPL or the LGPL. | |
34 * | |
35 * ***** END LICENSE BLOCK ***** */ | |
36 | |
37 #include "object.h" | |
38 #include "function.h" | |
39 #include "runtime.h" | |
40 #include "utils.h" | |
41 | |
42 JSObject * | |
43 PYM_JS_newObject(JSContext *cx, PyObject *pyObject) | |
44 { | |
45 JSObject *obj = JS_NewObject(cx, &PYM_JS_ObjectClass, NULL, NULL); | |
46 if (obj) { | |
47 if (!JS_SetPrivate(cx, obj, pyObject)) | |
48 return NULL; | |
49 Py_XINCREF(pyObject); | |
50 } | |
51 return obj; | |
52 } | |
53 | |
54 JSBool | |
55 PYM_JS_setPrivatePyObject(JSContext *cx, JSObject *obj, PyObject *pyObject) | |
56 { | |
57 PyObject *old; | |
58 if (!PYM_JS_getPrivatePyObject(cx, obj, &old)) | |
59 return JS_FALSE; | |
60 if (!JS_SetPrivate(cx, obj, pyObject)) | |
61 return JS_FALSE; | |
62 Py_INCREF(pyObject); | |
63 Py_XDECREF(old); | |
64 return JS_TRUE; | |
65 } | |
66 | |
67 JSBool | |
68 PYM_JS_getPrivatePyObject(JSContext *cx, JSObject *obj, PyObject **pyObject) | |
69 { | |
70 JSClass *klass = JS_GET_CLASS(cx, obj); | |
71 if (klass != &PYM_JS_ObjectClass) { | |
72 JS_ReportError(cx, "Object is not an instance of PymonkeyObject"); | |
73 return JS_FALSE; | |
74 } | |
75 | |
76 *pyObject = (PyObject *) JS_GetPrivate(cx, obj); | |
77 return JS_TRUE; | |
78 } | |
79 | |
80 static void | |
81 PYM_JS_finalizeObject(JSContext *cx, JSObject *obj) | |
82 { | |
83 PYM_PyAutoEnsureGIL gil; | |
84 PyObject *pyObject; | |
85 // TODO: What if this fails? | |
86 if (PYM_JS_getPrivatePyObject(cx, obj, &pyObject)) | |
87 Py_XDECREF(pyObject); | |
88 } | |
89 | |
90 // This one-size-fits-all JSClass is used for any JS objects created | |
91 // in Python. It can hold a reference to a Python object for as long as | |
92 // its parent JS object is accessible from JS-land. As soon as it's | |
93 // garbage collected by the JS interpreter, it releases its reference on | |
94 // the Python object. | |
95 JSClass PYM_JS_ObjectClass = { | |
96 "PymonkeyObject", JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_PRIVATE, | |
97 JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, | |
98 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, PYM_JS_finalizeObject, | |
99 JSCLASS_NO_OPTIONAL_MEMBERS | |
100 }; | |
101 | |
102 static void | |
103 PYM_JSObjectDealloc(PYM_JSObject *self) | |
104 { | |
105 if (self->obj) { | |
106 JS_DHashTableOperate(&self->runtime->objects, | |
107 (void *) self->obj, | |
108 JS_DHASH_REMOVE); | |
109 | |
110 // JS_RemoveRoot() always returns JS_TRUE, so don't | |
111 // bother checking its return value. | |
112 JS_RemoveRootRT(self->runtime->rt, &self->obj); | |
113 self->obj = NULL; | |
114 } | |
115 | |
116 if (self->runtime) { | |
117 Py_DECREF(self->runtime); | |
118 self->runtime = NULL; | |
119 } | |
120 | |
121 self->ob_type->tp_free((PyObject *) self); | |
122 } | |
123 | |
124 static PyObject * | |
125 PYM_getRuntime(PYM_JSObject *self, PyObject *args) | |
126 { | |
127 Py_INCREF(self->runtime); | |
128 return (PyObject *) self->runtime; | |
129 } | |
130 | |
131 static PyMethodDef PYM_JSObjectMethods[] = { | |
132 {"get_runtime", (PyCFunction) PYM_getRuntime, METH_VARARGS, | |
133 "Get the JavaScript runtime associated with this object."}, | |
134 {NULL, NULL, 0, NULL} | |
135 }; | |
136 | |
137 PyTypeObject PYM_JSObjectType = { | |
138 PyObject_HEAD_INIT(NULL) | |
139 0, /*ob_size*/ | |
140 "pymonkey.Object", /*tp_name*/ | |
141 sizeof(PYM_JSObject), /*tp_basicsize*/ | |
142 0, /*tp_itemsize*/ | |
143 /*tp_dealloc*/ | |
144 (destructor) PYM_JSObjectDealloc, | |
145 0, /*tp_print*/ | |
146 0, /*tp_getattr*/ | |
147 0, /*tp_setattr*/ | |
148 0, /*tp_compare*/ | |
149 0, /*tp_repr*/ | |
150 0, /*tp_as_number*/ | |
151 0, /*tp_as_sequence*/ | |
152 0, /*tp_as_mapping*/ | |
153 0, /*tp_hash */ | |
154 0, /*tp_call*/ | |
155 0, /*tp_str*/ | |
156 0, /*tp_getattro*/ | |
157 0, /*tp_setattro*/ | |
158 0, /*tp_as_buffer*/ | |
159 /*tp_flags*/ | |
160 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, | |
161 /* tp_doc */ | |
162 "JavaScript Object.", | |
163 0, /* tp_traverse */ | |
164 0, /* tp_clear */ | |
165 0, /* tp_richcompare */ | |
166 0, /* tp_weaklistoffset */ | |
167 0, /* tp_iter */ | |
168 0, /* tp_iternext */ | |
169 PYM_JSObjectMethods, /* tp_methods */ | |
170 0, /* tp_members */ | |
171 0, /* tp_getset */ | |
172 0, /* tp_base */ | |
173 0, /* tp_dict */ | |
174 0, /* tp_descr_get */ | |
175 0, /* tp_descr_set */ | |
176 0, /* tp_dictoffset */ | |
177 0, /* tp_init */ | |
178 0, /* tp_alloc */ | |
179 0, /* tp_new */ | |
180 }; | |
181 | |
182 PYM_JSObject *PYM_newJSObject(PYM_JSContextObject *context, | |
183 JSObject *obj, | |
184 PYM_JSObject *subclass) { | |
185 PYM_JSRuntimeObject *runtime = context->runtime; | |
186 PYM_HashEntry *cached = (PYM_HashEntry *) JS_DHashTableOperate( | |
187 &runtime->objects, | |
188 (void *) obj, | |
189 JS_DHASH_LOOKUP | |
190 ); | |
191 | |
192 if (JS_DHASH_ENTRY_IS_BUSY((JSDHashEntryHdr *) cached)) { | |
193 Py_INCREF((PyObject *) cached->value); | |
194 return (PYM_JSObject *) cached->value; | |
195 } | |
196 | |
197 PYM_JSObject *object; | |
198 | |
199 if (subclass) | |
200 object = subclass; | |
201 else { | |
202 if (JS_ObjectIsFunction(context->cx, obj)) { | |
203 PYM_JSFunction *func = PyObject_New(PYM_JSFunction, | |
204 &PYM_JSFunctionType); | |
205 object = (PYM_JSObject *) func; | |
206 } else | |
207 object = PyObject_New(PYM_JSObject, | |
208 &PYM_JSObjectType); | |
209 } | |
210 | |
211 if (object == NULL) | |
212 return NULL; | |
213 | |
214 object->runtime = NULL; | |
215 object->obj = NULL; | |
216 | |
217 cached = (PYM_HashEntry *) JS_DHashTableOperate(&runtime->objects, | |
218 (void *) obj, | |
219 JS_DHASH_ADD); | |
220 if (cached == NULL) { | |
221 Py_DECREF(object); | |
222 PyErr_SetString(PYM_error, "JS_DHashTableOperate() failed"); | |
223 return NULL; | |
224 } | |
225 | |
226 cached->base.key = (void *) obj; | |
227 cached->value = object; | |
228 | |
229 object->runtime = context->runtime; | |
230 Py_INCREF(object->runtime); | |
231 | |
232 object->obj = obj; | |
233 | |
234 JS_AddNamedRootRT(object->runtime->rt, &object->obj, | |
235 "Pymonkey-Generated Object"); | |
236 | |
237 return object; | |
238 } |