diff --git a/ext/java/nokogiri/XmlNode.java b/ext/java/nokogiri/XmlNode.java index b137c2c7d32..1d47f80b2bc 100644 --- a/ext/java/nokogiri/XmlNode.java +++ b/ext/java/nokogiri/XmlNode.java @@ -713,8 +713,16 @@ public IRubyObject child(ThreadContext context) { @JRubyMethod public IRubyObject children(ThreadContext context) { - XmlNodeSet xmlNodeSet = (XmlNodeSet) NokogiriService.XML_NODESET_ALLOCATOR.allocate(context.getRuntime(), getNokogiriClass(context.getRuntime(), "Nokogiri::XML::NodeSet")); - xmlNodeSet.setNodeList(node.getChildNodes()); + XmlNodeSet xmlNodeSet = XmlNodeSet.create(context.runtime); + + NodeList nodeList = node.getChildNodes(); + if (nodeList.getLength() > 0) { + xmlNodeSet.setNodeList(nodeList); // initializes @document from first node + } + else { // TODO this is very ripe for refactoring + setDocumentAndDecorate(context, xmlNodeSet, doc); + } + return xmlNodeSet; } @@ -1430,9 +1438,10 @@ public IRubyObject set_namespace(ThreadContext context, IRubyObject namespace) { @JRubyMethod(name = {"unlink", "remove"}) public IRubyObject unlink(ThreadContext context) { - if (node.getParentNode() != null) { - clearXpathContext(node.getParentNode()); - node.getParentNode().removeChild(node); + final Node parent = node.getParentNode(); + if (parent != null) { + parent.removeChild(node); + clearXpathContext(parent); } return this; } diff --git a/lib/nokogiri/xml/node_set.rb b/lib/nokogiri/xml/node_set.rb index ba5367b19d6..98718255a74 100644 --- a/lib/nokogiri/xml/node_set.rb +++ b/lib/nokogiri/xml/node_set.rb @@ -293,7 +293,11 @@ def == other # Returns a new NodeSet containing all the children of all the nodes in # the NodeSet def children - inject(NodeSet.new(document)) { |set, node| set += node.children } + node_set = NodeSet.new(document) + each do |node| + node.children.each { |n| node_set.push(n) } + end + node_set end ### diff --git a/test/xml/test_document_fragment.rb b/test/xml/test_document_fragment.rb index d8208c4f888..c919ee2068f 100644 --- a/test/xml/test_document_fragment.rb +++ b/test/xml/test_document_fragment.rb @@ -141,8 +141,7 @@ def test_fragment_css_search_with_whitespace_and_node_removal # does not expose the error. Putting both nodes on the same line # instead also fixes the crash. fragment = Nokogiri::XML::DocumentFragment.parse <<-EOXML -

hi

-

another paragraph

+

hi

x

another paragraph

EOXML children = fragment.css('p') assert_equal 2, children.length @@ -150,7 +149,7 @@ def test_fragment_css_search_with_whitespace_and_node_removal # node removal leaves around two consecutive text nodes which make the # css search crash? children.first.remove - # using xpath('/p') instead works as expected + assert_equal 1, fragment.xpath('.//p | self::p').length assert_equal 1, fragment.css('p').length end @@ -237,6 +236,16 @@ def awesome! assert fragment.children.respond_to?(:awesome!), fragment.children.class end + def test_decorator_is_applied_to_empty_set + x = Module.new do + def awesome! + end + end + util_decorate(@xml, x) + fragment = Nokogiri::XML::DocumentFragment.new(@xml, "") + assert fragment.children.respond_to?(:awesome!), fragment.children.class + end + def test_add_node_to_doc_fragment_segfault frag = Nokogiri::XML::DocumentFragment.new(@xml, '

hello world

') Nokogiri::XML::Comment.new(frag,'moo')