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 @@ } + + + - - -