leptris 1.9.312.0-ppc64le-linux → 1.9.313.0-ppc64le-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 +32 -0
- data/Rakefile +1 -1
- data/lib/leptris/version.rb +1 -1
- data/lib/leptris/xml/builder.rb +169 -0
- data/lib/leptris/xml/document.rb +14 -0
- data/lib/leptris/xml/element.rb +11 -0
- data/lib/leptris/xml.rb +1 -0
- data/lib/libleptris.so +0 -0
- data/vendor-src/README.md +1 -1
- data/vendor-src/libleptris/CHANGELOG.md +22 -0
- data/vendor-src/libleptris/CMakeLists.txt +1 -1
- data/vendor-src/libleptris/src/leptris/leptris.c +23 -9
- data/vendor-src/libleptris/src/leptris/leptris_internal.h +5 -0
- data/vendor-src/libleptris/test/abi/test_dom_mutation_bugs.cpp +26 -0
- data/vendor-src/libleptris/vcpkg.json +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5b0d75571e6bca74bbc0fda795a056ef0d06ee890c01a7702f4bafecf04b13b9
|
|
4
|
+
data.tar.gz: 00e7e1b1e4725cedbd9fed583ff3bed73766c48221920bc2e7444bf5d2c3b277
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a809fbb6ee0f7bf05ac4af11985ee50f5ec82410f65635bb1af97dd41bcefafc7d96a5a91e175585799c1418a5b459cd5b25fb1fb6728282a1f3ff7258f03a8b
|
|
7
|
+
data.tar.gz: 7e77d333407d8005739346eff63f9f1f3ca94bba8390b76c1e2d99db28a8db9bf001ebdf2640e71be7152e9f94661967c3deccd1c3a782c14d55c9b6f79a06bd
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
## [1.9.313.0] - 2026-10-07
|
|
2
|
+
|
|
3
|
+
### Fixed — engine sync (libleptris 1.9.313)
|
|
4
|
+
|
|
5
|
+
- **Absorption-aware release at the C ABI (#1557, engine #1566)**:
|
|
6
|
+
the follow-up to the #386 mitigation — `leptris_document_free`
|
|
7
|
+
now consults the absorption state itself. The anchor dying while
|
|
8
|
+
`absorbed_handle > 0` detaches the source and defers its release
|
|
9
|
+
to the outstanding holder's free (`absorbed_deferred`); handles
|
|
10
|
+
released before the anchor keep the #1548 handle-only no-op. C
|
|
11
|
+
consumers no longer need to mirror the absorbed flag at their own
|
|
12
|
+
release sites; the binding's 1.9.311.2 mitigation stays as
|
|
13
|
+
defense-in-depth. Both release orderings spec-pinned.
|
|
14
|
+
|
|
15
|
+
## [1.9.312.1] - 2026-10-07
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **Document#build / Element#build — the builder face (#374 lever
|
|
20
|
+
2)**: markup-accumulating construction. The block turns into
|
|
21
|
+
well-formed markup in Ruby (method_missing element dispatch
|
|
22
|
+
with attrs/text, `#text`/`#cdata`/`#comment`/`#raw`, one-pass
|
|
23
|
+
escaping of `& < > "`), and the flush performs ONE native
|
|
24
|
+
crossing for the whole subtree — parse + `root=` adoption for
|
|
25
|
+
document sinks (exactly one root, the parser enforces it;
|
|
26
|
+
returns the installed root wrapper), `append_markup` for
|
|
27
|
+
element sinks (returns the added NodeSet). Measured DSL-vs-DSL
|
|
28
|
+
under load (interleaved CPU-time medians, build(500)):
|
|
29
|
+
leptris builder 2.68 ms vs nokogiri's builder 5.29 ms —
|
|
30
|
+
**~2.0x** — and ~1.2x over our own object face (3.19 ms,
|
|
31
|
+
itself ~1.7x nokogiri after the 1.9.311.3 trim).
|
|
32
|
+
|
|
1
33
|
## [1.9.312.0] - 2026-10-07
|
|
2
34
|
|
|
3
35
|
### Added — engine sync (libleptris 1.9.312)
|
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.313"
|
|
12
12
|
# Vendored alongside libleptris for fn:normalize-unicode (TODO
|
|
13
13
|
# .restructure/20): built per platform with a RELOCATABLE @rpath
|
|
14
14
|
# install name, loaded by ffi.rb before libleptris so the
|
data/lib/leptris/version.rb
CHANGED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Markup-accumulating subtree construction (#374 lever 2): the
|
|
4
|
+
# builder turns a Ruby block into well-formed markup in a plain
|
|
5
|
+
# String (Ruby-side cost only), and the flush performs ONE native
|
|
6
|
+
# crossing — parse + attach — for the whole subtree. The
|
|
7
|
+
# per-element FFI crossing that dominated the object-face build
|
|
8
|
+
# profile collapses to one per #build call.
|
|
9
|
+
#
|
|
10
|
+
# doc.build do |b|
|
|
11
|
+
# b.catalog(id: "c") do
|
|
12
|
+
# b.item(id: 7) { b.name "Item 7" }
|
|
13
|
+
# end
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
# Element names arriving through method_missing are identifier-
|
|
17
|
+
# shaped by construction (Ruby method names cannot carry markup
|
|
18
|
+
# metacharacters); the explicit #element path checks NAME_RE.
|
|
19
|
+
# Text and attribute values escape in one pass per string.
|
|
20
|
+
class Leptris::XML::Builder
|
|
21
|
+
NAME_RE = /\A[a-zA-Z_][\w.-]*\z/
|
|
22
|
+
|
|
23
|
+
ESCAPE = {
|
|
24
|
+
"&" => "&",
|
|
25
|
+
"<" => "<",
|
|
26
|
+
">" => ">",
|
|
27
|
+
'"' => """,
|
|
28
|
+
}.freeze
|
|
29
|
+
ESCAPE_RE = /[&<>"]/
|
|
30
|
+
private_constant :ESCAPE, :ESCAPE_RE
|
|
31
|
+
|
|
32
|
+
# +sink+ receives the flushed markup (a Document or Element).
|
|
33
|
+
def initialize(sink)
|
|
34
|
+
@sink = sink
|
|
35
|
+
@buf = +""
|
|
36
|
+
@depth = 0
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def element(name, attributes = nil)
|
|
40
|
+
name = name.to_s
|
|
41
|
+
unless name =~ NAME_RE
|
|
42
|
+
raise ArgumentError,
|
|
43
|
+
"element name must match #{NAME_RE.inspect}, got #{name.inspect}"
|
|
44
|
+
end
|
|
45
|
+
@buf << "<" << name
|
|
46
|
+
write_attributes(attributes) if attributes
|
|
47
|
+
if block_given?
|
|
48
|
+
@buf << ">"
|
|
49
|
+
@depth += 1
|
|
50
|
+
begin
|
|
51
|
+
yield self
|
|
52
|
+
ensure
|
|
53
|
+
@depth -= 1
|
|
54
|
+
end
|
|
55
|
+
@buf << "</" << name << ">"
|
|
56
|
+
else
|
|
57
|
+
@buf << "/>"
|
|
58
|
+
end
|
|
59
|
+
self
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def text(content)
|
|
63
|
+
@buf << escape_text(content.to_s)
|
|
64
|
+
self
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def cdata(content)
|
|
68
|
+
@buf << "<![CDATA[" << content.to_s << "]]>"
|
|
69
|
+
self
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def comment(content)
|
|
73
|
+
@buf << "<!--" << escape_text(content.to_s) << "-->"
|
|
74
|
+
self
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Verbatim markup — the escape hatch for pre-serialized
|
|
78
|
+
# fragments; the caller owns well-formedness.
|
|
79
|
+
def raw(markup)
|
|
80
|
+
@buf << markup.to_s
|
|
81
|
+
self
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def method_missing(name, *args, &block)
|
|
85
|
+
# Method names are identifier-shaped: they cannot carry <, >,
|
|
86
|
+
# &, quotes, or whitespace, so they need no NAME_RE round-trip
|
|
87
|
+
# (trailing = / ? / ! are legal Ruby but never legal XML
|
|
88
|
+
# name tails here — reject them explicitly).
|
|
89
|
+
return super if name.to_s.end_with?("=", "?", "!")
|
|
90
|
+
case args.length
|
|
91
|
+
when 0
|
|
92
|
+
element(name.to_s, &block)
|
|
93
|
+
when 1
|
|
94
|
+
arg = args[0]
|
|
95
|
+
if arg.is_a?(Hash)
|
|
96
|
+
element(name.to_s, arg, &block)
|
|
97
|
+
else
|
|
98
|
+
element(name.to_s) { |b| b.text(arg); block&.call(b) }
|
|
99
|
+
end
|
|
100
|
+
when 2
|
|
101
|
+
attrs, txt = args
|
|
102
|
+
return super unless attrs.is_a?(Hash)
|
|
103
|
+
element(name.to_s, attrs) { |b| b.text(txt); block&.call(b) }
|
|
104
|
+
else
|
|
105
|
+
super
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def respond_to_missing?(name, include_private = false)
|
|
110
|
+
!name.to_s.end_with?("=", "?", "!") || super
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# One native crossing for the accumulated subtree: the flush
|
|
114
|
+
# parses + attaches. Document sinks take exactly one root
|
|
115
|
+
# (set_root_ex adopts the parsed root); element sinks append
|
|
116
|
+
# every fragment child.
|
|
117
|
+
def flush
|
|
118
|
+
unless @depth.zero?
|
|
119
|
+
raise Leptris::XML::Error,
|
|
120
|
+
"unbalanced builder — unclosed elements remain (depth #{@depth})"
|
|
121
|
+
end
|
|
122
|
+
markup = @buf
|
|
123
|
+
return @sink if markup.empty?
|
|
124
|
+
case @sink
|
|
125
|
+
when Leptris::XML::Document
|
|
126
|
+
parsed = Leptris::XML::Document.parse(markup)
|
|
127
|
+
root = parsed.root
|
|
128
|
+
if root.nil?
|
|
129
|
+
raise Leptris::XML::Error,
|
|
130
|
+
"builder markup produced no root element"
|
|
131
|
+
end
|
|
132
|
+
@sink.root = root
|
|
133
|
+
@buf = +""
|
|
134
|
+
# The INSTALLED root — the same wrapper #root now yields
|
|
135
|
+
# (root= returns the parsed source, not the adoption copy).
|
|
136
|
+
@sink.root
|
|
137
|
+
when Leptris::XML::Element
|
|
138
|
+
added = @sink.add_child(markup)
|
|
139
|
+
@buf = +""
|
|
140
|
+
added
|
|
141
|
+
else
|
|
142
|
+
raise ArgumentError,
|
|
143
|
+
"builder sink must be a Document or Element, got #{@sink.class}"
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
private
|
|
148
|
+
|
|
149
|
+
def write_attributes(attributes)
|
|
150
|
+
case attributes
|
|
151
|
+
when Hash
|
|
152
|
+
attributes.each do |k, v|
|
|
153
|
+
@buf << " " << k.to_s << '="' << escape_attr(v) << '"'
|
|
154
|
+
end
|
|
155
|
+
when nil then # nothing
|
|
156
|
+
else
|
|
157
|
+
raise ArgumentError,
|
|
158
|
+
"attributes must be a Hash, got #{attributes.class}"
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def escape_text(value)
|
|
163
|
+
value.gsub(ESCAPE_RE, ESCAPE)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def escape_attr(value)
|
|
167
|
+
value.to_s.gsub(ESCAPE_RE, ESCAPE)
|
|
168
|
+
end
|
|
169
|
+
end
|
data/lib/leptris/xml/document.rb
CHANGED
|
@@ -232,6 +232,20 @@ class Leptris::XML::Document
|
|
|
232
232
|
wrap(raw)
|
|
233
233
|
end
|
|
234
234
|
|
|
235
|
+
# Markup-accumulating construction (#374 lever 2): the block
|
|
236
|
+
# accumulates well-formed markup in Ruby; the flush performs
|
|
237
|
+
# ONE native crossing for the whole subtree. Exactly one root
|
|
238
|
+
# element — the parsed root is adopted with set_root_ex.
|
|
239
|
+
# Returns the flush's value (the installed root element).
|
|
240
|
+
#
|
|
241
|
+
# doc = Leptris::XML::Document.create
|
|
242
|
+
# doc.build { |b| b.catalog(id: "c") { b.item { b.name "x" } } }
|
|
243
|
+
def build
|
|
244
|
+
builder = Leptris::XML::Builder.new(self)
|
|
245
|
+
yield builder
|
|
246
|
+
builder.flush
|
|
247
|
+
end
|
|
248
|
+
|
|
235
249
|
# Deep copy of +node+ in a NEW document — the one authority
|
|
236
250
|
# behind Node#dup / Element#dup and the indent-unit path.
|
|
237
251
|
# Elements deep-copy through the C copier (every child kind and
|
data/lib/leptris/xml/element.rb
CHANGED
|
@@ -665,6 +665,17 @@ class Leptris::XML::Element < Leptris::XML::Node
|
|
|
665
665
|
Leptris::XML::Node.wrap_fresh(ptr, @document, Leptris::XML::FFI::NODE_ELEMENT)
|
|
666
666
|
end
|
|
667
667
|
|
|
668
|
+
# Markup-accumulating child construction (#374 lever 2): the
|
|
669
|
+
# block accumulates well-formed child markup in Ruby; the flush
|
|
670
|
+
# appends every fragment child in ONE native crossing
|
|
671
|
+
# (append_markup). Returns the flush's value (the NodeSet of
|
|
672
|
+
# added children).
|
|
673
|
+
def build
|
|
674
|
+
builder = Leptris::XML::Builder.new(self)
|
|
675
|
+
yield builder
|
|
676
|
+
builder.flush
|
|
677
|
+
end
|
|
678
|
+
|
|
668
679
|
def add_child(node_or_markup)
|
|
669
680
|
case node_or_markup
|
|
670
681
|
when Leptris::XML::Node
|
data/lib/leptris/xml.rb
CHANGED
|
@@ -14,6 +14,7 @@ module Leptris
|
|
|
14
14
|
autoload :Namespace, "leptris/xml/namespace"
|
|
15
15
|
autoload :Document, "leptris/xml/document"
|
|
16
16
|
autoload :DocumentFragment, "leptris/xml/document_fragment"
|
|
17
|
+
autoload :Builder, "leptris/xml/builder"
|
|
17
18
|
autoload :DocType, "leptris/xml/doc_type"
|
|
18
19
|
autoload :NodeSet, "leptris/xml/node_set"
|
|
19
20
|
autoload :Searchable, "leptris/xml/searchable"
|
data/lib/libleptris.so
CHANGED
|
Binary file
|
data/vendor-src/README.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [1.9.313] - 2026-10-07
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **Absorbed sources defer their release to outstanding handles
|
|
8
|
+
(#1557, PR #1566).** Follow-up to #1548's
|
|
9
|
+
`leptris_document_absorb`: the absorber's free cleared the
|
|
10
|
+
absorbed state before recursing, so a source handle that
|
|
11
|
+
OUTLIVED the absorber read the cleared flag and re-released the
|
|
12
|
+
already-destroyed pool — heap corruption (glibc abort /
|
|
13
|
+
`malloc_zone_error`), deterministic under exit-time finalizers
|
|
14
|
+
(leptris-ruby#386, 50-iteration repro). When the anchor dies
|
|
15
|
+
while `absorbed_handle > 0` it now detaches the source and marks
|
|
16
|
+
`absorbed_deferred`: the holder's `leptris_document_free`
|
|
17
|
+
performs the FULL release; handles released before the anchor
|
|
18
|
+
keep the #1548 handle-only no-op. Consumers no longer need to
|
|
19
|
+
mirror the absorbed flag at their own release sites. Gates: the
|
|
20
|
+
repro red under ASAN at leptris.c:937, green after; mutation
|
|
21
|
+
suite 27/27 ASAN + Release; full ctest 1866/1866; leaks 0.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
3
25
|
## [1.9.312] - 2026-10-06
|
|
4
26
|
|
|
5
27
|
### Added
|
|
@@ -933,9 +933,11 @@ LEPTRIS_API void leptris_document_free(struct leptris_document* doc) {
|
|
|
933
933
|
|
|
934
934
|
/* #1548: an absorbed document's MEMORY belongs to its absorber
|
|
935
935
|
* (it rides the absorber's child_docs chain). A caller free
|
|
936
|
-
* releases only the outstanding handle.
|
|
937
|
-
|
|
938
|
-
|
|
936
|
+
* releases only the outstanding handle. #1557: unless the
|
|
937
|
+
* anchor died first and DEFERRED the release to this holder —
|
|
938
|
+
* then this free is the real one. */
|
|
939
|
+
if (doc->absorbed_by && !doc->absorbed_deferred) {
|
|
940
|
+
if (doc->absorbed_handle > 0) doc->absorbed_handle--;
|
|
939
941
|
return;
|
|
940
942
|
}
|
|
941
943
|
|
|
@@ -1021,12 +1023,24 @@ LEPTRIS_API void leptris_document_free(struct leptris_document* doc) {
|
|
|
1021
1023
|
* doesn't try to walk the
|
|
1022
1024
|
* adopted subtree. */
|
|
1023
1025
|
ch->root = NULL;
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1026
|
+
if (ch->absorbed_by && ch->absorbed_handle > 0) {
|
|
1027
|
+
/* #1557: a caller still holds this absorbed handle.
|
|
1028
|
+
* Freeing here would strand it on freed memory (its
|
|
1029
|
+
* later free read the cleared flag and re-released
|
|
1030
|
+
* the pool — the leptris-ruby#386 double free).
|
|
1031
|
+
* DEFER: detach from our chain and hand the release
|
|
1032
|
+
* to the holder's leptris_document_free, which sees
|
|
1033
|
+
* absorbed_deferred and runs the full release. */
|
|
1034
|
+
ch->absorbed_deferred = 1;
|
|
1035
|
+
ch->next_adopted = NULL;
|
|
1036
|
+
} else {
|
|
1037
|
+
/* #1548: the anchor's free is the REAL one — clear
|
|
1038
|
+
* the absorbed state so the early handle-return
|
|
1039
|
+
* above does not swallow it. */
|
|
1040
|
+
ch->absorbed_by = NULL;
|
|
1041
|
+
ch->absorbed_handle = 0;
|
|
1042
|
+
leptris_document_free(ch);
|
|
1043
|
+
}
|
|
1030
1044
|
ch = next;
|
|
1031
1045
|
}
|
|
1032
1046
|
doc->child_docs = NULL;
|
|
@@ -195,6 +195,11 @@ struct leptris_document {
|
|
|
195
195
|
* (the anchor frees the memory later). */
|
|
196
196
|
struct leptris_document* absorbed_by;
|
|
197
197
|
int absorbed_handle;
|
|
198
|
+
/* #1557: the absorber died while this handle was outstanding —
|
|
199
|
+
* the anchor deferred the pool release to THIS holder's free,
|
|
200
|
+
* so leptris_document_free must run the full release (not the
|
|
201
|
+
* handle-only early return). */
|
|
202
|
+
int absorbed_deferred;
|
|
198
203
|
/* XML Declaration support */
|
|
199
204
|
char* xml_version; /* "1.0", "1.1", etc. or NULL if not present */
|
|
200
205
|
int standalone; /* -1=not set, 0=no, 1=yes */
|
|
@@ -670,6 +670,32 @@ TEST(CrossDocumentLeafAdoption, RootLevelLeafArgumentAdoptsByKind) {
|
|
|
670
670
|
}
|
|
671
671
|
}
|
|
672
672
|
|
|
673
|
+
// #1557: an absorbed source's handle may OUTLIVE the absorber. The
|
|
674
|
+
// anchor's free used to clear the absorbed state, so the holder's
|
|
675
|
+
// later free re-released the same pool — heap corruption. The anchor
|
|
676
|
+
// now defers the release to the outstanding handle.
|
|
677
|
+
TEST(AbsorbAdoption, SourceHandleMayOutliveAnchor) {
|
|
678
|
+
for (int i = 0; i < 50; i++) {
|
|
679
|
+
LeptrisDocument dest = Parse("<main><keep/></main>");
|
|
680
|
+
ASSERT_NE(dest, nullptr);
|
|
681
|
+
LeptrisDocument src = Parse("<scratch><a/></scratch>");
|
|
682
|
+
ASSERT_NE(src, nullptr);
|
|
683
|
+
ASSERT_EQ(leptris_document_absorb(dest, src), LEPTRIS_OK);
|
|
684
|
+
leptris_document_free(dest); /* anchor dies first */
|
|
685
|
+
leptris_document_free(src); /* holder releases after */
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
TEST(AbsorbAdoption, SourceHandleFreedBeforeAnchorStillNoOp) {
|
|
690
|
+
LeptrisDocument dest = Parse("<main><keep/></main>");
|
|
691
|
+
ASSERT_NE(dest, nullptr);
|
|
692
|
+
LeptrisDocument src = Parse("<scratch><a/></scratch>");
|
|
693
|
+
ASSERT_NE(src, nullptr);
|
|
694
|
+
ASSERT_EQ(leptris_document_absorb(dest, src), LEPTRIS_OK);
|
|
695
|
+
leptris_document_free(src); /* handle-only: memory stays with anchor */
|
|
696
|
+
leptris_document_free(dest); /* releases everything incl. the source */
|
|
697
|
+
}
|
|
698
|
+
|
|
673
699
|
TEST(AbsorbAdoption, SpliceAfterAbsorbIsZeroCopy) {
|
|
674
700
|
LeptrisDocument dst = Parse("<main><keep/></main>");
|
|
675
701
|
ASSERT_NE(dst, nullptr);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
|
|
3
3
|
"name": "leptris",
|
|
4
|
-
"version": "1.9.
|
|
4
|
+
"version": "1.9.313",
|
|
5
5
|
"description": "High-performance XML parser and XPath 1.0 engine in C (libleptris)",
|
|
6
6
|
"homepage": "https://github.com/leptris/leptris",
|
|
7
7
|
"license": "MIT",
|
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.313.0
|
|
5
5
|
platform: ppc64le-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ffi
|
|
@@ -144,6 +144,7 @@ files:
|
|
|
144
144
|
- lib/leptris/version.rb
|
|
145
145
|
- lib/leptris/xml.rb
|
|
146
146
|
- lib/leptris/xml/attr.rb
|
|
147
|
+
- lib/leptris/xml/builder.rb
|
|
147
148
|
- lib/leptris/xml/c_string_array.rb
|
|
148
149
|
- lib/leptris/xml/cdata.rb
|
|
149
150
|
- lib/leptris/xml/comment.rb
|