diff --git a/CHANGELOG.md b/CHANGELOG.md index 1869ed0ca..2b8bd0278 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ + +## [0.8.22](https://github.com/angular/zone.js/compare/v0.8.21...0.8.22) (2018-03-31) + + +### Bug Fixes + +* **fakeAsync:** fix [#1050](https://github.com/angular/zone.js/issues/1050), should only reset patched Date.now until fakeAsync exit ([#1051](https://github.com/angular/zone.js/issues/1051)) ([e15d735](https://github.com/angular/zone.js/commit/e15d735)) +* **fakeAsyncTest:** fix [#1061](https://github.com/angular/zone.js/issues/1061), fakeAsync should support setImmediate ([#1062](https://github.com/angular/zone.js/issues/1062)) ([66c6f97](https://github.com/angular/zone.js/commit/66c6f97)) + + + ## [0.8.21](https://github.com/angular/zone.js/compare/v0.8.20...0.8.21) (2018-03-30) diff --git a/dist/async-test.js b/dist/async-test.js index 952c5f77a..35c77f4ef 100644 --- a/dist/async-test.js +++ b/dist/async-test.js @@ -29,13 +29,11 @@ var AsyncTestZoneSpec = /** @class */ (function () { this.runZone = Zone.current; this.unresolvedChainedPromiseCount = 0; this.name = 'asyncTestZone for ' + namePrefix; - this.properties = { - 'AsyncTestZoneSpec': this - }; + this.properties = { 'AsyncTestZoneSpec': this }; } AsyncTestZoneSpec.prototype._finishCallbackIfDone = function () { var _this = this; - if (!(this._pendingMicroTasks || this._pendingMacroTasks || this.unresolvedChainedPromiseCount !== 0)) { + if (!(this._pendingMicroTasks || this._pendingMacroTasks)) { // We do this because we would like to catch unhandled rejected promises. this.runZone.run(function () { setTimeout(function () { @@ -63,7 +61,7 @@ var AsyncTestZoneSpec = /** @class */ (function () { this._isSync = false; } if (task.type === 'microTask' && task.data && task.data instanceof Promise) { - // check whether the promise is a chained promise + // check whether the promise is a chained promise if (task.data[AsyncTestZoneSpec.symbolParentUnresolved] === true) { // chained promise is being scheduled this.unresolvedChainedPromiseCount--; @@ -90,12 +88,10 @@ var AsyncTestZoneSpec = /** @class */ (function () { // was scheduled/invoked/canceled. AsyncTestZoneSpec.prototype.onInvoke = function (parentZoneDelegate, currentZone, targetZone, delegate, applyThis, applyArgs, source) { try { - this.patchPromiseForTest(); this._isSync = true; return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source); } finally { - this.unPatchPromiseForTest(); var afterTaskCounts = parentZoneDelegate._taskCounts; if (this._isSync) { this._finishCallbackIfDone(); diff --git a/dist/fake-async-test.js b/dist/fake-async-test.js index 32c0f215b..6fd9aa285 100644 --- a/dist/fake-async-test.js +++ b/dist/fake-async-test.js @@ -192,6 +192,7 @@ this._uncaughtPromiseErrors = Promise[Zone.__symbol__('uncaughtPromiseErrors')]; this.pendingPeriodicTimers = []; this.pendingTimers = []; + this.patchDateLocked = false; this.properties = { 'FakeAsyncTestZoneSpec': this }; this.name = 'fakeAsyncTestZone for ' + namePrefix; // in case user can't access the construction of FakeAsyncTestSpec @@ -307,12 +308,21 @@ return; } global['Date'] = FakeDate; + FakeDate.prototype = OriginalDate.prototype; }; FakeAsyncTestZoneSpec.resetDate = function () { if (global['Date'] === FakeDate) { global['Date'] = OriginalDate; } }; + FakeAsyncTestZoneSpec.prototype.lockDatePatch = function () { + this.patchDateLocked = true; + FakeAsyncTestZoneSpec.patchDate(); + }; + FakeAsyncTestZoneSpec.prototype.unlockDatePatch = function () { + this.patchDateLocked = false; + FakeAsyncTestZoneSpec.resetDate(); + }; FakeAsyncTestZoneSpec.prototype.tick = function (millis, doTick) { if (millis === void 0) { millis = 0; } FakeAsyncTestZoneSpec.assertInZone(); @@ -371,6 +381,9 @@ case 'setTimeout': task.data['handleId'] = this._setTimeout(task.invoke, task.data['delay'], Array.prototype.slice.call(task.data['args'], 2)); break; + case 'setImmediate': + task.data['handleId'] = this._setTimeout(task.invoke, 0, Array.prototype.slice.call(task.data['args'], 1)); + break; case 'setInterval': task.data['handleId'] = this._setInterval(task.invoke, task.data['delay'], Array.prototype.slice.call(task.data['args'], 2)); break; @@ -439,7 +452,9 @@ return delegate.invoke(target, callback, applyThis, applyArgs, source); } finally { - FakeAsyncTestZoneSpec.resetDate(); + if (!this.patchDateLocked) { + FakeAsyncTestZoneSpec.resetDate(); + } } }; FakeAsyncTestZoneSpec.prototype.findMacroTaskOption = function (task) { diff --git a/dist/jasmine-patch.js b/dist/jasmine-patch.js index 493d91a95..78cf8115b 100644 --- a/dist/jasmine-patch.js +++ b/dist/jasmine-patch.js @@ -116,7 +116,7 @@ return syncZone.run(describeBody, this, arguments); }; } - function runInTestZone(testBody, queueRunner, done) { + function runInTestZone(testBody, applyThis, queueRunner, done) { var isClockInstalled = !!jasmine[symbol('clockInstalled')]; var testProxyZoneSpec = queueRunner.testProxyZoneSpec; var testProxyZone = queueRunner.testProxyZone; @@ -127,18 +127,23 @@ var _fakeAsyncTestZoneSpec = new FakeAsyncTestZoneSpec(); lastDelegate = testProxyZoneSpec.getDelegate(); testProxyZoneSpec.setDelegate(_fakeAsyncTestZoneSpec); + _fakeAsyncTestZoneSpec.lockDatePatch(); } } try { if (done) { - return testProxyZone.run(testBody, this, [done]); + return testProxyZone.run(testBody, applyThis, [done]); } else { - return testProxyZone.run(testBody, this); + return testProxyZone.run(testBody, applyThis); } } finally { if (isClockInstalled) { + var _fakeAsyncTestZoneSpec = testProxyZoneSpec.getDelegate(); + if (_fakeAsyncTestZoneSpec) { + _fakeAsyncTestZoneSpec.unlockDatePatch(); + } testProxyZoneSpec.setDelegate(lastDelegate); } } @@ -153,9 +158,9 @@ // Note we have to make a function with correct number of arguments, otherwise jasmine will // think that all functions are sync or async. return (testBody && (testBody.length ? function (done) { - return runInTestZone(testBody, this.queueRunner, done); + return runInTestZone(testBody, this, this.queueRunner, done); } : function () { - return runInTestZone(testBody, this.queueRunner); + return runInTestZone(testBody, this, this.queueRunner); })); } var QueueRunner = jasmine.QueueRunner; diff --git a/dist/jasmine-patch.min.js b/dist/jasmine-patch.min.js index dd0f2ef54..c9796219e 100644 --- a/dist/jasmine-patch.min.js +++ b/dist/jasmine-patch.min.js @@ -1 +1 @@ -!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n():"function"==typeof define&&define.amd?define(n):n()}(this,function(){"use strict";!function(){function e(e){return function(){return u.run(e,this,arguments)}}function n(e,n,t){var o,r=!!jasmine[a("clockInstalled")],i=n.testProxyZoneSpec,s=n.testProxyZone;if(r){var c=Zone.FakeAsyncTestZoneSpec;if(c){var u=new c;o=i.getDelegate(),i.setDelegate(u)}}try{return t?s.run(e,this,[t]):s.run(e,this)}finally{r&&i.setDelegate(o)}}function t(e){return e&&(e.length?function(t){return n(e,this.queueRunner,t)}:function(){return n(e,this.queueRunner)})}var o=function(e,n){function t(){this.constructor=e}for(var o in n)n.hasOwnProperty(o)&&(e[o]=n[o]);e.prototype=null===n?Object.create(n):(t.prototype=n.prototype,new t)},r="undefined"!=typeof window&&window||"undefined"!=typeof self&&self||global;if(!Zone)throw new Error("Missing: zone.js");if("undefined"==typeof jasmine)throw new Error("Missing: jasmine.js");if(jasmine.__zone_patch__)throw new Error("'jasmine' has already been patched with 'Zone'.");jasmine.__zone_patch__=!0;var i=Zone.SyncTestZoneSpec,s=Zone.ProxyZoneSpec;if(!i)throw new Error("Missing: SyncTestZoneSpec");if(!s)throw new Error("Missing: ProxyZoneSpec");var c=Zone.current,u=c.fork(new i("jasmine.describe")),a=Zone.__symbol__,f=jasmine.getEnv();["describe","xdescribe","fdescribe"].forEach(function(n){var t=f[n];f[n]=function(n,o){return t.call(this,n,e(o))}}),["it","xit","fit"].forEach(function(e){var n=f[e];f[a(e)]=n,f[e]=function(e,o,r){return arguments[1]=t(o),n.apply(this,arguments)}}),["beforeEach","afterEach"].forEach(function(e){var n=f[e];f[a(e)]=n,f[e]=function(e,o){return arguments[0]=t(e),n.apply(this,arguments)}});var l=jasmine[a("clock")]=jasmine.clock;jasmine.clock=function(){var e=l.apply(this,arguments),n=e[a("tick")]=e.tick;e.tick=function(){var e=Zone.current.get("FakeAsyncTestZoneSpec");return e?e.tick.apply(e,arguments):n.apply(this,arguments)};var t=e[a("mockDate")]=e.mockDate;return e.mockDate=function(){var e=Zone.current.get("FakeAsyncTestZoneSpec");if(e){var n=arguments[0];return e.setCurrentRealTime.apply(e,n&&"function"==typeof n.getTime?[n.getTime()]:arguments)}return t.apply(this,arguments)},["install","uninstall"].forEach(function(n){var t=e[a(n)]=e[n];e[n]=function(){var e=Zone.FakeAsyncTestZoneSpec;return e?void(jasmine[a("clockInstalled")]="install"===n):t.apply(this,arguments)}}),e};var p=jasmine.QueueRunner;jasmine.QueueRunner=function(e){function n(n){var t=this;n.onComplete=function(e){return function(){t.testProxyZone=null,t.testProxyZoneSpec=null,c.scheduleMicroTask("jasmine.onComplete",e)}}(n.onComplete);var o=r.__zone_symbol__setTimeout,i=r.__zone_symbol__clearTimeout;o&&(n.timeout={setTimeout:o?o:r.setTimeout,clearTimeout:i?i:r.clearTimeout}),jasmine.UserContext?(n.userContext||(n.userContext=new jasmine.UserContext),n.userContext.queueRunner=this):(n.userContext||(n.userContext={}),n.userContext.queueRunner=this);var s=n.onException;n.onException=function(e){if(e&&"Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL."===e.message){var n=this&&this.testProxyZoneSpec;if(n){var t=n.getAndClearPendingTasksInfo();e.message+=t}}s&&s.call(this,e)},e.call(this,n)}return o(n,e),n.prototype.execute=function(){for(var n=this,t=Zone.current,o=!1;t;){if(t===c){o=!0;break}t=t.parent}if(!o)throw new Error("Unexpected Zone: "+Zone.current.name);this.testProxyZoneSpec=new s,this.testProxyZone=c.fork(this.testProxyZoneSpec),Zone.currentTask?e.prototype.execute.call(this):Zone.current.scheduleMicroTask("jasmine.execute().forceTask",function(){return p.prototype.execute.call(n)})},n}(p)}()}); \ No newline at end of file +!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n():"function"==typeof define&&define.amd?define(n):n()}(this,function(){"use strict";!function(){function e(e){return function(){return a.run(e,this,arguments)}}function n(e,n,t,o){var r,i=!!jasmine[u("clockInstalled")],s=t.testProxyZoneSpec,c=t.testProxyZone;if(i){var a=Zone.FakeAsyncTestZoneSpec;if(a){var f=new a;r=s.getDelegate(),s.setDelegate(f),f.lockDatePatch()}}try{return o?c.run(e,n,[o]):c.run(e,n)}finally{if(i){var f=s.getDelegate();f&&f.unlockDatePatch(),s.setDelegate(r)}}}function t(e){return e&&(e.length?function(t){return n(e,this,this.queueRunner,t)}:function(){return n(e,this,this.queueRunner)})}var o=function(e,n){function t(){this.constructor=e}for(var o in n)n.hasOwnProperty(o)&&(e[o]=n[o]);e.prototype=null===n?Object.create(n):(t.prototype=n.prototype,new t)},r="undefined"!=typeof window&&window||"undefined"!=typeof self&&self||global;if(!Zone)throw new Error("Missing: zone.js");if("undefined"==typeof jasmine)throw new Error("Missing: jasmine.js");if(jasmine.__zone_patch__)throw new Error("'jasmine' has already been patched with 'Zone'.");jasmine.__zone_patch__=!0;var i=Zone.SyncTestZoneSpec,s=Zone.ProxyZoneSpec;if(!i)throw new Error("Missing: SyncTestZoneSpec");if(!s)throw new Error("Missing: ProxyZoneSpec");var c=Zone.current,a=c.fork(new i("jasmine.describe")),u=Zone.__symbol__,f=jasmine.getEnv();["describe","xdescribe","fdescribe"].forEach(function(n){var t=f[n];f[n]=function(n,o){return t.call(this,n,e(o))}}),["it","xit","fit"].forEach(function(e){var n=f[e];f[u(e)]=n,f[e]=function(e,o,r){return arguments[1]=t(o),n.apply(this,arguments)}}),["beforeEach","afterEach"].forEach(function(e){var n=f[e];f[u(e)]=n,f[e]=function(e,o){return arguments[0]=t(e),n.apply(this,arguments)}});var l=jasmine[u("clock")]=jasmine.clock;jasmine.clock=function(){var e=l.apply(this,arguments),n=e[u("tick")]=e.tick;e.tick=function(){var e=Zone.current.get("FakeAsyncTestZoneSpec");return e?e.tick.apply(e,arguments):n.apply(this,arguments)};var t=e[u("mockDate")]=e.mockDate;return e.mockDate=function(){var e=Zone.current.get("FakeAsyncTestZoneSpec");if(e){var n=arguments[0];return e.setCurrentRealTime.apply(e,n&&"function"==typeof n.getTime?[n.getTime()]:arguments)}return t.apply(this,arguments)},["install","uninstall"].forEach(function(n){var t=e[u(n)]=e[n];e[n]=function(){var e=Zone.FakeAsyncTestZoneSpec;return e?void(jasmine[u("clockInstalled")]="install"===n):t.apply(this,arguments)}}),e};var p=jasmine.QueueRunner;jasmine.QueueRunner=function(e){function n(n){var t=this;n.onComplete=function(e){return function(){t.testProxyZone=null,t.testProxyZoneSpec=null,c.scheduleMicroTask("jasmine.onComplete",e)}}(n.onComplete);var o=r.__zone_symbol__setTimeout,i=r.__zone_symbol__clearTimeout;o&&(n.timeout={setTimeout:o?o:r.setTimeout,clearTimeout:i?i:r.clearTimeout}),jasmine.UserContext?(n.userContext||(n.userContext=new jasmine.UserContext),n.userContext.queueRunner=this):(n.userContext||(n.userContext={}),n.userContext.queueRunner=this);var s=n.onException;n.onException=function(e){if(e&&"Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL."===e.message){var n=this&&this.testProxyZoneSpec;if(n){var t=n.getAndClearPendingTasksInfo();e.message+=t}}s&&s.call(this,e)},e.call(this,n)}return o(n,e),n.prototype.execute=function(){for(var n=this,t=Zone.current,o=!1;t;){if(t===c){o=!0;break}t=t.parent}if(!o)throw new Error("Unexpected Zone: "+Zone.current.name);this.testProxyZoneSpec=new s,this.testProxyZone=c.fork(this.testProxyZoneSpec),Zone.currentTask?e.prototype.execute.call(this):Zone.current.scheduleMicroTask("jasmine.execute().forceTask",function(){return p.prototype.execute.call(n)})},n}(p)}()}); \ No newline at end of file diff --git a/dist/proxy.js b/dist/proxy.js index be3c426bb..5766ee978 100644 --- a/dist/proxy.js +++ b/dist/proxy.js @@ -63,6 +63,7 @@ var ProxyZoneSpec = /** @class */ (function () { return this._delegateSpec; }; ProxyZoneSpec.prototype.resetDelegate = function () { + var delegateSpec = this.getDelegate(); this.setDelegate(this.defaultSpecDelegate); }; ProxyZoneSpec.prototype.tryTriggerHasTask = function (parentZoneDelegate, currentZone, targetZone) { diff --git a/dist/proxy.min.js b/dist/proxy.min.js index 5f73c04aa..c0c44d725 100644 --- a/dist/proxy.min.js +++ b/dist/proxy.min.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t():"function"==typeof define&&define.amd?define(t):t()}(this,function(){"use strict";var e=function(){function e(e){void 0===e&&(e=null),this.defaultSpecDelegate=e,this.name="ProxyZone",this.properties={ProxyZoneSpec:this},this.propertyKeys=null,this.lastTaskState=null,this.isNeedToTriggerHasTask=!1,this.tasks=[],this.setDelegate(e)}return e.get=function(){return Zone.current.get("ProxyZoneSpec")},e.isLoaded=function(){return e.get()instanceof e},e.assertPresent=function(){if(!e.isLoaded())throw new Error("Expected to be running in 'ProxyZone', but it was not found.");return e.get()},e.prototype.setDelegate=function(e){var t=this,s=this._delegateSpec!==e;this._delegateSpec=e,this.propertyKeys&&this.propertyKeys.forEach(function(e){return delete t.properties[e]}),this.propertyKeys=null,e&&e.properties&&(this.propertyKeys=Object.keys(e.properties),this.propertyKeys.forEach(function(s){return t.properties[s]=e.properties[s]})),s&&this.lastTaskState&&(this.lastTaskState.macroTask||this.lastTaskState.microTask)&&(this.isNeedToTriggerHasTask=!0)},e.prototype.getDelegate=function(){return this._delegateSpec},e.prototype.resetDelegate=function(){this.setDelegate(this.defaultSpecDelegate)},e.prototype.tryTriggerHasTask=function(e,t,s){this.isNeedToTriggerHasTask&&this.lastTaskState&&(this.isNeedToTriggerHasTask=!1,this.onHasTask(e,t,s,this.lastTaskState))},e.prototype.removeFromTasks=function(e){if(this.tasks)for(var t=0;t 0) { + throw new Error(_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length + " " + + "periodic timer(s) still in the queue."); + } + if (_fakeAsyncTestZoneSpec.pendingTimers.length > 0) { + throw new Error(_fakeAsyncTestZoneSpec.pendingTimers.length + " timer(s) still in the queue."); + } + return res; + } + finally { + resetFakeAsyncZone(); + } + }; + } + function _getFakeAsyncZoneSpec() { + if (_fakeAsyncTestZoneSpec == null) { + _fakeAsyncTestZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); + if (_fakeAsyncTestZoneSpec == null) { + throw new Error('The code should be running in the fakeAsync zone to call this function'); + } + } + return _fakeAsyncTestZoneSpec; + } + /** + * Simulates the asynchronous passage of time for the timers in the fakeAsync zone. + * + * The microtasks queue is drained at the very start of this function and after any timer callback + * has been executed. + * + * ## Example + * + * {@example core/testing/ts/fake_async.ts region='basic'} + * + * @experimental + */ + function tick(millis) { + if (millis === void 0) { millis = 0; } + _getFakeAsyncZoneSpec().tick(millis); + } + /** + * Simulates the asynchronous passage of time for the timers in the fakeAsync zone by + * draining the macrotask queue until it is empty. The returned value is the milliseconds + * of time that would have been elapsed. + * + * @param maxTurns + * @returns The simulated time elapsed, in millis. + * + * @experimental + */ + function flush(maxTurns) { + return _getFakeAsyncZoneSpec().flush(maxTurns); + } + /** + * Discard all remaining periodic tasks. + * + * @experimental + */ + function discardPeriodicTasks() { + var zoneSpec = _getFakeAsyncZoneSpec(); + var pendingTimers = zoneSpec.pendingPeriodicTimers; + zoneSpec.pendingPeriodicTimers.length = 0; + } + /** + * Flush any pending microtasks. + * + * @experimental + */ + function flushMicrotasks() { + _getFakeAsyncZoneSpec().flushMicrotasks(); + } + Zone[api.symbol('fakeAsyncTest')] = + { resetFakeAsyncZone: resetFakeAsyncZone, flushMicrotasks: flushMicrotasks, discardPeriodicTasks: discardPeriodicTasks, tick: tick, flush: flush, fakeAsync: fakeAsync }; +}); + +}))); diff --git a/dist/zone-mix.js b/dist/zone-mix.js index 4b59965e3..23a6e068f 100644 --- a/dist/zone-mix.js +++ b/dist/zone-mix.js @@ -643,16 +643,6 @@ var Zone$1 = (function (global) { return global['Zone'] = Zone; })(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global); -var __values = (undefined && undefined.__values) || function (o) { - var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; - if (m) return m.call(o); - return { - next: function () { - if (o && i >= o.length) o = void 0; - return { value: o && o[i++], done: !o }; - } - }; -}; Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { var ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; var ObjectDefineProperty = Object.defineProperty; @@ -926,24 +916,14 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { function onReject(error) { promise && (promise = null || reject(error)); } - try { - for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) { - var value = values_1_1.value; - if (!isThenable(value)) { - value = this.resolve(value); - } - value.then(onResolve, onReject); - } - } - catch (e_1_1) { e_1 = { error: e_1_1 }; } - finally { - try { - if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1); + for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { + var value = values_1[_i]; + if (!isThenable(value)) { + value = this.resolve(value); } - finally { if (e_1) throw e_1.error; } + value.then(onResolve, onReject); } return promise; - var e_1, _a; }; ZoneAwarePromise.all = function (values) { var resolve; @@ -954,33 +934,23 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { }); var count = 0; var resolvedValues = []; - try { - for (var values_2 = __values(values), values_2_1 = values_2.next(); !values_2_1.done; values_2_1 = values_2.next()) { - var value = values_2_1.value; - if (!isThenable(value)) { - value = this.resolve(value); + for (var _i = 0, values_2 = values; _i < values_2.length; _i++) { + var value = values_2[_i]; + if (!isThenable(value)) { + value = this.resolve(value); + } + value.then((function (index) { return function (value) { + resolvedValues[index] = value; + count--; + if (!count) { + resolve(resolvedValues); } - value.then((function (index) { return function (value) { - resolvedValues[index] = value; - count--; - if (!count) { - resolve(resolvedValues); - } - }; })(count), reject); - count++; - } - } - catch (e_2_1) { e_2 = { error: e_2_1 }; } - finally { - try { - if (values_2_1 && !values_2_1.done && (_a = values_2.return)) _a.call(values_2); - } - finally { if (e_2) throw e_2.error; } + }; })(count), reject); + count++; } if (!count) resolve(resolvedValues); return promise; - var e_2, _a; }; ZoneAwarePromise.prototype.then = function (onFulfilled, onRejected) { var chainPromise = new this.constructor(null); diff --git a/dist/zone-node.js b/dist/zone-node.js index dc55a8875..c857c893c 100644 --- a/dist/zone-node.js +++ b/dist/zone-node.js @@ -643,16 +643,6 @@ var Zone$1 = (function (global) { return global['Zone'] = Zone; })(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global); -var __values = (undefined && undefined.__values) || function (o) { - var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; - if (m) return m.call(o); - return { - next: function () { - if (o && i >= o.length) o = void 0; - return { value: o && o[i++], done: !o }; - } - }; -}; Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { var ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; var ObjectDefineProperty = Object.defineProperty; @@ -926,24 +916,14 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { function onReject(error) { promise && (promise = null || reject(error)); } - try { - for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) { - var value = values_1_1.value; - if (!isThenable(value)) { - value = this.resolve(value); - } - value.then(onResolve, onReject); - } - } - catch (e_1_1) { e_1 = { error: e_1_1 }; } - finally { - try { - if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1); + for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { + var value = values_1[_i]; + if (!isThenable(value)) { + value = this.resolve(value); } - finally { if (e_1) throw e_1.error; } + value.then(onResolve, onReject); } return promise; - var e_1, _a; }; ZoneAwarePromise.all = function (values) { var resolve; @@ -954,33 +934,23 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { }); var count = 0; var resolvedValues = []; - try { - for (var values_2 = __values(values), values_2_1 = values_2.next(); !values_2_1.done; values_2_1 = values_2.next()) { - var value = values_2_1.value; - if (!isThenable(value)) { - value = this.resolve(value); + for (var _i = 0, values_2 = values; _i < values_2.length; _i++) { + var value = values_2[_i]; + if (!isThenable(value)) { + value = this.resolve(value); + } + value.then((function (index) { return function (value) { + resolvedValues[index] = value; + count--; + if (!count) { + resolve(resolvedValues); } - value.then((function (index) { return function (value) { - resolvedValues[index] = value; - count--; - if (!count) { - resolve(resolvedValues); - } - }; })(count), reject); - count++; - } - } - catch (e_2_1) { e_2 = { error: e_2_1 }; } - finally { - try { - if (values_2_1 && !values_2_1.done && (_a = values_2.return)) _a.call(values_2); - } - finally { if (e_2) throw e_2.error; } + }; })(count), reject); + count++; } if (!count) resolve(resolvedValues); return promise; - var e_2, _a; }; ZoneAwarePromise.prototype.then = function (onFulfilled, onRejected) { var chainPromise = new this.constructor(null); diff --git a/dist/zone-patch-jsonp.js b/dist/zone-patch-jsonp.js new file mode 100644 index 000000000..4dcf57382 --- /dev/null +++ b/dist/zone-patch-jsonp.js @@ -0,0 +1,81 @@ +/** +* @license +* Copyright Google Inc. All Rights Reserved. +* +* Use of this source code is governed by an MIT-style license that can be +* found in the LICENSE file at https://angular.io/license +*/ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +Zone.__load_patch('jsonp', function (global, Zone, api) { + Zone[Zone.__symbol__('jsonp')] = function patchJsonp(options) { + if (!options || !options.jsonp || !options.sendFuncName) { + return; + } + var noop = function () { }; + [options.successFuncName, options.failedFuncName].forEach(function (methodName) { + if (!methodName) { + return; + } + var oriFunc = global[methodName]; + if (oriFunc) { + api.patchMethod(global, methodName, function (delegate) { return function (self, args) { + var task = global[api.symbol('jsonTask')]; + if (task) { + task.callback = delegate; + return task.invoke.apply(self, args); + } + else { + return delegate.apply(self, args); + } + }; }); + } + else { + Object.defineProperty(global, methodName, { + configurable: true, + enumerable: true, + get: function () { + return function () { + var task = global[api.symbol('jsonpTask')]; + var delegate = global[api.symbol("jsonp" + methodName + "callback")]; + if (task) { + if (delegate) { + task.callback = delegate; + } + global[api.symbol('jsonpTask')] = undefined; + return task.invoke.apply(this, arguments); + } + else { + if (delegate) { + return delegate.apply(this, arguments); + } + } + return null; + }; + }, + set: function (callback) { + this[api.symbol("jsonp" + methodName + "callback")] = callback; + } + }); + } + }); + api.patchMethod(options.jsonp, options.sendFuncName, function (delegate) { return function (self, args) { + global[api.symbol('jsonpTask')] = Zone.current.scheduleMacroTask('jsonp', noop, {}, function (task) { + return delegate.apply(self, args); + }, noop); + }; }); + }; +}); + +}))); diff --git a/dist/zone-patch-jsonp.min.js b/dist/zone-patch-jsonp.min.js new file mode 100644 index 000000000..6d8881776 --- /dev/null +++ b/dist/zone-patch-jsonp.min.js @@ -0,0 +1 @@ +!function(n,o){"object"==typeof exports&&"undefined"!=typeof module?o():"function"==typeof define&&define.amd?define(o):o()}(this,function(){"use strict";Zone.__load_patch("jsonp",function(n,o,e){o[o.__symbol__("jsonp")]=function(t){if(t&&t.jsonp&&t.sendFuncName){var c=function(){};[t.successFuncName,t.failedFuncName].forEach(function(o){if(o){var t=n[o];t?e.patchMethod(n,o,function(o){return function(t,c){var s=n[e.symbol("jsonTask")];return s?(s.callback=o,s.invoke.apply(t,c)):o.apply(t,c)}}):Object.defineProperty(n,o,{configurable:!0,enumerable:!0,get:function(){return function(){var t=n[e.symbol("jsonpTask")],c=n[e.symbol("jsonp"+o+"callback")];return t?(c&&(t.callback=c),n[e.symbol("jsonpTask")]=void 0,t.invoke.apply(this,arguments)):c?c.apply(this,arguments):null}},set:function(n){this[e.symbol("jsonp"+o+"callback")]=n}})}}),e.patchMethod(t.jsonp,t.sendFuncName,function(t){return function(s,a){n[e.symbol("jsonpTask")]=o.current.scheduleMacroTask("jsonp",c,{},function(n){return t.apply(s,a)},c)}})}}})}); \ No newline at end of file diff --git a/dist/zone-patch-promise-test.js b/dist/zone-patch-promise-test.js new file mode 100644 index 000000000..45a7db12d --- /dev/null +++ b/dist/zone-patch-promise-test.js @@ -0,0 +1,80 @@ +/** +* @license +* Copyright Google Inc. All Rights Reserved. +* +* Use of this source code is governed by an MIT-style license that can be +* found in the LICENSE file at https://angular.io/license +*/ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +/** + * Promise for async/fakeAsync zoneSpec test + * can support async operation which not supported by zone.js + * such as + * it ('test jsonp in AsyncZone', async() => { + * new Promise(res => { + * jsonp(url, (data) => { + * // success callback + * res(data); + * }); + * }).then((jsonpResult) => { + * // get jsonp result. + * + * // user will expect AsyncZoneSpec wait for + * // then, but because jsonp is not zone aware + * // AsyncZone will finish before then is called. + * }); + * }); + */ +Zone.__load_patch('promisefortest', function (global, Zone, api) { + var symbolState = api.symbol('state'); + var UNRESOLVED = null; + var symbolParentUnresolved = api.symbol('parentUnresolved'); + // patch Promise.prototype.then to keep an internal + // number for tracking unresolved chained promise + // we will decrease this number when the parent promise + // being resolved/rejected and chained promise was + // scheduled as a microTask. + // so we can know such kind of chained promise still + // not resolved in AsyncTestZone + Promise[api.symbol('patchPromiseForTest')] = function patchPromiseForTest() { + var oriThen = Promise[Zone.__symbol__('ZonePromiseThen')]; + if (oriThen) { + return; + } + oriThen = Promise[Zone.__symbol__('ZonePromiseThen')] = Promise.prototype.then; + Promise.prototype.then = function () { + var chained = oriThen.apply(this, arguments); + if (this[symbolState] === UNRESOLVED) { + // parent promise is unresolved. + var asyncTestZoneSpec = Zone.current.get('AsyncTestZoneSpec'); + if (asyncTestZoneSpec) { + asyncTestZoneSpec.unresolvedChainedPromiseCount++; + chained[symbolParentUnresolved] = true; + } + } + return chained; + }; + }; + Promise[api.symbol('unPatchPromiseForTest')] = function unpatchPromiseForTest() { + // restore origin then + var oriThen = Promise[Zone.__symbol__('ZonePromiseThen')]; + if (oriThen) { + Promise.prototype.then = oriThen; + Promise[Zone.__symbol__('ZonePromiseThen')] = undefined; + } + }; +}); + +}))); diff --git a/dist/zone-patch-promise-test.min.js b/dist/zone-patch-promise-test.min.js new file mode 100644 index 000000000..55ac90a8c --- /dev/null +++ b/dist/zone-patch-promise-test.min.js @@ -0,0 +1 @@ +!function(e,o){"object"==typeof exports&&"undefined"!=typeof module?o():"function"==typeof define&&define.amd?define(o):o()}(this,function(){"use strict";Zone.__load_patch("promisefortest",function(e,o,n){var t=n.symbol("state"),s=null,r=n.symbol("parentUnresolved");Promise[n.symbol("patchPromiseForTest")]=function(){var e=Promise[o.__symbol__("ZonePromiseThen")];e||(e=Promise[o.__symbol__("ZonePromiseThen")]=Promise.prototype.then,Promise.prototype.then=function(){var n=e.apply(this,arguments);if(this[t]===s){var i=o.current.get("AsyncTestZoneSpec");i&&(i.unresolvedChainedPromiseCount++,n[r]=!0)}return n})},Promise[n.symbol("unPatchPromiseForTest")]=function(){var e=Promise[o.__symbol__("ZonePromiseThen")];e&&(Promise.prototype.then=e,Promise[o.__symbol__("ZonePromiseThen")]=void 0)}})}); \ No newline at end of file diff --git a/dist/zone-patch-resize-observer.js b/dist/zone-patch-resize-observer.js new file mode 100644 index 000000000..b0cabc088 --- /dev/null +++ b/dist/zone-patch-resize-observer.js @@ -0,0 +1,99 @@ +/** +* @license +* Copyright Google Inc. All Rights Reserved. +* +* Use of this source code is governed by an MIT-style license that can be +* found in the LICENSE file at https://angular.io/license +*/ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +Zone.__load_patch('ResizeObserver', function (global, Zone, api) { + var ResizeObserver = global['ResizeObserver']; + if (!ResizeObserver) { + return; + } + var resizeObserverSymbol = api.symbol('ResizeObserver'); + api.patchMethod(global, 'ResizeObserver', function (delegate) { return function (self, args) { + var callback = args.length > 0 ? args[0] : null; + if (callback) { + args[0] = function (entries, observer) { + var _this = this; + var zones = {}; + var currZone = Zone.current; + for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) { + var entry = entries_1[_i]; + var zone = entry.target[resizeObserverSymbol]; + if (!zone) { + zone = currZone; + } + var zoneEntriesInfo = zones[zone.name]; + if (!zoneEntriesInfo) { + zones[zone.name] = zoneEntriesInfo = { entries: [], zone: zone }; + } + zoneEntriesInfo.entries.push(entry); + } + Object.keys(zones).forEach(function (zoneName) { + var zoneEntriesInfo = zones[zoneName]; + if (zoneEntriesInfo.zone !== Zone.current) { + zoneEntriesInfo.zone.run(callback, _this, [zoneEntriesInfo.entries, observer], 'ResizeObserver'); + } + else { + callback.call(_this, zoneEntriesInfo.entries, observer); + } + }); + }; + } + return args.length > 0 ? new ResizeObserver(args[0]) : new ResizeObserver(); + }; }); + api.patchMethod(ResizeObserver.prototype, 'observe', function (delegate) { return function (self, args) { + var target = args.length > 0 ? args[0] : null; + if (!target) { + return delegate.apply(self, args); + } + var targets = self[resizeObserverSymbol]; + if (!targets) { + targets = self[resizeObserverSymbol] = []; + } + targets.push(target); + target[resizeObserverSymbol] = Zone.current; + return delegate.apply(self, args); + }; }); + api.patchMethod(ResizeObserver.prototype, 'unobserve', function (delegate) { return function (self, args) { + var target = args.length > 0 ? args[0] : null; + if (!target) { + return delegate.apply(self, args); + } + var targets = self[resizeObserverSymbol]; + if (targets) { + for (var i = 0; i < targets.length; i++) { + if (targets[i] === target) { + targets.splice(i, 1); + break; + } + } + } + target[resizeObserverSymbol] = undefined; + return delegate.apply(self, args); + }; }); + api.patchMethod(ResizeObserver.prototype, 'disconnect', function (delegate) { return function (self, args) { + var targets = self[resizeObserverSymbol]; + if (targets) { + targets.forEach(function (target) { target[resizeObserverSymbol] = undefined; }); + self[resizeObserverSymbol] = undefined; + } + return delegate.apply(self, args); + }; }); +}); + +}))); diff --git a/dist/zone-patch-resize-observer.min.js b/dist/zone-patch-resize-observer.min.js new file mode 100644 index 000000000..bffe2a10a --- /dev/null +++ b/dist/zone-patch-resize-observer.min.js @@ -0,0 +1 @@ +!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n():"function"==typeof define&&define.amd?define(n):n()}(this,function(){"use strict";Zone.__load_patch("ResizeObserver",function(e,n,r){var t=e.ResizeObserver;if(t){var o=r.symbol("ResizeObserver");r.patchMethod(e,"ResizeObserver",function(e){return function(e,r){var i=r.length>0?r[0]:null;return i&&(r[0]=function(e,r){for(var t=this,u={},a=n.current,c=0,f=e;c0?new t(r[0]):new t}}),r.patchMethod(t.prototype,"observe",function(e){return function(r,t){var i=t.length>0?t[0]:null;if(!i)return e.apply(r,t);var u=r[o];return u||(u=r[o]=[]),u.push(i),i[o]=n.current,e.apply(r,t)}}),r.patchMethod(t.prototype,"unobserve",function(e){return function(n,r){var t=r.length>0?r[0]:null;if(!t)return e.apply(n,r);var i=n[o];if(i)for(var u=0;u= o.length) o = void 0; - return { value: o && o[i++], done: !o }; - } - }; -}; Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { var ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; var ObjectDefineProperty = Object.defineProperty; @@ -926,24 +916,14 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { function onReject(error) { promise && (promise = null || reject(error)); } - try { - for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) { - var value = values_1_1.value; - if (!isThenable(value)) { - value = this.resolve(value); - } - value.then(onResolve, onReject); + for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { + var value = values_1[_i]; + if (!isThenable(value)) { + value = this.resolve(value); } - } - catch (e_1_1) { e_1 = { error: e_1_1 }; } - finally { - try { - if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1); - } - finally { if (e_1) throw e_1.error; } + value.then(onResolve, onReject); } return promise; - var e_1, _a; }; ZoneAwarePromise.all = function (values) { var resolve; @@ -954,33 +934,23 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { }); var count = 0; var resolvedValues = []; - try { - for (var values_2 = __values(values), values_2_1 = values_2.next(); !values_2_1.done; values_2_1 = values_2.next()) { - var value = values_2_1.value; - if (!isThenable(value)) { - value = this.resolve(value); - } - value.then((function (index) { return function (value) { - resolvedValues[index] = value; - count--; - if (!count) { - resolve(resolvedValues); - } - }; })(count), reject); - count++; - } - } - catch (e_2_1) { e_2 = { error: e_2_1 }; } - finally { - try { - if (values_2_1 && !values_2_1.done && (_a = values_2.return)) _a.call(values_2); + for (var _i = 0, values_2 = values; _i < values_2.length; _i++) { + var value = values_2[_i]; + if (!isThenable(value)) { + value = this.resolve(value); } - finally { if (e_2) throw e_2.error; } + value.then((function (index) { return function (value) { + resolvedValues[index] = value; + count--; + if (!count) { + resolve(resolvedValues); + } + }; })(count), reject); + count++; } if (!count) resolve(resolvedValues); return promise; - var e_2, _a; }; ZoneAwarePromise.prototype.then = function (onFulfilled, onRejected) { var chainPromise = new this.constructor(null); @@ -3299,6 +3269,7 @@ var ProxyZoneSpec = /** @class */ (function () { return this._delegateSpec; }; ProxyZoneSpec.prototype.resetDelegate = function () { + var delegateSpec = this.getDelegate(); this.setDelegate(this.defaultSpecDelegate); }; ProxyZoneSpec.prototype.tryTriggerHasTask = function (parentZoneDelegate, currentZone, targetZone) { @@ -3555,7 +3526,7 @@ Zone['SyncTestZoneSpec'] = SyncTestZoneSpec; return syncZone.run(describeBody, this, arguments); }; } - function runInTestZone(testBody, queueRunner, done) { + function runInTestZone(testBody, applyThis, queueRunner, done) { var isClockInstalled = !!jasmine[symbol('clockInstalled')]; var testProxyZoneSpec = queueRunner.testProxyZoneSpec; var testProxyZone = queueRunner.testProxyZone; @@ -3566,18 +3537,23 @@ Zone['SyncTestZoneSpec'] = SyncTestZoneSpec; var _fakeAsyncTestZoneSpec = new FakeAsyncTestZoneSpec(); lastDelegate = testProxyZoneSpec.getDelegate(); testProxyZoneSpec.setDelegate(_fakeAsyncTestZoneSpec); + _fakeAsyncTestZoneSpec.lockDatePatch(); } } try { if (done) { - return testProxyZone.run(testBody, this, [done]); + return testProxyZone.run(testBody, applyThis, [done]); } else { - return testProxyZone.run(testBody, this); + return testProxyZone.run(testBody, applyThis); } } finally { if (isClockInstalled) { + var _fakeAsyncTestZoneSpec = testProxyZoneSpec.getDelegate(); + if (_fakeAsyncTestZoneSpec) { + _fakeAsyncTestZoneSpec.unlockDatePatch(); + } testProxyZoneSpec.setDelegate(lastDelegate); } } @@ -3592,9 +3568,9 @@ Zone['SyncTestZoneSpec'] = SyncTestZoneSpec; // Note we have to make a function with correct number of arguments, otherwise jasmine will // think that all functions are sync or async. return (testBody && (testBody.length ? function (done) { - return runInTestZone(testBody, this.queueRunner, done); + return runInTestZone(testBody, this, this.queueRunner, done); } : function () { - return runInTestZone(testBody, this.queueRunner); + return runInTestZone(testBody, this, this.queueRunner); })); } var QueueRunner = jasmine.QueueRunner; @@ -3709,13 +3685,11 @@ var AsyncTestZoneSpec = /** @class */ (function () { this.runZone = Zone.current; this.unresolvedChainedPromiseCount = 0; this.name = 'asyncTestZone for ' + namePrefix; - this.properties = { - 'AsyncTestZoneSpec': this - }; + this.properties = { 'AsyncTestZoneSpec': this }; } AsyncTestZoneSpec.prototype._finishCallbackIfDone = function () { var _this = this; - if (!(this._pendingMicroTasks || this._pendingMacroTasks || this.unresolvedChainedPromiseCount !== 0)) { + if (!(this._pendingMicroTasks || this._pendingMacroTasks)) { // We do this because we would like to catch unhandled rejected promises. this.runZone.run(function () { setTimeout(function () { @@ -3743,7 +3717,7 @@ var AsyncTestZoneSpec = /** @class */ (function () { this._isSync = false; } if (task.type === 'microTask' && task.data && task.data instanceof Promise) { - // check whether the promise is a chained promise + // check whether the promise is a chained promise if (task.data[AsyncTestZoneSpec.symbolParentUnresolved] === true) { // chained promise is being scheduled this.unresolvedChainedPromiseCount--; @@ -3770,12 +3744,10 @@ var AsyncTestZoneSpec = /** @class */ (function () { // was scheduled/invoked/canceled. AsyncTestZoneSpec.prototype.onInvoke = function (parentZoneDelegate, currentZone, targetZone, delegate, applyThis, applyArgs, source) { try { - this.patchPromiseForTest(); this._isSync = true; return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source); } finally { - this.unPatchPromiseForTest(); var afterTaskCounts = parentZoneDelegate._taskCounts; if (this._isSync) { this._finishCallbackIfDone(); @@ -3990,6 +3962,7 @@ Zone['AsyncTestZoneSpec'] = AsyncTestZoneSpec; this._uncaughtPromiseErrors = Promise[Zone.__symbol__('uncaughtPromiseErrors')]; this.pendingPeriodicTimers = []; this.pendingTimers = []; + this.patchDateLocked = false; this.properties = { 'FakeAsyncTestZoneSpec': this }; this.name = 'fakeAsyncTestZone for ' + namePrefix; // in case user can't access the construction of FakeAsyncTestSpec @@ -4105,12 +4078,21 @@ Zone['AsyncTestZoneSpec'] = AsyncTestZoneSpec; return; } global['Date'] = FakeDate; + FakeDate.prototype = OriginalDate.prototype; }; FakeAsyncTestZoneSpec.resetDate = function () { if (global['Date'] === FakeDate) { global['Date'] = OriginalDate; } }; + FakeAsyncTestZoneSpec.prototype.lockDatePatch = function () { + this.patchDateLocked = true; + FakeAsyncTestZoneSpec.patchDate(); + }; + FakeAsyncTestZoneSpec.prototype.unlockDatePatch = function () { + this.patchDateLocked = false; + FakeAsyncTestZoneSpec.resetDate(); + }; FakeAsyncTestZoneSpec.prototype.tick = function (millis, doTick) { if (millis === void 0) { millis = 0; } FakeAsyncTestZoneSpec.assertInZone(); @@ -4169,6 +4151,9 @@ Zone['AsyncTestZoneSpec'] = AsyncTestZoneSpec; case 'setTimeout': task.data['handleId'] = this._setTimeout(task.invoke, task.data['delay'], Array.prototype.slice.call(task.data['args'], 2)); break; + case 'setImmediate': + task.data['handleId'] = this._setTimeout(task.invoke, 0, Array.prototype.slice.call(task.data['args'], 1)); + break; case 'setInterval': task.data['handleId'] = this._setInterval(task.invoke, task.data['delay'], Array.prototype.slice.call(task.data['args'], 2)); break; @@ -4237,7 +4222,9 @@ Zone['AsyncTestZoneSpec'] = AsyncTestZoneSpec; return delegate.invoke(target, callback, applyThis, applyArgs, source); } finally { - FakeAsyncTestZoneSpec.resetDate(); + if (!this.patchDateLocked) { + FakeAsyncTestZoneSpec.resetDate(); + } } }; FakeAsyncTestZoneSpec.prototype.findMacroTaskOption = function (task) { @@ -4336,10 +4323,91 @@ Zone.__load_patch('promisefortest', function (global, Zone, api) { * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ -/** - * Wraps a test function in an asynchronous test zone. The test will automatically - * complete when all asynchronous calls within this zone are done. - */ +Zone.__load_patch('asynctest', function (global, Zone, api) { + /** + * Wraps a test function in an asynchronous test zone. The test will automatically + * complete when all asynchronous calls within this zone are done. + */ + Zone[api.symbol('asyncTest')] = function asyncTest(fn) { + // If we're running using the Jasmine test framework, adapt to call the 'done' + // function when asynchronous activity is finished. + if (global.jasmine) { + // Not using an arrow function to preserve context passed from call site + return function (done) { + if (!done) { + // if we run beforeEach in @angular/core/testing/testing_internal then we get no done + // fake it here and assume sync. + done = function () { }; + done.fail = function (e) { + throw e; + }; + } + runInTestZone(fn, this, done, function (err) { + if (typeof err === 'string') { + return done.fail(new Error(err)); + } + else { + done.fail(err); + } + }); + }; + } + // Otherwise, return a promise which will resolve when asynchronous activity + // is finished. This will be correctly consumed by the Mocha framework with + // it('...', async(myFn)); or can be used in a custom framework. + // Not using an arrow function to preserve context passed from call site + return function () { + var _this = this; + return new Promise(function (finishCallback, failCallback) { + runInTestZone(fn, _this, finishCallback, failCallback); + }); + }; + }; + function runInTestZone(fn, context, finishCallback, failCallback) { + var currentZone = Zone.current; + var AsyncTestZoneSpec = Zone['AsyncTestZoneSpec']; + if (AsyncTestZoneSpec === undefined) { + throw new Error('AsyncTestZoneSpec is needed for the async() test helper but could not be found. ' + + 'Please make sure that your environment includes zone.js/dist/async-test.js'); + } + var ProxyZoneSpec = Zone['ProxyZoneSpec']; + if (ProxyZoneSpec === undefined) { + throw new Error('ProxyZoneSpec is needed for the async() test helper but could not be found. ' + + 'Please make sure that your environment includes zone.js/dist/proxy.js'); + } + var proxyZoneSpec = ProxyZoneSpec.get(); + ProxyZoneSpec.assertPresent(); + // We need to create the AsyncTestZoneSpec outside the ProxyZone. + // If we do it in ProxyZone then we will get to infinite recursion. + var proxyZone = Zone.current.getZoneWith('ProxyZoneSpec'); + var previousDelegate = proxyZoneSpec.getDelegate(); + proxyZone.parent.run(function () { + var testZoneSpec = new AsyncTestZoneSpec(function () { + // Need to restore the original zone. + if (proxyZoneSpec.getDelegate() == testZoneSpec) { + // Only reset the zone spec if it's + // sill this one. Otherwise, assume + // it's OK. + proxyZoneSpec.setDelegate(previousDelegate); + } + currentZone.run(function () { + finishCallback(); + }); + }, function (error) { + // Need to restore the original zone. + if (proxyZoneSpec.getDelegate() == testZoneSpec) { + // Only reset the zone spec if it's sill this one. Otherwise, assume it's OK. + proxyZoneSpec.setDelegate(previousDelegate); + } + currentZone.run(function () { + failCallback(error); + }); + }, 'test'); + proxyZoneSpec.setDelegate(testZoneSpec); + }); + return Zone.current.runGuarded(fn, context); + } +}); /** * @license @@ -4348,69 +4416,145 @@ Zone.__load_patch('promisefortest', function (global, Zone, api) { * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ -var FakeAsyncTestZoneSpec = Zone && Zone['FakeAsyncTestZoneSpec']; -var ProxyZoneSpec$1 = Zone && Zone['ProxyZoneSpec']; -/** - * Clears out the shared fake async zone for a test. - * To be called in a global `beforeEach`. - * - * @experimental - */ - -/** - * Wraps a function to be executed in the fakeAsync zone: - * - microtasks are manually executed by calling `flushMicrotasks()`, - * - timers are synchronous, `tick()` simulates the asynchronous passage of time. - * - * If there are any pending timers at the end of the function, an exception will be thrown. - * - * Can be used to wrap inject() calls. - * - * ## Example - * - * {@example core/testing/ts/fake_async.ts region='basic'} - * - * @param fn - * @returns The function wrapped to be executed in the fakeAsync zone - * - * @experimental - */ - -/** - * Simulates the asynchronous passage of time for the timers in the fakeAsync zone. - * - * The microtasks queue is drained at the very start of this function and after any timer callback - * has been executed. - * - * ## Example - * - * {@example core/testing/ts/fake_async.ts region='basic'} - * - * @experimental - */ - -/** - * Simulates the asynchronous passage of time for the timers in the fakeAsync zone by - * draining the macrotask queue until it is empty. The returned value is the milliseconds - * of time that would have been elapsed. - * - * @param maxTurns - * @returns The simulated time elapsed, in millis. - * - * @experimental - */ - -/** - * Discard all remaining periodic tasks. - * - * @experimental - */ - -/** - * Flush any pending microtasks. - * - * @experimental - */ +Zone.__load_patch('fakeasync', function (global, Zone, api) { + var FakeAsyncTestZoneSpec = Zone && Zone['FakeAsyncTestZoneSpec']; + var ProxyZoneSpec = Zone && Zone['ProxyZoneSpec']; + var _fakeAsyncTestZoneSpec = null; + /** + * Clears out the shared fake async zone for a test. + * To be called in a global `beforeEach`. + * + * @experimental + */ + function resetFakeAsyncZone() { + if (_fakeAsyncTestZoneSpec) { + _fakeAsyncTestZoneSpec.unlockDatePatch(); + } + _fakeAsyncTestZoneSpec = null; + // in node.js testing we may not have ProxyZoneSpec in which case there is nothing to reset. + ProxyZoneSpec && ProxyZoneSpec.assertPresent().resetDelegate(); + } + /** + * Wraps a function to be executed in the fakeAsync zone: + * - microtasks are manually executed by calling `flushMicrotasks()`, + * - timers are synchronous, `tick()` simulates the asynchronous passage of time. + * + * If there are any pending timers at the end of the function, an exception will be thrown. + * + * Can be used to wrap inject() calls. + * + * ## Example + * + * {@example core/testing/ts/fake_async.ts region='basic'} + * + * @param fn + * @returns The function wrapped to be executed in the fakeAsync zone + * + * @experimental + */ + function fakeAsync(fn) { + // Not using an arrow function to preserve context passed from call site + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var proxyZoneSpec = ProxyZoneSpec.assertPresent(); + if (Zone.current.get('FakeAsyncTestZoneSpec')) { + throw new Error('fakeAsync() calls can not be nested'); + } + try { + // in case jasmine.clock init a fakeAsyncTestZoneSpec + if (!_fakeAsyncTestZoneSpec) { + if (proxyZoneSpec.getDelegate() instanceof FakeAsyncTestZoneSpec) { + throw new Error('fakeAsync() calls can not be nested'); + } + _fakeAsyncTestZoneSpec = new FakeAsyncTestZoneSpec(); + } + var res = void 0; + var lastProxyZoneSpec = proxyZoneSpec.getDelegate(); + proxyZoneSpec.setDelegate(_fakeAsyncTestZoneSpec); + _fakeAsyncTestZoneSpec.lockDatePatch(); + try { + res = fn.apply(this, args); + flushMicrotasks(); + } + finally { + proxyZoneSpec.setDelegate(lastProxyZoneSpec); + } + if (_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length > 0) { + throw new Error(_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length + " " + + "periodic timer(s) still in the queue."); + } + if (_fakeAsyncTestZoneSpec.pendingTimers.length > 0) { + throw new Error(_fakeAsyncTestZoneSpec.pendingTimers.length + " timer(s) still in the queue."); + } + return res; + } + finally { + resetFakeAsyncZone(); + } + }; + } + function _getFakeAsyncZoneSpec() { + if (_fakeAsyncTestZoneSpec == null) { + _fakeAsyncTestZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); + if (_fakeAsyncTestZoneSpec == null) { + throw new Error('The code should be running in the fakeAsync zone to call this function'); + } + } + return _fakeAsyncTestZoneSpec; + } + /** + * Simulates the asynchronous passage of time for the timers in the fakeAsync zone. + * + * The microtasks queue is drained at the very start of this function and after any timer callback + * has been executed. + * + * ## Example + * + * {@example core/testing/ts/fake_async.ts region='basic'} + * + * @experimental + */ + function tick(millis) { + if (millis === void 0) { millis = 0; } + _getFakeAsyncZoneSpec().tick(millis); + } + /** + * Simulates the asynchronous passage of time for the timers in the fakeAsync zone by + * draining the macrotask queue until it is empty. The returned value is the milliseconds + * of time that would have been elapsed. + * + * @param maxTurns + * @returns The simulated time elapsed, in millis. + * + * @experimental + */ + function flush(maxTurns) { + return _getFakeAsyncZoneSpec().flush(maxTurns); + } + /** + * Discard all remaining periodic tasks. + * + * @experimental + */ + function discardPeriodicTasks() { + var zoneSpec = _getFakeAsyncZoneSpec(); + var pendingTimers = zoneSpec.pendingPeriodicTimers; + zoneSpec.pendingPeriodicTimers.length = 0; + } + /** + * Flush any pending microtasks. + * + * @experimental + */ + function flushMicrotasks() { + _getFakeAsyncZoneSpec().flushMicrotasks(); + } + Zone[api.symbol('fakeAsyncTest')] = + { resetFakeAsyncZone: resetFakeAsyncZone, flushMicrotasks: flushMicrotasks, discardPeriodicTasks: discardPeriodicTasks, tick: tick, flush: flush, fakeAsync: fakeAsync }; +}); /** * @license diff --git a/dist/zone-testing-node-bundle.js b/dist/zone-testing-node-bundle.js index 9e9605547..85de0f422 100644 --- a/dist/zone-testing-node-bundle.js +++ b/dist/zone-testing-node-bundle.js @@ -643,16 +643,6 @@ var Zone$1 = (function (global) { return global['Zone'] = Zone; })(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global); -var __values = (undefined && undefined.__values) || function (o) { - var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; - if (m) return m.call(o); - return { - next: function () { - if (o && i >= o.length) o = void 0; - return { value: o && o[i++], done: !o }; - } - }; -}; Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { var ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; var ObjectDefineProperty = Object.defineProperty; @@ -926,24 +916,14 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { function onReject(error) { promise && (promise = null || reject(error)); } - try { - for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) { - var value = values_1_1.value; - if (!isThenable(value)) { - value = this.resolve(value); - } - value.then(onResolve, onReject); - } - } - catch (e_1_1) { e_1 = { error: e_1_1 }; } - finally { - try { - if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1); + for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { + var value = values_1[_i]; + if (!isThenable(value)) { + value = this.resolve(value); } - finally { if (e_1) throw e_1.error; } + value.then(onResolve, onReject); } return promise; - var e_1, _a; }; ZoneAwarePromise.all = function (values) { var resolve; @@ -954,33 +934,23 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { }); var count = 0; var resolvedValues = []; - try { - for (var values_2 = __values(values), values_2_1 = values_2.next(); !values_2_1.done; values_2_1 = values_2.next()) { - var value = values_2_1.value; - if (!isThenable(value)) { - value = this.resolve(value); + for (var _i = 0, values_2 = values; _i < values_2.length; _i++) { + var value = values_2[_i]; + if (!isThenable(value)) { + value = this.resolve(value); + } + value.then((function (index) { return function (value) { + resolvedValues[index] = value; + count--; + if (!count) { + resolve(resolvedValues); } - value.then((function (index) { return function (value) { - resolvedValues[index] = value; - count--; - if (!count) { - resolve(resolvedValues); - } - }; })(count), reject); - count++; - } - } - catch (e_2_1) { e_2 = { error: e_2_1 }; } - finally { - try { - if (values_2_1 && !values_2_1.done && (_a = values_2.return)) _a.call(values_2); - } - finally { if (e_2) throw e_2.error; } + }; })(count), reject); + count++; } if (!count) resolve(resolvedValues); return promise; - var e_2, _a; }; ZoneAwarePromise.prototype.then = function (onFulfilled, onRejected) { var chainPromise = new this.constructor(null); @@ -2537,6 +2507,7 @@ var ProxyZoneSpec = /** @class */ (function () { return this._delegateSpec; }; ProxyZoneSpec.prototype.resetDelegate = function () { + var delegateSpec = this.getDelegate(); this.setDelegate(this.defaultSpecDelegate); }; ProxyZoneSpec.prototype.tryTriggerHasTask = function (parentZoneDelegate, currentZone, targetZone) { @@ -2793,7 +2764,7 @@ Zone['SyncTestZoneSpec'] = SyncTestZoneSpec; return syncZone.run(describeBody, this, arguments); }; } - function runInTestZone(testBody, queueRunner, done) { + function runInTestZone(testBody, applyThis, queueRunner, done) { var isClockInstalled = !!jasmine[symbol('clockInstalled')]; var testProxyZoneSpec = queueRunner.testProxyZoneSpec; var testProxyZone = queueRunner.testProxyZone; @@ -2804,18 +2775,23 @@ Zone['SyncTestZoneSpec'] = SyncTestZoneSpec; var _fakeAsyncTestZoneSpec = new FakeAsyncTestZoneSpec(); lastDelegate = testProxyZoneSpec.getDelegate(); testProxyZoneSpec.setDelegate(_fakeAsyncTestZoneSpec); + _fakeAsyncTestZoneSpec.lockDatePatch(); } } try { if (done) { - return testProxyZone.run(testBody, this, [done]); + return testProxyZone.run(testBody, applyThis, [done]); } else { - return testProxyZone.run(testBody, this); + return testProxyZone.run(testBody, applyThis); } } finally { if (isClockInstalled) { + var _fakeAsyncTestZoneSpec = testProxyZoneSpec.getDelegate(); + if (_fakeAsyncTestZoneSpec) { + _fakeAsyncTestZoneSpec.unlockDatePatch(); + } testProxyZoneSpec.setDelegate(lastDelegate); } } @@ -2830,9 +2806,9 @@ Zone['SyncTestZoneSpec'] = SyncTestZoneSpec; // Note we have to make a function with correct number of arguments, otherwise jasmine will // think that all functions are sync or async. return (testBody && (testBody.length ? function (done) { - return runInTestZone(testBody, this.queueRunner, done); + return runInTestZone(testBody, this, this.queueRunner, done); } : function () { - return runInTestZone(testBody, this.queueRunner); + return runInTestZone(testBody, this, this.queueRunner); })); } var QueueRunner = jasmine.QueueRunner; @@ -2947,13 +2923,11 @@ var AsyncTestZoneSpec = /** @class */ (function () { this.runZone = Zone.current; this.unresolvedChainedPromiseCount = 0; this.name = 'asyncTestZone for ' + namePrefix; - this.properties = { - 'AsyncTestZoneSpec': this - }; + this.properties = { 'AsyncTestZoneSpec': this }; } AsyncTestZoneSpec.prototype._finishCallbackIfDone = function () { var _this = this; - if (!(this._pendingMicroTasks || this._pendingMacroTasks || this.unresolvedChainedPromiseCount !== 0)) { + if (!(this._pendingMicroTasks || this._pendingMacroTasks)) { // We do this because we would like to catch unhandled rejected promises. this.runZone.run(function () { setTimeout(function () { @@ -2981,7 +2955,7 @@ var AsyncTestZoneSpec = /** @class */ (function () { this._isSync = false; } if (task.type === 'microTask' && task.data && task.data instanceof Promise) { - // check whether the promise is a chained promise + // check whether the promise is a chained promise if (task.data[AsyncTestZoneSpec.symbolParentUnresolved] === true) { // chained promise is being scheduled this.unresolvedChainedPromiseCount--; @@ -3008,12 +2982,10 @@ var AsyncTestZoneSpec = /** @class */ (function () { // was scheduled/invoked/canceled. AsyncTestZoneSpec.prototype.onInvoke = function (parentZoneDelegate, currentZone, targetZone, delegate, applyThis, applyArgs, source) { try { - this.patchPromiseForTest(); this._isSync = true; return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source); } finally { - this.unPatchPromiseForTest(); var afterTaskCounts = parentZoneDelegate._taskCounts; if (this._isSync) { this._finishCallbackIfDone(); @@ -3228,6 +3200,7 @@ Zone['AsyncTestZoneSpec'] = AsyncTestZoneSpec; this._uncaughtPromiseErrors = Promise[Zone.__symbol__('uncaughtPromiseErrors')]; this.pendingPeriodicTimers = []; this.pendingTimers = []; + this.patchDateLocked = false; this.properties = { 'FakeAsyncTestZoneSpec': this }; this.name = 'fakeAsyncTestZone for ' + namePrefix; // in case user can't access the construction of FakeAsyncTestSpec @@ -3343,12 +3316,21 @@ Zone['AsyncTestZoneSpec'] = AsyncTestZoneSpec; return; } global['Date'] = FakeDate; + FakeDate.prototype = OriginalDate.prototype; }; FakeAsyncTestZoneSpec.resetDate = function () { if (global['Date'] === FakeDate) { global['Date'] = OriginalDate; } }; + FakeAsyncTestZoneSpec.prototype.lockDatePatch = function () { + this.patchDateLocked = true; + FakeAsyncTestZoneSpec.patchDate(); + }; + FakeAsyncTestZoneSpec.prototype.unlockDatePatch = function () { + this.patchDateLocked = false; + FakeAsyncTestZoneSpec.resetDate(); + }; FakeAsyncTestZoneSpec.prototype.tick = function (millis, doTick) { if (millis === void 0) { millis = 0; } FakeAsyncTestZoneSpec.assertInZone(); @@ -3407,6 +3389,9 @@ Zone['AsyncTestZoneSpec'] = AsyncTestZoneSpec; case 'setTimeout': task.data['handleId'] = this._setTimeout(task.invoke, task.data['delay'], Array.prototype.slice.call(task.data['args'], 2)); break; + case 'setImmediate': + task.data['handleId'] = this._setTimeout(task.invoke, 0, Array.prototype.slice.call(task.data['args'], 1)); + break; case 'setInterval': task.data['handleId'] = this._setInterval(task.invoke, task.data['delay'], Array.prototype.slice.call(task.data['args'], 2)); break; @@ -3475,7 +3460,9 @@ Zone['AsyncTestZoneSpec'] = AsyncTestZoneSpec; return delegate.invoke(target, callback, applyThis, applyArgs, source); } finally { - FakeAsyncTestZoneSpec.resetDate(); + if (!this.patchDateLocked) { + FakeAsyncTestZoneSpec.resetDate(); + } } }; FakeAsyncTestZoneSpec.prototype.findMacroTaskOption = function (task) { @@ -3574,10 +3561,91 @@ Zone.__load_patch('promisefortest', function (global, Zone, api) { * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ -/** - * Wraps a test function in an asynchronous test zone. The test will automatically - * complete when all asynchronous calls within this zone are done. - */ +Zone.__load_patch('asynctest', function (global, Zone, api) { + /** + * Wraps a test function in an asynchronous test zone. The test will automatically + * complete when all asynchronous calls within this zone are done. + */ + Zone[api.symbol('asyncTest')] = function asyncTest(fn) { + // If we're running using the Jasmine test framework, adapt to call the 'done' + // function when asynchronous activity is finished. + if (global.jasmine) { + // Not using an arrow function to preserve context passed from call site + return function (done) { + if (!done) { + // if we run beforeEach in @angular/core/testing/testing_internal then we get no done + // fake it here and assume sync. + done = function () { }; + done.fail = function (e) { + throw e; + }; + } + runInTestZone(fn, this, done, function (err) { + if (typeof err === 'string') { + return done.fail(new Error(err)); + } + else { + done.fail(err); + } + }); + }; + } + // Otherwise, return a promise which will resolve when asynchronous activity + // is finished. This will be correctly consumed by the Mocha framework with + // it('...', async(myFn)); or can be used in a custom framework. + // Not using an arrow function to preserve context passed from call site + return function () { + var _this = this; + return new Promise(function (finishCallback, failCallback) { + runInTestZone(fn, _this, finishCallback, failCallback); + }); + }; + }; + function runInTestZone(fn, context, finishCallback, failCallback) { + var currentZone = Zone.current; + var AsyncTestZoneSpec = Zone['AsyncTestZoneSpec']; + if (AsyncTestZoneSpec === undefined) { + throw new Error('AsyncTestZoneSpec is needed for the async() test helper but could not be found. ' + + 'Please make sure that your environment includes zone.js/dist/async-test.js'); + } + var ProxyZoneSpec = Zone['ProxyZoneSpec']; + if (ProxyZoneSpec === undefined) { + throw new Error('ProxyZoneSpec is needed for the async() test helper but could not be found. ' + + 'Please make sure that your environment includes zone.js/dist/proxy.js'); + } + var proxyZoneSpec = ProxyZoneSpec.get(); + ProxyZoneSpec.assertPresent(); + // We need to create the AsyncTestZoneSpec outside the ProxyZone. + // If we do it in ProxyZone then we will get to infinite recursion. + var proxyZone = Zone.current.getZoneWith('ProxyZoneSpec'); + var previousDelegate = proxyZoneSpec.getDelegate(); + proxyZone.parent.run(function () { + var testZoneSpec = new AsyncTestZoneSpec(function () { + // Need to restore the original zone. + if (proxyZoneSpec.getDelegate() == testZoneSpec) { + // Only reset the zone spec if it's + // sill this one. Otherwise, assume + // it's OK. + proxyZoneSpec.setDelegate(previousDelegate); + } + currentZone.run(function () { + finishCallback(); + }); + }, function (error) { + // Need to restore the original zone. + if (proxyZoneSpec.getDelegate() == testZoneSpec) { + // Only reset the zone spec if it's sill this one. Otherwise, assume it's OK. + proxyZoneSpec.setDelegate(previousDelegate); + } + currentZone.run(function () { + failCallback(error); + }); + }, 'test'); + proxyZoneSpec.setDelegate(testZoneSpec); + }); + return Zone.current.runGuarded(fn, context); + } +}); /** * @license @@ -3586,69 +3654,145 @@ Zone.__load_patch('promisefortest', function (global, Zone, api) { * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ -var FakeAsyncTestZoneSpec = Zone && Zone['FakeAsyncTestZoneSpec']; -var ProxyZoneSpec$1 = Zone && Zone['ProxyZoneSpec']; -/** - * Clears out the shared fake async zone for a test. - * To be called in a global `beforeEach`. - * - * @experimental - */ - -/** - * Wraps a function to be executed in the fakeAsync zone: - * - microtasks are manually executed by calling `flushMicrotasks()`, - * - timers are synchronous, `tick()` simulates the asynchronous passage of time. - * - * If there are any pending timers at the end of the function, an exception will be thrown. - * - * Can be used to wrap inject() calls. - * - * ## Example - * - * {@example core/testing/ts/fake_async.ts region='basic'} - * - * @param fn - * @returns The function wrapped to be executed in the fakeAsync zone - * - * @experimental - */ - -/** - * Simulates the asynchronous passage of time for the timers in the fakeAsync zone. - * - * The microtasks queue is drained at the very start of this function and after any timer callback - * has been executed. - * - * ## Example - * - * {@example core/testing/ts/fake_async.ts region='basic'} - * - * @experimental - */ - -/** - * Simulates the asynchronous passage of time for the timers in the fakeAsync zone by - * draining the macrotask queue until it is empty. The returned value is the milliseconds - * of time that would have been elapsed. - * - * @param maxTurns - * @returns The simulated time elapsed, in millis. - * - * @experimental - */ - -/** - * Discard all remaining periodic tasks. - * - * @experimental - */ - -/** - * Flush any pending microtasks. - * - * @experimental - */ +Zone.__load_patch('fakeasync', function (global, Zone, api) { + var FakeAsyncTestZoneSpec = Zone && Zone['FakeAsyncTestZoneSpec']; + var ProxyZoneSpec = Zone && Zone['ProxyZoneSpec']; + var _fakeAsyncTestZoneSpec = null; + /** + * Clears out the shared fake async zone for a test. + * To be called in a global `beforeEach`. + * + * @experimental + */ + function resetFakeAsyncZone() { + if (_fakeAsyncTestZoneSpec) { + _fakeAsyncTestZoneSpec.unlockDatePatch(); + } + _fakeAsyncTestZoneSpec = null; + // in node.js testing we may not have ProxyZoneSpec in which case there is nothing to reset. + ProxyZoneSpec && ProxyZoneSpec.assertPresent().resetDelegate(); + } + /** + * Wraps a function to be executed in the fakeAsync zone: + * - microtasks are manually executed by calling `flushMicrotasks()`, + * - timers are synchronous, `tick()` simulates the asynchronous passage of time. + * + * If there are any pending timers at the end of the function, an exception will be thrown. + * + * Can be used to wrap inject() calls. + * + * ## Example + * + * {@example core/testing/ts/fake_async.ts region='basic'} + * + * @param fn + * @returns The function wrapped to be executed in the fakeAsync zone + * + * @experimental + */ + function fakeAsync(fn) { + // Not using an arrow function to preserve context passed from call site + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var proxyZoneSpec = ProxyZoneSpec.assertPresent(); + if (Zone.current.get('FakeAsyncTestZoneSpec')) { + throw new Error('fakeAsync() calls can not be nested'); + } + try { + // in case jasmine.clock init a fakeAsyncTestZoneSpec + if (!_fakeAsyncTestZoneSpec) { + if (proxyZoneSpec.getDelegate() instanceof FakeAsyncTestZoneSpec) { + throw new Error('fakeAsync() calls can not be nested'); + } + _fakeAsyncTestZoneSpec = new FakeAsyncTestZoneSpec(); + } + var res = void 0; + var lastProxyZoneSpec = proxyZoneSpec.getDelegate(); + proxyZoneSpec.setDelegate(_fakeAsyncTestZoneSpec); + _fakeAsyncTestZoneSpec.lockDatePatch(); + try { + res = fn.apply(this, args); + flushMicrotasks(); + } + finally { + proxyZoneSpec.setDelegate(lastProxyZoneSpec); + } + if (_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length > 0) { + throw new Error(_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length + " " + + "periodic timer(s) still in the queue."); + } + if (_fakeAsyncTestZoneSpec.pendingTimers.length > 0) { + throw new Error(_fakeAsyncTestZoneSpec.pendingTimers.length + " timer(s) still in the queue."); + } + return res; + } + finally { + resetFakeAsyncZone(); + } + }; + } + function _getFakeAsyncZoneSpec() { + if (_fakeAsyncTestZoneSpec == null) { + _fakeAsyncTestZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); + if (_fakeAsyncTestZoneSpec == null) { + throw new Error('The code should be running in the fakeAsync zone to call this function'); + } + } + return _fakeAsyncTestZoneSpec; + } + /** + * Simulates the asynchronous passage of time for the timers in the fakeAsync zone. + * + * The microtasks queue is drained at the very start of this function and after any timer callback + * has been executed. + * + * ## Example + * + * {@example core/testing/ts/fake_async.ts region='basic'} + * + * @experimental + */ + function tick(millis) { + if (millis === void 0) { millis = 0; } + _getFakeAsyncZoneSpec().tick(millis); + } + /** + * Simulates the asynchronous passage of time for the timers in the fakeAsync zone by + * draining the macrotask queue until it is empty. The returned value is the milliseconds + * of time that would have been elapsed. + * + * @param maxTurns + * @returns The simulated time elapsed, in millis. + * + * @experimental + */ + function flush(maxTurns) { + return _getFakeAsyncZoneSpec().flush(maxTurns); + } + /** + * Discard all remaining periodic tasks. + * + * @experimental + */ + function discardPeriodicTasks() { + var zoneSpec = _getFakeAsyncZoneSpec(); + var pendingTimers = zoneSpec.pendingPeriodicTimers; + zoneSpec.pendingPeriodicTimers.length = 0; + } + /** + * Flush any pending microtasks. + * + * @experimental + */ + function flushMicrotasks() { + _getFakeAsyncZoneSpec().flushMicrotasks(); + } + Zone[api.symbol('fakeAsyncTest')] = + { resetFakeAsyncZone: resetFakeAsyncZone, flushMicrotasks: flushMicrotasks, discardPeriodicTasks: discardPeriodicTasks, tick: tick, flush: flush, fakeAsync: fakeAsync }; +}); /** * @license diff --git a/dist/zone-testing.js b/dist/zone-testing.js index 2e6d244d6..5ea69eca1 100644 --- a/dist/zone-testing.js +++ b/dist/zone-testing.js @@ -6,10 +6,10 @@ * found in the LICENSE file at https://angular.io/license */ (function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (factory((global.zone = {}))); -}(this, (function (exports) { 'use strict'; + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; /** * @license @@ -223,6 +223,7 @@ var ProxyZoneSpec = /** @class */ (function () { return this._delegateSpec; }; ProxyZoneSpec.prototype.resetDelegate = function () { + var delegateSpec = this.getDelegate(); this.setDelegate(this.defaultSpecDelegate); }; ProxyZoneSpec.prototype.tryTriggerHasTask = function (parentZoneDelegate, currentZone, targetZone) { @@ -479,7 +480,7 @@ Zone['SyncTestZoneSpec'] = SyncTestZoneSpec; return syncZone.run(describeBody, this, arguments); }; } - function runInTestZone(testBody, queueRunner, done) { + function runInTestZone(testBody, applyThis, queueRunner, done) { var isClockInstalled = !!jasmine[symbol('clockInstalled')]; var testProxyZoneSpec = queueRunner.testProxyZoneSpec; var testProxyZone = queueRunner.testProxyZone; @@ -490,18 +491,23 @@ Zone['SyncTestZoneSpec'] = SyncTestZoneSpec; var _fakeAsyncTestZoneSpec = new FakeAsyncTestZoneSpec(); lastDelegate = testProxyZoneSpec.getDelegate(); testProxyZoneSpec.setDelegate(_fakeAsyncTestZoneSpec); + _fakeAsyncTestZoneSpec.lockDatePatch(); } } try { if (done) { - return testProxyZone.run(testBody, this, [done]); + return testProxyZone.run(testBody, applyThis, [done]); } else { - return testProxyZone.run(testBody, this); + return testProxyZone.run(testBody, applyThis); } } finally { if (isClockInstalled) { + var _fakeAsyncTestZoneSpec = testProxyZoneSpec.getDelegate(); + if (_fakeAsyncTestZoneSpec) { + _fakeAsyncTestZoneSpec.unlockDatePatch(); + } testProxyZoneSpec.setDelegate(lastDelegate); } } @@ -516,9 +522,9 @@ Zone['SyncTestZoneSpec'] = SyncTestZoneSpec; // Note we have to make a function with correct number of arguments, otherwise jasmine will // think that all functions are sync or async. return (testBody && (testBody.length ? function (done) { - return runInTestZone(testBody, this.queueRunner, done); + return runInTestZone(testBody, this, this.queueRunner, done); } : function () { - return runInTestZone(testBody, this.queueRunner); + return runInTestZone(testBody, this, this.queueRunner); })); } var QueueRunner = jasmine.QueueRunner; @@ -633,13 +639,11 @@ var AsyncTestZoneSpec = /** @class */ (function () { this.runZone = Zone.current; this.unresolvedChainedPromiseCount = 0; this.name = 'asyncTestZone for ' + namePrefix; - this.properties = { - 'AsyncTestZoneSpec': this - }; + this.properties = { 'AsyncTestZoneSpec': this }; } AsyncTestZoneSpec.prototype._finishCallbackIfDone = function () { var _this = this; - if (!(this._pendingMicroTasks || this._pendingMacroTasks || this.unresolvedChainedPromiseCount !== 0)) { + if (!(this._pendingMicroTasks || this._pendingMacroTasks)) { // We do this because we would like to catch unhandled rejected promises. this.runZone.run(function () { setTimeout(function () { @@ -667,7 +671,7 @@ var AsyncTestZoneSpec = /** @class */ (function () { this._isSync = false; } if (task.type === 'microTask' && task.data && task.data instanceof Promise) { - // check whether the promise is a chained promise + // check whether the promise is a chained promise if (task.data[AsyncTestZoneSpec.symbolParentUnresolved] === true) { // chained promise is being scheduled this.unresolvedChainedPromiseCount--; @@ -694,12 +698,10 @@ var AsyncTestZoneSpec = /** @class */ (function () { // was scheduled/invoked/canceled. AsyncTestZoneSpec.prototype.onInvoke = function (parentZoneDelegate, currentZone, targetZone, delegate, applyThis, applyArgs, source) { try { - this.patchPromiseForTest(); this._isSync = true; return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source); } finally { - this.unPatchPromiseForTest(); var afterTaskCounts = parentZoneDelegate._taskCounts; if (this._isSync) { this._finishCallbackIfDone(); @@ -914,6 +916,7 @@ Zone['AsyncTestZoneSpec'] = AsyncTestZoneSpec; this._uncaughtPromiseErrors = Promise[Zone.__symbol__('uncaughtPromiseErrors')]; this.pendingPeriodicTimers = []; this.pendingTimers = []; + this.patchDateLocked = false; this.properties = { 'FakeAsyncTestZoneSpec': this }; this.name = 'fakeAsyncTestZone for ' + namePrefix; // in case user can't access the construction of FakeAsyncTestSpec @@ -1029,12 +1032,21 @@ Zone['AsyncTestZoneSpec'] = AsyncTestZoneSpec; return; } global['Date'] = FakeDate; + FakeDate.prototype = OriginalDate.prototype; }; FakeAsyncTestZoneSpec.resetDate = function () { if (global['Date'] === FakeDate) { global['Date'] = OriginalDate; } }; + FakeAsyncTestZoneSpec.prototype.lockDatePatch = function () { + this.patchDateLocked = true; + FakeAsyncTestZoneSpec.patchDate(); + }; + FakeAsyncTestZoneSpec.prototype.unlockDatePatch = function () { + this.patchDateLocked = false; + FakeAsyncTestZoneSpec.resetDate(); + }; FakeAsyncTestZoneSpec.prototype.tick = function (millis, doTick) { if (millis === void 0) { millis = 0; } FakeAsyncTestZoneSpec.assertInZone(); @@ -1093,6 +1105,9 @@ Zone['AsyncTestZoneSpec'] = AsyncTestZoneSpec; case 'setTimeout': task.data['handleId'] = this._setTimeout(task.invoke, task.data['delay'], Array.prototype.slice.call(task.data['args'], 2)); break; + case 'setImmediate': + task.data['handleId'] = this._setTimeout(task.invoke, 0, Array.prototype.slice.call(task.data['args'], 1)); + break; case 'setInterval': task.data['handleId'] = this._setInterval(task.invoke, task.data['delay'], Array.prototype.slice.call(task.data['args'], 2)); break; @@ -1161,7 +1176,9 @@ Zone['AsyncTestZoneSpec'] = AsyncTestZoneSpec; return delegate.invoke(target, callback, applyThis, applyArgs, source); } finally { - FakeAsyncTestZoneSpec.resetDate(); + if (!this.patchDateLocked) { + FakeAsyncTestZoneSpec.resetDate(); + } } }; FakeAsyncTestZoneSpec.prototype.findMacroTaskOption = function (task) { @@ -1260,90 +1277,91 @@ Zone.__load_patch('promisefortest', function (global, Zone, api) { * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ -var _global = typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global; -/** - * Wraps a test function in an asynchronous test zone. The test will automatically - * complete when all asynchronous calls within this zone are done. - */ -function asyncTest(fn) { - // If we're running using the Jasmine test framework, adapt to call the 'done' - // function when asynchronous activity is finished. - if (_global.jasmine) { - // Not using an arrow function to preserve context passed from call site - return function (done) { - if (!done) { - // if we run beforeEach in @angular/core/testing/testing_internal then we get no done - // fake it here and assume sync. - done = function () { }; - done.fail = function (e) { - throw e; - }; - } - runInTestZone(fn, this, done, function (err) { - if (typeof err === 'string') { - return done.fail(new Error(err)); - } - else { - done.fail(err); +Zone.__load_patch('asynctest', function (global, Zone, api) { + /** + * Wraps a test function in an asynchronous test zone. The test will automatically + * complete when all asynchronous calls within this zone are done. + */ + Zone[api.symbol('asyncTest')] = function asyncTest(fn) { + // If we're running using the Jasmine test framework, adapt to call the 'done' + // function when asynchronous activity is finished. + if (global.jasmine) { + // Not using an arrow function to preserve context passed from call site + return function (done) { + if (!done) { + // if we run beforeEach in @angular/core/testing/testing_internal then we get no done + // fake it here and assume sync. + done = function () { }; + done.fail = function (e) { + throw e; + }; } + runInTestZone(fn, this, done, function (err) { + if (typeof err === 'string') { + return done.fail(new Error(err)); + } + else { + done.fail(err); + } + }); + }; + } + // Otherwise, return a promise which will resolve when asynchronous activity + // is finished. This will be correctly consumed by the Mocha framework with + // it('...', async(myFn)); or can be used in a custom framework. + // Not using an arrow function to preserve context passed from call site + return function () { + var _this = this; + return new Promise(function (finishCallback, failCallback) { + runInTestZone(fn, _this, finishCallback, failCallback); }); }; - } - // Otherwise, return a promise which will resolve when asynchronous activity - // is finished. This will be correctly consumed by the Mocha framework with - // it('...', async(myFn)); or can be used in a custom framework. - // Not using an arrow function to preserve context passed from call site - return function () { - var _this = this; - return new Promise(function (finishCallback, failCallback) { - runInTestZone(fn, _this, finishCallback, failCallback); - }); }; -} -function runInTestZone(fn, context, finishCallback, failCallback) { - var currentZone = Zone.current; - var AsyncTestZoneSpec = Zone['AsyncTestZoneSpec']; - if (AsyncTestZoneSpec === undefined) { - throw new Error('AsyncTestZoneSpec is needed for the async() test helper but could not be found. ' + - 'Please make sure that your environment includes zone.js/dist/async-test.js'); - } - var ProxyZoneSpec = Zone['ProxyZoneSpec']; - if (ProxyZoneSpec === undefined) { - throw new Error('ProxyZoneSpec is needed for the async() test helper but could not be found. ' + - 'Please make sure that your environment includes zone.js/dist/proxy.js'); + function runInTestZone(fn, context, finishCallback, failCallback) { + var currentZone = Zone.current; + var AsyncTestZoneSpec = Zone['AsyncTestZoneSpec']; + if (AsyncTestZoneSpec === undefined) { + throw new Error('AsyncTestZoneSpec is needed for the async() test helper but could not be found. ' + + 'Please make sure that your environment includes zone.js/dist/async-test.js'); + } + var ProxyZoneSpec = Zone['ProxyZoneSpec']; + if (ProxyZoneSpec === undefined) { + throw new Error('ProxyZoneSpec is needed for the async() test helper but could not be found. ' + + 'Please make sure that your environment includes zone.js/dist/proxy.js'); + } + var proxyZoneSpec = ProxyZoneSpec.get(); + ProxyZoneSpec.assertPresent(); + // We need to create the AsyncTestZoneSpec outside the ProxyZone. + // If we do it in ProxyZone then we will get to infinite recursion. + var proxyZone = Zone.current.getZoneWith('ProxyZoneSpec'); + var previousDelegate = proxyZoneSpec.getDelegate(); + proxyZone.parent.run(function () { + var testZoneSpec = new AsyncTestZoneSpec(function () { + // Need to restore the original zone. + if (proxyZoneSpec.getDelegate() == testZoneSpec) { + // Only reset the zone spec if it's + // sill this one. Otherwise, assume + // it's OK. + proxyZoneSpec.setDelegate(previousDelegate); + } + currentZone.run(function () { + finishCallback(); + }); + }, function (error) { + // Need to restore the original zone. + if (proxyZoneSpec.getDelegate() == testZoneSpec) { + // Only reset the zone spec if it's sill this one. Otherwise, assume it's OK. + proxyZoneSpec.setDelegate(previousDelegate); + } + currentZone.run(function () { + failCallback(error); + }); + }, 'test'); + proxyZoneSpec.setDelegate(testZoneSpec); + }); + return Zone.current.runGuarded(fn, context); } - var proxyZoneSpec = ProxyZoneSpec.get(); - ProxyZoneSpec.assertPresent(); - // We need to create the AsyncTestZoneSpec outside the ProxyZone. - // If we do it in ProxyZone then we will get to infinite recursion. - var proxyZone = Zone.current.getZoneWith('ProxyZoneSpec'); - var previousDelegate = proxyZoneSpec.getDelegate(); - proxyZone.parent.run(function () { - var testZoneSpec = new AsyncTestZoneSpec(function () { - // Need to restore the original zone. - if (proxyZoneSpec.getDelegate() == testZoneSpec) { - // Only reset the zone spec if it's - // sill this one. Otherwise, assume - // it's OK. - proxyZoneSpec.setDelegate(previousDelegate); - } - currentZone.run(function () { - finishCallback(); - }); - }, function (error) { - // Need to restore the original zone. - if (proxyZoneSpec.getDelegate() == testZoneSpec) { - // Only reset the zone spec if it's sill this one. Otherwise, assume it's OK. - proxyZoneSpec.setDelegate(previousDelegate); - } - currentZone.run(function () { - failCallback(error); - }); - }, 'test'); - proxyZoneSpec.setDelegate(testZoneSpec); - }); - return Zone.current.runGuarded(fn, context); -} +}); /** * @license @@ -1352,136 +1370,145 @@ function runInTestZone(fn, context, finishCallback, failCallback) { * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ -var FakeAsyncTestZoneSpec = Zone && Zone['FakeAsyncTestZoneSpec']; -var ProxyZoneSpec$1 = Zone && Zone['ProxyZoneSpec']; -var _fakeAsyncTestZoneSpec = null; -/** - * Clears out the shared fake async zone for a test. - * To be called in a global `beforeEach`. - * - * @experimental - */ -function resetFakeAsyncZone() { - _fakeAsyncTestZoneSpec = null; - // in node.js testing we may not have ProxyZoneSpec in which case there is nothing to reset. - ProxyZoneSpec$1 && ProxyZoneSpec$1.assertPresent().resetDelegate(); -} -var _inFakeAsyncCall = false; -/** - * Wraps a function to be executed in the fakeAsync zone: - * - microtasks are manually executed by calling `flushMicrotasks()`, - * - timers are synchronous, `tick()` simulates the asynchronous passage of time. - * - * If there are any pending timers at the end of the function, an exception will be thrown. - * - * Can be used to wrap inject() calls. - * - * ## Example - * - * {@example core/testing/ts/fake_async.ts region='basic'} - * - * @param fn - * @returns The function wrapped to be executed in the fakeAsync zone - * - * @experimental - */ -function fakeAsync(fn) { - // Not using an arrow function to preserve context passed from call site - return function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - var proxyZoneSpec = ProxyZoneSpec$1.assertPresent(); - if (_inFakeAsyncCall) { - throw new Error('fakeAsync() calls can not be nested'); +Zone.__load_patch('fakeasync', function (global, Zone, api) { + var FakeAsyncTestZoneSpec = Zone && Zone['FakeAsyncTestZoneSpec']; + var ProxyZoneSpec = Zone && Zone['ProxyZoneSpec']; + var _fakeAsyncTestZoneSpec = null; + /** + * Clears out the shared fake async zone for a test. + * To be called in a global `beforeEach`. + * + * @experimental + */ + function resetFakeAsyncZone() { + if (_fakeAsyncTestZoneSpec) { + _fakeAsyncTestZoneSpec.unlockDatePatch(); } - _inFakeAsyncCall = true; - try { - if (!_fakeAsyncTestZoneSpec) { - if (proxyZoneSpec.getDelegate() instanceof FakeAsyncTestZoneSpec) { - throw new Error('fakeAsync() calls can not be nested'); - } - _fakeAsyncTestZoneSpec = new FakeAsyncTestZoneSpec(); + _fakeAsyncTestZoneSpec = null; + // in node.js testing we may not have ProxyZoneSpec in which case there is nothing to reset. + ProxyZoneSpec && ProxyZoneSpec.assertPresent().resetDelegate(); + } + /** + * Wraps a function to be executed in the fakeAsync zone: + * - microtasks are manually executed by calling `flushMicrotasks()`, + * - timers are synchronous, `tick()` simulates the asynchronous passage of time. + * + * If there are any pending timers at the end of the function, an exception will be thrown. + * + * Can be used to wrap inject() calls. + * + * ## Example + * + * {@example core/testing/ts/fake_async.ts region='basic'} + * + * @param fn + * @returns The function wrapped to be executed in the fakeAsync zone + * + * @experimental + */ + function fakeAsync(fn) { + // Not using an arrow function to preserve context passed from call site + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var proxyZoneSpec = ProxyZoneSpec.assertPresent(); + if (Zone.current.get('FakeAsyncTestZoneSpec')) { + throw new Error('fakeAsync() calls can not be nested'); } - var res = void 0; - var lastProxyZoneSpec = proxyZoneSpec.getDelegate(); - proxyZoneSpec.setDelegate(_fakeAsyncTestZoneSpec); try { - res = fn.apply(this, args); - flushMicrotasks(); + // in case jasmine.clock init a fakeAsyncTestZoneSpec + if (!_fakeAsyncTestZoneSpec) { + if (proxyZoneSpec.getDelegate() instanceof FakeAsyncTestZoneSpec) { + throw new Error('fakeAsync() calls can not be nested'); + } + _fakeAsyncTestZoneSpec = new FakeAsyncTestZoneSpec(); + } + var res = void 0; + var lastProxyZoneSpec = proxyZoneSpec.getDelegate(); + proxyZoneSpec.setDelegate(_fakeAsyncTestZoneSpec); + _fakeAsyncTestZoneSpec.lockDatePatch(); + try { + res = fn.apply(this, args); + flushMicrotasks(); + } + finally { + proxyZoneSpec.setDelegate(lastProxyZoneSpec); + } + if (_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length > 0) { + throw new Error(_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length + " " + + "periodic timer(s) still in the queue."); + } + if (_fakeAsyncTestZoneSpec.pendingTimers.length > 0) { + throw new Error(_fakeAsyncTestZoneSpec.pendingTimers.length + " timer(s) still in the queue."); + } + return res; } finally { - proxyZoneSpec.setDelegate(lastProxyZoneSpec); - } - if (_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length > 0) { - throw new Error(_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length + " " + - "periodic timer(s) still in the queue."); + resetFakeAsyncZone(); } - if (_fakeAsyncTestZoneSpec.pendingTimers.length > 0) { - throw new Error(_fakeAsyncTestZoneSpec.pendingTimers.length + " timer(s) still in the queue."); + }; + } + function _getFakeAsyncZoneSpec() { + if (_fakeAsyncTestZoneSpec == null) { + _fakeAsyncTestZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); + if (_fakeAsyncTestZoneSpec == null) { + throw new Error('The code should be running in the fakeAsync zone to call this function'); } - return res; - } - finally { - _inFakeAsyncCall = false; - resetFakeAsyncZone(); } - }; -} -function _getFakeAsyncZoneSpec() { - if (_fakeAsyncTestZoneSpec == null) { - throw new Error('The code should be running in the fakeAsync zone to call this function'); + return _fakeAsyncTestZoneSpec; } - return _fakeAsyncTestZoneSpec; -} -/** - * Simulates the asynchronous passage of time for the timers in the fakeAsync zone. - * - * The microtasks queue is drained at the very start of this function and after any timer callback - * has been executed. - * - * ## Example - * - * {@example core/testing/ts/fake_async.ts region='basic'} - * - * @experimental - */ -function tick(millis) { - if (millis === void 0) { millis = 0; } - _getFakeAsyncZoneSpec().tick(millis); -} -/** - * Simulates the asynchronous passage of time for the timers in the fakeAsync zone by - * draining the macrotask queue until it is empty. The returned value is the milliseconds - * of time that would have been elapsed. - * - * @param maxTurns - * @returns The simulated time elapsed, in millis. - * - * @experimental - */ -function flush(maxTurns) { - return _getFakeAsyncZoneSpec().flush(maxTurns); -} -/** - * Discard all remaining periodic tasks. - * - * @experimental - */ -function discardPeriodicTasks() { - var zoneSpec = _getFakeAsyncZoneSpec(); - var pendingTimers = zoneSpec.pendingPeriodicTimers; - zoneSpec.pendingPeriodicTimers.length = 0; -} -/** - * Flush any pending microtasks. - * - * @experimental - */ -function flushMicrotasks() { - _getFakeAsyncZoneSpec().flushMicrotasks(); -} + /** + * Simulates the asynchronous passage of time for the timers in the fakeAsync zone. + * + * The microtasks queue is drained at the very start of this function and after any timer callback + * has been executed. + * + * ## Example + * + * {@example core/testing/ts/fake_async.ts region='basic'} + * + * @experimental + */ + function tick(millis) { + if (millis === void 0) { millis = 0; } + _getFakeAsyncZoneSpec().tick(millis); + } + /** + * Simulates the asynchronous passage of time for the timers in the fakeAsync zone by + * draining the macrotask queue until it is empty. The returned value is the milliseconds + * of time that would have been elapsed. + * + * @param maxTurns + * @returns The simulated time elapsed, in millis. + * + * @experimental + */ + function flush(maxTurns) { + return _getFakeAsyncZoneSpec().flush(maxTurns); + } + /** + * Discard all remaining periodic tasks. + * + * @experimental + */ + function discardPeriodicTasks() { + var zoneSpec = _getFakeAsyncZoneSpec(); + var pendingTimers = zoneSpec.pendingPeriodicTimers; + zoneSpec.pendingPeriodicTimers.length = 0; + } + /** + * Flush any pending microtasks. + * + * @experimental + */ + function flushMicrotasks() { + _getFakeAsyncZoneSpec().flushMicrotasks(); + } + Zone[api.symbol('fakeAsyncTest')] = + { resetFakeAsyncZone: resetFakeAsyncZone, flushMicrotasks: flushMicrotasks, discardPeriodicTasks: discardPeriodicTasks, tick: tick, flush: flush, fakeAsync: fakeAsync }; +}); /** * @license @@ -1492,14 +1519,4 @@ function flushMicrotasks() { */ // load test related files into bundle in correct order -exports.asyncTest = asyncTest; -exports.resetFakeAsyncZone = resetFakeAsyncZone; -exports.fakeAsync = fakeAsync; -exports.tick = tick; -exports.flush = flush; -exports.discardPeriodicTasks = discardPeriodicTasks; -exports.flushMicrotasks = flushMicrotasks; - -Object.defineProperty(exports, '__esModule', { value: true }); - }))); diff --git a/dist/zone.js b/dist/zone.js index 2cd0134c8..e15c127cf 100644 --- a/dist/zone.js +++ b/dist/zone.js @@ -643,16 +643,6 @@ var Zone$1 = (function (global) { return global['Zone'] = Zone; })(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global); -var __values = (undefined && undefined.__values) || function (o) { - var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; - if (m) return m.call(o); - return { - next: function () { - if (o && i >= o.length) o = void 0; - return { value: o && o[i++], done: !o }; - } - }; -}; Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { var ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; var ObjectDefineProperty = Object.defineProperty; @@ -926,24 +916,14 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { function onReject(error) { promise && (promise = null || reject(error)); } - try { - for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) { - var value = values_1_1.value; - if (!isThenable(value)) { - value = this.resolve(value); - } - value.then(onResolve, onReject); - } - } - catch (e_1_1) { e_1 = { error: e_1_1 }; } - finally { - try { - if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1); + for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { + var value = values_1[_i]; + if (!isThenable(value)) { + value = this.resolve(value); } - finally { if (e_1) throw e_1.error; } + value.then(onResolve, onReject); } return promise; - var e_1, _a; }; ZoneAwarePromise.all = function (values) { var resolve; @@ -954,33 +934,23 @@ Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { }); var count = 0; var resolvedValues = []; - try { - for (var values_2 = __values(values), values_2_1 = values_2.next(); !values_2_1.done; values_2_1 = values_2.next()) { - var value = values_2_1.value; - if (!isThenable(value)) { - value = this.resolve(value); + for (var _i = 0, values_2 = values; _i < values_2.length; _i++) { + var value = values_2[_i]; + if (!isThenable(value)) { + value = this.resolve(value); + } + value.then((function (index) { return function (value) { + resolvedValues[index] = value; + count--; + if (!count) { + resolve(resolvedValues); } - value.then((function (index) { return function (value) { - resolvedValues[index] = value; - count--; - if (!count) { - resolve(resolvedValues); - } - }; })(count), reject); - count++; - } - } - catch (e_2_1) { e_2 = { error: e_2_1 }; } - finally { - try { - if (values_2_1 && !values_2_1.done && (_a = values_2.return)) _a.call(values_2); - } - finally { if (e_2) throw e_2.error; } + }; })(count), reject); + count++; } if (!count) resolve(resolvedValues); return promise; - var e_2, _a; }; ZoneAwarePromise.prototype.then = function (onFulfilled, onRejected) { var chainPromise = new this.constructor(null); diff --git a/dist/zone.min.js b/dist/zone.min.js index 7d809e8d1..b95e78412 100644 --- a/dist/zone.min.js +++ b/dist/zone.min.js @@ -1,2 +1,2 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t():"function"==typeof define&&define.amd?define(t):t()}(this,function(){"use strict";function e(e,t){return Zone.current.wrap(e,t)}function t(e,t,n,r,o){return Zone.current.scheduleMacroTask(e,t,n,r,o)}function n(t,n){for(var r=t.length-1;r>=0;r--)"function"==typeof t[r]&&(t[r]=e(t[r],n+"_"+r));return t}function r(e,t){for(var r=e.constructor.name,a=function(a){var i=t[a],s=e[i];if(s){var c=j(e,i);if(!o(c))return"continue";e[i]=function(e){var t=function(){return e.apply(this,n(arguments,r+"."+i))};return l(t,e),t}(s)}},i=0;i=0&&"function"==typeof a[i.cbIdx]?t(i.name,a[i.cbIdx],i,o,null):e.apply(n,a)}})}function l(e,t){e[N("OriginalDelegate")]=t}function f(){if(ne)return re;ne=!0;try{var e=X.navigator.userAgent;return e.indexOf("MSIE ")===-1&&e.indexOf("Trident/")===-1&&e.indexOf("Edge/")===-1||(re=!0),re}catch(t){}}function p(e,t,n){function r(t,n){if(!t)return!1;var r=!0;n&&void 0!==n.useG&&(r=n.useG);var d=n&&n.vh,y=!0;n&&void 0!==n.chkDup&&(y=n.chkDup);var m=!1;n&&void 0!==n.rt&&(m=n.rt);for(var k=t;k&&!k.hasOwnProperty(o);)k=I(k);if(!k&&t[o]&&(k=t),!k)return!1;if(k[c])return!1;var _,b={},T=k[c]=k[o],w=k[N(a)]=k[a],E=k[N(i)]=k[i],S=k[N(s)]=k[s];n&&n.prepend&&(_=k[N(n.prepend)]=k[n.prepend]);var D=function(){if(!b.isExisting)return T.call(b.target,b.eventName,b.capture?g:v,b.options)},Z=function(e){if(!e.isRemoved){var t=ae[e.eventName],n=void 0;t&&(n=t[e.capture?q:A]);var r=n&&e.target[n];if(r)for(var o=0;o1?new n(e,t):new n(e),s=j(a,"onmessage");return s&&s.configurable===!1?(r=L(a),o=a,[R,x,"send","close"].forEach(function(e){r[e]=function(){var t=M.call(arguments);if(e===R||e===x){var n=t.length>0?t[0]:void 0;if(n){var o=Zone.__symbol__("ON_PROPERTY"+n);a[o]=r[o]}}return a[e].apply(a,t)}})):r=a,i(r,["close","error","message","open"],o),r};var r=t.WebSocket;for(var o in n)r[o]=n[o]}function T(e,t,n){if(!n)return t;var r=n.filter(function(t){return t.target===e});if(!r||0===r.length)return t;var o=r[0].ignoreProperties;return t.filter(function(e){return o.indexOf(e)===-1})}function w(e,t,n,r){if(e){var o=T(e,t,n);i(e,o,r)}}function E(e,t){if(!J||Q){var n="undefined"!=typeof WebSocket;if(S()){var r=t.__Zone_ignore_on_properties;if(Y){var o=window;w(o,Pe.concat(["messageerror"]),r,I(o)),w(Document.prototype,Pe,r),"undefined"!=typeof o.SVGElement&&w(o.SVGElement.prototype,Pe,r),w(Element.prototype,Pe,r),w(HTMLElement.prototype,Pe,r),w(HTMLMediaElement.prototype,me,r),w(HTMLFrameSetElement.prototype,ge.concat(Ee),r),w(HTMLBodyElement.prototype,ge.concat(Ee),r),w(HTMLFrameElement.prototype,we,r),w(HTMLIFrameElement.prototype,we,r);var a=o.HTMLMarqueeElement;a&&w(a.prototype,Se,r);var i=o.Worker;i&&w(i.prototype,Oe,r)}w(XMLHttpRequest.prototype,De,r);var c=t.XMLHttpRequestEventTarget;c&&w(c&&c.prototype,De,r),"undefined"!=typeof IDBIndex&&(w(IDBIndex.prototype,Ze,r),w(IDBRequest.prototype,Ze,r),w(IDBOpenDBRequest.prototype,Ze,r),w(IDBDatabase.prototype,Ze,r),w(IDBTransaction.prototype,Ze,r),w(IDBCursor.prototype,Ze,r)),n&&w(WebSocket.prototype,ze,r)}else D(),s("XMLHttpRequest"),n&&b(e,t)}}function S(){if((Y||Q)&&!j(HTMLElement.prototype,"onclick")&&"undefined"!=typeof Element){var e=j(Element.prototype,"onclick");if(e&&!e.configurable)return!1}var t="onreadystatechange",n=XMLHttpRequest.prototype,r=j(n,t);if(r){C(n,t,{enumerable:!0,configurable:!0,get:function(){return!0}});var o=new XMLHttpRequest,a=!!o.onreadystatechange;return C(n,t,r||{}),a}var i=N("fake");C(n,t,{enumerable:!0,configurable:!0,get:function(){return this[i]},set:function(e){this[i]=e}});var o=new XMLHttpRequest,s=function(){};o.onreadystatechange=s;var a=o[i]===s;return o.onreadystatechange=null,a}function D(){for(var t=function(t){var n=Pe[t],r="on"+n;self.addEventListener(n,function(t){var n,o,a=t.target;for(o=a?a.constructor.name+"."+r:"unknown."+r;a;)a[r]&&!a[r][je]&&(n=e(a[r],o),n[je]=a[r],a[r]=n),a=a.parentElement},!0)},n=0;n",this._properties=t&&t.properties||{},this._zoneDelegate=new p(this,this._parent&&this._parent._zoneDelegate,t)}return r.assertZonePatched=function(){if(e.Promise!==O.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")},Object.defineProperty(r,"root",{get:function(){for(var e=r.current;e.parent;)e=e.parent;return e},enumerable:!0,configurable:!0}),Object.defineProperty(r,"current",{get:function(){return j.zone},enumerable:!0,configurable:!0}),Object.defineProperty(r,"currentTask",{get:function(){return C},enumerable:!0,configurable:!0}),r.__load_patch=function(o,a){if(O.hasOwnProperty(o))throw Error("Already loaded patch: "+o);if(!e["__Zone_disable_"+o]){var i="Zone:"+o;t(i),O[o]=a(e,r,P),n(i,i)}},Object.defineProperty(r.prototype,"parent",{get:function(){return this._parent},enumerable:!0,configurable:!0}),Object.defineProperty(r.prototype,"name",{get:function(){return this._name},enumerable:!0,configurable:!0}),r.prototype.get=function(e){var t=this.getZoneWith(e);if(t)return t._properties[e]},r.prototype.getZoneWith=function(e){for(var t=this;t;){if(t._properties.hasOwnProperty(e))return t;t=t._parent}return null},r.prototype.fork=function(e){if(!e)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,e)},r.prototype.wrap=function(e,t){if(typeof e!==s)throw new Error("Expecting function got: "+e);var n=this._zoneDelegate.intercept(this,e,t),r=this;return function(){return r.runGuarded(n,this,arguments,t)}},r.prototype.run=function(e,t,n,r){void 0===t&&(t=void 0),void 0===n&&(n=null),void 0===r&&(r=null),j={parent:j,zone:this};try{return this._zoneDelegate.invoke(this,e,t,n,r)}finally{j=j.parent}},r.prototype.runGuarded=function(e,t,n,r){void 0===t&&(t=null),void 0===n&&(n=null),void 0===r&&(r=null),j={parent:j,zone:this};try{try{return this._zoneDelegate.invoke(this,e,t,n,r)}catch(o){if(this._zoneDelegate.handleError(this,o))throw o}}finally{j=j.parent}},r.prototype.runTask=function(e,t,n){if(e.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(e.zone||k).name+"; Execution: "+this.name+")");var r=e.state===_;if(!r||e.type!==z){var o=e.state!=w;o&&e._transitionTo(w,T),e.runCount++;var a=C;C=e,j={parent:j,zone:this};try{e.type==Z&&e.data&&!e.data.isPeriodic&&(e.cancelFn=null);try{return this._zoneDelegate.invokeTask(this,e,t,n)}catch(i){if(this._zoneDelegate.handleError(this,i))throw i}}finally{e.state!==_&&e.state!==S&&(e.type==z||e.data&&e.data.isPeriodic?o&&e._transitionTo(T,w):(e.runCount=0,this._updateTaskCount(e,-1),o&&e._transitionTo(_,w,_))),j=j.parent,C=a}}},r.prototype.scheduleTask=function(e){if(e.zone&&e.zone!==this)for(var t=this;t;){if(t===e.zone)throw Error("can not reschedule task to "+this.name+" which is descendants of the original zone "+e.zone.name);t=t.parent}e._transitionTo(b,_);var n=[];e._zoneDelegates=n,e._zone=this;try{e=this._zoneDelegate.scheduleTask(this,e)}catch(r){throw e._transitionTo(S,b,_),this._zoneDelegate.handleError(this,r),r}return e._zoneDelegates===n&&this._updateTaskCount(e,1),e.state==b&&e._transitionTo(T,b),e},r.prototype.scheduleMicroTask=function(e,t,n,r){return this.scheduleTask(new h(D,e,t,n,r,null))},r.prototype.scheduleMacroTask=function(e,t,n,r,o){return this.scheduleTask(new h(Z,e,t,n,r,o))},r.prototype.scheduleEventTask=function(e,t,n,r,o){return this.scheduleTask(new h(z,e,t,n,r,o))},r.prototype.cancelTask=function(e){if(e.zone!=this)throw new Error("A task can only be cancelled in the zone of creation! (Creation: "+(e.zone||k).name+"; Execution: "+this.name+")");e._transitionTo(E,T,w);try{this._zoneDelegate.cancelTask(this,e)}catch(t){throw e._transitionTo(S,E),this._zoneDelegate.handleError(this,t),t}return this._updateTaskCount(e,-1),e._transitionTo(_,E),e.runCount=0,e},r.prototype._updateTaskCount=function(e,t){var n=e._zoneDelegates;t==-1&&(e._zoneDelegates=null);for(var r=0;r0,macroTask:n.macroTask>0,eventTask:n.eventTask>0,change:e};this.hasTask(this.zone,a)}},e}(),h=function(){function t(n,r,o,a,i,s){this._zone=null,this.runCount=0,this._zoneDelegates=null,this._state="notScheduled",this.type=n,this.source=r,this.data=a,this.scheduleFn=i,this.cancelFn=s,this.callback=o;var c=this;n===z&&a&&a.useG?this.invoke=t.invokeTask:this.invoke=function(){return t.invokeTask.call(e,c,this,arguments)}}return t.invokeTask=function(e,t,n){e||(e=this),I++;try{return e.runCount++,e.zone.runTask(e,t,n)}finally{1==I&&o(),I--}},Object.defineProperty(t.prototype,"zone",{get:function(){return this._zone},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"state",{get:function(){return this._state},enumerable:!0,configurable:!0}),t.prototype.cancelScheduleRequest=function(){this._transitionTo(_,b)},t.prototype._transitionTo=function(e,t,n){if(this._state!==t&&this._state!==n)throw new Error(this.type+" '"+this.source+"': can not transition to '"+e+"', expecting state '"+t+"'"+(n?" or '"+n+"'":"")+", was '"+this._state+"'.");this._state=e,e==_&&(this._zoneDelegates=null)},t.prototype.toString=function(){return this.data&&"undefined"!=typeof this.data.handleId?this.data.handleId:Object.prototype.toString.call(this)},t.prototype.toJSON=function(){return{type:this.type,state:this.state,source:this.source,zone:this.zone.name,runCount:this.runCount}},t}(),d=i("setTimeout"),v=i("Promise"),g=i("then"),y=[],m=!1,k={name:"NO ZONE"},_="notScheduled",b="scheduling",T="scheduled",w="running",E="canceling",S="unknown",D="microTask",Z="macroTask",z="eventTask",O={},P={symbol:i,currentZoneFrame:function(){return j},onUnhandledError:a,microtaskDrainDone:a,scheduleMicroTask:r,showUncaughtError:function(){return!l[i("ignoreConsoleErrorUncaughtError")]},patchEventTarget:function(){return[]},patchOnProperties:a,patchMethod:function(){return a},bindArguments:function(){return null},setNativePromise:function(e){e&&typeof e.resolve===s&&(u=e.resolve(0))}},j={parent:null,zone:new l(null,null)},C=null,I=0;return n("Zone","Zone"),e.Zone=l}("undefined"!=typeof window&&window||"undefined"!=typeof self&&self||global),function(e){var t="function"==typeof Symbol&&e[Symbol.iterator],n=0;return t?t.call(e):{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}}});Zone.__load_patch("ZoneAwarePromise",function(e,t,n){function r(e){if(e&&e.toString===Object.prototype.toString){var t=e.constructor&&e.constructor.name;return(t?t:"")+": "+JSON.stringify(e)}return e?e.toString():Object.prototype.toString.call(e)}function o(e){n.onUnhandledError(e);try{var r=t[b];r&&"function"==typeof r&&r.call(this,e)}catch(o){}}function a(e){return e&&e.then}function i(e){return e}function s(e){return H.reject(e)}function c(e,t){return function(n){try{u(e,t,n)}catch(r){u(e,!1,r)}}}function u(e,o,a){var i=I();if(e===a)throw new TypeError(L);if(e[T]===z){var s=null;try{"object"!=typeof a&&"function"!=typeof a||(s=a&&a.then)}catch(p){return i(function(){u(e,!1,p)})(),e}if(o!==j&&a instanceof H&&a.hasOwnProperty(T)&&a.hasOwnProperty(w)&&a[T]!==z)l(a),u(e,a[T],a[w]);else if(o!==j&&"function"==typeof s)try{s.call(a,i(c(e,o)),i(c(e,!1)))}catch(p){i(function(){u(e,!1,p)})()}else{e[T]=o;var h=e[w];if(e[w]=a,e[E]===E&&o===O&&(e[T]=e[D],e[w]=e[S]),o===j&&a instanceof Error){var d=t.currentTask&&t.currentTask.data&&t.currentTask.data[_];d&&v(a,M,{configurable:!0,enumerable:!1,writable:!0,value:d})}for(var g=0;g=0;r--)"function"==typeof t[r]&&(t[r]=e(t[r],n+"_"+r));return t}function r(e,t){for(var r=e.constructor.name,a=function(a){var i=t[a],s=e[i];if(s){var c=P(e,i);if(!o(c))return"continue";e[i]=function(e){var t=function(){return e.apply(this,n(arguments,r+"."+i))};return l(t,e),t}(s)}},i=0;i=0&&"function"==typeof a[i.cbIdx]?t(i.name,a[i.cbIdx],i,o,null):e.apply(n,a)}})}function l(e,t){e[B("OriginalDelegate")]=t}function f(){if(te)return ne;te=!0;try{var e=W.navigator.userAgent;return e.indexOf("MSIE ")===-1&&e.indexOf("Trident/")===-1&&e.indexOf("Edge/")===-1||(ne=!0),ne}catch(t){}}function p(e,t,n){function r(t,n){if(!t)return!1;var r=!0;n&&void 0!==n.useG&&(r=n.useG);var d=n&&n.vh,y=!0;n&&void 0!==n.chkDup&&(y=n.chkDup);var m=!1;n&&void 0!==n.rt&&(m=n.rt);for(var k=t;k&&!k.hasOwnProperty(o);)k=C(k);if(!k&&t[o]&&(k=t),!k)return!1;if(k[c])return!1;var _,b={},T=k[c]=k[o],w=k[B(a)]=k[a],E=k[B(i)]=k[i],S=k[B(s)]=k[s];n&&n.prepend&&(_=k[B(n.prepend)]=k[n.prepend]);var D=function(){if(!b.isExisting)return T.call(b.target,b.eventName,b.capture?g:v,b.options)},Z=function(e){if(!e.isRemoved){var t=oe[e.eventName],n=void 0;t&&(n=t[e.capture?F:q]);var r=n&&e.target[n];if(r)for(var o=0;o1?new n(e,t):new n(e),s=P(a,"onmessage");return s&&s.configurable===!1?(r=I(a),o=a,[M,R,"send","close"].forEach(function(e){r[e]=function(){var t=L.call(arguments);if(e===M||e===R){var n=t.length>0?t[0]:void 0;if(n){var o=Zone.__symbol__("ON_PROPERTY"+n);a[o]=r[o]}}return a[e].apply(a,t)}})):r=a,i(r,["close","error","message","open"],o),r};var r=t.WebSocket;for(var o in n)r[o]=n[o]}function T(e,t,n){if(!n)return t;var r=n.filter(function(t){return t.target===e});if(!r||0===r.length)return t;var o=r[0].ignoreProperties;return t.filter(function(e){return o.indexOf(e)===-1})}function w(e,t,n,r){if(e){var o=T(e,t,n);i(e,o,r)}}function E(e,t){if(!K||Y){var n="undefined"!=typeof WebSocket;if(S()){var r=t.__Zone_ignore_on_properties;if(J){var o=window;w(o,Oe.concat(["messageerror"]),r,C(o)),w(Document.prototype,Oe,r),"undefined"!=typeof o.SVGElement&&w(o.SVGElement.prototype,Oe,r),w(Element.prototype,Oe,r),w(HTMLElement.prototype,Oe,r),w(HTMLMediaElement.prototype,ye,r),w(HTMLFrameSetElement.prototype,ve.concat(we),r),w(HTMLBodyElement.prototype,ve.concat(we),r),w(HTMLFrameElement.prototype,Te,r),w(HTMLIFrameElement.prototype,Te,r);var a=o.HTMLMarqueeElement;a&&w(a.prototype,Ee,r);var i=o.Worker;i&&w(i.prototype,ze,r)}w(XMLHttpRequest.prototype,Se,r);var c=t.XMLHttpRequestEventTarget;c&&w(c&&c.prototype,Se,r),"undefined"!=typeof IDBIndex&&(w(IDBIndex.prototype,De,r),w(IDBRequest.prototype,De,r),w(IDBOpenDBRequest.prototype,De,r),w(IDBDatabase.prototype,De,r),w(IDBTransaction.prototype,De,r),w(IDBCursor.prototype,De,r)),n&&w(WebSocket.prototype,Ze,r)}else D(),s("XMLHttpRequest"),n&&b(e,t)}}function S(){if((J||Y)&&!P(HTMLElement.prototype,"onclick")&&"undefined"!=typeof Element){var e=P(Element.prototype,"onclick");if(e&&!e.configurable)return!1}var t="onreadystatechange",n=XMLHttpRequest.prototype,r=P(n,t);if(r){j(n,t,{enumerable:!0,configurable:!0,get:function(){return!0}});var o=new XMLHttpRequest,a=!!o.onreadystatechange;return j(n,t,r||{}),a}var i=B("fake");j(n,t,{enumerable:!0,configurable:!0,get:function(){return this[i]},set:function(e){this[i]=e}});var o=new XMLHttpRequest,s=function(){};o.onreadystatechange=s;var a=o[i]===s;return o.onreadystatechange=null,a}function D(){for(var t=function(t){var n=Oe[t],r="on"+n;self.addEventListener(n,function(t){var n,o,a=t.target;for(o=a?a.constructor.name+"."+r:"unknown."+r;a;)a[r]&&!a[r][Pe]&&(n=e(a[r],o),n[Pe]=a[r],a[r]=n),a=a.parentElement},!0)},n=0;n",this._properties=t&&t.properties||{},this._zoneDelegate=new p(this,this._parent&&this._parent._zoneDelegate,t)}return r.assertZonePatched=function(){if(e.Promise!==O.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")},Object.defineProperty(r,"root",{get:function(){for(var e=r.current;e.parent;)e=e.parent;return e},enumerable:!0,configurable:!0}),Object.defineProperty(r,"current",{get:function(){return j.zone},enumerable:!0,configurable:!0}),Object.defineProperty(r,"currentTask",{get:function(){return C},enumerable:!0,configurable:!0}),r.__load_patch=function(o,a){if(O.hasOwnProperty(o))throw Error("Already loaded patch: "+o);if(!e["__Zone_disable_"+o]){var i="Zone:"+o;t(i),O[o]=a(e,r,P),n(i,i)}},Object.defineProperty(r.prototype,"parent",{get:function(){return this._parent},enumerable:!0,configurable:!0}),Object.defineProperty(r.prototype,"name",{get:function(){return this._name},enumerable:!0,configurable:!0}),r.prototype.get=function(e){var t=this.getZoneWith(e);if(t)return t._properties[e]},r.prototype.getZoneWith=function(e){for(var t=this;t;){if(t._properties.hasOwnProperty(e))return t;t=t._parent}return null},r.prototype.fork=function(e){if(!e)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,e)},r.prototype.wrap=function(e,t){if(typeof e!==s)throw new Error("Expecting function got: "+e);var n=this._zoneDelegate.intercept(this,e,t),r=this;return function(){return r.runGuarded(n,this,arguments,t)}},r.prototype.run=function(e,t,n,r){void 0===t&&(t=void 0),void 0===n&&(n=null),void 0===r&&(r=null),j={parent:j,zone:this};try{return this._zoneDelegate.invoke(this,e,t,n,r)}finally{j=j.parent}},r.prototype.runGuarded=function(e,t,n,r){void 0===t&&(t=null),void 0===n&&(n=null),void 0===r&&(r=null),j={parent:j,zone:this};try{try{return this._zoneDelegate.invoke(this,e,t,n,r)}catch(o){if(this._zoneDelegate.handleError(this,o))throw o}}finally{j=j.parent}},r.prototype.runTask=function(e,t,n){if(e.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(e.zone||k).name+"; Execution: "+this.name+")");var r=e.state===_;if(!r||e.type!==z){var o=e.state!=w;o&&e._transitionTo(w,T),e.runCount++;var a=C;C=e,j={parent:j,zone:this};try{e.type==Z&&e.data&&!e.data.isPeriodic&&(e.cancelFn=null);try{return this._zoneDelegate.invokeTask(this,e,t,n)}catch(i){if(this._zoneDelegate.handleError(this,i))throw i}}finally{e.state!==_&&e.state!==S&&(e.type==z||e.data&&e.data.isPeriodic?o&&e._transitionTo(T,w):(e.runCount=0,this._updateTaskCount(e,-1),o&&e._transitionTo(_,w,_))),j=j.parent,C=a}}},r.prototype.scheduleTask=function(e){if(e.zone&&e.zone!==this)for(var t=this;t;){if(t===e.zone)throw Error("can not reschedule task to "+this.name+" which is descendants of the original zone "+e.zone.name);t=t.parent}e._transitionTo(b,_);var n=[];e._zoneDelegates=n,e._zone=this;try{e=this._zoneDelegate.scheduleTask(this,e)}catch(r){throw e._transitionTo(S,b,_),this._zoneDelegate.handleError(this,r),r}return e._zoneDelegates===n&&this._updateTaskCount(e,1),e.state==b&&e._transitionTo(T,b),e},r.prototype.scheduleMicroTask=function(e,t,n,r){return this.scheduleTask(new h(D,e,t,n,r,null))},r.prototype.scheduleMacroTask=function(e,t,n,r,o){return this.scheduleTask(new h(Z,e,t,n,r,o))},r.prototype.scheduleEventTask=function(e,t,n,r,o){return this.scheduleTask(new h(z,e,t,n,r,o))},r.prototype.cancelTask=function(e){if(e.zone!=this)throw new Error("A task can only be cancelled in the zone of creation! (Creation: "+(e.zone||k).name+"; Execution: "+this.name+")");e._transitionTo(E,T,w);try{this._zoneDelegate.cancelTask(this,e)}catch(t){throw e._transitionTo(S,E),this._zoneDelegate.handleError(this,t),t}return this._updateTaskCount(e,-1),e._transitionTo(_,E),e.runCount=0,e},r.prototype._updateTaskCount=function(e,t){var n=e._zoneDelegates;t==-1&&(e._zoneDelegates=null);for(var r=0;r0,macroTask:n.macroTask>0,eventTask:n.eventTask>0,change:e};this.hasTask(this.zone,a)}},e}(),h=function(){function t(n,r,o,a,i,s){this._zone=null,this.runCount=0,this._zoneDelegates=null,this._state="notScheduled",this.type=n,this.source=r,this.data=a,this.scheduleFn=i,this.cancelFn=s,this.callback=o;var c=this;n===z&&a&&a.useG?this.invoke=t.invokeTask:this.invoke=function(){return t.invokeTask.call(e,c,this,arguments)}}return t.invokeTask=function(e,t,n){e||(e=this),I++;try{return e.runCount++,e.zone.runTask(e,t,n)}finally{1==I&&o(),I--}},Object.defineProperty(t.prototype,"zone",{get:function(){return this._zone},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"state",{get:function(){return this._state},enumerable:!0,configurable:!0}),t.prototype.cancelScheduleRequest=function(){this._transitionTo(_,b)},t.prototype._transitionTo=function(e,t,n){if(this._state!==t&&this._state!==n)throw new Error(this.type+" '"+this.source+"': can not transition to '"+e+"', expecting state '"+t+"'"+(n?" or '"+n+"'":"")+", was '"+this._state+"'.");this._state=e,e==_&&(this._zoneDelegates=null)},t.prototype.toString=function(){return this.data&&"undefined"!=typeof this.data.handleId?this.data.handleId:Object.prototype.toString.call(this)},t.prototype.toJSON=function(){return{type:this.type,state:this.state,source:this.source,zone:this.zone.name,runCount:this.runCount}},t}(),d=i("setTimeout"),v=i("Promise"),g=i("then"),y=[],m=!1,k={name:"NO ZONE"},_="notScheduled",b="scheduling",T="scheduled",w="running",E="canceling",S="unknown",D="microTask",Z="macroTask",z="eventTask",O={},P={symbol:i,currentZoneFrame:function(){return j},onUnhandledError:a,microtaskDrainDone:a,scheduleMicroTask:r,showUncaughtError:function(){return!l[i("ignoreConsoleErrorUncaughtError")]},patchEventTarget:function(){return[]},patchOnProperties:a,patchMethod:function(){return a},bindArguments:function(){return null},setNativePromise:function(e){e&&typeof e.resolve===s&&(u=e.resolve(0))}},j={parent:null,zone:new l(null,null)},C=null,I=0;return n("Zone","Zone"),e.Zone=l})("undefined"!=typeof window&&window||"undefined"!=typeof self&&self||global);Zone.__load_patch("ZoneAwarePromise",function(e,t,n){function r(e){if(e&&e.toString===Object.prototype.toString){var t=e.constructor&&e.constructor.name;return(t?t:"")+": "+JSON.stringify(e)}return e?e.toString():Object.prototype.toString.call(e)}function o(e){n.onUnhandledError(e);try{var r=t[b];r&&"function"==typeof r&&r.call(this,e)}catch(o){}}function a(e){return e&&e.then}function i(e){return e}function s(e){return H.reject(e)}function c(e,t){return function(n){try{u(e,t,n)}catch(r){u(e,!1,r)}}}function u(e,o,a){var i=C();if(e===a)throw new TypeError(I);if(e[T]===z){var s=null;try{"object"!=typeof a&&"function"!=typeof a||(s=a&&a.then)}catch(p){return i(function(){u(e,!1,p)})(),e}if(o!==P&&a instanceof H&&a.hasOwnProperty(T)&&a.hasOwnProperty(w)&&a[T]!==z)l(a),u(e,a[T],a[w]);else if(o!==P&&"function"==typeof s)try{s.call(a,i(c(e,o)),i(c(e,!1)))}catch(p){i(function(){u(e,!1,p)})()}else{e[T]=o;var h=e[w];if(e[w]=a,e[E]===E&&o===O&&(e[T]=e[D],e[w]=e[S]),o===P&&a instanceof Error){var d=t.currentTask&&t.currentTask.data&&t.currentTask.data[_];d&&v(a,L,{configurable:!0,enumerable:!1,writable:!0,value:d})}for(var g=0;g