4848/* See http://www.python.org/psf/license for licensing details. */
4949
5050#include "Python.h"
51+ #include "structmember.h"
5152
5253#define VERSION "1.0.6"
5354
@@ -229,6 +230,8 @@ typedef struct {
229230
230231 ElementObjectExtra * extra ;
231232
233+ PyObject * weakreflist ; /* For tp_weaklistoffset */
234+
232235} ElementObject ;
233236
234237static PyTypeObject Element_Type ;
@@ -261,17 +264,24 @@ create_extra(ElementObject* self, PyObject* attrib)
261264LOCAL (void )
262265dealloc_extra (ElementObject * self )
263266{
264- int i ;
267+ if (!self -> extra )
268+ return ;
269+
270+ /* Avoid DECREFs calling into this code again (cycles, etc.)
271+ */
272+ ElementObjectExtra * myextra = self -> extra ;
273+ self -> extra = NULL ;
265274
266- Py_DECREF (self -> extra -> attrib );
275+ Py_DECREF (myextra -> attrib );
267276
268- for (i = 0 ; i < self -> extra -> length ; i ++ )
269- Py_DECREF (self -> extra -> children [i ]);
277+ int i ;
278+ for (i = 0 ; i < myextra -> length ; i ++ )
279+ Py_DECREF (myextra -> children [i ]);
270280
271- if (self -> extra -> children != self -> extra -> _children )
272- PyObject_Free (self -> extra -> children );
281+ if (myextra -> children != myextra -> _children )
282+ PyObject_Free (myextra -> children );
273283
274- PyObject_Free (self -> extra );
284+ PyObject_Free (myextra );
275285}
276286
277287/* Convenience internal function to create new Element objects with the given
@@ -308,6 +318,8 @@ create_new_element(PyObject* tag, PyObject* attrib)
308318 Py_INCREF (Py_None );
309319 self -> tail = Py_None ;
310320
321+ self -> weakreflist = NULL ;
322+
311323 ALLOC (sizeof (ElementObject ), "create element" );
312324 PyObject_GC_Track (self );
313325 return (PyObject * ) self ;
@@ -328,6 +340,7 @@ element_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
328340 e -> tail = Py_None ;
329341
330342 e -> extra = NULL ;
343+ e -> weakreflist = NULL ;
331344 }
332345 return (PyObject * )e ;
333346}
@@ -576,26 +589,39 @@ element_gc_traverse(ElementObject *self, visitproc visit, void *arg)
576589static int
577590element_gc_clear (ElementObject * self )
578591{
579- PyObject * text = JOIN_OBJ (self -> text );
580- PyObject * tail = JOIN_OBJ (self -> tail );
581592 Py_CLEAR (self -> tag );
582- Py_CLEAR (text );
583- Py_CLEAR (tail );
584593
585- /* After dropping all references from extra, it's no longer valid anyway,
586- ** so fully deallocate it (see also element_clearmethod)
594+ /* The following is like Py_CLEAR for self->text and self->tail, but
595+ * written explicitily because the real pointers hide behind access
596+ * macros.
587597 */
588- if (self -> extra ) {
589- dealloc_extra (self );
590- self -> extra = NULL ;
598+ if (self -> text ) {
599+ PyObject * tmp = JOIN_OBJ (self -> text );
600+ self -> text = NULL ;
601+ Py_DECREF (tmp );
602+ }
603+
604+ if (self -> tail ) {
605+ PyObject * tmp = JOIN_OBJ (self -> tail );
606+ self -> tail = NULL ;
607+ Py_DECREF (tmp );
591608 }
609+
610+ /* After dropping all references from extra, it's no longer valid anyway,
611+ * so fully deallocate it.
612+ */
613+ dealloc_extra (self );
592614 return 0 ;
593615}
594616
595617static void
596618element_dealloc (ElementObject * self )
597619{
598620 PyObject_GC_UnTrack (self );
621+
622+ if (self -> weakreflist != NULL )
623+ PyObject_ClearWeakRefs ((PyObject * ) self );
624+
599625 /* element_gc_clear clears all references and deallocates extra
600626 */
601627 element_gc_clear (self );
@@ -626,10 +652,7 @@ element_clearmethod(ElementObject* self, PyObject* args)
626652 if (!PyArg_ParseTuple (args , ":clear" ))
627653 return NULL ;
628654
629- if (self -> extra ) {
630- dealloc_extra (self );
631- self -> extra = NULL ;
632- }
655+ dealloc_extra (self );
633656
634657 Py_INCREF (Py_None );
635658 Py_DECREF (JOIN_OBJ (self -> text ));
@@ -1693,7 +1716,7 @@ static PyTypeObject Element_Type = {
16931716 (traverseproc )element_gc_traverse , /* tp_traverse */
16941717 (inquiry )element_gc_clear , /* tp_clear */
16951718 0 , /* tp_richcompare */
1696- 0 , /* tp_weaklistoffset */
1719+ offsetof( ElementObject , weakreflist ), /* tp_weaklistoffset */
16971720 0 , /* tp_iter */
16981721 0 , /* tp_iternext */
16991722 element_methods , /* tp_methods */
0 commit comments