nokogiri 1.13.8 → 1.15.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +40 -0
  3. data/LICENSE-DEPENDENCIES.md +830 -509
  4. data/LICENSE.md +1 -1
  5. data/README.md +18 -11
  6. data/dependencies.yml +33 -15
  7. data/ext/nokogiri/extconf.rb +164 -46
  8. data/ext/nokogiri/gumbo.c +20 -10
  9. data/ext/nokogiri/html4_document.c +3 -4
  10. data/ext/nokogiri/html4_element_description.c +20 -15
  11. data/ext/nokogiri/html4_entity_lookup.c +2 -2
  12. data/ext/nokogiri/html4_sax_parser_context.c +11 -22
  13. data/ext/nokogiri/html4_sax_push_parser.c +3 -3
  14. data/ext/nokogiri/nokogiri.c +84 -75
  15. data/ext/nokogiri/nokogiri.h +31 -16
  16. data/ext/nokogiri/test_global_handlers.c +1 -1
  17. data/ext/nokogiri/xml_attr.c +2 -2
  18. data/ext/nokogiri/xml_attribute_decl.c +2 -2
  19. data/ext/nokogiri/xml_cdata.c +32 -18
  20. data/ext/nokogiri/xml_comment.c +2 -2
  21. data/ext/nokogiri/xml_document.c +127 -34
  22. data/ext/nokogiri/xml_document_fragment.c +2 -2
  23. data/ext/nokogiri/xml_dtd.c +2 -2
  24. data/ext/nokogiri/xml_element_content.c +34 -31
  25. data/ext/nokogiri/xml_element_decl.c +7 -7
  26. data/ext/nokogiri/xml_encoding_handler.c +15 -7
  27. data/ext/nokogiri/xml_entity_decl.c +1 -1
  28. data/ext/nokogiri/xml_entity_reference.c +2 -2
  29. data/ext/nokogiri/xml_namespace.c +79 -14
  30. data/ext/nokogiri/xml_node.c +300 -34
  31. data/ext/nokogiri/xml_node_set.c +125 -107
  32. data/ext/nokogiri/xml_processing_instruction.c +2 -2
  33. data/ext/nokogiri/xml_reader.c +81 -48
  34. data/ext/nokogiri/xml_relax_ng.c +66 -81
  35. data/ext/nokogiri/xml_sax_parser.c +45 -20
  36. data/ext/nokogiri/xml_sax_parser_context.c +46 -30
  37. data/ext/nokogiri/xml_sax_push_parser.c +30 -11
  38. data/ext/nokogiri/xml_schema.c +95 -117
  39. data/ext/nokogiri/xml_syntax_error.c +1 -1
  40. data/ext/nokogiri/xml_text.c +28 -14
  41. data/ext/nokogiri/xml_xpath_context.c +216 -136
  42. data/ext/nokogiri/xslt_stylesheet.c +118 -64
  43. data/gumbo-parser/Makefile +10 -0
  44. data/gumbo-parser/src/attribute.h +1 -1
  45. data/gumbo-parser/src/error.c +10 -6
  46. data/gumbo-parser/src/error.h +1 -1
  47. data/gumbo-parser/src/foreign_attrs.c +15 -16
  48. data/gumbo-parser/src/foreign_attrs.gperf +1 -1
  49. data/gumbo-parser/src/{gumbo.h → nokogiri_gumbo.h} +1 -0
  50. data/gumbo-parser/src/parser.c +21 -5
  51. data/gumbo-parser/src/replacement.h +1 -1
  52. data/gumbo-parser/src/string_buffer.h +1 -1
  53. data/gumbo-parser/src/string_piece.c +1 -1
  54. data/gumbo-parser/src/svg_attrs.c +2 -2
  55. data/gumbo-parser/src/svg_tags.c +2 -2
  56. data/gumbo-parser/src/tag.c +2 -1
  57. data/gumbo-parser/src/tag_lookup.c +7 -7
  58. data/gumbo-parser/src/tag_lookup.gperf +1 -0
  59. data/gumbo-parser/src/tag_lookup.h +1 -1
  60. data/gumbo-parser/src/token_buffer.h +1 -1
  61. data/gumbo-parser/src/tokenizer.c +1 -1
  62. data/gumbo-parser/src/tokenizer.h +1 -1
  63. data/gumbo-parser/src/utf8.c +1 -1
  64. data/gumbo-parser/src/utf8.h +1 -1
  65. data/gumbo-parser/src/util.c +1 -3
  66. data/gumbo-parser/src/util.h +4 -0
  67. data/gumbo-parser/src/vector.h +1 -1
  68. data/lib/nokogiri/css/node.rb +2 -2
  69. data/lib/nokogiri/css/xpath_visitor.rb +7 -5
  70. data/lib/nokogiri/css.rb +6 -0
  71. data/lib/nokogiri/decorators/slop.rb +1 -1
  72. data/lib/nokogiri/encoding_handler.rb +57 -0
  73. data/lib/nokogiri/extension.rb +4 -3
  74. data/lib/nokogiri/html4/document.rb +2 -121
  75. data/lib/nokogiri/html4/document_fragment.rb +1 -1
  76. data/lib/nokogiri/html4/element_description_defaults.rb +1827 -365
  77. data/lib/nokogiri/html4/encoding_reader.rb +121 -0
  78. data/lib/nokogiri/html4.rb +1 -0
  79. data/lib/nokogiri/html5/document.rb +113 -36
  80. data/lib/nokogiri/html5/document_fragment.rb +10 -3
  81. data/lib/nokogiri/html5/node.rb +8 -5
  82. data/lib/nokogiri/html5.rb +130 -216
  83. data/lib/nokogiri/jruby/dependencies.rb +1 -19
  84. data/lib/nokogiri/jruby/nokogiri_jars.rb +43 -0
  85. data/lib/nokogiri/version/constant.rb +1 -1
  86. data/lib/nokogiri/version/info.rb +11 -10
  87. data/lib/nokogiri/xml/attr.rb +49 -0
  88. data/lib/nokogiri/xml/attribute_decl.rb +4 -2
  89. data/lib/nokogiri/xml/builder.rb +1 -1
  90. data/lib/nokogiri/xml/document.rb +102 -55
  91. data/lib/nokogiri/xml/document_fragment.rb +50 -7
  92. data/lib/nokogiri/xml/element_content.rb +10 -2
  93. data/lib/nokogiri/xml/element_decl.rb +4 -2
  94. data/lib/nokogiri/xml/entity_decl.rb +4 -2
  95. data/lib/nokogiri/xml/namespace.rb +42 -0
  96. data/lib/nokogiri/xml/node/save_options.rb +14 -4
  97. data/lib/nokogiri/xml/node.rb +212 -48
  98. data/lib/nokogiri/xml/node_set.rb +88 -9
  99. data/lib/nokogiri/xml/parse_options.rb +129 -50
  100. data/lib/nokogiri/xml/pp/node.rb +28 -15
  101. data/lib/nokogiri/xml/processing_instruction.rb +2 -1
  102. data/lib/nokogiri/xml/sax/document.rb +1 -1
  103. data/lib/nokogiri/xml/sax/parser.rb +2 -3
  104. data/lib/nokogiri/xml/searchable.rb +18 -10
  105. data/lib/nokogiri/xslt.rb +74 -4
  106. data/lib/nokogiri.rb +15 -15
  107. data/lib/xsd/xmlparser/nokogiri.rb +4 -2
  108. data/patches/libxml2/0010-update-config.guess-and-config.sub-for-libxml2.patch +224 -0
  109. data/patches/libxml2/0011-rip-out-libxml2-s-libc_single_threaded-support.patch +30 -0
  110. data/patches/libxslt/0001-update-config.guess-and-config.sub-for-libxslt.patch +224 -0
  111. data/ports/archives/libxml2-2.11.7.tar.xz +0 -0
  112. data/ports/archives/libxslt-1.1.39.tar.xz +0 -0
  113. metadata +19 -242
  114. data/patches/libxml2/0004-use-glibc-strlen.patch +0 -53
  115. data/patches/libxml2/0005-avoid-isnan-isinf.patch +0 -81
  116. data/patches/libxml2/0006-update-automake-files-for-arm64.patch +0 -3040
  117. data/patches/libxml2/0008-htmlParseComment-handle-abruptly-closed-comments.patch +0 -61
  118. data/patches/libxslt/0001-update-automake-files-for-arm64.patch +0 -3037
  119. data/ports/archives/libxml2-2.9.14.tar.xz +0 -0
  120. data/ports/archives/libxslt-1.1.35.tar.xz +0 -0
@@ -6,17 +6,26 @@ 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(void *data)
14
16
  {
15
- NOKOGIRI_DEBUG_START(ctx);
16
- xmlXPathFreeContext(ctx);
17
- NOKOGIRI_DEBUG_END(ctx);
17
+ xmlXPathContextPtr c_context = data;
18
+ xmlXPathFreeContext(c_context);
18
19
  }
19
20
 
21
+ static const rb_data_type_t xml_xpath_context_type = {
22
+ .wrap_struct_name = "Nokogiri::XML::XPathContext",
23
+ .function = {
24
+ .dfree = xml_xpath_context_deallocate,
25
+ },
26
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
27
+ };
28
+
20
29
  /* find a CSS class in an HTML element's `class` attribute */
21
30
  static const xmlChar *
22
31
  builtin_css_class(const xmlChar *str, const xmlChar *val)
@@ -87,7 +96,8 @@ xpath_builtin_css_class(xmlXPathParserContextPtr ctxt, int nargs)
87
96
  }
88
97
 
89
98
 
90
- /* xmlXPathFunction to select nodes whose local name matches, for HTML5 CSS queries that should ignore namespaces */
99
+ /* xmlXPathFunction to select nodes whose local name matches, for HTML5 CSS queries that should
100
+ * ignore namespaces */
91
101
  static void
92
102
  xpath_builtin_local_name_is(xmlXPathParserContextPtr ctxt, int nargs)
93
103
  {
@@ -100,7 +110,10 @@ xpath_builtin_local_name_is(xmlXPathParserContextPtr ctxt, int nargs)
100
110
  CHECK_TYPE(XPATH_STRING);
101
111
  element_name = valuePop(ctxt);
102
112
 
103
- valuePush(ctxt, xmlXPathNewBoolean(xmlStrEqual(ctxt->context->node->name, element_name->stringval)));
113
+ valuePush(
114
+ ctxt,
115
+ xmlXPathNewBoolean(xmlStrEqual(ctxt->context->node->name, element_name->stringval))
116
+ );
104
117
 
105
118
  xmlXPathFreeObject(element_name);
106
119
  }
@@ -108,44 +121,61 @@ xpath_builtin_local_name_is(xmlXPathParserContextPtr ctxt, int nargs)
108
121
 
109
122
  /*
110
123
  * call-seq:
111
- * register_ns(prefix, uri)
124
+ * register_ns(prefix, uri) → Nokogiri::XML::XPathContext
125
+ *
126
+ * Register the namespace with +prefix+ and +uri+ for use in future queries.
112
127
  *
113
- * Register the namespace with +prefix+ and +uri+.
128
+ * [Returns] +self+
114
129
  */
115
130
  static VALUE
116
- register_ns(VALUE self, VALUE prefix, VALUE uri)
131
+ rb_xml_xpath_context_register_ns(VALUE rb_context, VALUE prefix, VALUE uri)
117
132
  {
118
- xmlXPathContextPtr ctx;
119
- Data_Get_Struct(self, xmlXPathContext, ctx);
133
+ xmlXPathContextPtr c_context;
120
134
 
121
- xmlXPathRegisterNs(ctx,
135
+ TypedData_Get_Struct(
136
+ rb_context,
137
+ xmlXPathContext,
138
+ &xml_xpath_context_type,
139
+ c_context
140
+ );
141
+
142
+ xmlXPathRegisterNs(c_context,
122
143
  (const xmlChar *)StringValueCStr(prefix),
123
144
  (const xmlChar *)StringValueCStr(uri)
124
145
  );
125
- return self;
146
+ return rb_context;
126
147
  }
127
148
 
128
149
  /*
129
150
  * call-seq:
130
- * register_variable(name, value)
151
+ * register_variable(name, value) → Nokogiri::XML::XPathContext
152
+ *
153
+ * Register the variable +name+ with +value+ for use in future queries.
131
154
  *
132
- * Register the variable +name+ with +value+.
155
+ * [Returns] +self+
133
156
  */
134
157
  static VALUE
135
- register_variable(VALUE self, VALUE name, VALUE value)
158
+ rb_xml_xpath_context_register_variable(VALUE rb_context, VALUE name, VALUE value)
136
159
  {
137
- xmlXPathContextPtr ctx;
160
+ xmlXPathContextPtr c_context;
138
161
  xmlXPathObjectPtr xmlValue;
139
- Data_Get_Struct(self, xmlXPathContext, ctx);
162
+
163
+ TypedData_Get_Struct(
164
+ rb_context,
165
+ xmlXPathContext,
166
+ &xml_xpath_context_type,
167
+ c_context
168
+ );
140
169
 
141
170
  xmlValue = xmlXPathNewCString(StringValueCStr(value));
142
171
 
143
- xmlXPathRegisterVariable(ctx,
144
- (const xmlChar *)StringValueCStr(name),
145
- xmlValue
146
- );
172
+ xmlXPathRegisterVariable(
173
+ c_context,
174
+ (const xmlChar *)StringValueCStr(name),
175
+ xmlValue
176
+ );
147
177
 
148
- return self;
178
+ return rb_context;
149
179
  }
150
180
 
151
181
 
@@ -154,28 +184,30 @@ register_variable(VALUE self, VALUE name, VALUE value)
154
184
  * returns Qundef if no conversion was possible.
155
185
  */
156
186
  static VALUE
157
- xpath2ruby(xmlXPathObjectPtr xobj, xmlXPathContextPtr xctx)
187
+ xpath2ruby(xmlXPathObjectPtr c_xpath_object, xmlXPathContextPtr c_context)
158
188
  {
159
- VALUE retval;
189
+ VALUE rb_retval;
160
190
 
161
- assert(xctx->doc);
162
- assert(DOC_RUBY_OBJECT_TEST(xctx->doc));
191
+ assert(c_context->doc);
192
+ assert(DOC_RUBY_OBJECT_TEST(c_context->doc));
163
193
 
164
- switch (xobj->type) {
194
+ switch (c_xpath_object->type) {
165
195
  case XPATH_STRING:
166
- retval = NOKOGIRI_STR_NEW2(xobj->stringval);
167
- xmlFree(xobj->stringval);
168
- return retval;
196
+ rb_retval = NOKOGIRI_STR_NEW2(c_xpath_object->stringval);
197
+ xmlFree(c_xpath_object->stringval);
198
+ return rb_retval;
169
199
 
170
200
  case XPATH_NODESET:
171
- return noko_xml_node_set_wrap(xobj->nodesetval,
172
- DOC_RUBY_OBJECT(xctx->doc));
201
+ return noko_xml_node_set_wrap(
202
+ c_xpath_object->nodesetval,
203
+ DOC_RUBY_OBJECT(c_context->doc)
204
+ );
173
205
 
174
206
  case XPATH_NUMBER:
175
- return rb_float_new(xobj->floatval);
207
+ return rb_float_new(c_xpath_object->floatval);
176
208
 
177
209
  case XPATH_BOOLEAN:
178
- return (xobj->boolval == 1) ? Qtrue : Qfalse;
210
+ return (c_xpath_object->boolval == 1) ? Qtrue : Qfalse;
179
211
 
180
212
  default:
181
213
  return Qundef;
@@ -183,75 +215,77 @@ xpath2ruby(xmlXPathObjectPtr xobj, xmlXPathContextPtr xctx)
183
215
  }
184
216
 
185
217
  void
186
- Nokogiri_marshal_xpath_funcall_and_return_values(xmlXPathParserContextPtr ctx, int nargs, VALUE handler,
187
- const char *function_name)
218
+ Nokogiri_marshal_xpath_funcall_and_return_values(
219
+ xmlXPathParserContextPtr ctxt,
220
+ int argc,
221
+ VALUE rb_xpath_handler,
222
+ const char *method_name
223
+ )
188
224
  {
189
- VALUE result, doc;
225
+ VALUE rb_retval;
190
226
  VALUE *argv;
191
- VALUE node_set = Qnil;
192
- xmlNodeSetPtr xml_node_set = NULL;
193
- xmlXPathObjectPtr obj;
227
+ VALUE rb_node_set = Qnil;
228
+ xmlNodeSetPtr c_node_set = NULL;
229
+ xmlXPathObjectPtr c_xpath_object;
194
230
 
195
- assert(ctx->context->doc);
196
- assert(DOC_RUBY_OBJECT_TEST(ctx->context->doc));
231
+ assert(ctxt->context->doc);
232
+ assert(DOC_RUBY_OBJECT_TEST(ctxt->context->doc));
197
233
 
198
- argv = (VALUE *)calloc((size_t)nargs, sizeof(VALUE));
199
- for (int j = 0 ; j < nargs ; ++j) {
234
+ argv = (VALUE *)ruby_xcalloc((size_t)argc, sizeof(VALUE));
235
+ for (int j = 0 ; j < argc ; ++j) {
200
236
  rb_gc_register_address(&argv[j]);
201
237
  }
202
238
 
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);
239
+ for (int j = argc - 1 ; j >= 0 ; --j) {
240
+ c_xpath_object = valuePop(ctxt);
241
+ argv[j] = xpath2ruby(c_xpath_object, ctxt->context);
208
242
  if (argv[j] == Qundef) {
209
- argv[j] = NOKOGIRI_STR_NEW2(xmlXPathCastToString(obj));
243
+ argv[j] = NOKOGIRI_STR_NEW2(xmlXPathCastToString(c_xpath_object));
210
244
  }
211
- xmlXPathFreeNodeSetList(obj);
245
+ xmlXPathFreeNodeSetList(c_xpath_object);
212
246
  }
213
247
 
214
- result = rb_funcall2(handler, rb_intern((const char *)function_name), nargs, argv);
248
+ rb_retval = rb_funcall2(
249
+ rb_xpath_handler,
250
+ rb_intern((const char *)method_name),
251
+ argc,
252
+ argv
253
+ );
215
254
 
216
- for (int j = 0 ; j < nargs ; ++j) {
255
+ for (int j = 0 ; j < argc ; ++j) {
217
256
  rb_gc_unregister_address(&argv[j]);
218
257
  }
219
- free(argv);
258
+ ruby_xfree(argv);
220
259
 
221
- switch (TYPE(result)) {
260
+ switch (TYPE(rb_retval)) {
222
261
  case T_FLOAT:
223
262
  case T_BIGNUM:
224
263
  case T_FIXNUM:
225
- xmlXPathReturnNumber(ctx, NUM2DBL(result));
264
+ xmlXPathReturnNumber(ctxt, NUM2DBL(rb_retval));
226
265
  break;
227
266
  case T_STRING:
228
- xmlXPathReturnString(
229
- ctx,
230
- xmlCharStrdup(StringValueCStr(result))
231
- );
267
+ xmlXPathReturnString(ctxt, xmlCharStrdup(StringValueCStr(rb_retval)));
232
268
  break;
233
269
  case T_TRUE:
234
- xmlXPathReturnTrue(ctx);
270
+ xmlXPathReturnTrue(ctxt);
235
271
  break;
236
272
  case T_FALSE:
237
- xmlXPathReturnFalse(ctx);
273
+ xmlXPathReturnFalse(ctxt);
238
274
  break;
239
275
  case T_NIL:
240
276
  break;
241
277
  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));
278
+ VALUE construct_args[2] = { DOC_RUBY_OBJECT(ctxt->context->doc), rb_retval };
279
+ rb_node_set = rb_class_new_instance(2, construct_args, cNokogiriXmlNodeSet);
280
+ c_node_set = noko_xml_node_set_unwrap(rb_node_set);
281
+ xmlXPathReturnNodeSet(ctxt, xmlXPathNodeSetMerge(NULL, c_node_set));
248
282
  }
249
283
  break;
250
284
  case T_DATA:
251
- if (rb_obj_is_kind_of(result, cNokogiriXmlNodeSet)) {
252
- Data_Get_Struct(result, xmlNodeSet, xml_node_set);
285
+ if (rb_obj_is_kind_of(rb_retval, cNokogiriXmlNodeSet)) {
286
+ c_node_set = noko_xml_node_set_unwrap(rb_retval);
253
287
  /* Copy the node set, otherwise it will get GC'd. */
254
- xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, xml_node_set));
288
+ xmlXPathReturnNodeSet(ctxt, xmlXPathNodeSetMerge(NULL, c_node_set));
255
289
  break;
256
290
  }
257
291
  default:
@@ -260,65 +294,95 @@ Nokogiri_marshal_xpath_funcall_and_return_values(xmlXPathParserContextPtr ctx, i
260
294
  }
261
295
 
262
296
  static void
263
- ruby_funcall(xmlXPathParserContextPtr ctx, int nargs)
297
+ method_caller(xmlXPathParserContextPtr ctxt, int argc)
264
298
  {
265
- VALUE handler = Qnil;
266
- const char *function = NULL ;
267
-
268
- assert(ctx);
269
- assert(ctx->context);
270
- assert(ctx->context->userData);
271
- assert(ctx->context->function);
272
-
273
- handler = (VALUE)(ctx->context->userData);
274
- function = (const char *)(ctx->context->function);
275
-
276
- Nokogiri_marshal_xpath_funcall_and_return_values(ctx, nargs, handler, function);
299
+ VALUE rb_xpath_handler = Qnil;
300
+ const char *method_name = NULL ;
301
+
302
+ assert(ctxt);
303
+ assert(ctxt->context);
304
+ assert(ctxt->context->userData);
305
+ assert(ctxt->context->function);
306
+
307
+ rb_xpath_handler = (VALUE)(ctxt->context->userData);
308
+ method_name = (const char *)(ctxt->context->function);
309
+
310
+ Nokogiri_marshal_xpath_funcall_and_return_values(
311
+ ctxt,
312
+ argc,
313
+ rb_xpath_handler,
314
+ method_name
315
+ );
277
316
  }
278
317
 
279
318
  static xmlXPathFunction
280
- lookup(void *ctx,
281
- const xmlChar *name,
282
- const xmlChar *ns_uri)
319
+ handler_lookup(void *data, const xmlChar *c_name, const xmlChar *c_ns_uri)
283
320
  {
284
- VALUE xpath_handler = (VALUE)ctx;
285
- if (rb_respond_to(xpath_handler, rb_intern((const char *)name))) {
286
- return ruby_funcall;
321
+ VALUE rb_handler = (VALUE)data;
322
+ if (rb_respond_to(rb_handler, rb_intern((const char *)c_name))) {
323
+ if (c_ns_uri == NULL) {
324
+ NOKO_WARN_DEPRECATION(
325
+ "A custom XPath or CSS handler function named '%s' is being invoked without a namespace."
326
+ " Please update your query to reference this function as 'nokogiri:%s'."
327
+ " Invoking custom handler functions without a namespace is deprecated and support will be removed in a future release of Nokogiri.",
328
+ c_name, c_name);
329
+ }
330
+ return method_caller;
287
331
  }
288
332
 
289
333
  return NULL;
290
334
  }
291
335
 
292
- NORETURN(static void xpath_generic_exception_handler(void *ctx, const char *msg, ...));
336
+ PRINTFLIKE_DECL(2, 3)
293
337
  static void
294
- xpath_generic_exception_handler(void *ctx, const char *msg, ...)
338
+ generic_exception_pusher(void *data, const char *msg, ...)
295
339
  {
296
- char *message;
340
+ VALUE rb_errors = (VALUE)data;
341
+ VALUE rb_message;
342
+ VALUE rb_exception;
297
343
 
344
+ Check_Type(rb_errors, T_ARRAY);
345
+
346
+ #ifdef TRUFFLERUBY_NOKOGIRI_SYSTEM_LIBRARIES
347
+ /* It is not currently possible to pass var args from native
348
+ functions to sulong, so we work around the issue here. */
349
+ rb_message = rb_sprintf("generic_exception_pusher: %s", msg);
350
+ #else
298
351
  va_list args;
299
352
  va_start(args, msg);
300
- vasprintf(&message, msg, args);
353
+ rb_message = rb_vsprintf(msg, args);
301
354
  va_end(args);
355
+ #endif
302
356
 
303
- rb_raise(rb_eRuntimeError, "%s", message);
357
+ rb_exception = rb_exc_new_str(cNokogiriXmlXpathSyntaxError, rb_message);
358
+ rb_ary_push(rb_errors, rb_exception);
304
359
  }
305
360
 
306
361
  /*
307
362
  * call-seq:
308
- * evaluate(search_path, handler = nil)
363
+ * evaluate(search_path, handler = nil) → Object
364
+ *
365
+ * Evaluate the +search_path+ query.
309
366
  *
310
- * Evaluate the +search_path+ returning an XML::XPath object.
367
+ * [Returns] an object of the appropriate type for the query, which could be +NodeSet+, a +String+,
368
+ * a +Float+, or a boolean.
311
369
  */
312
370
  static VALUE
313
- evaluate(int argc, VALUE *argv, VALUE self)
371
+ rb_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE rb_context)
314
372
  {
315
373
  VALUE search_path, xpath_handler;
316
374
  VALUE retval = Qnil;
317
- xmlXPathContextPtr ctx;
375
+ xmlXPathContextPtr c_context;
318
376
  xmlXPathObjectPtr xpath;
319
377
  xmlChar *query;
378
+ VALUE errors = rb_ary_new();
320
379
 
321
- Data_Get_Struct(self, xmlXPathContext, ctx);
380
+ TypedData_Get_Struct(
381
+ rb_context,
382
+ xmlXPathContext,
383
+ &xml_xpath_context_type,
384
+ c_context
385
+ );
322
386
 
323
387
  if (rb_scan_args(argc, argv, "11", &search_path, &xpath_handler) == 1) {
324
388
  xpath_handler = Qnil;
@@ -328,29 +392,29 @@ evaluate(int argc, VALUE *argv, VALUE self)
328
392
 
329
393
  if (Qnil != xpath_handler) {
330
394
  /* FIXME: not sure if this is the correct place to shove private data. */
331
- ctx->userData = (void *)xpath_handler;
332
- xmlXPathRegisterFuncLookup(ctx, lookup, (void *)xpath_handler);
395
+ c_context->userData = (void *)xpath_handler;
396
+ xmlXPathRegisterFuncLookup(
397
+ c_context,
398
+ handler_lookup,
399
+ (void *)xpath_handler
400
+ );
333
401
  }
334
402
 
335
- xmlResetLastError();
336
- xmlSetStructuredErrorFunc(NULL, Nokogiri_error_raise);
403
+ xmlSetStructuredErrorFunc((void *)errors, Nokogiri_error_array_pusher);
404
+ xmlSetGenericErrorFunc((void *)errors, generic_exception_pusher);
337
405
 
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);
406
+ xpath = xmlXPathEvalExpression(query, c_context);
341
407
 
342
- xpath = xmlXPathEvalExpression(query, ctx);
343
408
  xmlSetStructuredErrorFunc(NULL, NULL);
344
409
  xmlSetGenericErrorFunc(NULL, NULL);
345
410
 
346
411
  if (xpath == NULL) {
347
- xmlErrorPtr error = xmlGetLastError();
348
- rb_exc_raise(Nokogiri_wrap_xml_syntax_error(error));
412
+ rb_exc_raise(rb_ary_entry(errors, 0));
349
413
  }
350
414
 
351
- retval = xpath2ruby(xpath, ctx);
415
+ retval = xpath2ruby(xpath, c_context);
352
416
  if (retval == Qundef) {
353
- retval = noko_xml_node_set_wrap(NULL, DOC_RUBY_OBJECT(ctx->doc));
417
+ retval = noko_xml_node_set_wrap(NULL, DOC_RUBY_OBJECT(c_context->doc));
354
418
  }
355
419
 
356
420
  xmlXPathFreeNodeSetList(xpath);
@@ -360,47 +424,63 @@ evaluate(int argc, VALUE *argv, VALUE self)
360
424
 
361
425
  /*
362
426
  * call-seq:
363
- * new(node)
427
+ * new(node)
364
428
  *
365
- * Create a new XPathContext with +node+ as the reference point.
429
+ * Create a new XPathContext with +node+ as the context node.
366
430
  */
367
431
  static VALUE
368
- new (VALUE klass, VALUE nodeobj)
432
+ rb_xml_xpath_context_new(VALUE klass, VALUE rb_node)
369
433
  {
370
434
  xmlNodePtr node;
371
- xmlXPathContextPtr ctx;
372
- VALUE self;
435
+ xmlXPathContextPtr c_context;
436
+ VALUE rb_context;
373
437
 
374
- Noko_Node_Get_Struct(nodeobj, xmlNode, node);
438
+ Noko_Node_Get_Struct(rb_node, xmlNode, node);
375
439
 
440
+ #if LIBXML_VERSION < 21000
441
+ /* deprecated in 40483d0 */
376
442
  xmlXPathInit();
377
-
378
- ctx = xmlXPathNewContext(node->doc);
379
- ctx->node = node;
380
-
381
- xmlXPathRegisterNs(ctx, NOKOGIRI_BUILTIN_PREFIX, NOKOGIRI_BUILTIN_URI);
382
- xmlXPathRegisterFuncNS(ctx, (const xmlChar *)"css-class", NOKOGIRI_BUILTIN_URI,
383
- xpath_builtin_css_class);
384
- xmlXPathRegisterFuncNS(ctx, (const xmlChar *)"local-name-is", NOKOGIRI_BUILTIN_URI,
385
- xpath_builtin_local_name_is);
386
-
387
- self = Data_Wrap_Struct(klass, 0, deallocate, ctx);
388
- return self;
443
+ #endif
444
+
445
+ c_context = xmlXPathNewContext(node->doc);
446
+ c_context->node = node;
447
+
448
+ xmlXPathRegisterNs(c_context, NOKOGIRI_PREFIX, NOKOGIRI_URI);
449
+ xmlXPathRegisterNs(c_context, NOKOGIRI_BUILTIN_PREFIX, NOKOGIRI_BUILTIN_URI);
450
+ xmlXPathRegisterFuncNS(
451
+ c_context,
452
+ (const xmlChar *)"css-class",
453
+ NOKOGIRI_BUILTIN_URI,
454
+ xpath_builtin_css_class
455
+ );
456
+ xmlXPathRegisterFuncNS(
457
+ c_context,
458
+ (const xmlChar *)"local-name-is",
459
+ NOKOGIRI_BUILTIN_URI,
460
+ xpath_builtin_local_name_is
461
+ );
462
+
463
+ rb_context = TypedData_Wrap_Struct(
464
+ klass,
465
+ &xml_xpath_context_type,
466
+ c_context
467
+ );
468
+ return rb_context;
389
469
  }
390
470
 
391
471
  void
392
472
  noko_init_xml_xpath_context(void)
393
473
  {
394
474
  /*
395
- * XPathContext is the entry point for searching a Document by using XPath.
475
+ * XPathContext is the entry point for searching a +Document+ by using XPath.
396
476
  */
397
477
  cNokogiriXmlXpathContext = rb_define_class_under(mNokogiriXml, "XPathContext", rb_cObject);
398
478
 
399
479
  rb_undef_alloc_func(cNokogiriXmlXpathContext);
400
480
 
401
- rb_define_singleton_method(cNokogiriXmlXpathContext, "new", new, 1);
481
+ rb_define_singleton_method(cNokogiriXmlXpathContext, "new", rb_xml_xpath_context_new, 1);
402
482
 
403
- rb_define_method(cNokogiriXmlXpathContext, "evaluate", evaluate, -1);
404
- rb_define_method(cNokogiriXmlXpathContext, "register_variable", register_variable, 2);
405
- rb_define_method(cNokogiriXmlXpathContext, "register_ns", register_ns, 2);
483
+ rb_define_method(cNokogiriXmlXpathContext, "evaluate", rb_xml_xpath_context_evaluate, -1);
484
+ rb_define_method(cNokogiriXmlXpathContext, "register_variable", rb_xml_xpath_context_register_variable, 2);
485
+ rb_define_method(cNokogiriXmlXpathContext, "register_ns", rb_xml_xpath_context_register_ns, 2);
406
486
  }