moxml 0.5.173 → 0.5.175

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: be4403ff94123c6d65bf53402d99fee7462bd4d3e9c3ae34f87ff43170fddc29
4
- data.tar.gz: 642a836819599fc943103d87d0148cf34e40544d94cf376b4d2d74e5d65bc25e
3
+ metadata.gz: 14463613d8081db0efee985379ddcae7740f8044d9f0f7a8192f5f1828337a27
4
+ data.tar.gz: 7fcb65b5d65fedc5d9766d31f409441eafba5f78b8212478a854bcd17ffdf167
5
5
  SHA512:
6
- metadata.gz: 0ac3bb7ae1148c02ed3c9812c448c8a20e521854f201c20ef22a22dbbc4cd9c12f01d0d1ea4d19f29d4f35f6781d83ace0d4db88957877a8758a621c4b720ecb
7
- data.tar.gz: 2513f3da33f3b1836276b51428e9db7e814416db761bcaa3813bf0fd326851359e5a3cc6bb2e62401f0bbbf0aaa44b44dc7992dbb58a4bc475849cc659dd720d
6
+ metadata.gz: b7c402c813be0883260893a9e47290653e61104cf870702d7d46b155299d87752f8ec5662455ebb0b75c4b776d8962502d7ed223a3b5fca0764fb2600ae67488
7
+ data.tar.gz: cc0a50d550e12d1496c0f31a623c9e1c3a7569fe1d65b7796b97a1a30d63d994812d02c28cd6cfcfd22352a11d0fc9ed25d4a2488bda768ac0898342dad7837a
data/Gemfile CHANGED
@@ -9,7 +9,7 @@ gemspec
9
9
  gem "benchmark"
10
10
  gem "benchmark-ips"
11
11
  gem "get_process_mem"
12
- gem "leptris", "~> 1.9.382"
12
+ gem "leptris", "~> 1.9.386"
13
13
  gem "libxml-ruby", ">= 5.0"
14
14
  gem "nokogiri", "~> 1.18"
15
15
  gem "openssl", "~> 3.0"
data/README.adoc CHANGED
@@ -72,7 +72,7 @@ https://github.com/leptris/leptris-ruby[leptris-ruby] FFI binding
72
72
  every measured bulk operation — parse, XPath, serialization, SAX, and
73
73
  the compiled Moxml::Plan / Moxml::StructPlan materialization paths
74
74
  (StructPlan runs 2.3-2.6x raw Nokogiri on the benchmark shape);
75
- requires leptris >= 1.9.32 (see version table below).
75
+ requires leptris >= 1.9.386.0 (see version table below).
76
76
 
77
77
  === Underlying library versions
78
78
 
@@ -111,32 +111,18 @@ same libxml2 engine, governed by the consistency suite). Removal
111
111
  after the deprecation cycle.
112
112
 
113
113
  |Leptris (leptris-ruby)
114
- |>= 1.9.194.1
115
- |Hard floor — `MINIMUM_BINDING_VERSION`; older bindings do not load.
116
- Raised from 1.9.32 (2026-09-20): every known consumer resolves a
117
- modern binding, and the sub-1.9.194 accommodation paths are deleted.
118
- Newer bindings unlock more native surface automatically:
119
- 1.9.194.1+ hot-read aliases, 1.9.201.1+ the C struct
120
- executor (`Moxml::StructPlan`; the floor is the varargs-mint fix),
121
- 1.9.204+ native document-level parts (created DOCTYPEs as native
122
- nodes, document-PI removal, declaration clear), 1.9.240+ the bulk
123
- SAX record drain (`Handler#on_sax_records`) — and 1.9.242+ is
124
- REQUIRED for that drain to be CORRECT: 1.9.240/241 drain documents
125
- containing duplicate attributes without surfacing the fatal error
126
- (moxml#281), so the drain arms only on 1.9.242+, where such
127
- documents fall back to the callback path and the error fires.
128
- 1.9.255.2+ C-minted walk/build wrappers (construction identity
129
- without the Ruby mint); 1.9.273.1+ opt-in parse-skip flags
130
- (`skip_dup_detection`, `skip_source_positions`); 1.9.290.0+ XSLT
131
- top-level params threading and the bulk child-list append
132
- (one crossing for N children); 1.9.292.0+ native cross-document
133
- root adoption (the engine deep-copies a foreign root in C).
134
- Current recommendation: 1.9.292+ (the native-adoption train;
135
- carries the plan-ABI surface, the 1.9.290 XSLT-params and
136
- bulk-append faces, and the 1.9.292 engine deep-copy root install).
114
+ |>= 1.9.386.0
115
+ |ENFORCED hard floor — `MINIMUM_BINDING_VERSION`; the adapter refuses
116
+ to load below it. Raised 1.9.32 → 1.9.194.1 (2026-09-20) → 1.9.386.0
117
+ (2026-10-30, the tested pair): every accommodation path below it is
118
+ deleted and all native faces through the 1.9.385 parent-axis train
119
+ are unconditional. The capability report
120
+ (`Moxml::Adapter::Leptris.capabilities`) answers what the installed
121
+ pair serves; cross-import schema sets (`Context#xsd_set`) ride the
122
+ compile_set face (1.9.386.0 ✓).
137
123
  |===
138
124
 
139
- NOTE: moxml's dev Gemfile pins `leptris ~> 1.9.321` (the tested pair; the gemspec itself has zero runtime dependencies). Consumers of the leptris adapter should run leptris 1.9.320+ — earlier engines carry silent wrong-answer plan-path defects (moxml#344); moxml gates degrade to the always-correct slower paths below it.
125
+ NOTE: moxml's dev Gemfile pins `leptris ~> 1.9.386` (the tested pair; the gemspec itself has zero runtime dependencies). The adapter enforces the floor at load.
140
126
  `ox ~> 2.14`, `libxml-ruby >= 5.0`, and the vendored oga fork — the CI
141
127
  matrix tests exactly those floors.
142
128
 
@@ -147,7 +133,7 @@ the runtime environment:
147
133
 
148
134
  . If running on Opal (`RUBY_ENGINE == "opal"`), Oga is used (pure Ruby, no C extensions)
149
135
  . Otherwise, if the installed leptris gem supports programmatic document
150
- construction (`Leptris::XML::Document.create`, leptris >= 1.9.32), Leptris is used
136
+ construction (`Leptris::XML::Document.create`, leptris >= 1.9.386.0), Leptris is used
151
137
  . Otherwise, Moxml detects already-loaded XML libraries in this order:
152
138
  .. Nokogiri
153
139
  .. Ox
@@ -158,7 +144,7 @@ the runtime environment:
158
144
  ----
159
145
  # Automatic detection — picks the best available adapter
160
146
  ctx = Moxml.new
161
- ctx.config.adapter_name # => :leptris (leptris >= 1.9.32), :nokogiri otherwise, :oga on Opal
147
+ ctx.config.adapter_name # => :leptris (leptris >= 1.9.386.0), :nokogiri otherwise, :oga on Opal
162
148
 
163
149
  # Explicit override — always takes precedence
164
150
  ctx = Moxml.new(:ox)
@@ -29,7 +29,22 @@ module Moxml
29
29
  # Raised 1.9.32 -> 1.9.194.1 (2026-09-20): every known consumer
30
30
  # resolves a modern binding (canon itself pins ~> 1.9.193), and
31
31
  # the sub-1.9.194 accommodation paths are deleted.
32
- MINIMUM_BINDING_VERSION = "1.9.194.1"
32
+ # Raised 1.9.194.1 -> 1.9.386.0 (2026-10-30, owner directive
33
+ # "raise all floors"): the tested pair — every gate below it
34
+ # unwound, and the floor is ENFORCED (the load refuses below it;
35
+ # the README's "older bindings do not load" claim is now true).
36
+ MINIMUM_BINDING_VERSION = "1.9.386.0"
37
+
38
+ if Gem::Version.new(::Leptris::VERSION.to_s) <
39
+ Gem::Version.new(MINIMUM_BINDING_VERSION)
40
+ raise Moxml::AdapterError.new(
41
+ "the leptris binding is #{::Leptris::VERSION}; moxml requires " \
42
+ ">= #{MINIMUM_BINDING_VERSION} (the tested floor — older " \
43
+ "bindings are untested and their accommodation paths are deleted)",
44
+ adapter: :leptris,
45
+ operation: "load",
46
+ )
47
+ end
33
48
 
34
49
  # leptris_parse_html_string shipped in bindings 1.9.80
35
50
  # (libleptris 1.9.75, engine #659) as Leptris::XML.parse_html.
@@ -193,8 +208,7 @@ module Moxml
193
208
  # so the gate names the first release where the drain is
194
209
  # CORRECT, not merely present. Dev floor pins ~> 1.9.238;
195
210
  # older bindings take the callback Parser below.
196
- NATIVE_SAX_RECORDS =
197
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.242")
211
+ NATIVE_SAX_RECORDS = true
198
212
 
199
213
  # Document#absorb (engine #1548): one call transfers a source
200
214
  # document's pool ownership into the destination, so
@@ -208,8 +222,7 @@ module Moxml
208
222
  # lesson).
209
223
  NATIVE_DOC_ABSORB =
210
224
  defined?(::Leptris::XML::Document) &&
211
- ::Leptris::XML::Document.method_defined?(:absorb) &&
212
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.311.3")
225
+ ::Leptris::XML::Document.method_defined?(:absorb)
213
226
 
214
227
  # Document#to_html indent kwargs (issue #354, engine
215
228
  # leptris#1637 via leptris-ruby#421): the nested HTML layout
@@ -218,7 +231,6 @@ module Moxml
218
231
  # to_html takes no kwargs and would raise ArgumentError from
219
232
  # the pass-through.
220
233
  HTML_SERIALIZE_INDENT =
221
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.338.0") &&
222
234
  defined?(::Leptris::XML::Document) &&
223
235
  ::Leptris::XML::Document.method_defined?(:to_html) &&
224
236
  ::Leptris::XML::Document.instance_method(:to_html)
@@ -240,7 +252,6 @@ module Moxml
240
252
  # the rescue-to-empty fallback. The kwarg probe pairs the
241
253
  # floor (a binding without the kwarg cannot arm).
242
254
  RECOVER_MODE =
243
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.344.0") &&
244
255
  ::Leptris::XML::ParseOptions.instance_method(:initialize)
245
256
  .parameters.any? { |_, key| key == :recover }
246
257
 
@@ -250,7 +261,6 @@ module Moxml
250
261
  # per-attribute reads behind ::Leptris::XML::Element
251
262
  # #attribute_pairs.
252
263
  ELEMENT_ATTR_SNAPSHOT =
253
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.353.0") &&
254
264
  ::Leptris::XML::Element.method_defined?(:attributes_snapshot)
255
265
 
256
266
  # Markup-accumulating builder face (leptris-ruby#374 lever 2,
@@ -263,7 +273,6 @@ module Moxml
263
273
  # pairs the gate (misrelease races — NATIVE_PLAN_STRUCTS
264
274
  # lesson).
265
275
  NATIVE_XSD =
266
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.321.0") &&
267
276
  defined?(::Leptris::XML::XSD) &&
268
277
  ::Leptris::XML::FFI.respond_to?(:leptris_xsd_validate)
269
278
 
@@ -284,15 +293,13 @@ module Moxml
284
293
  # finalizer and frees now. Face-probed with the version
285
294
  # floor (the NATIVE_DOC_ABSORB pairing).
286
295
  XSD_RELEASE =
287
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.342.0") &&
288
296
  defined?(::Leptris::XML::XSD::Schema) &&
289
297
  ::Leptris::XML::XSD::Schema.method_defined?(:release)
290
298
 
291
299
  NATIVE_BUILDER =
292
300
  defined?(::Leptris::XML::Builder) &&
293
301
  defined?(::Leptris::XML::Document) &&
294
- ::Leptris::XML::Document.method_defined?(:build) &&
295
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.313.0")
302
+ ::Leptris::XML::Document.method_defined?(:build)
296
303
 
297
304
  # XSLT 1.0/2.0/3.0 through the engine's compiled-stylesheet
298
305
  # faces (Moxml::XSLT contract). Top-level parameters are not
@@ -328,9 +335,18 @@ module Moxml
328
335
  # consumers ask for them by name; the internal routing gates
329
336
  # the floor made constant are absent by design. Frozen; the
330
337
  # keys are the model's capability names.
338
+ #
339
+ # Two versions, never conflated (the binding vendors the
340
+ # engine; the numbers differ): +binding_version+ is the gem's
341
+ # (Leptris::VERSION), +engine_version+ is libleptris's own
342
+ # (the leptris_version() C face, face-probed — nil on a
343
+ # binding without it).
331
344
  def capabilities
332
345
  @capabilities ||= {
333
- engine_version: ::Leptris::VERSION,
346
+ binding_version: ::Leptris::VERSION,
347
+ engine_version:
348
+ (::Leptris::XML::FFI.leptris_version if
349
+ ::Leptris::XML::FFI.respond_to?(:leptris_version)),
334
350
  native_read_layer: !NATIVE_READ_LAYER.nil?,
335
351
  native_xpath_seams: !NATIVE_XPATH_SEAMS.nil?,
336
352
  bulk_xpath_rows: BULK_XPATH_ROWS,
@@ -339,9 +355,6 @@ module Moxml
339
355
  native_mutations_coherent: !NATIVE_MUTATIONS_COHERENT.nil?,
340
356
  native_entity_refs: !NATIVE_ENTITY_REFS.nil?,
341
357
  native_bulk_fixed: !NATIVE_BULK_FIXED.nil?,
342
- native_bulk_sax_records: NATIVE_SAX_RECORDS,
343
- native_document_parts: NATIVE_DOC_PARTS,
344
- native_plan_rows: NATIVE_PLAN_ROWS,
345
358
  native_plan_structs: NATIVE_PLAN_STRUCTS,
346
359
  native_plan_typed: NATIVE_PLAN_TYPED,
347
360
  digest: DIGEST_SUPPORTED,
@@ -577,9 +590,7 @@ module Moxml
577
590
  # there.
578
591
  NATIVE_IDENTITY = NATIVE_MUTATIONS_COHERENT
579
592
 
580
- NATIVE_C_MINT =
581
- NATIVE_IDENTITY &&
582
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.255.2")
593
+ NATIVE_C_MINT = NATIVE_IDENTITY
583
594
 
584
595
  NATIVE_KLASS_CHILDREN = NATIVE_IDENTITY
585
596
  end
@@ -1038,7 +1049,6 @@ module Moxml
1038
1049
  # of NoMethodError-ing — the 1.9.199.0 lesson).
1039
1050
  NATIVE_XSLT_PARAMS =
1040
1051
  NATIVE_READ_LAYER &&
1041
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.290.0") &&
1042
1052
  ::Leptris::XML::XSLT::Stylesheet.instance_method(:apply_to)
1043
1053
  .parameters.size > 1
1044
1054
 
@@ -1208,8 +1218,7 @@ module Moxml
1208
1218
  # SILENT wrong answers, so the gate names the fixed engine:
1209
1219
  # below 1.9.320.0 the plan faces degrade to the
1210
1220
  # always-correct generic wrapper walk.
1211
- NATIVE_PLAN_ROWS =
1212
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.320.0")
1221
+ NATIVE_PLAN_ROWS = true
1213
1222
 
1214
1223
  # leptris-ruby#272 (binding 1.9.201.1): Native.plan_structs —
1215
1224
  # the C struct executor behind Moxml::StructPlan. The floor
@@ -1224,9 +1233,8 @@ module Moxml
1224
1233
  # captures) — the struct executor degrades to the Ruby Plan
1225
1234
  # fallback below the fix, same as the varargs-mint floor.
1226
1235
  NATIVE_PLAN_STRUCTS =
1227
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.320.0") &&
1228
- (!defined?(::Leptris::XML::Native) ||
1229
- ::Leptris::XML::Native.respond_to?(:plan_structs))
1236
+ !defined?(::Leptris::XML::Native) ||
1237
+ ::Leptris::XML::Native.respond_to?(:plan_structs)
1230
1238
 
1231
1239
  # leptris-ruby#275 (binding 1.9.204, the remove half of the
1232
1240
  # document-level surfaces): remove_pi, clear_declaration,
@@ -1242,7 +1250,6 @@ module Moxml
1242
1250
  ::Leptris::XML::Native.respond_to?(:plan_structs_typed?)
1243
1251
 
1244
1252
  NATIVE_DOC_PARTS =
1245
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.204.0") &&
1246
1253
  ::Leptris::XML::Document.method_defined?(:remove_doctype) &&
1247
1254
  ::Leptris::XML::Document.method_defined?(:clear_declaration)
1248
1255
 
@@ -2290,9 +2297,7 @@ module Moxml
2290
2297
  end
2291
2298
  end
2292
2299
 
2293
- NATIVE_ROOT_ADOPT =
2294
- NATIVE_READ_LAYER &&
2295
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.292.0")
2300
+ NATIVE_ROOT_ADOPT = NATIVE_READ_LAYER
2296
2301
 
2297
2302
  # The engine deep-copies the foreign subtree into the target
2298
2303
  # document's pool (leptris#1495) and the binding memoizes the
@@ -3437,9 +3442,7 @@ module Moxml
3437
3442
  end
3438
3443
  end
3439
3444
 
3440
- NATIVE_APPEND_CHILDREN =
3441
- NATIVE_READ_LAYER &&
3442
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.290.0")
3445
+ NATIVE_APPEND_CHILDREN = NATIVE_READ_LAYER
3443
3446
 
3444
3447
  def replace_children(node, new_children)
3445
3448
  # Cross-pool children: the binding's bulk face adopts per
@@ -3893,8 +3896,7 @@ module Moxml
3893
3896
  # (parent-of-attribute names the OWNER element) plus the
3894
3897
  # cross-doc adopt attribute-chain fix, and standoc's svg
3895
3898
  # id cleanup rides `./@id/..` hot (moxml#474).
3896
- PARENT_AXIS_NATIVE =
3897
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.385")
3899
+ PARENT_AXIS_NATIVE = true
3898
3900
  NON_PARENT_REVERSE_AXES = %w[ancestor ancestor-or-self
3899
3901
  preceding preceding-sibling].freeze
3900
3902
  REVERSE_AXIS_CACHE = XPath::Cache.new(200)
data/lib/moxml/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Moxml
4
- VERSION = "0.5.173"
4
+ VERSION = "0.5.175"
5
5
  end
@@ -93,11 +93,11 @@ RSpec.describe Moxml::Adapter do
93
93
  end
94
94
  end
95
95
 
96
- it "pins the leptris binding floor at 1.9.194.1 (issue #149; raised 2026-09-20)" do
96
+ it "pins the leptris binding floor at 1.9.386.0 (raised 2026-09-20, raised again 2026-10-30; enforced at load)" do
97
97
  skip "leptris not installed" unless described_class.available?(:leptris)
98
98
 
99
99
  adapter = described_class.load(:leptris)
100
- expect(adapter::MINIMUM_BINDING_VERSION).to eq("1.9.194.1")
100
+ expect(adapter::MINIMUM_BINDING_VERSION).to eq("1.9.386.0")
101
101
  expect(Gem::Version.new(Leptris::VERSION))
102
102
  .to be >= Gem::Version.new(adapter::MINIMUM_BINDING_VERSION)
103
103
  end
@@ -8,21 +8,35 @@ require "spec_helper"
8
8
  # what the installed binding+engine serves — queried once at attach,
9
9
  # the replacement for the version-gate-constant class. Only
10
10
  # runtime-variable faces appear; anything the floor makes
11
- # unconditional is absent by design.
11
+ # unconditional is absent by design. The two versions are never
12
+ # conflated: the binding vendors the engine, and the numbers differ.
12
13
  RSpec.describe "engine capability report" do
13
- it "answers for leptris with the engine version and known faces" do
14
+ it "answers for leptris with both versions and known faces" do
14
15
  caps = Moxml::Adapter::Leptris.capabilities
15
16
  expect(caps).to be_frozen
17
+ expect(caps[:binding_version]).to eq(Leptris::VERSION)
16
18
  expect(caps[:engine_version]).to match(/\A1\.\d+\.\d+/)
17
19
  expect(caps.keys).to include(
18
- :native_read_layer, :native_plan_structs, :native_bulk_sax_records,
19
- :native_document_parts, :xsd, :relaxng, :xslt, :digest
20
+ :native_read_layer, :native_plan_structs, :native_plan_typed,
21
+ :xsd, :relaxng, :xslt, :digest
20
22
  )
21
23
  end
22
24
 
23
- it "reports only booleans beyond the version" do
25
+ it "answers the ENGINE's version under engine_version, not the binding's" do
24
26
  caps = Moxml::Adapter::Leptris.capabilities
25
- caps.except(:engine_version).each_value do |value|
27
+ engine = Leptris::XML::FFI.leptris_version
28
+ expect(caps[:engine_version]).to eq(engine)
29
+ if Gem::Version.new(Leptris::VERSION) != Gem::Version.new(engine)
30
+ expect(caps[:binding_version]).not_to eq(caps[:engine_version]),
31
+ "binding and engine versions are " \
32
+ "different numbers; the report must " \
33
+ "never conflate them"
34
+ end
35
+ end
36
+
37
+ it "reports only booleans beyond the versions" do
38
+ caps = Moxml::Adapter::Leptris.capabilities
39
+ caps.except(:binding_version, :engine_version).each_value do |value|
26
40
  expect(value).to eql(true).or eql(false)
27
41
  end
28
42
  end
@@ -31,7 +45,8 @@ RSpec.describe "engine capability report" do
31
45
  caps = Moxml::Adapter::Leptris.capabilities
32
46
  expect(caps.keys).not_to include(
33
47
  :prefixed_attr_predicates_native, :libxml2_layout_parity,
34
- :indent_unit_supported, :element_unit_comments
48
+ :indent_unit_supported, :element_unit_comments,
49
+ :native_bulk_sax_records, :native_document_parts, :native_plan_rows
35
50
  )
36
51
  expect(caps[:xsd]).to be(true)
37
52
  expect(caps[:xslt]).to be(true)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moxml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.173
4
+ version: 0.5.175
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.