2017-02-24 07:35:35 +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.
|
|
|
|
*/
|
2019-10-13 18:33:41 +09:00
|
|
|
/* eslint no-var: error */
|
2018-02-18 07:51:24 +09:00
|
|
|
|
2019-11-10 23:10:18 +09:00
|
|
|
const { globalScope, } = require('./global_scope');
|
2017-02-24 07:35:35 +09:00
|
|
|
|
2019-10-13 18:33:41 +09:00
|
|
|
// Skip compatibility checks for modern builds and if we already ran the module.
|
|
|
|
if ((typeof PDFJSDev === 'undefined' || !PDFJSDev.test('SKIP_BABEL')) &&
|
2018-02-18 07:51:24 +09:00
|
|
|
!globalScope._pdfjsCompatibilityChecked) {
|
|
|
|
|
|
|
|
globalScope._pdfjsCompatibilityChecked = true;
|
2017-02-24 07:35:35 +09:00
|
|
|
|
2019-11-10 23:10:18 +09:00
|
|
|
const { isNodeJS, } = require('./is_node');
|
2017-02-24 07:35:35 +09:00
|
|
|
|
2018-02-17 20:57:15 +09:00
|
|
|
const hasDOM = typeof window === 'object' && typeof document === 'object';
|
2017-02-24 07:35:35 +09:00
|
|
|
|
2018-01-06 21:10:58 +09:00
|
|
|
// Support: Node.js
|
|
|
|
(function checkNodeBtoa() {
|
|
|
|
if (globalScope.btoa || !isNodeJS()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
globalScope.btoa = function(chars) {
|
|
|
|
// eslint-disable-next-line no-undef
|
|
|
|
return Buffer.from(chars, 'binary').toString('base64');
|
|
|
|
};
|
|
|
|
})();
|
|
|
|
|
|
|
|
// Support: Node.js
|
|
|
|
(function checkNodeAtob() {
|
|
|
|
if (globalScope.atob || !isNodeJS()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
globalScope.atob = function(input) {
|
|
|
|
// eslint-disable-next-line no-undef
|
|
|
|
return Buffer.from(input, 'base64').toString('binary');
|
|
|
|
};
|
|
|
|
})();
|
|
|
|
|
2017-02-24 07:35:35 +09:00
|
|
|
// Provides support for ChildNode.remove in legacy browsers.
|
|
|
|
// Support: IE.
|
|
|
|
(function checkChildNodeRemove() {
|
|
|
|
if (!hasDOM) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (typeof Element.prototype.remove !== 'undefined') {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Element.prototype.remove = function () {
|
|
|
|
if (this.parentNode) {
|
2018-02-11 00:19:45 +09:00
|
|
|
// eslint-disable-next-line mozilla/avoid-removeChild
|
2017-02-24 07:35:35 +09:00
|
|
|
this.parentNode.removeChild(this);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
})();
|
2018-02-04 22:31:59 +09:00
|
|
|
|
2019-02-08 21:31:14 +09:00
|
|
|
// Provides support for DOMTokenList.prototype.{add, remove}, with more than
|
|
|
|
// one parameter, in legacy browsers.
|
|
|
|
// Support: IE
|
|
|
|
(function checkDOMTokenListAddRemove() {
|
|
|
|
if (!hasDOM || isNodeJS()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const div = document.createElement('div');
|
|
|
|
div.classList.add('testOne', 'testTwo');
|
|
|
|
|
|
|
|
if (div.classList.contains('testOne') === true &&
|
|
|
|
div.classList.contains('testTwo') === true) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const OriginalDOMTokenListAdd = DOMTokenList.prototype.add;
|
|
|
|
const OriginalDOMTokenListRemove = DOMTokenList.prototype.remove;
|
|
|
|
|
|
|
|
DOMTokenList.prototype.add = function(...tokens) {
|
|
|
|
for (let token of tokens) {
|
|
|
|
OriginalDOMTokenListAdd.call(this, token);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
DOMTokenList.prototype.remove = function(...tokens) {
|
|
|
|
for (let token of tokens) {
|
|
|
|
OriginalDOMTokenListRemove.call(this, token);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
})();
|
|
|
|
|
2018-10-12 22:25:38 +09:00
|
|
|
// Provides support for DOMTokenList.prototype.toggle, with the optional
|
|
|
|
// "force" parameter, in legacy browsers.
|
|
|
|
// Support: IE
|
|
|
|
(function checkDOMTokenListToggle() {
|
|
|
|
if (!hasDOM || isNodeJS()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const div = document.createElement('div');
|
|
|
|
if (div.classList.toggle('test', 0) === false) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DOMTokenList.prototype.toggle = function(token) {
|
2019-02-08 21:31:14 +09:00
|
|
|
let force = (arguments.length > 1 ? !!arguments[1] : !this.contains(token));
|
|
|
|
return (this[force ? 'add' : 'remove'](token), force);
|
2018-10-12 22:25:38 +09:00
|
|
|
};
|
|
|
|
})();
|
|
|
|
|
2019-01-06 01:09:44 +09:00
|
|
|
// Provides support for String.prototype.startsWith in legacy browsers.
|
|
|
|
// Support: IE, Chrome<41
|
|
|
|
(function checkStringStartsWith() {
|
|
|
|
if (String.prototype.startsWith) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
require('core-js/es/string/starts-with');
|
2019-01-06 01:09:44 +09:00
|
|
|
})();
|
|
|
|
|
|
|
|
// Provides support for String.prototype.endsWith in legacy browsers.
|
|
|
|
// Support: IE, Chrome<41
|
|
|
|
(function checkStringEndsWith() {
|
|
|
|
if (String.prototype.endsWith) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
require('core-js/es/string/ends-with');
|
2019-01-06 01:09:44 +09:00
|
|
|
})();
|
|
|
|
|
2018-02-04 22:31:59 +09:00
|
|
|
// Provides support for String.prototype.includes in legacy browsers.
|
|
|
|
// Support: IE, Chrome<41
|
|
|
|
(function checkStringIncludes() {
|
|
|
|
if (String.prototype.includes) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
require('core-js/es/string/includes');
|
2018-02-04 22:31:59 +09:00
|
|
|
})();
|
2017-02-24 07:35:35 +09:00
|
|
|
|
2017-10-16 16:09:08 +09:00
|
|
|
// Provides support for Array.prototype.includes in legacy browsers.
|
2018-01-24 04:12:03 +09:00
|
|
|
// Support: IE, Chrome<47
|
2017-10-16 16:09:08 +09:00
|
|
|
(function checkArrayIncludes() {
|
|
|
|
if (Array.prototype.includes) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
require('core-js/es/array/includes');
|
2017-10-16 16:09:08 +09:00
|
|
|
})();
|
|
|
|
|
2019-01-20 16:49:20 +09:00
|
|
|
// Provides support for Array.from in legacy browsers.
|
|
|
|
// Support: IE
|
|
|
|
(function checkArrayFrom() {
|
|
|
|
if (Array.from) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
require('core-js/es/array/from');
|
2019-01-20 16:49:20 +09:00
|
|
|
})();
|
|
|
|
|
2018-06-11 02:59:03 +09:00
|
|
|
// Provides support for Object.assign in legacy browsers.
|
|
|
|
// Support: IE
|
|
|
|
(function checkObjectAssign() {
|
|
|
|
if (Object.assign) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
require('core-js/es/object/assign');
|
2018-06-11 02:59:03 +09:00
|
|
|
})();
|
|
|
|
|
2017-12-10 01:24:31 +09:00
|
|
|
// Provides support for Math.log2 in legacy browsers.
|
2018-01-24 04:12:03 +09:00
|
|
|
// Support: IE, Chrome<38
|
2017-12-10 01:24:31 +09:00
|
|
|
(function checkMathLog2() {
|
|
|
|
if (Math.log2) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
Math.log2 = require('core-js/es/math/log2');
|
2017-12-10 01:24:31 +09:00
|
|
|
})();
|
2017-10-16 16:09:08 +09:00
|
|
|
|
2017-07-13 18:48:17 +09:00
|
|
|
// Provides support for Number.isNaN in legacy browsers.
|
|
|
|
// Support: IE.
|
|
|
|
(function checkNumberIsNaN() {
|
|
|
|
if (Number.isNaN) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
Number.isNaN = require('core-js/es/number/is-nan');
|
2017-07-13 18:48:17 +09:00
|
|
|
})();
|
|
|
|
|
|
|
|
// Provides support for Number.isInteger in legacy browsers.
|
2018-01-24 04:12:03 +09:00
|
|
|
// Support: IE, Chrome<34
|
2017-07-13 18:48:17 +09:00
|
|
|
(function checkNumberIsInteger() {
|
|
|
|
if (Number.isInteger) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
Number.isInteger = require('core-js/es/number/is-integer');
|
2017-07-13 18:48:17 +09:00
|
|
|
})();
|
|
|
|
|
Fallback to the built-in font renderer when font loading fails
After PR 9340 all glyphs are now re-mapped to a Private Use Area (PUA) which means that if a font fails to load, for whatever reason[1], all glyphs in the font will now render as Unicode glyph outlines.
This obviously doesn't look good, to say the least, and might be seen as a "regression" since previously many glyphs were left in their original positions which provided a slightly better fallback[2].
Hence this patch, which implements a *general* fallback to the PDF.js built-in font renderer for fonts that fail to load (i.e. are rejected by the sanitizer). One caveat here is that this only works for the Font Loading API, since it's easy to handle errors in that case[3].
The solution implemented in this patch does *not* in any way delay the loading of valid fonts, which was the problem with my previous attempt at a solution, and will only require a bit of extra work/waiting for those fonts that actually fail to load.
*Please note:* This patch doesn't fix any of the underlying PDF.js font conversion bugs that's responsible for creating corrupt font files, however it does *improve* rendering in a number of cases; refer to this possibly incomplete list:
[Bug 1524888](https://bugzilla.mozilla.org/show_bug.cgi?id=1524888)
Issue 10175
Issue 10232
---
[1] Usually because the PDF.js font conversion code wasn't able to parse the font file correctly.
[2] Glyphs fell back to some default font, which while not accurate was more useful than the current state.
[3] Furthermore I'm not sure how to implement this generally, assuming that's even possible, and don't really have time/interest to look into it either.
2019-02-11 08:47:56 +09:00
|
|
|
// Support: IE, Safari<11, Chrome<63
|
2017-02-24 07:35:35 +09:00
|
|
|
(function checkPromise() {
|
Add a `gulp image_decoders` command to allow packaging/distributing the image decoders (i.e. jpg.js, jpx.js, jbig2.js) separately from the main PDF.js library
Please note that the standalone `pdf.image_decoders.js` file will be including the complete `src/shared/util.js` file, despite only using parts of it.[1] This was done *purposely*, to not negatively impact the readability/maintainability of the core PDF.js code.
Furthermore, to ensure that the compatibility is the same in the regular PDF.js library *and* in the the standalone image decoders, `src/shared/compatibility.js` was included as well.
To (hopefully) prevent future complaints about the size of the built `pdf.image_decoders.js` file, a few existing async-related polyfills are being skipped (since all of the image decoders are completely synchronous).
Obviously this required adding a couple of pre-processor statements, but given that these are all limited to "compatibility" code, I think this might be OK!?
---
[1] However, please note that previous commits moved `PageViewport` and `MessageHandler` out of `src/shared/util.js` which reduced its size.
2018-05-16 20:49:26 +09:00
|
|
|
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('IMAGE_DECODERS')) {
|
|
|
|
// The current image decoders are synchronous, hence `Promise` shouldn't
|
|
|
|
// need to be polyfilled for the IMAGE_DECODERS build target.
|
|
|
|
return;
|
|
|
|
}
|
Fallback to the built-in font renderer when font loading fails
After PR 9340 all glyphs are now re-mapped to a Private Use Area (PUA) which means that if a font fails to load, for whatever reason[1], all glyphs in the font will now render as Unicode glyph outlines.
This obviously doesn't look good, to say the least, and might be seen as a "regression" since previously many glyphs were left in their original positions which provided a slightly better fallback[2].
Hence this patch, which implements a *general* fallback to the PDF.js built-in font renderer for fonts that fail to load (i.e. are rejected by the sanitizer). One caveat here is that this only works for the Font Loading API, since it's easy to handle errors in that case[3].
The solution implemented in this patch does *not* in any way delay the loading of valid fonts, which was the problem with my previous attempt at a solution, and will only require a bit of extra work/waiting for those fonts that actually fail to load.
*Please note:* This patch doesn't fix any of the underlying PDF.js font conversion bugs that's responsible for creating corrupt font files, however it does *improve* rendering in a number of cases; refer to this possibly incomplete list:
[Bug 1524888](https://bugzilla.mozilla.org/show_bug.cgi?id=1524888)
Issue 10175
Issue 10232
---
[1] Usually because the PDF.js font conversion code wasn't able to parse the font file correctly.
[2] Glyphs fell back to some default font, which while not accurate was more useful than the current state.
[3] Furthermore I'm not sure how to implement this generally, assuming that's even possible, and don't really have time/interest to look into it either.
2019-02-11 08:47:56 +09:00
|
|
|
if (globalScope.Promise && (globalScope.Promise.prototype &&
|
|
|
|
globalScope.Promise.prototype.finally)) {
|
2017-02-24 07:35:35 +09:00
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
globalScope.Promise = require('core-js/es/promise/index');
|
2017-02-24 07:35:35 +09:00
|
|
|
})();
|
|
|
|
|
2019-09-15 23:43:50 +09:00
|
|
|
// Support: IE
|
|
|
|
(function checkURL() {
|
|
|
|
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('IMAGE_DECODERS')) {
|
|
|
|
// The current image decoders don't use the `URL` constructor, so it
|
|
|
|
// doesn't need to be polyfilled for the IMAGE_DECODERS build target.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (typeof PDFJSDev !== 'undefined' && !PDFJSDev.test('GENERIC')) {
|
|
|
|
// The `URL` constructor is assumed to be available in the extension builds.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
globalScope.URL = require('core-js/web/url');
|
|
|
|
})();
|
|
|
|
|
2018-01-24 04:12:03 +09:00
|
|
|
// Support: IE<11, Safari<8, Chrome<36
|
2017-02-24 07:35:35 +09:00
|
|
|
(function checkWeakMap() {
|
|
|
|
if (globalScope.WeakMap) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
globalScope.WeakMap = require('core-js/es/weak-map/index');
|
2017-02-24 07:35:35 +09:00
|
|
|
})();
|
|
|
|
|
2018-11-01 02:15:23 +09:00
|
|
|
// Support: IE11
|
|
|
|
(function checkWeakSet() {
|
|
|
|
if (globalScope.WeakSet) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
globalScope.WeakSet = require('core-js/es/weak-set/index');
|
2018-11-01 02:15:23 +09:00
|
|
|
})();
|
|
|
|
|
2018-01-05 07:43:07 +09:00
|
|
|
// Provides support for String.codePointAt in legacy browsers.
|
|
|
|
// Support: IE11.
|
|
|
|
(function checkStringCodePointAt() {
|
2019-08-17 06:32:43 +09:00
|
|
|
if (String.prototype.codePointAt) {
|
2018-01-05 07:43:07 +09:00
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
require('core-js/es/string/code-point-at');
|
2018-01-05 07:43:07 +09:00
|
|
|
})();
|
|
|
|
|
|
|
|
// Provides support for String.fromCodePoint in legacy browsers.
|
|
|
|
// Support: IE11.
|
|
|
|
(function checkStringFromCodePoint() {
|
|
|
|
if (String.fromCodePoint) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
String.fromCodePoint = require('core-js/es/string/from-code-point');
|
2018-01-05 07:43:07 +09:00
|
|
|
})();
|
|
|
|
|
2018-08-20 19:14:37 +09:00
|
|
|
// Support: IE
|
|
|
|
(function checkSymbol() {
|
|
|
|
if (globalScope.Symbol) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
require('core-js/es/symbol/index');
|
2018-08-20 19:14:37 +09:00
|
|
|
})();
|
|
|
|
|
2019-01-06 01:09:44 +09:00
|
|
|
// Provides support for String.prototype.padStart in legacy browsers.
|
|
|
|
// Support: IE, Chrome<57
|
|
|
|
(function checkStringPadStart() {
|
|
|
|
if (String.prototype.padStart) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
require('core-js/es/string/pad-start');
|
2019-01-06 01:09:44 +09:00
|
|
|
})();
|
|
|
|
|
|
|
|
// Provides support for String.prototype.padEnd in legacy browsers.
|
|
|
|
// Support: IE, Chrome<57
|
|
|
|
(function checkStringPadEnd() {
|
|
|
|
if (String.prototype.padEnd) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
require('core-js/es/string/pad-end');
|
2019-01-06 01:09:44 +09:00
|
|
|
})();
|
|
|
|
|
2018-01-26 20:18:57 +09:00
|
|
|
// Provides support for Object.values in legacy browsers.
|
|
|
|
// Support: IE, Chrome<54
|
|
|
|
(function checkObjectValues() {
|
|
|
|
if (Object.values) {
|
|
|
|
return;
|
|
|
|
}
|
2019-09-15 23:29:46 +09:00
|
|
|
Object.values = require('core-js/es/object/values');
|
2018-01-26 20:18:57 +09:00
|
|
|
})();
|
|
|
|
|
2017-02-24 07:35:35 +09:00
|
|
|
}
|