Add general iteration support in the RefSet and RefSetCache classes

This patch removes the existing `forEach` methods, in favor of making the classes properly iterable instead. Given that the classes are using a `Set` respectively a `Map` internally, implementing this is very easy/efficient and allows us to simplify some existing code.
This commit is contained in:
Jonas Jenwald 2022-03-18 14:18:03 +01:00
parent 489e9ff7d3
commit c0736647f9
5 changed files with 54 additions and 60 deletions

View File

@ -1040,42 +1040,32 @@ class Catalog {
return shadow(this, "jsActions", actions); return shadow(this, "jsActions", actions);
} }
fontFallback(id, handler) { async fontFallback(id, handler) {
const promises = []; const translatedFonts = await Promise.all(this.fontCache);
this.fontCache.forEach(function (promise) {
promises.push(promise);
});
return Promise.all(promises).then(translatedFonts => {
for (const translatedFont of translatedFonts) { for (const translatedFont of translatedFonts) {
if (translatedFont.loadedName === id) { if (translatedFont.loadedName === id) {
translatedFont.fallback(handler); translatedFont.fallback(handler);
return; return;
} }
} }
});
} }
cleanup(manuallyTriggered = false) { async cleanup(manuallyTriggered = false) {
clearGlobalCaches(); clearGlobalCaches();
this.globalImageCache.clear(/* onlyData = */ manuallyTriggered); this.globalImageCache.clear(/* onlyData = */ manuallyTriggered);
this.pageKidsCountCache.clear(); this.pageKidsCountCache.clear();
this.pageIndexCache.clear(); this.pageIndexCache.clear();
this.nonBlendModesSet.clear(); this.nonBlendModesSet.clear();
const promises = []; const translatedFonts = await Promise.all(this.fontCache);
this.fontCache.forEach(function (promise) {
promises.push(promise);
});
return Promise.all(promises).then(translatedFonts => {
for (const { dict } of translatedFonts) { for (const { dict } of translatedFonts) {
delete dict.cacheKey; delete dict.cacheKey;
} }
this.fontCache.clear(); this.fontCache.clear();
this.builtInCMapCache.clear(); this.builtInCMapCache.clear();
this.standardFontDataCache.clear(); this.standardFontDataCache.clear();
});
} }
async getPageDict(pageIndex) { async getPageDict(pageIndex) {

View File

@ -352,9 +352,9 @@ class PartialEvaluator {
// When no blend modes exist, there's no need re-fetch/re-parse any of the // When no blend modes exist, there's no need re-fetch/re-parse any of the
// processed `Ref`s again for subsequent pages. This helps reduce redundant // processed `Ref`s again for subsequent pages. This helps reduce redundant
// `XRef.fetch` calls for some documents (e.g. issue6961.pdf). // `XRef.fetch` calls for some documents (e.g. issue6961.pdf).
processed.forEach(ref => { for (const ref of processed) {
nonBlendModesSet.put(ref); nonBlendModesSet.put(ref);
}); }
return false; return false;
} }

View File

@ -179,9 +179,9 @@ class GlobalImageCache {
get _byteSize() { get _byteSize() {
let byteSize = 0; let byteSize = 0;
this._imageCache.forEach(imageData => { for (const imageData of this._imageCache) {
byteSize += imageData.byteSize; byteSize += imageData.byteSize;
}); }
return byteSize; return byteSize;
} }

View File

@ -350,10 +350,8 @@ class RefSet {
this._set.delete(ref.toString()); this._set.delete(ref.toString());
} }
forEach(callback) { [Symbol.iterator]() {
for (const ref of this._set.values()) { return this._set.values();
callback(ref);
}
} }
clear() { clear() {
@ -386,10 +384,8 @@ class RefSetCache {
this._map.set(ref.toString(), this.get(aliasRef)); this._map.set(ref.toString(), this.get(aliasRef));
} }
forEach(callback) { [Symbol.iterator]() {
for (const value of this._map.values()) { return this._map.values();
callback(value);
}
} }
clear() { clear() {

View File

@ -418,28 +418,41 @@ describe("primitives", function () {
}); });
describe("RefSet", function () { describe("RefSet", function () {
it("should have a stored value", function () { const ref1 = Ref.get(4, 2),
const ref = Ref.get(4, 2); ref2 = Ref.get(5, 2);
const refset = new RefSet(); let refSet;
refset.put(ref);
expect(refset.has(ref)).toBeTruthy();
});
it("should not have an unknown value", function () {
const ref = Ref.get(4, 2);
const refset = new RefSet();
expect(refset.has(ref)).toBeFalsy();
refset.put(ref); beforeEach(function () {
const anotherRef = Ref.get(2, 4); refSet = new RefSet();
expect(refset.has(anotherRef)).toBeFalsy(); });
afterEach(function () {
refSet = null;
});
it("should have a stored value", function () {
refSet.put(ref1);
expect(refSet.has(ref1)).toBeTruthy();
});
it("should not have an unknown value", function () {
expect(refSet.has(ref1)).toBeFalsy();
refSet.put(ref1);
expect(refSet.has(ref2)).toBeFalsy();
});
it("should support iteration", function () {
refSet.put(ref1);
refSet.put(ref2);
expect([...refSet]).toEqual([ref1.toString(), ref2.toString()]);
}); });
}); });
describe("RefSetCache", function () { describe("RefSetCache", function () {
const ref1 = Ref.get(4, 2); const ref1 = Ref.get(4, 2),
const ref2 = Ref.get(5, 2); ref2 = Ref.get(5, 2),
const obj1 = Name.get("foo"); obj1 = Name.get("foo"),
const obj2 = Name.get("bar"); obj2 = Name.get("bar");
let cache; let cache;
beforeEach(function () { beforeEach(function () {
@ -483,12 +496,7 @@ describe("primitives", function () {
it("should support iteration", function () { it("should support iteration", function () {
cache.put(ref1, obj1); cache.put(ref1, obj1);
cache.put(ref2, obj2); cache.put(ref2, obj2);
expect([...cache]).toEqual([obj1, obj2]);
const values = [];
cache.forEach(function (value) {
values.push(value);
});
expect(values).toEqual([obj1, obj2]);
}); });
}); });