Skip to content

Commit 5f58b34

Browse files
committed
fix: namespace nodes behave properly when compacted
1 parent b08a858 commit 5f58b34

File tree

3 files changed

+43
-6
lines changed

3 files changed

+43
-6
lines changed

ext/nokogiri/nokogiri.h

+1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ int noko_io_write(void *ctx, char *buffer, int len);
171171
int noko_io_close(void *ctx);
172172

173173
#define Noko_Node_Get_Struct(obj,type,sval) ((sval) = (type*)DATA_PTR(obj))
174+
#define Noko_Namespace_Get_Struct(obj,type,sval) ((sval) = (type*)DATA_PTR(obj))
174175

175176
VALUE noko_xml_node_wrap(VALUE klass, xmlNodePtr node) ;
176177
VALUE noko_xml_node_wrap_node_set_result(xmlNodePtr node, VALUE node_set) ;

ext/nokogiri/xml_namespace.c

+41-5
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@
2525
VALUE cNokogiriXmlNamespace ;
2626

2727
static void
28-
dealloc_namespace(xmlNsPtr ns)
28+
_xml_namespace_dealloc(void *ptr)
2929
{
3030
/*
3131
* this deallocator is only used for namespace nodes that are part of an xpath
3232
* node set. see noko_xml_namespace_wrap().
3333
*/
34+
xmlNsPtr ns = ptr;
3435
NOKOGIRI_DEBUG_START(ns) ;
36+
3537
if (ns->href) {
3638
xmlFree(DISCARD_CONST_QUAL_XMLCHAR(ns->href));
3739
}
@@ -42,6 +44,36 @@ dealloc_namespace(xmlNsPtr ns)
4244
NOKOGIRI_DEBUG_END(ns) ;
4345
}
4446

47+
#ifdef HAVE_RB_GC_LOCATION
48+
static void
49+
_xml_namespace_update_references(void *ptr)
50+
{
51+
xmlNsPtr ns = ptr;
52+
if (ns->_private) {
53+
ns->_private = (void *)rb_gc_location((VALUE)ns->_private);
54+
}
55+
}
56+
#else
57+
# define _xml_namespace_update_references 0
58+
#endif
59+
60+
static const rb_data_type_t nokogiri_xml_namespace_type_with_dealloc = {
61+
"Nokogiri/XMLNamespace/WithDealloc",
62+
{0, _xml_namespace_dealloc, 0, _xml_namespace_update_references},
63+
0, 0,
64+
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
65+
RUBY_TYPED_FREE_IMMEDIATELY,
66+
#endif
67+
};
68+
69+
static const rb_data_type_t nokogiri_xml_namespace_type_without_dealloc = {
70+
"Nokogiri/XMLNamespace/WithoutDealloc",
71+
{0, 0, 0, _xml_namespace_update_references},
72+
0, 0,
73+
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
74+
RUBY_TYPED_FREE_IMMEDIATELY,
75+
#endif
76+
};
4577

4678
/*
4779
* call-seq:
@@ -54,7 +86,7 @@ prefix(VALUE self)
5486
{
5587
xmlNsPtr ns;
5688

57-
Data_Get_Struct(self, xmlNs, ns);
89+
Noko_Namespace_Get_Struct(self, xmlNs, ns);
5890
if (!ns->prefix) { return Qnil; }
5991

6092
return NOKOGIRI_STR_NEW2(ns->prefix);
@@ -71,7 +103,7 @@ href(VALUE self)
71103
{
72104
xmlNsPtr ns;
73105

74-
Data_Get_Struct(self, xmlNs, ns);
106+
Noko_Namespace_Get_Struct(self, xmlNs, ns);
75107
if (!ns->href) { return Qnil; }
76108

77109
return NOKOGIRI_STR_NEW2(ns->href);
@@ -87,14 +119,18 @@ noko_xml_namespace_wrap(xmlNsPtr c_namespace, xmlDocPtr c_document)
87119
}
88120

89121
if (c_document) {
90-
rb_namespace = Data_Wrap_Struct(cNokogiriXmlNamespace, 0, 0, c_namespace);
122+
rb_namespace = TypedData_Wrap_Struct(cNokogiriXmlNamespace,
123+
&nokogiri_xml_namespace_type_without_dealloc,
124+
c_namespace);
91125

92126
if (DOC_RUBY_OBJECT_TEST(c_document)) {
93127
rb_iv_set(rb_namespace, "@document", DOC_RUBY_OBJECT(c_document));
94128
rb_ary_push(DOC_NODE_CACHE(c_document), rb_namespace);
95129
}
96130
} else {
97-
rb_namespace = Data_Wrap_Struct(cNokogiriXmlNamespace, 0, dealloc_namespace, c_namespace);
131+
rb_namespace = TypedData_Wrap_Struct(cNokogiriXmlNamespace,
132+
&nokogiri_xml_namespace_type_with_dealloc,
133+
c_namespace);
98134
}
99135

100136
c_namespace->_private = (void *)rb_namespace;

ext/nokogiri/xml_node.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1353,7 +1353,7 @@ set_namespace(VALUE self, VALUE namespace)
13531353
Noko_Node_Get_Struct(self, xmlNode, node);
13541354

13551355
if (!NIL_P(namespace)) {
1356-
Data_Get_Struct(namespace, xmlNs, ns);
1356+
Noko_Namespace_Get_Struct(namespace, xmlNs, ns);
13571357
}
13581358

13591359
xmlSetNs(node, ns);

0 commit comments

Comments
 (0)