Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion lib/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,25 @@ class PDFObject {

return `(${string})`;
} else if (Array.isArray(object)) {
// Array entries are positional, so an `undefined` hole cannot simply be
// dropped without shifting everything after it. `null` is a real PDF
// object (ISO 32000-1, 7.3.9) and is the closest valid stand-in, which
// is also what JSON.stringify does.
const items = object
.map((e) => PDFObject.convert(e, encryptFn))
.map((e) => PDFObject.convert(e === undefined ? null : e, encryptFn))
.join(' ');
return `[${items}]`;
} else if ({}.toString.call(object) === '[object Object]') {
const out = ['<<'];
for (let key in object) {
const val = object[key];
// `undefined` has no PDF representation, so serialising it produced the
// literal token `undefined` and an unparseable file. The spec treats a
// dictionary entry whose value is null as absent (ISO 32000-1, 7.3.9),
// so omitting the key is the closest valid equivalent - and it matches
// JSON.stringify. An explicit `null` is left alone: it is a real PDF
// object and callers may be relying on it.
if (val === undefined) continue;
out.push(`/${key} ${PDFObject.convert(val, encryptFn)}`);
}

Expand Down
14 changes: 14 additions & 0 deletions tests/unit/object.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ describe('PDFObject', () => {
expect(result.length).toEqual(12);
expect(result).toMatchInlineSnapshot(`"(þÿ±²³´)"`);
});

test('dictionary omits keys whose value is undefined', () => {
expect(PDFObject.convert({ a: 1, b: undefined, c: 2 })).toEqual(
'<<\n/a 1\n/c 2\n>>',
);
});

test('dictionary keeps an explicit null', () => {
expect(PDFObject.convert({ a: null })).toEqual('<<\n/a null\n>>');
});

test('array converts an undefined entry to null to keep positions', () => {
expect(PDFObject.convert([1, undefined, 2])).toEqual('[1 null 2]');
});
});

describe('escapeName', () => {
Expand Down
Loading