M6: a /Parent given through an object that is only a reference is followed in the field name (form.field-list)

qualified_name reads each ancestor through Document::resolve, which follows an object that is
nothing but a reference to another, as document inspection does, so both name the kid the same.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pq7HyCHD1R3rywQBPCHXZA
This commit is contained in:
mtlcl410andClaude Opus 5.5 committed 2026-11-08 12:49:40 +08:00
1 parent eee81da38b
commit 8bb2d920a0
2 files changed
+19 -1

No files matched your search

+2 -1
View File
@@ -101,7 +101,8 @@ fn qualified_name(doc: &Document, r: ObjRef) -> Option<String> {
if seen.len() > 64 || !seen.insert(c) {
break;
}
let obj = doc.get(c);
// An object that is only a reference to another is followed, as `Document::resolve` does.
let obj = doc.resolve(&Object::Ref(c));
let d = obj.as_dict()?;
if let Some(t) = d.get(b"T").and_then(|o| text_of(&doc.resolve(o))) {
parts.push(t);
+17
View File
@@ -2492,6 +2492,23 @@ fn a_named_kid_whose_parent_is_another_field_is_named_under_it() {
assert_eq!(names, ["Other.k"]);
}
/// A `/Parent` naming an object that is only a reference to the parent field is followed to it,
/// as document inspection follows it, so both name the kid the same.
#[test]
fn a_parent_given_through_an_object_that_is_a_reference_names_the_kid() {
let objs: Vec<String> = vec![
"<< /Type /Catalog /Pages 2 0 R /AcroForm << /Fields [4 0 R] >> >>".into(), // 1
"<< /Type /Pages /Kids [3 0 R] /Count 1 /MediaBox [0 0 600 800] >>".into(), // 2
"<< /Type /Page /Parent 2 0 R /Annots [5 0 R] >>".into(), // 3
"<< /FT /Tx /T (Listing) /Kids [5 0 R] >>".into(), // 4
"<< /Type /Annot /Subtype /Widget /T (k) /Parent 6 0 R /Rect [50 700 150 715] /P 3 0 R >>".into(), // 5
"7 0 R".into(), // 6
"<< /T (Other) /Kids [5 0 R] >>".into(), // 7
];
let names: Vec<String> = fields(&document(&objs)).into_iter().map(|f| f.name).collect();
assert_eq!(names, ["Other.k"]);
}
/// The two kids of [`radio_kids_with_names`] (`Group1`, no `/Parent`), with the one drawing
/// `Choice2` (6, read first) or the one drawing `Choice1` (5) read-only.
fn radio_kids_one_read_only(read_only: u32) -> Document {