Merge pull request #11985 from Snuffleupagus/rm-isEmptyObj

Convert some `Object`s to `Map`s in `ChunkedStreamManager`, and move the `isEmptyObj` helper function to the test utils
This commit is contained in:
Tim van der Meij 2020-06-10 00:01:14 +02:00 committed by GitHub
commit a327f386ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 45 deletions

View File

@ -18,7 +18,6 @@ import {
arrayByteLength, arrayByteLength,
arraysToBytes, arraysToBytes,
createPromiseCapability, createPromiseCapability,
isEmptyObj,
} from "../shared/util.js"; } from "../shared/util.js";
import { MissingDataException } from "./core_utils.js"; import { MissingDataException } from "./core_utils.js";
@ -319,9 +318,9 @@ class ChunkedStreamManager {
this.currRequestId = 0; this.currRequestId = 0;
this.chunksNeededByRequest = Object.create(null); this._chunksNeededByRequest = new Map();
this.requestsByChunk = Object.create(null); this._requestsByChunk = new Map();
this.promisesByRequest = Object.create(null); this._promisesByRequest = new Map();
this.progressiveDataLength = 0; this.progressiveDataLength = 0;
this.aborted = false; this.aborted = false;
@ -384,29 +383,31 @@ class ChunkedStreamManager {
_requestChunks(chunks) { _requestChunks(chunks) {
const requestId = this.currRequestId++; const requestId = this.currRequestId++;
const chunksNeeded = Object.create(null); const chunksNeeded = new Set();
this.chunksNeededByRequest[requestId] = chunksNeeded; this._chunksNeededByRequest.set(requestId, chunksNeeded);
for (const chunk of chunks) { for (const chunk of chunks) {
if (!this.stream.hasChunk(chunk)) { if (!this.stream.hasChunk(chunk)) {
chunksNeeded[chunk] = true; chunksNeeded.add(chunk);
} }
} }
if (isEmptyObj(chunksNeeded)) { if (chunksNeeded.size === 0) {
return Promise.resolve(); return Promise.resolve();
} }
const capability = createPromiseCapability(); const capability = createPromiseCapability();
this.promisesByRequest[requestId] = capability; this._promisesByRequest.set(requestId, capability);
const chunksToRequest = []; const chunksToRequest = [];
for (let chunk in chunksNeeded) { for (const chunk of chunksNeeded) {
chunk = chunk | 0; let requestIds = this._requestsByChunk.get(chunk);
if (!(chunk in this.requestsByChunk)) { if (!requestIds) {
this.requestsByChunk[chunk] = []; requestIds = [];
this._requestsByChunk.set(chunk, requestIds);
chunksToRequest.push(chunk); chunksToRequest.push(chunk);
} }
this.requestsByChunk[chunk].push(requestId); requestIds.push(requestId);
} }
if (!chunksToRequest.length) { if (!chunksToRequest.length) {
@ -522,16 +523,19 @@ class ChunkedStreamManager {
const loadedRequests = []; const loadedRequests = [];
for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) { for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
// The server might return more chunks than requested. // The server might return more chunks than requested.
const requestIds = this.requestsByChunk[curChunk] || []; const requestIds = this._requestsByChunk.get(curChunk);
delete this.requestsByChunk[curChunk]; if (!requestIds) {
continue;
}
this._requestsByChunk.delete(curChunk);
for (const requestId of requestIds) { for (const requestId of requestIds) {
const chunksNeeded = this.chunksNeededByRequest[requestId]; const chunksNeeded = this._chunksNeededByRequest.get(requestId);
if (curChunk in chunksNeeded) { if (chunksNeeded.has(curChunk)) {
delete chunksNeeded[curChunk]; chunksNeeded.delete(curChunk);
} }
if (!isEmptyObj(chunksNeeded)) { if (chunksNeeded.size > 0) {
continue; continue;
} }
loadedRequests.push(requestId); loadedRequests.push(requestId);
@ -540,7 +544,7 @@ class ChunkedStreamManager {
// If there are no pending requests, automatically fetch the next // If there are no pending requests, automatically fetch the next
// unfetched chunk of the PDF file. // unfetched chunk of the PDF file.
if (!this.disableAutoFetch && isEmptyObj(this.requestsByChunk)) { if (!this.disableAutoFetch && this._requestsByChunk.size === 0) {
let nextEmptyChunk; let nextEmptyChunk;
if (this.stream.numChunksLoaded === 1) { if (this.stream.numChunksLoaded === 1) {
// This is a special optimization so that after fetching the first // This is a special optimization so that after fetching the first
@ -559,8 +563,8 @@ class ChunkedStreamManager {
} }
for (const requestId of loadedRequests) { for (const requestId of loadedRequests) {
const capability = this.promisesByRequest[requestId]; const capability = this._promisesByRequest.get(requestId);
delete this.promisesByRequest[requestId]; this._promisesByRequest.delete(requestId);
capability.resolve(); capability.resolve();
} }
@ -587,8 +591,8 @@ class ChunkedStreamManager {
if (this.pdfNetworkStream) { if (this.pdfNetworkStream) {
this.pdfNetworkStream.cancelAllRequests(reason); this.pdfNetworkStream.cancelAllRequests(reason);
} }
for (const requestId in this.promisesByRequest) { for (const [, capability] of this._promisesByRequest) {
this.promisesByRequest[requestId].reject(reason); capability.reject(reason);
} }
} }
} }

View File

@ -793,13 +793,6 @@ function utf8StringToString(str) {
return unescape(encodeURIComponent(str)); return unescape(encodeURIComponent(str));
} }
function isEmptyObj(obj) {
for (const key in obj) {
return false;
}
return true;
}
function isBool(v) { function isBool(v) {
return typeof v === "boolean"; return typeof v === "boolean";
} }
@ -931,7 +924,6 @@ export {
isArrayBuffer, isArrayBuffer,
isArrayEqual, isArrayEqual,
isBool, isBool,
isEmptyObj,
isNum, isNum,
isString, isString,
isSameOrigin, isSameOrigin,

View File

@ -13,7 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { isEmptyObj } from "../../src/shared/util.js"; import { isEmptyObj } from "./test_utils.js";
import { Metadata } from "../../src/display/metadata.js"; import { Metadata } from "../../src/display/metadata.js";
describe("metadata", function () { describe("metadata", function () {

View File

@ -175,6 +175,14 @@ function createIdFactory(pageIndex) {
return page.idFactory; return page.idFactory;
} }
function isEmptyObj(obj) {
assert(
typeof obj === "object" && obj !== null,
"isEmptyObj - invalid argument."
);
return Object.keys(obj).length === 0;
}
export { export {
DOMFileReaderFactory, DOMFileReaderFactory,
NodeFileReaderFactory, NodeFileReaderFactory,
@ -184,4 +192,5 @@ export {
buildGetDocumentParams, buildGetDocumentParams,
TEST_PDFS_PATH, TEST_PDFS_PATH,
createIdFactory, createIdFactory,
isEmptyObj,
}; };

View File

@ -19,7 +19,6 @@ import {
createValidAbsoluteUrl, createValidAbsoluteUrl,
isArrayBuffer, isArrayBuffer,
isBool, isBool,
isEmptyObj,
isNum, isNum,
isSameOrigin, isSameOrigin,
isString, isString,
@ -89,16 +88,6 @@ describe("util", function () {
}); });
}); });
describe("isEmptyObj", function () {
it("handles empty objects", function () {
expect(isEmptyObj({})).toEqual(true);
});
it("handles non-empty objects", function () {
expect(isEmptyObj({ foo: "bar" })).toEqual(false);
});
});
describe("isNum", function () { describe("isNum", function () {
it("handles numeric values", function () { it("handles numeric values", function () {
expect(isNum(1)).toEqual(true); expect(isNum(1)).toEqual(true);