nokogiri 1.13.10 → 1.14.0.rc1

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.

Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +33 -0
  3. data/LICENSE-DEPENDENCIES.md +830 -509
  4. data/README.md +18 -11
  5. data/dependencies.yml +25 -7
  6. data/ext/nokogiri/extconf.rb +79 -20
  7. data/ext/nokogiri/gumbo.c +19 -9
  8. data/ext/nokogiri/html4_document.c +1 -1
  9. data/ext/nokogiri/html4_entity_lookup.c +1 -1
  10. data/ext/nokogiri/html4_sax_parser_context.c +0 -5
  11. data/ext/nokogiri/nokogiri.c +32 -51
  12. data/ext/nokogiri/nokogiri.h +17 -14
  13. data/ext/nokogiri/xml_attribute_decl.c +1 -1
  14. data/ext/nokogiri/xml_cdata.c +1 -1
  15. data/ext/nokogiri/xml_document.c +16 -11
  16. data/ext/nokogiri/xml_element_content.c +2 -2
  17. data/ext/nokogiri/xml_element_decl.c +1 -1
  18. data/ext/nokogiri/xml_encoding_handler.c +2 -2
  19. data/ext/nokogiri/xml_namespace.c +38 -8
  20. data/ext/nokogiri/xml_node.c +286 -26
  21. data/ext/nokogiri/xml_node_set.c +0 -2
  22. data/ext/nokogiri/xml_reader.c +40 -20
  23. data/ext/nokogiri/xml_relax_ng.c +0 -2
  24. data/ext/nokogiri/xml_sax_parser.c +22 -16
  25. data/ext/nokogiri/xml_sax_parser_context.c +0 -5
  26. data/ext/nokogiri/xml_sax_push_parser.c +0 -2
  27. data/ext/nokogiri/xml_schema.c +0 -2
  28. data/ext/nokogiri/xml_xpath_context.c +87 -83
  29. data/ext/nokogiri/xslt_stylesheet.c +14 -13
  30. data/gumbo-parser/Makefile +10 -0
  31. data/gumbo-parser/src/attribute.h +1 -1
  32. data/gumbo-parser/src/error.c +1 -1
  33. data/gumbo-parser/src/error.h +1 -1
  34. data/gumbo-parser/src/foreign_attrs.c +2 -2
  35. data/gumbo-parser/src/{gumbo.h → nokogiri_gumbo.h} +1 -0
  36. data/gumbo-parser/src/parser.c +7 -4
  37. data/gumbo-parser/src/replacement.h +1 -1
  38. data/gumbo-parser/src/string_buffer.h +1 -1
  39. data/gumbo-parser/src/string_piece.c +1 -1
  40. data/gumbo-parser/src/svg_attrs.c +2 -2
  41. data/gumbo-parser/src/svg_tags.c +2 -2
  42. data/gumbo-parser/src/tag.c +2 -1
  43. data/gumbo-parser/src/tag_lookup.c +7 -7
  44. data/gumbo-parser/src/tag_lookup.gperf +1 -0
  45. data/gumbo-parser/src/tag_lookup.h +1 -1
  46. data/gumbo-parser/src/token_buffer.h +1 -1
  47. data/gumbo-parser/src/tokenizer.c +1 -1
  48. data/gumbo-parser/src/tokenizer.h +1 -1
  49. data/gumbo-parser/src/utf8.c +1 -1
  50. data/gumbo-parser/src/utf8.h +1 -1
  51. data/gumbo-parser/src/util.c +1 -3
  52. data/gumbo-parser/src/util.h +4 -0
  53. data/gumbo-parser/src/vector.h +1 -1
  54. data/lib/nokogiri/css/node.rb +2 -2
  55. data/lib/nokogiri/css/xpath_visitor.rb +3 -1
  56. data/lib/nokogiri/css.rb +6 -0
  57. data/lib/nokogiri/encoding_handler.rb +57 -0
  58. data/lib/nokogiri/extension.rb +3 -2
  59. data/lib/nokogiri/html4/document.rb +2 -121
  60. data/lib/nokogiri/html4/element_description_defaults.rb +6 -12
  61. data/lib/nokogiri/html4/encoding_reader.rb +121 -0
  62. data/lib/nokogiri/html4.rb +1 -0
  63. data/lib/nokogiri/html5/document.rb +113 -36
  64. data/lib/nokogiri/html5/document_fragment.rb +9 -2
  65. data/lib/nokogiri/html5/node.rb +3 -5
  66. data/lib/nokogiri/html5.rb +127 -216
  67. data/lib/nokogiri/jruby/dependencies.rb +1 -19
  68. data/lib/nokogiri/jruby/nokogiri_jars.rb +43 -0
  69. data/lib/nokogiri/version/constant.rb +1 -1
  70. data/lib/nokogiri/version/info.rb +11 -10
  71. data/lib/nokogiri/xml/attr.rb +49 -0
  72. data/lib/nokogiri/xml/builder.rb +1 -1
  73. data/lib/nokogiri/xml/document.rb +102 -54
  74. data/lib/nokogiri/xml/document_fragment.rb +49 -6
  75. data/lib/nokogiri/xml/namespace.rb +42 -0
  76. data/lib/nokogiri/xml/node/save_options.rb +4 -2
  77. data/lib/nokogiri/xml/node.rb +190 -35
  78. data/lib/nokogiri/xml/node_set.rb +87 -9
  79. data/lib/nokogiri/xml/parse_options.rb +127 -48
  80. data/lib/nokogiri/xml/pp/node.rb +6 -4
  81. data/lib/nokogiri/xml/processing_instruction.rb +2 -1
  82. data/lib/nokogiri/xml/sax/parser.rb +2 -3
  83. data/lib/nokogiri/xslt.rb +1 -1
  84. data/lib/nokogiri.rb +3 -11
  85. metadata +11 -247
  86. data/patches/libxml2/0005-avoid-isnan-isinf.patch +0 -81
@@ -88,13 +88,11 @@ deallocate(xmlNodeSetPtr node_set)
88
88
  * For reasons outlined in xml_namespace.c, here we reproduce xmlXPathFreeNodeSet() except for the
89
89
  * offending call to xmlXPathNodeSetFreeNs().
90
90
  */
91
- NOKOGIRI_DEBUG_START(node_set) ;
92
91
  if (node_set->nodeTab != NULL) {
93
92
  xmlFree(node_set->nodeTab);
94
93
  }
95
94
 
96
95
  xmlFree(node_set);
97
- NOKOGIRI_DEBUG_END(node_set) ;
98
96
  }
99
97
 
100
98
 
@@ -5,9 +5,7 @@ VALUE cNokogiriXmlReader;
5
5
  static void
6
6
  dealloc(xmlTextReaderPtr reader)
7
7
  {
8
- NOKOGIRI_DEBUG_START(reader);
9
8
  xmlFreeTextReader(reader);
10
- NOKOGIRI_DEBUG_END(reader);
11
9
  }
12
10
 
13
11
  static int
@@ -126,26 +124,37 @@ attributes_eh(VALUE self)
126
124
  * Get a hash of namespaces for this Node
127
125
  */
128
126
  static VALUE
129
- namespaces(VALUE self)
127
+ rb_xml_reader_namespaces(VALUE rb_reader)
130
128
  {
131
- xmlTextReaderPtr reader;
132
- xmlNodePtr ptr;
133
- VALUE attr ;
134
-
135
- Data_Get_Struct(self, xmlTextReader, reader);
129
+ VALUE rb_namespaces = rb_hash_new() ;
130
+ xmlTextReaderPtr c_reader;
131
+ xmlNodePtr c_node;
132
+ VALUE rb_errors;
136
133
 
137
- attr = rb_hash_new() ;
134
+ Data_Get_Struct(rb_reader, xmlTextReader, c_reader);
138
135
 
139
- if (! has_attributes(reader)) {
140
- return attr ;
136
+ if (! has_attributes(c_reader)) {
137
+ return rb_namespaces ;
141
138
  }
142
139
 
143
- ptr = xmlTextReaderExpand(reader);
144
- if (ptr == NULL) { return Qnil; }
140
+ rb_errors = rb_funcall(rb_reader, rb_intern("errors"), 0);
145
141
 
146
- Nokogiri_xml_node_namespaces(ptr, attr);
142
+ xmlSetStructuredErrorFunc((void *)rb_errors, Nokogiri_error_array_pusher);
143
+ c_node = xmlTextReaderExpand(c_reader);
144
+ xmlSetStructuredErrorFunc(NULL, NULL);
147
145
 
148
- return attr ;
146
+ if (c_node == NULL) {
147
+ if (RARRAY_LEN(rb_errors) > 0) {
148
+ VALUE rb_error = rb_ary_entry(rb_errors, 0);
149
+ VALUE exception_message = rb_funcall(rb_error, rb_intern("to_s"), 0);
150
+ rb_exc_raise(rb_class_new_instance(1, &exception_message, cNokogiriXmlSyntaxError));
151
+ }
152
+ return Qnil;
153
+ }
154
+
155
+ Nokogiri_xml_node_namespaces(c_node, rb_namespaces);
156
+
157
+ return rb_namespaces ;
149
158
  }
150
159
 
151
160
  /*
@@ -204,6 +213,7 @@ rb_xml_reader_attribute_hash(VALUE rb_reader)
204
213
  xmlTextReaderPtr c_reader;
205
214
  xmlNodePtr c_node;
206
215
  xmlAttrPtr c_property;
216
+ VALUE rb_errors;
207
217
 
208
218
  Data_Get_Struct(rb_reader, xmlTextReader, c_reader);
209
219
 
@@ -211,8 +221,18 @@ rb_xml_reader_attribute_hash(VALUE rb_reader)
211
221
  return rb_attributes;
212
222
  }
213
223
 
224
+ rb_errors = rb_funcall(rb_reader, rb_intern("errors"), 0);
225
+
226
+ xmlSetStructuredErrorFunc((void *)rb_errors, Nokogiri_error_array_pusher);
214
227
  c_node = xmlTextReaderExpand(c_reader);
228
+ xmlSetStructuredErrorFunc(NULL, NULL);
229
+
215
230
  if (c_node == NULL) {
231
+ if (RARRAY_LEN(rb_errors) > 0) {
232
+ VALUE rb_error = rb_ary_entry(rb_errors, 0);
233
+ VALUE exception_message = rb_funcall(rb_error, rb_intern("to_s"), 0);
234
+ rb_exc_raise(rb_class_new_instance(1, &exception_message, cNokogiriXmlSyntaxError));
235
+ }
216
236
  return Qnil;
217
237
  }
218
238
 
@@ -306,7 +326,7 @@ attribute_count(VALUE self)
306
326
  count = xmlTextReaderAttributeCount(reader);
307
327
  if (count == -1) { return Qnil; }
308
328
 
309
- return INT2NUM((long)count);
329
+ return INT2NUM(count);
310
330
  }
311
331
 
312
332
  /*
@@ -325,7 +345,7 @@ depth(VALUE self)
325
345
  depth = xmlTextReaderDepth(reader);
326
346
  if (depth == -1) { return Qnil; }
327
347
 
328
- return INT2NUM((long)depth);
348
+ return INT2NUM(depth);
329
349
  }
330
350
 
331
351
  /*
@@ -498,7 +518,7 @@ state(VALUE self)
498
518
  {
499
519
  xmlTextReaderPtr reader;
500
520
  Data_Get_Struct(self, xmlTextReader, reader);
501
- return INT2NUM((long)xmlTextReaderReadState(reader));
521
+ return INT2NUM(xmlTextReaderReadState(reader));
502
522
  }
503
523
 
504
524
  /*
@@ -512,7 +532,7 @@ node_type(VALUE self)
512
532
  {
513
533
  xmlTextReaderPtr reader;
514
534
  Data_Get_Struct(self, xmlTextReader, reader);
515
- return INT2NUM((long)xmlTextReaderNodeType(reader));
535
+ return INT2NUM(xmlTextReaderNodeType(reader));
516
536
  }
517
537
 
518
538
  /*
@@ -762,7 +782,7 @@ noko_init_xml_reader()
762
782
  rb_define_method(cNokogiriXmlReader, "local_name", local_name, 0);
763
783
  rb_define_method(cNokogiriXmlReader, "name", name, 0);
764
784
  rb_define_method(cNokogiriXmlReader, "namespace_uri", namespace_uri, 0);
765
- rb_define_method(cNokogiriXmlReader, "namespaces", namespaces, 0);
785
+ rb_define_method(cNokogiriXmlReader, "namespaces", rb_xml_reader_namespaces, 0);
766
786
  rb_define_method(cNokogiriXmlReader, "node_type", node_type, 0);
767
787
  rb_define_method(cNokogiriXmlReader, "outer_xml", outer_xml, 0);
768
788
  rb_define_method(cNokogiriXmlReader, "prefix", prefix, 0);
@@ -5,9 +5,7 @@ VALUE cNokogiriXmlRelaxNG;
5
5
  static void
6
6
  dealloc(xmlRelaxNGPtr schema)
7
7
  {
8
- NOKOGIRI_DEBUG_START(schema);
9
8
  xmlRelaxNGFree(schema);
10
- NOKOGIRI_DEBUG_END(schema);
11
9
  }
12
10
 
13
11
  /*
@@ -195,40 +195,48 @@ comment_func(void *ctx, const xmlChar *value)
195
195
  rb_funcall(doc, id_comment, 1, str);
196
196
  }
197
197
 
198
+ PRINTFLIKE_DECL(2, 3)
198
199
  static void
199
200
  warning_func(void *ctx, const char *msg, ...)
200
201
  {
201
202
  VALUE self = NOKOGIRI_SAX_SELF(ctx);
202
203
  VALUE doc = rb_iv_get(self, "@document");
203
- char *message;
204
- VALUE ruby_message;
204
+ VALUE rb_message;
205
205
 
206
+ #ifdef TRUFFLERUBY_NOKOGIRI_SYSTEM_LIBRARIES
207
+ /* It is not currently possible to pass var args from native
208
+ functions to sulong, so we work around the issue here. */
209
+ rb_message = rb_sprintf("warning_func: %s", msg);
210
+ #else
206
211
  va_list args;
207
212
  va_start(args, msg);
208
- vasprintf(&message, msg, args);
213
+ rb_message = rb_vsprintf(msg, args);
209
214
  va_end(args);
215
+ #endif
210
216
 
211
- ruby_message = NOKOGIRI_STR_NEW2(message);
212
- free(message);
213
- rb_funcall(doc, id_warning, 1, ruby_message);
217
+ rb_funcall(doc, id_warning, 1, rb_message);
214
218
  }
215
219
 
220
+ PRINTFLIKE_DECL(2, 3)
216
221
  static void
217
222
  error_func(void *ctx, const char *msg, ...)
218
223
  {
219
224
  VALUE self = NOKOGIRI_SAX_SELF(ctx);
220
225
  VALUE doc = rb_iv_get(self, "@document");
221
- char *message;
222
- VALUE ruby_message;
226
+ VALUE rb_message;
223
227
 
228
+ #ifdef TRUFFLERUBY_NOKOGIRI_SYSTEM_LIBRARIES
229
+ /* It is not currently possible to pass var args from native
230
+ functions to sulong, so we work around the issue here. */
231
+ rb_message = rb_sprintf("error_func: %s", msg);
232
+ #else
224
233
  va_list args;
225
234
  va_start(args, msg);
226
- vasprintf(&message, msg, args);
235
+ rb_message = rb_vsprintf(msg, args);
227
236
  va_end(args);
237
+ #endif
228
238
 
229
- ruby_message = NOKOGIRI_STR_NEW2(message);
230
- free(message);
231
- rb_funcall(doc, id_error, 1, ruby_message);
239
+ rb_funcall(doc, id_error, 1, rb_message);
232
240
  }
233
241
 
234
242
  static void
@@ -260,15 +268,13 @@ processing_instruction(void *ctx, const xmlChar *name, const xmlChar *content)
260
268
  static void
261
269
  deallocate(xmlSAXHandlerPtr handler)
262
270
  {
263
- NOKOGIRI_DEBUG_START(handler);
264
- free(handler);
265
- NOKOGIRI_DEBUG_END(handler);
271
+ ruby_xfree(handler);
266
272
  }
267
273
 
268
274
  static VALUE
269
275
  allocate(VALUE klass)
270
276
  {
271
- xmlSAXHandlerPtr handler = calloc((size_t)1, sizeof(xmlSAXHandler));
277
+ xmlSAXHandlerPtr handler = ruby_xcalloc((size_t)1, sizeof(xmlSAXHandler));
272
278
 
273
279
  handler->startDocument = start_document;
274
280
  handler->endDocument = end_document;
@@ -7,13 +7,8 @@ static ID id_read;
7
7
  static void
8
8
  deallocate(xmlParserCtxtPtr ctxt)
9
9
  {
10
- NOKOGIRI_DEBUG_START(ctxt);
11
-
12
10
  ctxt->sax = NULL;
13
-
14
11
  xmlFreeParserCtxt(ctxt);
15
-
16
- NOKOGIRI_DEBUG_END(ctxt);
17
12
  }
18
13
 
19
14
  /*
@@ -5,12 +5,10 @@ VALUE cNokogiriXmlSaxPushParser ;
5
5
  static void
6
6
  deallocate(xmlParserCtxtPtr ctx)
7
7
  {
8
- NOKOGIRI_DEBUG_START(ctx);
9
8
  if (ctx != NULL) {
10
9
  NOKOGIRI_SAX_TUPLE_DESTROY(ctx->userData);
11
10
  xmlFreeParserCtxt(ctx);
12
11
  }
13
- NOKOGIRI_DEBUG_END(ctx);
14
12
  }
15
13
 
16
14
  static VALUE
@@ -5,9 +5,7 @@ VALUE cNokogiriXmlSchema;
5
5
  static void
6
6
  dealloc(xmlSchemaPtr schema)
7
7
  {
8
- NOKOGIRI_DEBUG_START(schema);
9
8
  xmlSchemaFree(schema);
10
- NOKOGIRI_DEBUG_END(schema);
11
9
  }
12
10
 
13
11
  /*
@@ -6,15 +6,15 @@ VALUE cNokogiriXmlXpathContext;
6
6
  * these constants have matching declarations in
7
7
  * ext/java/nokogiri/internals/NokogiriNamespaceContext.java
8
8
  */
9
+ static const xmlChar *NOKOGIRI_PREFIX = (const xmlChar *)"nokogiri";
10
+ static const xmlChar *NOKOGIRI_URI = (const xmlChar *)"http://www.nokogiri.org/default_ns/ruby/extensions_functions";
9
11
  static const xmlChar *NOKOGIRI_BUILTIN_PREFIX = (const xmlChar *)"nokogiri-builtin";
10
12
  static const xmlChar *NOKOGIRI_BUILTIN_URI = (const xmlChar *)"https://www.nokogiri.org/default_ns/ruby/builtins";
11
13
 
12
14
  static void
13
- deallocate(xmlXPathContextPtr ctx)
15
+ xml_xpath_context_deallocate(xmlXPathContextPtr ctx)
14
16
  {
15
- NOKOGIRI_DEBUG_START(ctx);
16
17
  xmlXPathFreeContext(ctx);
17
- NOKOGIRI_DEBUG_END(ctx);
18
18
  }
19
19
 
20
20
  /* find a CSS class in an HTML element's `class` attribute */
@@ -113,7 +113,7 @@ xpath_builtin_local_name_is(xmlXPathParserContextPtr ctxt, int nargs)
113
113
  * Register the namespace with +prefix+ and +uri+.
114
114
  */
115
115
  static VALUE
116
- register_ns(VALUE self, VALUE prefix, VALUE uri)
116
+ rb_xml_xpath_context_register_ns(VALUE self, VALUE prefix, VALUE uri)
117
117
  {
118
118
  xmlXPathContextPtr ctx;
119
119
  Data_Get_Struct(self, xmlXPathContext, ctx);
@@ -132,7 +132,7 @@ register_ns(VALUE self, VALUE prefix, VALUE uri)
132
132
  * Register the variable +name+ with +value+.
133
133
  */
134
134
  static VALUE
135
- register_variable(VALUE self, VALUE name, VALUE value)
135
+ rb_xml_xpath_context_register_variable(VALUE self, VALUE name, VALUE value)
136
136
  {
137
137
  xmlXPathContextPtr ctx;
138
138
  xmlXPathObjectPtr xmlValue;
@@ -154,28 +154,28 @@ register_variable(VALUE self, VALUE name, VALUE value)
154
154
  * returns Qundef if no conversion was possible.
155
155
  */
156
156
  static VALUE
157
- xpath2ruby(xmlXPathObjectPtr xobj, xmlXPathContextPtr xctx)
157
+ xpath2ruby(xmlXPathObjectPtr c_xpath_object, xmlXPathContextPtr ctx)
158
158
  {
159
- VALUE retval;
159
+ VALUE rb_retval;
160
160
 
161
- assert(xctx->doc);
162
- assert(DOC_RUBY_OBJECT_TEST(xctx->doc));
161
+ assert(ctx->doc);
162
+ assert(DOC_RUBY_OBJECT_TEST(ctx->doc));
163
163
 
164
- switch (xobj->type) {
164
+ switch (c_xpath_object->type) {
165
165
  case XPATH_STRING:
166
- retval = NOKOGIRI_STR_NEW2(xobj->stringval);
167
- xmlFree(xobj->stringval);
168
- return retval;
166
+ rb_retval = NOKOGIRI_STR_NEW2(c_xpath_object->stringval);
167
+ xmlFree(c_xpath_object->stringval);
168
+ return rb_retval;
169
169
 
170
170
  case XPATH_NODESET:
171
- return noko_xml_node_set_wrap(xobj->nodesetval,
172
- DOC_RUBY_OBJECT(xctx->doc));
171
+ return noko_xml_node_set_wrap(c_xpath_object->nodesetval,
172
+ DOC_RUBY_OBJECT(ctx->doc));
173
173
 
174
174
  case XPATH_NUMBER:
175
- return rb_float_new(xobj->floatval);
175
+ return rb_float_new(c_xpath_object->floatval);
176
176
 
177
177
  case XPATH_BOOLEAN:
178
- return (xobj->boolval == 1) ? Qtrue : Qfalse;
178
+ return (c_xpath_object->boolval == 1) ? Qtrue : Qfalse;
179
179
 
180
180
  default:
181
181
  return Qundef;
@@ -183,52 +183,51 @@ xpath2ruby(xmlXPathObjectPtr xobj, xmlXPathContextPtr xctx)
183
183
  }
184
184
 
185
185
  void
186
- Nokogiri_marshal_xpath_funcall_and_return_values(xmlXPathParserContextPtr ctx, int nargs, VALUE handler,
187
- const char *function_name)
186
+ Nokogiri_marshal_xpath_funcall_and_return_values(
187
+ xmlXPathParserContextPtr ctx,
188
+ int argc,
189
+ VALUE rb_xpath_handler,
190
+ const char *method_name
191
+ )
188
192
  {
189
- VALUE result, doc;
193
+ VALUE rb_retval;
190
194
  VALUE *argv;
191
- VALUE node_set = Qnil;
192
- xmlNodeSetPtr xml_node_set = NULL;
193
- xmlXPathObjectPtr obj;
195
+ VALUE rb_node_set = Qnil;
196
+ xmlNodeSetPtr c_node_set = NULL;
197
+ xmlXPathObjectPtr c_xpath_object;
194
198
 
195
199
  assert(ctx->context->doc);
196
200
  assert(DOC_RUBY_OBJECT_TEST(ctx->context->doc));
197
201
 
198
- argv = (VALUE *)calloc((size_t)nargs, sizeof(VALUE));
199
- for (int j = 0 ; j < nargs ; ++j) {
202
+ argv = (VALUE *)ruby_xcalloc((size_t)argc, sizeof(VALUE));
203
+ for (int j = 0 ; j < argc ; ++j) {
200
204
  rb_gc_register_address(&argv[j]);
201
205
  }
202
206
 
203
- doc = DOC_RUBY_OBJECT(ctx->context->doc);
204
-
205
- for (int j = nargs - 1 ; j >= 0 ; --j) {
206
- obj = valuePop(ctx);
207
- argv[j] = xpath2ruby(obj, ctx->context);
207
+ for (int j = argc - 1 ; j >= 0 ; --j) {
208
+ c_xpath_object = valuePop(ctx);
209
+ argv[j] = xpath2ruby(c_xpath_object, ctx->context);
208
210
  if (argv[j] == Qundef) {
209
- argv[j] = NOKOGIRI_STR_NEW2(xmlXPathCastToString(obj));
211
+ argv[j] = NOKOGIRI_STR_NEW2(xmlXPathCastToString(c_xpath_object));
210
212
  }
211
- xmlXPathFreeNodeSetList(obj);
213
+ xmlXPathFreeNodeSetList(c_xpath_object);
212
214
  }
213
215
 
214
- result = rb_funcall2(handler, rb_intern((const char *)function_name), nargs, argv);
216
+ rb_retval = rb_funcall2(rb_xpath_handler, rb_intern((const char *)method_name), argc, argv);
215
217
 
216
- for (int j = 0 ; j < nargs ; ++j) {
218
+ for (int j = 0 ; j < argc ; ++j) {
217
219
  rb_gc_unregister_address(&argv[j]);
218
220
  }
219
- free(argv);
221
+ ruby_xfree(argv);
220
222
 
221
- switch (TYPE(result)) {
223
+ switch (TYPE(rb_retval)) {
222
224
  case T_FLOAT:
223
225
  case T_BIGNUM:
224
226
  case T_FIXNUM:
225
- xmlXPathReturnNumber(ctx, NUM2DBL(result));
227
+ xmlXPathReturnNumber(ctx, NUM2DBL(rb_retval));
226
228
  break;
227
229
  case T_STRING:
228
- xmlXPathReturnString(
229
- ctx,
230
- xmlCharStrdup(StringValueCStr(result))
231
- );
230
+ xmlXPathReturnString(ctx, xmlCharStrdup(StringValueCStr(rb_retval)));
232
231
  break;
233
232
  case T_TRUE:
234
233
  xmlXPathReturnTrue(ctx);
@@ -239,19 +238,17 @@ Nokogiri_marshal_xpath_funcall_and_return_values(xmlXPathParserContextPtr ctx, i
239
238
  case T_NIL:
240
239
  break;
241
240
  case T_ARRAY: {
242
- VALUE args[2];
243
- args[0] = doc;
244
- args[1] = result;
245
- node_set = rb_class_new_instance(2, args, cNokogiriXmlNodeSet);
246
- Data_Get_Struct(node_set, xmlNodeSet, xml_node_set);
247
- xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, xml_node_set));
241
+ VALUE construct_args[2] = { DOC_RUBY_OBJECT(ctx->context->doc), rb_retval };
242
+ rb_node_set = rb_class_new_instance(2, construct_args, cNokogiriXmlNodeSet);
243
+ Data_Get_Struct(rb_node_set, xmlNodeSet, c_node_set);
244
+ xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, c_node_set));
248
245
  }
249
246
  break;
250
247
  case T_DATA:
251
- if (rb_obj_is_kind_of(result, cNokogiriXmlNodeSet)) {
252
- Data_Get_Struct(result, xmlNodeSet, xml_node_set);
248
+ if (rb_obj_is_kind_of(rb_retval, cNokogiriXmlNodeSet)) {
249
+ Data_Get_Struct(rb_retval, xmlNodeSet, c_node_set);
253
250
  /* Copy the node set, otherwise it will get GC'd. */
254
- xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, xml_node_set));
251
+ xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, c_node_set));
255
252
  break;
256
253
  }
257
254
  default:
@@ -260,47 +257,56 @@ Nokogiri_marshal_xpath_funcall_and_return_values(xmlXPathParserContextPtr ctx, i
260
257
  }
261
258
 
262
259
  static void
263
- ruby_funcall(xmlXPathParserContextPtr ctx, int nargs)
260
+ method_caller(xmlXPathParserContextPtr ctx, int argc)
264
261
  {
265
- VALUE handler = Qnil;
266
- const char *function = NULL ;
262
+ VALUE rb_xpath_handler = Qnil;
263
+ const char *method_name = NULL ;
267
264
 
268
265
  assert(ctx);
269
266
  assert(ctx->context);
270
267
  assert(ctx->context->userData);
271
268
  assert(ctx->context->function);
272
269
 
273
- handler = (VALUE)(ctx->context->userData);
274
- function = (const char *)(ctx->context->function);
270
+ rb_xpath_handler = (VALUE)(ctx->context->userData);
271
+ method_name = (const char *)(ctx->context->function);
275
272
 
276
- Nokogiri_marshal_xpath_funcall_and_return_values(ctx, nargs, handler, function);
273
+ Nokogiri_marshal_xpath_funcall_and_return_values(ctx, argc, rb_xpath_handler, method_name);
277
274
  }
278
275
 
279
276
  static xmlXPathFunction
280
- lookup(void *ctx,
281
- const xmlChar *name,
282
- const xmlChar *ns_uri)
277
+ handler_lookup(void *ctx, const xmlChar *c_name, const xmlChar *c_ns_uri)
283
278
  {
284
- VALUE xpath_handler = (VALUE)ctx;
285
- if (rb_respond_to(xpath_handler, rb_intern((const char *)name))) {
286
- return ruby_funcall;
279
+ VALUE rb_xpath_handler = (VALUE)ctx;
280
+ if (rb_respond_to(rb_xpath_handler, rb_intern((const char *)c_name))) {
281
+ return method_caller;
287
282
  }
288
283
 
289
284
  return NULL;
290
285
  }
291
286
 
292
- NORETURN(static void xpath_generic_exception_handler(void *ctx, const char *msg, ...));
287
+ PRINTFLIKE_DECL(2, 3)
293
288
  static void
294
- xpath_generic_exception_handler(void *ctx, const char *msg, ...)
289
+ generic_exception_pusher(void *ctx, const char *msg, ...)
295
290
  {
296
- char *message;
291
+ VALUE rb_errors = (VALUE)ctx;
292
+ VALUE rb_message;
293
+ VALUE rb_exception;
294
+
295
+ Check_Type(rb_errors, T_ARRAY);
297
296
 
297
+ #ifdef TRUFFLERUBY_NOKOGIRI_SYSTEM_LIBRARIES
298
+ /* It is not currently possible to pass var args from native
299
+ functions to sulong, so we work around the issue here. */
300
+ rb_message = rb_sprintf("generic_exception_pusher: %s", msg);
301
+ #else
298
302
  va_list args;
299
303
  va_start(args, msg);
300
- vasprintf(&message, msg, args);
304
+ rb_message = rb_vsprintf(msg, args);
301
305
  va_end(args);
306
+ #endif
302
307
 
303
- rb_raise(rb_eRuntimeError, "%s", message);
308
+ rb_exception = rb_exc_new_str(cNokogiriXmlXpathSyntaxError, rb_message);
309
+ rb_ary_push(rb_errors, rb_exception);
304
310
  }
305
311
 
306
312
  /*
@@ -310,13 +316,14 @@ xpath_generic_exception_handler(void *ctx, const char *msg, ...)
310
316
  * Evaluate the +search_path+ returning an XML::XPath object.
311
317
  */
312
318
  static VALUE
313
- evaluate(int argc, VALUE *argv, VALUE self)
319
+ rb_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE self)
314
320
  {
315
321
  VALUE search_path, xpath_handler;
316
322
  VALUE retval = Qnil;
317
323
  xmlXPathContextPtr ctx;
318
324
  xmlXPathObjectPtr xpath;
319
325
  xmlChar *query;
326
+ VALUE errors = rb_ary_new();
320
327
 
321
328
  Data_Get_Struct(self, xmlXPathContext, ctx);
322
329
 
@@ -329,23 +336,19 @@ evaluate(int argc, VALUE *argv, VALUE self)
329
336
  if (Qnil != xpath_handler) {
330
337
  /* FIXME: not sure if this is the correct place to shove private data. */
331
338
  ctx->userData = (void *)xpath_handler;
332
- xmlXPathRegisterFuncLookup(ctx, lookup, (void *)xpath_handler);
339
+ xmlXPathRegisterFuncLookup(ctx, handler_lookup, (void *)xpath_handler);
333
340
  }
334
341
 
335
- xmlResetLastError();
336
- xmlSetStructuredErrorFunc(NULL, Nokogiri_error_raise);
337
-
338
- /* For some reason, xmlXPathEvalExpression will blow up with a generic error */
339
- /* when there is a non existent function. */
340
- xmlSetGenericErrorFunc(NULL, xpath_generic_exception_handler);
342
+ xmlSetStructuredErrorFunc((void *)errors, Nokogiri_error_array_pusher);
343
+ xmlSetGenericErrorFunc((void *)errors, generic_exception_pusher);
341
344
 
342
345
  xpath = xmlXPathEvalExpression(query, ctx);
346
+
343
347
  xmlSetStructuredErrorFunc(NULL, NULL);
344
348
  xmlSetGenericErrorFunc(NULL, NULL);
345
349
 
346
350
  if (xpath == NULL) {
347
- xmlErrorPtr error = xmlGetLastError();
348
- rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
351
+ rb_exc_raise(rb_ary_entry(errors, 0));
349
352
  }
350
353
 
351
354
  retval = xpath2ruby(xpath, ctx);
@@ -365,7 +368,7 @@ evaluate(int argc, VALUE *argv, VALUE self)
365
368
  * Create a new XPathContext with +node+ as the reference point.
366
369
  */
367
370
  static VALUE
368
- new (VALUE klass, VALUE nodeobj)
371
+ rb_xml_xpath_context_new(VALUE klass, VALUE nodeobj)
369
372
  {
370
373
  xmlNodePtr node;
371
374
  xmlXPathContextPtr ctx;
@@ -381,13 +384,14 @@ new (VALUE klass, VALUE nodeobj)
381
384
  ctx = xmlXPathNewContext(node->doc);
382
385
  ctx->node = node;
383
386
 
387
+ xmlXPathRegisterNs(ctx, NOKOGIRI_PREFIX, NOKOGIRI_URI);
384
388
  xmlXPathRegisterNs(ctx, NOKOGIRI_BUILTIN_PREFIX, NOKOGIRI_BUILTIN_URI);
385
389
  xmlXPathRegisterFuncNS(ctx, (const xmlChar *)"css-class", NOKOGIRI_BUILTIN_URI,
386
390
  xpath_builtin_css_class);
387
391
  xmlXPathRegisterFuncNS(ctx, (const xmlChar *)"local-name-is", NOKOGIRI_BUILTIN_URI,
388
392
  xpath_builtin_local_name_is);
389
393
 
390
- self = Data_Wrap_Struct(klass, 0, deallocate, ctx);
394
+ self = Data_Wrap_Struct(klass, 0, xml_xpath_context_deallocate, ctx);
391
395
  return self;
392
396
  }
393
397
 
@@ -401,9 +405,9 @@ noko_init_xml_xpath_context(void)
401
405
 
402
406
  rb_undef_alloc_func(cNokogiriXmlXpathContext);
403
407
 
404
- rb_define_singleton_method(cNokogiriXmlXpathContext, "new", new, 1);
408
+ rb_define_singleton_method(cNokogiriXmlXpathContext, "new", rb_xml_xpath_context_new, 1);
405
409
 
406
- rb_define_method(cNokogiriXmlXpathContext, "evaluate", evaluate, -1);
407
- rb_define_method(cNokogiriXmlXpathContext, "register_variable", register_variable, 2);
408
- rb_define_method(cNokogiriXmlXpathContext, "register_ns", register_ns, 2);
410
+ rb_define_method(cNokogiriXmlXpathContext, "evaluate", rb_xml_xpath_context_evaluate, -1);
411
+ rb_define_method(cNokogiriXmlXpathContext, "register_variable", rb_xml_xpath_context_register_variable, 2);
412
+ rb_define_method(cNokogiriXmlXpathContext, "register_ns", rb_xml_xpath_context_register_ns, 2);
409
413
  }
@@ -12,27 +12,28 @@ static void
12
12
  dealloc(nokogiriXsltStylesheetTuple *wrapper)
13
13
  {
14
14
  xsltStylesheetPtr doc = wrapper->ss;
15
-
16
- NOKOGIRI_DEBUG_START(doc);
17
- xsltFreeStylesheet(doc); /* commented out for now. */
18
- NOKOGIRI_DEBUG_END(doc);
19
-
20
- free(wrapper);
15
+ xsltFreeStylesheet(doc);
16
+ ruby_xfree(wrapper);
21
17
  }
22
18
 
19
+ PRINTFLIKE_DECL(2, 3)
23
20
  static void
24
21
  xslt_generic_error_handler(void *ctx, const char *msg, ...)
25
22
  {
26
- char *message;
23
+ VALUE message;
27
24
 
25
+ #ifdef TRUFFLERUBY_NOKOGIRI_SYSTEM_LIBRARIES
26
+ /* It is not currently possible to pass var args from native
27
+ functions to sulong, so we work around the issue here. */
28
+ message = rb_sprintf("xslt_generic_error_handler: %s", msg);
29
+ #else
28
30
  va_list args;
29
31
  va_start(args, msg);
30
- vasprintf(&message, msg, args);
32
+ message = rb_vsprintf(msg, args);
31
33
  va_end(args);
34
+ #endif
32
35
 
33
- rb_str_cat2((VALUE)ctx, message);
34
-
35
- free(message);
36
+ rb_str_concat((VALUE)ctx, message);
36
37
  }
37
38
 
38
39
  VALUE
@@ -248,7 +249,7 @@ transform(int argc, VALUE *argv, VALUE self)
248
249
  Data_Get_Struct(self, nokogiriXsltStylesheetTuple, wrapper);
249
250
 
250
251
  param_len = RARRAY_LEN(paramobj);
251
- params = calloc((size_t)param_len + 1, sizeof(char *));
252
+ params = ruby_xcalloc((size_t)param_len + 1, sizeof(char *));
252
253
  for (j = 0 ; j < param_len ; j++) {
253
254
  VALUE entry = rb_ary_entry(paramobj, j);
254
255
  const char *ptr = StringValueCStr(entry);
@@ -261,7 +262,7 @@ transform(int argc, VALUE *argv, VALUE self)
261
262
  xmlSetGenericErrorFunc((void *)errstr, xslt_generic_error_handler);
262
263
 
263
264
  result = xsltApplyStylesheet(wrapper->ss, xml, params);
264
- free(params);
265
+ ruby_xfree(params);
265
266
 
266
267
  xsltSetGenericErrorFunc(NULL, NULL);
267
268
  xmlSetGenericErrorFunc(NULL, NULL);