2017-01-10 01:40:57 +09:00
|
|
|
/* Copyright 2017 Mozilla Foundation
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
2012-05-11 06:11:27 +09:00
|
|
|
|
2020-01-02 20:00:16 +09:00
|
|
|
import { createIdFactory, XRefMock } from "./test_utils.js";
|
|
|
|
import { Dict, Name } from "../../src/core/primitives.js";
|
|
|
|
import { FormatError, OPS } from "../../src/shared/util.js";
|
|
|
|
import { Stream, StringStream } from "../../src/core/stream.js";
|
|
|
|
import { OperatorList } from "../../src/core/operator_list.js";
|
|
|
|
import { PartialEvaluator } from "../../src/core/evaluator.js";
|
|
|
|
import { WorkerTask } from "../../src/core/worker.js";
|
2017-01-10 01:40:57 +09:00
|
|
|
|
2020-04-14 19:28:14 +09:00
|
|
|
describe("evaluator", function () {
|
2012-05-11 06:11:27 +09:00
|
|
|
function HandlerMock() {
|
|
|
|
this.inputs = [];
|
|
|
|
}
|
|
|
|
HandlerMock.prototype = {
|
2017-04-28 20:40:47 +09:00
|
|
|
send(name, data) {
|
|
|
|
this.inputs.push({ name, data });
|
Fix inconsistent spacing and trailing commas in objects in `test/` files, so we can enable the `comma-dangle` and `object-curly-spacing` ESLint rules later on
http://eslint.org/docs/rules/comma-dangle
http://eslint.org/docs/rules/object-curly-spacing
Given that we currently have quite inconsistent object formatting, fixing this in *one* big patch probably wouldn't be feasible (since I cannot imagine anyone wanting to review that); hence I've opted to try and do this piecewise instead.
Please note: This patch was created automatically, using the ESLint `--fix` command line option. In a couple of places this caused lines to become too long, and I've fixed those manually; please refer to the interdiff below for the only hand-edits in this patch.
```diff
diff --git a/test/chromium/test-telemetry.js b/test/chromium/test-telemetry.js
index cc412a31..2e5bdfa1 100755
--- a/test/chromium/test-telemetry.js
+++ b/test/chromium/test-telemetry.js
@@ -324,7 +324,7 @@ var tests = [
var window = createExtensionGlobal();
telemetryScript.runInNewContext(window);
window.chrome.runtime.getManifest = function() {
- return { version: '1.0.1', };
+ return { version: '1.0.1', };
};
window.Date.test_now_value += 12 * 36E5;
telemetryScript.runInNewContext(window);
diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js
index 1f00747a..f22988e7 100644
--- a/test/unit/api_spec.js
+++ b/test/unit/api_spec.js
@@ -503,8 +503,9 @@ describe('api', function() {
it('gets destinations, from /Dests dictionary', function(done) {
var promise = doc.getDestinations();
promise.then(function(data) {
- expect(data).toEqual({ chapter1: [{ gen: 0, num: 17, }, { name: 'XYZ', },
- 0, 841.89, null], });
+ expect(data).toEqual({
+ chapter1: [{ gen: 0, num: 17, }, { name: 'XYZ', }, 0, 841.89, null],
+ });
done();
}).catch(function (reason) {
done.fail(reason);
diff --git a/test/unit/function_spec.js b/test/unit/function_spec.js
index 66441212..62127eb9 100644
--- a/test/unit/function_spec.js
+++ b/test/unit/function_spec.js
@@ -492,9 +492,11 @@ describe('function', function() {
it('check compiled mul', function() {
check([0.25, 0.5, 'mul'], [], [0, 1], [{ input: [], output: [0.125], }]);
check([0, 'mul'], [0, 1], [0, 1], [{ input: [0.25], output: [0], }]);
- check([0.5, 'mul'], [0, 1], [0, 1], [{ input: [0.25], output: [0.125], }]);
+ check([0.5, 'mul'], [0, 1], [0, 1],
+ [{ input: [0.25], output: [0.125], }]);
check([1, 'mul'], [0, 1], [0, 1], [{ input: [0.25], output: [0.25], }]);
- check([0, 'exch', 'mul'], [0, 1], [0, 1], [{ input: [0.25], output: [0], }]);
+ check([0, 'exch', 'mul'], [0, 1], [0, 1],
+ [{ input: [0.25], output: [0], }]);
check([0.5, 'exch', 'mul'], [0, 1], [0, 1],
[{ input: [0.25], output: [0.125], }]);
check([1, 'exch', 'mul'], [0, 1], [0, 1],
```
2017-06-02 19:55:01 +09:00
|
|
|
},
|
2012-05-11 06:11:27 +09:00
|
|
|
};
|
|
|
|
function ResourcesMock() {}
|
|
|
|
ResourcesMock.prototype = {
|
2017-04-28 20:40:47 +09:00
|
|
|
get(name) {
|
2012-05-11 06:11:27 +09:00
|
|
|
return this[name];
|
Fix inconsistent spacing and trailing commas in objects in `test/` files, so we can enable the `comma-dangle` and `object-curly-spacing` ESLint rules later on
http://eslint.org/docs/rules/comma-dangle
http://eslint.org/docs/rules/object-curly-spacing
Given that we currently have quite inconsistent object formatting, fixing this in *one* big patch probably wouldn't be feasible (since I cannot imagine anyone wanting to review that); hence I've opted to try and do this piecewise instead.
Please note: This patch was created automatically, using the ESLint `--fix` command line option. In a couple of places this caused lines to become too long, and I've fixed those manually; please refer to the interdiff below for the only hand-edits in this patch.
```diff
diff --git a/test/chromium/test-telemetry.js b/test/chromium/test-telemetry.js
index cc412a31..2e5bdfa1 100755
--- a/test/chromium/test-telemetry.js
+++ b/test/chromium/test-telemetry.js
@@ -324,7 +324,7 @@ var tests = [
var window = createExtensionGlobal();
telemetryScript.runInNewContext(window);
window.chrome.runtime.getManifest = function() {
- return { version: '1.0.1', };
+ return { version: '1.0.1', };
};
window.Date.test_now_value += 12 * 36E5;
telemetryScript.runInNewContext(window);
diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js
index 1f00747a..f22988e7 100644
--- a/test/unit/api_spec.js
+++ b/test/unit/api_spec.js
@@ -503,8 +503,9 @@ describe('api', function() {
it('gets destinations, from /Dests dictionary', function(done) {
var promise = doc.getDestinations();
promise.then(function(data) {
- expect(data).toEqual({ chapter1: [{ gen: 0, num: 17, }, { name: 'XYZ', },
- 0, 841.89, null], });
+ expect(data).toEqual({
+ chapter1: [{ gen: 0, num: 17, }, { name: 'XYZ', }, 0, 841.89, null],
+ });
done();
}).catch(function (reason) {
done.fail(reason);
diff --git a/test/unit/function_spec.js b/test/unit/function_spec.js
index 66441212..62127eb9 100644
--- a/test/unit/function_spec.js
+++ b/test/unit/function_spec.js
@@ -492,9 +492,11 @@ describe('function', function() {
it('check compiled mul', function() {
check([0.25, 0.5, 'mul'], [], [0, 1], [{ input: [], output: [0.125], }]);
check([0, 'mul'], [0, 1], [0, 1], [{ input: [0.25], output: [0], }]);
- check([0.5, 'mul'], [0, 1], [0, 1], [{ input: [0.25], output: [0.125], }]);
+ check([0.5, 'mul'], [0, 1], [0, 1],
+ [{ input: [0.25], output: [0.125], }]);
check([1, 'mul'], [0, 1], [0, 1], [{ input: [0.25], output: [0.25], }]);
- check([0, 'exch', 'mul'], [0, 1], [0, 1], [{ input: [0.25], output: [0], }]);
+ check([0, 'exch', 'mul'], [0, 1], [0, 1],
+ [{ input: [0.25], output: [0], }]);
check([0.5, 'exch', 'mul'], [0, 1], [0, 1],
[{ input: [0.25], output: [0.125], }]);
check([1, 'exch', 'mul'], [0, 1], [0, 1],
```
2017-06-02 19:55:01 +09:00
|
|
|
},
|
2012-05-11 06:11:27 +09:00
|
|
|
};
|
|
|
|
|
2021-04-18 02:47:56 +09:00
|
|
|
async function runOperatorListCheck(evaluator, stream, resources) {
|
|
|
|
const operatorList = new OperatorList();
|
2020-10-25 23:40:51 +09:00
|
|
|
const task = new WorkerTask("OperatorListCheck");
|
2021-04-18 02:47:56 +09:00
|
|
|
await evaluator.getOperatorList({
|
|
|
|
stream,
|
|
|
|
task,
|
|
|
|
resources,
|
|
|
|
operatorList,
|
|
|
|
});
|
|
|
|
return operatorList;
|
2014-05-10 10:21:15 +09:00
|
|
|
}
|
|
|
|
|
2020-10-25 23:40:51 +09:00
|
|
|
let partialEvaluator;
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
|
2021-04-11 03:21:31 +09:00
|
|
|
beforeAll(function () {
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
partialEvaluator = new PartialEvaluator({
|
2017-07-29 07:35:10 +09:00
|
|
|
xref: new XRefMock(),
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
handler: new HandlerMock(),
|
|
|
|
pageIndex: 0,
|
2019-04-20 19:36:49 +09:00
|
|
|
idFactory: createIdFactory(/* pageIndex = */ 0),
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-04-14 19:28:14 +09:00
|
|
|
afterAll(function () {
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
partialEvaluator = null;
|
|
|
|
});
|
|
|
|
|
2020-04-14 19:28:14 +09:00
|
|
|
describe("splitCombinedOperations", function () {
|
2021-04-18 02:47:56 +09:00
|
|
|
it("should reject unknown operations", async function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("fTT");
|
2021-04-18 02:47:56 +09:00
|
|
|
const result = await runOperatorListCheck(
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
partialEvaluator,
|
|
|
|
stream,
|
2021-04-18 02:47:56 +09:00
|
|
|
new ResourcesMock()
|
2014-05-10 10:21:15 +09:00
|
|
|
);
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
|
|
|
expect(result.fnArray.length).toEqual(1);
|
|
|
|
expect(result.fnArray[0]).toEqual(OPS.fill);
|
|
|
|
expect(result.argsArray[0]).toEqual(null);
|
2012-05-11 06:11:27 +09:00
|
|
|
});
|
|
|
|
|
2021-04-18 02:47:56 +09:00
|
|
|
it("should handle one operation", async function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("Q");
|
2021-04-18 02:47:56 +09:00
|
|
|
const result = await runOperatorListCheck(
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
partialEvaluator,
|
|
|
|
stream,
|
2021-04-18 02:47:56 +09:00
|
|
|
new ResourcesMock()
|
2014-05-10 10:21:15 +09:00
|
|
|
);
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
|
|
|
expect(result.fnArray.length).toEqual(1);
|
|
|
|
expect(result.fnArray[0]).toEqual(OPS.restore);
|
2012-05-11 06:11:27 +09:00
|
|
|
});
|
|
|
|
|
2021-04-18 02:47:56 +09:00
|
|
|
it("should handle two glued operations", async function () {
|
2020-07-12 23:34:05 +09:00
|
|
|
const imgDict = new Dict();
|
|
|
|
imgDict.set("Subtype", Name.get("Image"));
|
|
|
|
imgDict.set("Width", 1);
|
|
|
|
imgDict.set("Height", 1);
|
|
|
|
|
|
|
|
const imgStream = new Stream([0]);
|
|
|
|
imgStream.dict = imgDict;
|
|
|
|
|
|
|
|
const xObject = new Dict();
|
|
|
|
xObject.set("Res1", imgStream);
|
|
|
|
|
|
|
|
const resources = new ResourcesMock();
|
|
|
|
resources.XObject = xObject;
|
|
|
|
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("/Res1 DoQ");
|
2021-04-18 02:47:56 +09:00
|
|
|
const result = await runOperatorListCheck(
|
2020-11-29 17:59:03 +09:00
|
|
|
partialEvaluator,
|
|
|
|
stream,
|
2021-04-18 02:47:56 +09:00
|
|
|
resources
|
2020-11-29 17:59:03 +09:00
|
|
|
);
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(result.fnArray.length).toEqual(3);
|
|
|
|
expect(result.fnArray[0]).toEqual(OPS.dependency);
|
|
|
|
expect(result.fnArray[1]).toEqual(OPS.paintImageXObject);
|
|
|
|
expect(result.fnArray[2]).toEqual(OPS.restore);
|
|
|
|
expect(result.argsArray.length).toEqual(3);
|
|
|
|
expect(result.argsArray[0]).toEqual(["img_p0_1"]);
|
|
|
|
expect(result.argsArray[1]).toEqual(["img_p0_1", 1, 1]);
|
|
|
|
expect(result.argsArray[2]).toEqual(null);
|
2012-05-11 06:11:27 +09:00
|
|
|
});
|
|
|
|
|
2021-04-18 02:47:56 +09:00
|
|
|
it("should handle three glued operations", async function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("fff");
|
2021-04-18 02:47:56 +09:00
|
|
|
const result = await runOperatorListCheck(
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
partialEvaluator,
|
|
|
|
stream,
|
2021-04-18 02:47:56 +09:00
|
|
|
new ResourcesMock()
|
2014-05-10 10:21:15 +09:00
|
|
|
);
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
|
|
|
expect(result.fnArray.length).toEqual(3);
|
|
|
|
expect(result.fnArray[0]).toEqual(OPS.fill);
|
|
|
|
expect(result.fnArray[1]).toEqual(OPS.fill);
|
|
|
|
expect(result.fnArray[2]).toEqual(OPS.fill);
|
2012-05-11 06:11:27 +09:00
|
|
|
});
|
2012-05-21 03:44:03 +09:00
|
|
|
|
2021-04-18 02:47:56 +09:00
|
|
|
it("should handle three glued operations #2", async function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const resources = new ResourcesMock();
|
2012-05-21 03:44:03 +09:00
|
|
|
resources.Res1 = {};
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("B*Bf*");
|
2021-04-18 02:47:56 +09:00
|
|
|
const result = await runOperatorListCheck(
|
2020-11-29 17:59:03 +09:00
|
|
|
partialEvaluator,
|
|
|
|
stream,
|
2021-04-18 02:47:56 +09:00
|
|
|
resources
|
2020-11-29 17:59:03 +09:00
|
|
|
);
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
|
|
|
expect(result.fnArray.length).toEqual(3);
|
|
|
|
expect(result.fnArray[0]).toEqual(OPS.eoFillStroke);
|
|
|
|
expect(result.fnArray[1]).toEqual(OPS.fillStroke);
|
|
|
|
expect(result.fnArray[2]).toEqual(OPS.eoFill);
|
2012-05-21 03:44:03 +09:00
|
|
|
});
|
|
|
|
|
2021-04-18 02:47:56 +09:00
|
|
|
it("should handle glued operations and operands", async function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("f5 Ts");
|
2021-04-18 02:47:56 +09:00
|
|
|
const result = await runOperatorListCheck(
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
partialEvaluator,
|
|
|
|
stream,
|
2021-04-18 02:47:56 +09:00
|
|
|
new ResourcesMock()
|
2014-05-10 10:21:15 +09:00
|
|
|
);
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
|
|
|
expect(result.fnArray.length).toEqual(2);
|
|
|
|
expect(result.fnArray[0]).toEqual(OPS.fill);
|
|
|
|
expect(result.fnArray[1]).toEqual(OPS.setTextRise);
|
|
|
|
expect(result.argsArray.length).toEqual(2);
|
|
|
|
expect(result.argsArray[1].length).toEqual(1);
|
|
|
|
expect(result.argsArray[1][0]).toEqual(5);
|
2012-05-21 03:44:03 +09:00
|
|
|
});
|
2012-05-21 04:05:23 +09:00
|
|
|
|
2021-04-18 02:47:56 +09:00
|
|
|
it("should handle glued operations and literals", async function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("trueifalserinulln");
|
2021-04-18 02:47:56 +09:00
|
|
|
const result = await runOperatorListCheck(
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
partialEvaluator,
|
|
|
|
stream,
|
2021-04-18 02:47:56 +09:00
|
|
|
new ResourcesMock()
|
2014-05-10 10:21:15 +09:00
|
|
|
);
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
|
|
|
expect(result.fnArray.length).toEqual(3);
|
|
|
|
expect(result.fnArray[0]).toEqual(OPS.setFlatness);
|
|
|
|
expect(result.fnArray[1]).toEqual(OPS.setRenderingIntent);
|
|
|
|
expect(result.fnArray[2]).toEqual(OPS.endPath);
|
|
|
|
expect(result.argsArray.length).toEqual(3);
|
|
|
|
expect(result.argsArray[0].length).toEqual(1);
|
|
|
|
expect(result.argsArray[0][0]).toEqual(true);
|
|
|
|
expect(result.argsArray[1].length).toEqual(1);
|
|
|
|
expect(result.argsArray[1][0]).toEqual(false);
|
|
|
|
expect(result.argsArray[2]).toEqual(null);
|
2013-01-11 11:00:44 +09:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-04-14 19:28:14 +09:00
|
|
|
describe("validateNumberOfArgs", function () {
|
2021-04-18 02:47:56 +09:00
|
|
|
it("should execute if correct number of arguments", async function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("5 1 d0");
|
2021-04-18 02:47:56 +09:00
|
|
|
const result = await runOperatorListCheck(
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
partialEvaluator,
|
|
|
|
stream,
|
2021-04-18 02:47:56 +09:00
|
|
|
new ResourcesMock()
|
2014-05-10 10:21:15 +09:00
|
|
|
);
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(result.argsArray[0][0]).toEqual(5);
|
|
|
|
expect(result.argsArray[0][1]).toEqual(1);
|
|
|
|
expect(result.fnArray[0]).toEqual(OPS.setCharWidth);
|
2013-01-11 11:00:44 +09:00
|
|
|
});
|
2021-04-18 02:47:56 +09:00
|
|
|
|
|
|
|
it("should execute if too many arguments", async function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("5 1 4 d0");
|
2021-04-18 02:47:56 +09:00
|
|
|
const result = await runOperatorListCheck(
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
partialEvaluator,
|
|
|
|
stream,
|
2021-04-18 02:47:56 +09:00
|
|
|
new ResourcesMock()
|
2014-05-10 10:21:15 +09:00
|
|
|
);
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(result.argsArray[0][0]).toEqual(1);
|
|
|
|
expect(result.argsArray[0][1]).toEqual(4);
|
|
|
|
expect(result.fnArray[0]).toEqual(OPS.setCharWidth);
|
2013-01-11 11:00:44 +09:00
|
|
|
});
|
2021-04-18 02:47:56 +09:00
|
|
|
|
|
|
|
it("should execute if nested commands", async function () {
|
2020-07-11 20:52:11 +09:00
|
|
|
const gState = new Dict();
|
|
|
|
gState.set("LW", 2);
|
|
|
|
gState.set("CA", 0.5);
|
|
|
|
|
|
|
|
const extGState = new Dict();
|
|
|
|
extGState.set("GS2", gState);
|
|
|
|
|
|
|
|
const resources = new ResourcesMock();
|
|
|
|
resources.ExtGState = extGState;
|
|
|
|
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("/F2 /GS2 gs 5.711 Tf");
|
2021-04-18 02:47:56 +09:00
|
|
|
const result = await runOperatorListCheck(
|
2020-11-29 17:59:03 +09:00
|
|
|
partialEvaluator,
|
|
|
|
stream,
|
2021-04-18 02:47:56 +09:00
|
|
|
resources
|
2020-11-29 17:59:03 +09:00
|
|
|
);
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(result.fnArray.length).toEqual(3);
|
|
|
|
expect(result.fnArray[0]).toEqual(OPS.setGState);
|
|
|
|
expect(result.fnArray[1]).toEqual(OPS.dependency);
|
|
|
|
expect(result.fnArray[2]).toEqual(OPS.setFont);
|
|
|
|
expect(result.argsArray.length).toEqual(3);
|
|
|
|
expect(result.argsArray[0]).toEqual([
|
|
|
|
[
|
|
|
|
["LW", 2],
|
|
|
|
["CA", 0.5],
|
|
|
|
],
|
|
|
|
]);
|
|
|
|
expect(result.argsArray[1]).toEqual(["g_font_error"]);
|
|
|
|
expect(result.argsArray[2]).toEqual(["g_font_error", 5.711]);
|
2014-05-15 15:07:43 +09:00
|
|
|
});
|
2021-04-18 02:47:56 +09:00
|
|
|
|
|
|
|
it("should skip if too few arguments", async function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("5 d0");
|
2021-04-18 02:47:56 +09:00
|
|
|
const result = await runOperatorListCheck(
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
partialEvaluator,
|
|
|
|
stream,
|
2021-04-18 02:47:56 +09:00
|
|
|
new ResourcesMock()
|
2014-05-10 10:21:15 +09:00
|
|
|
);
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(result.argsArray).toEqual([]);
|
|
|
|
expect(result.fnArray).toEqual([]);
|
2012-05-21 04:05:23 +09:00
|
|
|
});
|
Error, rather than warn, once a number of invalid path operators are encountered in `EvaluatorPreprocessor.read` (bug 1443140)
Incomplete path operators, in particular, can result in fairly chaotic rendering artifacts, as can be observed on page four of the referenced PDF file.
The initial (naive) solution that was attempted, was to simply throw a `FormatError` as soon as any invalid (i.e. too short) operator was found and rely on the existing `ignoreErrors` code-paths. However, doing so would have caused regressions in some files; see the existing `issue2391-1` test-case, which was promoted to an `eq` test to help prevent future bugs.
Hence this patch, which adds special handling for invalid path operators since those may cause quite bad rendering artifacts.
You could, in all fairness, argue that the patch is a handwavy solution and I wouldn't object. However, given that this only concerns *corrupt* PDF files, the way that PDF viewers (PDF.js included) try to gracefully deal with those could probably be described as a best-effort solution anyway.
This patch also adjusts the existing `warn`/`info` messages to print the command name according to the PDF specification, rather than an internal PDF.js enumeration value. The former should be much more useful for debugging purposes.
Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1443140.
2018-06-24 16:53:32 +09:00
|
|
|
|
|
|
|
it(
|
|
|
|
"should error if (many) path operators have too few arguments " +
|
|
|
|
"(bug 1443140)",
|
2021-04-18 02:47:56 +09:00
|
|
|
async function () {
|
Error, rather than warn, once a number of invalid path operators are encountered in `EvaluatorPreprocessor.read` (bug 1443140)
Incomplete path operators, in particular, can result in fairly chaotic rendering artifacts, as can be observed on page four of the referenced PDF file.
The initial (naive) solution that was attempted, was to simply throw a `FormatError` as soon as any invalid (i.e. too short) operator was found and rely on the existing `ignoreErrors` code-paths. However, doing so would have caused regressions in some files; see the existing `issue2391-1` test-case, which was promoted to an `eq` test to help prevent future bugs.
Hence this patch, which adds special handling for invalid path operators since those may cause quite bad rendering artifacts.
You could, in all fairness, argue that the patch is a handwavy solution and I wouldn't object. However, given that this only concerns *corrupt* PDF files, the way that PDF viewers (PDF.js included) try to gracefully deal with those could probably be described as a best-effort solution anyway.
This patch also adjusts the existing `warn`/`info` messages to print the command name according to the PDF specification, rather than an internal PDF.js enumeration value. The former should be much more useful for debugging purposes.
Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1443140.
2018-06-24 16:53:32 +09:00
|
|
|
const NUM_INVALID_OPS = 25;
|
|
|
|
|
|
|
|
// Non-path operators, should be ignored.
|
2022-03-30 22:38:07 +09:00
|
|
|
const invalidMoveText = "10 Td\n".repeat(NUM_INVALID_OPS);
|
Error, rather than warn, once a number of invalid path operators are encountered in `EvaluatorPreprocessor.read` (bug 1443140)
Incomplete path operators, in particular, can result in fairly chaotic rendering artifacts, as can be observed on page four of the referenced PDF file.
The initial (naive) solution that was attempted, was to simply throw a `FormatError` as soon as any invalid (i.e. too short) operator was found and rely on the existing `ignoreErrors` code-paths. However, doing so would have caused regressions in some files; see the existing `issue2391-1` test-case, which was promoted to an `eq` test to help prevent future bugs.
Hence this patch, which adds special handling for invalid path operators since those may cause quite bad rendering artifacts.
You could, in all fairness, argue that the patch is a handwavy solution and I wouldn't object. However, given that this only concerns *corrupt* PDF files, the way that PDF viewers (PDF.js included) try to gracefully deal with those could probably be described as a best-effort solution anyway.
This patch also adjusts the existing `warn`/`info` messages to print the command name according to the PDF specification, rather than an internal PDF.js enumeration value. The former should be much more useful for debugging purposes.
Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1443140.
2018-06-24 16:53:32 +09:00
|
|
|
const moveTextStream = new StringStream(invalidMoveText);
|
2021-04-18 02:47:56 +09:00
|
|
|
const result = await runOperatorListCheck(
|
Error, rather than warn, once a number of invalid path operators are encountered in `EvaluatorPreprocessor.read` (bug 1443140)
Incomplete path operators, in particular, can result in fairly chaotic rendering artifacts, as can be observed on page four of the referenced PDF file.
The initial (naive) solution that was attempted, was to simply throw a `FormatError` as soon as any invalid (i.e. too short) operator was found and rely on the existing `ignoreErrors` code-paths. However, doing so would have caused regressions in some files; see the existing `issue2391-1` test-case, which was promoted to an `eq` test to help prevent future bugs.
Hence this patch, which adds special handling for invalid path operators since those may cause quite bad rendering artifacts.
You could, in all fairness, argue that the patch is a handwavy solution and I wouldn't object. However, given that this only concerns *corrupt* PDF files, the way that PDF viewers (PDF.js included) try to gracefully deal with those could probably be described as a best-effort solution anyway.
This patch also adjusts the existing `warn`/`info` messages to print the command name according to the PDF specification, rather than an internal PDF.js enumeration value. The former should be much more useful for debugging purposes.
Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1443140.
2018-06-24 16:53:32 +09:00
|
|
|
partialEvaluator,
|
|
|
|
moveTextStream,
|
2021-04-18 02:47:56 +09:00
|
|
|
new ResourcesMock()
|
Error, rather than warn, once a number of invalid path operators are encountered in `EvaluatorPreprocessor.read` (bug 1443140)
Incomplete path operators, in particular, can result in fairly chaotic rendering artifacts, as can be observed on page four of the referenced PDF file.
The initial (naive) solution that was attempted, was to simply throw a `FormatError` as soon as any invalid (i.e. too short) operator was found and rely on the existing `ignoreErrors` code-paths. However, doing so would have caused regressions in some files; see the existing `issue2391-1` test-case, which was promoted to an `eq` test to help prevent future bugs.
Hence this patch, which adds special handling for invalid path operators since those may cause quite bad rendering artifacts.
You could, in all fairness, argue that the patch is a handwavy solution and I wouldn't object. However, given that this only concerns *corrupt* PDF files, the way that PDF viewers (PDF.js included) try to gracefully deal with those could probably be described as a best-effort solution anyway.
This patch also adjusts the existing `warn`/`info` messages to print the command name according to the PDF specification, rather than an internal PDF.js enumeration value. The former should be much more useful for debugging purposes.
Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1443140.
2018-06-24 16:53:32 +09:00
|
|
|
);
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(result.argsArray).toEqual([]);
|
|
|
|
expect(result.fnArray).toEqual([]);
|
Error, rather than warn, once a number of invalid path operators are encountered in `EvaluatorPreprocessor.read` (bug 1443140)
Incomplete path operators, in particular, can result in fairly chaotic rendering artifacts, as can be observed on page four of the referenced PDF file.
The initial (naive) solution that was attempted, was to simply throw a `FormatError` as soon as any invalid (i.e. too short) operator was found and rely on the existing `ignoreErrors` code-paths. However, doing so would have caused regressions in some files; see the existing `issue2391-1` test-case, which was promoted to an `eq` test to help prevent future bugs.
Hence this patch, which adds special handling for invalid path operators since those may cause quite bad rendering artifacts.
You could, in all fairness, argue that the patch is a handwavy solution and I wouldn't object. However, given that this only concerns *corrupt* PDF files, the way that PDF viewers (PDF.js included) try to gracefully deal with those could probably be described as a best-effort solution anyway.
This patch also adjusts the existing `warn`/`info` messages to print the command name according to the PDF specification, rather than an internal PDF.js enumeration value. The former should be much more useful for debugging purposes.
Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1443140.
2018-06-24 16:53:32 +09:00
|
|
|
|
|
|
|
// Path operators, should throw error.
|
2022-03-30 22:38:07 +09:00
|
|
|
const invalidLineTo = "20 l\n".repeat(NUM_INVALID_OPS);
|
Error, rather than warn, once a number of invalid path operators are encountered in `EvaluatorPreprocessor.read` (bug 1443140)
Incomplete path operators, in particular, can result in fairly chaotic rendering artifacts, as can be observed on page four of the referenced PDF file.
The initial (naive) solution that was attempted, was to simply throw a `FormatError` as soon as any invalid (i.e. too short) operator was found and rely on the existing `ignoreErrors` code-paths. However, doing so would have caused regressions in some files; see the existing `issue2391-1` test-case, which was promoted to an `eq` test to help prevent future bugs.
Hence this patch, which adds special handling for invalid path operators since those may cause quite bad rendering artifacts.
You could, in all fairness, argue that the patch is a handwavy solution and I wouldn't object. However, given that this only concerns *corrupt* PDF files, the way that PDF viewers (PDF.js included) try to gracefully deal with those could probably be described as a best-effort solution anyway.
This patch also adjusts the existing `warn`/`info` messages to print the command name according to the PDF specification, rather than an internal PDF.js enumeration value. The former should be much more useful for debugging purposes.
Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1443140.
2018-06-24 16:53:32 +09:00
|
|
|
const lineToStream = new StringStream(invalidLineTo);
|
2021-04-18 02:47:56 +09:00
|
|
|
|
|
|
|
try {
|
|
|
|
await runOperatorListCheck(
|
|
|
|
partialEvaluator,
|
|
|
|
lineToStream,
|
|
|
|
new ResourcesMock()
|
|
|
|
);
|
|
|
|
|
|
|
|
// Shouldn't get here.
|
|
|
|
expect(false).toEqual(true);
|
|
|
|
} catch (reason) {
|
|
|
|
expect(reason instanceof FormatError).toEqual(true);
|
|
|
|
expect(reason.message).toEqual(
|
|
|
|
"Invalid command l: expected 2 args, but received 1 args."
|
|
|
|
);
|
|
|
|
}
|
Error, rather than warn, once a number of invalid path operators are encountered in `EvaluatorPreprocessor.read` (bug 1443140)
Incomplete path operators, in particular, can result in fairly chaotic rendering artifacts, as can be observed on page four of the referenced PDF file.
The initial (naive) solution that was attempted, was to simply throw a `FormatError` as soon as any invalid (i.e. too short) operator was found and rely on the existing `ignoreErrors` code-paths. However, doing so would have caused regressions in some files; see the existing `issue2391-1` test-case, which was promoted to an `eq` test to help prevent future bugs.
Hence this patch, which adds special handling for invalid path operators since those may cause quite bad rendering artifacts.
You could, in all fairness, argue that the patch is a handwavy solution and I wouldn't object. However, given that this only concerns *corrupt* PDF files, the way that PDF viewers (PDF.js included) try to gracefully deal with those could probably be described as a best-effort solution anyway.
This patch also adjusts the existing `warn`/`info` messages to print the command name according to the PDF specification, rather than an internal PDF.js enumeration value. The former should be much more useful for debugging purposes.
Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1443140.
2018-06-24 16:53:32 +09:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2021-04-18 02:47:56 +09:00
|
|
|
it("should close opened saves", async function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("qq");
|
2021-04-18 02:47:56 +09:00
|
|
|
const result = await runOperatorListCheck(
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
partialEvaluator,
|
|
|
|
stream,
|
2021-04-18 02:47:56 +09:00
|
|
|
new ResourcesMock()
|
2014-05-10 10:21:15 +09:00
|
|
|
);
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
|
|
|
expect(result.fnArray.length).toEqual(4);
|
|
|
|
expect(result.fnArray[0]).toEqual(OPS.save);
|
|
|
|
expect(result.fnArray[1]).toEqual(OPS.save);
|
|
|
|
expect(result.fnArray[2]).toEqual(OPS.restore);
|
|
|
|
expect(result.fnArray[3]).toEqual(OPS.restore);
|
2014-01-17 22:16:52 +09:00
|
|
|
});
|
2021-04-18 02:47:56 +09:00
|
|
|
|
|
|
|
it("should error on paintXObject if name is missing", async function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("/ Do");
|
2021-04-18 02:47:56 +09:00
|
|
|
|
|
|
|
try {
|
|
|
|
await runOperatorListCheck(
|
|
|
|
partialEvaluator,
|
|
|
|
stream,
|
|
|
|
new ResourcesMock()
|
|
|
|
);
|
|
|
|
|
|
|
|
// Shouldn't get here.
|
|
|
|
expect(false).toEqual(true);
|
|
|
|
} catch (reason) {
|
|
|
|
expect(reason instanceof FormatError).toEqual(true);
|
2021-06-22 22:44:52 +09:00
|
|
|
expect(reason.message).toEqual("XObject should be a stream");
|
2021-04-18 02:47:56 +09:00
|
|
|
}
|
2015-06-22 20:33:15 +09:00
|
|
|
});
|
2021-04-18 02:47:56 +09:00
|
|
|
|
|
|
|
it("should skip paintXObject if subtype is PS", async function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const xobjStreamDict = new Dict();
|
2015-08-30 01:21:00 +09:00
|
|
|
xobjStreamDict.set("Subtype", Name.get("PS"));
|
2020-10-25 23:40:51 +09:00
|
|
|
const xobjStream = new Stream([], 0, 0, xobjStreamDict);
|
2015-08-30 01:21:00 +09:00
|
|
|
|
2020-10-25 23:40:51 +09:00
|
|
|
const xobjs = new Dict();
|
2015-08-30 01:21:00 +09:00
|
|
|
xobjs.set("Res1", xobjStream);
|
|
|
|
|
2020-10-25 23:40:51 +09:00
|
|
|
const resources = new Dict();
|
2015-08-30 01:21:00 +09:00
|
|
|
resources.set("XObject", xobjs);
|
|
|
|
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("/Res1 Do");
|
2021-04-18 02:47:56 +09:00
|
|
|
const result = await runOperatorListCheck(
|
2020-11-29 17:59:03 +09:00
|
|
|
partialEvaluator,
|
|
|
|
stream,
|
2021-04-18 02:47:56 +09:00
|
|
|
resources
|
2020-11-29 17:59:03 +09:00
|
|
|
);
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(result.argsArray).toEqual([]);
|
|
|
|
expect(result.fnArray).toEqual([]);
|
2015-08-30 01:21:00 +09:00
|
|
|
});
|
2012-05-11 06:11:27 +09:00
|
|
|
});
|
2015-10-21 10:50:32 +09:00
|
|
|
|
2020-04-14 19:28:14 +09:00
|
|
|
describe("thread control", function () {
|
2021-04-18 02:47:56 +09:00
|
|
|
it("should abort operator list parsing", async function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const stream = new StringStream("qqQQ");
|
|
|
|
const resources = new ResourcesMock();
|
|
|
|
const result = new OperatorList();
|
|
|
|
const task = new WorkerTask("OperatorListAbort");
|
2016-03-29 23:34:13 +09:00
|
|
|
task.terminate();
|
2021-04-18 02:47:56 +09:00
|
|
|
|
|
|
|
try {
|
|
|
|
await partialEvaluator.getOperatorList({
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
stream,
|
|
|
|
task,
|
|
|
|
resources,
|
|
|
|
operatorList: result,
|
|
|
|
});
|
2021-04-18 02:47:56 +09:00
|
|
|
|
|
|
|
// Shouldn't get here.
|
|
|
|
expect(false).toEqual(true);
|
2023-06-12 18:46:11 +09:00
|
|
|
} catch {
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
|
|
|
expect(result.fnArray.length).toEqual(0);
|
|
|
|
}
|
2015-10-21 10:50:32 +09:00
|
|
|
});
|
2021-04-18 02:47:56 +09:00
|
|
|
|
|
|
|
it("should abort text content parsing", async function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const resources = new ResourcesMock();
|
|
|
|
const stream = new StringStream("qqQQ");
|
|
|
|
const task = new WorkerTask("TextContentAbort");
|
2016-03-29 23:34:13 +09:00
|
|
|
task.terminate();
|
2021-04-18 02:47:56 +09:00
|
|
|
|
|
|
|
try {
|
|
|
|
await partialEvaluator.getTextContent({
|
Change the signatures of the `PartialEvaluator` "constructor" and its `getOperatorList`/`getTextContent` methods to take parameter objects
Currently these methods accept a large number of parameters, which creates quite unwieldy call-sites. When invoking them, you have to remember not only what arguments to supply, but also the correct order, to avoid runtime errors.
Furthermore, since some of the parameters are optional, you also have to remember to pass e.g. `null` or `undefined` for those ones.
Also, adding new parameters to these methods (which happens occasionally), often becomes unnecessarily tedious (based on personal experience).
Please note that I do *not* think that we need/should convert *every* single method in `evaluator.js` (or elsewhere in `/core` files) to take parameter objects. However, in my opinion, once a method starts relying on approximately five parameter (or even more), passing them in individually becomes quite cumbersome.
With these changes, I obviously needed to update the `evaluator_spec.js` unit-tests. The main change there, except the new method signatures[1], is that it's now re-using *one* `PartialEvalutor` instance, since I couldn't see any compelling reason for creating a new one in every single test.
*Note:* If this patch is accepted, my intention is to (time permitting) see if it makes sense to convert additional methods in `evaluator.js` (and other `/core` files) in a similar fashion, but I figured that it'd be a good idea to limit the initial scope somewhat.
---
[1] A fun fact here, note how the `PartialEvaluator` signature used in `evaluator_spec.js` wasn't even correct in the current `master`.
2017-04-30 06:13:51 +09:00
|
|
|
stream,
|
|
|
|
task,
|
|
|
|
resources,
|
|
|
|
});
|
2021-04-18 02:47:56 +09:00
|
|
|
|
|
|
|
// Shouldn't get here.
|
|
|
|
expect(false).toEqual(true);
|
2023-06-12 18:46:11 +09:00
|
|
|
} catch {
|
2021-04-18 02:47:56 +09:00
|
|
|
expect(true).toEqual(true);
|
|
|
|
}
|
2015-10-21 10:50:32 +09:00
|
|
|
});
|
|
|
|
});
|
2015-10-27 00:38:06 +09:00
|
|
|
|
2020-04-14 19:28:14 +09:00
|
|
|
describe("operator list", function () {
|
Use streams for OperatorList chunking (issue 10023)
*Please note:* The majority of this patch was written by Yury, and it's simply been rebased and slightly extended to prevent issues when dealing with `RenderingCancelledException`.
By leveraging streams this (finally) provides a simple way in which parsing can be aborted on the worker-thread, which will ultimately help save resources.
With this patch worker-thread parsing will *only* be aborted when the document is destroyed, and not when rendering is cancelled. There's a couple of reasons for this:
- The API currently expects the *entire* OperatorList to be extracted, or an Error to occur, once it's been started. Hence additional re-factoring/re-writing of the API code will be necessary to properly support cancelling and re-starting of OperatorList parsing in cases where the `lastChunk` hasn't yet been seen.
- Even with the above addressed, immediately cancelling when encountering a `RenderingCancelledException` will lead to worse performance in e.g. the default viewer. When zooming and/or rotation of the document occurs it's very likely that `cancel` will be (almost) immediately followed by a new `render` call. In that case you'd obviously *not* want to abort parsing on the worker-thread, since then you'd risk throwing away a partially parsed Page and thus be forced to re-parse it again which will regress perceived performance.
- This patch is already *somewhat* risky, given that it touches fundamentally important/critical code, and trying to keep it somewhat small should hopefully reduce the risk of regressions (and simplify reviewing as well).
Time permitting, once this has landed and been in Nightly for awhile, I'll try to work on the remaining points outlined above.
Co-Authored-By: Yury Delendik <ydelendik@mozilla.com>
Co-Authored-By: Jonas Jenwald <jonas.jenwald@gmail.com>
2017-11-10 10:58:43 +09:00
|
|
|
class StreamSinkMock {
|
|
|
|
enqueue() {}
|
|
|
|
}
|
2015-10-27 00:38:06 +09:00
|
|
|
|
2020-04-14 19:28:14 +09:00
|
|
|
it("should get correct total length after flushing", function () {
|
2020-10-25 23:40:51 +09:00
|
|
|
const operatorList = new OperatorList(null, new StreamSinkMock());
|
2015-10-27 00:38:06 +09:00
|
|
|
operatorList.addOp(OPS.save, null);
|
|
|
|
operatorList.addOp(OPS.restore, null);
|
|
|
|
|
|
|
|
expect(operatorList.totalLength).toEqual(2);
|
|
|
|
expect(operatorList.length).toEqual(2);
|
|
|
|
|
|
|
|
operatorList.flush();
|
|
|
|
|
|
|
|
expect(operatorList.totalLength).toEqual(2);
|
|
|
|
expect(operatorList.length).toEqual(0);
|
|
|
|
});
|
|
|
|
});
|
2012-05-11 06:11:27 +09:00
|
|
|
});
|