diff --git a/documentation/api_jszip/external.md b/documentation/api_jszip/external.md
index c0ce2381..a480972f 100644
--- a/documentation/api_jszip/external.md
+++ b/documentation/api_jszip/external.md
@@ -4,12 +4,15 @@ layout: default
section: api
---
-JSZip uses polyfills of objects that may not exist on every platform.
+JSZip uses objects that may not exist on every platform, in which case it uses
+a shim.
Accessing or replacing these objects can sometimes be useful. JSZip.external
contains the following properties :
* `Promise` : the [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) implementation used.
+The global object is prefered when available.
+
__Example__
```js
diff --git a/lib/external.js b/lib/external.js
index cbd69ede..37bd7064 100644
--- a/lib/external.js
+++ b/lib/external.js
@@ -1,6 +1,9 @@
'use strict';
-var ES6Promise = require("es6-promise").Promise;
+// load the global object first:
+// - it should be better integrated in the system (unhandledRejection in node)
+// - the environment may have a custom Promise implementation (see zone.js)
+var ES6Promise = global.Promise || require("lie");
/**
* Let the user use/change some implementations.
diff --git a/package.json b/package.json
index 807a2762..2620913d 100644
--- a/package.json
+++ b/package.json
@@ -53,6 +53,7 @@
"dependencies": {
"core-js": "~2.3.0",
"es6-promise": "~3.0.2",
+ "lie": "~3.1.0",
"pako": "~1.0.2",
"readable-stream": "~2.0.6"
},
diff --git a/test/asserts/external.js b/test/asserts/external.js
index 10217c2c..e1d522ba 100644
--- a/test/asserts/external.js
+++ b/test/asserts/external.js
@@ -1,34 +1,62 @@
/* jshint qunit: true */
-/* global JSZip,JSZipTestUtils */
+/* global JSZip,JSZipTestUtils,Promise */
'use strict';
QUnit.module("external");
+/**
+ * Creates a wrapper around an existing Promise implementation to count
+ * calls and detect custom implementations.
+ * @param {Promise} OriginalPromise the promise to wrap
+ * @return {Promise} the wrapped promise
+ */
function createPromiseProxy(OriginalPromise) {
- function MyShinyPromise () {
- OriginalPromise.apply(this, arguments);
+ function MyShinyPromise (input) {
+ if (input.then) { // thenable, we wrap it
+ this._promise = input;
+ } else { // executor
+ this._promise = new OriginalPromise(input);
+ }
MyShinyPromise.calls++;
}
MyShinyPromise.calls = 0;
- MyShinyPromise.prototype = OriginalPromise.prototype;
- function proxyMethod(method) {
- if (typeof OriginalPromise[method] === "function") {
- MyShinyPromise[method] = function () {
- MyShinyPromise.calls++;
- return OriginalPromise[method].apply(OriginalPromise, arguments);
- };
- }
- }
- MyShinyPromise.prototype.isACustomImplementation = true;
- for(var method in OriginalPromise) {
- if (!OriginalPromise.hasOwnProperty(method)) {
- continue;
- }
- proxyMethod(method);
- }
+ MyShinyPromise.prototype = {
+ then: function (onFulfilled, onRejected) {
+ return new MyShinyPromise(this._promise.then(onFulfilled, onRejected));
+ },
+ "catch": function (onRejected) {
+ return new MyShinyPromise(this._promise['catch'](onRejected));
+ },
+ isACustomImplementation: true
+ };
+
+ MyShinyPromise.resolve = function (value) {
+ return new MyShinyPromise(OriginalPromise.resolve(value));
+ };
+ MyShinyPromise.reject = function (value) {
+ return new MyShinyPromise(OriginalPromise.reject(value));
+ };
+ MyShinyPromise.all = function (value) {
+ return new MyShinyPromise(OriginalPromise.all(value));
+ };
return MyShinyPromise;
}
+test("JSZip.external.Promise", function (assert) {
+ assert.ok(JSZip.external.Promise, "JSZip.external.Promise is defined");
+ assert.ok(JSZip.external.Promise.resolve, "JSZip.external.Promise looks like a Promise");
+ assert.ok(JSZip.external.Promise.reject, "JSZip.external.Promise looks like a Promise");
+});
+
+test("load JSZip doesn't override the global Promise", function (assert) {
+ if (typeof Promise !== "undefined"){
+ assert.equal(Promise, JSZipTestUtils.oldPromise, "the previous Promise didn't change");
+ assert.equal(Promise, JSZip.external.Promise, "JSZip.external.Promise reused the global Promise");
+ } else {
+ assert.ok(JSZip.external.Promise, "JSZip.external.Promise is defined even if the global Promise doesn't exist");
+ }
+});
+
test("external.Promise can be replaced in .async()", function (assert) {
var done = assert.async();
var OriginalPromise = JSZip.external.Promise;
diff --git a/test/helpers/test-utils.js b/test/helpers/test-utils.js
index ba82717e..bbe541bd 100644
--- a/test/helpers/test-utils.js
+++ b/test/helpers/test-utils.js
@@ -203,5 +203,12 @@
return base64Dict[input];
};
+
+ if (global.JSZip) {
+ throw new Error("JSZip is already defined, we can't capture the global state *before* its load");
+ }
+
+ JSZipTestUtils.oldPromise = global.Promise;
+
global.JSZipTestUtils = JSZipTestUtils;
})(typeof window !== "undefined" && window || global);
diff --git a/test/index.html b/test/index.html
index a966a96d..52c81cf8 100644
--- a/test/index.html
+++ b/test/index.html
@@ -13,6 +13,9 @@
}
+
+
+
-
-
-