From 4cb0c032f3753dcc82077551ced0d7f9da430187 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sun, 21 Jun 2020 16:42:39 +0200 Subject: [PATCH] Convert the `PDFPageProxy.intentStates` property from an `Object` to a `Map` As can be seen in the code there's a handful of places where this structure needs to be iterated, something that becomes cumbersome when dealing with `Object`s. Hence, by changing this to a `Map` instead we can both simplify the code and avoid creating unnecessary closures. Particularily the `PDFPageProxy._tryCleanup` method becomes a lot more readable, at least in my opinion. Finally, since this property is intended to be "private" the name is adjusted to reflect that. --- src/display/api.js | 60 +++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index 784995825..9c524809c 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -898,7 +898,7 @@ class PDFPageProxy { this.cleanupAfterRender = false; this.pendingCleanup = false; - this.intentStates = Object.create(null); + this._intentStates = new Map(); this.destroyed = false; } @@ -1003,10 +1003,11 @@ class PDFPageProxy { // this call to render. this.pendingCleanup = false; - if (!this.intentStates[renderingIntent]) { - this.intentStates[renderingIntent] = Object.create(null); + let intentState = this._intentStates.get(renderingIntent); + if (!intentState) { + intentState = Object.create(null); + this._intentStates.set(renderingIntent, intentState); } - const intentState = this.intentStates[renderingIntent]; // Ensure that a pending `streamReader` cancel timeout is always aborted. if (intentState.streamReaderCancelTimeout) { @@ -1128,14 +1129,15 @@ class PDFPageProxy { } const renderingIntent = "oplist"; - if (!this.intentStates[renderingIntent]) { - this.intentStates[renderingIntent] = Object.create(null); + let intentState = this._intentStates.get(renderingIntent); + if (!intentState) { + intentState = Object.create(null); + this._intentStates.set(renderingIntent, intentState); } - const intentState = this.intentStates[renderingIntent]; let opListTask; if (!intentState.opListReadCapability) { - opListTask = {}; + opListTask = Object.create(null); opListTask.operatorListChanged = operatorListChanged; intentState.opListReadCapability = createPromiseCapability(); intentState.renderTasks = []; @@ -1222,8 +1224,7 @@ class PDFPageProxy { this._transport.pageCache[this._pageIndex] = null; const waitOn = []; - Object.keys(this.intentStates).forEach(intent => { - const intentState = this.intentStates[intent]; + for (const [intent, intentState] of this._intentStates) { this._abortOperatorList({ intentState, reason: new Error("Page was destroyed."), @@ -1232,13 +1233,13 @@ class PDFPageProxy { if (intent === "oplist") { // Avoid errors below, since the renderTasks are just stubs. - return; + continue; } for (const internalRenderTask of intentState.renderTasks) { waitOn.push(internalRenderTask.completed); internalRenderTask.cancel(); } - }); + } this.objs.clear(); this.annotationsPromise = null; this.pendingCleanup = false; @@ -1261,22 +1262,16 @@ class PDFPageProxy { * @private */ _tryCleanup(resetStats = false) { - if ( - !this.pendingCleanup || - Object.keys(this.intentStates).some(intent => { - const intentState = this.intentStates[intent]; - return ( - intentState.renderTasks.length !== 0 || - !intentState.operatorList.lastChunk - ); - }) - ) { + if (!this.pendingCleanup) { return false; } + for (const { renderTasks, operatorList } of this._intentStates.values()) { + if (renderTasks.length !== 0 || !operatorList.lastChunk) { + return false; + } + } - Object.keys(this.intentStates).forEach(intent => { - delete this.intentStates[intent]; - }); + this._intentStates.clear(); this.objs.clear(); this.annotationsPromise = null; if (resetStats && this._stats) { @@ -1290,7 +1285,7 @@ class PDFPageProxy { * @private */ _startRenderPage(transparency, intent) { - const intentState = this.intentStates[intent]; + const intentState = this._intentStates.get(intent); if (!intentState) { return; // Rendering was cancelled. } @@ -1340,7 +1335,7 @@ class PDFPageProxy { ); const reader = readableStream.getReader(); - const intentState = this.intentStates[args.intent]; + const intentState = this._intentStates.get(args.intent); intentState.streamReader = reader; const pump = () => { @@ -1425,13 +1420,12 @@ class PDFPageProxy { } // Remove the current `intentState`, since a cancelled `getOperatorList` // call on the worker-thread cannot be re-started... - Object.keys(this.intentStates).some(intent => { - if (this.intentStates[intent] === intentState) { - delete this.intentStates[intent]; - return true; + for (const [intent, curIntentState] of this._intentStates) { + if (curIntentState === intentState) { + this._intentStates.delete(intent); + break; } - return false; - }); + } // ... and force clean-up to ensure that any old state is always removed. this.cleanup(); }