nokogiri 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of nokogiri might be problematic. Click here for more details.

@@ -1,6 +1,15 @@
1
+ === 1.0.4
2
+
3
+ * Bugfixes
4
+
5
+ * Changed memory mangement from weak refs to document refs
6
+ * Plugged some memory leaks
7
+ * extconf.rb now complains if your libxml2 is not between 2.6.13 and 2.6.99
8
+ * Builder blocks can call methods from surrounding contexts
9
+
1
10
  === 1.0.3
2
11
 
3
- * 5 Bigfixes
12
+ * 5 Bugfixes
4
13
 
5
14
  * NodeSet now implements to_ary
6
15
  * XML::Document should not implement parent
@@ -119,3 +119,4 @@ test/xml/test_dtd.rb
119
119
  test/xml/test_node.rb
120
120
  test/xml/test_node_set.rb
121
121
  test/xml/test_text.rb
122
+ vendor/hoe.rb
data/Rakefile CHANGED
@@ -1,8 +1,8 @@
1
1
  # -*- ruby -*-
2
2
 
3
3
  require 'rubygems'
4
- require 'mkmf'
5
- require 'hoe'
4
+ require 'rake'
5
+
6
6
 
7
7
  kind = Config::CONFIG['DLEXT']
8
8
  windows = RUBY_PLATFORM =~ /mswin/i ? true : false
@@ -10,6 +10,8 @@ windows = RUBY_PLATFORM =~ /mswin/i ? true : false
10
10
  LIB_DIR = File.expand_path(File.join(File.dirname(__FILE__), 'lib'))
11
11
  $LOAD_PATH << LIB_DIR
12
12
 
13
+ require 'vendor/hoe'
14
+
13
15
  GENERATED_PARSER = "lib/nokogiri/css/generated_parser.rb"
14
16
  GENERATED_TOKENIZER = "lib/nokogiri/css/generated_tokenizer.rb"
15
17
 
@@ -41,7 +43,7 @@ namespace :gem do
41
43
  end
42
44
 
43
45
  namespace :win32 do
44
- task :spec do
46
+ task :spec => ['build:win32'] do
45
47
  File.open("#{HOE.name}.gemspec", 'w') do |f|
46
48
  HOE.spec.files += Dir['ext/nokogiri/**.{dll,so}']
47
49
  if windows
@@ -55,6 +57,16 @@ namespace :gem do
55
57
  end
56
58
  end
57
59
 
60
+ namespace :jruby do
61
+ task :spec => ['build'] do
62
+ File.open("#{HOE.name}.gemspec", 'w') do |f|
63
+ HOE.spec.platform = 'jruby'
64
+ HOE.spec.extensions = []
65
+ f.write(HOE.spec.to_ruby)
66
+ end
67
+ end
68
+ end
69
+
58
70
  namespace :unix do
59
71
  task :spec do
60
72
  File.open("#{HOE.name}.gemspec", 'w') do |f|
@@ -73,17 +85,19 @@ task :coverage do
73
85
  end
74
86
 
75
87
  file GENERATED_PARSER => "lib/nokogiri/css/parser.y" do |t|
76
- unless find_executable("racc")
88
+ begin
89
+ sh "racc -o #{t.name} #{t.prerequisites.first}"
90
+ rescue
77
91
  abort "need racc, get the tarball from http://i.loveruby.net/archive/racc/racc-1.4.5-all.tar.gz"
78
92
  end
79
- sh "racc -o #{t.name} #{t.prerequisites.first}"
80
93
  end
81
94
 
82
95
  file GENERATED_TOKENIZER => "lib/nokogiri/css/tokenizer.rex" do |t|
83
- unless find_executable("frex")
96
+ begin
97
+ sh "frex -i --independent -o #{t.name} #{t.prerequisites.first}"
98
+ rescue
84
99
  abort "need frex, sudo gem install aaronp-frex -s http://gems.github.com"
85
100
  end
86
- sh "frex -i --independent -o #{t.name} #{t.prerequisites.first}"
87
101
  end
88
102
 
89
103
  task 'ext/nokogiri/Makefile' do
@@ -98,7 +112,11 @@ task EXT => 'ext/nokogiri/Makefile' do
98
112
  end
99
113
  end
100
114
 
101
- task :build => [EXT, GENERATED_PARSER, GENERATED_TOKENIZER]
115
+ if RUBY_PLATFORM == 'java'
116
+ task :build => [GENERATED_PARSER, GENERATED_TOKENIZER]
117
+ else
118
+ task :build => [EXT, GENERATED_PARSER, GENERATED_TOKENIZER]
119
+ end
102
120
 
103
121
  namespace :build do
104
122
  namespace :win32 do
@@ -268,4 +286,12 @@ unless windows
268
286
  Rake::Task[:check_manifest].prerequisites << GENERATED_TOKENIZER
269
287
  end
270
288
 
289
+ # Evil evil hack. Do not run tests when gem installs
290
+ if ENV['RUBYARCHDIR']
291
+ class << Rake::Task[:default]
292
+ attr_writer :prerequisites
293
+ end
294
+ Rake::Task[:default].prerequisites = [:build]
295
+ end
296
+
271
297
  # vim: syntax=Ruby
@@ -50,6 +50,8 @@ else
50
50
  unless find_header('libxslt/xslt.h', INCLUDEDIR, '/usr/include')
51
51
  abort "need libxslt"
52
52
  end
53
+
54
+ version = try_constant('LIBXML_VERSION', 'libxml/xmlversion.h')
53
55
  end
54
56
 
55
57
  create_makefile('nokogiri/native')
@@ -39,8 +39,11 @@ static VALUE read_memory( VALUE klass,
39
39
 
40
40
  htmlDocPtr doc = htmlReadMemory(c_buffer, len, c_url, c_enc, NUM2INT(options));
41
41
 
42
- if(doc == NULL)
43
- doc = htmlNewDoc((const xmlChar *)c_url, NULL);
42
+ if(doc == NULL) {
43
+ xmlFreeDoc(doc);
44
+ rb_raise(rb_eRuntimeError, "Couldn't create a document");
45
+ return Qnil;
46
+ }
44
47
 
45
48
  return Nokogiri_wrap_xml_document(klass, doc);
46
49
  }
@@ -2,6 +2,7 @@
2
2
  #define NOKOGIRI_NATIVE
3
3
 
4
4
  #include <stdlib.h>
5
+ #include <assert.h>
5
6
  #include <ruby.h>
6
7
  #include <libxml/parser.h>
7
8
  #include <libxml/xpath.h>
@@ -1,24 +1,9 @@
1
1
  #include <xml_document.h>
2
2
 
3
- /*
4
- * note that xmlDocPtr is being cast as an xmlNodePtr, which is legal for the
5
- * "common part" struct header which contains only node pointers.
6
- */
7
- static void gc_mark(xmlNodePtr node)
8
- {
9
- VALUE rb_obj ;
10
- xmlNodePtr child ;
11
- /* mark children nodes */
12
- for (child = node->children ; child ; child = child->next) {
13
- if ((rb_obj = Nokogiri_xml_node2obj_get(child)) != Qnil)
14
- rb_gc_mark(rb_obj);
15
- }
16
- }
17
-
18
3
  static void dealloc(xmlDocPtr doc)
19
4
  {
20
5
  NOKOGIRI_DEBUG_START(doc);
21
- Nokogiri_xml_node2obj_remove((xmlNodePtr)doc);
6
+ doc->_private = NULL;
22
7
  xmlFreeDoc(doc);
23
8
  NOKOGIRI_DEBUG_END(doc);
24
9
  }
@@ -57,7 +42,6 @@ static VALUE set_root(VALUE self, VALUE root)
57
42
  Data_Get_Struct(root, xmlNode, new_root);
58
43
 
59
44
  xmlDocSetRootElement(doc, new_root);
60
- Nokogiri_xml_node_owned_set(new_root);
61
45
  return root;
62
46
  }
63
47
 
@@ -95,6 +79,7 @@ static VALUE read_memory( VALUE klass,
95
79
  if(doc == NULL) {
96
80
  xmlFreeDoc(doc);
97
81
  rb_raise(rb_eRuntimeError, "Couldn't create a document");
82
+ return Qnil;
98
83
  }
99
84
 
100
85
  return Nokogiri_wrap_xml_document(klass, doc);
@@ -156,11 +141,8 @@ VALUE Nokogiri_wrap_xml_document(VALUE klass, xmlDocPtr doc)
156
141
  {
157
142
  VALUE rb_doc = Qnil;
158
143
 
159
- if ((rb_doc = Nokogiri_xml_node2obj_get((xmlNodePtr)doc)) != Qnil)
160
- return rb_doc ;
161
-
162
- rb_doc = Data_Wrap_Struct(klass ? klass : cNokogiriXmlDocument, gc_mark, dealloc, doc) ;
144
+ rb_doc = Data_Wrap_Struct(klass ? klass : cNokogiriXmlDocument, 0, dealloc, doc) ;
145
+ doc->_private = (void *)rb_doc;
163
146
 
164
- Nokogiri_xml_node2obj_set((xmlNodePtr)doc, rb_doc);
165
147
  return rb_doc ;
166
148
  }
@@ -1,5 +1,19 @@
1
1
  #include <xml_node.h>
2
2
 
3
+ /*
4
+ * call-seq:
5
+ * pointer_id
6
+ *
7
+ * Get the internal pointer number
8
+ */
9
+ static VALUE pointer_id(VALUE self)
10
+ {
11
+ xmlNodePtr node;
12
+ Data_Get_Struct(self, xmlNode, node);
13
+
14
+ return INT2NUM((int)(node));
15
+ }
16
+
3
17
  /*
4
18
  * call-seq:
5
19
  * encode_special_chars(string)
@@ -55,6 +69,10 @@ static VALUE duplicate_node(VALUE self)
55
69
 
56
70
  dup = xmlCopyNode(node, 1);
57
71
  if(dup == NULL) return Qnil;
72
+ dup->doc = node->doc;
73
+ assert(node->parent);
74
+
75
+ xmlAddChild(node->parent, dup);
58
76
 
59
77
  return Nokogiri_wrap_xml_node(dup);
60
78
  }
@@ -70,7 +88,6 @@ static VALUE unlink_node(VALUE self)
70
88
  xmlNodePtr node;
71
89
  Data_Get_Struct(self, xmlNode, node);
72
90
  xmlUnlinkNode(node);
73
- Nokogiri_xml_node_owned_set(node);
74
91
  return self;
75
92
  }
76
93
 
@@ -136,8 +153,6 @@ static VALUE replace(VALUE self, VALUE _new_node)
136
153
  Data_Get_Struct(_new_node, xmlNode, new_node);
137
154
 
138
155
  xmlReplaceNode(node, new_node);
139
- Nokogiri_xml_node_owned_set(node);
140
- Nokogiri_xml_node_owned_set(new_node);
141
156
  return self ;
142
157
  }
143
158
 
@@ -324,7 +339,6 @@ static VALUE set_parent(VALUE self, VALUE parent_node)
324
339
  Data_Get_Struct(parent_node, xmlNode, parent);
325
340
 
326
341
  xmlAddChild(parent, node);
327
- Nokogiri_xml_node_owned_set(node);
328
342
  return parent_node;
329
343
  }
330
344
 
@@ -391,21 +405,6 @@ static VALUE path(VALUE self)
391
405
  return rval ;
392
406
  }
393
407
 
394
- /*
395
- * call-seq:
396
- * document
397
- *
398
- * Returns the Nokogiri::XML::Document associated with this Node
399
- */
400
- static VALUE document(VALUE self)
401
- {
402
- xmlNodePtr node;
403
- Data_Get_Struct(self, xmlNode, node);
404
-
405
- if(!node->doc) return Qnil;
406
- return Nokogiri_xml_node2obj_get(node->doc);
407
- }
408
-
409
408
  /*
410
409
  * call-seq:
411
410
  * add_next_sibling(node)
@@ -420,7 +419,6 @@ static VALUE add_next_sibling(VALUE self, VALUE rb_node)
420
419
  xmlAddNextSibling(node, new_sibling);
421
420
 
422
421
  rb_funcall(rb_node, rb_intern("decorate!"), 0);
423
- Nokogiri_xml_node_owned_set(new_sibling);
424
422
 
425
423
  return rb_node;
426
424
  }
@@ -439,7 +437,6 @@ static VALUE add_previous_sibling(VALUE self, VALUE rb_node)
439
437
  xmlAddPrevSibling(node, new_sibling);
440
438
 
441
439
  rb_funcall(rb_node, rb_intern("decorate!"), 0);
442
- Nokogiri_xml_node_owned_set(new_sibling);
443
440
 
444
441
  return rb_node;
445
442
  }
@@ -472,14 +469,18 @@ static VALUE to_xml(VALUE self)
472
469
  *
473
470
  * Create a new node with +name+
474
471
  */
475
- static VALUE new(VALUE klass, VALUE name)
472
+ static VALUE new(VALUE klass, VALUE name, VALUE document)
476
473
  {
474
+ xmlDocPtr doc;
475
+
476
+ Data_Get_Struct(document, xmlDoc, doc);
477
+
477
478
  xmlNodePtr node = xmlNewNode(NULL, (xmlChar *)StringValuePtr(name));
478
- VALUE rb_node = Nokogiri_wrap_xml_node(node) ;
479
+ node->doc = doc;
479
480
 
480
- if(rb_block_given_p()) rb_yield(rb_node);
481
+ VALUE rb_node = Nokogiri_wrap_xml_node(node);
481
482
 
482
- Nokogiri_xml_node_owned_set(node);
483
+ if(rb_block_given_p()) rb_yield(rb_node);
483
484
 
484
485
  return rb_node;
485
486
  }
@@ -505,79 +506,49 @@ static VALUE new_from_str(VALUE klass, VALUE xml)
505
506
  xml, Qnil, Qnil, INT2NUM(0));
506
507
  Data_Get_Struct(rb_doc, xmlDoc, doc);
507
508
  node = xmlCopyNode(xmlDocGetRootElement(doc), 1); /* 1 => recursive */
508
- return Nokogiri_wrap_xml_node(node);
509
- }
510
-
511
- static void deallocate(xmlNodePtr node)
512
- {
513
- Nokogiri_xml_node2obj_remove(node);
514
- if (! Nokogiri_xml_node_owned_get(node)) {
515
- NOKOGIRI_DEBUG_START_NODE(node);
516
- xmlFreeNode(node);
517
- NOKOGIRI_DEBUG_END(node);
518
- }
519
- }
509
+ node->doc = doc;
520
510
 
521
- static void gc_mark_node(xmlNodePtr node)
522
- {
523
- xmlNodePtr child ;
524
- VALUE rb_obj ;
525
- /* mark document */
526
- if (node && node->doc && (rb_obj = Nokogiri_xml_node2obj_get((xmlNodePtr)node->doc)) != Qnil)
527
- rb_gc_mark(rb_obj);
528
- /* mark parent node */
529
- if (node && node->parent && (rb_obj = Nokogiri_xml_node2obj_get(node->parent)) != Qnil)
530
- rb_gc_mark(rb_obj);
531
- /* mark children nodes */
532
- for (child = node->children ; child ; child = child->next) {
533
- if ((rb_obj = Nokogiri_xml_node2obj_get(child)) != Qnil)
534
- rb_gc_mark(rb_obj);
535
- }
536
- /* mark sibling nodes */
537
- if (node->next && (rb_obj = Nokogiri_xml_node2obj_get(node->next)) != Qnil)
538
- rb_gc_mark(rb_obj);
539
- if (node->prev && (rb_obj = Nokogiri_xml_node2obj_get(node->prev)) != Qnil)
540
- rb_gc_mark(rb_obj);
511
+ return Nokogiri_wrap_xml_node(node);
541
512
  }
542
513
 
543
514
  VALUE Nokogiri_wrap_xml_node(xmlNodePtr node)
544
515
  {
545
516
  VALUE rb_node = Qnil;
546
517
 
547
- if ((rb_node = Nokogiri_xml_node2obj_get(node)) != Qnil)
548
- return rb_node ;
549
-
550
518
  switch(node->type)
551
519
  {
552
520
  VALUE klass;
553
521
 
554
522
  case XML_TEXT_NODE:
555
523
  klass = rb_const_get(mNokogiriXml, rb_intern("Text"));
556
- rb_node = Data_Wrap_Struct(klass, gc_mark_node, deallocate, node) ;
524
+ rb_node = Data_Wrap_Struct(klass, 0, 0, node) ;
557
525
  break;
558
526
  case XML_ELEMENT_NODE:
559
527
  klass = rb_const_get(mNokogiriXml, rb_intern("Element"));
560
- rb_node = Data_Wrap_Struct(klass, gc_mark_node, deallocate, node) ;
528
+ rb_node = Data_Wrap_Struct(klass, 0, 0, node) ;
561
529
  break;
562
530
  case XML_ENTITY_DECL:
563
531
  klass = rb_const_get(mNokogiriXml, rb_intern("EntityDeclaration"));
564
- rb_node = Data_Wrap_Struct(klass, gc_mark_node, deallocate, node) ;
532
+ rb_node = Data_Wrap_Struct(klass, 0, 0, node) ;
565
533
  break;
566
534
  case XML_CDATA_SECTION_NODE:
567
535
  klass = rb_const_get(mNokogiriXml, rb_intern("CDATA"));
568
- rb_node = Data_Wrap_Struct(klass, gc_mark_node, deallocate, node) ;
536
+ rb_node = Data_Wrap_Struct(klass, 0, 0, node) ;
569
537
  break;
570
538
  case XML_DTD_NODE:
571
539
  klass = rb_const_get(mNokogiriXml, rb_intern("DTD"));
572
- rb_node = Data_Wrap_Struct(klass, gc_mark_node, deallocate, node) ;
540
+ rb_node = Data_Wrap_Struct(klass, 0, 0, node) ;
573
541
  break;
574
542
  default:
575
- rb_node = Data_Wrap_Struct(cNokogiriXmlNode, gc_mark_node, deallocate, node) ;
543
+ rb_node = Data_Wrap_Struct(cNokogiriXmlNode, 0, 0, node) ;
576
544
  }
577
545
 
578
- Nokogiri_xml_node2obj_set(node, rb_node);
546
+ assert(node);
547
+ assert(node->doc);
548
+ assert(node->doc->_private);
549
+
550
+ rb_iv_set(rb_node, "@document",(VALUE)node->doc->_private);
579
551
  rb_funcall(rb_node, rb_intern("decorate!"), 0);
580
- Nokogiri_xml_node_owned_set(node);
581
552
  return rb_node ;
582
553
  }
583
554
 
@@ -634,64 +605,6 @@ void Nokogiri_xml_node_namespaces(xmlNodePtr node, VALUE attr_hash)
634
605
  }
635
606
 
636
607
 
637
- void Nokogiri_xml_node2obj_set(xmlNodePtr node, VALUE rb_obj)
638
- {
639
- VALUE hash = rb_cvar_get(cNokogiriXmlNode, rb_intern("@@node2obj"));
640
- VALUE weakref = rb_obj_id(rb_obj) ; /* so GC won't mark the object. sneaky
641
- sneaky. */
642
- rb_hash_aset(hash, INT2NUM((long)node), weakref);
643
- }
644
-
645
- VALUE Nokogiri_xml_node2obj_get(xmlNodePtr node)
646
- {
647
- static VALUE ObjectSpace = 0 ;
648
- static ID id2ref = 0 ;
649
-
650
- if (! ObjectSpace) ObjectSpace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
651
- if (! id2ref) id2ref = rb_intern("_id2ref");
652
-
653
- VALUE hash = rb_cvar_get(cNokogiriXmlNode, rb_intern("@@node2obj"));
654
- VALUE weakref = rb_hash_aref(hash, INT2NUM((long)node)) ;
655
- if (weakref == Qnil)
656
- return Qnil ;
657
- return rb_funcall(ObjectSpace, id2ref, 1, weakref); /* translate weakref to
658
- * the object */
659
- }
660
-
661
- void Nokogiri_xml_node2obj_remove(xmlNodePtr node)
662
- {
663
- VALUE hash = rb_cvar_get(cNokogiriXmlNode, rb_intern("@@node2obj"));
664
- rb_hash_delete(hash, INT2NUM((long)node));
665
- }
666
-
667
- void Nokogiri_xml_node_owned_set(xmlNodePtr node)
668
- {
669
- VALUE hash = rb_cvar_get(cNokogiriXmlNode, rb_intern("@@owned"));
670
- rb_hash_aset(hash, INT2NUM((long)node), node->parent ? Qtrue : Qfalse) ;
671
- }
672
-
673
- int Nokogiri_xml_node_owned_get(xmlNodePtr node)
674
- {
675
- VALUE hash = rb_cvar_get(cNokogiriXmlNode, rb_intern("@@owned"));
676
- VALUE q = rb_hash_aref(hash, INT2NUM((long)node)) ;
677
- return q == Qtrue ? Qtrue : Qfalse ;
678
- }
679
-
680
- /*
681
- * call-seq:
682
- * owned?
683
- *
684
- * Is this node owned by a document?
685
- */
686
- static VALUE owned_eh(VALUE self)
687
- {
688
- xmlNodePtr node ;
689
- VALUE hash = rb_cvar_get(cNokogiriXmlNode, rb_intern("@@owned"));
690
- Data_Get_Struct(self, xmlNode, node);
691
- return rb_hash_aref(hash, INT2NUM((long)node)) == Qtrue ? Qtrue : Qfalse ;
692
- }
693
-
694
-
695
608
  VALUE cNokogiriXmlNode ;
696
609
  void init_xml_node()
697
610
  {
@@ -706,10 +619,9 @@ void init_xml_node()
706
619
 
707
620
  VALUE klass = cNokogiriXmlNode = rb_const_get(mNokogiriXml, rb_intern("Node"));
708
621
 
709
- rb_define_singleton_method(klass, "new", new, 1);
622
+ rb_define_singleton_method(klass, "new", new, 2);
710
623
  rb_define_singleton_method(klass, "new_from_str", new_from_str, 1);
711
624
 
712
- rb_define_method(klass, "document", document, 0);
713
625
  rb_define_method(klass, "name", get_name, 0);
714
626
  rb_define_method(klass, "name=", set_name, 1);
715
627
  rb_define_method(klass, "parent=", set_parent, 1);
@@ -734,8 +646,8 @@ void init_xml_node()
734
646
  rb_define_method(klass, "dup", duplicate_node, 0);
735
647
  rb_define_method(klass, "unlink", unlink_node, 0);
736
648
  rb_define_method(klass, "internal_subset", internal_subset, 0);
649
+ rb_define_method(klass, "pointer_id", pointer_id, 0);
737
650
 
738
651
  rb_define_private_method(klass, "native_content=", set_content, 1);
739
652
  rb_define_private_method(klass, "get", get, 1);
740
- rb_define_private_method(klass, "owned?", owned_eh, 0);
741
653
  }