pdf.js.mirror/test/unit/name_number_tree_spec.js

171 lines
5.6 KiB
JavaScript

/* Copyright 2026 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Dict, Ref } from "../../src/core/primitives.js";
import { NameTree, NumberTree } from "../../src/core/name_number_tree.js";
import { XRefMock } from "./test_utils.js";
describe("NameOrNumberTree", function () {
describe("NameTree", function () {
it("should return an empty map when root is null", function () {
const xref = new XRefMock([]);
const tree = new NameTree(null, xref);
expect(tree.getAll().size).toEqual(0);
});
it("should collect all entries from a flat tree", function () {
const root = new Dict();
root.set("Names", ["alpha", "value_a", "beta", "value_b"]);
const xref = new XRefMock([]);
const tree = new NameTree(root, xref);
const map = tree.getAll();
expect(map.size).toEqual(2);
expect(map.get("alpha")).toEqual("value_a");
expect(map.get("beta")).toEqual("value_b");
});
it("should collect all entries from a tree with Ref-based Kids", function () {
const leafRef = Ref.get(10, 0);
const leaf = new Dict();
leaf.set("Names", ["key1", "val1", "key2", "val2"]);
const root = new Dict();
root.set("Kids", [leafRef]);
const xref = new XRefMock([{ ref: leafRef, data: leaf }]);
const tree = new NameTree(root, xref);
const map = tree.getAll();
expect(map.size).toEqual(2);
expect(map.get("key1")).toEqual("val1");
expect(map.get("key2")).toEqual("val2");
});
it("should handle Kids containing inline (non-Ref) Dict nodes without throwing", function () {
// Regression test: before the fix, processed.put() was called on non-Ref
// Dict objects, causing an error in TESTING mode because RefSet only
// accepts Ref instances or ref strings.
const inlineLeaf = new Dict();
inlineLeaf.set("Names", ["key1", "val1", "key2", "val2"]);
const root = new Dict();
root.set("Kids", [inlineLeaf]);
const xref = new XRefMock([]);
const tree = new NameTree(root, xref);
// Should not throw even though the kid is an inline Dict (not a Ref).
const map = tree.getAll();
expect(map.size).toEqual(2);
expect(map.get("key1")).toEqual("val1");
expect(map.get("key2")).toEqual("val2");
});
it("should throw on duplicate Ref entries in Kids", function () {
const leafRef = Ref.get(20, 0);
const leaf = new Dict();
leaf.set("Names", ["a", "b"]);
const root = new Dict();
root.set("Kids", [leafRef, leafRef]);
const xref = new XRefMock([{ ref: leafRef, data: leaf }]);
const tree = new NameTree(root, xref);
expect(() => tree.getAll()).toThrow(
new Error('Duplicate entry in "Names" tree.')
);
});
it("should resolve Ref values when isRaw is false", function () {
const valRef = Ref.get(30, 0);
const valData = "resolved_value";
const root = new Dict();
root.set("Names", ["mykey", valRef]);
const xref = new XRefMock([{ ref: valRef, data: valData }]);
const tree = new NameTree(root, xref);
const map = tree.getAll();
expect(map.get("mykey")).toEqual("resolved_value");
});
it("should keep raw Ref values when isRaw is true", function () {
const valRef = Ref.get(31, 0);
const root = new Dict();
root.set("Names", ["mykey", valRef]);
const xref = new XRefMock([{ ref: valRef, data: "resolved_value" }]);
const tree = new NameTree(root, xref);
const map = tree.getAll(/* isRaw = */ true);
expect(map.get("mykey")).toBe(valRef);
});
});
describe("NumberTree", function () {
it("should collect all entries from a flat tree", function () {
const root = new Dict();
root.set("Nums", [1, "one", 2, "two"]);
const xref = new XRefMock([]);
const tree = new NumberTree(root, xref);
const map = tree.getAll();
expect(map.size).toEqual(2);
expect(map.get(1)).toEqual("one");
expect(map.get(2)).toEqual("two");
});
it("should handle Kids containing inline (non-Ref) Dict nodes without throwing", function () {
// Same regression as NameTree: non-Ref kids must not be passed to
// RefSet.put().
const inlineLeaf = new Dict();
inlineLeaf.set("Nums", [0, "zero", 1, "one"]);
const root = new Dict();
root.set("Kids", [inlineLeaf]);
const xref = new XRefMock([]);
const tree = new NumberTree(root, xref);
const map = tree.getAll();
expect(map.size).toEqual(2);
expect(map.get(0)).toEqual("zero");
expect(map.get(1)).toEqual("one");
});
it("should throw on duplicate Ref entries in Kids", function () {
const leafRef = Ref.get(40, 0);
const leaf = new Dict();
leaf.set("Nums", [5, "five"]);
const root = new Dict();
root.set("Kids", [leafRef, leafRef]);
const xref = new XRefMock([{ ref: leafRef, data: leaf }]);
const tree = new NumberTree(root, xref);
expect(() => tree.getAll()).toThrow(
new Error('Duplicate entry in "Nums" tree.')
);
});
});
});