leptris 1.9.38-aarch64-linux → 1.9.40-aarch64-linux
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 +4 -4
- data/CHANGELOG.md +50 -0
- data/Rakefile +12 -2
- data/lib/leptris/version.rb +1 -1
- data/lib/leptris/xml/document_fragment.rb +3 -2
- data/lib/leptris/xml/ffi.rb +60 -4
- data/lib/leptris/xml/node.rb +6 -3
- data/lib/leptris/xml/sax/dom_dispatch.rb +14 -3
- data/lib/leptris/xml/sax/parser.rb +8 -8
- data/lib/libleptris.so +0 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1753f68ffbc65299a2742ad1645a74e8feb3c054cf25a44ab01b8571aaa78e1f
|
|
4
|
+
data.tar.gz: 9a4076ab46da988a84261485317b153f33220878851bc95e586aaebc9df2a524
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3ff2d04232695b730e659859a68d974c9d4f52fc87e7b41b0ba2290d8e0e99a04d62933cacd060b53c086f38497ed2224680e5cd224751fdef48d3ef9f90d0b6
|
|
7
|
+
data.tar.gz: 53112f18a2ba2ce418433d4bdb18bb435f60a701be8d02d44736e0da9ef956aa2965c594a533bec5f72bbd09fef4dc393722afa4454067c5b97829716ae01066
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,56 @@ All notable changes to Leptris will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.9.40] - 2026-08-30
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **SAX delivers through the engine transports again** — the #95
|
|
13
|
+
attribute corruption is fixed upstream (libleptris 1.9.18,
|
|
14
|
+
verified on the issue fixture through both engine transports:
|
|
15
|
+
all 7 image attributes intact). `SAX::Parser` defaults to
|
|
16
|
+
`streaming: true`; `streaming: false` keeps the DOM-backed
|
|
17
|
+
dispatcher as a fallback for older engines. The correctness tax
|
|
18
|
+
is gone: all-events 119 ms and text-only 21.6 ms per big.xml
|
|
19
|
+
parse vs Nokogiri's 131/130 ms — SAX wins every shape outright
|
|
20
|
+
again, with correct data.
|
|
21
|
+
- **libleptris 1.9.14–1.9.18 lockstep** (audit 253/253, three new
|
|
22
|
+
symbols): fixes for everything we were tracking upstream —
|
|
23
|
+
#625 (SAX attrs), #626 (MSVC non-ASCII names; the Windows spec
|
|
24
|
+
gate is removed), #627/#628/#630 (XSLT unknown fns and last();
|
|
25
|
+
relative namespaced descendant paths — spec added), #613
|
|
26
|
+
(latin-1), #608 (combined ns+vars eval; attached), #617
|
|
27
|
+
(node_children out_kinds; wired), #633 (pretty-print parity),
|
|
28
|
+
#635 (xmlns interleave; wired).
|
|
29
|
+
- **Children batches carry kinds** (`leptris_node_children_ex`):
|
|
30
|
+
`#children` and the fragment/dispatch walks wrap with the kind
|
|
31
|
+
hint — no per-child get_type dispatch. Measured: the cold
|
|
32
|
+
full-tree walk's remaining gap vs Nokogiri (1.5x) is the Ruby
|
|
33
|
+
wrapper allocation floor, not type dispatch; noted for the
|
|
34
|
+
record.
|
|
35
|
+
- **Exact xmlns interleave** (`leptris_element_attributes_raw`):
|
|
36
|
+
the DOM-backed fallback now reproduces the streaming contract's
|
|
37
|
+
byte-positioned declarations; the #99 spec is upgraded from
|
|
38
|
+
set-equality to exact order equality.
|
|
39
|
+
|
|
40
|
+
## [1.9.39] - 2026-08-29
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- **Namespace declarations return to SAX events (leptris-ruby#99,
|
|
45
|
+
critical)**: the DOM-backed dispatcher (1.9.36's #95 workaround)
|
|
46
|
+
built start_element pairs from the DOM attribute chain, which
|
|
47
|
+
excludes xmlns declarations — namespace-aware consumers went
|
|
48
|
+
blind (canon's namespace-declaration diffs came back empty). The
|
|
49
|
+
engine's streaming contract carries declarations among the
|
|
50
|
+
attribute pairs; the dispatcher now emits them first in
|
|
51
|
+
declaration order (default as `xmlns`, prefixed as
|
|
52
|
+
`xmlns:prefix`), then the attributes in source order with their
|
|
53
|
+
prefixed names preserved. The exact byte-level interleave of the
|
|
54
|
+
streaming path is unrecoverable from the DOM model and is the
|
|
55
|
+
one documented difference — a spec pins set-equality against
|
|
56
|
+
the engine transport per element.
|
|
57
|
+
|
|
8
58
|
## [1.9.38] - 2026-08-29
|
|
9
59
|
|
|
10
60
|
### Changed
|
data/Rakefile
CHANGED
|
@@ -8,7 +8,7 @@ RSpec::Core::RakeTask.new(:spec)
|
|
|
8
8
|
# Pin for `rake compile` and the platform-gem builds. Keep in lockstep
|
|
9
9
|
# with .github/workflows/build.yml (which calls `rake compile`) and the
|
|
10
10
|
# CHANGELOG when libleptris releases.
|
|
11
|
-
LIBLEPTRIS_VERSION = "1.9.
|
|
11
|
+
LIBLEPTRIS_VERSION = "1.9.18"
|
|
12
12
|
|
|
13
13
|
CMAKE_FLAGS = %w[
|
|
14
14
|
-DCMAKE_BUILD_TYPE=Release
|
|
@@ -30,7 +30,17 @@ task :compile do
|
|
|
30
30
|
mkdir_p(build)
|
|
31
31
|
url = "https://api.github.com/repos/leptris/leptris/tarball/v#{version}"
|
|
32
32
|
sh "curl -sL #{url} | tar xz -C #{build} --strip-components=1"
|
|
33
|
-
|
|
33
|
+
# libleptris 1.9.18's xslt_functions.c:270 assigns LeptrisElement
|
|
34
|
+
# to LeptrisNodeRef — GCC 14 (Alpine/musl) makes incompatible
|
|
35
|
+
# pointer types an error by default and the musl platform gems
|
|
36
|
+
# fail to build; clang toolchains only warn. Downgrade to warning
|
|
37
|
+
# until the upstream fix (leptris/leptris#640).
|
|
38
|
+
# No quoting: the flag carries no spaces, and single quotes are
|
|
39
|
+
# literal on Windows shells (they broke the MSVC build).
|
|
40
|
+
# GCC-family only — MSVC's cl rejects the flag outright (D8021).
|
|
41
|
+
cflags = Gem.win_platform? ? "" : "-Wno-error=incompatible-pointer-types"
|
|
42
|
+
sh "cmake -B #{build}/build -S #{build} " \
|
|
43
|
+
"#{CMAKE_FLAGS.join(' ')} #{cflags.empty? ? '' : "-DCMAKE_C_FLAGS=#{cflags}"}"
|
|
34
44
|
sh "cmake --build #{build}/build --config Release -j 4"
|
|
35
45
|
# Windows names the shared library leptris.dll (no "lib" prefix);
|
|
36
46
|
# vendoring under the uniform libleptris.* name keeps the FFI
|
data/lib/leptris/version.rb
CHANGED
|
@@ -25,8 +25,9 @@ class Leptris::XML::DocumentFragment
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def children
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
pointers, kinds = Leptris::XML::FFI.fetch_children(@c_ptr)
|
|
29
|
+
nodes = Array.new(pointers.size) do |i|
|
|
30
|
+
Leptris::XML::Node.wrap(pointers[i], @document, node_type: kinds[i])
|
|
30
31
|
end
|
|
31
32
|
Leptris::XML::NodeSet.new(@document, nodes)
|
|
32
33
|
end
|
data/lib/leptris/xml/ffi.rb
CHANGED
|
@@ -225,8 +225,17 @@ module Leptris
|
|
|
225
225
|
# count-only query returning the TOTAL across every child kind.
|
|
226
226
|
attach_function :leptris_node_children,
|
|
227
227
|
[:leptris_node_ref, :pointer, :size_t], :size_t
|
|
228
|
+
# Children with out_kinds (1.9.18, upstream #617): the kind
|
|
229
|
+
# rides the batch, so wrappers skip the per-child get_type.
|
|
230
|
+
attach_function :leptris_node_children_ex,
|
|
231
|
+
[:leptris_node_ref, :pointer, :pointer, :size_t], :size_t
|
|
228
232
|
# Element-only batch; mirror-only — fetch_children rides the
|
|
229
233
|
# all-kind node_children above.
|
|
234
|
+
# Raw qname-ordered attribute list INCLUDING xmlns
|
|
235
|
+
# declarations at their byte positions (1.9.18, upstream
|
|
236
|
+
# #635) — the streaming SAX contract's mixed view.
|
|
237
|
+
attach_function :leptris_element_attributes_raw,
|
|
238
|
+
[:leptris_element, :pointer, :pointer, :size_t], :size_t
|
|
230
239
|
attach_function :leptris_element_children,
|
|
231
240
|
[:leptris_element, :pointer, :size_t], :size_t
|
|
232
241
|
attach_function :leptris_node_as_element,
|
|
@@ -538,6 +547,11 @@ module Leptris
|
|
|
538
547
|
attach_function :leptris_xpath_compiled_eval_vars,
|
|
539
548
|
[:leptris_xpath_compiled, :leptris_document, :leptris_element,
|
|
540
549
|
:leptris_xpath_var_set], :leptris_xpath_result
|
|
550
|
+
# Combined namespaces + variables (1.9.18, upstream #608).
|
|
551
|
+
attach_function :leptris_xpath_compiled_eval_ns_vars,
|
|
552
|
+
[:leptris_xpath_compiled, :leptris_document, :leptris_element,
|
|
553
|
+
:leptris_xpath_ns_set, :leptris_xpath_var_set],
|
|
554
|
+
:leptris_xpath_result
|
|
541
555
|
# Source text of a compiled expression (owned by the handle).
|
|
542
556
|
attach_function :leptris_xpath_compiled_text,
|
|
543
557
|
[:leptris_xpath_compiled], :string
|
|
@@ -893,6 +907,9 @@ module Leptris
|
|
|
893
907
|
FETCH_INITIAL = 32
|
|
894
908
|
private_constant :FETCH_INITIAL
|
|
895
909
|
|
|
910
|
+
# Returns [pointers, kinds] — the kinds ride the batch
|
|
911
|
+
# (leptris_node_children_ex, 1.9.18 #617) so wrappers skip
|
|
912
|
+
# the per-child get_type dispatch.
|
|
896
913
|
def self.fetch_children(c_ptr)
|
|
897
914
|
scratch = (Thread.current[:leptris_scratch] ||= {})
|
|
898
915
|
buffer = scratch[:pointers]
|
|
@@ -900,18 +917,57 @@ module Leptris
|
|
|
900
917
|
buffer = scratch[:pointers] =
|
|
901
918
|
::FFI::MemoryPointer.new(:pointer, FETCH_INITIAL)
|
|
902
919
|
end
|
|
920
|
+
# size the kinds buffer from the POINTERS buffer's capacity —
|
|
921
|
+
# it may have grown past FETCH_INITIAL on earlier use, and C
|
|
922
|
+
# writes one kind per copied child
|
|
903
923
|
cap = buffer.size / PTR_BYTES
|
|
904
|
-
|
|
924
|
+
kinds = scratch_ints(cap)
|
|
925
|
+
copied = leptris_node_children_ex(c_ptr, buffer, kinds, cap)
|
|
905
926
|
if copied == cap
|
|
906
|
-
total =
|
|
927
|
+
total = leptris_node_children_ex(c_ptr, nil, nil, 0)
|
|
907
928
|
if total > cap
|
|
908
929
|
buffer.free
|
|
909
930
|
buffer = scratch[:pointers] =
|
|
910
931
|
::FFI::MemoryPointer.new(:pointer, total)
|
|
911
|
-
|
|
932
|
+
kinds = scratch_ints(total)
|
|
933
|
+
copied = leptris_node_children_ex(c_ptr, buffer, kinds, total)
|
|
912
934
|
end
|
|
913
935
|
end
|
|
914
|
-
buffer.get_array_of_pointer(0, copied)
|
|
936
|
+
[buffer.get_array_of_pointer(0, copied),
|
|
937
|
+
kinds.get_array_of_int(0, copied)]
|
|
938
|
+
end
|
|
939
|
+
|
|
940
|
+
# Raw qname-ordered attribute pairs INCLUDING xmlns at their
|
|
941
|
+
# byte positions (leptris_element_attributes_raw, 1.9.18
|
|
942
|
+
# #635) — the streaming SAX contract's mixed view.
|
|
943
|
+
def self.fetch_attributes_raw(el_ptr)
|
|
944
|
+
total = leptris_element_attributes_raw(el_ptr, nil, nil, 0)
|
|
945
|
+
return [] if total.zero?
|
|
946
|
+
scratch = (Thread.current[:leptris_scratch] ||= {})
|
|
947
|
+
names = scratch[:attr_names]
|
|
948
|
+
if names.nil? || names.size / PTR_BYTES < total
|
|
949
|
+
names&.free
|
|
950
|
+
names = scratch[:attr_names] =
|
|
951
|
+
::FFI::MemoryPointer.new(:pointer, total)
|
|
952
|
+
end
|
|
953
|
+
values = scratch[:attr_values]
|
|
954
|
+
if values.nil? || values.size / PTR_BYTES < total
|
|
955
|
+
values&.free
|
|
956
|
+
values = scratch[:attr_values] =
|
|
957
|
+
::FFI::MemoryPointer.new(:pointer, total)
|
|
958
|
+
end
|
|
959
|
+
copied = leptris_element_attributes_raw(
|
|
960
|
+
el_ptr, names, values, total)
|
|
961
|
+
Array.new(copied) do |i|
|
|
962
|
+
[utf8(names.get_pointer(i * PTR_BYTES).read_string),
|
|
963
|
+
utf8(values.get_pointer(i * PTR_BYTES).read_string)]
|
|
964
|
+
end
|
|
965
|
+
end
|
|
966
|
+
|
|
967
|
+
# Attribute strings cross the seam UTF-8 on both faces
|
|
968
|
+
# (ADR-0002).
|
|
969
|
+
def self.utf8(str)
|
|
970
|
+
str.nil? ? nil : str.force_encoding(Encoding::UTF_8)
|
|
915
971
|
end
|
|
916
972
|
|
|
917
973
|
# Element-only child batch (the mirror of fetch_children over
|
data/lib/leptris/xml/node.rb
CHANGED
|
@@ -156,12 +156,15 @@ class Leptris::XML::Node
|
|
|
156
156
|
|
|
157
157
|
def children
|
|
158
158
|
# Immutable in readonly mode: the batch fetch plus wrapper
|
|
159
|
-
# construction is paid once.
|
|
159
|
+
# construction is paid once. The kinds ride the batch
|
|
160
|
+
# (leptris_node_children_ex), so no per-child get_type.
|
|
160
161
|
return @children if memo_hit?(@children_version)
|
|
161
162
|
ensure_alive!
|
|
162
163
|
parent = as_element_or_self
|
|
163
|
-
|
|
164
|
-
|
|
164
|
+
pointers, kinds = Leptris::XML::FFI.fetch_children(@c_ptr)
|
|
165
|
+
nodes = Array.new(pointers.size) do |i|
|
|
166
|
+
Leptris::XML::Node.wrap(pointers[i], @document,
|
|
167
|
+
parent: parent, node_type: kinds[i])
|
|
165
168
|
end
|
|
166
169
|
result = Leptris::XML::NodeSet.new(@document, nodes)
|
|
167
170
|
if @document
|
|
@@ -61,8 +61,9 @@ module Leptris::XML::SAX::DomDispatch
|
|
|
61
61
|
end
|
|
62
62
|
return
|
|
63
63
|
end
|
|
64
|
-
Leptris::XML::FFI.fetch_children(c_ptr)
|
|
65
|
-
|
|
64
|
+
pointers, kinds = Leptris::XML::FFI.fetch_children(c_ptr)
|
|
65
|
+
pointers.each_with_index do |child_ptr, i|
|
|
66
|
+
case kinds[i]
|
|
66
67
|
when ELEMENT
|
|
67
68
|
visit_element(
|
|
68
69
|
Leptris::XML::Node.wrap(child_ptr, doc, node_type: ELEMENT),
|
|
@@ -101,7 +102,7 @@ module Leptris::XML::SAX::DomDispatch
|
|
|
101
102
|
if dispatched[:start_element] == :one_arg
|
|
102
103
|
handler.start_element(qname)
|
|
103
104
|
else
|
|
104
|
-
handler.start_element(qname,
|
|
105
|
+
handler.start_element(qname, declared_pairs(element))
|
|
105
106
|
end
|
|
106
107
|
end
|
|
107
108
|
visit_children(element.c_ptr, element.document, handler, dispatched)
|
|
@@ -113,6 +114,16 @@ module Leptris::XML::SAX::DomDispatch
|
|
|
113
114
|
end
|
|
114
115
|
end
|
|
115
116
|
|
|
117
|
+
# start_element's pairs with xmlns declarations carried — the
|
|
118
|
+
# engine's streaming contract reports declarations among the
|
|
119
|
+
# attribute pairs at their byte positions. Since libleptris
|
|
120
|
+
# 1.9.18 (upstream #635, closing leptris-ruby#99's documented
|
|
121
|
+
# difference), the raw qname-ordered list reproduces the exact
|
|
122
|
+
# interleave.
|
|
123
|
+
def declared_pairs(element)
|
|
124
|
+
Leptris::XML::FFI.fetch_attributes_raw(element.c_ptr)
|
|
125
|
+
end
|
|
126
|
+
|
|
116
127
|
# [name, value] pairs in source order, read straight from the
|
|
117
128
|
# attribute chain — no Attr objects, no hash.
|
|
118
129
|
def attr_pairs(c_ptr)
|
|
@@ -8,15 +8,15 @@ class Leptris::XML::SAX::Parser
|
|
|
8
8
|
|
|
9
9
|
attr_reader :document, :encoding
|
|
10
10
|
|
|
11
|
-
# streaming:
|
|
12
|
-
#
|
|
13
|
-
# attribute
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
11
|
+
# streaming: true (default, since 1.9.40) delivers through the
|
|
12
|
+
# engine transports — bulk/callback picked by override weight
|
|
13
|
+
# (leptris-ruby#95's attribute corruption is fixed upstream in
|
|
14
|
+
# libleptris 1.9.18, verified on the issue fixture). streaming:
|
|
15
|
+
# false delivers from a DOM parse (SAX::DomDispatch) — the
|
|
16
|
+
# correctness-first fallback kept for engines older than 1.9.18
|
|
17
|
+
# and for consumers wanting the DOM view's shapes.
|
|
18
18
|
def initialize(handler = Leptris::XML::SAX::Document.new,
|
|
19
|
-
encoding = nil, streaming:
|
|
19
|
+
encoding = nil, streaming: true)
|
|
20
20
|
@document = handler
|
|
21
21
|
@encoding = encoding
|
|
22
22
|
@streaming = streaming
|
data/lib/libleptris.so
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: leptris
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.9.
|
|
4
|
+
version: 1.9.40
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ffi
|