Skip to content

Commit

Permalink
fix: namespace objects behave with compaction
Browse files Browse the repository at this point in the history
  • Loading branch information
flavorjones committed Oct 6, 2022
1 parent 5110609 commit 6bea7e0
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 6 deletions.
1 change: 1 addition & 0 deletions ext/nokogiri/nokogiri.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ int noko_io_write(void *ctx, char *buffer, int len);
int noko_io_close(void *ctx);

#define Noko_Node_Get_Struct(obj,type,sval) ((sval) = (type*)DATA_PTR(obj))
#define Noko_Namespace_Get_Struct(obj,type,sval) ((sval) = (type*)DATA_PTR(obj))

VALUE noko_xml_node_wrap(VALUE klass, xmlNodePtr node) ;
VALUE noko_xml_node_wrap_node_set_result(xmlNodePtr node, VALUE node_set) ;
Expand Down
61 changes: 56 additions & 5 deletions ext/nokogiri/xml_namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@
VALUE cNokogiriXmlNamespace ;

static void
dealloc_namespace(xmlNsPtr ns)
_xml_namespace_mark(xmlNsPtr ns)
{
rb_gc_mark((VALUE)ns->_private);
}

static void
_xml_namespace_dealloc(xmlNsPtr ns)
{
/*
* this deallocator is only used for namespace nodes that are part of an xpath
Expand All @@ -42,6 +48,47 @@ dealloc_namespace(xmlNsPtr ns)
NOKOGIRI_DEBUG_END(ns) ;
}

#ifdef HAVE_RB_GC_LOCATION
static void
_xml_namespace_update_references(xmlNsPtr ns)
{
if (ns->_private) {
ns->_private = (void *)rb_gc_location((VALUE)ns->_private);
}
}
#else
# define _xml_namespace_update_references 0
#endif

static const rb_data_type_t nokogiri_xml_namespace_type_with_dealloc = {
"Nokogiri/XMLNamespace/WithDealloc",
{
(noko_gc_callback_t)_xml_namespace_mark,
(noko_gc_callback_t)_xml_namespace_dealloc,
0,
(noko_gc_callback_t)_xml_namespace_update_references
},
0,
0,
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
RUBY_TYPED_FREE_IMMEDIATELY,
#endif
};

static const rb_data_type_t nokogiri_xml_namespace_type_without_dealloc = {
"Nokogiri/XMLNamespace/WithoutDealloc",
{
(noko_gc_callback_t)_xml_namespace_mark,
0,
0,
(noko_gc_callback_t)_xml_namespace_update_references
},
0,
0,
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
RUBY_TYPED_FREE_IMMEDIATELY,
#endif
};

/*
* call-seq:
Expand All @@ -54,7 +101,7 @@ prefix(VALUE self)
{
xmlNsPtr ns;

Data_Get_Struct(self, xmlNs, ns);
Noko_Namespace_Get_Struct(self, xmlNs, ns);
if (!ns->prefix) { return Qnil; }

return NOKOGIRI_STR_NEW2(ns->prefix);
Expand All @@ -71,7 +118,7 @@ href(VALUE self)
{
xmlNsPtr ns;

Data_Get_Struct(self, xmlNs, ns);
Noko_Namespace_Get_Struct(self, xmlNs, ns);
if (!ns->href) { return Qnil; }

return NOKOGIRI_STR_NEW2(ns->href);
Expand All @@ -87,14 +134,18 @@ noko_xml_namespace_wrap(xmlNsPtr c_namespace, xmlDocPtr c_document)
}

if (c_document) {
rb_namespace = Data_Wrap_Struct(cNokogiriXmlNamespace, 0, 0, c_namespace);
rb_namespace = TypedData_Wrap_Struct(cNokogiriXmlNamespace,
&nokogiri_xml_namespace_type_without_dealloc,
c_namespace);

if (DOC_RUBY_OBJECT_TEST(c_document)) {
rb_iv_set(rb_namespace, "@document", DOC_RUBY_OBJECT(c_document));
rb_ary_push(DOC_NODE_CACHE(c_document), rb_namespace);
}
} else {
rb_namespace = Data_Wrap_Struct(cNokogiriXmlNamespace, 0, dealloc_namespace, c_namespace);
rb_namespace = TypedData_Wrap_Struct(cNokogiriXmlNamespace,
&nokogiri_xml_namespace_type_with_dealloc,
c_namespace);
}

c_namespace->_private = (void *)rb_namespace;
Expand Down
2 changes: 1 addition & 1 deletion ext/nokogiri/xml_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -1356,7 +1356,7 @@ set_namespace(VALUE self, VALUE namespace)
Noko_Node_Get_Struct(self, xmlNode, node);

if (!NIL_P(namespace)) {
Data_Get_Struct(namespace, xmlNs, ns);
Noko_Namespace_Get_Struct(namespace, xmlNs, ns);
}

xmlSetNs(node, ns);
Expand Down

0 comments on commit 6bea7e0

Please sign in to comment.