leptris 1.9.311.0 → 1.9.311.1
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 +23 -0
- data/lib/leptris/vendor/aarch64-linux-musl/libleptris.so +0 -0
- data/lib/leptris/vendor/arm64-darwin/libleptris.dylib +0 -0
- data/lib/leptris/version.rb +1 -1
- data/lib/leptris/xml/document.rb +6 -1
- data/lib/leptris/xml/element.rb +28 -21
- data/lib/leptris/xml/node.rb +3 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a00351d2185cc9432a2a675feb686a11e616e9bfc4ed930ed5c3737e7eee8cbf
|
|
4
|
+
data.tar.gz: 93aa8c74620619e74b7a28a4f83569a2154df36c600edd0f8126cf2129d39bda
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 169251ef7965e3ff58646406f37bbebc1308732d7e5dc3ab400b1e766df5142bde0d887acba8e3eb2eb1b22ef5f71dc934ca76b8f01c7baff96f2ee55ab41872
|
|
7
|
+
data.tar.gz: 9e84022d8a35c5135b1fdf7f7b60531c4ba2231f9f462c48b9051de2f268b84bb9a042d2d1298f3e06aa74898364a71c6a25b57010d81c265f44da571112b74a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
## [1.9.311.1] - 2026-10-06
|
|
2
|
+
|
|
3
|
+
### Fixed
|
|
4
|
+
|
|
5
|
+
- **Docless children now route through the adoption contract
|
|
6
|
+
(#376)**: moxml's created nodes arrive as Node wrappers whose
|
|
7
|
+
#document is nil but whose C node is live in a foreign pool —
|
|
8
|
+
the splice sites' foreign check required a document, so those
|
|
9
|
+
children bypassed the namespace lift and, worse, the returned
|
|
10
|
+
wrapper addressed the ABANDONED source instead of the installed
|
|
11
|
+
in-tree copy (moxml's flows then mutated a node the tree never
|
|
12
|
+
saw). `foreign_child?` now treats document-nil as foreign at
|
|
13
|
+
add_child, prepend_child, add_next_sibling,
|
|
14
|
+
add_previous_sibling, and append_children, so every splice
|
|
15
|
+
returns the installed wrapper. Document#root= routes docless
|
|
16
|
+
roots through the copying ex-face too — the plain set_root of a
|
|
17
|
+
foreign-pool node linked the pointer WITHOUT adopting it into
|
|
18
|
+
the destination pool, so destination-side writes landed in the
|
|
19
|
+
source arena and reads through the root memo missed them.
|
|
20
|
+
Node-level mutations on docless
|
|
21
|
+
wrappers no longer crash the version gate (they memoize
|
|
22
|
+
nothing, so there is no version to advance).
|
|
23
|
+
|
|
1
24
|
## [1.9.311.0] - 2026-10-06
|
|
2
25
|
|
|
3
26
|
### Added
|
|
Binary file
|
|
Binary file
|
data/lib/leptris/version.rb
CHANGED
data/lib/leptris/xml/document.rb
CHANGED
|
@@ -388,7 +388,12 @@ class Leptris::XML::Document
|
|
|
388
388
|
# the foreign subtree into this document's pool and reports the
|
|
389
389
|
# installed element — a fresh handle distinct from the source
|
|
390
390
|
# pointer. Same-document installs keep the native fast path.
|
|
391
|
-
|
|
391
|
+
# Docless roots count as foreign (#376): a plain set_root of a
|
|
392
|
+
# foreign-pool node links the pointer WITHOUT adopting it into
|
|
393
|
+
# this pool — writes through this document land in the source
|
|
394
|
+
# arena and reads through the root memo miss them. The ex-face
|
|
395
|
+
# copies properly.
|
|
396
|
+
cross = Leptris::XML::Element.foreign_to?(element, self)
|
|
392
397
|
installed_ptr = nil
|
|
393
398
|
if cross
|
|
394
399
|
out = ::FFI::MemoryPointer.new(:pointer)
|
data/lib/leptris/xml/element.rb
CHANGED
|
@@ -389,6 +389,15 @@ class Leptris::XML::Element < Leptris::XML::Node
|
|
|
389
389
|
!Leptris::XML::Native.ns_lift_needed?(node.c_ptr.address)
|
|
390
390
|
end
|
|
391
391
|
|
|
392
|
+
# A node is foreign to +document+ when it belongs to another one
|
|
393
|
+
# — or to NONE (#376): moxml's created nodes are live C nodes
|
|
394
|
+
# wrapped without a document, and they splice by copy exactly
|
|
395
|
+
# like attached-foreign ones. One definition of "foreign" for
|
|
396
|
+
# the element splices and Document#root=.
|
|
397
|
+
def self.foreign_to?(node, document)
|
|
398
|
+
node.document.nil? || !node.document.equal?(document)
|
|
399
|
+
end
|
|
400
|
+
|
|
392
401
|
def self.lift_namespaces_for_adoption(node, target_scope)
|
|
393
402
|
return unless node.is_a?(Leptris::XML::Element)
|
|
394
403
|
# Declarations the node already carries (its own definitions —
|
|
@@ -419,11 +428,11 @@ class Leptris::XML::Element < Leptris::XML::Node
|
|
|
419
428
|
# C-bound insert (TODO.perf/14): gates + predicate + version
|
|
420
429
|
# bump + engine insert in one dispatch; Qnil = the child needs
|
|
421
430
|
# the namespace lift — the full path below handles it.
|
|
422
|
-
# Cross-document nodes skip the fast path entirely
|
|
423
|
-
# #1528): the engine deep-copies them at the
|
|
424
|
-
# full path's lift must run FIRST and the source
|
|
425
|
-
# removed after (move semantics).
|
|
426
|
-
if
|
|
431
|
+
# Cross-document and docless nodes skip the fast path entirely
|
|
432
|
+
# (1.9.304, #1528; #376): the engine deep-copies them at the
|
|
433
|
+
# splice, so the full path's lift must run FIRST and the source
|
|
434
|
+
# original is removed after (move semantics).
|
|
435
|
+
if Leptris::XML::Element.foreign_to?(node, @document)
|
|
427
436
|
ensure_writable!
|
|
428
437
|
unless Leptris::XML::Element.skip_adoption_lift?(node)
|
|
429
438
|
Leptris::XML::Element.lift_namespaces_for_adoption(node, namespaces)
|
|
@@ -455,10 +464,10 @@ class Leptris::XML::Element < Leptris::XML::Node
|
|
|
455
464
|
# C-bound insert (TODO.perf/14): gates + predicate + version
|
|
456
465
|
# bump + engine insert in one dispatch; Qnil = the child needs
|
|
457
466
|
# the namespace lift — the full path below handles it.
|
|
458
|
-
# Cross-document: full path first (lift +
|
|
459
|
-
# the source original is removed; returns
|
|
460
|
-
# (self's new next sibling).
|
|
461
|
-
if
|
|
467
|
+
# Cross-document and docless (#376): full path first (lift +
|
|
468
|
+
# engine copy), then the source original is removed; returns
|
|
469
|
+
# the installed copy (self's new next sibling).
|
|
470
|
+
if Leptris::XML::Element.foreign_to?(node, @document)
|
|
462
471
|
ensure_writable!
|
|
463
472
|
unless Leptris::XML::Element.skip_adoption_lift?(node)
|
|
464
473
|
Leptris::XML::Element.lift_namespaces_for_adoption(node, namespaces)
|
|
@@ -490,10 +499,10 @@ class Leptris::XML::Element < Leptris::XML::Node
|
|
|
490
499
|
# C-bound insert (TODO.perf/14): gates + predicate + version
|
|
491
500
|
# bump + engine insert in one dispatch; Qnil = the child needs
|
|
492
501
|
# the namespace lift — the full path below handles it.
|
|
493
|
-
# Cross-document: full path first (lift +
|
|
494
|
-
# the source original is removed; returns
|
|
495
|
-
# (self's new previous sibling).
|
|
496
|
-
if
|
|
502
|
+
# Cross-document and docless (#376): full path first (lift +
|
|
503
|
+
# engine copy), then the source original is removed; returns
|
|
504
|
+
# the installed copy (self's new previous sibling).
|
|
505
|
+
if Leptris::XML::Element.foreign_to?(node, @document)
|
|
497
506
|
ensure_writable!
|
|
498
507
|
unless Leptris::XML::Element.skip_adoption_lift?(node)
|
|
499
508
|
Leptris::XML::Element.lift_namespaces_for_adoption(node, namespaces)
|
|
@@ -551,9 +560,7 @@ class Leptris::XML::Element < Leptris::XML::Node
|
|
|
551
560
|
nodes.each { |n| add_child(n) }
|
|
552
561
|
return
|
|
553
562
|
end
|
|
554
|
-
cross = nodes.any?
|
|
555
|
-
n.document && !n.document.equal?(@document)
|
|
556
|
-
end
|
|
563
|
+
cross = nodes.any? { |n| Leptris::XML::Element.foreign_to?(n, @document) }
|
|
557
564
|
if native_fast_children?
|
|
558
565
|
addrs = nodes.map { |n| n.c_ptr.address }
|
|
559
566
|
done = Leptris::XML::Native.append_binding_children(
|
|
@@ -668,13 +675,13 @@ class Leptris::XML::Element < Leptris::XML::Node
|
|
|
668
675
|
ensure_writable!
|
|
669
676
|
case node_or_markup
|
|
670
677
|
when Leptris::XML::Node
|
|
671
|
-
#
|
|
678
|
+
# Foreign-child adoption (1.9.304, #1528): the engine
|
|
672
679
|
# deep-copies foreign nodes at the splice — the returned
|
|
673
680
|
# wrapper must be the INSTALLED copy, not the detached
|
|
674
|
-
# source.
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
return append_installed(node_or_markup) if
|
|
681
|
+
# source. Docless wrappers count as foreign (#376): moxml's
|
|
682
|
+
# created nodes carry live C pointers with no owning
|
|
683
|
+
# document, and their callers expect the in-tree handle.
|
|
684
|
+
return append_installed(node_or_markup) if Leptris::XML::Element.foreign_to?(node_or_markup, @document)
|
|
678
685
|
# C-bound append (TODO.perf/08-09): one dispatch runs the
|
|
679
686
|
# readonly/liveness gates, the provable no-op lift
|
|
680
687
|
# predicate, the version bump, and the engine append. Qnil
|
data/lib/leptris/xml/node.rb
CHANGED
|
@@ -281,14 +281,15 @@ class Leptris::XML::Node
|
|
|
281
281
|
# passes through this gate, so it is where the document's mutation
|
|
282
282
|
# version advances — the invalidation behind writable-document
|
|
283
283
|
# memoization. Bumping before the C call is conservative: a failed
|
|
284
|
-
# mutation merely discards memos.
|
|
284
|
+
# mutation merely discards memos. Docless wrappers (#376) mutate
|
|
285
|
+
# fine — they memoize nothing, so there is no version to advance.
|
|
285
286
|
def ensure_writable!
|
|
286
287
|
ensure_alive!
|
|
287
288
|
if readonly_document?
|
|
288
289
|
raise Leptris::XML::ReadOnlyError,
|
|
289
290
|
"document is readonly — mutation attempted on #{inspect}"
|
|
290
291
|
end
|
|
291
|
-
@document
|
|
292
|
+
@document&.advance_version
|
|
292
293
|
nil
|
|
293
294
|
end
|
|
294
295
|
|