Reduce the number of function calls in the Dict class

The following changes were made:
 - Remove unnecessary `typeof` checks in the `get`/`getAsync` methods.
 - Reduce unnecessary code duplication in the `get`/`getAsync` methods.
 - Inline the `Ref` checks in the `get`/`getAsync`/`getArray` methods, since it helps avoid many unnecessary functions calls. I.e. this way it's possible to directly call `XRef.{fetch, fetchAsync)` only when necessary, rather than always having to call `XRef.{fetchIfRef, fetchIfRefAsync)`.

This patch was tested using the PDF file from issue 2618, i.e. http://bugzilla-attachments.gnome.org/attachment.cgi?id=226471, using the following manifest file:
```
[
    {  "id": "issue2618",
       "file": "../web/pdfs/issue2618.pdf",
       "md5": "",
       "rounds": 250,
       "type": "eq"
    }
]
```
This gave the following results when comparing this patch against the `master` branch:
```
-- Grouped By browser, stat --
browser | stat         | Count | Baseline(ms) | Current(ms) | +/- |    %  | Result(P<.05)
------- | ------------ | ----- | ------------ | ----------- | --- | ----- | -------------
Firefox | Overall      |   250 |         2821 |        2790 | -32 | -1.12 |        faster
Firefox | Page Request |   250 |            2 |           2 |   0 |  6.68 |
Firefox | Rendering    |   250 |         2820 |        2788 | -32 | -1.13 |        faster
```
This commit is contained in:
Jonas Jenwald 2019-09-22 13:16:38 +02:00
parent 44f4cd529d
commit 2cac68467f

View File

@ -81,59 +81,47 @@ var Dict = (function DictClosure() {
},
// automatically dereferences Ref objects
get: function Dict_get(key1, key2, key3) {
var value;
var xref = this.xref, suppressEncryption = this.suppressEncryption;
if (typeof (value = this._map[key1]) !== 'undefined' ||
key1 in this._map || typeof key2 === 'undefined') {
return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
get(key1, key2, key3) {
let value = this._map[key1];
if (value === undefined && !(key1 in this._map) && key2 !== undefined) {
value = this._map[key2];
if (value === undefined && !(key2 in this._map) && key3 !== undefined) {
value = this._map[key3];
}
}
if (typeof (value = this._map[key2]) !== 'undefined' ||
key2 in this._map || typeof key3 === 'undefined') {
return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
if (value instanceof Ref && this.xref) {
return this.xref.fetch(value, this.suppressEncryption);
}
value = this._map[key3];
return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
return value;
},
// Same as get(), but returns a promise and uses fetchIfRefAsync().
getAsync: function Dict_getAsync(key1, key2, key3) {
var value;
var xref = this.xref, suppressEncryption = this.suppressEncryption;
if (typeof (value = this._map[key1]) !== 'undefined' ||
key1 in this._map || typeof key2 === 'undefined') {
if (xref) {
return xref.fetchIfRefAsync(value, suppressEncryption);
async getAsync(key1, key2, key3) {
let value = this._map[key1];
if (value === undefined && !(key1 in this._map) && key2 !== undefined) {
value = this._map[key2];
if (value === undefined && !(key2 in this._map) && key3 !== undefined) {
value = this._map[key3];
}
return Promise.resolve(value);
}
if (typeof (value = this._map[key2]) !== 'undefined' ||
key2 in this._map || typeof key3 === 'undefined') {
if (xref) {
return xref.fetchIfRefAsync(value, suppressEncryption);
}
return Promise.resolve(value);
if (value instanceof Ref && this.xref) {
return this.xref.fetchAsync(value, this.suppressEncryption);
}
value = this._map[key3];
if (xref) {
return xref.fetchIfRefAsync(value, suppressEncryption);
}
return Promise.resolve(value);
return value;
},
// Same as get(), but dereferences all elements if the result is an Array.
getArray: function Dict_getArray(key1, key2, key3) {
var value = this.get(key1, key2, key3);
var xref = this.xref, suppressEncryption = this.suppressEncryption;
if (!Array.isArray(value) || !xref) {
getArray(key1, key2, key3) {
let value = this.get(key1, key2, key3);
if (!Array.isArray(value) || !this.xref) {
return value;
}
value = value.slice(); // Ensure that we don't modify the Dict data.
for (var i = 0, ii = value.length; i < ii; i++) {
if (!isRef(value[i])) {
for (let i = 0, ii = value.length; i < ii; i++) {
if (!(value[i] instanceof Ref)) {
continue;
}
value[i] = xref.fetch(value[i], suppressEncryption);
value[i] = this.xref.fetch(value[i], this.suppressEncryption);
}
return value;
},