From 2d4a1aa0afc8265d360b72830fc9d8af5e0ba978 Mon Sep 17 00:00:00 2001
From: Jonas Jenwald <jonas.jenwald@gmail.com>
Date: Wed, 3 Feb 2016 14:29:20 +0100
Subject: [PATCH 1/2] Actually ignore no-op `setGState` (PR 5192 followup)

The intention of PR 5192 was to avoid adding empty `setGState` ops to the operatorList. But the patch accidentally used `>=`, which means that it's not actually working as intended, since empty arrays always have `length === 0`.
---
 src/core/evaluator.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/core/evaluator.js b/src/core/evaluator.js
index 224b23b99..bf9b05563 100644
--- a/src/core/evaluator.js
+++ b/src/core/evaluator.js
@@ -542,7 +542,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
         }
       }
       return promise.then(function () {
-        if (gStateObj.length >= 0) {
+        if (gStateObj.length > 0) {
           operatorList.addOp(OPS.setGState, [gStateObj]);
         }
       });

From a1fe2cb443963272cf5f3685098fd2b548b9059d Mon Sep 17 00:00:00 2001
From: Jonas Jenwald <jonas.jenwald@gmail.com>
Date: Wed, 3 Feb 2016 16:53:18 +0100
Subject: [PATCH 2/2] Don't directly access the private `map` in `setGState`,
 and ensure that we avoid indirect objects

*This patch is based on something I noticed while debugging some of the PDF files in issue 6931.*

In a number of the cases in `setGState`, we're implicitly assuming that we're not dealing with indirect objects (i.e. `Ref`s). See e.g. the 'Font' case, or the various cases where we simply do `gStateObj.push([key, value]);` (since the code in `canvas.js` won't be able to deal with a `Ref` for those cases).

The reason that I didn't use `Dict_forEach` instead, is that it would re-introduce the unncessary closures that PR 5205 removed.
---
 src/core/evaluator.js | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/core/evaluator.js b/src/core/evaluator.js
index bf9b05563..044cc7c1f 100644
--- a/src/core/evaluator.js
+++ b/src/core/evaluator.js
@@ -468,11 +468,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
                                                    xref, stateManager) {
       // This array holds the converted/processed state data.
       var gStateObj = [];
-      var gStateMap = gState.map;
+      var gStateKeys = gState.getKeys();
       var self = this;
       var promise = Promise.resolve();
-      for (var key in gStateMap) {
-        var value = gStateMap[key];
+      for (var i = 0, ii = gStateKeys.length; i < ii; i++) {
+        var key = gStateKeys[i];
+        var value = gState.get(key);
         switch (key) {
           case 'Type':
             break;
@@ -505,12 +506,11 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
               gStateObj.push([key, false]);
               break;
             }
-            var dict = xref.fetchIfRef(value);
-            if (isDict(dict)) {
-              promise = promise.then(function () {
+            if (isDict(value)) {
+              promise = promise.then(function (dict) {
                 return self.handleSMask(dict, resources, operatorList,
                                         task, stateManager);
-              });
+              }.bind(this, value));
               gStateObj.push([key, true]);
             } else {
               warn('Unsupported SMask type');