diff --git a/README.md b/README.md
index 060fb42..be632b1 100755
--- a/README.md
+++ b/README.md
@@ -7,7 +7,11 @@
- [Mozilla Firefox](https://www.mozilla.org/ru/firefox/new/) (v43+). Начиная с версии 52, с [расширением](https://www.cryptopro.ru/sites/default/files/products/cades/extensions/cryptopro_extension_for_cades_browser_plug_in-1.1.1-an+fx-windows.xpi).
- [Internet Explorer](http://windows.microsoft.com/ru-ru/internet-explorer/download-ie) (v8+).
-Полифилл для Promise необходимо подключать самостоятельно.
+Список необходимых полифиллов (подключаются самостоятельно):
+- Promise
+- EventTarget.addEventListener
+- Array.prototype.forEach
+- Array.prototype.map
## Установка и настройка
```bash
diff --git a/example/index.html b/example/index.html
index 37c3149..0f03004 100755
--- a/example/index.html
+++ b/example/index.html
@@ -3,7 +3,6 @@
Пример использования CryptoPro
-
@@ -16,7 +15,20 @@
publicPath: '../dist/'
};
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/polyfills/addEventListener.js b/example/polyfills/addEventListener.js
new file mode 100644
index 0000000..c38f96d
--- /dev/null
+++ b/example/polyfills/addEventListener.js
@@ -0,0 +1,32 @@
+!window.addEventListener && (function (WindowPrototype, DocumentPrototype, ElementPrototype, addEventListener, removeEventListener, dispatchEvent, registry) {
+ WindowPrototype[addEventListener] = DocumentPrototype[addEventListener] = ElementPrototype[addEventListener] = function (type, listener) {
+ var target = this;
+
+ registry.unshift([target, type, listener, function (event) {
+ event.currentTarget = target;
+ event.preventDefault = function () {
+ event.returnValue = false
+ };
+ event.stopPropagation = function () {
+ event.cancelBubble = true
+ };
+ event.target = event.srcElement || target;
+
+ listener.call(target, event);
+ }]);
+
+ this.attachEvent("on" + type, registry[0][3]);
+ };
+
+ WindowPrototype[removeEventListener] = DocumentPrototype[removeEventListener] = ElementPrototype[removeEventListener] = function (type, listener) {
+ for (var index = 0, register; register = registry[index]; ++index) {
+ if (register[0] == this && register[1] == type && register[2] == listener) {
+ return this.detachEvent("on" + type, registry.splice(index, 1)[0][3]);
+ }
+ }
+ };
+
+ WindowPrototype[dispatchEvent] = DocumentPrototype[dispatchEvent] = ElementPrototype[dispatchEvent] = function (eventObject) {
+ return this.fireEvent("on" + eventObject.type, eventObject);
+ };
+})(Window.prototype, HTMLDocument.prototype, Element.prototype, "addEventListener", "removeEventListener", "dispatchEvent", []);
\ No newline at end of file
diff --git a/example/polyfills/atob-btoa.js b/example/polyfills/atob-btoa.js
new file mode 100644
index 0000000..43d9b10
--- /dev/null
+++ b/example/polyfills/atob-btoa.js
@@ -0,0 +1,76 @@
+(function (root, factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module.
+ define([], function () {
+ factory(root);
+ });
+ } else factory(root);
+// node.js has always supported base64 conversions, while browsers that support
+// web workers support base64 too, but you may never know.
+})(typeof exports !== "undefined" ? exports : this, function (root) {
+ if (root.atob) {
+ // Some browsers' implementation of atob doesn't support whitespaces
+ // in the encoded string (notably, IE). This wraps the native atob
+ // in a function that strips the whitespaces.
+ // The original function can be retrieved in atob.original
+ try {
+ root.atob(" ");
+ } catch (e) {
+ root.atob = (function (atob) {
+ var func = function (string) {
+ return atob(String(string).replace(/[\t\n\f\r ]+/g, ""));
+ };
+ func.original = atob;
+ return func;
+ })(root.atob);
+ }
+ return;
+ }
+
+ // base64 character set, plus padding character (=)
+ var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
+ // Regular expression to check formal correctness of base64 encoded strings
+ b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
+
+ root.btoa = function (string) {
+ string = String(string);
+ var bitmap, a, b, c,
+ result = "", i = 0,
+ rest = string.length % 3; // To determine the final padding
+
+ for (; i < string.length;) {
+ if ((a = string.charCodeAt(i++)) > 255
+ || (b = string.charCodeAt(i++)) > 255
+ || (c = string.charCodeAt(i++)) > 255)
+ throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");
+
+ bitmap = (a << 16) | (b << 8) | c;
+ result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63)
+ + b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63);
+ }
+
+ // If there's need of padding, replace the last 'A's with equal signs
+ return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result;
+ };
+
+ root.atob = function (string) {
+ // atob can work with strings with whitespaces, even inside the encoded part,
+ // but only \t, \n, \f, \r and ' ', which can be stripped.
+ string = String(string).replace(/[\t\n\f\r ]+/g, "");
+ if (!b64re.test(string))
+ throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");
+
+ // Adding the padding if missing, for semplicity
+ string += "==".slice(2 - (string.length & 3));
+ var bitmap, result = "", r1, r2, i = 0;
+ for (; i < string.length;) {
+ bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12
+ | (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++)));
+
+ result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255)
+ : r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255)
+ : String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255);
+ }
+ return result;
+ };
+});
\ No newline at end of file
diff --git a/example/polyfills/forEach.js b/example/polyfills/forEach.js
new file mode 100644
index 0000000..ff2481c
--- /dev/null
+++ b/example/polyfills/forEach.js
@@ -0,0 +1,59 @@
+// Шаги алгоритма ECMA-262, 5-е издание, 15.4.4.18
+// Ссылка (en): http://es5.github.io/#x15.4.4.18
+// Ссылка (ru): http://es5.javascript.ru/x15.4.html#x15.4.4.18
+if (!Array.prototype.forEach) {
+
+ Array.prototype.forEach = function (callback, thisArg) {
+
+ var T, k;
+
+ if (this == null) {
+ throw new TypeError(' this is null or not defined');
+ }
+
+ // 1. Положим O равным результату вызова ToObject passing the |this| value as the argument.
+ var O = Object(this);
+
+ // 2. Положим lenValue равным результату вызова внутреннего метода Get объекта O с аргументом "length".
+ // 3. Положим len равным ToUint32(lenValue).
+ var len = O.length >>> 0;
+
+ // 4. Если IsCallable(callback) равен false, выкинем исключение TypeError.
+ // Смотрите: http://es5.github.com/#x9.11
+ if (typeof callback !== 'function') {
+ throw new TypeError(callback + ' is not a function');
+ }
+
+ // 5. Если thisArg присутствует, положим T равным thisArg; иначе положим T равным undefined.
+ if (arguments.length > 1) {
+ T = thisArg;
+ }
+
+ // 6. Положим k равным 0
+ k = 0;
+
+ // 7. Пока k < len, будем повторять
+ while (k < len) {
+
+ var kValue;
+
+ // a. Положим Pk равным ToString(k).
+ // Это неявное преобразование для левостороннего операнда в операторе in
+ // b. Положим kPresent равным результату вызова внутреннего метода HasProperty объекта O с аргументом Pk.
+ // Этот шаг может быть объединён с шагом c
+ // c. Если kPresent равен true, то
+ if (k in O) {
+
+ // i. Положим kValue равным результату вызова внутреннего метода Get объекта O с аргументом Pk.
+ kValue = O[k];
+
+ // ii. Вызовем внутренний метод Call функции callback с объектом T в качестве значения this и
+ // списком аргументов, содержащим kValue, k и O.
+ callback.call(T, kValue, k, O);
+ }
+ // d. Увеличим k на 1.
+ k++;
+ }
+ // 8. Вернём undefined.
+ };
+}
\ No newline at end of file
diff --git a/example/polyfills/map.js b/example/polyfills/map.js
new file mode 100644
index 0000000..5ea7c9a
--- /dev/null
+++ b/example/polyfills/map.js
@@ -0,0 +1,91 @@
+// Шаги алгоритма ECMA-262, 5-е издание, 15.4.4.19
+// Ссылка (en): http://es5.github.com/#x15.4.4.19
+// Ссылка (ru): http://es5.javascript.ru/x15.4.html#x15.4.4.19
+if (!Array.prototype.map) {
+
+ Array.prototype.map = function(callback, thisArg) {
+
+ var T, A, k;
+
+ if (this == null) {
+ throw new TypeError(' this is null or not defined');
+ }
+
+ // 1. Положим O равным результату вызова ToObject с передачей ему
+ // значения |this| в качестве аргумента.
+ var O = Object(this);
+
+ // 2. Положим lenValue равным результату вызова внутреннего метода Get
+ // объекта O с аргументом "length".
+ // 3. Положим len равным ToUint32(lenValue).
+ var len = O.length >>> 0;
+
+ // 4. Если вызов IsCallable(callback) равен false, выкидываем исключение TypeError.
+ // Смотрите (en): http://es5.github.com/#x9.11
+ // Смотрите (ru): http://es5.javascript.ru/x9.html#x9.11
+ if (typeof callback !== 'function') {
+ throw new TypeError(callback + ' is not a function');
+ }
+
+ // 5. Если thisArg присутствует, положим T равным thisArg; иначе положим T равным undefined.
+ if (arguments.length > 1) {
+ T = thisArg;
+ }
+
+ // 6. Положим A равным новому масиву, как если бы он был создан выражением new Array(len),
+ // где Array является стандартным встроенным конструктором с этим именем,
+ // а len является значением len.
+ A = new Array(len);
+
+ // 7. Положим k равным 0
+ k = 0;
+
+ // 8. Пока k < len, будем повторять
+ while (k < len) {
+
+ var kValue, mappedValue;
+
+ // a. Положим Pk равным ToString(k).
+ // Это неявное преобразование для левостороннего операнда в операторе in
+ // b. Положим kPresent равным результату вызова внутреннего метода HasProperty
+ // объекта O с аргументом Pk.
+ // Этот шаг может быть объединён с шагом c
+ // c. Если kPresent равен true, то
+ if (k in O) {
+
+ // i. Положим kValue равным результату вызова внутреннего метода Get
+ // объекта O с аргументом Pk.
+ kValue = O[k];
+
+ // ii. Положим mappedValue равным результату вызова внутреннего метода Call
+ // функции callback со значением T в качестве значения this и списком
+ // аргументов, содержащим kValue, k и O.
+ mappedValue = callback.call(T, kValue, k, O);
+
+ // iii. Вызовем внутренний метод DefineOwnProperty объекта A с аргументами
+ // Pk, Описатель Свойства
+ // { Value: mappedValue,
+ // Writable: true,
+ // Enumerable: true,
+ // Configurable: true }
+ // и false.
+
+ // В браузерах, поддерживающих Object.defineProperty, используем следующий код:
+ // Object.defineProperty(A, k, {
+ // value: mappedValue,
+ // writable: true,
+ // enumerable: true,
+ // configurable: true
+ // });
+
+ // Для лучшей поддержки браузерами, используем следующий код:
+ A[k] = mappedValue;
+ }
+ // d. Увеличим k на 1.
+ k++;
+ }
+
+ // 9. Вернём A.
+ return A;
+ };
+}
\ No newline at end of file
diff --git a/example/polyfills/promise.js b/example/polyfills/promise.js
new file mode 100644
index 0000000..56786ec
--- /dev/null
+++ b/example/polyfills/promise.js
@@ -0,0 +1,236 @@
+(function (root) {
+
+ // Store setTimeout reference so promise-polyfill will be unaffected by
+ // other code modifying setTimeout (like sinon.useFakeTimers())
+ var setTimeoutFunc = setTimeout;
+
+ function noop() {
+ }
+
+ // Polyfill for Function.prototype.bind
+ function bind(fn, thisArg) {
+ return function () {
+ fn.apply(thisArg, arguments);
+ };
+ }
+
+ function Promise(fn) {
+ if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new');
+ if (typeof fn !== 'function') throw new TypeError('not a function');
+ this._state = 0;
+ this._handled = false;
+ this._value = undefined;
+ this._deferreds = [];
+
+ doResolve(fn, this);
+ }
+
+ function handle(self, deferred) {
+ while (self._state === 3) {
+ self = self._value;
+ }
+ if (self._state === 0) {
+ self._deferreds.push(deferred);
+ return;
+ }
+ self._handled = true;
+ Promise._immediateFn(function () {
+ var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
+ if (cb === null) {
+ (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
+ return;
+ }
+ var ret;
+ try {
+ ret = cb(self._value);
+ } catch (e) {
+ reject(deferred.promise, e);
+ return;
+ }
+ resolve(deferred.promise, ret);
+ });
+ }
+
+ function resolve(self, newValue) {
+ try {
+ // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
+ if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.');
+ if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
+ var then = newValue.then;
+ if (newValue instanceof Promise) {
+ self._state = 3;
+ self._value = newValue;
+ finale(self);
+ return;
+ } else if (typeof then === 'function') {
+ doResolve(bind(then, newValue), self);
+ return;
+ }
+ }
+ self._state = 1;
+ self._value = newValue;
+ finale(self);
+ } catch (e) {
+ reject(self, e);
+ }
+ }
+
+ function reject(self, newValue) {
+ self._state = 2;
+ self._value = newValue;
+ finale(self);
+ }
+
+ function finale(self) {
+ if (self._state === 2 && self._deferreds.length === 0) {
+ Promise._immediateFn(function () {
+ if (!self._handled) {
+ Promise._unhandledRejectionFn(self._value);
+ }
+ });
+ }
+
+ for (var i = 0, len = self._deferreds.length; i < len; i++) {
+ handle(self, self._deferreds[i]);
+ }
+ self._deferreds = null;
+ }
+
+ function Handler(onFulfilled, onRejected, promise) {
+ this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
+ this.onRejected = typeof onRejected === 'function' ? onRejected : null;
+ this.promise = promise;
+ }
+
+ /**
+ * Take a potentially misbehaving resolver function and make sure
+ * onFulfilled and onRejected are only called once.
+ *
+ * Makes no guarantees about asynchrony.
+ */
+ function doResolve(fn, self) {
+ var done = false;
+ try {
+ fn(function (value) {
+ if (done) return;
+ done = true;
+ resolve(self, value);
+ }, function (reason) {
+ if (done) return;
+ done = true;
+ reject(self, reason);
+ });
+ } catch (ex) {
+ if (done) return;
+ done = true;
+ reject(self, ex);
+ }
+ }
+
+ Promise.prototype['catch'] = function (onRejected) {
+ return this.then(null, onRejected);
+ };
+
+ Promise.prototype.then = function (onFulfilled, onRejected) {
+ var prom = new (this.constructor)(noop);
+
+ handle(this, new Handler(onFulfilled, onRejected, prom));
+ return prom;
+ };
+
+ Promise.all = function (arr) {
+ var args = Array.prototype.slice.call(arr);
+
+ return new Promise(function (resolve, reject) {
+ if (args.length === 0) return resolve([]);
+ var remaining = args.length;
+
+ function res(i, val) {
+ try {
+ if (val && (typeof val === 'object' || typeof val === 'function')) {
+ var then = val.then;
+ if (typeof then === 'function') {
+ then.call(val, function (val) {
+ res(i, val);
+ }, reject);
+ return;
+ }
+ }
+ args[i] = val;
+ if (--remaining === 0) {
+ resolve(args);
+ }
+ } catch (ex) {
+ reject(ex);
+ }
+ }
+
+ for (var i = 0; i < args.length; i++) {
+ res(i, args[i]);
+ }
+ });
+ };
+
+ Promise.resolve = function (value) {
+ if (value && typeof value === 'object' && value.constructor === Promise) {
+ return value;
+ }
+
+ return new Promise(function (resolve) {
+ resolve(value);
+ });
+ };
+
+ Promise.reject = function (value) {
+ return new Promise(function (resolve, reject) {
+ reject(value);
+ });
+ };
+
+ Promise.race = function (values) {
+ return new Promise(function (resolve, reject) {
+ for (var i = 0, len = values.length; i < len; i++) {
+ values[i].then(resolve, reject);
+ }
+ });
+ };
+
+ // Use polyfill for setImmediate for performance gains
+ Promise._immediateFn = (typeof setImmediate === 'function' && function (fn) {
+ setImmediate(fn);
+ }) ||
+ function (fn) {
+ setTimeoutFunc(fn, 0);
+ };
+
+ Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
+ if (typeof console !== 'undefined' && console) {
+ console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
+ }
+ };
+
+ /**
+ * Set the immediate function to execute callbacks
+ * @param fn {function} Function to execute
+ * @deprecated
+ */
+ Promise._setImmediateFn = function _setImmediateFn(fn) {
+ Promise._immediateFn = fn;
+ };
+
+ /**
+ * Change the function to execute on unhandled rejection
+ * @param {function} fn Function to execute on unhandled rejection
+ * @deprecated
+ */
+ Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
+ Promise._unhandledRejectionFn = fn;
+ };
+
+ if (typeof module !== 'undefined' && module.exports) {
+ module.exports = Promise;
+ } else if (!root.Promise) {
+ root.Promise = Promise;
+ }
+
+})(this);
\ No newline at end of file