@@ -282,7 +282,7 @@ create_new_element(PyObject* tag, PyObject* attrib)
282282{
283283 ElementObject * self ;
284284
285- self = PyObject_New (ElementObject , & Element_Type );
285+ self = PyObject_GC_New (ElementObject , & Element_Type );
286286 if (self == NULL )
287287 return NULL ;
288288
@@ -309,7 +309,7 @@ create_new_element(PyObject* tag, PyObject* attrib)
309309 self -> tail = Py_None ;
310310
311311 ALLOC (sizeof (ElementObject ), "create element" );
312-
312+ PyObject_GC_Track ( self );
313313 return (PyObject * ) self ;
314314}
315315
@@ -556,19 +556,51 @@ subelement(PyObject* self, PyObject* args, PyObject* kw)
556556 return elem ;
557557}
558558
559- static void
560- element_dealloc (ElementObject * self )
559+ static int
560+ element_gc_traverse (ElementObject * self , visitproc visit , void * arg )
561+ {
562+ Py_VISIT (self -> tag );
563+ Py_VISIT (JOIN_OBJ (self -> text ));
564+ Py_VISIT (JOIN_OBJ (self -> tail ));
565+
566+ if (self -> extra ) {
567+ int i ;
568+ Py_VISIT (self -> extra -> attrib );
569+
570+ for (i = 0 ; i < self -> extra -> length ; ++ i )
571+ Py_VISIT (self -> extra -> children [i ]);
572+ }
573+ return 0 ;
574+ }
575+
576+ static int
577+ element_gc_clear (ElementObject * self )
561578{
562- if (self -> extra )
579+ PyObject * text = JOIN_OBJ (self -> text );
580+ PyObject * tail = JOIN_OBJ (self -> tail );
581+ Py_CLEAR (self -> tag );
582+ Py_CLEAR (text );
583+ Py_CLEAR (tail );
584+
585+ /* After dropping all references from extra, it's no longer valid anyway,
586+ ** so fully deallocate it (see also element_clearmethod)
587+ */
588+ if (self -> extra ) {
563589 dealloc_extra (self );
590+ self -> extra = NULL ;
591+ }
592+ return 0 ;
593+ }
564594
565- /* discard attributes */
566- Py_DECREF (self -> tag );
567- Py_DECREF (JOIN_OBJ (self -> text ));
568- Py_DECREF (JOIN_OBJ (self -> tail ));
595+ static void
596+ element_dealloc (ElementObject * self )
597+ {
598+ PyObject_GC_UnTrack (self );
599+ /* element_gc_clear clears all references and deallocates extra
600+ */
601+ element_gc_clear (self );
569602
570603 RELEASE (sizeof (ElementObject ), "destroy element" );
571-
572604 Py_TYPE (self )-> tp_free ((PyObject * )self );
573605}
574606
@@ -589,7 +621,7 @@ element_append(ElementObject* self, PyObject* args)
589621}
590622
591623static PyObject *
592- element_clear (ElementObject * self , PyObject * args )
624+ element_clearmethod (ElementObject * self , PyObject * args )
593625{
594626 if (!PyArg_ParseTuple (args , ":clear" ))
595627 return NULL ;
@@ -1505,7 +1537,7 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
15051537
15061538static PyMethodDef element_methods [] = {
15071539
1508- {"clear" , (PyCFunction ) element_clear , METH_VARARGS },
1540+ {"clear" , (PyCFunction ) element_clearmethod , METH_VARARGS },
15091541
15101542 {"get" , (PyCFunction ) element_get , METH_VARARGS },
15111543 {"set" , (PyCFunction ) element_set , METH_VARARGS },
@@ -1655,10 +1687,11 @@ static PyTypeObject Element_Type = {
16551687 (getattrofunc )element_getattro , /* tp_getattro */
16561688 0 , /* tp_setattro */
16571689 0 , /* tp_as_buffer */
1658- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
1690+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC ,
1691+ /* tp_flags */
16591692 0 , /* tp_doc */
1660- 0 , /* tp_traverse */
1661- 0 , /* tp_clear */
1693+ ( traverseproc ) element_gc_traverse , /* tp_traverse */
1694+ ( inquiry ) element_gc_clear , /* tp_clear */
16621695 0 , /* tp_richcompare */
16631696 0 , /* tp_weaklistoffset */
16641697 0 , /* tp_iter */
0 commit comments