From 6c890fa61b5fe5d58dd3126ef148b05468c9fd98 Mon Sep 17 00:00:00 2001 From: Joey Perrott Date: Fri, 19 Apr 2024 16:53:49 +0000 Subject: [PATCH] refactor: migrate zone.js to prettier formatting Migrate formatting to prettier for zone.js from clang-format --- .ng-dev/format.mts | 2 + packages/zone.js/check-file-size.js | 9 +- .../example/benchmarks/event_emitter.js | 16 +- packages/zone.js/example/js/counting-zone.js | 10 +- packages/zone.js/karma-base.conf.js | 14 +- packages/zone.js/karma-build-jasmine.conf.js | 3 +- .../karma-build-jasmine.es2015.conf.js | 3 +- packages/zone.js/karma-build-mocha.conf.js | 7 +- .../zone.js/karma-build-sauce-mocha.conf.js | 2 +- .../karma-build-sauce-selenium3-mocha.conf.js | 2 +- packages/zone.js/karma-build.conf.js | 2 +- packages/zone.js/karma-dist-jasmine.conf.js | 3 +- packages/zone.js/karma-dist-mocha.conf.js | 7 +- .../zone.js/karma-dist-sauce-jasmine.conf.js | 2 +- .../karma-dist-sauce-jasmine.es2015.conf.js | 3 +- .../zone.js/karma-dist-sauce-jasmine3.conf.js | 18 +- ...karma-dist-sauce-selenium3-jasmine.conf.js | 2 +- packages/zone.js/karma-dist.conf.js | 2 +- .../karma-evergreen-dist-jasmine.conf.js | 3 +- ...karma-evergreen-dist-sauce-jasmine.conf.js | 2 +- packages/zone.js/karma-evergreen-dist.conf.js | 2 +- packages/zone.js/lib/browser/api-util.ts | 34 +- .../zone.js/lib/browser/browser-legacy.ts | 14 +- packages/zone.js/lib/browser/browser-util.ts | 13 +- packages/zone.js/lib/browser/browser.ts | 88 +- packages/zone.js/lib/browser/canvas.ts | 7 +- .../zone.js/lib/browser/custom-elements.ts | 11 +- .../zone.js/lib/browser/define-property.ts | 41 +- .../lib/browser/event-target-legacy.ts | 27 +- packages/zone.js/lib/browser/event-target.ts | 2 +- .../lib/browser/property-descriptor-legacy.ts | 127 +- .../lib/browser/property-descriptor.ts | 75 +- .../zone.js/lib/browser/register-element.ts | 8 +- packages/zone.js/lib/browser/shadydom.ts | 13 +- .../lib/browser/webapis-media-query.ts | 2 +- .../lib/browser/webapis-resize-observer.ts | 94 +- .../zone.js/lib/browser/webapis-user-media.ts | 2 +- packages/zone.js/lib/browser/websocket.ts | 29 +- packages/zone.js/lib/common/error-rewrite.ts | 215 +- packages/zone.js/lib/common/events.ts | 197 +- packages/zone.js/lib/common/fetch.ts | 135 +- packages/zone.js/lib/common/promise.ts | 267 +- .../zone.js/lib/common/queue-microtask.ts | 2 +- packages/zone.js/lib/common/timers.ts | 57 +- packages/zone.js/lib/common/to-string.ts | 3 +- packages/zone.js/lib/common/utils.ts | 158 +- packages/zone.js/lib/extra/bluebird.ts | 53 +- packages/zone.js/lib/extra/cordova.ts | 16 +- packages/zone.js/lib/extra/electron.ts | 7 +- packages/zone.js/lib/extra/jsonp.ts | 34 +- packages/zone.js/lib/extra/socket-io.ts | 8 +- packages/zone.js/lib/jasmine/jasmine.ts | 139 +- packages/zone.js/lib/jest/jest.ts | 115 +- packages/zone.js/lib/mocha/mocha.ts | 78 +- packages/zone.js/lib/node/events.ts | 9 +- packages/zone.js/lib/node/fs.ts | 75 +- packages/zone.js/lib/node/main.ts | 2 +- packages/zone.js/lib/node/node.ts | 80 +- packages/zone.js/lib/node/node_util.ts | 8 +- packages/zone.js/lib/rxjs/rxjs.ts | 76 +- .../zone.js/lib/testing/promise-testing.ts | 4 +- packages/zone.js/lib/zone-impl.ts | 578 +- packages/zone.js/lib/zone-spec/async-test.ts | 126 +- .../zone.js/lib/zone-spec/fake-async-test.ts | 240 +- .../zone.js/lib/zone-spec/long-stack-trace.ts | 70 +- packages/zone.js/lib/zone-spec/proxy.ts | 118 +- .../zone.js/lib/zone-spec/task-tracking.ts | 25 +- packages/zone.js/lib/zone-spec/wtf.ts | 94 +- .../zone.js/lib/zone.configurations.api.ts | 2 +- packages/zone.js/lib/zone.ts | 21 +- packages/zone.js/rollup.config.js | 6 +- packages/zone.js/sauce-evergreen.conf.js | 26 +- packages/zone.js/sauce-selenium3.conf.js | 26 +- packages/zone.js/sauce.conf.js | 46 +- packages/zone.js/sauce.es2015.conf.js | 22 +- packages/zone.js/simple-server.js | 8 +- .../zone.js/test/browser/FileReader.spec.ts | 201 +- .../zone.js/test/browser/HTMLImports.spec.ts | 23 +- .../zone.js/test/browser/MediaQuery.spec.ts | 21 +- .../test/browser/MutationObserver.spec.ts | 145 +- .../zone.js/test/browser/Notification.spec.ts | 20 +- .../zone.js/test/browser/WebSocket.spec.ts | 274 +- packages/zone.js/test/browser/Worker.spec.ts | 33 +- .../test/browser/XMLHttpRequest.spec.ts | 542 +- packages/zone.js/test/browser/browser.spec.ts | 6179 +++++++++-------- .../test/browser/custom-element.spec.js | 20 +- .../test/browser/define-property.spec.ts | 31 +- packages/zone.js/test/browser/element.spec.ts | 165 +- .../test/browser/geolocation.spec.manual.ts | 45 +- .../zone.js/test/browser/messageport.spec.ts | 4 +- .../test/browser/registerElement.spec.ts | 138 +- .../browser/requestAnimationFrame.spec.ts | 21 +- .../zone.js/test/browser/shadydom.spec.ts | 9 +- .../zone.js/test/browser_shadydom_setup.ts | 18 +- packages/zone.js/test/closure/zone.closure.ts | 116 +- packages/zone.js/test/common/Error.spec.ts | 299 +- packages/zone.js/test/common/Promise.spec.ts | 1581 +++-- packages/zone.js/test/common/fetch.spec.ts | 486 +- .../zone.js/test/common/microtasks.spec.ts | 90 +- ...le-wrap-uncaught-promise-rejection.spec.ts | 125 +- .../test/common/queue-microtask.spec.ts | 45 +- .../zone.js/test/common/setInterval.spec.ts | 116 +- .../zone.js/test/common/setTimeout.spec.ts | 118 +- packages/zone.js/test/common/task.spec.ts | 2148 +++--- packages/zone.js/test/common/toString.spec.ts | 52 +- packages/zone.js/test/common/util.spec.ts | 226 +- packages/zone.js/test/common/zone.spec.ts | 358 +- packages/zone.js/test/extra/bluebird.spec.ts | 773 ++- packages/zone.js/test/extra/cordova.spec.ts | 36 +- packages/zone.js/test/extra/electron.js | 20 +- packages/zone.js/test/jasmine-patch.spec.ts | 10 +- .../test/jest/jest-zone-patch-fake-timer.js | 2 +- packages/zone.js/test/jest/jest.config.js | 2 +- .../zone.js/test/jest/jest.node.config.js | 2 +- packages/zone.js/test/jest/jest.spec.js | 8 +- packages/zone.js/test/main.ts | 54 +- packages/zone.js/test/mocha-patch.spec.ts | 16 +- packages/zone.js/test/node/Error.spec.ts | 6 +- packages/zone.js/test/node/console.spec.ts | 13 +- packages/zone.js/test/node/crypto.spec.ts | 33 +- packages/zone.js/test/node/events.spec.ts | 18 +- packages/zone.js/test/node/fs.spec.ts | 166 +- packages/zone.js/test/node/http.spec.ts | 28 +- packages/zone.js/test/node/process.spec.ts | 92 +- packages/zone.js/test/node/timer.spec.ts | 33 +- .../test/node_bluebird_entry_point.init.ts | 6 +- .../zone.js/test/node_error_disable_policy.ts | 2 +- .../zone.js/test/node_error_lazy_policy.ts | 2 +- .../test/npm_package/npm_package.spec.ts | 10 +- packages/zone.js/test/patch/IndexedDB.spec.js | 187 +- .../zone.js/test/performance/eventTarget.js | 148 +- .../test/performance/performance_setup.js | 496 +- .../test/performance/performance_ui.js | 280 +- packages/zone.js/test/performance/promise.js | 106 +- .../test/performance/requestAnimationFrame.js | 119 +- packages/zone.js/test/performance/timeout.js | 116 +- packages/zone.js/test/performance/xhr.js | 86 +- .../test/rxjs/rxjs.Observable.audit.spec.ts | 128 +- .../test/rxjs/rxjs.Observable.buffer.spec.ts | 348 +- .../test/rxjs/rxjs.Observable.catch.spec.ts | 91 +- .../rxjs/rxjs.Observable.collection.spec.ts | 822 ++- .../test/rxjs/rxjs.Observable.combine.spec.ts | 179 +- .../test/rxjs/rxjs.Observable.concat.spec.ts | 297 +- .../test/rxjs/rxjs.Observable.count.spec.ts | 33 +- .../rxjs/rxjs.Observable.debounce.spec.ts | 108 +- .../test/rxjs/rxjs.Observable.default.spec.ts | 50 +- .../test/rxjs/rxjs.Observable.delay.spec.ts | 106 +- .../rxjs/rxjs.Observable.distinct.spec.ts | 86 +- .../test/rxjs/rxjs.Observable.do.spec.ts | 35 +- .../test/rxjs/rxjs.Observable.map.spec.ts | 102 +- .../test/rxjs/rxjs.Observable.merge.spec.ts | 297 +- .../rxjs/rxjs.Observable.multicast.spec.ts | 62 +- .../rxjs/rxjs.Observable.notification.spec.ts | 76 +- .../test/rxjs/rxjs.Observable.race.spec.ts | 52 +- .../test/rxjs/rxjs.Observable.retry.spec.ts | 44 +- .../test/rxjs/rxjs.Observable.sample.spec.ts | 111 +- .../test/rxjs/rxjs.Observable.take.spec.ts | 154 +- .../test/rxjs/rxjs.Observable.timeout.spec.ts | 98 +- .../test/rxjs/rxjs.Observable.window.spec.ts | 253 +- packages/zone.js/test/rxjs/rxjs.asap.spec.ts | 100 +- .../test/rxjs/rxjs.bindCallback.spec.ts | 43 +- .../test/rxjs/rxjs.bindNodeCallback.spec.ts | 64 +- .../test/rxjs/rxjs.combineLatest.spec.ts | 52 +- .../zone.js/test/rxjs/rxjs.common.spec.ts | 250 +- .../zone.js/test/rxjs/rxjs.concat.spec.ts | 79 +- packages/zone.js/test/rxjs/rxjs.defer.spec.ts | 2 +- packages/zone.js/test/rxjs/rxjs.empty.spec.ts | 19 +- .../zone.js/test/rxjs/rxjs.forkjoin.spec.ts | 46 +- packages/zone.js/test/rxjs/rxjs.from.spec.ts | 100 +- .../zone.js/test/rxjs/rxjs.fromEvent.spec.ts | 139 +- .../test/rxjs/rxjs.fromPromise.spec.ts | 62 +- .../zone.js/test/rxjs/rxjs.interval.spec.ts | 50 +- packages/zone.js/test/rxjs/rxjs.merge.spec.ts | 72 +- packages/zone.js/test/rxjs/rxjs.never.spec.ts | 21 +- packages/zone.js/test/rxjs/rxjs.of.spec.ts | 23 +- packages/zone.js/test/rxjs/rxjs.range.spec.ts | 67 +- packages/zone.js/test/rxjs/rxjs.retry.spec.ts | 43 +- packages/zone.js/test/rxjs/rxjs.spec.ts | 10 +- packages/zone.js/test/rxjs/rxjs.throw.spec.ts | 67 +- packages/zone.js/test/rxjs/rxjs.timer.spec.ts | 56 +- packages/zone.js/test/rxjs/rxjs.util.ts | 2 +- packages/zone.js/test/rxjs/rxjs.zip.spec.ts | 25 +- packages/zone.js/test/test-env-setup-mocha.ts | 55 +- packages/zone.js/test/test-util.ts | 23 +- packages/zone.js/test/test_fake_polyfill.ts | 42 +- packages/zone.js/test/webdriver/test.js | 15 +- .../test/webdriver/test.sauce.es2015.js | 80 +- packages/zone.js/test/webdriver/test.sauce.js | 74 +- packages/zone.js/test/ws-server.js | 16 +- packages/zone.js/test/wtf_mock.ts | 144 +- .../zone.js/test/zone-spec/async-test.spec.ts | 899 +-- .../fake-async-patched-clock.spec.ts | 2 +- .../fake-async-unpatched-clock.spec.ts | 68 +- .../test/zone-spec/fake-async-test.spec.ts | 975 +-- .../zone-spec/long-stack-trace-zone.spec.ts | 353 +- packages/zone.js/test/zone-spec/proxy.spec.ts | 95 +- .../zone.js/test/zone-spec/sync-test.spec.ts | 62 +- .../test/zone-spec/task-tracking.spec.ts | 9 +- .../zone.js/test/zone_worker_entry_point.ts | 33 +- 199 files changed, 15494 insertions(+), 12741 deletions(-) diff --git a/.ng-dev/format.mts b/.ng-dev/format.mts index c6a12db93b7b7..7ddf2216ed8e2 100644 --- a/.ng-dev/format.mts +++ b/.ng-dev/format.mts @@ -28,6 +28,7 @@ export const format: FormatConfig = { 'packages/router/**/*.{js,ts}', 'packages/service-worker/**/*.{js,ts}', 'packages/upgrade/**/*.{js,ts}', + 'packages/zone.js/**/*.{js,ts}', // Do not format d.ts files as they are generated '!**/*.d.ts', @@ -82,6 +83,7 @@ export const format: FormatConfig = { '!packages/router/**/*.{js,ts}', '!packages/service-worker/**/*.{js,ts}', '!packages/upgrade/**/*.{js,ts}', + '!packages/zone.js/**/*.{js,ts}', ], }, 'buildifier': true, diff --git a/packages/zone.js/check-file-size.js b/packages/zone.js/check-file-size.js index 8835b61c5e016..e8882e607249a 100644 --- a/packages/zone.js/check-file-size.js +++ b/packages/zone.js/check-file-size.js @@ -7,15 +7,16 @@ */ const fs = require('fs'); -module.exports = function(config) { +module.exports = function (config) { let chkResult = true; - config.targets.forEach(target => { + config.targets.forEach((target) => { if (target.checkTarget) { try { const stats = fs.statSync(target.path); if (stats.size > target.limit) { - console.error(`file ${target.path} size over limit, limit is ${target.limit}, actual is ${ - stats.size}`); + console.error( + `file ${target.path} size over limit, limit is ${target.limit}, actual is ${stats.size}`, + ); chkResult = false; } } catch (err) { diff --git a/packages/zone.js/example/benchmarks/event_emitter.js b/packages/zone.js/example/benchmarks/event_emitter.js index c62e4bb44c90f..3ae84cfb589ac 100644 --- a/packages/zone.js/example/benchmarks/event_emitter.js +++ b/packages/zone.js/example/benchmarks/event_emitter.js @@ -14,8 +14,8 @@ const callbacks = []; const size = 100000; for (let i = 0; i < size; i++) { const emitter = new EventEmitter(); - const callback = (function(i) { - return function() { + const callback = (function (i) { + return function () { console.log(i); }; })(i); @@ -29,19 +29,15 @@ function addRemoveCallback(reuse, useZone) { for (let i = 0; i < size; i++) { const emitter = emitters[i]; if (!reuse) callback = callbacks[i]; - if (useZone) - emitter.on('msg', callback); - else - emitter.__zone_symbol__addListener('msg', callback); + if (useZone) emitter.on('msg', callback); + else emitter.__zone_symbol__addListener('msg', callback); } for (let i = 0; i < size; i++) { const emitter = emitters[i]; if (!reuse) callback = callbacks[i]; - if (useZone) - emitter.removeListener('msg', callback); - else - emitter.__zone_symbol__removeListener('msg', callback); + if (useZone) emitter.removeListener('msg', callback); + else emitter.__zone_symbol__removeListener('msg', callback); } const end = new Date(); console.log(useZone ? 'use zone' : 'native', reuse ? 'reuse' : 'new'); diff --git a/packages/zone.js/example/js/counting-zone.js b/packages/zone.js/example/js/counting-zone.js index fbe3b555171ab..937ccd370468a 100644 --- a/packages/zone.js/example/js/counting-zone.js +++ b/packages/zone.js/example/js/counting-zone.js @@ -5,7 +5,7 @@ Zone['countingZoneSpec'] = { name: 'counterZone', // setTimeout - onScheduleTask: function(delegate, current, target, task) { + onScheduleTask: function (delegate, current, target, task) { this.data.count += 1; delegate.scheduleTask(target, task); }, @@ -13,23 +13,23 @@ Zone['countingZoneSpec'] = { // fires when... // - clearTimeout // - setTimeout finishes - onInvokeTask: function(delegate, current, target, task, applyThis, applyArgs) { + onInvokeTask: function (delegate, current, target, task, applyThis, applyArgs) { delegate.invokeTask(target, task, applyThis, applyArgs); this.data.count -= 1; }, - onHasTask: function(delegate, current, target, hasTask) { + onHasTask: function (delegate, current, target, hasTask) { if (this.data.count === 0 && !this.data.flushed) { this.data.flushed = true; target.run(this.onFlush); } }, - counter: function() { + counter: function () { return this.data.count; }, data: {count: 0, flushed: false}, - onFlush: function() {} + onFlush: function () {}, }; diff --git a/packages/zone.js/karma-base.conf.js b/packages/zone.js/karma-base.conf.js index 1f538252e931b..9ed09899631cf 100644 --- a/packages/zone.js/karma-base.conf.js +++ b/packages/zone.js/karma-base.conf.js @@ -6,12 +6,13 @@ * found in the LICENSE file at https://angular.io/license */ -module.exports = function(config) { +module.exports = function (config) { config.set({ basePath: '', client: {errorpolicy: config.errorpolicy}, files: [ - 'node_modules/systemjs/dist/system-polyfills.js', 'node_modules/systemjs/dist/system.src.js', + 'node_modules/systemjs/dist/system-polyfills.js', + 'node_modules/systemjs/dist/system.src.js', 'node_modules/whatwg-fetch/fetch.js', {pattern: 'node_modules/rxjs/**/**/*.js', included: false, watched: false}, {pattern: 'node_modules/rxjs/**/**/*.js.map', included: false, watched: false}, @@ -21,12 +22,13 @@ module.exports = function(config) { {pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false}, {pattern: 'test/assets/**/*.*', watched: true, served: true, included: false}, {pattern: 'build/**/*.js.map', watched: true, served: true, included: false}, - {pattern: 'build/**/*.js', watched: true, served: true, included: false} + {pattern: 'build/**/*.js', watched: true, served: true, included: false}, ], plugins: [ - require('karma-chrome-launcher'), require('karma-firefox-launcher'), - require('karma-sourcemap-loader') + require('karma-chrome-launcher'), + require('karma-firefox-launcher'), + require('karma-sourcemap-loader'), ], preprocessors: {'**/*.js': ['sourcemap']}, @@ -46,6 +48,6 @@ module.exports = function(config) { retryLimit: 4, autoWatch: true, - singleRun: false + singleRun: false, }); }; diff --git a/packages/zone.js/karma-build-jasmine.conf.js b/packages/zone.js/karma-build-jasmine.conf.js index 432a2159385a5..a44882f4cdc5d 100644 --- a/packages/zone.js/karma-build-jasmine.conf.js +++ b/packages/zone.js/karma-build-jasmine.conf.js @@ -1,5 +1,4 @@ - -module.exports = function(config) { +module.exports = function (config) { require('./karma-build.conf.js')(config); config.plugins.push(require('karma-jasmine')); diff --git a/packages/zone.js/karma-build-jasmine.es2015.conf.js b/packages/zone.js/karma-build-jasmine.es2015.conf.js index 16eedcd7ae3e3..6a75301764fd4 100644 --- a/packages/zone.js/karma-build-jasmine.es2015.conf.js +++ b/packages/zone.js/karma-build-jasmine.es2015.conf.js @@ -1,5 +1,4 @@ - -module.exports = function(config) { +module.exports = function (config) { require('./karma-build-jasmine.conf.js')(config); config.client.entrypoint = 'browser_es2015_entry_point'; }; diff --git a/packages/zone.js/karma-build-mocha.conf.js b/packages/zone.js/karma-build-mocha.conf.js index 44ff081948117..0938ac708c475 100644 --- a/packages/zone.js/karma-build-mocha.conf.js +++ b/packages/zone.js/karma-build-mocha.conf.js @@ -1,11 +1,10 @@ - -module.exports = function(config) { +module.exports = function (config) { require('./karma-build.conf.js')(config); config.plugins.push(require('karma-mocha')); config.frameworks.push('mocha'); config.client.mocha = { - timeout: 5000 // copied timeout for Jasmine in WebSocket.spec (otherwise Mochas default timeout - // at 2 sec is to low for the tests) + timeout: 5000, // copied timeout for Jasmine in WebSocket.spec (otherwise Mochas default timeout + // at 2 sec is to low for the tests) }; }; diff --git a/packages/zone.js/karma-build-sauce-mocha.conf.js b/packages/zone.js/karma-build-sauce-mocha.conf.js index b7f02f4931e08..733487eb6963e 100644 --- a/packages/zone.js/karma-build-sauce-mocha.conf.js +++ b/packages/zone.js/karma-build-sauce-mocha.conf.js @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -module.exports = function(config) { +module.exports = function (config) { require('./karma-dist-mocha.conf.js')(config); require('./sauce.conf')(config); }; diff --git a/packages/zone.js/karma-build-sauce-selenium3-mocha.conf.js b/packages/zone.js/karma-build-sauce-selenium3-mocha.conf.js index 61ae015d5d863..568176bf358dd 100644 --- a/packages/zone.js/karma-build-sauce-selenium3-mocha.conf.js +++ b/packages/zone.js/karma-build-sauce-selenium3-mocha.conf.js @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -module.exports = function(config) { +module.exports = function (config) { require('./karma-dist-mocha.conf.js')(config); require('./sauce-selenium3.conf')(config); }; diff --git a/packages/zone.js/karma-build.conf.js b/packages/zone.js/karma-build.conf.js index 943a610509fdd..11e44e39421a7 100644 --- a/packages/zone.js/karma-build.conf.js +++ b/packages/zone.js/karma-build.conf.js @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -module.exports = function(config) { +module.exports = function (config) { require('./karma-base.conf.js')(config); config.files.push('build/test/browser-env-setup.js'); config.files.push('build/test/wtf_mock.js'); diff --git a/packages/zone.js/karma-dist-jasmine.conf.js b/packages/zone.js/karma-dist-jasmine.conf.js index 32627d46eaed5..f483f6471809b 100644 --- a/packages/zone.js/karma-dist-jasmine.conf.js +++ b/packages/zone.js/karma-dist-jasmine.conf.js @@ -1,5 +1,4 @@ - -module.exports = function(config) { +module.exports = function (config) { require('./karma-dist.conf.js')(config); config.plugins.push(require('karma-jasmine')); diff --git a/packages/zone.js/karma-dist-mocha.conf.js b/packages/zone.js/karma-dist-mocha.conf.js index a7dcf6c7ea1e0..e9963025d55fc 100644 --- a/packages/zone.js/karma-dist-mocha.conf.js +++ b/packages/zone.js/karma-dist-mocha.conf.js @@ -1,5 +1,4 @@ - -module.exports = function(config) { +module.exports = function (config) { require('./karma-dist.conf.js')(config); for (let i = 0; i < config.files.length; i++) { @@ -17,7 +16,7 @@ module.exports = function(config) { config.plugins.push(require('karma-mocha')); config.frameworks.push('mocha'); config.client.mocha = { - timeout: 5000 // copied timeout for Jasmine in WebSocket.spec (otherwise Mochas default timeout - // at 2 sec is to low for the tests) + timeout: 5000, // copied timeout for Jasmine in WebSocket.spec (otherwise Mochas default timeout + // at 2 sec is to low for the tests) }; }; diff --git a/packages/zone.js/karma-dist-sauce-jasmine.conf.js b/packages/zone.js/karma-dist-sauce-jasmine.conf.js index 1c72c66968b69..c2ba80efbff7f 100644 --- a/packages/zone.js/karma-dist-sauce-jasmine.conf.js +++ b/packages/zone.js/karma-dist-sauce-jasmine.conf.js @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -module.exports = function(config) { +module.exports = function (config) { require('./karma-dist-jasmine.conf.js')(config); require('./sauce.conf')(config, ['SL_IOS9']); }; diff --git a/packages/zone.js/karma-dist-sauce-jasmine.es2015.conf.js b/packages/zone.js/karma-dist-sauce-jasmine.es2015.conf.js index 8f78f82a9154e..983b91ee1a09c 100644 --- a/packages/zone.js/karma-dist-sauce-jasmine.es2015.conf.js +++ b/packages/zone.js/karma-dist-sauce-jasmine.es2015.conf.js @@ -1,5 +1,4 @@ - -module.exports = function(config) { +module.exports = function (config) { require('./karma-dist-jasmine.conf.js')(config); require('./sauce.es2015.conf')(config); config.files.push('build/test/wtf_mock.js'); diff --git a/packages/zone.js/karma-dist-sauce-jasmine3.conf.js b/packages/zone.js/karma-dist-sauce-jasmine3.conf.js index 377ef15935f77..849538953449d 100644 --- a/packages/zone.js/karma-dist-sauce-jasmine3.conf.js +++ b/packages/zone.js/karma-dist-sauce-jasmine3.conf.js @@ -6,10 +6,20 @@ * found in the LICENSE file at https://angular.io/license */ -module.exports = function(config) { +module.exports = function (config) { require('./karma-dist-jasmine.conf.js')(config); require('./sauce.conf')(config, [ - 'SL_IOS9', 'SL_CHROME', 'SL_FIREFOX_54', 'SL_SAFARI8', 'SL_SAFARI9', 'SL_SAFARI10', 'SL_IOS8', - 'SL_IOS9', 'SL_IOS10', 'SL_MSEDGE15', 'SL_ANDROID4.4', 'SL_ANDROID5.1' - ]) + 'SL_IOS9', + 'SL_CHROME', + 'SL_FIREFOX_54', + 'SL_SAFARI8', + 'SL_SAFARI9', + 'SL_SAFARI10', + 'SL_IOS8', + 'SL_IOS9', + 'SL_IOS10', + 'SL_MSEDGE15', + 'SL_ANDROID4.4', + 'SL_ANDROID5.1', + ]); }; diff --git a/packages/zone.js/karma-dist-sauce-selenium3-jasmine.conf.js b/packages/zone.js/karma-dist-sauce-selenium3-jasmine.conf.js index 44e571b5a4eec..a7afee10d78c6 100644 --- a/packages/zone.js/karma-dist-sauce-selenium3-jasmine.conf.js +++ b/packages/zone.js/karma-dist-sauce-selenium3-jasmine.conf.js @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -module.exports = function(config) { +module.exports = function (config) { require('./karma-dist-jasmine.conf.js')(config); require('./sauce-selenium3.conf')(config); }; diff --git a/packages/zone.js/karma-dist.conf.js b/packages/zone.js/karma-dist.conf.js index 8349c7d07498f..4ecf1439b9736 100644 --- a/packages/zone.js/karma-dist.conf.js +++ b/packages/zone.js/karma-dist.conf.js @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -module.exports = function(config) { +module.exports = function (config) { require('./karma-base.conf.js')(config); config.files.push('build/test/browser-env-setup.js'); config.files.push('build/test/wtf_mock.js'); diff --git a/packages/zone.js/karma-evergreen-dist-jasmine.conf.js b/packages/zone.js/karma-evergreen-dist-jasmine.conf.js index f7df41e676bf2..8eff5abef5af7 100644 --- a/packages/zone.js/karma-evergreen-dist-jasmine.conf.js +++ b/packages/zone.js/karma-evergreen-dist-jasmine.conf.js @@ -1,5 +1,4 @@ - -module.exports = function(config) { +module.exports = function (config) { require('./karma-evergreen-dist.conf.js')(config); config.plugins.push(require('karma-jasmine')); diff --git a/packages/zone.js/karma-evergreen-dist-sauce-jasmine.conf.js b/packages/zone.js/karma-evergreen-dist-sauce-jasmine.conf.js index fc6c60a31802b..2b1ff0328e7fa 100644 --- a/packages/zone.js/karma-evergreen-dist-sauce-jasmine.conf.js +++ b/packages/zone.js/karma-evergreen-dist-sauce-jasmine.conf.js @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -module.exports = function(config) { +module.exports = function (config) { require('./karma-evergreen-dist-jasmine.conf.js')(config); require('./sauce-evergreen.conf')(config); }; diff --git a/packages/zone.js/karma-evergreen-dist.conf.js b/packages/zone.js/karma-evergreen-dist.conf.js index d7b15b15bc313..3493525cbc958 100644 --- a/packages/zone.js/karma-evergreen-dist.conf.js +++ b/packages/zone.js/karma-evergreen-dist.conf.js @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -module.exports = function(config) { +module.exports = function (config) { require('./karma-base.conf.js')(config); config.files.push('build/test/browser-env-setup.js'); config.files.push('build/test/wtf_mock.js'); diff --git a/packages/zone.js/lib/browser/api-util.ts b/packages/zone.js/lib/browser/api-util.ts index d6bb7d64b59d3..67fcf5893e5a0 100644 --- a/packages/zone.js/lib/browser/api-util.ts +++ b/packages/zone.js/lib/browser/api-util.ts @@ -6,8 +6,34 @@ * found in the LICENSE file at https://angular.io/license */ -import {globalSources, patchEventPrototype, patchEventTarget, zoneSymbolEventNames} from '../common/events'; -import {ADD_EVENT_LISTENER_STR, ArraySlice, attachOriginToPatched, bindArguments, FALSE_STR, isBrowser, isIEOrEdge, isMix, isNode, ObjectCreate, ObjectDefineProperty, ObjectGetOwnPropertyDescriptor, patchClass, patchMacroTask, patchMethod, patchOnProperties, REMOVE_EVENT_LISTENER_STR, TRUE_STR, wrapWithCurrentZone, ZONE_SYMBOL_PREFIX} from '../common/utils'; +import { + globalSources, + patchEventPrototype, + patchEventTarget, + zoneSymbolEventNames, +} from '../common/events'; +import { + ADD_EVENT_LISTENER_STR, + ArraySlice, + attachOriginToPatched, + bindArguments, + FALSE_STR, + isBrowser, + isIEOrEdge, + isMix, + isNode, + ObjectCreate, + ObjectDefineProperty, + ObjectGetOwnPropertyDescriptor, + patchClass, + patchMacroTask, + patchMethod, + patchOnProperties, + REMOVE_EVENT_LISTENER_STR, + TRUE_STR, + wrapWithCurrentZone, + ZONE_SYMBOL_PREFIX, +} from '../common/utils'; import {ZoneType} from '../zone-impl'; import {patchCallbacks} from './browser-util'; @@ -34,7 +60,7 @@ export function patchUtil(Zone: ZoneType): void { } if (global[SYMBOL_BLACK_LISTED_EVENTS]) { (Zone as any)[SYMBOL_BLACK_LISTED_EVENTS] = (Zone as any)[SYMBOL_UNPATCHED_EVENTS] = - global[SYMBOL_BLACK_LISTED_EVENTS]; + global[SYMBOL_BLACK_LISTED_EVENTS]; } api.patchEventPrototype = patchEventPrototype; api.patchEventTarget = patchEventTarget; @@ -60,7 +86,7 @@ export function patchUtil(Zone: ZoneType): void { FALSE_STR, ZONE_SYMBOL_PREFIX, ADD_EVENT_LISTENER_STR, - REMOVE_EVENT_LISTENER_STR + REMOVE_EVENT_LISTENER_STR, }); }); } diff --git a/packages/zone.js/lib/browser/browser-legacy.ts b/packages/zone.js/lib/browser/browser-legacy.ts index 48249ffbe2ecd..f97c197ec55b1 100644 --- a/packages/zone.js/lib/browser/browser-legacy.ts +++ b/packages/zone.js/lib/browser/browser-legacy.ts @@ -16,15 +16,19 @@ import {propertyDescriptorLegacyPatch} from './property-descriptor-legacy'; import {registerElementPatch} from './register-element'; export function patchBrowserLegacy(): void { - const _global: any = typeof window !== 'undefined' ? window : - typeof global !== 'undefined' ? global : - typeof self !== 'undefined' ? self : - {}; + const _global: any = + typeof window !== 'undefined' + ? window + : typeof global !== 'undefined' + ? global + : typeof self !== 'undefined' + ? self + : {}; const symbolPrefix = _global['__Zone_symbol_prefix'] || '__zone_symbol__'; function __symbol__(name: string) { return symbolPrefix + name; } - _global[__symbol__('legacyPatch')] = function() { + _global[__symbol__('legacyPatch')] = function () { const Zone = _global['Zone']; Zone.__load_patch('defineProperty', (global: any, Zone: ZoneType, api: _ZonePrivate) => { api._redefineProperty = _redefineProperty; diff --git a/packages/zone.js/lib/browser/browser-util.ts b/packages/zone.js/lib/browser/browser-util.ts index a7c48035bf589..ebcbef521ce39 100644 --- a/packages/zone.js/lib/browser/browser-util.ts +++ b/packages/zone.js/lib/browser/browser-util.ts @@ -6,15 +6,20 @@ * found in the LICENSE file at https://angular.io/license */ export function patchCallbacks( - api: _ZonePrivate, target: any, targetName: string, method: string, callbacks: string[]) { + api: _ZonePrivate, + target: any, + targetName: string, + method: string, + callbacks: string[], +) { const symbol = Zone.__symbol__(method); if (target[symbol]) { return; } - const nativeDelegate = target[symbol] = target[method]; - target[method] = function(name: any, opts: any, options?: any) { + const nativeDelegate = (target[symbol] = target[method]); + target[method] = function (name: any, opts: any, options?: any) { if (opts && opts.prototype) { - callbacks.forEach(function(callback) { + callbacks.forEach(function (callback) { const source = `${targetName}.${method}::` + callback; const prototype = opts.prototype; // Note: the `patchCallbacks` is used for patching the `document.registerElement` and diff --git a/packages/zone.js/lib/browser/browser.ts b/packages/zone.js/lib/browser/browser.ts index 5b74a58eb74f5..7b9054c92ccd9 100644 --- a/packages/zone.js/lib/browser/browser.ts +++ b/packages/zone.js/lib/browser/browser.ts @@ -13,7 +13,15 @@ import {findEventTasks} from '../common/events'; import {patchQueueMicrotask} from '../common/queue-microtask'; import {patchTimer} from '../common/timers'; -import {patchClass, patchMethod, patchPrototype, scheduleMacroTaskWithCurrentZone, ZONE_SYMBOL_ADD_EVENT_LISTENER, ZONE_SYMBOL_REMOVE_EVENT_LISTENER, zoneSymbol,} from '../common/utils'; +import { + patchClass, + patchMethod, + patchPrototype, + scheduleMacroTaskWithCurrentZone, + ZONE_SYMBOL_ADD_EVENT_LISTENER, + ZONE_SYMBOL_REMOVE_EVENT_LISTENER, + zoneSymbol, +} from '../common/utils'; import {ZoneType} from '../zone-impl'; import {patchCustomElements} from './custom-elements'; @@ -47,7 +55,7 @@ export function patchBrowser(Zone: ZoneType): void { for (let i = 0; i < blockingMethods.length; i++) { const name = blockingMethods[i]; patchMethod(global, name, (delegate, symbol, name) => { - return function(s: any, args: any[]) { + return function (s: any, args: any[]) { return Zone.current.run(delegate, global, args, name); }; }); @@ -144,7 +152,7 @@ export function patchBrowser(Zone: ZoneType): void { if (listener) { oriRemoveListener.call(target, READY_STATE_CHANGE, listener); } - const newListener = target[XHR_LISTENER] = () => { + const newListener = (target[XHR_LISTENER] = () => { if (target.readyState === target.DONE) { // sometimes on some browsers XMLHttpRequest will fire onreadystatechange with // readyState=4 multiple times, so we need to check task state here @@ -159,7 +167,7 @@ export function patchBrowser(Zone: ZoneType): void { const loadTasks = target[Zone.__symbol__('loadfalse')]; if (target.status !== 0 && loadTasks && loadTasks.length > 0) { const oriInvoke = task.invoke; - task.invoke = function() { + task.invoke = function () { // need to load the tasks again, because in other // load listener, they may remove themselves const loadTasks = target[Zone.__symbol__('loadfalse')]; @@ -181,7 +189,7 @@ export function patchBrowser(Zone: ZoneType): void { target[XHR_ERROR_BEFORE_SCHEDULED] = true; } } - }; + }); oriAddListener.call(target, READY_STATE_CHANGE, newListener); const storedTask: Task = target[XHR_TASK]; @@ -203,18 +211,25 @@ export function patchBrowser(Zone: ZoneType): void { return abortNative!.apply(data.target, data.args); } - const openNative = - patchMethod(XMLHttpRequestPrototype, 'open', () => function(self: any, args: any[]) { + const openNative = patchMethod( + XMLHttpRequestPrototype, + 'open', + () => + function (self: any, args: any[]) { self[XHR_SYNC] = args[2] == false; self[XHR_URL] = args[1]; return openNative!.apply(self, args); - }); + }, + ); const XMLHTTPREQUEST_SOURCE = 'XMLHttpRequest.send'; const fetchTaskAborting = zoneSymbol('fetchTaskAborting'); const fetchTaskScheduling = zoneSymbol('fetchTaskScheduling'); - const sendNative: Function|null = - patchMethod(XMLHttpRequestPrototype, 'send', () => function(self: any, args: any[]) { + const sendNative: Function | null = patchMethod( + XMLHttpRequestPrototype, + 'send', + () => + function (self: any, args: any[]) { if ((Zone.current as any)[fetchTaskScheduling] === true) { // a fetch is scheduling, so we are using xhr to polyfill fetch // and because we already schedule macroTask for fetch, we should @@ -225,22 +240,40 @@ export function patchBrowser(Zone: ZoneType): void { // if the XHR is sync there is no task to schedule, just execute the code. return sendNative!.apply(self, args); } else { - const options: XHROptions = - {target: self, url: self[XHR_URL], isPeriodic: false, args: args, aborted: false}; + const options: XHROptions = { + target: self, + url: self[XHR_URL], + isPeriodic: false, + args: args, + aborted: false, + }; const task = scheduleMacroTaskWithCurrentZone( - XMLHTTPREQUEST_SOURCE, placeholderCallback, options, scheduleTask, clearTask); - if (self && self[XHR_ERROR_BEFORE_SCHEDULED] === true && !options.aborted && - task.state === SCHEDULED) { + XMLHTTPREQUEST_SOURCE, + placeholderCallback, + options, + scheduleTask, + clearTask, + ); + if ( + self && + self[XHR_ERROR_BEFORE_SCHEDULED] === true && + !options.aborted && + task.state === SCHEDULED + ) { // xhr request throw error when send // we should invoke task instead of leaving a scheduled // pending macroTask task.invoke(); } } - }); - - const abortNative = - patchMethod(XMLHttpRequestPrototype, 'abort', () => function(self: any, args: any[]) { + }, + ); + + const abortNative = patchMethod( + XMLHttpRequestPrototype, + 'abort', + () => + function (self: any, args: any[]) { const task: Task = findPendingTask(self); if (task && typeof task.type == 'string') { // If the XHR has already completed, do nothing. @@ -258,7 +291,8 @@ export function patchBrowser(Zone: ZoneType): void { // Otherwise, we are trying to abort an XHR which has not yet been sent, so there is no // task // to cancel. Do nothing. - }); + }, + ); } }); @@ -272,15 +306,17 @@ export function patchBrowser(Zone: ZoneType): void { Zone.__load_patch('PromiseRejectionEvent', (global: any, Zone: ZoneType) => { // handle unhandled promise rejection function findPromiseRejectionHandler(evtName: string) { - return function(e: any) { + return function (e: any) { const eventTasks = findEventTasks(global, evtName); - eventTasks.forEach(eventTask => { + eventTasks.forEach((eventTask) => { // windows has added unhandledrejection event listener // trigger the event listener const PromiseRejectionEvent = global['PromiseRejectionEvent']; if (PromiseRejectionEvent) { - const evt = - new PromiseRejectionEvent(evtName, {promise: e.promise, reason: e.rejection}); + const evt = new PromiseRejectionEvent(evtName, { + promise: e.promise, + reason: e.rejection, + }); eventTask.invoke(evt); } }); @@ -289,10 +325,10 @@ export function patchBrowser(Zone: ZoneType): void { if (global['PromiseRejectionEvent']) { (Zone as any)[zoneSymbol('unhandledPromiseRejectionHandler')] = - findPromiseRejectionHandler('unhandledrejection'); + findPromiseRejectionHandler('unhandledrejection'); (Zone as any)[zoneSymbol('rejectionHandledHandler')] = - findPromiseRejectionHandler('rejectionhandled'); + findPromiseRejectionHandler('rejectionhandled'); } }); diff --git a/packages/zone.js/lib/browser/canvas.ts b/packages/zone.js/lib/browser/canvas.ts index 9097164978bc4..8109bb308454f 100644 --- a/packages/zone.js/lib/browser/canvas.ts +++ b/packages/zone.js/lib/browser/canvas.ts @@ -11,8 +11,11 @@ import {ZoneType} from '../zone-impl'; export function patchCanvas(Zone: ZoneType): void { Zone.__load_patch('canvas', (global: any, Zone: ZoneType, api: _ZonePrivate) => { const HTMLCanvasElement = global['HTMLCanvasElement']; - if (typeof HTMLCanvasElement !== 'undefined' && HTMLCanvasElement.prototype && - HTMLCanvasElement.prototype.toBlob) { + if ( + typeof HTMLCanvasElement !== 'undefined' && + HTMLCanvasElement.prototype && + HTMLCanvasElement.prototype.toBlob + ) { api.patchMacroTask(HTMLCanvasElement.prototype, 'toBlob', (self: any, args: any[]) => { return {name: 'HTMLCanvasElement.toBlob', target: self, cbIdx: 0, args: args}; }); diff --git a/packages/zone.js/lib/browser/custom-elements.ts b/packages/zone.js/lib/browser/custom-elements.ts index 4947611dd0d13..f866eace3597a 100644 --- a/packages/zone.js/lib/browser/custom-elements.ts +++ b/packages/zone.js/lib/browser/custom-elements.ts @@ -14,9 +14,14 @@ export function patchCustomElements(_global: any, api: _ZonePrivate) { // https://html.spec.whatwg.org/multipage/custom-elements.html#concept-custom-element-definition-lifecycle-callbacks const callbacks = [ - 'connectedCallback', 'disconnectedCallback', 'adoptedCallback', 'attributeChangedCallback', - 'formAssociatedCallback', 'formDisabledCallback', 'formResetCallback', - 'formStateRestoreCallback' + 'connectedCallback', + 'disconnectedCallback', + 'adoptedCallback', + 'attributeChangedCallback', + 'formAssociatedCallback', + 'formDisabledCallback', + 'formResetCallback', + 'formStateRestoreCallback', ]; api.patchCallbacks(api, _global.customElements, 'customElements', 'define', callbacks); diff --git a/packages/zone.js/lib/browser/define-property.ts b/packages/zone.js/lib/browser/define-property.ts index 813da07be9093..9579d472b6e96 100644 --- a/packages/zone.js/lib/browser/define-property.ts +++ b/packages/zone.js/lib/browser/define-property.ts @@ -21,12 +21,12 @@ export function propertyPatch() { zoneSymbol = Zone.__symbol__; _defineProperty = (Object as any)[zoneSymbol('defineProperty')] = Object.defineProperty; _getOwnPropertyDescriptor = (Object as any)[zoneSymbol('getOwnPropertyDescriptor')] = - Object.getOwnPropertyDescriptor; + Object.getOwnPropertyDescriptor; _create = Object.create; unconfigurablesKey = zoneSymbol('unconfigurables'); - Object.defineProperty = function(obj: any, prop: string, desc: any) { + Object.defineProperty = function (obj: any, prop: string, desc: any) { if (isUnconfigurable(obj, prop)) { - throw new TypeError('Cannot assign to read only property \'' + prop + '\' of ' + obj); + throw new TypeError("Cannot assign to read only property '" + prop + "' of " + obj); } const originalConfigurableFlag = desc.configurable; if (prop !== 'prototype') { @@ -35,10 +35,14 @@ export function propertyPatch() { return _tryDefineProperty(obj, prop, desc, originalConfigurableFlag); }; - Object.defineProperties = function(obj: T, props: PropertyDescriptorMap&ThisType&{ - [s: symbol]: PropertyDescriptor; - }): T { - Object.keys(props).forEach(function(prop) { + Object.defineProperties = function ( + obj: T, + props: PropertyDescriptorMap & + ThisType & { + [s: symbol]: PropertyDescriptor; + }, + ): T { + Object.keys(props).forEach(function (prop) { Object.defineProperty(obj, prop, props[prop]); }); for (const sym of Object.getOwnPropertySymbols(props)) { @@ -55,18 +59,18 @@ export function propertyPatch() { } } return obj; - } + }; - Object.create = function(proto: any, propertiesObject: any) { + Object.create = function (proto: any, propertiesObject: any) { if (typeof propertiesObject === 'object' && !Object.isFrozen(propertiesObject)) { - Object.keys(propertiesObject).forEach(function(prop) { + Object.keys(propertiesObject).forEach(function (prop) { propertiesObject[prop] = rewriteDescriptor(proto, prop, propertiesObject[prop]); }); } return _create(proto, propertiesObject); }; - Object.getOwnPropertyDescriptor = function(obj, prop) { + Object.getOwnPropertyDescriptor = function (obj, prop) { const desc = _getOwnPropertyDescriptor(obj, prop); if (desc && isUnconfigurable(obj, prop)) { desc.configurable = false; @@ -118,8 +122,12 @@ function _tryDefineProperty(obj: any, prop: string, desc: any, originalConfigura return _defineProperty(obj, prop, desc); } catch (error) { let swallowError = false; - if (prop === 'createdCallback' || prop === 'attachedCallback' || - prop === 'detachedCallback' || prop === 'attributeChangedCallback') { + if ( + prop === 'createdCallback' || + prop === 'attachedCallback' || + prop === 'detachedCallback' || + prop === 'attributeChangedCallback' + ) { // We only swallow the error in registerElement patch // this is the work around since some applications // fail if we throw the error @@ -131,14 +139,15 @@ function _tryDefineProperty(obj: any, prop: string, desc: any, originalConfigura // TODO: @JiaLiPassion, Some application such as `registerElement` patch // still need to swallow the error, in the future after these applications // are updated, the following logic can be removed. - let descJson: string|null = null; + let descJson: string | null = null; try { descJson = JSON.stringify(desc); } catch (error) { descJson = desc.toString(); } - console.log(`Attempting to configure '${prop}' with descriptor '${descJson}' on object '${ - obj}' and got error, giving up: ${error}`); + console.log( + `Attempting to configure '${prop}' with descriptor '${descJson}' on object '${obj}' and got error, giving up: ${error}`, + ); } } else { throw error; diff --git a/packages/zone.js/lib/browser/event-target-legacy.ts b/packages/zone.js/lib/browser/event-target-legacy.ts index 5bebb2c395e03..03b9811977474 100644 --- a/packages/zone.js/lib/browser/event-target-legacy.ts +++ b/packages/zone.js/lib/browser/event-target-legacy.ts @@ -8,12 +8,13 @@ export function eventTargetLegacyPatch(_global: any, api: _ZonePrivate) { const {eventNames, globalSources, zoneSymbolEventNames, TRUE_STR, FALSE_STR, ZONE_SYMBOL_PREFIX} = - api.getGlobalObjects()!; + api.getGlobalObjects()!; const WTF_ISSUE_555 = - 'Anchor,Area,Audio,BR,Base,BaseFont,Body,Button,Canvas,Content,DList,Directory,Div,Embed,FieldSet,Font,Form,Frame,FrameSet,HR,Head,Heading,Html,IFrame,Image,Input,Keygen,LI,Label,Legend,Link,Map,Marquee,Media,Menu,Meta,Meter,Mod,OList,Object,OptGroup,Option,Output,Paragraph,Pre,Progress,Quote,Script,Select,Source,Span,Style,TableCaption,TableCell,TableCol,Table,TableRow,TableSection,TextArea,Title,Track,UList,Unknown,Video'; + 'Anchor,Area,Audio,BR,Base,BaseFont,Body,Button,Canvas,Content,DList,Directory,Div,Embed,FieldSet,Font,Form,Frame,FrameSet,HR,Head,Heading,Html,IFrame,Image,Input,Keygen,LI,Label,Legend,Link,Map,Marquee,Media,Menu,Meta,Meter,Mod,OList,Object,OptGroup,Option,Output,Paragraph,Pre,Progress,Quote,Script,Select,Source,Span,Style,TableCaption,TableCell,TableCol,Table,TableRow,TableSection,TextArea,Title,Track,UList,Unknown,Video'; const NO_EVENT_TARGET = - 'ApplicationCache,EventSource,FileReader,InputMethodContext,MediaController,MessagePort,Node,Performance,SVGElementInstance,SharedWorker,TextTrack,TextTrackCue,TextTrackList,WebKitNamedFlow,Window,Worker,WorkerGlobalScope,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload,IDBRequest,IDBOpenDBRequest,IDBDatabase,IDBTransaction,IDBCursor,DBIndex,WebSocket' - .split(','); + 'ApplicationCache,EventSource,FileReader,InputMethodContext,MediaController,MessagePort,Node,Performance,SVGElementInstance,SharedWorker,TextTrack,TextTrackCue,TextTrackList,WebKitNamedFlow,Window,Worker,WorkerGlobalScope,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload,IDBRequest,IDBOpenDBRequest,IDBDatabase,IDBTransaction,IDBCursor,DBIndex,WebSocket'.split( + ',', + ); const EVENT_TARGET = 'EventTarget'; let apis: any[] = []; @@ -48,7 +49,7 @@ export function eventTargetLegacyPatch(_global: any, api: _ZonePrivate) { 'MSPointerMove': 'pointermove', 'MSPointerOut': 'pointerout', 'MSPointerOver': 'pointerover', - 'MSPointerUp': 'pointerup' + 'MSPointerUp': 'pointerup', }; // predefine all __zone_symbol__ + eventName + true/false string @@ -66,20 +67,24 @@ export function eventTargetLegacyPatch(_global: any, api: _ZonePrivate) { // predefine all task.source string for (let i = 0; i < WTF_ISSUE_555_ARRAY.length; i++) { const target: any = WTF_ISSUE_555_ARRAY[i]; - const targets: any = globalSources[target] = {}; + const targets: any = (globalSources[target] = {}); for (let j = 0; j < eventNames.length; j++) { const eventName = eventNames[j]; targets[eventName] = target + ADD_EVENT_LISTENER_SOURCE + eventName; } } - const checkIEAndCrossContext = function( - nativeDelegate: any, delegate: any, target: any, args: any) { + const checkIEAndCrossContext = function ( + nativeDelegate: any, + delegate: any, + target: any, + args: any, + ) { if (!isDisableIECheck && ieOrEdge) { if (isEnableCrossContextCheck) { try { const testString = delegate.toString(); - if ((testString === FUNCTION_WRAPPER || testString == BROWSER_TOOLS)) { + if (testString === FUNCTION_WRAPPER || testString == BROWSER_TOOLS) { nativeDelegate.apply(target, args); return false; } @@ -89,7 +94,7 @@ export function eventTargetLegacyPatch(_global: any, api: _ZonePrivate) { } } else { const testString = delegate.toString(); - if ((testString === FUNCTION_WRAPPER || testString == BROWSER_TOOLS)) { + if (testString === FUNCTION_WRAPPER || testString == BROWSER_TOOLS) { nativeDelegate.apply(target, args); return false; } @@ -117,7 +122,7 @@ export function eventTargetLegacyPatch(_global: any, api: _ZonePrivate) { transferEventName: (eventName: string) => { const pointerEventName = pointerEventsMap[eventName]; return pointerEventName || eventName; - } + }, }); (Zone as any)[api.symbol('patchEventTarget')] = !!_global[EVENT_TARGET]; return true; diff --git a/packages/zone.js/lib/browser/event-target.ts b/packages/zone.js/lib/browser/event-target.ts index 215ac3d13ef03..99e2941672e51 100644 --- a/packages/zone.js/lib/browser/event-target.ts +++ b/packages/zone.js/lib/browser/event-target.ts @@ -12,7 +12,7 @@ export function eventTargetPatch(_global: any, api: _ZonePrivate) { return; } const {eventNames, zoneSymbolEventNames, TRUE_STR, FALSE_STR, ZONE_SYMBOL_PREFIX} = - api.getGlobalObjects()!; + api.getGlobalObjects()!; // predefine all __zone_symbol__ + eventName + true/false string for (let i = 0; i < eventNames.length; i++) { const eventName = eventNames[i]; diff --git a/packages/zone.js/lib/browser/property-descriptor-legacy.ts b/packages/zone.js/lib/browser/property-descriptor-legacy.ts index a5946f6ea4592..02a1e13a9dc9b 100644 --- a/packages/zone.js/lib/browser/property-descriptor-legacy.ts +++ b/packages/zone.js/lib/browser/property-descriptor-legacy.ts @@ -32,9 +32,11 @@ export function propertyDescriptorLegacyPatch(api: _ZonePrivate, _global: any) { function canPatchViaPropertyDescriptor(api: _ZonePrivate, _global: any) { const {isBrowser, isMix} = api.getGlobalObjects()!; - if ((isBrowser || isMix) && - !api.ObjectGetOwnPropertyDescriptor(HTMLElement.prototype, 'onclick') && - typeof Element !== 'undefined') { + if ( + (isBrowser || isMix) && + !api.ObjectGetOwnPropertyDescriptor(HTMLElement.prototype, 'onclick') && + typeof Element !== 'undefined' + ) { // WebKit https://bugs.webkit.org/show_bug.cgi?id=134364 // IDL interface attributes are not configurable const desc = api.ObjectGetOwnPropertyDescriptor(Element.prototype, 'onclick'); @@ -45,9 +47,9 @@ function canPatchViaPropertyDescriptor(api: _ZonePrivate, _global: any) { api.ObjectDefineProperty(Element.prototype, 'onclick', { enumerable: true, configurable: true, - get: function() { + get: function () { return true; - } + }, }); const div = document.createElement('div'); const result = !!div.onclick; @@ -64,8 +66,10 @@ function canPatchViaPropertyDescriptor(api: _ZonePrivate, _global: any) { const ON_READY_STATE_CHANGE = 'onreadystatechange'; const XMLHttpRequestPrototype = XMLHttpRequest.prototype; - const xhrDesc = - api.ObjectGetOwnPropertyDescriptor(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE); + const xhrDesc = api.ObjectGetOwnPropertyDescriptor( + XMLHttpRequestPrototype, + ON_READY_STATE_CHANGE, + ); // add enumerable and configurable here because in opera // by default XMLHttpRequest.prototype.onreadystatechange is undefined @@ -77,9 +81,9 @@ function canPatchViaPropertyDescriptor(api: _ZonePrivate, _global: any) { api.ObjectDefineProperty(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, { enumerable: true, configurable: true, - get: function() { + get: function () { return true; - } + }, }); const req = new XMLHttpRequest(); const result = !!req.onreadystatechange; @@ -91,12 +95,12 @@ function canPatchViaPropertyDescriptor(api: _ZonePrivate, _global: any) { api.ObjectDefineProperty(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, { enumerable: true, configurable: true, - get: function() { + get: function () { return this[SYMBOL_FAKE_ONREADYSTATECHANGE]; }, - set: function(value) { + set: function (value) { this[SYMBOL_FAKE_ONREADYSTATECHANGE] = value; - } + }, }); const req = new XMLHttpRequest(); const detectFunc = () => {}; @@ -203,13 +207,24 @@ const globalEventHandlersEventNames = [ 'transitioncancel', 'transitionend', 'waiting', - 'wheel' + 'wheel', ]; const documentEventNames = [ - 'afterscriptexecute', 'beforescriptexecute', 'DOMContentLoaded', 'freeze', 'fullscreenchange', - 'mozfullscreenchange', 'webkitfullscreenchange', 'msfullscreenchange', 'fullscreenerror', - 'mozfullscreenerror', 'webkitfullscreenerror', 'msfullscreenerror', 'readystatechange', - 'visibilitychange', 'resume' + 'afterscriptexecute', + 'beforescriptexecute', + 'DOMContentLoaded', + 'freeze', + 'fullscreenchange', + 'mozfullscreenchange', + 'webkitfullscreenchange', + 'msfullscreenchange', + 'fullscreenerror', + 'mozfullscreenerror', + 'webkitfullscreenerror', + 'msfullscreenerror', + 'readystatechange', + 'visibilitychange', + 'resume', ]; const windowEventNames = [ 'absolutedeviceorientation', @@ -241,15 +256,33 @@ const windowEventNames = [ 'userproximity', 'vrdisplayconnected', 'vrdisplaydisconnected', - 'vrdisplaypresentchange' + 'vrdisplaypresentchange', ]; const htmlElementEventNames = [ - 'beforecopy', 'beforecut', 'beforepaste', 'copy', 'cut', 'paste', 'dragstart', 'loadend', - 'animationstart', 'search', 'transitionrun', 'transitionstart', 'webkitanimationend', - 'webkitanimationiteration', 'webkitanimationstart', 'webkittransitionend' + 'beforecopy', + 'beforecut', + 'beforepaste', + 'copy', + 'cut', + 'paste', + 'dragstart', + 'loadend', + 'animationstart', + 'search', + 'transitionrun', + 'transitionstart', + 'webkitanimationend', + 'webkitanimationiteration', + 'webkitanimationstart', + 'webkittransitionend', +]; +const mediaElementEventNames = [ + 'encrypted', + 'waitingforkey', + 'msneedkey', + 'mozinterruptbegin', + 'mozinterruptend', ]; -const mediaElementEventNames = - ['encrypted', 'waitingforkey', 'msneedkey', 'mozinterruptbegin', 'mozinterruptend']; const ieElementEventNames = [ 'activate', 'afterupdate', @@ -305,15 +338,21 @@ const ieElementEventNames = [ 'mssitemodejumplistitemremoved', 'msthumbnailclick', 'stop', - 'storagecommit' + 'storagecommit', ]; const webglEventNames = ['webglcontextrestored', 'webglcontextlost', 'webglcontextcreationerror']; const formEventNames = ['autocomplete', 'autocompleteerror']; const detailEventNames = ['toggle']; const eventNames = [ - ...globalEventHandlersEventNames, ...webglEventNames, ...formEventNames, ...detailEventNames, - ...documentEventNames, ...windowEventNames, ...htmlElementEventNames, ...ieElementEventNames + ...globalEventHandlersEventNames, + ...webglEventNames, + ...formEventNames, + ...detailEventNames, + ...documentEventNames, + ...windowEventNames, + ...htmlElementEventNames, + ...ieElementEventNames, ]; // Whenever any eventListener fires, we check the eventListener target and all parents @@ -324,21 +363,27 @@ function patchViaCapturingAllTheEvents(api: _ZonePrivate) { for (let i = 0; i < eventNames.length; i++) { const property = eventNames[i]; const onproperty = 'on' + property; - self.addEventListener(property, function(event) { - let elt: any = event.target, bound, source; - if (elt) { - source = elt.constructor['name'] + '.' + onproperty; - } else { - source = 'unknown.' + onproperty; - } - while (elt) { - if (elt[onproperty] && !elt[onproperty][unboundKey]) { - bound = api.wrapWithCurrentZone(elt[onproperty], source); - bound[unboundKey] = elt[onproperty]; - elt[onproperty] = bound; + self.addEventListener( + property, + function (event) { + let elt: any = event.target, + bound, + source; + if (elt) { + source = elt.constructor['name'] + '.' + onproperty; + } else { + source = 'unknown.' + onproperty; + } + while (elt) { + if (elt[onproperty] && !elt[onproperty][unboundKey]) { + bound = api.wrapWithCurrentZone(elt[onproperty], source); + bound[unboundKey] = elt[onproperty]; + elt[onproperty] = bound; + } + elt = elt.parentElement; } - elt = elt.parentElement; - } - }, true); + }, + true, + ); } } diff --git a/packages/zone.js/lib/browser/property-descriptor.ts b/packages/zone.js/lib/browser/property-descriptor.ts index cc08e692df0e8..7060ba29f9d3b 100644 --- a/packages/zone.js/lib/browser/property-descriptor.ts +++ b/packages/zone.js/lib/browser/property-descriptor.ts @@ -10,7 +10,14 @@ * @suppress {globalThis} */ -import {isBrowser, isIE, isMix, isNode, ObjectGetPrototypeOf, patchOnProperties} from '../common/utils'; +import { + isBrowser, + isIE, + isMix, + isNode, + ObjectGetPrototypeOf, + patchOnProperties, +} from '../common/utils'; export interface IgnoreProperty { target: any; @@ -18,22 +25,29 @@ export interface IgnoreProperty { } export function filterProperties( - target: any, onProperties: string[], ignoreProperties: IgnoreProperty[]): string[] { + target: any, + onProperties: string[], + ignoreProperties: IgnoreProperty[], +): string[] { if (!ignoreProperties || ignoreProperties.length === 0) { return onProperties; } - const tip: IgnoreProperty[] = ignoreProperties.filter(ip => ip.target === target); + const tip: IgnoreProperty[] = ignoreProperties.filter((ip) => ip.target === target); if (!tip || tip.length === 0) { return onProperties; } const targetIgnoreProperties: string[] = tip[0].ignoreProperties; - return onProperties.filter(op => targetIgnoreProperties.indexOf(op) === -1); + return onProperties.filter((op) => targetIgnoreProperties.indexOf(op) === -1); } export function patchFilteredProperties( - target: any, onProperties: string[], ignoreProperties: IgnoreProperty[], prototype?: any) { + target: any, + onProperties: string[], + ignoreProperties: IgnoreProperty[], + prototype?: any, +) { // check whether target is available, sometimes target will be undefined // because different browser or some 3rd party plugin. if (!target) { @@ -49,8 +63,8 @@ export function patchFilteredProperties( */ export function getOnEventNames(target: Object) { return Object.getOwnPropertyNames(target) - .filter(name => name.startsWith('on') && name.length > 2) - .map(name => name.substring(2)); + .filter((name) => name.startsWith('on') && name.length > 2) + .map((name) => name.substring(2)); } export function propertyDescriptorPatch(api: _ZonePrivate, _global: any) { @@ -67,26 +81,49 @@ export function propertyDescriptorPatch(api: _ZonePrivate, _global: any) { if (isBrowser) { const internalWindow: any = window; patchTargets = patchTargets.concat([ - 'Document', 'SVGElement', 'Element', 'HTMLElement', 'HTMLBodyElement', 'HTMLMediaElement', - 'HTMLFrameSetElement', 'HTMLFrameElement', 'HTMLIFrameElement', 'HTMLMarqueeElement', 'Worker' + 'Document', + 'SVGElement', + 'Element', + 'HTMLElement', + 'HTMLBodyElement', + 'HTMLMediaElement', + 'HTMLFrameSetElement', + 'HTMLFrameElement', + 'HTMLIFrameElement', + 'HTMLMarqueeElement', + 'Worker', ]); - const ignoreErrorProperties = - isIE() ? [{target: internalWindow, ignoreProperties: ['error']}] : []; + const ignoreErrorProperties = isIE() + ? [{target: internalWindow, ignoreProperties: ['error']}] + : []; // in IE/Edge, onProp not exist in window object, but in WindowPrototype // so we need to pass WindowPrototype to check onProp exist or not patchFilteredProperties( - internalWindow, getOnEventNames(internalWindow), - ignoreProperties ? ignoreProperties.concat(ignoreErrorProperties) : ignoreProperties, - ObjectGetPrototypeOf(internalWindow)); + internalWindow, + getOnEventNames(internalWindow), + ignoreProperties ? ignoreProperties.concat(ignoreErrorProperties) : ignoreProperties, + ObjectGetPrototypeOf(internalWindow), + ); } patchTargets = patchTargets.concat([ - 'XMLHttpRequest', 'XMLHttpRequestEventTarget', 'IDBIndex', 'IDBRequest', 'IDBOpenDBRequest', - 'IDBDatabase', 'IDBTransaction', 'IDBCursor', 'WebSocket' + 'XMLHttpRequest', + 'XMLHttpRequestEventTarget', + 'IDBIndex', + 'IDBRequest', + 'IDBOpenDBRequest', + 'IDBDatabase', + 'IDBTransaction', + 'IDBCursor', + 'WebSocket', ]); for (let i = 0; i < patchTargets.length; i++) { const target = _global[patchTargets[i]]; - target && target.prototype && - patchFilteredProperties( - target.prototype, getOnEventNames(target.prototype), ignoreProperties); + target && + target.prototype && + patchFilteredProperties( + target.prototype, + getOnEventNames(target.prototype), + ignoreProperties, + ); } } diff --git a/packages/zone.js/lib/browser/register-element.ts b/packages/zone.js/lib/browser/register-element.ts index 8a4c6dd827a00..09b11b831e603 100644 --- a/packages/zone.js/lib/browser/register-element.ts +++ b/packages/zone.js/lib/browser/register-element.ts @@ -12,8 +12,12 @@ export function registerElementPatch(_global: any, api: _ZonePrivate) { return; } - const callbacks = - ['createdCallback', 'attachedCallback', 'detachedCallback', 'attributeChangedCallback']; + const callbacks = [ + 'createdCallback', + 'attachedCallback', + 'detachedCallback', + 'attributeChangedCallback', + ]; api.patchCallbacks(api, document, 'Document', 'registerElement', callbacks); } diff --git a/packages/zone.js/lib/browser/shadydom.ts b/packages/zone.js/lib/browser/shadydom.ts index 37492ad337ece..9a4517f080306 100644 --- a/packages/zone.js/lib/browser/shadydom.ts +++ b/packages/zone.js/lib/browser/shadydom.ts @@ -16,11 +16,16 @@ export function patchShadyDom(Zone: ZoneType): void { // so zone.js need to patch them again. const HTMLSlotElement = global.HTMLSlotElement; const prototypes = [ - Object.getPrototypeOf(window), Node.prototype, Text.prototype, Element.prototype, - HTMLElement.prototype, HTMLSlotElement && HTMLSlotElement.prototype, - DocumentFragment.prototype, Document.prototype + Object.getPrototypeOf(window), + Node.prototype, + Text.prototype, + Element.prototype, + HTMLElement.prototype, + HTMLSlotElement && HTMLSlotElement.prototype, + DocumentFragment.prototype, + Document.prototype, ]; - prototypes.forEach(function(proto) { + prototypes.forEach(function (proto) { if (proto && proto.hasOwnProperty('addEventListener')) { proto[Zone.__symbol__('addEventListener')] = null; proto[Zone.__symbol__('removeEventListener')] = null; diff --git a/packages/zone.js/lib/browser/webapis-media-query.ts b/packages/zone.js/lib/browser/webapis-media-query.ts index ff8ea2ceea086..04f84257a82e9 100644 --- a/packages/zone.js/lib/browser/webapis-media-query.ts +++ b/packages/zone.js/lib/browser/webapis-media-query.ts @@ -67,4 +67,4 @@ export function patchMediaQuery(Zone: ZoneType): void { }); } }); -} \ No newline at end of file +} diff --git a/packages/zone.js/lib/browser/webapis-resize-observer.ts b/packages/zone.js/lib/browser/webapis-resize-observer.ts index abe3336aa64b7..8c76f0863a60d 100644 --- a/packages/zone.js/lib/browser/webapis-resize-observer.ts +++ b/packages/zone.js/lib/browser/webapis-resize-observer.ts @@ -20,7 +20,7 @@ export function patchResizeObserver(Zone: ZoneType): void { api.patchMethod(global, 'ResizeObserver', (delegate: Function) => (self: any, args: any[]) => { const callback = args.length > 0 ? args[0] : null; if (callback) { - args[0] = function(entries: any, observer: any) { + args[0] = function (entries: any, observer: any) { const zones: {[zoneName: string]: any} = {}; const currZone = Zone.current; for (let entry of entries) { @@ -35,11 +35,15 @@ export function patchResizeObserver(Zone: ZoneType): void { zoneEntriesInfo.entries.push(entry); } - Object.keys(zones).forEach(zoneName => { + Object.keys(zones).forEach((zoneName) => { const zoneEntriesInfo = zones[zoneName]; if (zoneEntriesInfo.zone !== Zone.current) { zoneEntriesInfo.zone.run( - callback, this, [zoneEntriesInfo.entries, observer], 'ResizeObserver'); + callback, + this, + [zoneEntriesInfo.entries, observer], + 'ResizeObserver', + ); } else { callback.call(this, zoneEntriesInfo.entries, observer); } @@ -50,50 +54,58 @@ export function patchResizeObserver(Zone: ZoneType): void { }); api.patchMethod( - ResizeObserver.prototype, 'observe', (delegate: Function) => (self: any, args: any[]) => { - const target = args.length > 0 ? args[0] : null; - if (!target) { - return delegate.apply(self, args); - } - let targets = self[resizeObserverSymbol]; - if (!targets) { - targets = self[resizeObserverSymbol] = []; - } - targets.push(target); - target[resizeObserverSymbol] = Zone.current; + ResizeObserver.prototype, + 'observe', + (delegate: Function) => (self: any, args: any[]) => { + const target = args.length > 0 ? args[0] : null; + if (!target) { return delegate.apply(self, args); - }); + } + let 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', (delegate: Function) => (self: any, args: any[]) => { - const target = args.length > 0 ? args[0] : null; - if (!target) { - return delegate.apply(self, args); - } - let targets = self[resizeObserverSymbol]; - if (targets) { - for (let i = 0; i < targets.length; i++) { - if (targets[i] === target) { - targets.splice(i, 1); - break; - } + ResizeObserver.prototype, + 'unobserve', + (delegate: Function) => (self: any, args: any[]) => { + const target = args.length > 0 ? args[0] : null; + if (!target) { + return delegate.apply(self, args); + } + let targets = self[resizeObserverSymbol]; + if (targets) { + for (let i = 0; i < targets.length; i++) { + if (targets[i] === target) { + targets.splice(i, 1); + break; } } - target[resizeObserverSymbol] = undefined; - return delegate.apply(self, args); - }); + } + target[resizeObserverSymbol] = undefined; + return delegate.apply(self, args); + }, + ); api.patchMethod( - ResizeObserver.prototype, 'disconnect', - (delegate: Function) => (self: any, args: any[]) => { - const targets = self[resizeObserverSymbol]; - if (targets) { - targets.forEach((target: any) => { - target[resizeObserverSymbol] = undefined; - }); - self[resizeObserverSymbol] = undefined; - } - return delegate.apply(self, args); - }); + ResizeObserver.prototype, + 'disconnect', + (delegate: Function) => (self: any, args: any[]) => { + const targets = self[resizeObserverSymbol]; + if (targets) { + targets.forEach((target: any) => { + target[resizeObserverSymbol] = undefined; + }); + self[resizeObserverSymbol] = undefined; + } + return delegate.apply(self, args); + }, + ); }); } diff --git a/packages/zone.js/lib/browser/webapis-user-media.ts b/packages/zone.js/lib/browser/webapis-user-media.ts index c4de209a74e7c..b7ced6659ca47 100644 --- a/packages/zone.js/lib/browser/webapis-user-media.ts +++ b/packages/zone.js/lib/browser/webapis-user-media.ts @@ -11,7 +11,7 @@ import {ZoneType} from '../zone-impl'; export function patchUserMedia(Zone: ZoneType): void { Zone.__load_patch('getUserMedia', (global: any, Zone: any, api: _ZonePrivate) => { function wrapFunctionArgs(func: Function, source?: string): Function { - return function(this: unknown) { + return function (this: unknown) { const args = Array.prototype.slice.call(arguments); const wrappedArgs = api.bindArguments(args, source ? source : (func as any).name); return func.apply(this, wrappedArgs); diff --git a/packages/zone.js/lib/browser/websocket.ts b/packages/zone.js/lib/browser/websocket.ts index fecb81496644e..a5e0710394111 100644 --- a/packages/zone.js/lib/browser/websocket.ts +++ b/packages/zone.js/lib/browser/websocket.ts @@ -15,7 +15,7 @@ export function apply(api: _ZonePrivate, _global: any) { if (!(_global).EventTarget) { api.patchEventTarget(_global, api, [WS.prototype]); } - (_global).WebSocket = function(x: any, y: any) { + (_global).WebSocket = function (x: any, y: any) { const socket = arguments.length > 1 ? new WS(x, y) : new WS(x); let proxySocket: any; @@ -29,20 +29,21 @@ export function apply(api: _ZonePrivate, _global: any) { // but proxySocket not, so we will keep socket as prototype and pass it to // patchOnProperties method proxySocketProto = socket; - [ADD_EVENT_LISTENER_STR, REMOVE_EVENT_LISTENER_STR, 'send', 'close'].forEach(function( - propName) { - proxySocket[propName] = function() { - const args = api.ArraySlice.call(arguments); - if (propName === ADD_EVENT_LISTENER_STR || propName === REMOVE_EVENT_LISTENER_STR) { - const eventName = args.length > 0 ? args[0] : undefined; - if (eventName) { - const propertySymbol = Zone.__symbol__('ON_PROPERTY' + eventName); - socket[propertySymbol] = proxySocket[propertySymbol]; + [ADD_EVENT_LISTENER_STR, REMOVE_EVENT_LISTENER_STR, 'send', 'close'].forEach( + function (propName) { + proxySocket[propName] = function () { + const args = api.ArraySlice.call(arguments); + if (propName === ADD_EVENT_LISTENER_STR || propName === REMOVE_EVENT_LISTENER_STR) { + const eventName = args.length > 0 ? args[0] : undefined; + if (eventName) { + const propertySymbol = Zone.__symbol__('ON_PROPERTY' + eventName); + socket[propertySymbol] = proxySocket[propertySymbol]; + } } - } - return socket[propName].apply(socket, args); - }; - }); + return socket[propName].apply(socket, args); + }; + }, + ); } else { // we can patch the real socket proxySocket = socket; diff --git a/packages/zone.js/lib/common/error-rewrite.ts b/packages/zone.js/lib/common/error-rewrite.ts index b9b24daab8b65..c0ee7714ad63f 100644 --- a/packages/zone.js/lib/common/error-rewrite.ts +++ b/packages/zone.js/lib/common/error-rewrite.ts @@ -24,11 +24,11 @@ export function patchError(Zone: ZoneType): void { /// Skip this frame when printing out stack zoneJsInternal, /// This frame marks zone transition - transition + transition, } const zoneJsInternalStackFramesSymbol = api.symbol('zoneJsInternalStackFrames'); - const NativeError = global[api.symbol('Error')] = global['Error']; + const NativeError = (global[api.symbol('Error')] = global['Error']); // Store the frames which should be removed from the stack frames const zoneJsInternalStackFrames: {[frame: string]: FrameType} = {}; // We must find the frame where Error was created, otherwise we assume we don't understand stack @@ -41,10 +41,11 @@ export function patchError(Zone: ZoneType): void { global['Error'] = ZoneAwareError; const stackRewrite = 'stackRewrite'; - type ZoneJsInternalStackFramesPolicy = 'default'|'disable'|'lazy'; + type ZoneJsInternalStackFramesPolicy = 'default' | 'disable' | 'lazy'; const zoneJsInternalStackFramesPolicy: ZoneJsInternalStackFramesPolicy = - global['__Zone_Error_BlacklistedStackFrames_policy'] || - global['__Zone_Error_ZoneJsInternalStackFrames_policy'] || 'default'; + global['__Zone_Error_BlacklistedStackFrames_policy'] || + global['__Zone_Error_ZoneJsInternalStackFrames_policy'] || + 'default'; interface ZoneFrameName { zoneName: string; @@ -64,14 +65,23 @@ export function patchError(Zone: ZoneType): void { } function buildZoneAwareStackFrames( - originalStack: string, zoneFrame: _ZoneFrame|ZoneFrameName|null, isZoneFrame = true) { + originalStack: string, + zoneFrame: _ZoneFrame | ZoneFrameName | null, + isZoneFrame = true, + ) { let frames: string[] = originalStack.split('\n'); let i = 0; // Find the first frame - while (!(frames[i] === zoneAwareFrame1 || frames[i] === zoneAwareFrame2 || - frames[i] === zoneAwareFrame1WithoutNew || frames[i] === zoneAwareFrame2WithoutNew || - frames[i] === zoneAwareFrame3WithoutNew) && - i < frames.length) { + while ( + !( + frames[i] === zoneAwareFrame1 || + frames[i] === zoneAwareFrame2 || + frames[i] === zoneAwareFrame1WithoutNew || + frames[i] === zoneAwareFrame2WithoutNew || + frames[i] === zoneAwareFrame3WithoutNew + ) && + i < frames.length + ) { i++; } for (; i < frames.length && zoneFrame; i++) { @@ -93,8 +103,9 @@ export function patchError(Zone: ZoneType): void { i--; break; default: - frames[i] += isZoneFrame ? ` [${(zoneFrame as _ZoneFrame).zone.name}]` : - ` [${(zoneFrame as ZoneFrameName).zoneName}]`; + frames[i] += isZoneFrame + ? ` [${(zoneFrame as _ZoneFrame).zone.name}]` + : ` [${(zoneFrame as ZoneFrameName).zoneName}]`; } } } @@ -104,11 +115,11 @@ export function patchError(Zone: ZoneType): void { * This is ZoneAwareError which processes the stack frame and cleans up extra frames as well as * adds zone information to it. */ - function ZoneAwareError(this: unknown|typeof NativeError): Error { + function ZoneAwareError(this: unknown | typeof NativeError): Error { // We always have to return native error otherwise the browser console will not work. let error: Error = NativeError.apply(this, arguments); // Save original stack trace - const originalStack = (error as any)['originalStack'] = error.stack; + const originalStack = ((error as any)['originalStack'] = error.stack); // Process the stack trace and rewrite the frames. if ((ZoneAwareError as any)[stackRewrite] && originalStack) { @@ -118,8 +129,10 @@ export function patchError(Zone: ZoneType): void { (error as any)[api.symbol('zoneFrameNames')] = buildZoneFrameNames(zoneFrame); } else if (zoneJsInternalStackFramesPolicy === 'default') { try { - error.stack = error.zoneAwareStack = - buildZoneAwareStackFrames(originalStack, zoneFrame); + error.stack = error.zoneAwareStack = buildZoneAwareStackFrames( + originalStack, + zoneFrame, + ); } catch (e) { // ignore as some browsers don't allow overriding of stack } @@ -129,16 +142,18 @@ export function patchError(Zone: ZoneType): void { if (this instanceof NativeError && this.constructor != NativeError) { // We got called with a `new` operator AND we are subclass of ZoneAwareError // in that case we have to copy all of our properties to `this`. - Object.keys(error).concat('stack', 'message').forEach((key) => { - const value = (error as any)[key]; - if (value !== undefined) { - try { - this[key] = value; - } catch (e) { - // ignore the assignment in case it is a setter and it throws. + Object.keys(error) + .concat('stack', 'message') + .forEach((key) => { + const value = (error as any)[key]; + if (value !== undefined) { + try { + this[key] = value; + } catch (e) { + // ignore the assignment in case it is a setter and it throws. + } } - } - }); + }); return this; } return error; @@ -156,18 +171,24 @@ export function patchError(Zone: ZoneType): void { Object.defineProperty(ZoneAwareError.prototype, 'zoneAwareStack', { configurable: true, enumerable: true, - get: function() { + get: function () { if (!this[zoneAwareStackSymbol]) { this[zoneAwareStackSymbol] = buildZoneAwareStackFrames( - this.originalStack, this[api.symbol('zoneFrameNames')], false); + this.originalStack, + this[api.symbol('zoneFrameNames')], + false, + ); } return this[zoneAwareStackSymbol]; }, - set: function(newStack: string) { + set: function (newStack: string) { this.originalStack = newStack; this[zoneAwareStackSymbol] = buildZoneAwareStackFrames( - this.originalStack, this[api.symbol('zoneFrameNames')], false); - } + this.originalStack, + this[api.symbol('zoneFrameNames')], + false, + ); + }, }); } @@ -176,15 +197,15 @@ export function patchError(Zone: ZoneType): void { // those properties of NativeError should be set to ZoneAwareError const nativeErrorProperties = Object.keys(NativeError); if (nativeErrorProperties) { - nativeErrorProperties.forEach(prop => { - if (specialPropertyNames.filter(sp => sp === prop).length === 0) { + nativeErrorProperties.forEach((prop) => { + if (specialPropertyNames.filter((sp) => sp === prop).length === 0) { Object.defineProperty(ZoneAwareError, prop, { - get: function() { + get: function () { return NativeError[prop]; }, - set: function(value) { + set: function (value) { NativeError[prop] = value; - } + }, }); } }); @@ -196,12 +217,12 @@ export function patchError(Zone: ZoneType): void { // make sure that ZoneAwareError has the same property which forwards to NativeError. Object.defineProperty(ZoneAwareError, 'stackTraceLimit', { - get: function() { + get: function () { return NativeError.stackTraceLimit; }, - set: function(value) { - return NativeError.stackTraceLimit = value; - } + set: function (value) { + return (NativeError.stackTraceLimit = value); + }, }); } @@ -211,21 +232,23 @@ export function patchError(Zone: ZoneType): void { // stack frame when prepareStackTrace below value: function zoneCaptureStackTrace(targetObject: Object, constructorOpt?: Function) { NativeError.captureStackTrace(targetObject, constructorOpt); - } + }, }); } const ZONE_CAPTURESTACKTRACE = 'zoneCaptureStackTrace'; Object.defineProperty(ZoneAwareError, 'prepareStackTrace', { - get: function() { + get: function () { return NativeError.prepareStackTrace; }, - set: function(value) { + set: function (value) { if (!value || typeof value !== 'function') { - return NativeError.prepareStackTrace = value; + return (NativeError.prepareStackTrace = value); } - return NativeError.prepareStackTrace = function( - error: Error, structuredStackTrace: {getFunctionName: Function}[]) { + return (NativeError.prepareStackTrace = function ( + error: Error, + structuredStackTrace: {getFunctionName: Function}[], + ) { // remove additional stack information from ZoneAwareError.captureStackTrace if (structuredStackTrace) { for (let i = 0; i < structuredStackTrace.length; i++) { @@ -238,8 +261,8 @@ export function patchError(Zone: ZoneType): void { } } return value.call(this, error, structuredStackTrace); - }; - } + }); + }, }); if (zoneJsInternalStackFramesPolicy === 'disable') { @@ -253,11 +276,17 @@ export function patchError(Zone: ZoneType): void { let detectZone: Zone = Zone.current.fork({ name: 'detect', - onHandleError: function( - parentZD: ZoneDelegate, current: Zone, target: Zone, error: any): boolean { + onHandleError: function ( + parentZD: ZoneDelegate, + current: Zone, + target: Zone, + error: any, + ): boolean { if (error.originalStack && Error === ZoneAwareError) { let frames = error.originalStack.split(/\n/); - let runFrame = false, runGuardedFrame = false, runTaskFrame = false; + let runFrame = false, + runGuardedFrame = false, + runTaskFrame = false; while (frames.length) { let frame = frames.shift(); // On safari it is possible to have stack frame with no line number. @@ -280,8 +309,10 @@ export function patchError(Zone: ZoneType): void { zoneAwareFrame1WithoutNew = frame; zoneAwareFrame2WithoutNew = frame.replace('Error.', ''); if (frame.indexOf('Error.ZoneAwareError') === -1) { - zoneAwareFrame3WithoutNew = - frame.replace('ZoneAwareError', 'Error.ZoneAwareError'); + zoneAwareFrame3WithoutNew = frame.replace( + 'ZoneAwareError', + 'Error.ZoneAwareError', + ); } } zoneJsInternalStackFrames[zoneAwareFrame2] = FrameType.zoneJsInternal; @@ -305,25 +336,25 @@ export function patchError(Zone: ZoneType): void { } } return false; - } + }, }) as Zone; // carefully constructor a stack frame which contains all of the frames of interest which // need to be detected and marked as an internal zoneJs frame. const childDetectZone = detectZone.fork({ name: 'child', - onScheduleTask: function(delegate, curr, target, task) { + onScheduleTask: function (delegate, curr, target, task) { return delegate.scheduleTask(target, task); }, - onInvokeTask: function(delegate, curr, target, task, applyThis, applyArgs) { + onInvokeTask: function (delegate, curr, target, task, applyThis, applyArgs) { return delegate.invokeTask(target, task, applyThis, applyArgs); }, - onCancelTask: function(delegate, curr, target, task) { + onCancelTask: function (delegate, curr, target, task) { return delegate.cancelTask(target, task); }, - onInvoke: function(delegate, curr, target, callback, applyThis, applyArgs, source) { + onInvoke: function (delegate, curr, target, callback, applyThis, applyArgs, source) { return delegate.invoke(target, callback, applyThis, applyArgs, source); - } + }, }); // we need to detect all zone related frames, it will @@ -339,45 +370,49 @@ export function patchError(Zone: ZoneType): void { childDetectZone.runGuarded(() => { const fakeTransitionTo = () => {}; childDetectZone.scheduleEventTask( - zoneJsInternalStackFramesSymbol, - () => { - childDetectZone.scheduleMacroTask( + zoneJsInternalStackFramesSymbol, + () => { + childDetectZone.scheduleMacroTask( + zoneJsInternalStackFramesSymbol, + () => { + childDetectZone.scheduleMicroTask( zoneJsInternalStackFramesSymbol, () => { - childDetectZone.scheduleMicroTask( - zoneJsInternalStackFramesSymbol, - () => { - throw new Error(); - }, - undefined, - (t: Task) => { - (t as any)._transitionTo = fakeTransitionTo; - t.invoke(); - }); - childDetectZone.scheduleMicroTask( - zoneJsInternalStackFramesSymbol, - () => { - throw Error(); - }, - undefined, - (t: Task) => { - (t as any)._transitionTo = fakeTransitionTo; - t.invoke(); - }); + throw new Error(); }, undefined, - (t) => { + (t: Task) => { (t as any)._transitionTo = fakeTransitionTo; t.invoke(); }, - () => {}); - }, - undefined, - (t) => { - (t as any)._transitionTo = fakeTransitionTo; - t.invoke(); - }, - () => {}); + ); + childDetectZone.scheduleMicroTask( + zoneJsInternalStackFramesSymbol, + () => { + throw Error(); + }, + undefined, + (t: Task) => { + (t as any)._transitionTo = fakeTransitionTo; + t.invoke(); + }, + ); + }, + undefined, + (t) => { + (t as any)._transitionTo = fakeTransitionTo; + t.invoke(); + }, + () => {}, + ); + }, + undefined, + (t) => { + (t as any)._transitionTo = fakeTransitionTo; + t.invoke(); + }, + () => {}, + ); }); }); diff --git a/packages/zone.js/lib/common/events.ts b/packages/zone.js/lib/common/events.ts index 89fa6a856a2f1..7c4eae29ff8cb 100644 --- a/packages/zone.js/lib/common/events.ts +++ b/packages/zone.js/lib/common/events.ts @@ -10,8 +10,17 @@ * @suppress {missingRequire} */ -import {ADD_EVENT_LISTENER_STR, attachOriginToPatched, FALSE_STR, isNode, ObjectGetPrototypeOf, REMOVE_EVENT_LISTENER_STR, TRUE_STR, ZONE_SYMBOL_PREFIX, zoneSymbol} from './utils'; - +import { + ADD_EVENT_LISTENER_STR, + attachOriginToPatched, + FALSE_STR, + isNode, + ObjectGetPrototypeOf, + REMOVE_EVENT_LISTENER_STR, + TRUE_STR, + ZONE_SYMBOL_PREFIX, + zoneSymbol, +} from './utils'; /** @internal **/ interface EventTaskData extends TaskData { @@ -24,9 +33,9 @@ let passiveSupported = false; if (typeof window !== 'undefined') { try { const options = Object.defineProperty({}, 'passive', { - get: function() { + get: function () { passiveSupported = true; - } + }, }); // Note: We pass the `options` object as the event handler too. This is not compatible with the // signature of `addEventListener` or `removeEventListener` but enables us to remove the handler @@ -40,7 +49,7 @@ if (typeof window !== 'undefined') { // an identifier to tell ZoneTask do not create a new invoke closure const OPTIMIZED_ZONE_EVENT_TASK_DATA: EventTaskData = { - useG: true + useG: true, }; export const zoneSymbolEventNames: any = {}; @@ -89,13 +98,17 @@ export interface PatchEventTargetOptions { } export function patchEventTarget( - _global: any, api: _ZonePrivate, apis: any[], patchOptions?: PatchEventTargetOptions) { + _global: any, + api: _ZonePrivate, + apis: any[], + patchOptions?: PatchEventTargetOptions, +) { const ADD_EVENT_LISTENER = (patchOptions && patchOptions.add) || ADD_EVENT_LISTENER_STR; const REMOVE_EVENT_LISTENER = (patchOptions && patchOptions.rm) || REMOVE_EVENT_LISTENER_STR; const LISTENERS_EVENT_LISTENER = (patchOptions && patchOptions.listeners) || 'eventListeners'; const REMOVE_ALL_LISTENERS_EVENT_LISTENER = - (patchOptions && patchOptions.rmAll) || 'removeAllListeners'; + (patchOptions && patchOptions.rmAll) || 'removeAllListeners'; const zoneSymbolAddEventListener = zoneSymbol(ADD_EVENT_LISTENER); @@ -104,7 +117,7 @@ export function patchEventTarget( const PREPEND_EVENT_LISTENER = 'prependListener'; const PREPEND_EVENT_LISTENER_SOURCE = '.' + PREPEND_EVENT_LISTENER + ':'; - const invokeTask = function(task: any, target: any, event: Event): Error|undefined { + const invokeTask = function (task: any, target: any, event: Event): Error | undefined { // for better performance, check isRemoved which is set // by removeEventListener if (task.isRemoved) { @@ -184,12 +197,12 @@ export function patchEventTarget( } // global shared zoneAwareCallback to handle all event callback with capture = false - const globalZoneAwareCallback = function(this: unknown, event: Event) { + const globalZoneAwareCallback = function (this: unknown, event: Event) { return globalCallback(this, event, false); }; // global shared zoneAwareCallback to handle all event callback with capture = true - const globalZoneAwareCaptureCallback = function(this: unknown, event: Event) { + const globalZoneAwareCaptureCallback = function (this: unknown, event: Event) { return globalCallback(this, event, true); }; @@ -236,19 +249,19 @@ export function patchEventTarget( // so we do not need to create a new object just for pass some data const taskData: any = {}; - const nativeAddEventListener = proto[zoneSymbolAddEventListener] = proto[ADD_EVENT_LISTENER]; - const nativeRemoveEventListener = proto[zoneSymbol(REMOVE_EVENT_LISTENER)] = - proto[REMOVE_EVENT_LISTENER]; + const nativeAddEventListener = (proto[zoneSymbolAddEventListener] = proto[ADD_EVENT_LISTENER]); + const nativeRemoveEventListener = (proto[zoneSymbol(REMOVE_EVENT_LISTENER)] = + proto[REMOVE_EVENT_LISTENER]); - const nativeListeners = proto[zoneSymbol(LISTENERS_EVENT_LISTENER)] = - proto[LISTENERS_EVENT_LISTENER]; - const nativeRemoveAllListeners = proto[zoneSymbol(REMOVE_ALL_LISTENERS_EVENT_LISTENER)] = - proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER]; + const nativeListeners = (proto[zoneSymbol(LISTENERS_EVENT_LISTENER)] = + proto[LISTENERS_EVENT_LISTENER]); + const nativeRemoveAllListeners = (proto[zoneSymbol(REMOVE_ALL_LISTENERS_EVENT_LISTENER)] = + proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER]); let nativePrependEventListener: any; if (patchOptions && patchOptions.prepend) { nativePrependEventListener = proto[zoneSymbol(patchOptions.prepend)] = - proto[patchOptions.prepend]; + proto[patchOptions.prepend]; } /** @@ -277,19 +290,21 @@ export function patchEventTarget( return options; } - const customScheduleGlobal = function(task: Task) { + const customScheduleGlobal = function (task: Task) { // if there is already a task for the eventName + capture, // just return, because we use the shared globalZoneAwareCallback here. if (taskData.isExisting) { return; } return nativeAddEventListener.call( - taskData.target, taskData.eventName, - taskData.capture ? globalZoneAwareCaptureCallback : globalZoneAwareCallback, - taskData.options); + taskData.target, + taskData.eventName, + taskData.capture ? globalZoneAwareCaptureCallback : globalZoneAwareCallback, + taskData.options, + ); }; - const customCancelGlobal = function(task: any) { + const customCancelGlobal = function (task: any) { // if task is not marked as isRemoved, this call is directly // from Zone.prototype.cancelTask, we should remove the task // from tasksList of target first @@ -325,43 +340,61 @@ export function patchEventTarget( return; } return nativeRemoveEventListener.call( - task.target, task.eventName, - task.capture ? globalZoneAwareCaptureCallback : globalZoneAwareCallback, task.options); + task.target, + task.eventName, + task.capture ? globalZoneAwareCaptureCallback : globalZoneAwareCallback, + task.options, + ); }; - const customScheduleNonGlobal = function(task: Task) { + const customScheduleNonGlobal = function (task: Task) { return nativeAddEventListener.call( - taskData.target, taskData.eventName, task.invoke, taskData.options); + taskData.target, + taskData.eventName, + task.invoke, + taskData.options, + ); }; - const customSchedulePrepend = function(task: Task) { + const customSchedulePrepend = function (task: Task) { return nativePrependEventListener.call( - taskData.target, taskData.eventName, task.invoke, taskData.options); + taskData.target, + taskData.eventName, + task.invoke, + taskData.options, + ); }; - const customCancelNonGlobal = function(task: any) { + const customCancelNonGlobal = function (task: any) { return nativeRemoveEventListener.call(task.target, task.eventName, task.invoke, task.options); }; const customSchedule = useGlobalCallback ? customScheduleGlobal : customScheduleNonGlobal; const customCancel = useGlobalCallback ? customCancelGlobal : customCancelNonGlobal; - const compareTaskCallbackVsDelegate = function(task: any, delegate: any) { + const compareTaskCallbackVsDelegate = function (task: any, delegate: any) { const typeOfDelegate = typeof delegate; - return (typeOfDelegate === 'function' && task.callback === delegate) || - (typeOfDelegate === 'object' && task.originalDelegate === delegate); + return ( + (typeOfDelegate === 'function' && task.callback === delegate) || + (typeOfDelegate === 'object' && task.originalDelegate === delegate) + ); }; const compare = - (patchOptions && patchOptions.diff) ? patchOptions.diff : compareTaskCallbackVsDelegate; + patchOptions && patchOptions.diff ? patchOptions.diff : compareTaskCallbackVsDelegate; const unpatchedEvents: string[] = (Zone as any)[zoneSymbol('UNPATCHED_EVENTS')]; const passiveEvents: string[] = _global[zoneSymbol('PASSIVE_EVENTS')]; - const makeAddListener = function( - nativeListener: any, addSource: string, customScheduleFn: any, customCancelFn: any, - returnTarget = false, prepend = false) { - return function(this: unknown) { + const makeAddListener = function ( + nativeListener: any, + addSource: string, + customScheduleFn: any, + customCancelFn: any, + returnTarget = false, + prepend = false, + ) { + return function (this: unknown) { const target = this || _global; let eventName = arguments[0]; if (patchOptions && patchOptions.transferEventName) { @@ -392,12 +425,15 @@ export function patchEventTarget( } const passive = - passiveSupported && !!passiveEvents && passiveEvents.indexOf(eventName) !== -1; + passiveSupported && !!passiveEvents && passiveEvents.indexOf(eventName) !== -1; const options = buildEventListenerOptions(arguments[2], passive); - const signal = options && typeof options === 'object' && options.signal && - typeof options.signal === 'object' ? - options.signal : - undefined; + const signal = + options && + typeof options === 'object' && + options.signal && + typeof options.signal === 'object' + ? options.signal + : undefined; if (signal?.aborted) { // the signal is an aborted one, just return without attaching the event listener. return; @@ -449,8 +485,10 @@ export function patchEventTarget( source = targetSource[eventName]; } if (!source) { - source = constructorName + addSource + - (eventNameToString ? eventNameToString(eventName) : eventName); + source = + constructorName + + addSource + + (eventNameToString ? eventNameToString(eventName) : eventName); } // do not create a new object as task.data to pass those things // just use the global shared one @@ -479,15 +517,25 @@ export function patchEventTarget( // and handle ourselves. taskData.options.signal = undefined; } - const task: any = - zone.scheduleEventTask(source, delegate, data, customScheduleFn, customCancelFn); + const task: any = zone.scheduleEventTask( + source, + delegate, + data, + customScheduleFn, + customCancelFn, + ); if (signal) { // after task is scheduled, we need to store the signal back to task.options taskData.options.signal = signal; - nativeListener.call(signal, 'abort', () => { - task.zone.cancelTask(task); - }, {once: true}); + nativeListener.call( + signal, + 'abort', + () => { + task.zone.cancelTask(task); + }, + {once: true}, + ); } // should clear taskData.target to avoid memory leak @@ -529,15 +577,24 @@ export function patchEventTarget( }; proto[ADD_EVENT_LISTENER] = makeAddListener( - nativeAddEventListener, ADD_EVENT_LISTENER_SOURCE, customSchedule, customCancel, - returnTarget); + nativeAddEventListener, + ADD_EVENT_LISTENER_SOURCE, + customSchedule, + customCancel, + returnTarget, + ); if (nativePrependEventListener) { proto[PREPEND_EVENT_LISTENER] = makeAddListener( - nativePrependEventListener, PREPEND_EVENT_LISTENER_SOURCE, customSchedulePrepend, - customCancel, returnTarget, true); + nativePrependEventListener, + PREPEND_EVENT_LISTENER_SOURCE, + customSchedulePrepend, + customCancel, + returnTarget, + true, + ); } - proto[REMOVE_EVENT_LISTENER] = function() { + proto[REMOVE_EVENT_LISTENER] = function () { const target = this || _global; let eventName = arguments[0]; if (patchOptions && patchOptions.transferEventName) { @@ -551,8 +608,10 @@ export function patchEventTarget( return nativeRemoveEventListener.apply(this, arguments); } - if (validateHandler && - !validateHandler(nativeRemoveEventListener, delegate, target, arguments)) { + if ( + validateHandler && + !validateHandler(nativeRemoveEventListener, delegate, target, arguments) + ) { return; } @@ -599,7 +658,7 @@ export function patchEventTarget( return nativeRemoveEventListener.apply(this, arguments); }; - proto[LISTENERS_EVENT_LISTENER] = function() { + proto[LISTENERS_EVENT_LISTENER] = function () { const target = this || _global; let eventName = arguments[0]; if (patchOptions && patchOptions.transferEventName) { @@ -607,8 +666,10 @@ export function patchEventTarget( } const listeners: any[] = []; - const tasks = - findEventTasks(target, eventNameToString ? eventNameToString(eventName) : eventName); + const tasks = findEventTasks( + target, + eventNameToString ? eventNameToString(eventName) : eventName, + ); for (let i = 0; i < tasks.length; i++) { const task: any = tasks[i]; @@ -618,7 +679,7 @@ export function patchEventTarget( return listeners; }; - proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER] = function() { + proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER] = function () { const target = this || _global; let eventName = arguments[0]; @@ -722,8 +783,9 @@ export function findEventTasks(target: any, eventName: string): Task[] { if (!captureFalseTasks) { return captureTrueTasks ? captureTrueTasks.slice() : []; } else { - return captureTrueTasks ? captureFalseTasks.concat(captureTrueTasks) : - captureFalseTasks.slice(); + return captureTrueTasks + ? captureFalseTasks.concat(captureTrueTasks) + : captureFalseTasks.slice(); } } @@ -731,13 +793,16 @@ export function patchEventPrototype(global: any, api: _ZonePrivate) { const Event = global['Event']; if (Event && Event.prototype) { api.patchMethod( - Event.prototype, 'stopImmediatePropagation', - (delegate: Function) => function(self: any, args: any[]) { + Event.prototype, + 'stopImmediatePropagation', + (delegate: Function) => + function (self: any, args: any[]) { self[IMMEDIATE_PROPAGATION_SYMBOL] = true; // we need to call the native stopImmediatePropagation // in case in some hybrid application, some part of // application will be controlled by zone, some are not delegate && delegate.apply(self, args); - }); + }, + ); } } diff --git a/packages/zone.js/lib/common/fetch.ts b/packages/zone.js/lib/common/fetch.ts index ddb80ff478e69..d2892d6ad2d34 100644 --- a/packages/zone.js/lib/common/fetch.ts +++ b/packages/zone.js/lib/common/fetch.ts @@ -30,60 +30,70 @@ export function patchFetch(Zone: ZoneType): void { const symbolThenPatched = api.symbol('thenPatched'); const fetchTaskScheduling = api.symbol('fetchTaskScheduling'); const OriginalResponse = global.Response; - const placeholder = function() {}; + const placeholder = function () {}; - const createFetchTask = - (source: string, data: TaskData|undefined, originalImpl: any, self: any, args: any[], - ac?: AbortController) => new Promise((resolve, reject) => { - const task = Zone.current.scheduleMacroTask( - source, placeholder, data, - () => { - // The promise object returned by the original implementation passed into the - // function. This might be a `fetch` promise, `Response.prototype.json` promise, - // etc. - let implPromise; - let zone = Zone.current; + const createFetchTask = ( + source: string, + data: TaskData | undefined, + originalImpl: any, + self: any, + args: any[], + ac?: AbortController, + ) => + new Promise((resolve, reject) => { + const task = Zone.current.scheduleMacroTask( + source, + placeholder, + data, + () => { + // The promise object returned by the original implementation passed into the + // function. This might be a `fetch` promise, `Response.prototype.json` promise, + // etc. + let implPromise; + let zone = Zone.current; - try { - (zone as any)[fetchTaskScheduling] = true; - implPromise = originalImpl.apply(self, args); - } catch (error) { - reject(error); - return; - } finally { - (zone as any)[fetchTaskScheduling] = false; - } + try { + (zone as any)[fetchTaskScheduling] = true; + implPromise = originalImpl.apply(self, args); + } catch (error) { + reject(error); + return; + } finally { + (zone as any)[fetchTaskScheduling] = false; + } - if (!(implPromise instanceof ZoneAwarePromise)) { - let ctor = implPromise.constructor; - if (!ctor[symbolThenPatched]) { - api.patchThen(ctor); - } - } + if (!(implPromise instanceof ZoneAwarePromise)) { + let ctor = implPromise.constructor; + if (!ctor[symbolThenPatched]) { + api.patchThen(ctor); + } + } - implPromise.then( - (resource: any) => { - if (task.state !== 'notScheduled') { - task.invoke(); - } - resolve(resource); - }, - (error: any) => { - if (task.state !== 'notScheduled') { - task.invoke(); - } - reject(error); - }); + implPromise.then( + (resource: any) => { + if (task.state !== 'notScheduled') { + task.invoke(); + } + resolve(resource); }, - () => { - ac?.abort(); - }); - }); + (error: any) => { + if (task.state !== 'notScheduled') { + task.invoke(); + } + reject(error); + }, + ); + }, + () => { + ac?.abort(); + }, + ); + }); - global['fetch'] = function() { + global['fetch'] = function () { const args = Array.prototype.slice.call(arguments); const options = args.length > 1 ? args[1] : {}; - const signal: AbortSignal|undefined = options?.signal; + const signal: AbortSignal | undefined = options?.signal; const ac = new AbortController(); const fetchSignal = ac.signal; options.signal = fetchSignal; @@ -91,12 +101,17 @@ export function patchFetch(Zone: ZoneType): void { if (signal) { const nativeAddEventListener = - signal[Zone.__symbol__('addEventListener') as 'addEventListener'] || - signal.addEventListener; + signal[Zone.__symbol__('addEventListener') as 'addEventListener'] || + signal.addEventListener; - nativeAddEventListener.call(signal, 'abort', function() { - ac!.abort(); - }, {once: true}); + nativeAddEventListener.call( + signal, + 'abort', + function () { + ac!.abort(); + }, + {once: true}, + ); } return createFetchTask('fetch', {fetchArgs: args} as FetchTaskData, fetch, this, args, ac); @@ -105,14 +120,16 @@ export function patchFetch(Zone: ZoneType): void { if (OriginalResponse?.prototype) { // https://fetch.spec.whatwg.org/#body-mixin ['arrayBuffer', 'blob', 'formData', 'json', 'text'] - // Safely check whether the method exists on the `Response` prototype before patching. - .filter(method => typeof OriginalResponse.prototype[method] === 'function') - .forEach(method => { - api.patchMethod( - OriginalResponse.prototype, method, - (delegate: Function) => (self, args) => createFetchTask( - `Response.${method}`, undefined, delegate, self, args, undefined)); - }); + // Safely check whether the method exists on the `Response` prototype before patching. + .filter((method) => typeof OriginalResponse.prototype[method] === 'function') + .forEach((method) => { + api.patchMethod( + OriginalResponse.prototype, + method, + (delegate: Function) => (self, args) => + createFetchTask(`Response.${method}`, undefined, delegate, self, args, undefined), + ); + }); } }); } diff --git a/packages/zone.js/lib/common/promise.ts b/packages/zone.js/lib/common/promise.ts index acfbb5edf1c97..1bcd3d91ed596 100644 --- a/packages/zone.js/lib/common/promise.ts +++ b/packages/zone.js/lib/common/promise.ts @@ -26,7 +26,7 @@ export function patchPromise(Zone: ZoneType): void { const __symbol__ = api.symbol; const _uncaughtPromiseErrors: UncaughtPromiseError[] = []; const isDisableWrappingUncaughtPromiseRejection = - global[__symbol__('DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION')] !== false; + global[__symbol__('DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION')] !== false; const symbolPromise = __symbol__('Promise'); const symbolThen = __symbol__('then'); const creationTrace = '__creationTrace__'; @@ -36,10 +36,16 @@ export function patchPromise(Zone: ZoneType): void { const rejection = e && e.rejection; if (rejection) { console.error( - 'Unhandled Promise rejection:', - rejection instanceof Error ? rejection.message : rejection, - '; Zone:', (e.zone).name, '; Task:', e.task && (e.task).source, - '; Value:', rejection, rejection instanceof Error ? rejection.stack : undefined); + 'Unhandled Promise rejection:', + rejection instanceof Error ? rejection.message : rejection, + '; Zone:', + (e.zone).name, + '; Task:', + e.task && (e.task).source, + '; Value:', + rejection, + rejection instanceof Error ? rejection.stack : undefined, + ); } else { console.error(e); } @@ -62,8 +68,9 @@ export function patchPromise(Zone: ZoneType): void { } }; - const UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL = - __symbol__('unhandledPromiseRejectionHandler'); + const UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL = __symbol__( + 'unhandledPromiseRejectionHandler', + ); function handleUnhandledRejection(this: unknown, e: any) { api.onUnhandledError(e); @@ -72,8 +79,7 @@ export function patchPromise(Zone: ZoneType): void { if (typeof handler === 'function') { handler.call(this, e); } - } catch (err) { - } + } catch (err) {} } function isThenable(value: any): boolean { @@ -110,11 +116,11 @@ export function patchPromise(Zone: ZoneType): void { }; } - const once = function() { + const once = function () { let wasCalled = false; return function wrapper(wrappedFunction: Function) { - return function() { + return function () { if (wasCalled) { return; } @@ -129,7 +135,10 @@ export function patchPromise(Zone: ZoneType): void { // Promise Resolution function resolvePromise( - promise: ZoneAwarePromise, state: boolean, value: any): ZoneAwarePromise { + promise: ZoneAwarePromise, + state: boolean, + value: any, + ): ZoneAwarePromise { const onceWrapper = once(); if (promise === value) { throw new TypeError(TYPE_ERROR); @@ -148,16 +157,22 @@ export function patchPromise(Zone: ZoneType): void { return promise; } // if (value instanceof ZoneAwarePromise) { - if (state !== REJECTED && value instanceof ZoneAwarePromise && - value.hasOwnProperty(symbolState) && value.hasOwnProperty(symbolValue) && - (value as any)[symbolState] !== UNRESOLVED) { + if ( + state !== REJECTED && + value instanceof ZoneAwarePromise && + value.hasOwnProperty(symbolState) && + value.hasOwnProperty(symbolValue) && + (value as any)[symbolState] !== UNRESOLVED + ) { clearRejectedNoCatch(value); resolvePromise(promise, (value as any)[symbolState], (value as any)[symbolValue]); } else if (state !== REJECTED && typeof then === 'function') { try { then.call( - value, onceWrapper(makeResolver(promise, state)), - onceWrapper(makeResolver(promise, false))); + value, + onceWrapper(makeResolver(promise, state)), + onceWrapper(makeResolver(promise, false)), + ); } catch (err) { onceWrapper(() => { resolvePromise(promise, false, err); @@ -182,17 +197,22 @@ export function patchPromise(Zone: ZoneType): void { // do some additional work such as render longStackTrace if (state === REJECTED && value instanceof Error) { // check if longStackTraceZone is here - const trace = Zone.currentTask && Zone.currentTask.data && - (Zone.currentTask.data as any)[creationTrace]; + const trace = + Zone.currentTask && + Zone.currentTask.data && + (Zone.currentTask.data as any)[creationTrace]; if (trace) { // only keep the long stack trace into error when in longStackTraceZone - ObjectDefineProperty( - value, CURRENT_TASK_TRACE_SYMBOL, - {configurable: true, enumerable: false, writable: true, value: trace}); + ObjectDefineProperty(value, CURRENT_TASK_TRACE_SYMBOL, { + configurable: true, + enumerable: false, + writable: true, + value: trace, + }); } } - for (let i = 0; i < queue.length;) { + for (let i = 0; i < queue.length; ) { scheduleResolveOrReject(promise, queue[i++], queue[i++], queue[i++], queue[i++]); } if (queue.length == 0 && state == REJECTED) { @@ -203,8 +223,10 @@ export function patchPromise(Zone: ZoneType): void { // and if the value is not an error, zone.js builds an `Error` // Object here to attach the stack information. throw new Error( - 'Uncaught (in promise): ' + readableObjectToString(value) + - (value && value.stack ? '\n' + value.stack : '')); + 'Uncaught (in promise): ' + + readableObjectToString(value) + + (value && value.stack ? '\n' + value.stack : ''), + ); } catch (err) { uncaughtPromiseError = err; } @@ -218,7 +240,7 @@ export function patchPromise(Zone: ZoneType): void { uncaughtPromiseError.zone = Zone.current; uncaughtPromiseError.task = Zone.currentTask!; _uncaughtPromiseErrors.push(uncaughtPromiseError); - api.scheduleMicroTask(); // to make sure that it is running + api.scheduleMicroTask(); // to make sure that it is running } } } @@ -239,8 +261,7 @@ export function patchPromise(Zone: ZoneType): void { if (handler && typeof handler === 'function') { handler.call(this, {rejection: (promise as any)[symbolValue], promise: promise}); } - } catch (err) { - } + } catch (err) {} (promise as any)[symbolState] = REJECTED; for (let i = 0; i < _uncaughtPromiseErrors.length; i++) { if (promise === _uncaughtPromiseErrors[i].promise) { @@ -251,42 +272,54 @@ export function patchPromise(Zone: ZoneType): void { } function scheduleResolveOrReject( - promise: ZoneAwarePromise, zone: Zone, chainPromise: ZoneAwarePromise, - onFulfilled?: ((value: R) => U1)|null|undefined, - onRejected?: ((error: any) => U2)|null|undefined): void { + promise: ZoneAwarePromise, + zone: Zone, + chainPromise: ZoneAwarePromise, + onFulfilled?: ((value: R) => U1) | null | undefined, + onRejected?: ((error: any) => U2) | null | undefined, + ): void { clearRejectedNoCatch(promise); const promiseState = (promise as any)[symbolState]; - const delegate = promiseState ? - (typeof onFulfilled === 'function') ? onFulfilled : forwardResolution : - (typeof onRejected === 'function') ? onRejected : - forwardRejection; - zone.scheduleMicroTask(source, () => { - try { - const parentPromiseValue = (promise as any)[symbolValue]; - const isFinallyPromise = + const delegate = promiseState + ? typeof onFulfilled === 'function' + ? onFulfilled + : forwardResolution + : typeof onRejected === 'function' + ? onRejected + : forwardRejection; + zone.scheduleMicroTask( + source, + () => { + try { + const parentPromiseValue = (promise as any)[symbolValue]; + const isFinallyPromise = !!chainPromise && symbolFinally === (chainPromise as any)[symbolFinally]; - if (isFinallyPromise) { - // if the promise is generated from finally call, keep parent promise's state and value - (chainPromise as any)[symbolParentPromiseValue] = parentPromiseValue; - (chainPromise as any)[symbolParentPromiseState] = promiseState; + if (isFinallyPromise) { + // if the promise is generated from finally call, keep parent promise's state and value + (chainPromise as any)[symbolParentPromiseValue] = parentPromiseValue; + (chainPromise as any)[symbolParentPromiseState] = promiseState; + } + // should not pass value to finally callback + const value = zone.run( + delegate, + undefined, + isFinallyPromise && delegate !== forwardRejection && delegate !== forwardResolution + ? [] + : [parentPromiseValue], + ); + resolvePromise(chainPromise, true, value); + } catch (error) { + // if error occurs, should always return this error + resolvePromise(chainPromise, false, error); } - // should not pass value to finally callback - const value = zone.run( - delegate, undefined, - isFinallyPromise && delegate !== forwardRejection && delegate !== forwardResolution ? - [] : - [parentPromiseValue]); - resolvePromise(chainPromise, true, value); - } catch (error) { - // if error occurs, should always return this error - resolvePromise(chainPromise, false, error); - } - }, chainPromise as TaskData); + }, + chainPromise as TaskData, + ); } const ZONE_AWARE_PROMISE_TO_STRING = 'function ZoneAwarePromise() { [native code] }'; - const noop = function() {}; + const noop = function () {}; const AggregateError = global.AggregateError; @@ -307,9 +340,9 @@ export function patchPromise(Zone: ZoneType): void { } static withResolvers(): { - promise: Promise, - resolve: (value?: T|PromiseLike) => void, - reject: (error?: any) => void + promise: Promise; + resolve: (value?: T | PromiseLike) => void; + reject: (error?: any) => void; } { const result: any = {}; result.promise = new ZoneAwarePromise((res, rej) => { @@ -341,24 +374,25 @@ export function patchPromise(Zone: ZoneType): void { return new ZoneAwarePromise((resolve, reject) => { for (let i = 0; i < promises.length; i++) { promises[i].then( - v => { - if (finished) { - return; - } + (v) => { + if (finished) { + return; + } + finished = true; + resolve(v); + }, + (err) => { + errors.push(err); + count--; + if (count === 0) { finished = true; - resolve(v); - }, - err => { - errors.push(err); - count--; - if (count === 0) { - finished = true; - reject(new AggregateError(errors, 'All promises were rejected')); - } - }); + reject(new AggregateError(errors, 'All promises were rejected')); + } + }, + ); } }); - }; + } static race(values: PromiseLike[]): Promise { let resolve: (v: any) => void; @@ -391,14 +425,17 @@ export function patchPromise(Zone: ZoneType): void { const P = this && this.prototype instanceof ZoneAwarePromise ? this : ZoneAwarePromise; return P.allWithCallback(values, { thenCallback: (value: any) => ({status: 'fulfilled', value}), - errorCallback: (err: any) => ({status: 'rejected', reason: err}) + errorCallback: (err: any) => ({status: 'rejected', reason: err}), }); } - static allWithCallback(values: any, callback?: { - thenCallback: (value: any) => any, - errorCallback: (err: any) => any - }): Promise { + static allWithCallback( + values: any, + callback?: { + thenCallback: (value: any) => any; + errorCallback: (err: any) => any; + }, + ): Promise { let resolve: (v: any) => void; let reject: (v: any) => void; let promise = new this((res, rej) => { @@ -419,24 +456,25 @@ export function patchPromise(Zone: ZoneType): void { const curValueIndex = valueIndex; try { value.then( - (value: any) => { - resolvedValues[curValueIndex] = callback ? callback.thenCallback(value) : value; + (value: any) => { + resolvedValues[curValueIndex] = callback ? callback.thenCallback(value) : value; + unresolvedCount--; + if (unresolvedCount === 0) { + resolve!(resolvedValues); + } + }, + (err: any) => { + if (!callback) { + reject!(err); + } else { + resolvedValues[curValueIndex] = callback.errorCallback(err); unresolvedCount--; if (unresolvedCount === 0) { resolve!(resolvedValues); } - }, - (err: any) => { - if (!callback) { - reject!(err); - } else { - resolvedValues[curValueIndex] = callback.errorCallback(err); - unresolvedCount--; - if (unresolvedCount === 0) { - resolve!(resolvedValues); - } - } - }); + } + }, + ); } catch (thenErr) { reject!(thenErr); } @@ -456,37 +494,41 @@ export function patchPromise(Zone: ZoneType): void { } constructor( - executor: (resolve: (value?: R|PromiseLike) => void, reject: (error?: any) => void) => - void) { + executor: ( + resolve: (value?: R | PromiseLike) => void, + reject: (error?: any) => void, + ) => void, + ) { const promise: ZoneAwarePromise = this; if (!(promise instanceof ZoneAwarePromise)) { throw new Error('Must be an instanceof Promise.'); } (promise as any)[symbolState] = UNRESOLVED; - (promise as any)[symbolValue] = []; // queue; + (promise as any)[symbolValue] = []; // queue; try { const onceWrapper = once(); executor && - executor( - onceWrapper(makeResolver(promise, RESOLVED)), - onceWrapper(makeResolver(promise, REJECTED))); + executor( + onceWrapper(makeResolver(promise, RESOLVED)), + onceWrapper(makeResolver(promise, REJECTED)), + ); } catch (error) { resolvePromise(promise, false, error); } } - get[Symbol.toStringTag]() { + get [Symbol.toStringTag]() { return 'Promise' as any; } - get[Symbol.species]() { + get [Symbol.species]() { return ZoneAwarePromise; } then( - onFulfilled?: ((value: R) => TResult1 | PromiseLike)|undefined|null, - onRejected?: ((reason: any) => TResult2 | PromiseLike)|undefined| - null): Promise { + onFulfilled?: ((value: R) => TResult1 | PromiseLike) | undefined | null, + onRejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, + ): Promise { // We must read `Symbol.species` safely because `this` may be anything. For instance, `this` // may be an object without a prototype (created through `Object.create(null)`); thus // `this.constructor` will be undefined. One of the use cases is SystemJS creating @@ -499,7 +541,7 @@ export function patchPromise(Zone: ZoneType): void { if (!C || typeof C !== 'function') { C = this.constructor || ZoneAwarePromise; } - const chainPromise: Promise = new (C as typeof ZoneAwarePromise)(noop); + const chainPromise: Promise = new (C as typeof ZoneAwarePromise)(noop); const zone = Zone.current; if ((this as any)[symbolState] == UNRESOLVED) { ((this as any)[symbolValue]).push(zone, chainPromise, onFulfilled, onRejected); @@ -509,8 +551,9 @@ export function patchPromise(Zone: ZoneType): void { return chainPromise; } - catch(onRejected?: ((reason: any) => TResult | PromiseLike)| - undefined|null): Promise { + catch( + onRejected?: ((reason: any) => TResult | PromiseLike) | undefined | null, + ): Promise { return this.then(null, onRejected); } @@ -520,7 +563,7 @@ export function patchPromise(Zone: ZoneType): void { if (!C || typeof C !== 'function') { C = ZoneAwarePromise; } - const chainPromise: Promise = new (C as typeof ZoneAwarePromise)(noop); + const chainPromise: Promise = new (C as typeof ZoneAwarePromise)(noop); (chainPromise as any)[symbolFinally] = symbolFinally; const zone = Zone.current; if ((this as any)[symbolState] == UNRESOLVED) { @@ -538,7 +581,7 @@ export function patchPromise(Zone: ZoneType): void { ZoneAwarePromise['race'] = ZoneAwarePromise.race; ZoneAwarePromise['all'] = ZoneAwarePromise.all; - const NativePromise = global[symbolPromise] = global['Promise']; + const NativePromise = (global[symbolPromise] = global['Promise']); global['Promise'] = ZoneAwarePromise; const symbolThenPatched = __symbol__('thenPatched'); @@ -557,7 +600,7 @@ export function patchPromise(Zone: ZoneType): void { // Keep a reference to the original method. proto[symbolThen] = originalThen; - Ctor.prototype.then = function(onResolve: any, onReject: any) { + Ctor.prototype.then = function (onResolve: any, onReject: any) { const wrapped = new ZoneAwarePromise((resolve, reject) => { originalThen.call(this, resolve, reject); }); @@ -569,7 +612,7 @@ export function patchPromise(Zone: ZoneType): void { api.patchThen = patchThen; function zoneify(fn: Function) { - return function(self: any, args: any[]) { + return function (self: any, args: any[]) { let resultPromise = fn.apply(self, args); if (resultPromise instanceof ZoneAwarePromise) { return resultPromise; @@ -584,7 +627,7 @@ export function patchPromise(Zone: ZoneType): void { if (NativePromise) { patchThen(NativePromise); - patchMethod(global, 'fetch', delegate => zoneify(delegate)); + patchMethod(global, 'fetch', (delegate) => zoneify(delegate)); } // This is not part of public API, but it is useful for tests, so we expose it. diff --git a/packages/zone.js/lib/common/queue-microtask.ts b/packages/zone.js/lib/common/queue-microtask.ts index c758c3448c953..945c7aca796ef 100644 --- a/packages/zone.js/lib/common/queue-microtask.ts +++ b/packages/zone.js/lib/common/queue-microtask.ts @@ -12,7 +12,7 @@ export function patchQueueMicrotask(global: any, api: _ZonePrivate) { api.patchMethod(global, 'queueMicrotask', (delegate) => { - return function(self: any, args: any[]) { + return function (self: any, args: any[]) { Zone.current.scheduleMicroTask('queueMicrotask', args[0]); }; }); diff --git a/packages/zone.js/lib/common/timers.ts b/packages/zone.js/lib/common/timers.ts index 2e8a6d7b795c3..de99f5024fc81 100644 --- a/packages/zone.js/lib/common/timers.ts +++ b/packages/zone.js/lib/common/timers.ts @@ -20,8 +20,8 @@ interface TimerOptions extends TaskData { } export function patchTimer(window: any, setName: string, cancelName: string, nameSuffix: string) { - let setNative: Function|null = null; - let clearNative: Function|null = null; + let setNative: Function | null = null; + let clearNative: Function | null = null; setName += nameSuffix; cancelName += nameSuffix; @@ -29,7 +29,7 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam function scheduleTask(task: Task) { const data = task.data; - data.args[0] = function() { + data.args[0] = function () { return task.invoke.apply(this, arguments); }; data.handleId = setNative!.apply(window, data.args); @@ -40,14 +40,16 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam return clearNative!.call(window, (task.data).handleId); } - setNative = - patchMethod(window, setName, (delegate: Function) => function(self: any, args: any[]) { + setNative = patchMethod( + window, + setName, + (delegate: Function) => + function (self: any, args: any[]) { if (typeof args[0] === 'function') { const options: TimerOptions = { isPeriodic: nameSuffix === 'Interval', - delay: (nameSuffix === 'Timeout' || nameSuffix === 'Interval') ? args[1] || 0 : - undefined, - args: args + delay: nameSuffix === 'Timeout' || nameSuffix === 'Interval' ? args[1] || 0 : undefined, + args: args, }; const callback = args[0]; args[0] = function timer(this: unknown) { @@ -62,7 +64,7 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam // Cleanup tasksByHandleId should be handled before scheduleTask // Since some zoneSpec may intercept and doesn't trigger // scheduleFn(scheduleTask) provided here. - if (!(options.isPeriodic)) { + if (!options.isPeriodic) { if (typeof options.handleId === 'number') { // in non-nodejs env, we remove timerId // from local cache @@ -75,8 +77,13 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam } } }; - const task = - scheduleMacroTaskWithCurrentZone(setName, args[0], options, scheduleTask, clearTask); + const task = scheduleMacroTaskWithCurrentZone( + setName, + args[0], + options, + scheduleTask, + clearTask, + ); if (!task) { return task; } @@ -94,8 +101,13 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam // check whether handle is null, because some polyfill or browser // may return undefined from setTimeout/setInterval/setImmediate/requestAnimationFrame - if (handle && handle.ref && handle.unref && typeof handle.ref === 'function' && - typeof handle.unref === 'function') { + if ( + handle && + handle.ref && + handle.unref && + typeof handle.ref === 'function' && + typeof handle.unref === 'function' + ) { (task).ref = (handle).ref.bind(handle); (task).unref = (handle).unref.bind(handle); } @@ -107,10 +119,14 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam // cause an error by calling it directly. return delegate.apply(window, args); } - }); + }, + ); - clearNative = - patchMethod(window, cancelName, (delegate: Function) => function(self: any, args: any[]) { + clearNative = patchMethod( + window, + cancelName, + (delegate: Function) => + function (self: any, args: any[]) { const id = args[0]; let task: Task; if (typeof id === 'number') { @@ -125,8 +141,10 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam } } if (task && typeof task.type === 'string') { - if (task.state !== 'notScheduled' && - (task.cancelFn && task.data!.isPeriodic || task.runCount === 0)) { + if ( + task.state !== 'notScheduled' && + ((task.cancelFn && task.data!.isPeriodic) || task.runCount === 0) + ) { if (typeof id === 'number') { delete tasksByHandleId[id]; } else if (id) { @@ -139,5 +157,6 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam // cause an error by calling it directly. delegate.apply(window, args); } - }); + }, + ); } diff --git a/packages/zone.js/lib/common/to-string.ts b/packages/zone.js/lib/common/to-string.ts index 21c7746926e72..a5edaf5bd1183 100644 --- a/packages/zone.js/lib/common/to-string.ts +++ b/packages/zone.js/lib/common/to-string.ts @@ -47,11 +47,10 @@ export function patchToString(Zone: ZoneType): void { (newFunctionToString as any)[ORIGINAL_DELEGATE_SYMBOL] = originalFunctionToString; Function.prototype.toString = newFunctionToString; - // patch Object.prototype.toString to let them look like native const originalObjectToString = Object.prototype.toString; const PROMISE_OBJECT_TO_STRING = '[object Promise]'; - Object.prototype.toString = function() { + Object.prototype.toString = function () { if (typeof Promise === 'function' && this instanceof Promise) { return PROMISE_OBJECT_TO_STRING; } diff --git a/packages/zone.js/lib/common/utils.ts b/packages/zone.js/lib/common/utils.ts index 00e393f3621e2..d9d79a2394e3e 100644 --- a/packages/zone.js/lib/common/utils.ts +++ b/packages/zone.js/lib/common/utils.ts @@ -46,8 +46,12 @@ export function wrapWithCurrentZone(callback: T, source: str } export function scheduleMacroTaskWithCurrentZone( - source: string, callback: Function, data?: TaskData, customSchedule?: (task: Task) => void, - customCancel?: (task: Task) => void): MacroTask { + source: string, + callback: Function, + data?: TaskData, + customSchedule?: (task: Task) => void, + customCancel?: (task: Task) => void, +): MacroTask { return Zone.current.scheduleMacroTask(source, callback, data, customSchedule, customCancel); } @@ -57,7 +61,7 @@ declare const WorkerGlobalScope: any; export const zoneSymbol = __symbol__; const isWindowExists = typeof window !== 'undefined'; const internalWindow: any = isWindowExists ? window : undefined; -const _global: any = isWindowExists && internalWindow || globalThis; +const _global: any = (isWindowExists && internalWindow) || globalThis; const REMOVE_ATTRIBUTE = 'removeAttribute'; @@ -81,7 +85,7 @@ export function patchPrototype(prototype: any, fnNames: string[]) { continue; } prototype[name] = ((delegate: Function) => { - const patched: any = function(this: unknown) { + const patched: any = function (this: unknown) { return delegate.apply(this, bindArguments(arguments, source + '.' + name)); }; attachOriginToPatched(patched, delegate); @@ -104,27 +108,30 @@ export function isPropertyWritable(propertyDesc: any) { } export const isWebWorker: boolean = - (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope); + typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope; // Make sure to access `process` through `_global` so that WebPack does not accidentally browserify // this code. export const isNode: boolean = - (!('nw' in _global) && typeof _global.process !== 'undefined' && - {}.toString.call(_global.process) === '[object process]'); + !('nw' in _global) && + typeof _global.process !== 'undefined' && + {}.toString.call(_global.process) === '[object process]'; export const isBrowser: boolean = - !isNode && !isWebWorker && !!(isWindowExists && internalWindow['HTMLElement']); + !isNode && !isWebWorker && !!(isWindowExists && internalWindow['HTMLElement']); // we are in electron of nw, so we are both browser and nodejs // Make sure to access `process` through `_global` so that WebPack does not accidentally browserify // this code. -export const isMix: boolean = typeof _global.process !== 'undefined' && - {}.toString.call(_global.process) === '[object process]' && !isWebWorker && - !!(isWindowExists && internalWindow['HTMLElement']); +export const isMix: boolean = + typeof _global.process !== 'undefined' && + {}.toString.call(_global.process) === '[object process]' && + !isWebWorker && + !!(isWindowExists && internalWindow['HTMLElement']); const zoneSymbolEventNames: {[eventName: string]: string} = {}; -const wrapFn = function(this: unknown, event: Event) { +const wrapFn = function (this: unknown, event: Event) { // https://github.com/angular/zone.js/issues/911, in IE, sometimes // event will be undefined, so we need to use window.event event = event || _global.event; @@ -143,10 +150,16 @@ const wrapFn = function(this: unknown, event: Event) { // https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror#window.onerror // and onerror callback will prevent default when callback return true const errorEvent: ErrorEvent = event as any; - result = listener && - listener.call( - this, errorEvent.message, errorEvent.filename, errorEvent.lineno, errorEvent.colno, - errorEvent.error); + result = + listener && + listener.call( + this, + errorEvent.message, + errorEvent.filename, + errorEvent.lineno, + errorEvent.colno, + errorEvent.error, + ); if (result === true) { event.preventDefault(); } @@ -198,7 +211,7 @@ export function patchProperty(obj: any, prop: string, prototype?: any) { eventNameSymbol = zoneSymbolEventNames[eventName] = zoneSymbol('ON_PROPERTY' + eventName); } - desc.set = function(this: EventSource, newValue) { + desc.set = function (this: EventSource, newValue) { // in some of windows's onproperty callback, this is undefined // so we need to check it let target = this; @@ -225,7 +238,7 @@ export function patchProperty(obj: any, prop: string, prototype?: any) { // The getter would return undefined for unassigned properties but the default value of an // unassigned property is null - desc.get = function() { + desc.get = function () { // in some of windows's onproperty callback, this is undefined // so we need to check it let target: any = this; @@ -262,7 +275,7 @@ export function patchProperty(obj: any, prop: string, prototype?: any) { obj[onPropPatchedSymbol] = true; } -export function patchOnProperties(obj: any, properties: string[]|null, prototype?: any) { +export function patchOnProperties(obj: any, properties: string[] | null, prototype?: any) { if (properties) { for (let i = 0; i < properties.length; i++) { patchProperty(obj, 'on' + properties[i], prototype); @@ -289,7 +302,7 @@ export function patchClass(className: string) { // keep original class in global _global[zoneSymbol(className)] = OriginalClass; - _global[className] = function() { + _global[className] = function () { const a = bindArguments(arguments, className); switch (a.length) { case 0: @@ -315,20 +328,20 @@ export function patchClass(className: string) { // attach original delegate to patched function attachOriginToPatched(_global[className], OriginalClass); - const instance = new OriginalClass(function() {}); + const instance = new OriginalClass(function () {}); let prop; for (prop in instance) { // https://bugs.webkit.org/show_bug.cgi?id=44721 if (className === 'XMLHttpRequest' && prop === 'responseBlob') continue; - (function(prop) { + (function (prop) { if (typeof instance[prop] === 'function') { - _global[className].prototype[prop] = function() { + _global[className].prototype[prop] = function () { return this[originalInstanceKey][prop].apply(this[originalInstanceKey], arguments); }; } else { ObjectDefineProperty(_global[className].prototype, prop, { - set: function(fn) { + set: function (fn) { if (typeof fn === 'function') { this[originalInstanceKey][prop] = wrapWithCurrentZone(fn, className + '.' + prop); // keep callback in wrapped function so we can @@ -339,12 +352,12 @@ export function patchClass(className: string) { this[originalInstanceKey][prop] = fn; } }, - get: function() { + get: function () { return this[originalInstanceKey][prop]; - } + }, }); } - }(prop)); + })(prop); } for (prop in OriginalClass) { @@ -362,10 +375,10 @@ export function copySymbolProperties(src: any, dest: any) { symbols.forEach((symbol: any) => { const desc = Object.getOwnPropertyDescriptor(src, symbol); Object.defineProperty(dest, symbol, { - get: function() { + get: function () { return src[symbol]; }, - set: function(value: any) { + set: function (value: any) { if (desc && (!desc.writable || typeof desc.set !== 'function')) { // if src[symbol] is not writable or not have a setter, just return return; @@ -373,7 +386,7 @@ export function copySymbolProperties(src: any, dest: any) { src[symbol] = value; }, enumerable: desc ? desc.enumerable : true, - configurable: desc ? desc.configurable : true + configurable: desc ? desc.configurable : true, }); }); } @@ -385,9 +398,14 @@ export function setShouldCopySymbolProperties(flag: boolean) { } export function patchMethod( - target: any, name: string, - patchFn: (delegate: Function, delegateName: string, name: string) => (self: any, args: any[]) => - any): Function|null { + target: any, + name: string, + patchFn: ( + delegate: Function, + delegateName: string, + name: string, + ) => (self: any, args: any[]) => any, +): Function | null { let proto = target; while (proto && !proto.hasOwnProperty(name)) { proto = ObjectGetPrototypeOf(proto); @@ -398,7 +416,7 @@ export function patchMethod( } const delegateName = zoneSymbol(name); - let delegate: Function|null = null; + let delegate: Function | null = null; if (proto && (!(delegate = proto[delegateName]) || !proto.hasOwnProperty(delegateName))) { delegate = proto[delegateName] = proto[name]; // check whether proto[name] is writable @@ -406,7 +424,7 @@ export function patchMethod( const desc = proto && ObjectGetOwnPropertyDescriptor(proto, name); if (isPropertyWritable(desc)) { const patchDelegate = patchFn(delegate!, delegateName, name); - proto[name] = function() { + proto[name] = function () { return patchDelegate(this, arguments as any); }; attachOriginToPatched(proto[name], delegate); @@ -427,27 +445,35 @@ export interface MacroTaskMeta extends TaskData { // TODO: @JiaLiPassion, support cancel task later if necessary export function patchMacroTask( - obj: any, funcName: string, metaCreator: (self: any, args: any[]) => MacroTaskMeta) { - let setNative: Function|null = null; + obj: any, + funcName: string, + metaCreator: (self: any, args: any[]) => MacroTaskMeta, +) { + let setNative: Function | null = null; function scheduleTask(task: Task) { const data = task.data; - data.args[data.cbIdx] = function() { + data.args[data.cbIdx] = function () { task.invoke.apply(this, arguments); }; setNative!.apply(data.target, data.args); return task; } - setNative = patchMethod(obj, funcName, (delegate: Function) => function(self: any, args: any[]) { - const meta = metaCreator(self, args); - if (meta.cbIdx >= 0 && typeof args[meta.cbIdx] === 'function') { - return scheduleMacroTaskWithCurrentZone(meta.name, args[meta.cbIdx], meta, scheduleTask); - } else { - // cause an error by calling it directly. - return delegate.apply(self, args); - } - }); + setNative = patchMethod( + obj, + funcName, + (delegate: Function) => + function (self: any, args: any[]) { + const meta = metaCreator(self, args); + if (meta.cbIdx >= 0 && typeof args[meta.cbIdx] === 'function') { + return scheduleMacroTaskWithCurrentZone(meta.name, args[meta.cbIdx], meta, scheduleTask); + } else { + // cause an error by calling it directly. + return delegate.apply(self, args); + } + }, + ); } export interface MicroTaskMeta extends TaskData { @@ -458,27 +484,35 @@ export interface MicroTaskMeta extends TaskData { } export function patchMicroTask( - obj: any, funcName: string, metaCreator: (self: any, args: any[]) => MicroTaskMeta) { - let setNative: Function|null = null; + obj: any, + funcName: string, + metaCreator: (self: any, args: any[]) => MicroTaskMeta, +) { + let setNative: Function | null = null; function scheduleTask(task: Task) { const data = task.data; - data.args[data.cbIdx] = function() { + data.args[data.cbIdx] = function () { task.invoke.apply(this, arguments); }; setNative!.apply(data.target, data.args); return task; } - setNative = patchMethod(obj, funcName, (delegate: Function) => function(self: any, args: any[]) { - const meta = metaCreator(self, args); - if (meta.cbIdx >= 0 && typeof args[meta.cbIdx] === 'function') { - return Zone.current.scheduleMicroTask(meta.name, args[meta.cbIdx], meta, scheduleTask); - } else { - // cause an error by calling it directly. - return delegate.apply(self, args); - } - }); + setNative = patchMethod( + obj, + funcName, + (delegate: Function) => + function (self: any, args: any[]) { + const meta = metaCreator(self, args); + if (meta.cbIdx >= 0 && typeof args[meta.cbIdx] === 'function') { + return Zone.current.scheduleMicroTask(meta.name, args[meta.cbIdx], meta, scheduleTask); + } else { + // cause an error by calling it directly. + return delegate.apply(self, args); + } + }, + ); } export function attachOriginToPatched(patched: Function, original: any) { @@ -494,8 +528,7 @@ export function isIE() { if (ua.indexOf('MSIE ') !== -1 || ua.indexOf('Trident/') !== -1) { return true; } - } catch (error) { - } + } catch (error) {} return false; } @@ -511,7 +544,6 @@ export function isIEOrEdge() { if (ua.indexOf('MSIE ') !== -1 || ua.indexOf('Trident/') !== -1 || ua.indexOf('Edge/') !== -1) { ieOrEdge = true; } - } catch (error) { - } + } catch (error) {} return ieOrEdge; } diff --git a/packages/zone.js/lib/extra/bluebird.ts b/packages/zone.js/lib/extra/bluebird.ts index 051cbf99cfaf1..a01555934265d 100644 --- a/packages/zone.js/lib/extra/bluebird.ts +++ b/packages/zone.js/lib/extra/bluebird.ts @@ -19,34 +19,37 @@ export function patchBluebird(Zone: ZoneType): void { (Zone as any)[Zone.__symbol__(BLUEBIRD)] = function patchBluebird(Bluebird: any) { // patch method of Bluebird.prototype which not using `then` internally const bluebirdApis: string[] = ['then', 'spread', 'finally']; - bluebirdApis.forEach(bapi => { + bluebirdApis.forEach((bapi) => { api.patchMethod( - Bluebird.prototype, bapi, (delegate: Function) => (self: any, args: any[]) => { - const zone = Zone.current; - for (let i = 0; i < args.length; i++) { - const func = args[i]; - if (typeof func === 'function') { - args[i] = function() { - const argSelf: any = this; - const argArgs: any = arguments; - return new Bluebird((res: any, rej: any) => { - zone.scheduleMicroTask('Promise.then', () => { - try { - res(func.apply(argSelf, argArgs)); - } catch (error) { - rej(error); - } - }); + Bluebird.prototype, + bapi, + (delegate: Function) => (self: any, args: any[]) => { + const zone = Zone.current; + for (let i = 0; i < args.length; i++) { + const func = args[i]; + if (typeof func === 'function') { + args[i] = function () { + const argSelf: any = this; + const argArgs: any = arguments; + return new Bluebird((res: any, rej: any) => { + zone.scheduleMicroTask('Promise.then', () => { + try { + res(func.apply(argSelf, argArgs)); + } catch (error) { + rej(error); + } }); - }; - } + }); + }; } - return delegate.apply(self, args); - }); + } + return delegate.apply(self, args); + }, + ); }); if (typeof window !== 'undefined') { - window.addEventListener('unhandledrejection', function(event: any) { + window.addEventListener('unhandledrejection', function (event: any) { const error = event.detail && event.detail.reason; if (error && error.isHandledByZone) { event.preventDefault(); @@ -64,14 +67,14 @@ export function patchBluebird(Zone: ZoneType): void { // will not be triggered. process.removeAllListeners('unhandledRejection'); process.nextTick(() => { - listeners.forEach(listener => process.on('unhandledRejection', listener)); + listeners.forEach((listener) => process.on('unhandledRejection', listener)); }); } } }); } - Bluebird.onPossiblyUnhandledRejection(function(e: any, promise: any) { + Bluebird.onPossiblyUnhandledRejection(function (e: any, promise: any) { try { Zone.current.runGuarded(() => { e.isHandledByZone = true; @@ -87,4 +90,4 @@ export function patchBluebird(Zone: ZoneType): void { global.Promise = Bluebird; }; }); -} \ No newline at end of file +} diff --git a/packages/zone.js/lib/extra/cordova.ts b/packages/zone.js/lib/extra/cordova.ts index 2e118de798ec5..79526006aeb83 100644 --- a/packages/zone.js/lib/extra/cordova.ts +++ b/packages/zone.js/lib/extra/cordova.ts @@ -14,8 +14,11 @@ export function patchCordova(Zone: ZoneType): void { const SUCCESS_SOURCE = 'cordova.exec.success'; const ERROR_SOURCE = 'cordova.exec.error'; const FUNCTION = 'function'; - const nativeExec: Function|null = - api.patchMethod(global.cordova, 'exec', () => function(self: any, args: any[]) { + const nativeExec: Function | null = api.patchMethod( + global.cordova, + 'exec', + () => + function (self: any, args: any[]) { if (args.length > 0 && typeof args[0] === FUNCTION) { args[0] = Zone.current.wrap(args[0], SUCCESS_SOURCE); } @@ -23,7 +26,8 @@ export function patchCordova(Zone: ZoneType): void { args[1] = Zone.current.wrap(args[1], ERROR_SOURCE); } return nativeExec!.apply(self, args); - }); + }, + ); } }); @@ -31,13 +35,13 @@ export function patchCordova(Zone: ZoneType): void { if (global.cordova && typeof global['FileReader'] !== 'undefined') { document.addEventListener('deviceReady', () => { const FileReader = global['FileReader']; - ['abort', 'error', 'load', 'loadstart', 'loadend', 'progress'].forEach(prop => { + ['abort', 'error', 'load', 'loadstart', 'loadend', 'progress'].forEach((prop) => { const eventNameSymbol = Zone.__symbol__('ON_PROPERTY' + prop); Object.defineProperty(FileReader.prototype, eventNameSymbol, { configurable: true, - get: function() { + get: function () { return this._realReader && this._realReader[eventNameSymbol]; - } + }, }); }); }); diff --git a/packages/zone.js/lib/extra/electron.ts b/packages/zone.js/lib/extra/electron.ts index ca49a70498957..da682fed7348a 100644 --- a/packages/zone.js/lib/extra/electron.ts +++ b/packages/zone.js/lib/extra/electron.ts @@ -10,7 +10,7 @@ import {ZoneType} from '../zone-impl'; export function patchElectron(Zone: ZoneType): void { Zone.__load_patch('electron', (global: any, Zone: ZoneType, api: _ZonePrivate) => { - function patchArguments(target: any, name: string, source: string): Function|null { + function patchArguments(target: any, name: string, source: string): Function | null { return api.patchMethod(target, name, (delegate: Function) => (self: any, args: any[]) => { return delegate && delegate.apply(self, api.bindArguments(args, source)); }); @@ -22,9 +22,8 @@ export function patchElectron(Zone: ZoneType): void { // since from electron 14+, the CallbacksRegistry is moved to @electron/remote // package and not exported to outside, so this is a hack to patch CallbacksRegistry. CallbacksRegistry = - require('@electron/remote/dist/src/renderer/callbacks-registry').CallbacksRegistry; - } catch (err) { - } + require('@electron/remote/dist/src/renderer/callbacks-registry').CallbacksRegistry; + } catch (err) {} } // patch api in renderer process directly // desktopCapturer diff --git a/packages/zone.js/lib/extra/jsonp.ts b/packages/zone.js/lib/extra/jsonp.ts index 7862ac71ad79d..b00b8f77d61cd 100644 --- a/packages/zone.js/lib/extra/jsonp.ts +++ b/packages/zone.js/lib/extra/jsonp.ts @@ -10,7 +10,7 @@ import {ZoneType} from '../zone-impl'; export function patchJsonp(Zone: ZoneType): void { Zone.__load_patch('jsonp', (global: any, Zone: ZoneType, api: _ZonePrivate) => { - const noop = function() {}; + const noop = function () {}; // because jsonp is not a standard api, there are a lot of // implementations, so zone.js just provide a helper util to // patch the jsonp send and onSuccess/onError callback @@ -23,9 +23,9 @@ export function patchJsonp(Zone: ZoneType): void { if (!options || !options.jsonp || !options.sendFuncName) { return; } - const noop = function() {}; + const noop = function () {}; - [options.successFuncName, options.failedFuncName].forEach(methodName => { + [options.successFuncName, options.failedFuncName].forEach((methodName) => { if (!methodName) { return; } @@ -45,8 +45,8 @@ export function patchJsonp(Zone: ZoneType): void { Object.defineProperty(global, methodName, { configurable: true, enumerable: true, - get: function() { - return function(this: unknown) { + get: function () { + return function (this: unknown) { const task = global[api.symbol('jsonpTask')]; const target = this ? this : global; const delegate = global[api.symbol(`jsonp${methodName}callback`)]; @@ -65,20 +65,28 @@ export function patchJsonp(Zone: ZoneType): void { return null; }; }, - set: function(callback: Function) { + set: function (callback: Function) { this[api.symbol(`jsonp${methodName}callback`)] = callback; - } + }, }); } }); api.patchMethod( - options.jsonp, options.sendFuncName, (delegate: Function) => (self: any, args: any[]) => { - global[api.symbol('jsonpTask')] = - Zone.current.scheduleMacroTask('jsonp', noop, {}, (task: Task) => { - return delegate.apply(self, args); - }, noop); - }); + options.jsonp, + options.sendFuncName, + (delegate: Function) => (self: any, args: any[]) => { + global[api.symbol('jsonpTask')] = Zone.current.scheduleMacroTask( + 'jsonp', + noop, + {}, + (task: Task) => { + return delegate.apply(self, args); + }, + noop, + ); + }, + ); }; }); } diff --git a/packages/zone.js/lib/extra/socket-io.ts b/packages/zone.js/lib/extra/socket-io.ts index 163c20c9558a7..6d4b8091e4248 100644 --- a/packages/zone.js/lib/extra/socket-io.ts +++ b/packages/zone.js/lib/extra/socket-io.ts @@ -18,12 +18,14 @@ export function patchSocketIo(Zone: ZoneType): void { rt: true, diff: (task: any, delegate: any) => { return task.callback === delegate; - } + }, }); // also patch io.Socket.prototype.on/off/removeListener/removeAllListeners io.Socket.prototype.on = io.Socket.prototype.addEventListener; - io.Socket.prototype.off = io.Socket.prototype.removeListener = - io.Socket.prototype.removeAllListeners = io.Socket.prototype.removeEventListener; + io.Socket.prototype.off = + io.Socket.prototype.removeListener = + io.Socket.prototype.removeAllListeners = + io.Socket.prototype.removeEventListener; }; }); } diff --git a/packages/zone.js/lib/jasmine/jasmine.ts b/packages/zone.js/lib/jasmine/jasmine.ts index ac1d5972ff76b..1282170c244d0 100644 --- a/packages/zone.js/lib/jasmine/jasmine.ts +++ b/packages/zone.js/lib/jasmine/jasmine.ts @@ -10,19 +10,18 @@ import {ZoneType} from '../zone-impl'; -'use strict'; +('use strict'); declare let jest: any; export function patchJasmine(Zone: ZoneType): void { Zone.__load_patch('jasmine', (global: any, Zone: ZoneType, api: _ZonePrivate) => { - const __extends = function(d: any, b: any) { - for (const p in b) - if (b.hasOwnProperty(p)) d[p] = b[p]; + const __extends = function (d: any, b: any) { + for (const p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __(this: Object) { this.constructor = d; } d.prototype = - b === null ? Object.create(b) : ((__.prototype = b.prototype), new (__ as any)()); + b === null ? Object.create(b) : ((__.prototype = b.prototype), new (__ as any)()); }; // Patch jasmine's describe/it/beforeEach/afterEach functions so test code always runs // in a testZone (ProxyZone). (See: angular/zone.js#91 & angular/angular#10503) @@ -51,9 +50,10 @@ export function patchJasmine(Zone: ZoneType): void { // the original variable name fakeAsyncPatchLock is not accurate, so the name will be // fakeAsyncAutoFakeAsyncWhenClockPatched and if this enablePatchingJasmineClock is false, we // also automatically disable the auto jump into fakeAsync feature - const enableAutoFakeAsyncWhenClockPatched = !disablePatchingJasmineClock && - ((global[symbol('fakeAsyncPatchLock')] === true) || - (global[symbol('fakeAsyncAutoFakeAsyncWhenClockPatched')] === true)); + const enableAutoFakeAsyncWhenClockPatched = + !disablePatchingJasmineClock && + (global[symbol('fakeAsyncPatchLock')] === true || + global[symbol('fakeAsyncAutoFakeAsyncWhenClockPatched')] === true); const ignoreUnhandledRejection = global[symbol('ignoreUnhandledRejection')] === true; @@ -61,12 +61,12 @@ export function patchJasmine(Zone: ZoneType): void { const globalErrors = (jasmine as any).GlobalErrors; if (globalErrors && !(jasmine as any)[symbol('GlobalErrors')]) { (jasmine as any)[symbol('GlobalErrors')] = globalErrors; - (jasmine as any).GlobalErrors = function() { + (jasmine as any).GlobalErrors = function () { const instance = new globalErrors(); const originalInstall = instance.install; if (originalInstall && !instance[symbol('install')]) { instance[symbol('install')] = originalInstall; - instance.install = function() { + instance.install = function () { const isNode = typeof process !== 'undefined' && !!process.on; // Note: Jasmine checks internally if `process` and `process.on` is defined. // Otherwise, it installs the browser rejection handler through the @@ -74,13 +74,15 @@ export function patchJasmine(Zone: ZoneType): void { // `process` is not defined, and this will lead to a runtime exception since Webpack 5 // removed automatic Node.js polyfills. Note, that events are named differently, it's // `unhandledRejection` in Node.js and `unhandledrejection` in the browser. - const originalHandlers: any[] = isNode ? process.listeners('unhandledRejection') : - global.eventListeners('unhandledrejection'); + const originalHandlers: any[] = isNode + ? process.listeners('unhandledRejection') + : global.eventListeners('unhandledrejection'); const result = originalInstall.apply(this, arguments); - isNode ? process.removeAllListeners('unhandledRejection') : - global.removeAllListeners('unhandledrejection'); + isNode + ? process.removeAllListeners('unhandledRejection') + : global.removeAllListeners('unhandledrejection'); if (originalHandlers) { - originalHandlers.forEach(handler => { + originalHandlers.forEach((handler) => { if (isNode) { process.on('unhandledRejection', handler); } else { @@ -98,26 +100,32 @@ export function patchJasmine(Zone: ZoneType): void { // Monkey patch all of the jasmine DSL so that each function runs in appropriate zone. const jasmineEnv: any = jasmine.getEnv(); - ['describe', 'xdescribe', 'fdescribe'].forEach(methodName => { + ['describe', 'xdescribe', 'fdescribe'].forEach((methodName) => { let originalJasmineFn: Function = jasmineEnv[methodName]; - jasmineEnv[methodName] = function(description: string, specDefinitions: Function) { + jasmineEnv[methodName] = function (description: string, specDefinitions: Function) { return originalJasmineFn.call( - this, description, wrapDescribeInZone(description, specDefinitions)); + this, + description, + wrapDescribeInZone(description, specDefinitions), + ); }; }); - ['it', 'xit', 'fit'].forEach(methodName => { + ['it', 'xit', 'fit'].forEach((methodName) => { let originalJasmineFn: Function = jasmineEnv[methodName]; jasmineEnv[symbol(methodName)] = originalJasmineFn; - jasmineEnv[methodName] = function( - description: string, specDefinitions: Function, timeout: number) { + jasmineEnv[methodName] = function ( + description: string, + specDefinitions: Function, + timeout: number, + ) { arguments[1] = wrapTestInZone(specDefinitions); return originalJasmineFn.apply(this, arguments); }; }); - ['beforeEach', 'afterEach', 'beforeAll', 'afterAll'].forEach(methodName => { + ['beforeEach', 'afterEach', 'beforeAll', 'afterAll'].forEach((methodName) => { let originalJasmineFn: Function = jasmineEnv[methodName]; jasmineEnv[symbol(methodName)] = originalJasmineFn; - jasmineEnv[methodName] = function(specDefinitions: Function, timeout: number) { + jasmineEnv[methodName] = function (specDefinitions: Function, timeout: number) { arguments[0] = wrapTestInZone(specDefinitions); return originalJasmineFn.apply(this, arguments); }; @@ -127,12 +135,12 @@ export function patchJasmine(Zone: ZoneType): void { // need to patch jasmine.clock().mockDate and jasmine.clock().tick() so // they can work properly in FakeAsyncTest const originalClockFn: Function = ((jasmine as any)[symbol('clock')] = jasmine['clock']); - (jasmine as any)['clock'] = function() { + (jasmine as any)['clock'] = function () { const clock = originalClockFn.apply(this, arguments); if (!clock[symbol('patched')]) { clock[symbol('patched')] = symbol('patched'); const originalTick = (clock[symbol('tick')] = clock.tick); - clock.tick = function() { + clock.tick = function () { const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); if (fakeAsyncZoneSpec) { return fakeAsyncZoneSpec.tick.apply(fakeAsyncZoneSpec, arguments); @@ -140,22 +148,24 @@ export function patchJasmine(Zone: ZoneType): void { return originalTick.apply(this, arguments); }; const originalMockDate = (clock[symbol('mockDate')] = clock.mockDate); - clock.mockDate = function() { + clock.mockDate = function () { const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); if (fakeAsyncZoneSpec) { const dateTime = arguments.length > 0 ? arguments[0] : new Date(); return fakeAsyncZoneSpec.setFakeBaseSystemTime.apply( - fakeAsyncZoneSpec, - dateTime && typeof dateTime.getTime === 'function' ? [dateTime.getTime()] : - arguments); + fakeAsyncZoneSpec, + dateTime && typeof dateTime.getTime === 'function' + ? [dateTime.getTime()] + : arguments, + ); } return originalMockDate.apply(this, arguments); }; // for auto go into fakeAsync feature, we need the flag to enable it if (enableAutoFakeAsyncWhenClockPatched) { - ['install', 'uninstall'].forEach(methodName => { + ['install', 'uninstall'].forEach((methodName) => { const originalClockFn: Function = (clock[symbol(methodName)] = clock[methodName]); - clock[methodName] = function() { + clock[methodName] = function () { const FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; if (FakeAsyncTestZoneSpec) { (jasmine as any)[symbol('clockInstalled')] = 'install' === methodName; @@ -174,15 +184,18 @@ export function patchJasmine(Zone: ZoneType): void { if (!(jasmine as any)[Zone.__symbol__('createSpyObj')]) { const originalCreateSpyObj = jasmine.createSpyObj; (jasmine as any)[Zone.__symbol__('createSpyObj')] = originalCreateSpyObj; - jasmine.createSpyObj = function() { + jasmine.createSpyObj = function () { const args: any = Array.prototype.slice.call(arguments); const propertyNames = args.length >= 3 ? args[2] : null; let spyObj: any; if (propertyNames) { const defineProperty = Object.defineProperty; - Object.defineProperty = function(obj: T, p: PropertyKey, attributes: any) { - return defineProperty.call( - this, obj, p, {...attributes, configurable: true, enumerable: true}) as T; + Object.defineProperty = function (obj: T, p: PropertyKey, attributes: any) { + return defineProperty.call(this, obj, p, { + ...attributes, + configurable: true, + enumerable: true, + }) as T; }; try { spyObj = originalCreateSpyObj.apply(this, args); @@ -201,16 +214,20 @@ export function patchJasmine(Zone: ZoneType): void { * synchronous-only zone. */ function wrapDescribeInZone(description: string, describeBody: Function): Function { - return function(this: unknown) { + return function (this: unknown) { // Create a synchronous-only zone in which to run `describe` blocks in order to raise an // error if any asynchronous operations are attempted inside of a `describe`. const syncZone = ambientZone.fork(new SyncTestZoneSpec(`jasmine.describe#${description}`)); - return syncZone.run(describeBody, this, (arguments as any) as any[]); + return syncZone.run(describeBody, this, arguments as any as any[]); }; } function runInTestZone( - testBody: Function, applyThis: any, queueRunner: QueueRunner, done?: Function) { + testBody: Function, + applyThis: any, + queueRunner: QueueRunner, + done?: Function, + ) { const isClockInstalled = !!(jasmine as any)[symbol('clockInstalled')]; const testProxyZoneSpec = queueRunner.testProxyZoneSpec!; const testProxyZone = queueRunner.testProxyZone!; @@ -239,16 +256,20 @@ export function patchJasmine(Zone: ZoneType): void { // 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(this: QueueRunnerUserContext, done: Function) { - return runInTestZone(testBody, this, this.queueRunner!, done); - } : function(this: QueueRunnerUserContext) { - return runInTestZone(testBody, this, this.queueRunner!); - })); + testBody && + (testBody.length + ? function (this: QueueRunnerUserContext, done: Function) { + return runInTestZone(testBody, this, this.queueRunner!, done); + } + : function (this: QueueRunnerUserContext) { + return runInTestZone(testBody, this, this.queueRunner!); + }) + ); } interface QueueRunner { execute(): void; - testProxyZoneSpec: ZoneSpec|null; - testProxyZone: Zone|null; + testProxyZoneSpec: ZoneSpec | null; + testProxyZone: Zone | null; } interface QueueRunnerAttrs { queueableFns: {fn: Function}[]; @@ -264,11 +285,11 @@ export function patchJasmine(Zone: ZoneType): void { const QueueRunner = (jasmine as any).QueueRunner as { new (attrs: QueueRunnerAttrs): QueueRunner; }; - (jasmine as any).QueueRunner = (function(_super) { + (jasmine as any).QueueRunner = (function (_super) { __extends(ZoneQueueRunner, _super); function ZoneQueueRunner(this: QueueRunner, attrs: QueueRunnerAttrs) { if (attrs.onComplete) { - attrs.onComplete = (fn => () => { + attrs.onComplete = ((fn) => () => { // All functions are done, clear the test zone. this.testProxyZone = null; this.testProxyZoneSpec = null; @@ -282,7 +303,7 @@ export function patchJasmine(Zone: ZoneType): void { // should run setTimeout inside jasmine outside of zone attrs.timeout = { setTimeout: nativeSetTimeout ? nativeSetTimeout : global.setTimeout, - clearTimeout: nativeClearTimeout ? nativeClearTimeout : global.clearTimeout + clearTimeout: nativeClearTimeout ? nativeClearTimeout : global.clearTimeout, }; } @@ -302,10 +323,12 @@ export function patchJasmine(Zone: ZoneType): void { // patch attrs.onException const onException = attrs.onException; - attrs.onException = function(this: undefined|QueueRunner, error: any) { - if (error && - error.message === - 'Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.') { + attrs.onException = function (this: undefined | QueueRunner, error: any) { + if ( + error && + error.message === + 'Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.' + ) { // jasmine timeout, we can make the error message more // reasonable to tell what tasks are pending const proxyZoneSpec: any = this && this.testProxyZoneSpec; @@ -314,8 +337,7 @@ export function patchJasmine(Zone: ZoneType): void { try { // try catch here in case error.message is not writable error.message += pendingTasksInfo; - } catch (err) { - } + } catch (err) {} } } if (onException) { @@ -325,8 +347,8 @@ export function patchJasmine(Zone: ZoneType): void { _super.call(this, attrs); } - ZoneQueueRunner.prototype.execute = function() { - let zone: Zone|null = Zone.current; + ZoneQueueRunner.prototype.execute = function () { + let zone: Zone | null = Zone.current; let isChildOfAmbientZone = false; while (zone) { if (zone === ambientZone) { @@ -356,8 +378,9 @@ export function patchJasmine(Zone: ZoneType): void { // addEventListener callback would think that it is the top most task and would // drain the microtask queue on element.click() which would be incorrect. // For this reason we always force a task when running jasmine tests. - Zone.current.scheduleMicroTask( - 'jasmine.execute().forceTask', () => QueueRunner.prototype.execute.call(this)); + Zone.current.scheduleMicroTask('jasmine.execute().forceTask', () => + QueueRunner.prototype.execute.call(this), + ); } else { _super.prototype.execute.call(this); } diff --git a/packages/zone.js/lib/jest/jest.ts b/packages/zone.js/lib/jest/jest.ts index 6d1edd3366ee1..e3311763d9594 100644 --- a/packages/zone.js/lib/jest/jest.ts +++ b/packages/zone.js/lib/jest/jest.ts @@ -8,7 +8,7 @@ import {ZoneType} from '../zone-impl'; -'use strict'; +('use strict'); declare let jest: any; export function patchJest(Zone: ZoneType): void { @@ -17,7 +17,6 @@ export function patchJest(Zone: ZoneType): void { return; } - // From jest 29 and jest-preset-angular v13, the module transform logic // changed, and now jest-preset-angular use the use the tsconfig target // other than the hardcoded one, https://github.com/thymikee/jest-preset-angular/issues/2010 @@ -42,9 +41,9 @@ export function patchJest(Zone: ZoneType): void { const proxyZone = rootZone.fork(proxyZoneSpec); function wrapDescribeFactoryInZone(originalJestFn: Function) { - return function(this: unknown, ...tableArgs: any[]) { + return function (this: unknown, ...tableArgs: any[]) { const originalDescribeFn = originalJestFn.apply(this, tableArgs); - return function(this: unknown, ...args: any[]) { + return function (this: unknown, ...args: any[]) { args[1] = wrapDescribeInZone(args[1]); return originalDescribeFn.apply(this, args); }; @@ -52,8 +51,8 @@ export function patchJest(Zone: ZoneType): void { } function wrapTestFactoryInZone(originalJestFn: Function) { - return function(this: unknown, ...tableArgs: any[]) { - return function(this: unknown, ...args: any[]) { + return function (this: unknown, ...tableArgs: any[]) { + return function (this: unknown, ...args: any[]) { args[1] = wrapTestInZone(args[1]); return originalJestFn.apply(this, tableArgs).apply(this, args); }; @@ -65,7 +64,7 @@ export function patchJest(Zone: ZoneType): void { * synchronous-only zone. */ function wrapDescribeInZone(describeBody: Function): Function { - return function(this: unknown, ...args: any[]) { + return function (this: unknown, ...args: any[]) { return syncZone.run(describeBody, this, args); }; } @@ -79,9 +78,12 @@ export function patchJest(Zone: ZoneType): void { if (typeof testBody !== 'function') { return testBody; } - const wrappedFunc = function() { - if ((Zone as any)[api.symbol('useFakeTimersCalled')] === true && testBody && - !(testBody as any).isFakeAsync) { + const wrappedFunc = function () { + if ( + (Zone as any)[api.symbol('useFakeTimersCalled')] === true && + testBody && + !(testBody as any).isFakeAsync + ) { // jest.useFakeTimers is called, run into fakeAsyncTest automatically. const fakeAsyncModule = (Zone as any)[Zone.__symbol__('fakeAsyncTest')]; if (fakeAsyncModule && typeof fakeAsyncModule.fakeAsync === 'function') { @@ -93,19 +95,22 @@ export function patchJest(Zone: ZoneType): void { }; // Update the length of wrappedFunc to be the same as the length of the testBody // So jest core can handle whether the test function has `done()` or not correctly - Object.defineProperty( - wrappedFunc, 'length', {configurable: true, writable: true, enumerable: false}); + Object.defineProperty(wrappedFunc, 'length', { + configurable: true, + writable: true, + enumerable: false, + }); wrappedFunc.length = testBody.length; return wrappedFunc; } - ['describe', 'xdescribe', 'fdescribe'].forEach(methodName => { + ['describe', 'xdescribe', 'fdescribe'].forEach((methodName) => { let originalJestFn: Function = context[methodName]; if (context[Zone.__symbol__(methodName)]) { return; } context[Zone.__symbol__(methodName)] = originalJestFn; - context[methodName] = function(this: unknown, ...args: any[]) { + context[methodName] = function (this: unknown, ...args: any[]) { args[1] = wrapDescribeInZone(args[1]); return originalJestFn.apply(this, args); }; @@ -114,13 +119,13 @@ export function patchJest(Zone: ZoneType): void { context.describe.only = context.fdescribe; context.describe.skip = context.xdescribe; - ['it', 'xit', 'fit', 'test', 'xtest'].forEach(methodName => { + ['it', 'xit', 'fit', 'test', 'xtest'].forEach((methodName) => { let originalJestFn: Function = context[methodName]; if (context[Zone.__symbol__(methodName)]) { return; } context[Zone.__symbol__(methodName)] = originalJestFn; - context[methodName] = function(this: unknown, ...args: any[]) { + context[methodName] = function (this: unknown, ...args: any[]) { args[1] = wrapTestInZone(args[1], true); return originalJestFn.apply(this, args); }; @@ -133,13 +138,13 @@ export function patchJest(Zone: ZoneType): void { context.test.only = context.fit; context.test.skip = context.xit; - ['beforeEach', 'afterEach', 'beforeAll', 'afterAll'].forEach(methodName => { + ['beforeEach', 'afterEach', 'beforeAll', 'afterAll'].forEach((methodName) => { let originalJestFn: Function = context[methodName]; if (context[Zone.__symbol__(methodName)]) { return; } context[Zone.__symbol__(methodName)] = originalJestFn; - context[methodName] = function(this: unknown, ...args: any[]) { + context[methodName] = function (this: unknown, ...args: any[]) { args[0] = wrapTestInZone(args[0]); return originalJestFn.apply(this, args); }; @@ -165,145 +170,145 @@ export function patchJest(Zone: ZoneType): void { Timer[api.symbol('fakeTimers')] = true; // patch jest fakeTimer internal method to make sure no console.warn print out - api.patchMethod(Timer, '_checkFakeTimers', delegate => { - return function(self: any, args: any[]) { + api.patchMethod(Timer, '_checkFakeTimers', (delegate) => { + return function (self: any, args: any[]) { if (isPatchingFakeTimer()) { return true; } else { return delegate.apply(self, args); } - } + }; }); // patch useFakeTimers(), set useFakeTimersCalled flag, and make test auto run into fakeAsync - api.patchMethod(Timer, 'useFakeTimers', delegate => { - return function(self: any, args: any[]) { + api.patchMethod(Timer, 'useFakeTimers', (delegate) => { + return function (self: any, args: any[]) { (Zone as any)[api.symbol('useFakeTimersCalled')] = true; if (isModern || isInTestFunc()) { return delegate.apply(self, args); } return self; - } + }; }); // patch useRealTimers(), unset useFakeTimers flag - api.patchMethod(Timer, 'useRealTimers', delegate => { - return function(self: any, args: any[]) { + api.patchMethod(Timer, 'useRealTimers', (delegate) => { + return function (self: any, args: any[]) { (Zone as any)[api.symbol('useFakeTimersCalled')] = false; if (isModern || isInTestFunc()) { return delegate.apply(self, args); } return self; - } + }; }); // patch setSystemTime(), call setCurrentRealTime() in the fakeAsyncTest - api.patchMethod(Timer, 'setSystemTime', delegate => { - return function(self: any, args: any[]) { + api.patchMethod(Timer, 'setSystemTime', (delegate) => { + return function (self: any, args: any[]) { const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); if (fakeAsyncZoneSpec && isPatchingFakeTimer()) { fakeAsyncZoneSpec.setFakeBaseSystemTime(args[0]); } else { return delegate.apply(self, args); } - } + }; }); // patch getSystemTime(), call getCurrentRealTime() in the fakeAsyncTest - api.patchMethod(Timer, 'getRealSystemTime', delegate => { - return function(self: any, args: any[]) { + api.patchMethod(Timer, 'getRealSystemTime', (delegate) => { + return function (self: any, args: any[]) { const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); if (fakeAsyncZoneSpec && isPatchingFakeTimer()) { return fakeAsyncZoneSpec.getRealSystemTime(); } else { return delegate.apply(self, args); } - } + }; }); // patch runAllTicks(), run all microTasks inside fakeAsync - api.patchMethod(Timer, 'runAllTicks', delegate => { - return function(self: any, args: any[]) { + api.patchMethod(Timer, 'runAllTicks', (delegate) => { + return function (self: any, args: any[]) { const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); if (fakeAsyncZoneSpec) { fakeAsyncZoneSpec.flushMicrotasks(); } else { return delegate.apply(self, args); } - } + }; }); // patch runAllTimers(), run all macroTasks inside fakeAsync - api.patchMethod(Timer, 'runAllTimers', delegate => { - return function(self: any, args: any[]) { + api.patchMethod(Timer, 'runAllTimers', (delegate) => { + return function (self: any, args: any[]) { const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); if (fakeAsyncZoneSpec) { fakeAsyncZoneSpec.flush(100, true); } else { return delegate.apply(self, args); } - } + }; }); // patch advanceTimersByTime(), call tick() in the fakeAsyncTest - api.patchMethod(Timer, 'advanceTimersByTime', delegate => { - return function(self: any, args: any[]) { + api.patchMethod(Timer, 'advanceTimersByTime', (delegate) => { + return function (self: any, args: any[]) { const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); if (fakeAsyncZoneSpec) { fakeAsyncZoneSpec.tick(args[0]); } else { return delegate.apply(self, args); } - } + }; }); // patch runOnlyPendingTimers(), call flushOnlyPendingTimers() in the fakeAsyncTest - api.patchMethod(Timer, 'runOnlyPendingTimers', delegate => { - return function(self: any, args: any[]) { + api.patchMethod(Timer, 'runOnlyPendingTimers', (delegate) => { + return function (self: any, args: any[]) { const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); if (fakeAsyncZoneSpec) { fakeAsyncZoneSpec.flushOnlyPendingTimers(); } else { return delegate.apply(self, args); } - } + }; }); // patch advanceTimersToNextTimer(), call tickToNext() in the fakeAsyncTest - api.patchMethod(Timer, 'advanceTimersToNextTimer', delegate => { - return function(self: any, args: any[]) { + api.patchMethod(Timer, 'advanceTimersToNextTimer', (delegate) => { + return function (self: any, args: any[]) { const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); if (fakeAsyncZoneSpec) { fakeAsyncZoneSpec.tickToNext(args[0]); } else { return delegate.apply(self, args); } - } + }; }); // patch clearAllTimers(), call removeAllTimers() in the fakeAsyncTest - api.patchMethod(Timer, 'clearAllTimers', delegate => { - return function(self: any, args: any[]) { + api.patchMethod(Timer, 'clearAllTimers', (delegate) => { + return function (self: any, args: any[]) { const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); if (fakeAsyncZoneSpec) { fakeAsyncZoneSpec.removeAllTimers(); } else { return delegate.apply(self, args); } - } + }; }); // patch getTimerCount(), call getTimerCount() in the fakeAsyncTest - api.patchMethod(Timer, 'getTimerCount', delegate => { - return function(self: any, args: any[]) { + api.patchMethod(Timer, 'getTimerCount', (delegate) => { + return function (self: any, args: any[]) { const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); if (fakeAsyncZoneSpec) { return fakeAsyncZoneSpec.getTimerCount(); } else { return delegate.apply(self, args); } - } + }; }); - } + }; }); } diff --git a/packages/zone.js/lib/mocha/mocha.ts b/packages/zone.js/lib/mocha/mocha.ts index ffc262c739753..fac81db44c077 100644 --- a/packages/zone.js/lib/mocha/mocha.ts +++ b/packages/zone.js/lib/mocha/mocha.ts @@ -8,7 +8,7 @@ import {ZoneType} from '../zone-impl'; -'use strict'; +('use strict'); export function patchMocha(Zone: ZoneType): void { Zone.__load_patch('mocha', (global: any, Zone: ZoneType) => { @@ -39,7 +39,7 @@ export function patchMocha(Zone: ZoneType): void { const rootZone = Zone.current; const syncZone = rootZone.fork(new SyncTestZoneSpec('Mocha.describe')); - let testZone: Zone|null = null; + let testZone: Zone | null = null; const suiteZone = rootZone.fork(new ProxyZoneSpec()); const mochaOriginal = { @@ -48,7 +48,7 @@ export function patchMocha(Zone: ZoneType): void { before: global.before, beforeEach: global.beforeEach, describe: global.describe, - it: global.it + it: global.it, }; function modifyArguments(args: IArguments, syncTest: Function, asyncTest?: Function): any[] { @@ -60,10 +60,10 @@ export function patchMocha(Zone: ZoneType): void { // Note we have to make a function with correct number of arguments, // otherwise mocha will // think that all functions are sync or async. - args[i] = (arg.length === 0) ? syncTest(arg) : asyncTest!(arg); + args[i] = arg.length === 0 ? syncTest(arg) : asyncTest!(arg); // Mocha uses toString to view the test body in the result list, make sure we return the // correct function body - args[i].toString = function() { + args[i].toString = function () { return arg.toString(); }; } @@ -73,8 +73,8 @@ export function patchMocha(Zone: ZoneType): void { } function wrapDescribeInZone(args: IArguments): any[] { - const syncTest: any = function(fn: Function) { - return function(this: unknown) { + const syncTest: any = function (fn: Function) { + return function (this: unknown) { return syncZone.run(fn, this, arguments as any as any[]); }; }; @@ -83,14 +83,14 @@ export function patchMocha(Zone: ZoneType): void { } function wrapTestInZone(args: IArguments): any[] { - const asyncTest = function(fn: Function) { - return function(this: unknown, done: Function) { + const asyncTest = function (fn: Function) { + return function (this: unknown, done: Function) { return testZone!.run(fn, this, [done]); }; }; - const syncTest: any = function(fn: Function) { - return function(this: unknown) { + const syncTest: any = function (fn: Function) { + return function (this: unknown) { return testZone!.run(fn, this); }; }; @@ -99,14 +99,14 @@ export function patchMocha(Zone: ZoneType): void { } function wrapSuiteInZone(args: IArguments): any[] { - const asyncTest = function(fn: Function) { - return function(this: unknown, done: Function) { + const asyncTest = function (fn: Function) { + return function (this: unknown, done: Function) { return suiteZone.run(fn, this, [done]); }; }; - const syncTest: any = function(fn: Function) { - return function(this: unknown) { + const syncTest: any = function (fn: Function) { + return function (this: unknown) { return suiteZone.run(fn, this); }; }; @@ -114,54 +114,63 @@ export function patchMocha(Zone: ZoneType): void { return modifyArguments(args, syncTest, asyncTest); } - global.describe = global.suite = function() { + global.describe = global.suite = function () { return mochaOriginal.describe.apply(this, wrapDescribeInZone(arguments)); }; - global.xdescribe = global.suite.skip = global.describe.skip = function() { - return mochaOriginal.describe.skip.apply(this, wrapDescribeInZone(arguments)); - }; + global.xdescribe = + global.suite.skip = + global.describe.skip = + function () { + return mochaOriginal.describe.skip.apply(this, wrapDescribeInZone(arguments)); + }; - global.describe.only = global.suite.only = function() { + global.describe.only = global.suite.only = function () { return mochaOriginal.describe.only.apply(this, wrapDescribeInZone(arguments)); }; - global.it = global.specify = global.test = function() { - return mochaOriginal.it.apply(this, wrapTestInZone(arguments)); - }; + global.it = + global.specify = + global.test = + function () { + return mochaOriginal.it.apply(this, wrapTestInZone(arguments)); + }; - global.xit = global.xspecify = global.it.skip = function() { - return mochaOriginal.it.skip.apply(this, wrapTestInZone(arguments)); - }; + global.xit = + global.xspecify = + global.it.skip = + function () { + return mochaOriginal.it.skip.apply(this, wrapTestInZone(arguments)); + }; - global.it.only = global.test.only = function() { + global.it.only = global.test.only = function () { return mochaOriginal.it.only.apply(this, wrapTestInZone(arguments)); }; - global.after = global.suiteTeardown = function() { + global.after = global.suiteTeardown = function () { return mochaOriginal.after.apply(this, wrapSuiteInZone(arguments)); }; - global.afterEach = global.teardown = function() { + global.afterEach = global.teardown = function () { return mochaOriginal.afterEach.apply(this, wrapTestInZone(arguments)); }; - global.before = global.suiteSetup = function() { + global.before = global.suiteSetup = function () { return mochaOriginal.before.apply(this, wrapSuiteInZone(arguments)); }; - global.beforeEach = global.setup = function() { + global.beforeEach = global.setup = function () { return mochaOriginal.beforeEach.apply(this, wrapTestInZone(arguments)); }; ((originalRunTest, originalRun) => { - Mocha.Runner.prototype.runTest = function(fn: Function) { + Mocha.Runner.prototype.runTest = function (fn: Function) { Zone.current.scheduleMicroTask('mocha.forceTask', () => { originalRunTest.call(this, fn); }); }; - Mocha.Runner.prototype.run = function(fn: Function) { + Mocha.Runner.prototype.run = function (fn: Function) { this.on('test', (e: any) => { testZone = rootZone.fork(new ProxyZoneSpec()); }); @@ -172,8 +181,7 @@ export function patchMocha(Zone: ZoneType): void { try { // try catch here in case err.message is not writable err.message += proxyZoneSpec.getAndClearPendingTasksInfo(); - } catch (error) { - } + } catch (error) {} } }); diff --git a/packages/zone.js/lib/node/events.ts b/packages/zone.js/lib/node/events.ts index c9415a7c2a06d..b77b06bf13962 100644 --- a/packages/zone.js/lib/node/events.ts +++ b/packages/zone.js/lib/node/events.ts @@ -20,12 +20,12 @@ export function patchEvents(Zone: ZoneType): void { const EE_ON = 'on'; const EE_OFF = 'off'; - const compareTaskCallbackVsDelegate = function(task: any, delegate: any) { + const compareTaskCallbackVsDelegate = function (task: any, delegate: any) { // same callback, same capture, same event name, just return return task.callback === delegate || task.callback.listener === delegate; }; - const eventNameToString = function(eventName: string|Symbol) { + const eventNameToString = function (eventName: string | Symbol) { if (typeof eventName === 'string') { return eventName; } @@ -46,7 +46,7 @@ export function patchEvents(Zone: ZoneType): void { chkDup: false, rt: true, diff: compareTaskCallbackVsDelegate, - eventNameToString: eventNameToString + eventNameToString: eventNameToString, }); if (result && result[0]) { obj[EE_ON] = obj[EE_ADD_LISTENER]; @@ -58,8 +58,7 @@ export function patchEvents(Zone: ZoneType): void { let events; try { events = require('events'); - } catch (err) { - } + } catch (err) {} if (events && events.EventEmitter) { patchEventEmitterMethods(events.EventEmitter.prototype); diff --git a/packages/zone.js/lib/node/fs.ts b/packages/zone.js/lib/node/fs.ts index 255f3000f31f6..cf9b0230bad5a 100644 --- a/packages/zone.js/lib/node/fs.ts +++ b/packages/zone.js/lib/node/fs.ts @@ -14,32 +14,61 @@ export function patchFs(Zone: ZoneType): void { let fs: any; try { fs = require('fs'); - } catch (err) { - } + } catch (err) {} if (!fs) return; // watch, watchFile, unwatchFile has been patched // because EventEmitter has been patched const TO_PATCH_MACROTASK_METHODS = [ - 'access', 'appendFile', 'chmod', 'chown', 'close', 'exists', 'fchmod', - 'fchown', 'fdatasync', 'fstat', 'fsync', 'ftruncate', 'futimes', 'lchmod', - 'lchown', 'link', 'lstat', 'mkdir', 'mkdtemp', 'open', 'read', - 'readdir', 'readFile', 'readlink', 'realpath', 'rename', 'rmdir', 'stat', - 'symlink', 'truncate', 'unlink', 'utimes', 'write', 'writeFile', + 'access', + 'appendFile', + 'chmod', + 'chown', + 'close', + 'exists', + 'fchmod', + 'fchown', + 'fdatasync', + 'fstat', + 'fsync', + 'ftruncate', + 'futimes', + 'lchmod', + 'lchown', + 'link', + 'lstat', + 'mkdir', + 'mkdtemp', + 'open', + 'read', + 'readdir', + 'readFile', + 'readlink', + 'realpath', + 'rename', + 'rmdir', + 'stat', + 'symlink', + 'truncate', + 'unlink', + 'utimes', + 'write', + 'writeFile', ]; - TO_PATCH_MACROTASK_METHODS.filter(name => !!fs[name] && typeof fs[name] === 'function') - .forEach(name => { - patchMacroTask(fs, name, (self: any, args: any[]) => { - return { - name: 'fs.' + name, - args: args, - cbIdx: args.length > 0 ? args.length - 1 : -1, - target: self - }; - }); - }); + TO_PATCH_MACROTASK_METHODS.filter( + (name) => !!fs[name] && typeof fs[name] === 'function', + ).forEach((name) => { + patchMacroTask(fs, name, (self: any, args: any[]) => { + return { + name: 'fs.' + name, + args: args, + cbIdx: args.length > 0 ? args.length - 1 : -1, + target: self, + }; + }); + }); const realpathOriginalDelegate = fs.realpath?.[api.symbol('OriginalDelegate')]; // This is the only specific method that should be additionally patched because the previous @@ -47,11 +76,11 @@ export function patchFs(Zone: ZoneType): void { if (realpathOriginalDelegate?.native) { fs.realpath.native = realpathOriginalDelegate.native; patchMacroTask(fs.realpath, 'native', (self, args) => ({ - args, - target: self, - cbIdx: args.length > 0 ? args.length - 1 : -1, - name: 'fs.realpath.native', - })); + args, + target: self, + cbIdx: args.length > 0 ? args.length - 1 : -1, + name: 'fs.realpath.native', + })); } }); } diff --git a/packages/zone.js/lib/node/main.ts b/packages/zone.js/lib/node/main.ts index 5d286e1446aa8..ebddcf688e23b 100644 --- a/packages/zone.js/lib/node/main.ts +++ b/packages/zone.js/lib/node/main.ts @@ -16,7 +16,7 @@ import {patchNode} from './node'; export function rollupMain(): ZoneType { const Zone = loadZone(); - patchNode(Zone); // Node needs to come first. + patchNode(Zone); // Node needs to come first. patchPromise(Zone); patchToString(Zone); diff --git a/packages/zone.js/lib/node/node.ts b/packages/zone.js/lib/node/node.ts index 4551b719049b5..4342c83c709c9 100644 --- a/packages/zone.js/lib/node/node.ts +++ b/packages/zone.js/lib/node/node.ts @@ -37,7 +37,7 @@ export function patchNode(Zone: ZoneType): void { // 2. if global.setTimeout not equal timers.setTimeout, check // whether global.setTimeout use timers.setTimeout or not const originSetTimeout = timers.setTimeout; - timers.setTimeout = function() { + timers.setTimeout = function () { globalUseTimeoutFromTimer = true; return originSetTimeout.apply(this, arguments); }; @@ -84,58 +84,57 @@ export function patchNode(Zone: ZoneType): void { return { name: 'process.nextTick', args: args, - cbIdx: (args.length > 0 && typeof args[0] === 'function') ? 0 : -1, - target: process + cbIdx: args.length > 0 && typeof args[0] === 'function' ? 0 : -1, + target: process, }; }); }); Zone.__load_patch( - 'handleUnhandledPromiseRejection', (global: any, Zone: ZoneType, api: _ZonePrivate) => { - (Zone as any)[api.symbol('unhandledPromiseRejectionHandler')] = - findProcessPromiseRejectionHandler('unhandledRejection'); + 'handleUnhandledPromiseRejection', + (global: any, Zone: ZoneType, api: _ZonePrivate) => { + (Zone as any)[api.symbol('unhandledPromiseRejectionHandler')] = + findProcessPromiseRejectionHandler('unhandledRejection'); - (Zone as any)[api.symbol('rejectionHandledHandler')] = - findProcessPromiseRejectionHandler('rejectionHandled'); - - // handle unhandled promise rejection - function findProcessPromiseRejectionHandler(evtName: string) { - return function(e: any) { - const eventTasks = findEventTasks(process, evtName); - eventTasks.forEach(eventTask => { - // process has added unhandledrejection event listener - // trigger the event listener - if (evtName === 'unhandledRejection') { - eventTask.invoke(e.rejection, e.promise); - } else if (evtName === 'rejectionHandled') { - eventTask.invoke(e.promise); - } - }); - }; - } - }); + (Zone as any)[api.symbol('rejectionHandledHandler')] = + findProcessPromiseRejectionHandler('rejectionHandled'); + // handle unhandled promise rejection + function findProcessPromiseRejectionHandler(evtName: string) { + return function (e: any) { + const eventTasks = findEventTasks(process, evtName); + eventTasks.forEach((eventTask) => { + // process has added unhandledrejection event listener + // trigger the event listener + if (evtName === 'unhandledRejection') { + eventTask.invoke(e.rejection, e.promise); + } else if (evtName === 'rejectionHandled') { + eventTask.invoke(e.promise); + } + }); + }; + } + }, + ); // Crypto Zone.__load_patch('crypto', () => { let crypto: any; try { crypto = require('crypto'); - } catch (err) { - } + } catch (err) {} // use the generic patchMacroTask to patch crypto if (crypto) { const methodNames = ['randomBytes', 'pbkdf2']; - methodNames.forEach(name => { + methodNames.forEach((name) => { patchMacroTask(crypto, name, (self: any, args: any[]) => { return { name: 'crypto.' + name, args: args, - cbIdx: (args.length > 0 && typeof args[args.length - 1] === 'function') ? - args.length - 1 : - -1, - target: crypto + cbIdx: + args.length > 0 && typeof args[args.length - 1] === 'function' ? args.length - 1 : -1, + target: crypto, }; }); }); @@ -143,12 +142,21 @@ export function patchNode(Zone: ZoneType): void { }); Zone.__load_patch('console', (global: any, Zone: ZoneType) => { - const consoleMethods = - ['dir', 'log', 'info', 'error', 'warn', 'assert', 'debug', 'timeEnd', 'trace']; + const consoleMethods = [ + 'dir', + 'log', + 'info', + 'error', + 'warn', + 'assert', + 'debug', + 'timeEnd', + 'trace', + ]; consoleMethods.forEach((m: string) => { - const originalMethod = (console as any)[Zone.__symbol__(m)] = (console as any)[m]; + const originalMethod = ((console as any)[Zone.__symbol__(m)] = (console as any)[m]); if (originalMethod) { - (console as any)[m] = function() { + (console as any)[m] = function () { const args = ArraySlice.call(arguments); if (Zone.current === Zone.root) { return originalMethod.apply(this, args); diff --git a/packages/zone.js/lib/node/node_util.ts b/packages/zone.js/lib/node/node_util.ts index 37165af88ab6b..cae35d898eef1 100644 --- a/packages/zone.js/lib/node/node_util.ts +++ b/packages/zone.js/lib/node/node_util.ts @@ -6,7 +6,13 @@ * found in the LICENSE file at https://angular.io/license */ -import {bindArguments, patchMacroTask, patchMethod, patchOnProperties, setShouldCopySymbolProperties} from '../common/utils'; +import { + bindArguments, + patchMacroTask, + patchMethod, + patchOnProperties, + setShouldCopySymbolProperties, +} from '../common/utils'; import {ZoneType} from '../zone-impl'; export function patchNodeUtil(Zone: ZoneType): void { diff --git a/packages/zone.js/lib/rxjs/rxjs.ts b/packages/zone.js/lib/rxjs/rxjs.ts index f6531c4ff84db..bc10153527a2b 100644 --- a/packages/zone.js/lib/rxjs/rxjs.ts +++ b/packages/zone.js/lib/rxjs/rxjs.ts @@ -11,8 +11,8 @@ import {Observable, Subscriber, Subscription} from 'rxjs'; import {ZoneType} from '../zone-impl'; type ZoneSubscriberContext = { - _zone: Zone -}&Subscriber; + _zone: Zone; +} & Subscriber; export function patchRxJs(Zone: ZoneType): void { (Zone as any).__load_patch('rxjs', (global: any, Zone: ZoneType, api: _ZonePrivate) => { @@ -23,10 +23,10 @@ export function patchRxJs(Zone: ZoneType): void { const ObjectDefineProperties = Object.defineProperties; - const patchObservable = function() { + const patchObservable = function () { const ObservablePrototype: any = Observable.prototype; const _symbolSubscribe = symbol('_subscribe'); - const _subscribe = ObservablePrototype[_symbolSubscribe] = ObservablePrototype._subscribe; + const _subscribe = (ObservablePrototype[_symbolSubscribe] = ObservablePrototype._subscribe); ObjectDefineProperties(Observable.prototype, { _zone: {value: null, writable: true, configurable: true}, @@ -34,17 +34,17 @@ export function patchRxJs(Zone: ZoneType): void { _zoneSubscribe: {value: null, writable: true, configurable: true}, source: { configurable: true, - get: function(this: Observable) { + get: function (this: Observable) { return (this as any)._zoneSource; }, - set: function(this: Observable, source: any) { + set: function (this: Observable, source: any) { (this as any)._zone = Zone.current; (this as any)._zoneSource = source; - } + }, }, _subscribe: { configurable: true, - get: function(this: Observable) { + get: function (this: Observable) { if ((this as any)._zoneSubscribe) { return (this as any)._zoneSubscribe; } else if (this.constructor === Observable) { @@ -53,17 +53,17 @@ export function patchRxJs(Zone: ZoneType): void { const proto = Object.getPrototypeOf(this); return proto && proto._subscribe; }, - set: function(this: Observable, subscribe: any) { + set: function (this: Observable, subscribe: any) { (this as any)._zone = Zone.current; if (!subscribe) { (this as any)._zoneSubscribe = subscribe; } else { - (this as any)._zoneSubscribe = function(this: ZoneSubscriberContext) { + (this as any)._zoneSubscribe = function (this: ZoneSubscriberContext) { if (this._zone && this._zone !== Zone.current) { const tearDown = this._zone.run(subscribe, this, arguments as any); if (typeof tearDown === 'function') { const zone = this._zone; - return function(this: ZoneSubscriberContext) { + return function (this: ZoneSubscriberContext) { if (zone !== Zone.current) { return zone.run(tearDown, this, arguments as any); } @@ -77,22 +77,22 @@ export function patchRxJs(Zone: ZoneType): void { } }; } - } + }, }, subjectFactory: { - get: function() { + get: function () { return (this as any)._zoneSubjectFactory; }, - set: function(factory: any) { + set: function (factory: any) { const zone = this._zone; - this._zoneSubjectFactory = function() { + this._zoneSubjectFactory = function () { if (zone && zone !== Zone.current) { return zone.run(factory, this, arguments); } return factory.apply(this, arguments); }; - } - } + }, + }, }); }; @@ -101,30 +101,32 @@ export function patchRxJs(Zone: ZoneType): void { if (observable.operator) { observable.operator._zone = Zone.current; api.patchMethod( - observable.operator, 'call', - (operatorDelegate: any) => (operatorSelf: any, operatorArgs: any[]) => { - if (operatorSelf._zone && operatorSelf._zone !== Zone.current) { - return operatorSelf._zone.run(operatorDelegate, operatorSelf, operatorArgs); - } - return operatorDelegate.apply(operatorSelf, operatorArgs); - }); + observable.operator, + 'call', + (operatorDelegate: any) => (operatorSelf: any, operatorArgs: any[]) => { + if (operatorSelf._zone && operatorSelf._zone !== Zone.current) { + return operatorSelf._zone.run(operatorDelegate, operatorSelf, operatorArgs); + } + return operatorDelegate.apply(operatorSelf, operatorArgs); + }, + ); } return observable; }); - const patchSubscription = function() { + const patchSubscription = function () { ObjectDefineProperties(Subscription.prototype, { _zone: {value: null, writable: true, configurable: true}, _zoneUnsubscribe: {value: null, writable: true, configurable: true}, _unsubscribe: { - get: function(this: Subscription) { + get: function (this: Subscription) { if ((this as any)._zoneUnsubscribe || (this as any)._zoneUnsubscribeCleared) { return (this as any)._zoneUnsubscribe; } const proto = Object.getPrototypeOf(this); return proto && proto._unsubscribe; }, - set: function(this: Subscription, unsubscribe: any) { + set: function (this: Subscription, unsubscribe: any) { (this as any)._zone = Zone.current; if (!unsubscribe) { (this as any)._zoneUnsubscribe = unsubscribe; @@ -135,7 +137,7 @@ export function patchRxJs(Zone: ZoneType): void { (this as any)._zoneUnsubscribeCleared = true; } else { (this as any)._zoneUnsubscribeCleared = false; - (this as any)._zoneUnsubscribe = function() { + (this as any)._zoneUnsubscribe = function () { if (this._zone && this._zone !== Zone.current) { return this._zone.run(unsubscribe, this, arguments); } else { @@ -143,30 +145,30 @@ export function patchRxJs(Zone: ZoneType): void { } }; } - } - } + }, + }, }); }; - const patchSubscriber = function() { + const patchSubscriber = function () { const next = Subscriber.prototype.next; const error = Subscriber.prototype.error; const complete = Subscriber.prototype.complete; Object.defineProperty(Subscriber.prototype, 'destination', { configurable: true, - get: function(this: Subscriber) { + get: function (this: Subscriber) { return (this as any)._zoneDestination; }, - set: function(this: Subscriber, destination: any) { + set: function (this: Subscriber, destination: any) { (this as any)._zone = Zone.current; (this as any)._zoneDestination = destination; - } + }, }); // patch Subscriber.next to make sure it run // into SubscriptionZone - Subscriber.prototype.next = function(this: ZoneSubscriberContext) { + Subscriber.prototype.next = function (this: ZoneSubscriberContext) { const currentZone = Zone.current; const subscriptionZone = this._zone; @@ -179,7 +181,7 @@ export function patchRxJs(Zone: ZoneType): void { } }; - Subscriber.prototype.error = function(this: ZoneSubscriberContext) { + Subscriber.prototype.error = function (this: ZoneSubscriberContext) { const currentZone = Zone.current; const subscriptionZone = this._zone; @@ -192,7 +194,7 @@ export function patchRxJs(Zone: ZoneType): void { } }; - Subscriber.prototype.complete = function(this: ZoneSubscriberContext) { + Subscriber.prototype.complete = function (this: ZoneSubscriberContext) { const currentZone = Zone.current; const subscriptionZone = this._zone; diff --git a/packages/zone.js/lib/testing/promise-testing.ts b/packages/zone.js/lib/testing/promise-testing.ts index bfae256c67333..25453d4c9510d 100644 --- a/packages/zone.js/lib/testing/promise-testing.ts +++ b/packages/zone.js/lib/testing/promise-testing.ts @@ -46,7 +46,7 @@ export function patchPromiseTesting(Zone: ZoneType): void { return; } oriThen = (Promise as any)[Zone.__symbol__('ZonePromiseThen')] = Promise.prototype.then; - Promise.prototype.then = function() { + Promise.prototype.then = function () { const chained = oriThen.apply(this, arguments); if ((this as any)[symbolState] === UNRESOLVED) { // parent promise is unresolved. @@ -69,4 +69,4 @@ export function patchPromiseTesting(Zone: ZoneType): void { } }; }); -} \ No newline at end of file +} diff --git a/packages/zone.js/lib/zone-impl.ts b/packages/zone.js/lib/zone-impl.ts index 5c377bdac2b9c..1e081815ebdb6 100644 --- a/packages/zone.js/lib/zone-impl.ts +++ b/packages/zone.js/lib/zone-impl.ts @@ -138,7 +138,7 @@ export declare interface Zone { * * @returns {Zone} The parent Zone. */ - parent: Zone|null; + parent: Zone | null; /** * @returns {string} The Zone name (useful for debugging) */ @@ -163,7 +163,7 @@ export declare interface Zone { * @param key The key to use for identification of the returned zone. * @returns {Zone} The Zone which defines the `key`, `null` if not found. */ - getZoneWith(key: string): Zone|null; + getZoneWith(key: string): Zone | null; /** * Used to create a child zone. @@ -237,8 +237,11 @@ export declare interface Zone { * @param customSchedule */ scheduleMicroTask( - source: string, callback: Function, data?: TaskData, - customSchedule?: (task: Task) => void): MicroTask; + source: string, + callback: Function, + data?: TaskData, + customSchedule?: (task: Task) => void, + ): MicroTask; /** * Schedule a MacroTask. @@ -250,8 +253,12 @@ export declare interface Zone { * @param customCancel */ scheduleMacroTask( - source: string, callback: Function, data?: TaskData, customSchedule?: (task: Task) => void, - customCancel?: (task: Task) => void): MacroTask; + source: string, + callback: Function, + data?: TaskData, + customSchedule?: (task: Task) => void, + customCancel?: (task: Task) => void, + ): MacroTask; /** * Schedule an EventTask. @@ -263,8 +270,12 @@ export declare interface Zone { * @param customCancel */ scheduleEventTask( - source: string, callback: Function, data?: TaskData, customSchedule?: (task: Task) => void, - customCancel?: (task: Task) => void): EventTask; + source: string, + callback: Function, + data?: TaskData, + customSchedule?: (task: Task) => void, + customCancel?: (task: Task) => void, + ): EventTask; /** * Schedule an existing Task. @@ -298,7 +309,7 @@ export declare interface ZoneType { /** * @returns {Task} The task associated with the current execution. */ - currentTask: Task|null; + currentTask: Task | null; /** * Verify that Zone has been correctly patched. Specifically that Promise is zone aware. @@ -339,21 +350,32 @@ export declare interface ZonePrivate { microtaskDrainDone: () => void; showUncaughtError: () => boolean; patchEventTarget: (global: any, api: ZonePrivate, apis: any[], options?: any) => boolean[]; - patchOnProperties: (obj: any, properties: string[]|null, prototype?: any) => void; + patchOnProperties: (obj: any, properties: string[] | null, prototype?: any) => void; patchThen: (ctro: Function) => void; - patchMethod: - (target: any, name: string, - patchFn: (delegate: Function, delegateName: string, name: string) => - (self: any, args: any[]) => any) => Function | null; + patchMethod: ( + target: any, + name: string, + patchFn: ( + delegate: Function, + delegateName: string, + name: string, + ) => (self: any, args: any[]) => any, + ) => Function | null; bindArguments: (args: any[], source: string) => any[]; - patchMacroTask: - (obj: any, funcName: string, metaCreator: (self: any, args: any[]) => any) => void; + patchMacroTask: ( + obj: any, + funcName: string, + metaCreator: (self: any, args: any[]) => any, + ) => void; patchEventPrototype: (_global: any, api: ZonePrivate) => void; isIEOrEdge: () => boolean; - ObjectDefineProperty: - (o: any, p: PropertyKey, attributes: PropertyDescriptor&ThisType) => any; + ObjectDefineProperty: ( + o: any, + p: PropertyKey, + attributes: PropertyDescriptor & ThisType, + ) => any; ObjectGetOwnPropertyDescriptor: (o: any, p: PropertyKey) => PropertyDescriptor | undefined; - ObjectCreate(o: object|null, properties?: PropertyDescriptorMap&ThisType): any; + ObjectCreate(o: object | null, properties?: PropertyDescriptorMap & ThisType): any; ArraySlice(start?: number, end?: number): any[]; patchClass: (className: string) => void; wrapWithCurrentZone: (callback: any, source: string) => any; @@ -361,22 +383,35 @@ export declare interface ZonePrivate { attachOriginToPatched: (target: any, origin: any) => void; _redefineProperty: (target: any, callback: string, desc: any) => void; nativeScheduleMicroTask: (func: Function) => void; - patchCallbacks: - (api: ZonePrivate, target: any, targetName: string, method: string, - callbacks: string[]) => void; - getGlobalObjects: () => { - globalSources: any, zoneSymbolEventNames: any, eventNames: string[], isBrowser: boolean, - isMix: boolean, isNode: boolean, TRUE_STR: string, FALSE_STR: string, - ZONE_SYMBOL_PREFIX: string, ADD_EVENT_LISTENER_STR: string, - REMOVE_EVENT_LISTENER_STR: string - } | undefined; + patchCallbacks: ( + api: ZonePrivate, + target: any, + targetName: string, + method: string, + callbacks: string[], + ) => void; + getGlobalObjects: () => + | { + globalSources: any; + zoneSymbolEventNames: any; + eventNames: string[]; + isBrowser: boolean; + isMix: boolean; + isNode: boolean; + TRUE_STR: string; + FALSE_STR: string; + ZONE_SYMBOL_PREFIX: string; + ADD_EVENT_LISTENER_STR: string; + REMOVE_EVENT_LISTENER_STR: string; + } + | undefined; } /** * ZoneFrame represents zone stack frame information */ export declare interface ZoneFrame { - parent: ZoneFrame|null; + parent: ZoneFrame | null; zone: Zone; } @@ -414,9 +449,12 @@ export declare interface ZoneSpec { * @param targetZone The [Zone] which originally received the request. * @param zoneSpec The argument passed into the `fork` method. */ - onFork?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - zoneSpec: ZoneSpec) => Zone; + onFork?: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + zoneSpec: ZoneSpec, + ) => Zone; /** * Allows interception of the wrapping of the callback. @@ -427,9 +465,13 @@ export declare interface ZoneSpec { * @param delegate The argument passed into the `wrap` method. * @param source The argument passed into the `wrap` method. */ - onIntercept?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, - source: string) => Function; + onIntercept?: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + delegate: Function, + source: string, + ) => Function; /** * Allows interception of the callback invocation. @@ -442,9 +484,15 @@ export declare interface ZoneSpec { * @param applyArgs The argument passed into the `run` method. * @param source The argument passed into the `run` method. */ - onInvoke?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, - applyThis: any, applyArgs?: any[], source?: string) => any; + onInvoke?: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + delegate: Function, + applyThis: any, + applyArgs?: any[], + source?: string, + ) => any; /** * Allows interception of the error handling. @@ -454,9 +502,12 @@ export declare interface ZoneSpec { * @param targetZone The [Zone] which originally received the request. * @param error The argument passed into the `handleError` method. */ - onHandleError?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - error: any) => boolean; + onHandleError?: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + error: any, + ) => boolean; /** * Allows interception of task scheduling. @@ -466,12 +517,21 @@ export declare interface ZoneSpec { * @param targetZone The [Zone] which originally received the request. * @param task The argument passed into the `scheduleTask` method. */ - onScheduleTask?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => Task; - - onInvokeTask?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, - applyThis: any, applyArgs?: any[]) => any; + onScheduleTask?: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ) => Task; + + onInvokeTask?: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + applyThis: any, + applyArgs?: any[], + ) => any; /** * Allows interception of task cancellation. @@ -481,8 +541,12 @@ export declare interface ZoneSpec { * @param targetZone The [Zone] which originally received the request. * @param task The argument passed into the `cancelTask` method. */ - onCancelTask?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => any; + onCancelTask?: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ) => any; /** * Notifies of changes to the task queue empty status. @@ -492,12 +556,14 @@ export declare interface ZoneSpec { * @param targetZone The [Zone] which originally received the request. * @param hasTaskState */ - onHasTask?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - hasTaskState: HasTaskState) => void; + onHasTask?: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + hasTaskState: HasTaskState, + ) => void; } - /** * A delegate when intercepting zone operations. * @@ -533,8 +599,13 @@ export declare interface ZoneDelegate { zone: Zone; fork(targetZone: Zone, zoneSpec: ZoneSpec): Zone; intercept(targetZone: Zone, callback: Function, source: string): Function; - invoke(targetZone: Zone, callback: Function, applyThis?: any, applyArgs?: any[], source?: string): - any; + invoke( + targetZone: Zone, + callback: Function, + applyThis?: any, + applyArgs?: any[], + source?: string, + ): any; handleError(targetZone: Zone, error: any): boolean; scheduleTask(targetZone: Zone, task: Task): Task; invokeTask(targetZone: Zone, task: Task, applyThis?: any, applyArgs?: any[]): any; @@ -543,19 +614,27 @@ export declare interface ZoneDelegate { } export type HasTaskState = { - microTask: boolean; macroTask: boolean; eventTask: boolean; change: TaskType; + microTask: boolean; + macroTask: boolean; + eventTask: boolean; + change: TaskType; }; /** * Task type: `microTask`, `macroTask`, `eventTask`. */ -export type TaskType = 'microTask'|'macroTask'|'eventTask'; +export type TaskType = 'microTask' | 'macroTask' | 'eventTask'; /** * Task type: `notScheduled`, `scheduling`, `scheduled`, `running`, `canceling`, 'unknown'. */ -export type TaskState = 'notScheduled'|'scheduling'|'scheduled'|'running'|'canceling'|'unknown'; - +export type TaskState = + | 'notScheduled' + | 'scheduling' + | 'scheduled' + | 'running' + | 'canceling' + | 'unknown'; /** */ @@ -684,8 +763,8 @@ export function __symbol__(name: string) { } export function initZone(): ZoneType { - const performance: {mark(name: string): void; measure(name: string, label: string): void;} = - global['performance']; + const performance: {mark(name: string): void; measure(name: string, label: string): void} = + global['performance']; function mark(name: string) { performance && performance['mark'] && performance['mark'](name); } @@ -701,11 +780,12 @@ export function initZone(): ZoneType { static assertZonePatched() { if (global['Promise'] !== patches['ZoneAwarePromise']) { throw new Error( - 'Zone.js has detected that ZoneAwarePromise `(window|global).Promise` ' + + 'Zone.js has detected that ZoneAwarePromise `(window|global).Promise` ' + 'has been overwritten.\n' + 'Most 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.)'); + 'If you must load one, do so before loading zone.js.)', + ); } } @@ -721,7 +801,7 @@ export function initZone(): ZoneType { return _currentZoneFrame.zone; } - static get currentTask(): Task|null { + static get currentTask(): Task | null { return _currentTask; } @@ -743,7 +823,7 @@ export function initZone(): ZoneType { } } - public get parent(): AmbientZone|null { + public get parent(): AmbientZone | null { return this._parent; } @@ -751,18 +831,20 @@ export function initZone(): ZoneType { return this._name; } - - private _parent: ZoneImpl|null; + private _parent: ZoneImpl | null; private _name: string; private _properties: {[key: string]: any}; private _zoneDelegate: _ZoneDelegate; - constructor(parent: ZoneImpl|null, zoneSpec: ZoneSpec|null) { + constructor(parent: ZoneImpl | null, zoneSpec: ZoneSpec | null) { this._parent = parent as ZoneImpl; this._name = zoneSpec ? zoneSpec.name || 'unnamed' : ''; - this._properties = zoneSpec && zoneSpec.properties || {}; - this._zoneDelegate = - new _ZoneDelegate(this, this._parent && this._parent._zoneDelegate, zoneSpec); + this._properties = (zoneSpec && zoneSpec.properties) || {}; + this._zoneDelegate = new _ZoneDelegate( + this, + this._parent && this._parent._zoneDelegate, + zoneSpec, + ); } public get(key: string): any { @@ -770,8 +852,8 @@ export function initZone(): ZoneType { if (zone) return zone._properties[key]; } - public getZoneWith(key: string): AmbientZone|null { - let current: ZoneImpl|null = this; + public getZoneWith(key: string): AmbientZone | null { + let current: ZoneImpl | null = this; while (current) { if (current._properties.hasOwnProperty(key)) { return current; @@ -792,14 +874,18 @@ export function initZone(): ZoneType { } const _callback = this._zoneDelegate.intercept(this, callback, source); const zone: ZoneImpl = this; - return function(this: unknown) { + return function (this: unknown) { return zone.runGuarded(_callback, this, arguments, source); } as any as T; } public run(callback: Function, applyThis?: any, applyArgs?: any[], source?: string): any; public run( - callback: (...args: any[]) => T, applyThis?: any, applyArgs?: any[], source?: string): T { + callback: (...args: any[]) => T, + applyThis?: any, + applyArgs?: any[], + source?: string, + ): T { _currentZoneFrame = {parent: _currentZoneFrame, zone: this}; try { return this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source); @@ -810,8 +896,11 @@ export function initZone(): ZoneType { public runGuarded(callback: Function, applyThis?: any, applyArgs?: any[], source?: string): any; public runGuarded( - callback: (...args: any[]) => T, applyThis: any = null, applyArgs?: any[], - source?: string) { + callback: (...args: any[]) => T, + applyThis: any = null, + applyArgs?: any[], + source?: string, + ) { _currentZoneFrame = {parent: _currentZoneFrame, zone: this}; try { try { @@ -826,12 +915,15 @@ export function initZone(): ZoneType { } } - runTask(task: Task, applyThis?: any, applyArgs?: any): any { if (task.zone != this) { throw new Error( - 'A task can only be run in the zone of creation! (Creation: ' + - (task.zone || NO_ZONE).name + '; Execution: ' + this.name + ')'); + 'A task can only be run in the zone of creation! (Creation: ' + + (task.zone || NO_ZONE).name + + '; Execution: ' + + this.name + + ')', + ); } // https://github.com/angular/zone.js/issues/778, sometimes eventTask // will run in notScheduled(canceled) state, we should not try to @@ -868,7 +960,7 @@ export function initZone(): ZoneType { task.runCount = 0; this._updateTaskCount(task as ZoneTask, -1); reEntryGuard && - (task as ZoneTask)._transitionTo(notScheduled, running, notScheduled); + (task as ZoneTask)._transitionTo(notScheduled, running, notScheduled); } } _currentZoneFrame = _currentZoneFrame.parent!; @@ -883,8 +975,9 @@ export function initZone(): ZoneType { let newZone: any = this; while (newZone) { if (newZone === task.zone) { - throw Error(`can not reschedule task to ${ - this.name} which is descendants of the original zone ${task.zone.name}`); + throw Error( + `can not reschedule task to ${this.name} which is descendants of the original zone ${task.zone.name}`, + ); } newZone = newZone.parent; } @@ -914,31 +1007,49 @@ export function initZone(): ZoneType { } scheduleMicroTask( - source: string, callback: Function, data?: TaskData, - customSchedule?: (task: Task) => void): MicroTask { + source: string, + callback: Function, + data?: TaskData, + customSchedule?: (task: Task) => void, + ): MicroTask { return this.scheduleTask( - new ZoneTask(microTask, source, callback, data, customSchedule, undefined)); + new ZoneTask(microTask, source, callback, data, customSchedule, undefined), + ); } scheduleMacroTask( - source: string, callback: Function, data?: TaskData, customSchedule?: (task: Task) => void, - customCancel?: (task: Task) => void): MacroTask { + source: string, + callback: Function, + data?: TaskData, + customSchedule?: (task: Task) => void, + customCancel?: (task: Task) => void, + ): MacroTask { return this.scheduleTask( - new ZoneTask(macroTask, source, callback, data, customSchedule, customCancel)); + new ZoneTask(macroTask, source, callback, data, customSchedule, customCancel), + ); } scheduleEventTask( - source: string, callback: Function, data?: TaskData, customSchedule?: (task: Task) => void, - customCancel?: (task: Task) => void): EventTask { + source: string, + callback: Function, + data?: TaskData, + customSchedule?: (task: Task) => void, + customCancel?: (task: Task) => void, + ): EventTask { return this.scheduleTask( - new ZoneTask(eventTask, source, callback, data, customSchedule, customCancel)); + new ZoneTask(eventTask, source, callback, data, customSchedule, customCancel), + ); } cancelTask(task: Task): any { if (task.zone != this) throw new Error( - 'A task can only be cancelled in the zone of creation! (Creation: ' + - (task.zone || NO_ZONE).name + '; Execution: ' + this.name + ')'); + 'A task can only be cancelled in the zone of creation! (Creation: ' + + (task.zone || NO_ZONE).name + + '; Execution: ' + + this.name + + ')', + ); if (task.state !== scheduled && task.state !== running) { return; @@ -972,16 +1083,28 @@ export function initZone(): ZoneType { const DELEGATE_ZS: ZoneSpec = { name: '', - onHasTask: - (delegate: ZoneDelegate, _: AmbientZone, target: AmbientZone, hasTaskState: HasTaskState): - void => delegate.hasTask(target, hasTaskState), - onScheduleTask: (delegate: ZoneDelegate, _: AmbientZone, target: AmbientZone, task: Task): - Task => delegate.scheduleTask(target, task), - onInvokeTask: - (delegate: ZoneDelegate, _: AmbientZone, target: AmbientZone, task: Task, applyThis: any, - applyArgs: any): any => delegate.invokeTask(target, task, applyThis, applyArgs), + onHasTask: ( + delegate: ZoneDelegate, + _: AmbientZone, + target: AmbientZone, + hasTaskState: HasTaskState, + ): void => delegate.hasTask(target, hasTaskState), + onScheduleTask: ( + delegate: ZoneDelegate, + _: AmbientZone, + target: AmbientZone, + task: Task, + ): Task => delegate.scheduleTask(target, task), + onInvokeTask: ( + delegate: ZoneDelegate, + _: AmbientZone, + target: AmbientZone, + task: Task, + applyThis: any, + applyArgs: any, + ): any => delegate.invokeTask(target, task, applyThis, applyArgs), onCancelTask: (delegate: ZoneDelegate, _: AmbientZone, target: AmbientZone, task: Task): any => - delegate.cancelTask(target, task) + delegate.cancelTask(target, task), }; class _ZoneDelegate implements ZoneDelegate { @@ -990,95 +1113,96 @@ export function initZone(): ZoneType { } private _zone: ZoneImpl; - private _taskCounts: - {microTask: number, - macroTask: number, - eventTask: number} = {'microTask': 0, 'macroTask': 0, 'eventTask': 0}; + private _taskCounts: {microTask: number; macroTask: number; eventTask: number} = { + 'microTask': 0, + 'macroTask': 0, + 'eventTask': 0, + }; - private _parentDelegate: _ZoneDelegate|null; + private _parentDelegate: _ZoneDelegate | null; - private _forkDlgt: _ZoneDelegate|null; - private _forkZS: ZoneSpec|null; - private _forkCurrZone: Zone|null; + private _forkDlgt: _ZoneDelegate | null; + private _forkZS: ZoneSpec | null; + private _forkCurrZone: Zone | null; - private _interceptDlgt: _ZoneDelegate|null; - private _interceptZS: ZoneSpec|null; - private _interceptCurrZone: Zone|null; + private _interceptDlgt: _ZoneDelegate | null; + private _interceptZS: ZoneSpec | null; + private _interceptCurrZone: Zone | null; - private _invokeDlgt: _ZoneDelegate|null; - private _invokeZS: ZoneSpec|null; - private _invokeCurrZone: ZoneImpl|null; + private _invokeDlgt: _ZoneDelegate | null; + private _invokeZS: ZoneSpec | null; + private _invokeCurrZone: ZoneImpl | null; - private _handleErrorDlgt: _ZoneDelegate|null; - private _handleErrorZS: ZoneSpec|null; - private _handleErrorCurrZone: ZoneImpl|null; + private _handleErrorDlgt: _ZoneDelegate | null; + private _handleErrorZS: ZoneSpec | null; + private _handleErrorCurrZone: ZoneImpl | null; - private _scheduleTaskDlgt: _ZoneDelegate|null; - private _scheduleTaskZS: ZoneSpec|null; - private _scheduleTaskCurrZone: ZoneImpl|null; + private _scheduleTaskDlgt: _ZoneDelegate | null; + private _scheduleTaskZS: ZoneSpec | null; + private _scheduleTaskCurrZone: ZoneImpl | null; - private _invokeTaskDlgt: _ZoneDelegate|null; - private _invokeTaskZS: ZoneSpec|null; - private _invokeTaskCurrZone: ZoneImpl|null; + private _invokeTaskDlgt: _ZoneDelegate | null; + private _invokeTaskZS: ZoneSpec | null; + private _invokeTaskCurrZone: ZoneImpl | null; - private _cancelTaskDlgt: _ZoneDelegate|null; - private _cancelTaskZS: ZoneSpec|null; - private _cancelTaskCurrZone: ZoneImpl|null; + private _cancelTaskDlgt: _ZoneDelegate | null; + private _cancelTaskZS: ZoneSpec | null; + private _cancelTaskCurrZone: ZoneImpl | null; - private _hasTaskDlgt: _ZoneDelegate|null; - private _hasTaskDlgtOwner: _ZoneDelegate|null; - private _hasTaskZS: ZoneSpec|null; - private _hasTaskCurrZone: ZoneImpl|null; + private _hasTaskDlgt: _ZoneDelegate | null; + private _hasTaskDlgtOwner: _ZoneDelegate | null; + private _hasTaskZS: ZoneSpec | null; + private _hasTaskCurrZone: ZoneImpl | null; - constructor(zone: Zone, parentDelegate: _ZoneDelegate|null, zoneSpec: ZoneSpec|null) { + constructor(zone: Zone, parentDelegate: _ZoneDelegate | null, zoneSpec: ZoneSpec | null) { this._zone = zone as ZoneImpl; this._parentDelegate = parentDelegate; this._forkZS = zoneSpec && (zoneSpec && zoneSpec.onFork ? zoneSpec : parentDelegate!._forkZS); this._forkDlgt = zoneSpec && (zoneSpec.onFork ? parentDelegate : parentDelegate!._forkDlgt); this._forkCurrZone = - zoneSpec && (zoneSpec.onFork ? this._zone : parentDelegate!._forkCurrZone); + zoneSpec && (zoneSpec.onFork ? this._zone : parentDelegate!._forkCurrZone); this._interceptZS = - zoneSpec && (zoneSpec.onIntercept ? zoneSpec : parentDelegate!._interceptZS); + zoneSpec && (zoneSpec.onIntercept ? zoneSpec : parentDelegate!._interceptZS); this._interceptDlgt = - zoneSpec && (zoneSpec.onIntercept ? parentDelegate : parentDelegate!._interceptDlgt); + zoneSpec && (zoneSpec.onIntercept ? parentDelegate : parentDelegate!._interceptDlgt); this._interceptCurrZone = - zoneSpec && (zoneSpec.onIntercept ? this._zone : parentDelegate!._interceptCurrZone); + zoneSpec && (zoneSpec.onIntercept ? this._zone : parentDelegate!._interceptCurrZone); this._invokeZS = zoneSpec && (zoneSpec.onInvoke ? zoneSpec : parentDelegate!._invokeZS); this._invokeDlgt = - zoneSpec && (zoneSpec.onInvoke ? parentDelegate! : parentDelegate!._invokeDlgt); + zoneSpec && (zoneSpec.onInvoke ? parentDelegate! : parentDelegate!._invokeDlgt); this._invokeCurrZone = - zoneSpec && (zoneSpec.onInvoke ? this._zone : parentDelegate!._invokeCurrZone); + zoneSpec && (zoneSpec.onInvoke ? this._zone : parentDelegate!._invokeCurrZone); this._handleErrorZS = - zoneSpec && (zoneSpec.onHandleError ? zoneSpec : parentDelegate!._handleErrorZS); + zoneSpec && (zoneSpec.onHandleError ? zoneSpec : parentDelegate!._handleErrorZS); this._handleErrorDlgt = - zoneSpec && (zoneSpec.onHandleError ? parentDelegate! : parentDelegate!._handleErrorDlgt); + zoneSpec && (zoneSpec.onHandleError ? parentDelegate! : parentDelegate!._handleErrorDlgt); this._handleErrorCurrZone = - zoneSpec && (zoneSpec.onHandleError ? this._zone : parentDelegate!._handleErrorCurrZone); + zoneSpec && (zoneSpec.onHandleError ? this._zone : parentDelegate!._handleErrorCurrZone); this._scheduleTaskZS = - zoneSpec && (zoneSpec.onScheduleTask ? zoneSpec : parentDelegate!._scheduleTaskZS); - this._scheduleTaskDlgt = zoneSpec && - (zoneSpec.onScheduleTask ? parentDelegate! : parentDelegate!._scheduleTaskDlgt); - this._scheduleTaskCurrZone = zoneSpec && - (zoneSpec.onScheduleTask ? this._zone : parentDelegate!._scheduleTaskCurrZone); + zoneSpec && (zoneSpec.onScheduleTask ? zoneSpec : parentDelegate!._scheduleTaskZS); + this._scheduleTaskDlgt = + zoneSpec && (zoneSpec.onScheduleTask ? parentDelegate! : parentDelegate!._scheduleTaskDlgt); + this._scheduleTaskCurrZone = + zoneSpec && (zoneSpec.onScheduleTask ? this._zone : parentDelegate!._scheduleTaskCurrZone); this._invokeTaskZS = - zoneSpec && (zoneSpec.onInvokeTask ? zoneSpec : parentDelegate!._invokeTaskZS); + zoneSpec && (zoneSpec.onInvokeTask ? zoneSpec : parentDelegate!._invokeTaskZS); this._invokeTaskDlgt = - zoneSpec && (zoneSpec.onInvokeTask ? parentDelegate! : parentDelegate!._invokeTaskDlgt); + zoneSpec && (zoneSpec.onInvokeTask ? parentDelegate! : parentDelegate!._invokeTaskDlgt); this._invokeTaskCurrZone = - zoneSpec && (zoneSpec.onInvokeTask ? this._zone : parentDelegate!._invokeTaskCurrZone); + zoneSpec && (zoneSpec.onInvokeTask ? this._zone : parentDelegate!._invokeTaskCurrZone); this._cancelTaskZS = - zoneSpec && (zoneSpec.onCancelTask ? zoneSpec : parentDelegate!._cancelTaskZS); + zoneSpec && (zoneSpec.onCancelTask ? zoneSpec : parentDelegate!._cancelTaskZS); this._cancelTaskDlgt = - zoneSpec && (zoneSpec.onCancelTask ? parentDelegate! : parentDelegate!._cancelTaskDlgt); + zoneSpec && (zoneSpec.onCancelTask ? parentDelegate! : parentDelegate!._cancelTaskDlgt); this._cancelTaskCurrZone = - zoneSpec && (zoneSpec.onCancelTask ? this._zone : parentDelegate!._cancelTaskCurrZone); + zoneSpec && (zoneSpec.onCancelTask ? this._zone : parentDelegate!._cancelTaskCurrZone); this._hasTaskZS = null; this._hasTaskDlgt = null; @@ -1113,31 +1237,52 @@ export function initZone(): ZoneType { } fork(targetZone: ZoneImpl, zoneSpec: ZoneSpec): AmbientZone { - return this._forkZS ? this._forkZS.onFork!(this._forkDlgt!, this.zone, targetZone, zoneSpec) : - new ZoneImpl(targetZone, zoneSpec); + return this._forkZS + ? this._forkZS.onFork!(this._forkDlgt!, this.zone, targetZone, zoneSpec) + : new ZoneImpl(targetZone, zoneSpec); } intercept(targetZone: ZoneImpl, callback: Function, source: string): Function { - return this._interceptZS ? - this._interceptZS.onIntercept! - (this._interceptDlgt!, this._interceptCurrZone!, targetZone, callback, source) : - callback; + return this._interceptZS + ? this._interceptZS.onIntercept!( + this._interceptDlgt!, + this._interceptCurrZone!, + targetZone, + callback, + source, + ) + : callback; } invoke( - targetZone: ZoneImpl, callback: Function, applyThis: any, applyArgs?: any[], - source?: string): any { - return this._invokeZS ? this._invokeZS.onInvoke! - (this._invokeDlgt!, this._invokeCurrZone!, targetZone, callback, - applyThis, applyArgs, source) : - callback.apply(applyThis, applyArgs); + targetZone: ZoneImpl, + callback: Function, + applyThis: any, + applyArgs?: any[], + source?: string, + ): any { + return this._invokeZS + ? this._invokeZS.onInvoke!( + this._invokeDlgt!, + this._invokeCurrZone!, + targetZone, + callback, + applyThis, + applyArgs, + source, + ) + : callback.apply(applyThis, applyArgs); } handleError(targetZone: ZoneImpl, error: any): boolean { - return this._handleErrorZS ? - this._handleErrorZS.onHandleError! - (this._handleErrorDlgt!, this._handleErrorCurrZone!, targetZone, error) : - true; + return this._handleErrorZS + ? this._handleErrorZS.onHandleError!( + this._handleErrorDlgt!, + this._handleErrorCurrZone!, + targetZone, + error, + ) + : true; } scheduleTask(targetZone: ZoneImpl, task: Task): Task { @@ -1147,8 +1292,12 @@ export function initZone(): ZoneType { returnTask._zoneDelegates!.push(this._hasTaskDlgtOwner!); } // clang-format off - returnTask = this._scheduleTaskZS.onScheduleTask !( - this._scheduleTaskDlgt !, this._scheduleTaskCurrZone !, targetZone, task) as ZoneTask; + returnTask = this._scheduleTaskZS.onScheduleTask!( + this._scheduleTaskDlgt!, + this._scheduleTaskCurrZone!, + targetZone, + task, + ) as ZoneTask; // clang-format on if (!returnTask) returnTask = task as ZoneTask; } else { @@ -1164,17 +1313,27 @@ export function initZone(): ZoneType { } invokeTask(targetZone: ZoneImpl, task: Task, applyThis: any, applyArgs?: any[]): any { - return this._invokeTaskZS ? this._invokeTaskZS.onInvokeTask! - (this._invokeTaskDlgt!, this._invokeTaskCurrZone!, targetZone, - task, applyThis, applyArgs) : - task.callback.apply(applyThis, applyArgs); + return this._invokeTaskZS + ? this._invokeTaskZS.onInvokeTask!( + this._invokeTaskDlgt!, + this._invokeTaskCurrZone!, + targetZone, + task, + applyThis, + applyArgs, + ) + : task.callback.apply(applyThis, applyArgs); } cancelTask(targetZone: ZoneImpl, task: Task): any { let value: any; if (this._cancelTaskZS) { - value = this._cancelTaskZS.onCancelTask! - (this._cancelTaskDlgt!, this._cancelTaskCurrZone!, targetZone, task); + value = this._cancelTaskZS.onCancelTask!( + this._cancelTaskDlgt!, + this._cancelTaskCurrZone!, + targetZone, + task, + ); } else { if (!task.cancelFn) { throw Error('Task is not cancelable'); @@ -1189,8 +1348,12 @@ export function initZone(): ZoneType { // can still trigger hasTask callback try { this._hasTaskZS && - this._hasTaskZS.onHasTask! - (this._hasTaskDlgt!, this._hasTaskCurrZone!, targetZone, isEmpty); + this._hasTaskZS.onHasTask!( + this._hasTaskDlgt!, + this._hasTaskCurrZone!, + targetZone, + isEmpty, + ); } catch (err) { this.handleError(targetZone, err); } @@ -1200,7 +1363,7 @@ export function initZone(): ZoneType { _updateTaskCount(type: TaskType, count: number) { const counts = this._taskCounts; const prev = counts[type]; - const next = counts[type] = prev + count; + const next = (counts[type] = prev + count); if (next < 0) { throw new Error('More tasks executed then were scheduled.'); } @@ -1209,7 +1372,7 @@ export function initZone(): ZoneType { microTask: counts['microTask'] > 0, macroTask: counts['macroTask'] > 0, eventTask: counts['eventTask'] > 0, - change: type + change: type, }; this.hasTask(this._zone, isEmpty); } @@ -1221,20 +1384,25 @@ export function initZone(): ZoneType { public source: string; public invoke: Function; public callback: Function; - public data: TaskData|undefined; - public scheduleFn: ((task: Task) => void)|undefined; - public cancelFn: ((task: Task) => void)|undefined; + public data: TaskData | undefined; + public scheduleFn: ((task: Task) => void) | undefined; + public cancelFn: ((task: Task) => void) | undefined; // tslint:disable-next-line:require-internal-with-underscore - _zone: ZoneImpl|null = null; + _zone: ZoneImpl | null = null; public runCount: number = 0; // tslint:disable-next-line:require-internal-with-underscore - _zoneDelegates: _ZoneDelegate[]|null = null; + _zoneDelegates: _ZoneDelegate[] | null = null; // tslint:disable-next-line:require-internal-with-underscore _state: TaskState = 'notScheduled'; constructor( - type: T, source: string, callback: Function, options: TaskData|undefined, - scheduleFn: ((task: Task) => void)|undefined, cancelFn: ((task: Task) => void)|undefined) { + type: T, + source: string, + callback: Function, + options: TaskData | undefined, + scheduleFn: ((task: Task) => void) | undefined, + cancelFn: ((task: Task) => void) | undefined, + ) { this.type = type; this.source = source; this.data = options; @@ -1249,7 +1417,7 @@ export function initZone(): ZoneType { if (type === eventTask && options && (options as any).useG) { this.invoke = ZoneTask.invokeTask; } else { - this.invoke = function() { + this.invoke = function () { return ZoneTask.invokeTask.call(global, self, this, arguments); }; } @@ -1291,9 +1459,11 @@ export function initZone(): ZoneType { this._zoneDelegates = null; } } else { - throw new Error(`${this.type} '${this.source}': can not transition to '${ - toState}', expecting state '${fromState1}'${ - fromState2 ? ' or \'' + fromState2 + '\'' : ''}, was '${this._state}'.`); + throw new Error( + `${this.type} '${this.source}': can not transition to '${toState}', expecting state '${fromState1}'${ + fromState2 ? " or '" + fromState2 + "'" : '' + }, was '${this._state}'.`, + ); } } @@ -1313,12 +1483,11 @@ export function initZone(): ZoneType { state: this.state, source: this.source, zone: this.zone.name, - runCount: this.runCount + runCount: this.runCount, }; } } - ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// /// MICROTASK QUEUE @@ -1386,13 +1555,16 @@ export function initZone(): ZoneType { ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// - const NO_ZONE = {name: 'NO ZONE'}; - const notScheduled: 'notScheduled' = 'notScheduled', scheduling: 'scheduling' = 'scheduling', - scheduled: 'scheduled' = 'scheduled', running: 'running' = 'running', - canceling: 'canceling' = 'canceling', unknown: 'unknown' = 'unknown'; - const microTask: 'microTask' = 'microTask', macroTask: 'macroTask' = 'macroTask', - eventTask: 'eventTask' = 'eventTask'; + const notScheduled: 'notScheduled' = 'notScheduled', + scheduling: 'scheduling' = 'scheduling', + scheduled: 'scheduled' = 'scheduled', + running: 'running' = 'running', + canceling: 'canceling' = 'canceling', + unknown: 'unknown' = 'unknown'; + const microTask: 'microTask' = 'microTask', + macroTask: 'macroTask' = 'macroTask', + eventTask: 'eventTask' = 'eventTask'; const patches: {[key: string]: any} = {}; const _api: ZonePrivate = { @@ -1421,10 +1593,10 @@ export function initZone(): ZoneType { attachOriginToPatched: () => noop, _redefineProperty: () => noop, patchCallbacks: () => noop, - nativeScheduleMicroTask: nativeScheduleMicroTask + nativeScheduleMicroTask: nativeScheduleMicroTask, }; let _currentZoneFrame: ZoneFrame = {parent: null, zone: new ZoneImpl(null, null)}; - let _currentTask: Task|null = null; + let _currentTask: Task | null = null; let _numberOfNestedTaskFrames = 0; function noop() {} diff --git a/packages/zone.js/lib/zone-spec/async-test.ts b/packages/zone.js/lib/zone-spec/async-test.ts index 82972933d8b9e..d6efb799d71de 100644 --- a/packages/zone.js/lib/zone-spec/async-test.ts +++ b/packages/zone.js/lib/zone-spec/async-test.ts @@ -9,7 +9,7 @@ import {__symbol__, ZoneType} from '../zone-impl'; const __global: any = - typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global; + (typeof window !== 'undefined' && window) || (typeof self !== 'undefined' && self) || global; class AsyncTestZoneSpec implements ZoneSpec { // Needs to be a getter and not a plain property in order run this just-in-time. Otherwise // `__symbol__` would be evaluated during top-level execution prior to the Zone prefix being @@ -22,20 +22,23 @@ class AsyncTestZoneSpec implements ZoneSpec { _pendingMacroTasks: boolean = false; _alreadyErrored: boolean = false; _isSync: boolean = false; - _existingFinishTimer: ReturnType|null = null; + _existingFinishTimer: ReturnType | null = null; - entryFunction: Function|null = null; + entryFunction: Function | null = null; runZone = Zone.current; unresolvedChainedPromiseCount = 0; supportWaitUnresolvedChainedPromise = false; constructor( - private finishCallback: Function, private failCallback: Function, namePrefix: string) { + private finishCallback: Function, + private failCallback: Function, + namePrefix: string, + ) { this.name = 'asyncTestZone for ' + namePrefix; this.properties = {'AsyncTestZoneSpec': this}; this.supportWaitUnresolvedChainedPromise = - __global[__symbol__('supportWaitUnResolvedChainedPromise')] === true; + __global[__symbol__('supportWaitUnResolvedChainedPromise')] === true; } isUnresolvedChainedPromisePending() { @@ -62,8 +65,13 @@ class AsyncTestZoneSpec implements ZoneSpec { this._existingFinishTimer = null; } - if (!(this._pendingMicroTasks || this._pendingMacroTasks || - (this.supportWaitUnresolvedChainedPromise && this.isUnresolvedChainedPromisePending()))) { + if ( + !( + this._pendingMicroTasks || + this._pendingMacroTasks || + (this.supportWaitUnresolvedChainedPromise && this.isUnresolvedChainedPromisePending()) + ) + ) { // We wait until the next tick because we would like to catch unhandled promises which could // cause test logic to be executed. In such cases we cannot finish with tasks pending then. this.runZone.run(() => { @@ -117,8 +125,13 @@ class AsyncTestZoneSpec implements ZoneSpec { } onInvokeTask( - delegate: ZoneDelegate, current: Zone, target: Zone, task: Task, applyThis: any, - applyArgs: any) { + delegate: ZoneDelegate, + current: Zone, + target: Zone, + task: Task, + applyThis: any, + applyArgs: any, + ) { if (task.type !== 'eventTask') { this._isSync = false; } @@ -138,8 +151,14 @@ class AsyncTestZoneSpec implements ZoneSpec { // updated by(JiaLiPassion), only call finish callback when no task // was scheduled/invoked/canceled. onInvoke( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, - applyThis: any, applyArgs?: any[], source?: string): any { + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + delegate: Function, + applyThis: any, + applyArgs?: any[], + source?: string, + ): any { if (!this.entryFunction) { this.entryFunction = delegate; } @@ -163,8 +182,12 @@ class AsyncTestZoneSpec implements ZoneSpec { } } - onHandleError(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any): - boolean { + onHandleError( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + error: any, + ): boolean { // Let the parent try to handle the error. const result = parentZoneDelegate.handleError(targetZone, error); if (result) { @@ -216,12 +239,12 @@ export function patchAsyncTest(Zone: ZoneType): void { // function when asynchronous activity is finished. if (global.jasmine) { // Not using an arrow function to preserve context passed from call site - return function(this: unknown, done: any) { + return function (this: unknown, done: any) { 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: any) { + done = function () {}; + done.fail = function (e: any) { throw e; }; } @@ -238,7 +261,7 @@ export function patchAsyncTest(Zone: ZoneType): void { // 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(this: unknown) { + return function (this: unknown) { return new Promise((finishCallback, failCallback) => { runInTestZone(fn, this, finishCallback, failCallback); }); @@ -246,22 +269,28 @@ export function patchAsyncTest(Zone: ZoneType): void { }; function runInTestZone( - fn: Function, context: any, finishCallback: Function, failCallback: Function) { + fn: Function, + context: any, + finishCallback: Function, + failCallback: Function, + ) { const currentZone = Zone.current; const AsyncTestZoneSpec = (Zone as any)['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/plugins/async-test'); + 'AsyncTestZoneSpec is needed for the async() test helper but could not be found. ' + + 'Please make sure that your environment includes zone.js/plugins/async-test', + ); } const ProxyZoneSpec = (Zone as any)['ProxyZoneSpec'] as { - get(): {setDelegate(spec: ZoneSpec): void; getDelegate(): ZoneSpec;}; + get(): {setDelegate(spec: ZoneSpec): void; getDelegate(): ZoneSpec}; assertPresent: () => void; }; if (!ProxyZoneSpec) { 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/plugins/proxy'); + 'ProxyZoneSpec is needed for the async() test helper but could not be found. ' + + 'Please make sure that your environment includes zone.js/plugins/proxy', + ); } const proxyZoneSpec = ProxyZoneSpec.get(); ProxyZoneSpec.assertPresent(); @@ -271,31 +300,32 @@ export function patchAsyncTest(Zone: ZoneType): void { const previousDelegate = proxyZoneSpec.getDelegate(); proxyZone!.parent!.run(() => { const testZoneSpec: ZoneSpec = new AsyncTestZoneSpec( - () => { - // Need to restore the original zone. - if (proxyZoneSpec.getDelegate() == testZoneSpec) { - // Only reset the zone spec if it's - // still this one. Otherwise, assume - // it's OK. - proxyZoneSpec.setDelegate(previousDelegate); - } - (testZoneSpec as any).unPatchPromiseForTest(); - currentZone.run(() => { - finishCallback(); - }); - }, - (error: any) => { - // 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); - } - (testZoneSpec as any).unPatchPromiseForTest(); - currentZone.run(() => { - failCallback(error); - }); - }, - 'test'); + () => { + // Need to restore the original zone. + if (proxyZoneSpec.getDelegate() == testZoneSpec) { + // Only reset the zone spec if it's + // still this one. Otherwise, assume + // it's OK. + proxyZoneSpec.setDelegate(previousDelegate); + } + (testZoneSpec as any).unPatchPromiseForTest(); + currentZone.run(() => { + finishCallback(); + }); + }, + (error: any) => { + // 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); + } + (testZoneSpec as any).unPatchPromiseForTest(); + currentZone.run(() => { + failCallback(error); + }); + }, + 'test', + ); proxyZoneSpec.setDelegate(testZoneSpec); (testZoneSpec as any).patchPromiseForTest(); }); diff --git a/packages/zone.js/lib/zone-spec/fake-async-test.ts b/packages/zone.js/lib/zone-spec/fake-async-test.ts index be04a1aa3bc59..9127358d9f3ae 100644 --- a/packages/zone.js/lib/zone-spec/fake-async-test.ts +++ b/packages/zone.js/lib/zone-spec/fake-async-test.ts @@ -9,7 +9,7 @@ import {ZoneType} from '../zone-impl'; const global: any = - typeof window === 'object' && window || typeof self === 'object' && self || globalThis.global; + (typeof window === 'object' && window) || (typeof self === 'object' && self) || globalThis.global; interface ScheduledFunction { endTime: number; @@ -49,7 +49,7 @@ function FakeDate() { } } -FakeDate.now = function(this: unknown) { +FakeDate.now = function (this: unknown) { const fakeAsyncTestZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); if (fakeAsyncTestZoneSpec) { return fakeAsyncTestZoneSpec.getFakeSystemTime(); @@ -61,16 +61,18 @@ FakeDate.UTC = OriginalDate.UTC; FakeDate.parse = OriginalDate.parse; // keep a reference for zone patched timer function -let patchedTimers: { - setTimeout: typeof setTimeout, - setInterval: typeof setInterval, - clearTimeout: typeof clearTimeout, - clearInterval: typeof clearInterval, - nativeSetTimeout: typeof setTimeout, - nativeClearTimeout: typeof clearTimeout, -}|undefined; +let patchedTimers: + | { + setTimeout: typeof setTimeout; + setInterval: typeof setInterval; + clearTimeout: typeof clearTimeout; + clearInterval: typeof clearInterval; + nativeSetTimeout: typeof setTimeout; + nativeClearTimeout: typeof clearTimeout; + } + | undefined; -const timeoutCallback = function() {}; +const timeoutCallback = function () {}; class Scheduler { // Next scheduler id. @@ -115,22 +117,26 @@ class Scheduler { return OriginalDate.now(); } - scheduleFunction(cb: Function, delay: number, options?: { - args?: any[], - isPeriodic?: boolean, - isRequestAnimationFrame?: boolean, - id?: number, - isRequeuePeriodic?: boolean - }): number { + scheduleFunction( + cb: Function, + delay: number, + options?: { + args?: any[]; + isPeriodic?: boolean; + isRequestAnimationFrame?: boolean; + id?: number; + isRequeuePeriodic?: boolean; + }, + ): number { options = { ...{ args: [], isPeriodic: false, isRequestAnimationFrame: false, id: -1, - isRequeuePeriodic: false + isRequeuePeriodic: false, }, - ...options + ...options, }; let currentId = options.id! < 0 ? Scheduler.nextId : options.id!; Scheduler.nextId = Scheduler.getNextId(); @@ -144,7 +150,7 @@ class Scheduler { args: options.args!, delay: delay, isPeriodic: options.isPeriodic!, - isRequestAnimationFrame: options.isRequestAnimationFrame! + isRequestAnimationFrame: options.isRequestAnimationFrame!, }; if (options.isRequeuePeriodic!) { this._currentTickRequeuePeriodicEntries.push(newEntry); @@ -177,9 +183,13 @@ class Scheduler { return this._schedulerQueue.length; } - tickToNext(step: number = 1, doTick?: (elapsed: number) => void, tickOptions?: { - processNewMacroTasksSynchronously: boolean - }) { + tickToNext( + step: number = 1, + doTick?: (elapsed: number) => void, + tickOptions?: { + processNewMacroTasksSynchronously: boolean; + }, + ) { if (this._schedulerQueue.length < step) { return; } @@ -190,18 +200,22 @@ class Scheduler { this.tick(targetTask.endTime - startTime, doTick, tickOptions); } - tick(millis: number = 0, doTick?: (elapsed: number) => void, tickOptions?: { - processNewMacroTasksSynchronously: boolean - }): void { + tick( + millis: number = 0, + doTick?: (elapsed: number) => void, + tickOptions?: { + processNewMacroTasksSynchronously: boolean; + }, + ): void { let finalTime = this._currentTickTime + millis; let lastCurrentTime = 0; tickOptions = Object.assign({processNewMacroTasksSynchronously: true}, tickOptions); // we need to copy the schedulerQueue so nested timeout // will not be wrongly called in the current tick // https://github.com/angular/angular/issues/33799 - const schedulerQueue = tickOptions.processNewMacroTasksSynchronously ? - this._schedulerQueue : - this._schedulerQueue.slice(); + const schedulerQueue = tickOptions.processNewMacroTasksSynchronously + ? this._schedulerQueue + : this._schedulerQueue.slice(); if (schedulerQueue.length === 0 && doTick) { doTick(millis); return; @@ -228,7 +242,9 @@ class Scheduler { doTick(this._currentTickTime - lastCurrentTime); } let retval = current.func.apply( - global, current.isRequestAnimationFrame ? [this._currentTickTime] : current.args); + global, + current.isRequestAnimationFrame ? [this._currentTickTime] : current.args, + ); if (!retval) { // Uncaught exception in the current scheduled function. Stop processing the queue. break; @@ -237,7 +253,7 @@ class Scheduler { // check is there any requeue periodic entry is added in // current loop, if there is, we need to add to current loop if (!tickOptions.processNewMacroTasksSynchronously) { - this._currentTickRequeuePeriodicEntries.forEach(newEntry => { + this._currentTickRequeuePeriodicEntries.forEach((newEntry) => { let i = 0; for (; i < schedulerQueue.length; i++) { const currentEntry = schedulerQueue[i]; @@ -297,14 +313,18 @@ class Scheduler { count++; if (count > limit) { throw new Error( - 'flush failed after reaching the limit of ' + limit + - ' tasks. Does your code use a polling timeout?'); + 'flush failed after reaching the limit of ' + + limit + + ' tasks. Does your code use a polling timeout?', + ); } // flush only non-periodic timers. // If the only remaining tasks are periodic(or requestAnimationFrame), finish flushing. - if (this._schedulerQueue.filter(task => !task.isPeriodic && !task.isRequestAnimationFrame) - .length === 0) { + if ( + this._schedulerQueue.filter((task) => !task.isPeriodic && !task.isRequestAnimationFrame) + .length === 0 + ) { break; } @@ -334,9 +354,10 @@ class FakeAsyncTestZoneSpec implements ZoneSpec { private _scheduler: Scheduler = new Scheduler(); private _microtasks: MicroTaskScheduledFunction[] = []; - private _lastError: Error|null = null; - private _uncaughtPromiseErrors: {rejection: any}[] = - (Promise as any)[(Zone as any).__symbol__('uncaughtPromiseErrors')]; + private _lastError: Error | null = null; + private _uncaughtPromiseErrors: {rejection: any}[] = (Promise as any)[ + (Zone as any).__symbol__('uncaughtPromiseErrors') + ]; pendingPeriodicTimers: number[] = []; pendingTimers: number[] = []; @@ -344,8 +365,10 @@ class FakeAsyncTestZoneSpec implements ZoneSpec { private patchDateLocked = false; constructor( - namePrefix: string, private trackPendingRequestAnimationFrame = false, - private macroTaskOptions?: MacroTaskOptions[]) { + namePrefix: string, + private trackPendingRequestAnimationFrame = false, + private macroTaskOptions?: MacroTaskOptions[], + ) { this.name = 'fakeAsyncTestZone for ' + namePrefix; // in case user can't access the construction of FakeAsyncTestSpec // user can also define macroTaskOptions by define a global variable. @@ -354,18 +377,22 @@ class FakeAsyncTestZoneSpec implements ZoneSpec { } } - private _fnAndFlush(fn: Function, completers: {onSuccess?: Function, onError?: Function}): - Function { + private _fnAndFlush( + fn: Function, + completers: {onSuccess?: Function; onError?: Function}, + ): Function { return (...args: any[]): boolean => { fn.apply(global, args); - if (this._lastError === null) { // Success + if (this._lastError === null) { + // Success if (completers.onSuccess != null) { completers.onSuccess.apply(global); } // Flush microtasks only on success. this.flushMicrotasks(); - } else { // Failure + } else { + // Failure if (completers.onError != null) { completers.onError.apply(global); } @@ -392,8 +419,12 @@ class FakeAsyncTestZoneSpec implements ZoneSpec { return () => { // Requeue the timer callback if it's not been canceled. if (this.pendingPeriodicTimers.indexOf(id) !== -1) { - this._scheduler.scheduleFunction( - fn, interval, {args, isPeriodic: true, id, isRequeuePeriodic: true}); + this._scheduler.scheduleFunction(fn, interval, { + args, + isPeriodic: true, + id, + isRequeuePeriodic: true, + }); } }; } @@ -515,9 +546,13 @@ class FakeAsyncTestZoneSpec implements ZoneSpec { FakeAsyncTestZoneSpec.resetDate(); } - tickToNext(steps: number = 1, doTick?: (elapsed: number) => void, tickOptions: { - processNewMacroTasksSynchronously: boolean - } = {processNewMacroTasksSynchronously: true}): void { + tickToNext( + steps: number = 1, + doTick?: (elapsed: number) => void, + tickOptions: { + processNewMacroTasksSynchronously: boolean; + } = {processNewMacroTasksSynchronously: true}, + ): void { if (steps <= 0) { return; } @@ -529,9 +564,13 @@ class FakeAsyncTestZoneSpec implements ZoneSpec { } } - tick(millis: number = 0, doTick?: (elapsed: number) => void, tickOptions: { - processNewMacroTasksSynchronously: boolean - } = {processNewMacroTasksSynchronously: true}): void { + tick( + millis: number = 0, + doTick?: (elapsed: number) => void, + tickOptions: { + processNewMacroTasksSynchronously: boolean; + } = {processNewMacroTasksSynchronously: true}, + ): void { FakeAsyncTestZoneSpec.assertInZone(); this.flushMicrotasks(); this._scheduler.tick(millis, doTick, tickOptions); @@ -599,7 +638,7 @@ class FakeAsyncTestZoneSpec implements ZoneSpec { // should pass additional arguments to callback if have any // currently we know process.nextTick will have such additional // arguments - let additionalArgs: any[]|undefined; + let additionalArgs: any[] | undefined; if (args) { let callbackIndex = (task.data as any).cbIdx; if (typeof args.length === 'number' && args.length > callbackIndex + 1) { @@ -609,37 +648,48 @@ class FakeAsyncTestZoneSpec implements ZoneSpec { this._microtasks.push({ func: task.invoke, args: additionalArgs, - target: task.data && (task.data as any).target + target: task.data && (task.data as any).target, }); break; case 'macroTask': switch (task.source) { case 'setTimeout': task.data!['handleId'] = this._setTimeout( - task.invoke, task.data!['delay']!, - Array.prototype.slice.call((task.data as any)['args'], 2)); + task.invoke, + task.data!['delay']!, + Array.prototype.slice.call((task.data as any)['args'], 2), + ); break; case 'setImmediate': task.data!['handleId'] = this._setTimeout( - task.invoke, 0, Array.prototype.slice.call((task.data as any)['args'], 1)); + task.invoke, + 0, + Array.prototype.slice.call((task.data as any)['args'], 1), + ); break; case 'setInterval': task.data!['handleId'] = this._setInterval( - task.invoke, task.data!['delay']!, - Array.prototype.slice.call((task.data as any)['args'], 2)); + task.invoke, + task.data!['delay']!, + Array.prototype.slice.call((task.data as any)['args'], 2), + ); break; case 'XMLHttpRequest.send': throw new Error( - 'Cannot make XHRs from within a fake async test. Request URL: ' + - (task.data as any)['url']); + 'Cannot make XHRs from within a fake async test. Request URL: ' + + (task.data as any)['url'], + ); case 'requestAnimationFrame': case 'webkitRequestAnimationFrame': case 'mozRequestAnimationFrame': // Simulate a requestAnimationFrame by using a setTimeout with 16 ms. // (60 frames per second) task.data!['handleId'] = this._setTimeout( - task.invoke, 16, (task.data as any)['args'], - this.trackPendingRequestAnimationFrame); + task.invoke, + 16, + (task.data as any)['args'], + this.trackPendingRequestAnimationFrame, + ); break; default: // user can define which macroTask they want to support by passing @@ -684,16 +734,23 @@ class FakeAsyncTestZoneSpec implements ZoneSpec { const macroTaskOption = this.findMacroTaskOption(task); if (macroTaskOption) { const handleId: number = task.data!['handleId']; - return macroTaskOption.isPeriodic ? this._clearInterval(handleId) : - this._clearTimeout(handleId); + return macroTaskOption.isPeriodic + ? this._clearInterval(handleId) + : this._clearTimeout(handleId); } return delegate.cancelTask(target, task); } } onInvoke( - delegate: ZoneDelegate, current: Zone, target: Zone, callback: Function, applyThis: any, - applyArgs?: any[], source?: string): any { + delegate: ZoneDelegate, + current: Zone, + target: Zone, + callback: Function, + applyThis: any, + applyArgs?: any[], + source?: string, + ): any { try { FakeAsyncTestZoneSpec.patchDate(); return delegate.invoke(target, callback, applyThis, applyArgs, source); @@ -717,17 +774,23 @@ class FakeAsyncTestZoneSpec implements ZoneSpec { return null; } - onHandleError(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any): - boolean { + onHandleError( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + error: any, + ): boolean { this._lastError = error; - return false; // Don't propagate error to parent zone. + return false; // Don't propagate error to parent zone. } } let _fakeAsyncTestZoneSpec: any = null; type ProxyZoneSpecType = { - setDelegate(delegateSpec: ZoneSpec): void; getDelegate(): ZoneSpec; resetDelegate(): void; + setDelegate(delegateSpec: ZoneSpec): void; + getDelegate(): ZoneSpec; + resetDelegate(): void; }; function getProxyZoneSpec(): {get(): ProxyZoneSpecType; assertPresent: () => ProxyZoneSpecType} { return Zone && (Zone as any)['ProxyZoneSpec']; @@ -768,12 +831,13 @@ export function resetFakeAsyncZone() { */ export function fakeAsync(fn: Function): (...args: any[]) => any { // Not using an arrow function to preserve context passed from call site - const fakeAsyncFn: any = function(this: unknown, ...args: any[]) { + const fakeAsyncFn: any = function (this: unknown, ...args: any[]) { const ProxyZoneSpec = getProxyZoneSpec(); if (!ProxyZoneSpec) { 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/plugins/proxy'); + 'ProxyZoneSpec is needed for the async() test helper but could not be found. ' + + 'Please make sure that your environment includes zone.js/plugins/proxy', + ); } const proxyZoneSpec = ProxyZoneSpec.assertPresent(); if (Zone.current.get('FakeAsyncTestZoneSpec')) { @@ -803,13 +867,15 @@ export function fakeAsync(fn: Function): (...args: any[]) => any { if (_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length > 0) { throw new Error( - `${_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length} ` + - `periodic timer(s) still in the queue.`); + `${_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.`); + `${_fakeAsyncTestZoneSpec.pendingTimers.length} timer(s) still in the queue.`, + ); } return res; } finally { @@ -885,10 +951,20 @@ export function patchFakeAsyncTest(Zone: ZoneType): void { // constructor params. (Zone as any)['FakeAsyncTestZoneSpec'] = FakeAsyncTestZoneSpec; - Zone.__load_patch('fakeasync', (global: any, Zone: ZoneType, api: _ZonePrivate) => { - (Zone as any)[api.symbol('fakeAsyncTest')] = - {resetFakeAsyncZone, flushMicrotasks, discardPeriodicTasks, tick, flush, fakeAsync}; - }, true); + Zone.__load_patch( + 'fakeasync', + (global: any, Zone: ZoneType, api: _ZonePrivate) => { + (Zone as any)[api.symbol('fakeAsyncTest')] = { + resetFakeAsyncZone, + flushMicrotasks, + discardPeriodicTasks, + tick, + flush, + fakeAsync, + }; + }, + true, + ); patchedTimers = { setTimeout: global.setTimeout, diff --git a/packages/zone.js/lib/zone-spec/long-stack-trace.ts b/packages/zone.js/lib/zone-spec/long-stack-trace.ts index c9ff1f0e5f8bc..18c5447f71439 100644 --- a/packages/zone.js/lib/zone-spec/long-stack-trace.ts +++ b/packages/zone.js/lib/zone-spec/long-stack-trace.ts @@ -41,9 +41,11 @@ export function patchLongStackTrace(Zone: ZoneType): void { // isn't thrown, however it's faster not to actually throw the exception. const error = getStacktraceWithUncaughtError(); const caughtError = getStacktraceWithCaughtError(); - const getStacktrace = error.stack ? - getStacktraceWithUncaughtError : - (caughtError.stack ? getStacktraceWithCaughtError : getStacktraceWithUncaughtError); + const getStacktrace = error.stack + ? getStacktraceWithUncaughtError + : caughtError.stack + ? getStacktraceWithCaughtError + : getStacktraceWithUncaughtError; function getFrames(error: Error): string[] { return error.stack ? error.stack.split(NEWLINE) : []; @@ -68,8 +70,7 @@ export function patchLongStackTrace(Zone: ZoneType): void { for (let i = 0; i < frames.length; i++) { const traceFrames: LongStackTrace = frames[i]; const lastTime = traceFrames.timestamp; - let separator = - `____________________Elapsed ${timestamp - lastTime.getTime()} ms; At: ${lastTime}`; + let separator = `____________________Elapsed ${timestamp - lastTime.getTime()} ms; At: ${lastTime}`; separator = separator.replace(/[^\w\d]/g, '_'); longTrace.push(sepTemplate.replace(SEP_TAG, separator)); addErrorStack(longTrace, traceFrames.error); @@ -91,31 +92,34 @@ export function patchLongStackTrace(Zone: ZoneType): void { return (Error as any).stackTraceLimit > 0; } - type LongStackTraceZoneSpec = ZoneSpec&{longStackTraceLimit: number}; + type LongStackTraceZoneSpec = ZoneSpec & {longStackTraceLimit: number}; (Zone as any)['longStackTraceZoneSpec'] = { name: 'long-stack-trace', - longStackTraceLimit: 10, // Max number of task to keep the stack trace for. + longStackTraceLimit: 10, // Max number of task to keep the stack trace for. // add a getLongStackTrace method in spec to // handle handled reject promise error. - getLongStackTrace: function(error: Error): string | - undefined { - if (!error) { - return undefined; - } - const trace = (error as any)[(Zone as any).__symbol__('currentTaskTrace')]; - if (!trace) { - return error.stack; - } - return renderLongStackTrace(trace, error.stack); - }, - - onScheduleTask: function( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): any { + getLongStackTrace: function (error: Error): string | undefined { + if (!error) { + return undefined; + } + const trace = (error as any)[(Zone as any).__symbol__('currentTaskTrace')]; + if (!trace) { + return error.stack; + } + return renderLongStackTrace(trace, error.stack); + }, + + onScheduleTask: function ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any { if (stackTracesEnabled()) { const currentTask = Zone.currentTask; let trace = - currentTask && currentTask.data && (currentTask.data as any)[creationTrace] || []; + (currentTask && currentTask.data && (currentTask.data as any)[creationTrace]) || []; trace = [new LongStackTrace()].concat(trace); if (trace.length > this.longStackTraceLimit) { trace.length = this.longStackTraceLimit; @@ -135,27 +139,31 @@ export function patchLongStackTrace(Zone: ZoneType): void { return parentZoneDelegate.scheduleTask(targetZone, task); }, - onHandleError: function( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - error: any): boolean { + onHandleError: function ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + error: any, + ): boolean { if (stackTracesEnabled()) { const parentTask = Zone.currentTask || error.task; if (error instanceof Error && parentTask) { - const longStack = - renderLongStackTrace(parentTask.data && parentTask.data[creationTrace], error.stack); + const longStack = renderLongStackTrace( + parentTask.data && parentTask.data[creationTrace], + error.stack, + ); try { error.stack = (error as any).longStack = longStack; - } catch (err) { - } + } catch (err) {} } } return parentZoneDelegate.handleError(targetZone, error); - } + }, }; function captureStackTraces(stackTraces: string[][], count: number): void { if (count > 0) { - stackTraces.push(getFrames((new LongStackTrace()).error)); + stackTraces.push(getFrames(new LongStackTrace().error)); captureStackTraces(stackTraces, count - 1); } } diff --git a/packages/zone.js/lib/zone-spec/proxy.ts b/packages/zone.js/lib/zone-spec/proxy.ts index cd6bcbef48742..a7dcfaeca84a8 100644 --- a/packages/zone.js/lib/zone-spec/proxy.ts +++ b/packages/zone.js/lib/zone-spec/proxy.ts @@ -11,12 +11,12 @@ import {ZoneType} from '../zone-impl'; export class ProxyZoneSpec implements ZoneSpec { name: string = 'ProxyZone'; - private _delegateSpec: ZoneSpec|null = null; + private _delegateSpec: ZoneSpec | null = null; properties: {[k: string]: any} = {'ProxyZoneSpec': this}; - propertyKeys: string[]|null = null; + propertyKeys: string[] | null = null; - lastTaskState: HasTaskState|null = null; + lastTaskState: HasTaskState | null = null; isNeedToTriggerHasTask = false; private tasks: Task[] = []; @@ -36,22 +36,25 @@ export class ProxyZoneSpec implements ZoneSpec { return ProxyZoneSpec.get(); } - constructor(private defaultSpecDelegate: ZoneSpec|null = null) { + constructor(private defaultSpecDelegate: ZoneSpec | null = null) { this.setDelegate(defaultSpecDelegate); } - setDelegate(delegateSpec: ZoneSpec|null) { + setDelegate(delegateSpec: ZoneSpec | null) { const isNewDelegate = this._delegateSpec !== delegateSpec; this._delegateSpec = delegateSpec; this.propertyKeys && this.propertyKeys.forEach((key) => delete this.properties[key]); this.propertyKeys = null; if (delegateSpec && delegateSpec.properties) { this.propertyKeys = Object.keys(delegateSpec.properties); - this.propertyKeys.forEach((k) => this.properties[k] = delegateSpec.properties![k]); + this.propertyKeys.forEach((k) => (this.properties[k] = delegateSpec.properties![k])); } // if a new delegateSpec was set, check if we need to trigger hasTask - if (isNewDelegate && this.lastTaskState && - (this.lastTaskState.macroTask || this.lastTaskState.microTask)) { + if ( + isNewDelegate && + this.lastTaskState && + (this.lastTaskState.macroTask || this.lastTaskState.microTask) + ) { this.isNeedToTriggerHasTask = true; } } @@ -60,7 +63,6 @@ export class ProxyZoneSpec implements ZoneSpec { return this._delegateSpec; } - resetDelegate() { const delegateSpec = this.getDelegate(); this.setDelegate(this.defaultSpecDelegate); @@ -92,12 +94,13 @@ export class ProxyZoneSpec implements ZoneSpec { return ''; } const taskInfo = this.tasks.map((task: Task) => { - const dataInfo = task.data && - Object.keys(task.data) - .map((key: string) => { - return key + ':' + (task.data as any)[key]; - }) - .join(','); + const dataInfo = + task.data && + Object.keys(task.data) + .map((key: string) => { + return key + ':' + (task.data as any)[key]; + }) + .join(','); return `type: ${task.type}, source: ${task.source}, args: {${dataInfo}}`; }); const pendingTasksInfo = '--Pending async tasks are: [' + taskInfo + ']'; @@ -107,8 +110,12 @@ export class ProxyZoneSpec implements ZoneSpec { return pendingTasksInfo; } - onFork(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, zoneSpec: ZoneSpec): - Zone { + onFork( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + zoneSpec: ZoneSpec, + ): Zone { if (this._delegateSpec && this._delegateSpec.onFork) { return this._delegateSpec.onFork(parentZoneDelegate, currentZone, targetZone, zoneSpec); } else { @@ -116,33 +123,57 @@ export class ProxyZoneSpec implements ZoneSpec { } } - onIntercept( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, - source: string): Function { + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + delegate: Function, + source: string, + ): Function { if (this._delegateSpec && this._delegateSpec.onIntercept) { return this._delegateSpec.onIntercept( - parentZoneDelegate, currentZone, targetZone, delegate, source); + parentZoneDelegate, + currentZone, + targetZone, + delegate, + source, + ); } else { return parentZoneDelegate.intercept(targetZone, delegate, source); } } - onInvoke( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, - applyThis: any, applyArgs?: any[], source?: string): any { + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + delegate: Function, + applyThis: any, + applyArgs?: any[], + source?: string, + ): any { this.tryTriggerHasTask(parentZoneDelegate, currentZone, targetZone); if (this._delegateSpec && this._delegateSpec.onInvoke) { return this._delegateSpec.onInvoke( - parentZoneDelegate, currentZone, targetZone, delegate, applyThis, applyArgs, source); + parentZoneDelegate, + currentZone, + targetZone, + delegate, + applyThis, + applyArgs, + source, + ); } else { return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source); } } - onHandleError(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any): - boolean { + onHandleError( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + error: any, + ): boolean { if (this._delegateSpec && this._delegateSpec.onHandleError) { return this._delegateSpec.onHandleError(parentZoneDelegate, currentZone, targetZone, error); } else { @@ -150,8 +181,12 @@ export class ProxyZoneSpec implements ZoneSpec { } } - onScheduleTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - Task { + onScheduleTask( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): Task { if (task.type !== 'eventTask') { this.tasks.push(task); } @@ -163,22 +198,37 @@ export class ProxyZoneSpec implements ZoneSpec { } onInvokeTask( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, - applyThis: any, applyArgs: any): any { + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + applyThis: any, + applyArgs: any, + ): any { if (task.type !== 'eventTask') { this.removeFromTasks(task); } this.tryTriggerHasTask(parentZoneDelegate, currentZone, targetZone); if (this._delegateSpec && this._delegateSpec.onInvokeTask) { return this._delegateSpec.onInvokeTask( - parentZoneDelegate, currentZone, targetZone, task, applyThis, applyArgs); + parentZoneDelegate, + currentZone, + targetZone, + task, + applyThis, + applyArgs, + ); } else { return parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs); } } - onCancelTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any { + onCancelTask( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any { if (task.type !== 'eventTask') { this.removeFromTasks(task); } diff --git a/packages/zone.js/lib/zone-spec/task-tracking.ts b/packages/zone.js/lib/zone-spec/task-tracking.ts index f08fd1d95f13f..b22ec53c715ee 100644 --- a/packages/zone.js/lib/zone-spec/task-tracking.ts +++ b/packages/zone.js/lib/zone-spec/task-tracking.ts @@ -37,16 +37,24 @@ export class TaskTrackingZoneSpec implements ZoneSpec { throw new Error('Unknown task format: ' + type); } - onScheduleTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - Task { + onScheduleTask( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): Task { (task as any)['creationLocation'] = new Error(`Task '${task.type}' from '${task.source}'.`); const tasks = this.getTasksFor(task.type); tasks.push(task); return parentZoneDelegate.scheduleTask(targetZone, task); } - onCancelTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any { + onCancelTask( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any { const tasks = this.getTasksFor(task.type); for (let i = 0; i < tasks.length; i++) { if (tasks[i] == task) { @@ -58,8 +66,13 @@ export class TaskTrackingZoneSpec implements ZoneSpec { } onInvokeTask( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, - applyThis: any, applyArgs: any): any { + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + applyThis: any, + applyArgs: any, + ): any { if (task.type === 'eventTask' || task.data?.isPeriodic) return parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs); const tasks = this.getTasksFor(task.type); diff --git a/packages/zone.js/lib/zone-spec/wtf.ts b/packages/zone.js/lib/zone-spec/wtf.ts index 85bdc6d5382b1..9e96d7c5a7a9e 100644 --- a/packages/zone.js/lib/zone-spec/wtf.ts +++ b/packages/zone.js/lib/zone-spec/wtf.ts @@ -13,7 +13,7 @@ import {ZoneType} from '../zone-impl'; const _global: any = - typeof window === 'object' && window || typeof self === 'object' && self || global; + (typeof window === 'object' && window) || (typeof self === 'object' && self) || global; export function patchWtf(Zone: ZoneType): void { interface Wtf { @@ -36,9 +36,9 @@ export function patchWtf(Zone: ZoneType): void { type WtfEventFn = (...args: any[]) => any; // Detect and setup WTF. - let wtfTrace: WtfTrace|null = null; - let wtfEvents: WtfEvents|null = null; - const wtfEnabled: boolean = (function(): boolean { + let wtfTrace: WtfTrace | null = null; + let wtfEvents: WtfEvents | null = null; + const wtfEnabled: boolean = (function (): boolean { const wtf: Wtf = _global['wtf']; if (wtf) { wtfTrace = wtf.trace; @@ -53,77 +53,107 @@ export function patchWtf(Zone: ZoneType): void { class WtfZoneSpec implements ZoneSpec { name: string = 'WTF'; - static forkInstance = - wtfEnabled ? wtfEvents!.createInstance('Zone:fork(ascii zone, ascii newZone)') : null; + static forkInstance = wtfEnabled + ? wtfEvents!.createInstance('Zone:fork(ascii zone, ascii newZone)') + : null; static scheduleInstance: {[key: string]: WtfEventFn} = {}; static cancelInstance: {[key: string]: WtfEventFn} = {}; static invokeScope: {[key: string]: WtfEventFn} = {}; static invokeTaskScope: {[key: string]: WtfEventFn} = {}; onFork( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - zoneSpec: ZoneSpec): Zone { + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + zoneSpec: ZoneSpec, + ): Zone { const retValue = parentZoneDelegate.fork(targetZone, zoneSpec); WtfZoneSpec.forkInstance!(zonePathName(targetZone), retValue.name); return retValue; } onInvoke( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, - applyThis: any, applyArgs?: any[], source?: string): any { + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + delegate: Function, + applyThis: any, + applyArgs?: any[], + source?: string, + ): any { const src = source || 'unknown'; let scope = WtfZoneSpec.invokeScope[src]; if (!scope) { - scope = WtfZoneSpec.invokeScope[src] = - wtfEvents!.createScope(`Zone:invoke:${source}(ascii zone)`); + scope = WtfZoneSpec.invokeScope[src] = wtfEvents!.createScope( + `Zone:invoke:${source}(ascii zone)`, + ); } return wtfTrace!.leaveScope( - scope(zonePathName(targetZone)), - parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source)); + scope(zonePathName(targetZone)), + parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source), + ); } - onHandleError( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - error: any): boolean { + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + error: any, + ): boolean { return parentZoneDelegate.handleError(targetZone, error); } onScheduleTask( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): any { + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any { const key = task.type + ':' + task.source; let instance = WtfZoneSpec.scheduleInstance[key]; if (!instance) { - instance = WtfZoneSpec.scheduleInstance[key] = - wtfEvents!.createInstance(`Zone:schedule:${key}(ascii zone, any data)`); + instance = WtfZoneSpec.scheduleInstance[key] = wtfEvents!.createInstance( + `Zone:schedule:${key}(ascii zone, any data)`, + ); } const retValue = parentZoneDelegate.scheduleTask(targetZone, task); instance(zonePathName(targetZone), shallowObj(task.data, 2)); return retValue; } - onInvokeTask( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, - applyThis?: any, applyArgs?: any[]): any { + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + applyThis?: any, + applyArgs?: any[], + ): any { const source = task.source; let scope = WtfZoneSpec.invokeTaskScope[source]; if (!scope) { - scope = WtfZoneSpec.invokeTaskScope[source] = - wtfEvents!.createScope(`Zone:invokeTask:${source}(ascii zone)`); + scope = WtfZoneSpec.invokeTaskScope[source] = wtfEvents!.createScope( + `Zone:invokeTask:${source}(ascii zone)`, + ); } return wtfTrace!.leaveScope( - scope(zonePathName(targetZone)), - parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs)); + scope(zonePathName(targetZone)), + parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs), + ); } - onCancelTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any { + onCancelTask( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any { const key = task.source; let instance = WtfZoneSpec.cancelInstance[key]; if (!instance) { - instance = WtfZoneSpec.cancelInstance[key] = - wtfEvents!.createInstance(`Zone:cancel:${key}(ascii zone, any options)`); + instance = WtfZoneSpec.cancelInstance[key] = wtfEvents!.createInstance( + `Zone:cancel:${key}(ascii zone, any options)`, + ); } const retValue = parentZoneDelegate.cancelTask(targetZone, task); instance(zonePathName(targetZone), shallowObj(task.data, 2)); @@ -131,7 +161,7 @@ export function patchWtf(Zone: ZoneType): void { } } - function shallowObj(obj: {[k: string]: any}|undefined, depth: number): any { + function shallowObj(obj: {[k: string]: any} | undefined, depth: number): any { if (!obj || !depth) return null; const out: {[k: string]: any} = {}; for (const key in obj) { diff --git a/packages/zone.js/lib/zone.configurations.api.ts b/packages/zone.js/lib/zone.configurations.api.ts index fd0d3e92ef197..2f9a0d706c6e3 100644 --- a/packages/zone.js/lib/zone.configurations.api.ts +++ b/packages/zone.js/lib/zone.configurations.api.ts @@ -607,7 +607,7 @@ declare global { * previously. When `__Zone_ignore_on_properties` is setup, we should not see those properties * on targets. */ - __Zone_ignore_on_properties?: {target: any; ignoreProperties: string[];}[]; + __Zone_ignore_on_properties?: {target: any; ignoreProperties: string[]}[]; /** * Define the event names of the passive listeners. diff --git a/packages/zone.js/lib/zone.ts b/packages/zone.js/lib/zone.ts index bc59e66f94ed0..f94dd8a373883 100644 --- a/packages/zone.js/lib/zone.ts +++ b/packages/zone.js/lib/zone.ts @@ -6,7 +6,26 @@ * found in the LICENSE file at https://angular.io/license */ -import {__symbol__, EventTask as _EventTask, HasTaskState as _HasTaskState, initZone, MacroTask as _MacroTask, MicroTask as _MicroTask, PatchFn, Task as _Task, TaskData as _TaskData, TaskState as _TaskState, TaskType as _TaskType, UncaughtPromiseError as _UncaughtPromiseError, Zone as _Zone, ZoneDelegate as _ZoneDelegate, ZoneFrame, ZonePrivate, ZoneSpec as _ZoneSpec, ZoneType as _ZoneType} from './zone-impl'; +import { + __symbol__, + EventTask as _EventTask, + HasTaskState as _HasTaskState, + initZone, + MacroTask as _MacroTask, + MicroTask as _MicroTask, + PatchFn, + Task as _Task, + TaskData as _TaskData, + TaskState as _TaskState, + TaskType as _TaskType, + UncaughtPromiseError as _UncaughtPromiseError, + Zone as _Zone, + ZoneDelegate as _ZoneDelegate, + ZoneFrame, + ZonePrivate, + ZoneSpec as _ZoneSpec, + ZoneType as _ZoneType, +} from './zone-impl'; declare global { const Zone: ZoneType; diff --git a/packages/zone.js/rollup.config.js b/packages/zone.js/rollup.config.js index a2956fee3814a..efc8abc78b727 100644 --- a/packages/zone.js/rollup.config.js +++ b/packages/zone.js/rollup.config.js @@ -6,9 +6,9 @@ const MagicString = require('magic-string'); let version = ''; if (bazel_version_file) { const versionTag = require('fs') - .readFileSync(bazel_version_file, {encoding: 'utf-8'}) - .split('\n') - .find((s) => s.startsWith('STABLE_PROJECT_VERSION')); + .readFileSync(bazel_version_file, {encoding: 'utf-8'}) + .split('\n') + .find((s) => s.startsWith('STABLE_PROJECT_VERSION')); // Don't assume STABLE_PROJECT_VERSION exists if (versionTag) { version = versionTag.split(' ')[1].trim(); diff --git a/packages/zone.js/sauce-evergreen.conf.js b/packages/zone.js/sauce-evergreen.conf.js index a6c455fe4c665..ee96241a6b08f 100644 --- a/packages/zone.js/sauce-evergreen.conf.js +++ b/packages/zone.js/sauce-evergreen.conf.js @@ -1,6 +1,6 @@ // Sauce configuration -module.exports = function(config, ignoredLaunchers) { +module.exports = function (config, ignoredLaunchers) { // The WS server is not available with Sauce config.files.unshift('test/saucelabs.js'); @@ -13,20 +13,20 @@ module.exports = function(config, ignoredLaunchers) { appiumVersion: '1.9.1', platformName: 'Android', deviceName: 'Android GoogleAPI Emulator', - platformVersion: '8.0' - } + platformVersion: '8.0', + }, }; var customLaunchers = {}; if (!ignoredLaunchers) { customLaunchers = basicLaunchers; } else { - Object.keys(basicLaunchers).forEach(function(key) { - if (ignoredLaunchers - .filter(function(ignore) { - return ignore === key; - }) - .length === 0) { + Object.keys(basicLaunchers).forEach(function (key) { + if ( + ignoredLaunchers.filter(function (ignore) { + return ignore === key; + }).length === 0 + ) { customLaunchers[key] = basicLaunchers[key]; } }); @@ -45,8 +45,8 @@ module.exports = function(config, ignoredLaunchers) { 'selenium-version': '3.4.0', 'command-timeout': 600, 'idle-timeout': 600, - 'max-duration': 5400 - } + 'max-duration': 5400, + }, }, customLaunchers: customLaunchers, @@ -57,12 +57,12 @@ module.exports = function(config, ignoredLaunchers) { singleRun: true, - plugins: ['karma-*'] + plugins: ['karma-*'], }); if (process.env.TRAVIS) { config.sauceLabs.build = - 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')'; + 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')'; config.sauceLabs.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER; process.env.SAUCE_ACCESS_KEY = process.env.SAUCE_ACCESS_KEY.split('').reverse().join(''); diff --git a/packages/zone.js/sauce-selenium3.conf.js b/packages/zone.js/sauce-selenium3.conf.js index 0141e88089e06..4500358c4c6fe 100644 --- a/packages/zone.js/sauce-selenium3.conf.js +++ b/packages/zone.js/sauce-selenium3.conf.js @@ -1,14 +1,22 @@ // Sauce configuration with Welenium drivers 3+ -module.exports = function(config) { +module.exports = function (config) { // The WS server is not available with Sauce config.files.unshift('test/saucelabs.js'); var customLaunchers = { - 'SL_CHROME60': - {base: 'SauceLabs', browserName: 'Chrome', platform: 'Windows 10', version: '60.0'}, - 'SL_SAFARI11': - {base: 'SauceLabs', browserName: 'safari', platform: 'macOS 10.13', version: '11.1'}, + 'SL_CHROME60': { + base: 'SauceLabs', + browserName: 'Chrome', + platform: 'Windows 10', + version: '60.0', + }, + 'SL_SAFARI11': { + base: 'SauceLabs', + browserName: 'safari', + platform: 'macOS 10.13', + version: '11.1', + }, }; config.set({ @@ -24,8 +32,8 @@ module.exports = function(config) { 'selenium-version': '3.5.0', 'command-timeout': 600, 'idle-timeout': 600, - 'max-duration': 5400 - } + 'max-duration': 5400, + }, }, customLaunchers: customLaunchers, @@ -36,12 +44,12 @@ module.exports = function(config) { singleRun: true, - plugins: ['karma-*'] + plugins: ['karma-*'], }); if (process.env.TRAVIS) { config.sauceLabs.build = - 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')'; + 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')'; config.sauceLabs.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER; process.env.SAUCE_ACCESS_KEY = process.env.SAUCE_ACCESS_KEY.split('').reverse().join(''); diff --git a/packages/zone.js/sauce.conf.js b/packages/zone.js/sauce.conf.js index ac4f5c00eb85b..8dfca72ec5e60 100644 --- a/packages/zone.js/sauce.conf.js +++ b/packages/zone.js/sauce.conf.js @@ -1,6 +1,6 @@ // Sauce configuration -module.exports = function(config, ignoredLaunchers) { +module.exports = function (config, ignoredLaunchers) { // The WS server is not available with Sauce config.files.unshift('test/saucelabs.js'); @@ -17,10 +17,18 @@ module.exports = function(config, ignoredLaunchers) { },*/ //'SL_SAFARI8': // {base: 'SauceLabs', browserName: 'safari', platform: 'OS X 10.10', version: '8.0'}, - 'SL_SAFARI9': - {base: 'SauceLabs', browserName: 'safari', platform: 'OS X 10.11', version: '9.0'}, - 'SL_SAFARI10': - {base: 'SauceLabs', browserName: 'safari', platform: 'OS X 10.11', version: '10.0'}, + 'SL_SAFARI9': { + base: 'SauceLabs', + browserName: 'safari', + platform: 'OS X 10.11', + version: '9.0', + }, + 'SL_SAFARI10': { + base: 'SauceLabs', + browserName: 'safari', + platform: 'OS X 10.11', + version: '10.0', + }, /* no longer supported in SauceLabs 'SL_IOS7': { @@ -42,13 +50,13 @@ module.exports = function(config, ignoredLaunchers) { base: 'SauceLabs', browserName: 'MicrosoftEdge', platform: 'Windows 10', - version: '14.14393' + version: '14.14393', }, 'SL_MSEDGE15': { base: 'SauceLabs', browserName: 'MicrosoftEdge', platform: 'Windows 10', - version: '15.15063' + version: '15.15063', }, /* fix issue #584, Android 4.1~4.3 are not supported @@ -80,20 +88,20 @@ module.exports = function(config, ignoredLaunchers) { appiumVersion: '1.12.1', platformName: 'Android', deviceName: 'Android GoogleAPI Emulator', - platformVersion: '8.0' - } + platformVersion: '8.0', + }, }; var customLaunchers = {}; if (!ignoredLaunchers) { customLaunchers = basicLaunchers; } else { - Object.keys(basicLaunchers).forEach(function(key) { - if (ignoredLaunchers - .filter(function(ignore) { - return ignore === key; - }) - .length === 0) { + Object.keys(basicLaunchers).forEach(function (key) { + if ( + ignoredLaunchers.filter(function (ignore) { + return ignore === key; + }).length === 0 + ) { customLaunchers[key] = basicLaunchers[key]; } }); @@ -112,8 +120,8 @@ module.exports = function(config, ignoredLaunchers) { 'selenium-version': '2.53.0', 'command-timeout': 600, 'idle-timeout': 600, - 'max-duration': 5400 - } + 'max-duration': 5400, + }, }, customLaunchers: customLaunchers, @@ -124,12 +132,12 @@ module.exports = function(config, ignoredLaunchers) { singleRun: true, - plugins: ['karma-*'] + plugins: ['karma-*'], }); if (process.env.TRAVIS) { config.sauceLabs.build = - 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')'; + 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')'; config.sauceLabs.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER; process.env.SAUCE_ACCESS_KEY = process.env.SAUCE_ACCESS_KEY.split('').reverse().join(''); diff --git a/packages/zone.js/sauce.es2015.conf.js b/packages/zone.js/sauce.es2015.conf.js index dd051f730b4ef..5b56979e6c901 100644 --- a/packages/zone.js/sauce.es2015.conf.js +++ b/packages/zone.js/sauce.es2015.conf.js @@ -1,6 +1,6 @@ // Sauce configuration -module.exports = function(config, ignoredLaunchers) { +module.exports = function (config, ignoredLaunchers) { // The WS server is not available with Sauce config.files.unshift('test/saucelabs.js'); @@ -12,12 +12,12 @@ module.exports = function(config, ignoredLaunchers) { if (!ignoredLaunchers) { customLaunchers = basicLaunchers; } else { - Object.keys(basicLaunchers).forEach(function(key) { - if (ignoredLaunchers - .filter(function(ignore) { - return ignore === key; - }) - .length === 0) { + Object.keys(basicLaunchers).forEach(function (key) { + if ( + ignoredLaunchers.filter(function (ignore) { + return ignore === key; + }).length === 0 + ) { customLaunchers[key] = basicLaunchers[key]; } }); @@ -36,8 +36,8 @@ module.exports = function(config, ignoredLaunchers) { 'selenium-version': '2.53.0', 'command-timeout': 600, 'idle-timeout': 600, - 'max-duration': 5400 - } + 'max-duration': 5400, + }, }, customLaunchers: customLaunchers, @@ -48,12 +48,12 @@ module.exports = function(config, ignoredLaunchers) { singleRun: true, - plugins: ['karma-*'] + plugins: ['karma-*'], }); if (process.env.TRAVIS) { config.sauceLabs.build = - 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')'; + 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')'; config.sauceLabs.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER; process.env.SAUCE_ACCESS_KEY = process.env.SAUCE_ACCESS_KEY.split('').reverse().join(''); diff --git a/packages/zone.js/simple-server.js b/packages/zone.js/simple-server.js index 62e56593f9c42..0b5ac0d8fe0fd 100644 --- a/packages/zone.js/simple-server.js +++ b/packages/zone.js/simple-server.js @@ -31,15 +31,15 @@ function requestHandler(req, res) { return; } - fs.readFile(file, function(err, contents) { + fs.readFile(file, function (err, contents) { if (!err) { res.end(contents); } else { writeNotFound(res); return; - }; + } }); - }; -}; + } +} server = http.createServer(requestHandler).listen(8080); diff --git a/packages/zone.js/test/browser/FileReader.spec.ts b/packages/zone.js/test/browser/FileReader.spec.ts index 6faa2b513393d..1a26e7e6383a0 100644 --- a/packages/zone.js/test/browser/FileReader.spec.ts +++ b/packages/zone.js/test/browser/FileReader.spec.ts @@ -9,101 +9,106 @@ import {ifEnvSupports} from '../test-util'; declare const global: any; -describe('FileReader', ifEnvSupports('FileReader', function() { - let fileReader: FileReader; - let blob: Blob; - const data = 'Hello, World!'; - - // Android 4.3's native browser doesn't implement add/RemoveEventListener for FileReader - function supportsEventTargetFns() { - return !!FileReader.prototype.addEventListener && - !!FileReader.prototype.removeEventListener; - } - (supportsEventTargetFns).message = - 'FileReader#addEventListener and FileReader#removeEventListener'; - - beforeEach(function() { - fileReader = new FileReader(); - - try { - blob = new Blob([data]); - } catch (e) { - // For hosts that don't support the Blob ctor (e.g. Android 4.3's native browser) - const blobBuilder = new global['WebKitBlobBuilder'](); - blobBuilder.append(data); - - blob = blobBuilder.getBlob(); - } - }); - - describe('EventTarget methods', ifEnvSupports(supportsEventTargetFns, function() { - it('should bind addEventListener listeners', function(done) { - const testZone = Zone.current.fork({name: 'TestZone'}); - - testZone.run(function() { - fileReader.addEventListener('load', function() { - expect(Zone.current).toBe(testZone); - expect(fileReader.result).toEqual(data); - done(); - }); - }); - - fileReader.readAsText(blob); - }); - - it('should remove listeners via removeEventListener', function(done) { - const testZone = Zone.current.fork({name: 'TestZone'}); - const listenerSpy = jasmine.createSpy('listener'); - - testZone.run(function() { - fileReader.addEventListener('loadstart', listenerSpy); - fileReader.addEventListener('loadend', function() { - expect(listenerSpy).not.toHaveBeenCalled(); - done(); - }); - }); - - fileReader.removeEventListener('loadstart', listenerSpy); - fileReader.readAsText(blob); - }); - })); - - it('should bind onEventType listeners', function(done) { - const testZone = Zone.current.fork({name: 'TestZone'}); - let listenersCalled = 0; - - testZone.run(function() { - fileReader.onloadstart = function() { - listenersCalled++; - expect(Zone.current).toBe(testZone); - }; - - fileReader.onload = function() { - listenersCalled++; - expect(Zone.current).toBe(testZone); - }; - - fileReader.onloadend = function() { - listenersCalled++; - - expect(Zone.current).toBe(testZone); - expect(fileReader.result).toEqual(data); - expect(listenersCalled).toBe(3); - done(); - }; - }); - - fileReader.readAsText(blob); - }); - - it('should have correct readyState', function(done) { - fileReader.onloadend = function() { - expect(fileReader.readyState).toBe((FileReader).DONE); - done(); - }; - - expect(fileReader.readyState).toBe((FileReader).EMPTY); - - fileReader.readAsText(blob); - }); - })); +describe( + 'FileReader', + ifEnvSupports('FileReader', function () { + let fileReader: FileReader; + let blob: Blob; + const data = 'Hello, World!'; + + // Android 4.3's native browser doesn't implement add/RemoveEventListener for FileReader + function supportsEventTargetFns() { + return !!FileReader.prototype.addEventListener && !!FileReader.prototype.removeEventListener; + } + (supportsEventTargetFns).message = + 'FileReader#addEventListener and FileReader#removeEventListener'; + + beforeEach(function () { + fileReader = new FileReader(); + + try { + blob = new Blob([data]); + } catch (e) { + // For hosts that don't support the Blob ctor (e.g. Android 4.3's native browser) + const blobBuilder = new global['WebKitBlobBuilder'](); + blobBuilder.append(data); + + blob = blobBuilder.getBlob(); + } + }); + + describe( + 'EventTarget methods', + ifEnvSupports(supportsEventTargetFns, function () { + it('should bind addEventListener listeners', function (done) { + const testZone = Zone.current.fork({name: 'TestZone'}); + + testZone.run(function () { + fileReader.addEventListener('load', function () { + expect(Zone.current).toBe(testZone); + expect(fileReader.result).toEqual(data); + done(); + }); + }); + + fileReader.readAsText(blob); + }); + + it('should remove listeners via removeEventListener', function (done) { + const testZone = Zone.current.fork({name: 'TestZone'}); + const listenerSpy = jasmine.createSpy('listener'); + + testZone.run(function () { + fileReader.addEventListener('loadstart', listenerSpy); + fileReader.addEventListener('loadend', function () { + expect(listenerSpy).not.toHaveBeenCalled(); + done(); + }); + }); + + fileReader.removeEventListener('loadstart', listenerSpy); + fileReader.readAsText(blob); + }); + }), + ); + + it('should bind onEventType listeners', function (done) { + const testZone = Zone.current.fork({name: 'TestZone'}); + let listenersCalled = 0; + + testZone.run(function () { + fileReader.onloadstart = function () { + listenersCalled++; + expect(Zone.current).toBe(testZone); + }; + + fileReader.onload = function () { + listenersCalled++; + expect(Zone.current).toBe(testZone); + }; + + fileReader.onloadend = function () { + listenersCalled++; + + expect(Zone.current).toBe(testZone); + expect(fileReader.result).toEqual(data); + expect(listenersCalled).toBe(3); + done(); + }; + }); + + fileReader.readAsText(blob); + }); + + it('should have correct readyState', function (done) { + fileReader.onloadend = function () { + expect(fileReader.readyState).toBe((FileReader).DONE); + done(); + }; + + expect(fileReader.readyState).toBe((FileReader).EMPTY); + + fileReader.readAsText(blob); + }); + }), +); diff --git a/packages/zone.js/test/browser/HTMLImports.spec.ts b/packages/zone.js/test/browser/HTMLImports.spec.ts index 9ba90050e38cd..64aa9c106cfcf 100644 --- a/packages/zone.js/test/browser/HTMLImports.spec.ts +++ b/packages/zone.js/test/browser/HTMLImports.spec.ts @@ -13,17 +13,17 @@ function supportsImports() { } if (supportsImports()) { - describe('HTML Imports', function() { + describe('HTML Imports', function () { const testZone = Zone.current.fork({name: 'test'}); - it('should work with addEventListener', function(done) { + it('should work with addEventListener', function (done) { let link: HTMLLinkElement; - testZone.run(function() { + testZone.run(function () { link = document.createElement('link'); link.rel = 'import'; link.href = 'someUrl'; - link.addEventListener('error', function() { + link.addEventListener('error', function () { expect(Zone.current).toBe(testZone); document.head.removeChild(link); done(); @@ -40,16 +40,15 @@ if (supportsImports()) { } (supportsOnEvents).message = 'Supports HTMLLinkElement#onxxx patching'; - - ifEnvSupports(supportsOnEvents, function() { - it('should work with onerror', function(done) { + ifEnvSupports(supportsOnEvents, function () { + it('should work with onerror', function (done) { let link: HTMLLinkElement; - testZone.run(function() { + testZone.run(function () { link = document.createElement('link'); link.rel = 'import'; link.href = 'anotherUrl'; - link.onerror = function() { + link.onerror = function () { expect(Zone.current).toBe(testZone); document.head.removeChild(link); done(); @@ -59,14 +58,14 @@ if (supportsImports()) { document.head.appendChild(link!); }); - it('should work with onload', function(done) { + it('should work with onload', function (done) { let link: HTMLLinkElement; - testZone.run(function() { + testZone.run(function () { link = document.createElement('link'); link.rel = 'import'; link.href = '/base/angular/packages/zone.js/test/assets/import.html'; - link.onload = function() { + link.onload = function () { expect(Zone.current).toBe(testZone); document.head.removeChild(link); done(); diff --git a/packages/zone.js/test/browser/MediaQuery.spec.ts b/packages/zone.js/test/browser/MediaQuery.spec.ts index 1fd7e110645d7..6ede63935f619 100644 --- a/packages/zone.js/test/browser/MediaQuery.spec.ts +++ b/packages/zone.js/test/browser/MediaQuery.spec.ts @@ -12,15 +12,18 @@ declare const global: any; function supportMediaQuery() { const _global = - typeof window === 'object' && window || typeof self === 'object' && self || global; + (typeof window === 'object' && window) || (typeof self === 'object' && self) || global; return _global['MediaQueryList'] && _global['matchMedia']; } -describe('test mediaQuery patch', ifEnvSupports(supportMediaQuery, () => { - it('test whether addListener is patched', () => { - const mqList = window.matchMedia('min-width:500px'); - if (mqList && mqList['addListener']) { - expect((mqList as any)[zoneSymbol('addListener')]).toBeTruthy(); - } - }); - })); +describe( + 'test mediaQuery patch', + ifEnvSupports(supportMediaQuery, () => { + it('test whether addListener is patched', () => { + const mqList = window.matchMedia('min-width:500px'); + if (mqList && mqList['addListener']) { + expect((mqList as any)[zoneSymbol('addListener')]).toBeTruthy(); + } + }); + }), +); diff --git a/packages/zone.js/test/browser/MutationObserver.spec.ts b/packages/zone.js/test/browser/MutationObserver.spec.ts index ee800e6517679..b2d59e52feec1 100644 --- a/packages/zone.js/test/browser/MutationObserver.spec.ts +++ b/packages/zone.js/test/browser/MutationObserver.spec.ts @@ -9,73 +9,78 @@ import {ifEnvSupports} from '../test-util'; declare const global: any; - -describe('MutationObserver', ifEnvSupports('MutationObserver', function() { - let elt: HTMLDivElement; - - beforeEach(function() { - elt = document.createElement('div'); - document.body.appendChild(elt); - }); - - afterEach(function() { - document.body.removeChild(elt); - }); - - it('should run observers within the zone', function(done) { - const testZone = Zone.current.fork({name: 'test'}); - let ob; - elt = document.createElement('div'); - document.body.appendChild(elt); - - testZone.run(function() { - ob = new MutationObserver(function() { - expect(Zone.current).toBe(testZone); - done(); - }); - - ob.observe(elt, {childList: true}); - }); - - elt.innerHTML = '

hey

'; - }); - - it('should only dequeue upon disconnect if something is observed', function() { - let ob: MutationObserver; - let flag = false; - const elt = document.createElement('div'); - const childZone = Zone.current.fork({ - name: 'test', - onInvokeTask: function() { - flag = true; - } - }); - - childZone.run(function() { - ob = new MutationObserver(function() {}); - }); - - ob!.disconnect(); - expect(flag).toBe(false); - }); - })); - -describe('WebKitMutationObserver', ifEnvSupports('WebKitMutationObserver', function() { - it('should run observers within the zone', function(done) { - const testZone = Zone.current.fork({name: 'test'}); - let elt: HTMLDivElement; - - testZone.run(function() { - elt = document.createElement('div'); - - const ob = new global['WebKitMutationObserver'](function() { - expect(Zone.current).toBe(testZone); - done(); - }); - - ob.observe(elt, {childList: true}); - }); - - elt!.innerHTML = '

hey

'; - }); - })); +describe( + 'MutationObserver', + ifEnvSupports('MutationObserver', function () { + let elt: HTMLDivElement; + + beforeEach(function () { + elt = document.createElement('div'); + document.body.appendChild(elt); + }); + + afterEach(function () { + document.body.removeChild(elt); + }); + + it('should run observers within the zone', function (done) { + const testZone = Zone.current.fork({name: 'test'}); + let ob; + elt = document.createElement('div'); + document.body.appendChild(elt); + + testZone.run(function () { + ob = new MutationObserver(function () { + expect(Zone.current).toBe(testZone); + done(); + }); + + ob.observe(elt, {childList: true}); + }); + + elt.innerHTML = '

hey

'; + }); + + it('should only dequeue upon disconnect if something is observed', function () { + let ob: MutationObserver; + let flag = false; + const elt = document.createElement('div'); + const childZone = Zone.current.fork({ + name: 'test', + onInvokeTask: function () { + flag = true; + }, + }); + + childZone.run(function () { + ob = new MutationObserver(function () {}); + }); + + ob!.disconnect(); + expect(flag).toBe(false); + }); + }), +); + +describe( + 'WebKitMutationObserver', + ifEnvSupports('WebKitMutationObserver', function () { + it('should run observers within the zone', function (done) { + const testZone = Zone.current.fork({name: 'test'}); + let elt: HTMLDivElement; + + testZone.run(function () { + elt = document.createElement('div'); + + const ob = new global['WebKitMutationObserver'](function () { + expect(Zone.current).toBe(testZone); + done(); + }); + + ob.observe(elt, {childList: true}); + }); + + elt!.innerHTML = '

hey

'; + }); + }), +); diff --git a/packages/zone.js/test/browser/Notification.spec.ts b/packages/zone.js/test/browser/Notification.spec.ts index 0d56855b4f838..562628fdd5c77 100644 --- a/packages/zone.js/test/browser/Notification.spec.ts +++ b/packages/zone.js/test/browser/Notification.spec.ts @@ -11,16 +11,20 @@ import {ifEnvSupports} from '../test-util'; declare const window: any; function notificationSupport() { - const desc = window['Notification'] && - Object.getOwnPropertyDescriptor(window['Notification'].prototype, 'onerror'); + const desc = + window['Notification'] && + Object.getOwnPropertyDescriptor(window['Notification'].prototype, 'onerror'); return window['Notification'] && window['Notification'].prototype && desc && desc.configurable; } (notificationSupport).message = 'Notification Support'; -describe('Notification API', ifEnvSupports(notificationSupport, function() { - it('Notification API should be patched by Zone', () => { - const Notification = window['Notification']; - expect(Notification.prototype[zoneSymbol('addEventListener')]).toBeTruthy(); - }); - })); +describe( + 'Notification API', + ifEnvSupports(notificationSupport, function () { + it('Notification API should be patched by Zone', () => { + const Notification = window['Notification']; + expect(Notification.prototype[zoneSymbol('addEventListener')]).toBeTruthy(); + }); + }), +); diff --git a/packages/zone.js/test/browser/WebSocket.spec.ts b/packages/zone.js/test/browser/WebSocket.spec.ts index ac9ff024d1125..8bd09c58fc12c 100644 --- a/packages/zone.js/test/browser/WebSocket.spec.ts +++ b/packages/zone.js/test/browser/WebSocket.spec.ts @@ -14,131 +14,151 @@ const TIMEOUT = 5000; if (!window['saucelabs']) { // sauceLabs does not support WebSockets; skip these tests - xdescribe('WebSocket', ifEnvSupports('WebSocket', function() { - let socket: WebSocket; - const TEST_SERVER_URL = 'ws://localhost:8001'; - const testZone = Zone.current.fork({name: 'test'}); - - - beforeEach(function(done) { - socket = new WebSocket(TEST_SERVER_URL); - socket.addEventListener('open', function() { - done(); - }); - socket.addEventListener('error', function() { - fail( - 'Can\'t establish socket to ' + TEST_SERVER_URL + - '! do you have test/ws-server.js running?'); - done(); - }); - }, TIMEOUT); - - afterEach(function(done) { - socket.addEventListener('close', function() { - done(); - }); - socket.close(); - }, TIMEOUT); - - xit('should be patched in a Web Worker', done => { - const worker = new Worker('/base/test/ws-webworker-context.js'); - worker.onmessage = (e: MessageEvent) => { - if (e.data !== 'pass' && e.data !== 'fail') { - fail(`web worker ${e.data}`); - return; - } - expect(e.data).toBe('pass'); - done(); - }; - }, 10000); - - it('should work with addEventListener', function(done) { - testZone.run(function() { - socket.addEventListener('message', function(event) { - expect(Zone.current).toBe(testZone); - expect(event['data']).toBe('hi'); - done(); - }); - }); - socket.send('hi'); - }, TIMEOUT); - - - it('should respect removeEventListener', function(done) { - let log = ''; - - function logOnMessage() { - log += 'a'; - - expect(log).toEqual('a'); - - socket.removeEventListener('message', logOnMessage); - socket.send('hi'); - - setTimeout(function() { - expect(log).toEqual('a'); - done(); - }, 10); - } - - socket.addEventListener('message', logOnMessage); - socket.send('hi'); - }, TIMEOUT); - - - it('should work with onmessage', function(done) { - testZone.run(function() { - socket.onmessage = function(contents) { - expect(Zone.current).toBe(testZone); - expect(contents.data).toBe('hi'); - done(); - }; - }); - socket.send('hi'); - }, TIMEOUT); - - - it('should only allow one onmessage handler', function(done) { - let log = ''; - - socket.onmessage = function() { - log += 'a'; - expect(log).toEqual('b'); - done(); - }; - - socket.onmessage = function() { - log += 'b'; - expect(log).toEqual('b'); - done(); - }; - - socket.send('hi'); - }, TIMEOUT); - - - it('should handler removing onmessage', function(done) { - let log = ''; - - socket.onmessage = function() { - log += 'a'; - }; - - socket.onmessage = null as any; - - socket.send('hi'); - - setTimeout(function() { - expect(log).toEqual(''); - done(); - }, 100); - }, TIMEOUT); - - it('should have constants', function() { - expect(Object.keys(WebSocket)).toContain('CONNECTING'); - expect(Object.keys(WebSocket)).toContain('OPEN'); - expect(Object.keys(WebSocket)).toContain('CLOSING'); - expect(Object.keys(WebSocket)).toContain('CLOSED'); - }); - })); + xdescribe( + 'WebSocket', + ifEnvSupports('WebSocket', function () { + let socket: WebSocket; + const TEST_SERVER_URL = 'ws://localhost:8001'; + const testZone = Zone.current.fork({name: 'test'}); + + beforeEach(function (done) { + socket = new WebSocket(TEST_SERVER_URL); + socket.addEventListener('open', function () { + done(); + }); + socket.addEventListener('error', function () { + fail( + "Can't establish socket to " + + TEST_SERVER_URL + + '! do you have test/ws-server.js running?', + ); + done(); + }); + }, TIMEOUT); + + afterEach(function (done) { + socket.addEventListener('close', function () { + done(); + }); + socket.close(); + }, TIMEOUT); + + xit('should be patched in a Web Worker', (done) => { + const worker = new Worker('/base/test/ws-webworker-context.js'); + worker.onmessage = (e: MessageEvent) => { + if (e.data !== 'pass' && e.data !== 'fail') { + fail(`web worker ${e.data}`); + return; + } + expect(e.data).toBe('pass'); + done(); + }; + }, 10000); + + it( + 'should work with addEventListener', + function (done) { + testZone.run(function () { + socket.addEventListener('message', function (event) { + expect(Zone.current).toBe(testZone); + expect(event['data']).toBe('hi'); + done(); + }); + }); + socket.send('hi'); + }, + TIMEOUT, + ); + + it( + 'should respect removeEventListener', + function (done) { + let log = ''; + + function logOnMessage() { + log += 'a'; + + expect(log).toEqual('a'); + + socket.removeEventListener('message', logOnMessage); + socket.send('hi'); + + setTimeout(function () { + expect(log).toEqual('a'); + done(); + }, 10); + } + + socket.addEventListener('message', logOnMessage); + socket.send('hi'); + }, + TIMEOUT, + ); + + it( + 'should work with onmessage', + function (done) { + testZone.run(function () { + socket.onmessage = function (contents) { + expect(Zone.current).toBe(testZone); + expect(contents.data).toBe('hi'); + done(); + }; + }); + socket.send('hi'); + }, + TIMEOUT, + ); + + it( + 'should only allow one onmessage handler', + function (done) { + let log = ''; + + socket.onmessage = function () { + log += 'a'; + expect(log).toEqual('b'); + done(); + }; + + socket.onmessage = function () { + log += 'b'; + expect(log).toEqual('b'); + done(); + }; + + socket.send('hi'); + }, + TIMEOUT, + ); + + it( + 'should handler removing onmessage', + function (done) { + let log = ''; + + socket.onmessage = function () { + log += 'a'; + }; + + socket.onmessage = null as any; + + socket.send('hi'); + + setTimeout(function () { + expect(log).toEqual(''); + done(); + }, 100); + }, + TIMEOUT, + ); + + it('should have constants', function () { + expect(Object.keys(WebSocket)).toContain('CONNECTING'); + expect(Object.keys(WebSocket)).toContain('OPEN'); + expect(Object.keys(WebSocket)).toContain('CLOSING'); + expect(Object.keys(WebSocket)).toContain('CLOSED'); + }); + }), + ); } diff --git a/packages/zone.js/test/browser/Worker.spec.ts b/packages/zone.js/test/browser/Worker.spec.ts index a4c5f66c03af3..c9a0ee1049865 100644 --- a/packages/zone.js/test/browser/Worker.spec.ts +++ b/packages/zone.js/test/browser/Worker.spec.ts @@ -23,17 +23,22 @@ function workerSupport() { (workerSupport as any).message = 'Worker Support'; -xdescribe('Worker API', ifEnvSupports(workerSupport, function() { - it('Worker API should be patched by Zone', asyncTest((done: Function) => { - const zone: Zone = Zone.current.fork({name: 'worker'}); - zone.run(() => { - const worker = - new Worker('/base/angular/packages/zone.js/test/assets/worker.js'); - worker.onmessage = function(evt: MessageEvent) { - expect(evt.data).toEqual('worker'); - expect(Zone.current.name).toEqual('worker'); - done(); - }; - }); - }, Zone.root)); - })); +xdescribe( + 'Worker API', + ifEnvSupports(workerSupport, function () { + it( + 'Worker API should be patched by Zone', + asyncTest((done: Function) => { + const zone: Zone = Zone.current.fork({name: 'worker'}); + zone.run(() => { + const worker = new Worker('/base/angular/packages/zone.js/test/assets/worker.js'); + worker.onmessage = function (evt: MessageEvent) { + expect(evt.data).toEqual('worker'); + expect(Zone.current.name).toEqual('worker'); + done(); + }; + }); + }, Zone.root), + ); + }), +); diff --git a/packages/zone.js/test/browser/XMLHttpRequest.spec.ts b/packages/zone.js/test/browser/XMLHttpRequest.spec.ts index 3fdc7409b6887..8ea3cbf775070 100644 --- a/packages/zone.js/test/browser/XMLHttpRequest.spec.ts +++ b/packages/zone.js/test/browser/XMLHttpRequest.spec.ts @@ -6,18 +6,23 @@ * found in the LICENSE file at https://angular.io/license */ -import {ifEnvSupports, ifEnvSupportsWithDone, supportPatchXHROnProperty, zoneSymbol} from '../test-util'; +import { + ifEnvSupports, + ifEnvSupportsWithDone, + supportPatchXHROnProperty, + zoneSymbol, +} from '../test-util'; declare const global: any; const wtfMock = global.wtfMock; -describe('XMLHttpRequest', function() { +describe('XMLHttpRequest', function () { let testZone: Zone; beforeEach(() => { testZone = Zone.current.fork({name: 'test'}); }); - it('should intercept XHRs and treat them as MacroTasks', function(done) { + it('should intercept XHRs and treat them as MacroTasks', function (done) { let req: XMLHttpRequest; let onStable: any; const testZoneWithWtf = Zone.current.fork((Zone as any)['wtfZoneSpec']).fork({ @@ -26,42 +31,51 @@ describe('XMLHttpRequest', function() { if (!hasTask.macroTask) { onStable && onStable(); } - } + }, }); - testZoneWithWtf.run(() => { - req = new XMLHttpRequest(); - const logs: string[] = []; - req.onload = () => { - logs.push('onload'); - }; - onStable = function() { - expect(wtfMock.log[wtfMock.log.length - 2]) - .toEqual('> Zone:invokeTask:XMLHttpRequest.send("::ProxyZone::WTF::TestZone")'); - expect(wtfMock.log[wtfMock.log.length - 1]) - .toEqual('< Zone:invokeTask:XMLHttpRequest.send'); - if (supportPatchXHROnProperty()) { - expect(wtfMock.log[wtfMock.log.length - 3]) - .toMatch(/\< Zone\:invokeTask.*addEventListener\:load/); - expect(wtfMock.log[wtfMock.log.length - 4]) - .toMatch(/\> Zone\:invokeTask.*addEventListener\:load/); - } - // if browser can patch onload - if ((req as any)[zoneSymbol('loadfalse')]) { - expect(logs).toEqual(['onload']); - } - onStable = null; - done(); - }; + testZoneWithWtf.run( + () => { + req = new XMLHttpRequest(); + const logs: string[] = []; + req.onload = () => { + logs.push('onload'); + }; + onStable = function () { + expect(wtfMock.log[wtfMock.log.length - 2]).toEqual( + '> Zone:invokeTask:XMLHttpRequest.send("::ProxyZone::WTF::TestZone")', + ); + expect(wtfMock.log[wtfMock.log.length - 1]).toEqual( + '< Zone:invokeTask:XMLHttpRequest.send', + ); + if (supportPatchXHROnProperty()) { + expect(wtfMock.log[wtfMock.log.length - 3]).toMatch( + /\< Zone\:invokeTask.*addEventListener\:load/, + ); + expect(wtfMock.log[wtfMock.log.length - 4]).toMatch( + /\> Zone\:invokeTask.*addEventListener\:load/, + ); + } + // if browser can patch onload + if ((req as any)[zoneSymbol('loadfalse')]) { + expect(logs).toEqual(['onload']); + } + onStable = null; + done(); + }; - req.open('get', '/', true); - req.send(); - const lastScheduled = wtfMock.log[wtfMock.log.length - 1]; - expect(lastScheduled).toMatch('# Zone:schedule:macroTask:XMLHttpRequest.send'); - }, null, undefined, 'unit-test'); + req.open('get', '/', true); + req.send(); + const lastScheduled = wtfMock.log[wtfMock.log.length - 1]; + expect(lastScheduled).toMatch('# Zone:schedule:macroTask:XMLHttpRequest.send'); + }, + null, + undefined, + 'unit-test', + ); }); - it('should not trigger Zone callback of internal onreadystatechange', function(done) { + it('should not trigger Zone callback of internal onreadystatechange', function (done) { const scheduleSpy = jasmine.createSpy('schedule'); const xhrZone = Zone.current.fork({ name: 'xhr', @@ -70,12 +84,12 @@ describe('XMLHttpRequest', function() { scheduleSpy(task.source); } return delegate.scheduleTask(targetZone, task); - } + }, }); xhrZone.run(() => { const req = new XMLHttpRequest(); - req.onload = function() { + req.onload = function () { expect(Zone.current.name).toEqual('xhr'); if (supportPatchXHROnProperty()) { expect(scheduleSpy).toHaveBeenCalled(); @@ -87,12 +101,12 @@ describe('XMLHttpRequest', function() { }); }); - it('should work with onreadystatechange', function(done) { + it('should work with onreadystatechange', function (done) { let req: XMLHttpRequest; - testZone.run(function() { + testZone.run(function () { req = new XMLHttpRequest(); - req.onreadystatechange = function() { + req.onreadystatechange = function () { // Make sure that the wrapCallback will only be called once req.onreadystatechange = null as any; expect(Zone.current).toBe(testZone); @@ -104,25 +118,26 @@ describe('XMLHttpRequest', function() { req!.send(); }); - it('should run onload listeners before internal readystatechange', function(done) { + it('should run onload listeners before internal readystatechange', function (done) { const logs: string[] = []; const xhrZone = Zone.current.fork({ name: 'xhr', onInvokeTask: (delegate, curr, target, task, applyThis, applyArgs) => { logs.push('invokeTask ' + task.source); return delegate.invokeTask(target, task, applyThis, applyArgs); - } + }, }); - xhrZone.run(function() { + xhrZone.run(function () { const req = new XMLHttpRequest(); - req.onload = function() { + req.onload = function () { logs.push('onload'); (window as any)[Zone.__symbol__('setTimeout')](() => { expect(logs).toEqual([ - 'invokeTask XMLHttpRequest.addEventListener:load', 'onload', - 'invokeTask XMLHttpRequest.send' - ]) + 'invokeTask XMLHttpRequest.addEventListener:load', + 'onload', + 'invokeTask XMLHttpRequest.send', + ]); done(); }); }; @@ -131,10 +146,10 @@ describe('XMLHttpRequest', function() { }); }); - it('should invoke xhr task even onload listener throw error', function(done) { + it('should invoke xhr task even onload listener throw error', function (done) { const oriWindowError = window.onerror; const logs: string[] = []; - window.onerror = function(err: any) { + window.onerror = function (err: any) { logs.push(err); }; try { @@ -149,12 +164,12 @@ describe('XMLHttpRequest', function() { logs.push('hasTask ' + hasTaskState.macroTask); } return delegate.hasTask(target, hasTaskState); - } + }, }); - xhrZone.run(function() { + xhrZone.run(function () { const req = new XMLHttpRequest(); - req.onload = function() { + req.onload = function () { logs.push('onload'); throw new Error('test'); }; @@ -166,9 +181,14 @@ describe('XMLHttpRequest', function() { logs.push('onload1'); (window as any)[Zone.__symbol__('setTimeout')](() => { expect(logs).toEqual([ - 'hasTask true', 'invokeTask XMLHttpRequest.addEventListener:load', 'onload', - 'invokeTask XMLHttpRequest.addEventListener:load', 'onload1', - 'invokeTask XMLHttpRequest.send', 'hasTask false', 'Uncaught Error: test' + 'hasTask true', + 'invokeTask XMLHttpRequest.addEventListener:load', + 'onload', + 'invokeTask XMLHttpRequest.addEventListener:load', + 'onload1', + 'invokeTask XMLHttpRequest.send', + 'hasTask false', + 'Uncaught Error: test', ]); window.removeEventListener('unhandledrejection', unhandledRejection); window.onerror = oriWindowError; @@ -183,96 +203,102 @@ describe('XMLHttpRequest', function() { } }); - it('should return null when access ontimeout first time without error', function() { + it('should return null when access ontimeout first time without error', function () { let req: XMLHttpRequest = new XMLHttpRequest(); expect(req.ontimeout).toBe(null); }); - const supportsOnProgress = function() { - return 'onprogress' in (new XMLHttpRequest()); + const supportsOnProgress = function () { + return 'onprogress' in new XMLHttpRequest(); }; (supportsOnProgress).message = 'XMLHttpRequest.onprogress'; - describe('onprogress', ifEnvSupports(supportsOnProgress, function() { - it('should work with onprogress', function(done) { - let req: XMLHttpRequest; - testZone.run(function() { - req = new XMLHttpRequest(); - req.onprogress = function() { - // Make sure that the wrapCallback will only be called once - req.onprogress = null as any; - expect(Zone.current).toBe(testZone); - done(); - }; - req.open('get', '/', true); - }); - - req!.send(); - }); - - it('should allow canceling of an XMLHttpRequest', function(done) { - const spy = jasmine.createSpy('spy'); - let req: XMLHttpRequest; - let pending = false; - - const trackingTestZone = Zone.current.fork({ - name: 'tracking test zone', - onHasTask: - (delegate: ZoneDelegate, current: Zone, target: Zone, - hasTaskState: HasTaskState) => { - if (hasTaskState.change == 'macroTask') { - pending = hasTaskState.macroTask; - } - delegate.hasTask(target, hasTaskState); - } - }); - - trackingTestZone.run(function() { - req = new XMLHttpRequest(); - req.onreadystatechange = function() { - if (req.readyState === XMLHttpRequest.DONE) { - if (req.status !== 0) { - spy(); - } - } - }; - req.open('get', '/', true); - - req.send(); - req.abort(); - }); - - setTimeout(function() { - expect(spy).not.toHaveBeenCalled(); - expect(pending).toEqual(false); - done(); - }, 0); - }); - - it('should allow aborting an XMLHttpRequest after its completed', function(done) { - let req: XMLHttpRequest; - - testZone.run(function() { - req = new XMLHttpRequest(); - req.onreadystatechange = function() { - if (req.readyState === XMLHttpRequest.DONE) { - if (req.status !== 0) { - setTimeout(function() { - req.abort(); - done(); - }, 0); - } - } - }; - req.open('get', '/', true); - - req.send(); - }); - }); - })); - - it('should preserve other setters', function() { + describe( + 'onprogress', + ifEnvSupports(supportsOnProgress, function () { + it('should work with onprogress', function (done) { + let req: XMLHttpRequest; + testZone.run(function () { + req = new XMLHttpRequest(); + req.onprogress = function () { + // Make sure that the wrapCallback will only be called once + req.onprogress = null as any; + expect(Zone.current).toBe(testZone); + done(); + }; + req.open('get', '/', true); + }); + + req!.send(); + }); + + it('should allow canceling of an XMLHttpRequest', function (done) { + const spy = jasmine.createSpy('spy'); + let req: XMLHttpRequest; + let pending = false; + + const trackingTestZone = Zone.current.fork({ + name: 'tracking test zone', + onHasTask: ( + delegate: ZoneDelegate, + current: Zone, + target: Zone, + hasTaskState: HasTaskState, + ) => { + if (hasTaskState.change == 'macroTask') { + pending = hasTaskState.macroTask; + } + delegate.hasTask(target, hasTaskState); + }, + }); + + trackingTestZone.run(function () { + req = new XMLHttpRequest(); + req.onreadystatechange = function () { + if (req.readyState === XMLHttpRequest.DONE) { + if (req.status !== 0) { + spy(); + } + } + }; + req.open('get', '/', true); + + req.send(); + req.abort(); + }); + + setTimeout(function () { + expect(spy).not.toHaveBeenCalled(); + expect(pending).toEqual(false); + done(); + }, 0); + }); + + it('should allow aborting an XMLHttpRequest after its completed', function (done) { + let req: XMLHttpRequest; + + testZone.run(function () { + req = new XMLHttpRequest(); + req.onreadystatechange = function () { + if (req.readyState === XMLHttpRequest.DONE) { + if (req.status !== 0) { + setTimeout(function () { + req.abort(); + done(); + }, 0); + } + } + }; + req.open('get', '/', true); + + req.send(); + }); + }); + }), + ); + + it('should preserve other setters', function () { const req = new XMLHttpRequest(); req.open('get', '/', true); req.send(); @@ -285,26 +311,30 @@ describe('XMLHttpRequest', function() { } }); - it('should work with synchronous XMLHttpRequest', function() { + it('should work with synchronous XMLHttpRequest', function () { const log: HasTaskState[] = []; Zone.current - .fork({ - name: 'sync-xhr-test', - onHasTask: function( - delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState) { - log.push(hasTaskState); - delegate.hasTask(target, hasTaskState); - } - }) - .run(() => { - const req = new XMLHttpRequest(); - req.open('get', '/', false); - req.send(); - }); + .fork({ + name: 'sync-xhr-test', + onHasTask: function ( + delegate: ZoneDelegate, + current: Zone, + target: Zone, + hasTaskState: HasTaskState, + ) { + log.push(hasTaskState); + delegate.hasTask(target, hasTaskState); + }, + }) + .run(() => { + const req = new XMLHttpRequest(); + req.open('get', '/', false); + req.send(); + }); expect(log).toEqual([]); }); - it('should preserve static constants', function() { + it('should preserve static constants', function () { expect(XMLHttpRequest.UNSENT).toEqual(0); expect(XMLHttpRequest.OPENED).toEqual(1); expect(XMLHttpRequest.HEADERS_RECEIVED).toEqual(2); @@ -312,76 +342,73 @@ describe('XMLHttpRequest', function() { expect(XMLHttpRequest.DONE).toEqual(4); }); - it('should work properly when send request multiple times on single xmlRequest instance', - function(done) { - testZone.run(function() { - const req = new XMLHttpRequest(); - req.open('get', '/', true); - req.send(); - req.onload = function() { - req.onload = null as any; - req.open('get', '/', true); - req.onload = function() { - done(); - }; - expect(() => { - req.send(); - }).not.toThrow(); - }; - }); - }); - - it('should keep taskcount correctly when abort was called multiple times before request is done', - function(done) { - testZone.run(function() { - const req = new XMLHttpRequest(); - - req.open('get', '/', true); - req.send(); - - let count = 0; - const listener = function(ev: any) { - if (req.readyState >= 2) { - const isInitial = count++ === 0; - - expect(() => { - // this triggers a synchronous dispatch of the state change event. - req.abort(); - }).not.toThrow(); - - req.removeEventListener('readystatechange', listener); - - if (isInitial) { - done(); - } - } - }; - req.addEventListener('readystatechange', listener); - }); - }); - - it('should close xhr request if error happened when connect', function(done) { - const logs: boolean[] = []; - Zone.current - .fork({ - name: 'xhr', - onHasTask: - (delegate: ZoneDelegate, curr: Zone, target: Zone, taskState: HasTaskState) => { - if (taskState.change === 'macroTask') { - logs.push(taskState.macroTask); - } - return delegate.hasTask(target, taskState); - } - }) - .run(function() { - const req = new XMLHttpRequest(); - req.open('get', 'http://notexists.url', true); + it('should work properly when send request multiple times on single xmlRequest instance', function (done) { + testZone.run(function () { + const req = new XMLHttpRequest(); + req.open('get', '/', true); + req.send(); + req.onload = function () { + req.onload = null as any; + req.open('get', '/', true); + req.onload = function () { + done(); + }; + expect(() => { req.send(); - req.addEventListener('error', () => { - expect(logs).toEqual([true, false]); + }).not.toThrow(); + }; + }); + }); + + it('should keep taskcount correctly when abort was called multiple times before request is done', function (done) { + testZone.run(function () { + const req = new XMLHttpRequest(); + + req.open('get', '/', true); + req.send(); + + let count = 0; + const listener = function (ev: any) { + if (req.readyState >= 2) { + const isInitial = count++ === 0; + + expect(() => { + // this triggers a synchronous dispatch of the state change event. + req.abort(); + }).not.toThrow(); + + req.removeEventListener('readystatechange', listener); + + if (isInitial) { done(); - }); + } + } + }; + req.addEventListener('readystatechange', listener); + }); + }); + + it('should close xhr request if error happened when connect', function (done) { + const logs: boolean[] = []; + Zone.current + .fork({ + name: 'xhr', + onHasTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, taskState: HasTaskState) => { + if (taskState.change === 'macroTask') { + logs.push(taskState.macroTask); + } + return delegate.hasTask(target, taskState); + }, + }) + .run(function () { + const req = new XMLHttpRequest(); + req.open('get', 'http://notexists.url', true); + req.send(); + req.addEventListener('error', () => { + expect(logs).toEqual([true, false]); + done(); }); + }); }); it('should trigger readystatechange if xhr request trigger cors error', (done) => { @@ -394,7 +421,7 @@ describe('XMLHttpRequest', function() { done(); return; } - req.addEventListener('readystatechange', function(ev) { + req.addEventListener('readystatechange', function (ev) { if (req.readyState === 4) { const xhrScheduled = (req as any)[zoneSymbol('xhrScheduled')]; const task = (req as any)[zoneSymbol('xhrTask')]; @@ -427,7 +454,7 @@ describe('XMLHttpRequest', function() { name: 'xhr', onHasTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, hasTask: HasTaskState) => { logs.push(JSON.stringify(hasTask)); - } + }, }); const req = new XMLHttpRequest(); try { @@ -444,7 +471,7 @@ describe('XMLHttpRequest', function() { timerId = (window as any)[zoneSymbol('setTimeout')](() => { expect(logs).toEqual([ `{"microTask":false,"macroTask":true,"eventTask":false,"change":"macroTask"}`, - `{"microTask":false,"macroTask":false,"eventTask":false,"change":"macroTask"}` + `{"microTask":false,"macroTask":false,"eventTask":false,"change":"macroTask"}`, ]); done(); }, 500); @@ -457,26 +484,25 @@ describe('XMLHttpRequest', function() { }); }); - it('should not throw error when get XMLHttpRequest.prototype.onreadystatechange the first time', - function() { - const func = function() { - testZone.run(function() { - const req = new XMLHttpRequest(); - req.onreadystatechange; - }); - }; - expect(func).not.toThrow(); - }); - - it('should be in the zone when use XMLHttpRequest.addEventListener', function(done) { - testZone.run(function() { + it('should not throw error when get XMLHttpRequest.prototype.onreadystatechange the first time', function () { + const func = function () { + testZone.run(function () { + const req = new XMLHttpRequest(); + req.onreadystatechange; + }); + }; + expect(func).not.toThrow(); + }); + + it('should be in the zone when use XMLHttpRequest.addEventListener', function (done) { + testZone.run(function () { // sometimes this case will cause timeout // so we set it longer const interval = (jasmine).DEFAULT_TIMEOUT_INTERVAL; (jasmine).DEFAULT_TIMEOUT_INTERVAL = 5000; const req = new XMLHttpRequest(); req.open('get', '/', true); - req.addEventListener('readystatechange', function() { + req.addEventListener('readystatechange', function () { if (req.readyState === 4) { // expect(Zone.current.name).toEqual('test'); (jasmine).DEFAULT_TIMEOUT_INTERVAL = interval; @@ -487,26 +513,28 @@ describe('XMLHttpRequest', function() { }); }); - it('should return origin listener when call xhr.onreadystatechange', - ifEnvSupportsWithDone(supportPatchXHROnProperty, function(done: Function) { - testZone.run(function() { - // sometimes this case will cause timeout - // so we set it longer - const req = new XMLHttpRequest(); - req.open('get', '/', true); - const interval = (jasmine).DEFAULT_TIMEOUT_INTERVAL; - (jasmine).DEFAULT_TIMEOUT_INTERVAL = 5000; - const listener = req.onreadystatechange = function() { - if (req.readyState === 4) { - (jasmine).DEFAULT_TIMEOUT_INTERVAL = interval; - done(); - } - }; - expect(req.onreadystatechange).toBe(listener); - req.onreadystatechange = function() { - return listener.call(this); - }; - req.send(); - }); - })); + it( + 'should return origin listener when call xhr.onreadystatechange', + ifEnvSupportsWithDone(supportPatchXHROnProperty, function (done: Function) { + testZone.run(function () { + // sometimes this case will cause timeout + // so we set it longer + const req = new XMLHttpRequest(); + req.open('get', '/', true); + const interval = (jasmine).DEFAULT_TIMEOUT_INTERVAL; + (jasmine).DEFAULT_TIMEOUT_INTERVAL = 5000; + const listener = (req.onreadystatechange = function () { + if (req.readyState === 4) { + (jasmine).DEFAULT_TIMEOUT_INTERVAL = interval; + done(); + } + }); + expect(req.onreadystatechange).toBe(listener); + req.onreadystatechange = function () { + return listener.call(this); + }; + req.send(); + }); + }), + ); }); diff --git a/packages/zone.js/test/browser/browser.spec.ts b/packages/zone.js/test/browser/browser.spec.ts index 22b9da697c902..53af912305f3b 100644 --- a/packages/zone.js/test/browser/browser.spec.ts +++ b/packages/zone.js/test/browser/browser.spec.ts @@ -9,12 +9,18 @@ import {patchFilteredProperties} from '../../lib/browser/property-descriptor'; import {patchEventTarget} from '../../lib/common/events'; import {isIEOrEdge, zoneSymbol} from '../../lib/common/utils'; -import {getEdgeVersion, getIEVersion, ifEnvSupports, ifEnvSupportsWithDone, isEdge} from '../test-util'; +import { + getEdgeVersion, + getIEVersion, + ifEnvSupports, + ifEnvSupportsWithDone, + isEdge, +} from '../test-util'; import Spy = jasmine.Spy; declare const global: any; -const noop = function() {}; +const noop = function () {}; function windowPrototype() { return !!(global['Window'] && global['Window'].prototype); @@ -25,7 +31,7 @@ function promiseUnhandleRejectionSupport() { } function canPatchOnProperty(obj: any, prop: string) { - const func = function() { + const func = function () { if (!obj) { return false; } @@ -43,14 +49,13 @@ function canPatchOnProperty(obj: any, prop: string) { let supportsPassive = false; try { const opts = Object.defineProperty({}, 'passive', { - get: function() { + get: function () { supportsPassive = true; - } + }, }); window.addEventListener('test', opts as any, opts); window.removeEventListener('test', opts as any, opts); -} catch (e) { -} +} catch (e) {} function supportEventListenerOptions() { return supportsPassive; @@ -60,8 +65,10 @@ function supportEventListenerOptions() { function supportCanvasTest() { const HTMLCanvasElement = (window as any)['HTMLCanvasElement']; - const supportCanvas = typeof HTMLCanvasElement !== 'undefined' && HTMLCanvasElement.prototype && - HTMLCanvasElement.prototype.toBlob; + const supportCanvas = + typeof HTMLCanvasElement !== 'undefined' && + HTMLCanvasElement.prototype && + HTMLCanvasElement.prototype.toBlob; const FileReader = (window as any)['FileReader']; const supportFileReader = typeof FileReader !== 'undefined'; return supportCanvas && supportFileReader; @@ -83,31 +90,40 @@ class TestEventListener { removeEventListener(eventName: string, listener: any, options: any) {} } -describe('Zone', function() { +describe('Zone', function () { const rootZone = Zone.current; (Zone as any)[zoneSymbol('ignoreConsoleErrorUncaughtError')] = true; - describe('hooks', function() { - it('should allow you to override alert/prompt/confirm', function() { + describe('hooks', function () { + it('should allow you to override alert/prompt/confirm', function () { const alertSpy = jasmine.createSpy('alert'); const promptSpy = jasmine.createSpy('prompt'); const confirmSpy = jasmine.createSpy('confirm'); - const spies: - {[k: string]: Function} = {'alert': alertSpy, 'prompt': promptSpy, 'confirm': confirmSpy}; + const spies: {[k: string]: Function} = { + 'alert': alertSpy, + 'prompt': promptSpy, + 'confirm': confirmSpy, + }; const myZone = Zone.current.fork({ name: 'spy', onInvoke: ( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - callback: Function, applyThis?: any, applyArgs?: any[], source?: string): any => { + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + callback: Function, + applyThis?: any, + applyArgs?: any[], + source?: string, + ): any => { if (source) { spies[source].apply(null, applyArgs); } else { return parentZoneDelegate.invoke(targetZone, callback, applyThis, applyArgs, source); } - } + }, }); - myZone.run(function() { + myZone.run(function () { alert('alertMsg'); prompt('promptMsg', 'default'); confirm('confirmMsg'); @@ -119,736 +135,905 @@ describe('Zone', function() { }); describe( - 'DOM onProperty hooks', - ifEnvSupports(canPatchOnProperty(HTMLElement.prototype, 'onclick'), function() { - let mouseEvent = document.createEvent('Event'); - let hookSpy: Spy, eventListenerSpy: Spy; - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - hookSpy(); - return parentZoneDelegate.scheduleTask(targetZone, task); - } - }); + 'DOM onProperty hooks', + ifEnvSupports(canPatchOnProperty(HTMLElement.prototype, 'onclick'), function () { + let mouseEvent = document.createEvent('Event'); + let hookSpy: Spy, eventListenerSpy: Spy; + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy(); + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + }); - beforeEach(function() { - mouseEvent.initEvent('mousedown', true, true); - hookSpy = jasmine.createSpy('hook'); - eventListenerSpy = jasmine.createSpy('eventListener'); - }); - const globalEventHandlersEventNames = [ - 'abort', - 'animationcancel', - 'animationend', - 'animationiteration', - 'auxclick', - 'beforeinput', - 'blur', - 'cancel', - 'canplay', - 'canplaythrough', - 'change', - 'compositionstart', - 'compositionupdate', - 'compositionend', - 'cuechange', - 'click', - 'close', - 'contextmenu', - 'curechange', - 'dblclick', - 'drag', - 'dragend', - 'dragenter', - 'dragexit', - 'dragleave', - 'dragover', - 'drop', - 'durationchange', - 'emptied', - 'ended', - 'error', - 'focus', - 'focusin', - 'focusout', - 'gotpointercapture', - 'input', - 'invalid', - 'keydown', - 'keypress', - 'keyup', - 'load', - 'loadstart', - 'loadeddata', - 'loadedmetadata', - 'lostpointercapture', - 'mousedown', - 'mouseenter', - 'mouseleave', - 'mousemove', - 'mouseout', - 'mouseover', - 'mouseup', - 'mousewheel', - 'orientationchange', - 'pause', - 'play', - 'playing', - 'pointercancel', - 'pointerdown', - 'pointerenter', - 'pointerleave', - 'pointerlockchange', - 'mozpointerlockchange', - 'webkitpointerlockerchange', - 'pointerlockerror', - 'mozpointerlockerror', - 'webkitpointerlockerror', - 'pointermove', - 'pointout', - 'pointerover', - 'pointerup', - 'progress', - 'ratechange', - 'reset', - 'resize', - 'scroll', - 'seeked', - 'seeking', - 'select', - 'selectionchange', - 'selectstart', - 'show', - 'sort', - 'stalled', - 'submit', - 'suspend', - 'timeupdate', - 'volumechange', - 'touchcancel', - 'touchmove', - 'touchstart', - 'touchend', - 'transitioncancel', - 'transitionend', - 'waiting', - 'wheel' - ]; - const documentEventNames = [ - 'afterscriptexecute', 'beforescriptexecute', 'DOMContentLoaded', 'freeze', - 'fullscreenchange', 'mozfullscreenchange', 'webkitfullscreenchange', - 'msfullscreenchange', 'fullscreenerror', 'mozfullscreenerror', 'webkitfullscreenerror', - 'msfullscreenerror', 'readystatechange', 'visibilitychange', 'resume' - ]; - const windowEventNames = [ - 'absolutedeviceorientation', - 'afterinput', - 'afterprint', - 'appinstalled', - 'beforeinstallprompt', - 'beforeprint', - 'beforeunload', - 'devicelight', - 'devicemotion', - 'deviceorientation', - 'deviceorientationabsolute', - 'deviceproximity', - 'hashchange', - 'languagechange', - 'message', - 'mozbeforepaint', - 'offline', - 'online', - 'paint', - 'pageshow', - 'pagehide', - 'popstate', - 'rejectionhandled', - 'storage', - 'unhandledrejection', - 'unload', - 'userproximity', - 'vrdisplayconnected', - 'vrdisplaydisconnected', - 'vrdisplaypresentchange' - ]; - const htmlElementEventNames = [ - 'beforecopy', 'beforecut', 'beforepaste', 'copy', 'cut', 'paste', 'dragstart', - 'loadend', 'animationstart', 'search', 'transitionrun', 'transitionstart', - 'webkitanimationend', 'webkitanimationiteration', 'webkitanimationstart', - 'webkittransitionend' - ]; - const mediaElementEventNames = - ['encrypted', 'waitingforkey', 'msneedkey', 'mozinterruptbegin', 'mozinterruptend']; - const ieElementEventNames = [ - 'activate', - 'afterupdate', - 'ariarequest', - 'beforeactivate', - 'beforedeactivate', - 'beforeeditfocus', - 'beforeupdate', - 'cellchange', - 'controlselect', - 'dataavailable', - 'datasetchanged', - 'datasetcomplete', - 'errorupdate', - 'filterchange', - 'layoutcomplete', - 'losecapture', - 'move', - 'moveend', - 'movestart', - 'propertychange', - 'resizeend', - 'resizestart', - 'rowenter', - 'rowexit', - 'rowsdelete', - 'rowsinserted', - 'command', - 'compassneedscalibration', - 'deactivate', - 'help', - 'mscontentzoom', - 'msmanipulationstatechanged', - 'msgesturechange', - 'msgesturedoubletap', - 'msgestureend', - 'msgesturehold', - 'msgesturestart', - 'msgesturetap', - 'msgotpointercapture', - 'msinertiastart', - 'mslostpointercapture', - 'mspointercancel', - 'mspointerdown', - 'mspointerenter', - 'mspointerhover', - 'mspointerleave', - 'mspointermove', - 'mspointerout', - 'mspointerover', - 'mspointerup', - 'pointerout', - 'mssitemodejumplistitemremoved', - 'msthumbnailclick', - 'stop', - 'storagecommit' - ]; - const webglEventNames = - ['webglcontextrestored', 'webglcontextlost', 'webglcontextcreationerror']; - const formEventNames = ['autocomplete', 'autocompleteerror']; - const detailEventNames = ['toggle']; - const frameEventNames = ['load']; - const frameSetEventNames = - ['blur', 'error', 'focus', 'load', 'resize', 'scroll', 'messageerror']; - const marqueeEventNames = ['bounce', 'finish', 'start']; - - const XMLHttpRequestEventNames = [ - 'loadstart', 'progress', 'abort', 'error', 'load', 'progress', 'timeout', 'loadend', - 'readystatechange' - ]; - const IDBIndexEventNames = [ - 'upgradeneeded', 'complete', 'abort', 'success', 'error', 'blocked', 'versionchange', - 'close' - ]; - const websocketEventNames = ['close', 'error', 'open', 'message']; - const workerEventNames = ['error', 'message']; - - const eventNames = globalEventHandlersEventNames.concat( - webglEventNames, formEventNames, detailEventNames, documentEventNames, - windowEventNames, htmlElementEventNames, ieElementEventNames); - - - function checkIsOnPropertiesPatched( - target: any, shouldPatchedProperties?: string[], ignoredProperties?: string[]) { - let checkTargetProps = - shouldPatchedProperties && shouldPatchedProperties.map(p => `on${p}`); - if (!checkTargetProps) { - checkTargetProps = []; - for (let prop in target) { - checkTargetProps.push(prop); - } + beforeEach(function () { + mouseEvent.initEvent('mousedown', true, true); + hookSpy = jasmine.createSpy('hook'); + eventListenerSpy = jasmine.createSpy('eventListener'); + }); + const globalEventHandlersEventNames = [ + 'abort', + 'animationcancel', + 'animationend', + 'animationiteration', + 'auxclick', + 'beforeinput', + 'blur', + 'cancel', + 'canplay', + 'canplaythrough', + 'change', + 'compositionstart', + 'compositionupdate', + 'compositionend', + 'cuechange', + 'click', + 'close', + 'contextmenu', + 'curechange', + 'dblclick', + 'drag', + 'dragend', + 'dragenter', + 'dragexit', + 'dragleave', + 'dragover', + 'drop', + 'durationchange', + 'emptied', + 'ended', + 'error', + 'focus', + 'focusin', + 'focusout', + 'gotpointercapture', + 'input', + 'invalid', + 'keydown', + 'keypress', + 'keyup', + 'load', + 'loadstart', + 'loadeddata', + 'loadedmetadata', + 'lostpointercapture', + 'mousedown', + 'mouseenter', + 'mouseleave', + 'mousemove', + 'mouseout', + 'mouseover', + 'mouseup', + 'mousewheel', + 'orientationchange', + 'pause', + 'play', + 'playing', + 'pointercancel', + 'pointerdown', + 'pointerenter', + 'pointerleave', + 'pointerlockchange', + 'mozpointerlockchange', + 'webkitpointerlockerchange', + 'pointerlockerror', + 'mozpointerlockerror', + 'webkitpointerlockerror', + 'pointermove', + 'pointout', + 'pointerover', + 'pointerup', + 'progress', + 'ratechange', + 'reset', + 'resize', + 'scroll', + 'seeked', + 'seeking', + 'select', + 'selectionchange', + 'selectstart', + 'show', + 'sort', + 'stalled', + 'submit', + 'suspend', + 'timeupdate', + 'volumechange', + 'touchcancel', + 'touchmove', + 'touchstart', + 'touchend', + 'transitioncancel', + 'transitionend', + 'waiting', + 'wheel', + ]; + const documentEventNames = [ + 'afterscriptexecute', + 'beforescriptexecute', + 'DOMContentLoaded', + 'freeze', + 'fullscreenchange', + 'mozfullscreenchange', + 'webkitfullscreenchange', + 'msfullscreenchange', + 'fullscreenerror', + 'mozfullscreenerror', + 'webkitfullscreenerror', + 'msfullscreenerror', + 'readystatechange', + 'visibilitychange', + 'resume', + ]; + const windowEventNames = [ + 'absolutedeviceorientation', + 'afterinput', + 'afterprint', + 'appinstalled', + 'beforeinstallprompt', + 'beforeprint', + 'beforeunload', + 'devicelight', + 'devicemotion', + 'deviceorientation', + 'deviceorientationabsolute', + 'deviceproximity', + 'hashchange', + 'languagechange', + 'message', + 'mozbeforepaint', + 'offline', + 'online', + 'paint', + 'pageshow', + 'pagehide', + 'popstate', + 'rejectionhandled', + 'storage', + 'unhandledrejection', + 'unload', + 'userproximity', + 'vrdisplayconnected', + 'vrdisplaydisconnected', + 'vrdisplaypresentchange', + ]; + const htmlElementEventNames = [ + 'beforecopy', + 'beforecut', + 'beforepaste', + 'copy', + 'cut', + 'paste', + 'dragstart', + 'loadend', + 'animationstart', + 'search', + 'transitionrun', + 'transitionstart', + 'webkitanimationend', + 'webkitanimationiteration', + 'webkitanimationstart', + 'webkittransitionend', + ]; + const mediaElementEventNames = [ + 'encrypted', + 'waitingforkey', + 'msneedkey', + 'mozinterruptbegin', + 'mozinterruptend', + ]; + const ieElementEventNames = [ + 'activate', + 'afterupdate', + 'ariarequest', + 'beforeactivate', + 'beforedeactivate', + 'beforeeditfocus', + 'beforeupdate', + 'cellchange', + 'controlselect', + 'dataavailable', + 'datasetchanged', + 'datasetcomplete', + 'errorupdate', + 'filterchange', + 'layoutcomplete', + 'losecapture', + 'move', + 'moveend', + 'movestart', + 'propertychange', + 'resizeend', + 'resizestart', + 'rowenter', + 'rowexit', + 'rowsdelete', + 'rowsinserted', + 'command', + 'compassneedscalibration', + 'deactivate', + 'help', + 'mscontentzoom', + 'msmanipulationstatechanged', + 'msgesturechange', + 'msgesturedoubletap', + 'msgestureend', + 'msgesturehold', + 'msgesturestart', + 'msgesturetap', + 'msgotpointercapture', + 'msinertiastart', + 'mslostpointercapture', + 'mspointercancel', + 'mspointerdown', + 'mspointerenter', + 'mspointerhover', + 'mspointerleave', + 'mspointermove', + 'mspointerout', + 'mspointerover', + 'mspointerup', + 'pointerout', + 'mssitemodejumplistitemremoved', + 'msthumbnailclick', + 'stop', + 'storagecommit', + ]; + const webglEventNames = [ + 'webglcontextrestored', + 'webglcontextlost', + 'webglcontextcreationerror', + ]; + const formEventNames = ['autocomplete', 'autocompleteerror']; + const detailEventNames = ['toggle']; + const frameEventNames = ['load']; + const frameSetEventNames = [ + 'blur', + 'error', + 'focus', + 'load', + 'resize', + 'scroll', + 'messageerror', + ]; + const marqueeEventNames = ['bounce', 'finish', 'start']; + + const XMLHttpRequestEventNames = [ + 'loadstart', + 'progress', + 'abort', + 'error', + 'load', + 'progress', + 'timeout', + 'loadend', + 'readystatechange', + ]; + const IDBIndexEventNames = [ + 'upgradeneeded', + 'complete', + 'abort', + 'success', + 'error', + 'blocked', + 'versionchange', + 'close', + ]; + const websocketEventNames = ['close', 'error', 'open', 'message']; + const workerEventNames = ['error', 'message']; + + const eventNames = globalEventHandlersEventNames.concat( + webglEventNames, + formEventNames, + detailEventNames, + documentEventNames, + windowEventNames, + htmlElementEventNames, + ieElementEventNames, + ); + + function checkIsOnPropertiesPatched( + target: any, + shouldPatchedProperties?: string[], + ignoredProperties?: string[], + ) { + let checkTargetProps = + shouldPatchedProperties && shouldPatchedProperties.map((p) => `on${p}`); + if (!checkTargetProps) { + checkTargetProps = []; + for (let prop in target) { + checkTargetProps.push(prop); } - for (let i = 0; i < checkTargetProps.length; i++) { - const prop = checkTargetProps[i]; - if (ignoredProperties && - ignoredProperties.filter(ignoreProp => ignoreProp === prop).length > 0) { + } + for (let i = 0; i < checkTargetProps.length; i++) { + const prop = checkTargetProps[i]; + if ( + ignoredProperties && + ignoredProperties.filter((ignoreProp) => ignoreProp === prop).length > 0 + ) { + continue; + } + if (prop.slice(0, 2) === 'on' && prop.length > 2) { + let propExistsOnTarget = false; + let checkTarget = target; + while (checkTarget && checkTarget !== Object) { + const desc = Object.getOwnPropertyDescriptor(checkTarget, prop); + if (desc && desc.configurable) { + propExistsOnTarget = true; + break; + } + checkTarget = Object.getPrototypeOf(checkTarget); + } + if (!propExistsOnTarget) { + console.warn(`${prop} not exists on target ${target}`); continue; } - if (prop.slice(0, 2) === 'on' && prop.length > 2) { - let propExistsOnTarget = false; - let checkTarget = target; - while (checkTarget && checkTarget !== Object) { - const desc = Object.getOwnPropertyDescriptor(checkTarget, prop); - if (desc && desc.configurable) { - propExistsOnTarget = true; - break; - } - checkTarget = Object.getPrototypeOf(checkTarget); - } - if (!propExistsOnTarget) { - console.warn(`${prop} not exists on target ${target}`); - continue; - } - target[prop] = noop; - if (!target[Zone.__symbol__('ON_PROPERTY' + prop.slice(2))]) { - fail(`${prop} of ${target} is not patched`); - } else { - expect(target[prop]).toBe(noop); - target[prop] = null; - expect(target[Zone.__symbol__('ON_PROPERTY' + prop.slice(2))]).toBeNull(); - } + target[prop] = noop; + if (!target[Zone.__symbol__('ON_PROPERTY' + prop.slice(2))]) { + fail(`${prop} of ${target} is not patched`); + } else { + expect(target[prop]).toBe(noop); + target[prop] = null; + expect(target[Zone.__symbol__('ON_PROPERTY' + prop.slice(2))]).toBeNull(); } } } + } - it('should patch all possible on properties on native prototype', function() { - function isPropertyPatched(obj: any, prop: string, prototype?: any) { - let desc = Object.getOwnPropertyDescriptor(obj, prop); - if (!desc && prototype) { - // when patch window object, use prototype to check prop exist or not - const prototypeDesc = Object.getOwnPropertyDescriptor(prototype, prop); - if (prototypeDesc) { - desc = {enumerable: true, configurable: true}; - } - } - // if the descriptor not exists or is not configurable - // just return - if (!desc || !desc.configurable) { - return true; + it('should patch all possible on properties on native prototype', function () { + function isPropertyPatched(obj: any, prop: string, prototype?: any) { + let desc = Object.getOwnPropertyDescriptor(obj, prop); + if (!desc && prototype) { + // when patch window object, use prototype to check prop exist or not + const prototypeDesc = Object.getOwnPropertyDescriptor(prototype, prop); + if (prototypeDesc) { + desc = {enumerable: true, configurable: true}; } + } + // if the descriptor not exists or is not configurable + // just return + if (!desc || !desc.configurable) { + return true; + } - const onPropPatchedSymbol = zoneSymbol('on' + prop + 'patched'); - if (obj.hasOwnProperty(onPropPatchedSymbol) && obj[onPropPatchedSymbol]) { - return true; - } - return false; + const onPropPatchedSymbol = zoneSymbol('on' + prop + 'patched'); + if (obj.hasOwnProperty(onPropPatchedSymbol) && obj[onPropPatchedSymbol]) { + return true; } + return false; + } - function isPropertiesPatched(obj: any, properties: string[]|null, prototype?: any) { - if (properties) { - for (let i = 0; i < properties.length; i++) { - if (!isPropertyPatched(obj, 'on' + properties[i], prototype)) { - fail(`${properties[i]} is not patched on ${obj}`); - } + function isPropertiesPatched(obj: any, properties: string[] | null, prototype?: any) { + if (properties) { + for (let i = 0; i < properties.length; i++) { + if (!isPropertyPatched(obj, 'on' + properties[i], prototype)) { + fail(`${properties[i]} is not patched on ${obj}`); } } } + } - isPropertiesPatched( - window, eventNames.concat(['messageerror']), Object.getPrototypeOf(window)); - isPropertiesPatched(Document.prototype, eventNames); + isPropertiesPatched( + window, + eventNames.concat(['messageerror']), + Object.getPrototypeOf(window), + ); + isPropertiesPatched(Document.prototype, eventNames); - if (typeof window['SVGElement'] !== 'undefined') { - isPropertiesPatched(window['SVGElement'].prototype, eventNames); - } - isPropertiesPatched(Element.prototype, eventNames); - isPropertiesPatched(HTMLElement.prototype, eventNames); - isPropertiesPatched(HTMLMediaElement.prototype, mediaElementEventNames); - isPropertiesPatched( - HTMLFrameSetElement.prototype, windowEventNames.concat(frameSetEventNames)); + if (typeof window['SVGElement'] !== 'undefined') { + isPropertiesPatched(window['SVGElement'].prototype, eventNames); + } + isPropertiesPatched(Element.prototype, eventNames); + isPropertiesPatched(HTMLElement.prototype, eventNames); + isPropertiesPatched(HTMLMediaElement.prototype, mediaElementEventNames); + isPropertiesPatched( + HTMLFrameSetElement.prototype, + windowEventNames.concat(frameSetEventNames), + ); + isPropertiesPatched( + HTMLBodyElement.prototype, + windowEventNames.concat(frameSetEventNames), + ); + isPropertiesPatched(HTMLFrameElement.prototype, frameEventNames); + isPropertiesPatched(HTMLIFrameElement.prototype, frameEventNames); + + const HTMLMarqueeElement = window['HTMLMarqueeElement']; + if (HTMLMarqueeElement) { + isPropertiesPatched(HTMLMarqueeElement.prototype, marqueeEventNames); + } + const Worker = window['Worker']; + if (Worker) { + isPropertiesPatched(Worker.prototype, workerEventNames); + } + const XMLHttpRequest = window['XMLHttpRequest']; + if (XMLHttpRequest) { + // XMLHttpRequest is not available in ServiceWorker, so we need to check here + isPropertiesPatched(XMLHttpRequest.prototype, XMLHttpRequestEventNames); + } + const XMLHttpRequestEventTarget = window['XMLHttpRequestEventTarget']; + if (XMLHttpRequestEventTarget) { isPropertiesPatched( - HTMLBodyElement.prototype, windowEventNames.concat(frameSetEventNames)); - isPropertiesPatched(HTMLFrameElement.prototype, frameEventNames); - isPropertiesPatched(HTMLIFrameElement.prototype, frameEventNames); + XMLHttpRequestEventTarget && XMLHttpRequestEventTarget.prototype, + XMLHttpRequestEventNames, + ); + } + if (typeof IDBIndex !== 'undefined') { + isPropertiesPatched(IDBIndex.prototype, IDBIndexEventNames); + isPropertiesPatched(IDBRequest.prototype, IDBIndexEventNames); + isPropertiesPatched(IDBOpenDBRequest.prototype, IDBIndexEventNames); + isPropertiesPatched(IDBDatabase.prototype, IDBIndexEventNames); + isPropertiesPatched(IDBTransaction.prototype, IDBIndexEventNames); + isPropertiesPatched(IDBCursor.prototype, IDBIndexEventNames); + } + const WebSocket = window['WebSocket']; + if (WebSocket) { + isPropertiesPatched(WebSocket.prototype, websocketEventNames); + } + }); - const HTMLMarqueeElement = window['HTMLMarqueeElement']; - if (HTMLMarqueeElement) { - isPropertiesPatched(HTMLMarqueeElement.prototype, marqueeEventNames); - } - const Worker = window['Worker']; - if (Worker) { - isPropertiesPatched(Worker.prototype, workerEventNames); - } - const XMLHttpRequest = window['XMLHttpRequest']; - if (XMLHttpRequest) { - // XMLHttpRequest is not available in ServiceWorker, so we need to check here - isPropertiesPatched(XMLHttpRequest.prototype, XMLHttpRequestEventNames); - } - const XMLHttpRequestEventTarget = window['XMLHttpRequestEventTarget']; - if (XMLHttpRequestEventTarget) { - isPropertiesPatched( - XMLHttpRequestEventTarget && XMLHttpRequestEventTarget.prototype, - XMLHttpRequestEventNames); - } - if (typeof IDBIndex !== 'undefined') { - isPropertiesPatched(IDBIndex.prototype, IDBIndexEventNames); - isPropertiesPatched(IDBRequest.prototype, IDBIndexEventNames); - isPropertiesPatched(IDBOpenDBRequest.prototype, IDBIndexEventNames); - isPropertiesPatched(IDBDatabase.prototype, IDBIndexEventNames); - isPropertiesPatched(IDBTransaction.prototype, IDBIndexEventNames); - isPropertiesPatched(IDBCursor.prototype, IDBIndexEventNames); - } - const WebSocket = window['WebSocket']; - if (WebSocket) { - isPropertiesPatched(WebSocket.prototype, websocketEventNames); - } + it('should patch all possible on properties on element', function () { + const htmlElementTagNames: string[] = [ + 'a', + 'area', + 'audio', + 'base', + 'basefont', + 'blockquote', + 'br', + 'button', + 'canvas', + 'caption', + 'col', + 'colgroup', + 'data', + 'datalist', + 'del', + 'dir', + 'div', + 'dl', + 'embed', + 'fieldset', + 'font', + 'form', + 'frame', + 'frameset', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'head', + 'hr', + 'html', + 'iframe', + 'img', + 'input', + 'ins', + 'isindex', + 'label', + 'legend', + 'li', + 'link', + 'listing', + 'map', + 'marquee', + 'menu', + 'meta', + 'meter', + 'nextid', + 'ol', + 'optgroup', + 'option', + 'output', + 'p', + 'param', + 'picture', + 'pre', + 'progress', + 'q', + 'script', + 'select', + 'source', + 'span', + 'style', + 'table', + 'tbody', + 'td', + 'template', + 'textarea', + 'tfoot', + 'th', + 'thead', + 'time', + 'title', + 'tr', + 'track', + 'ul', + 'video', + ]; + htmlElementTagNames.forEach((tagName) => { + checkIsOnPropertiesPatched(document.createElement(tagName), eventNames, [ + 'onorientationchange', + ]); }); + }); - it('should patch all possible on properties on element', function() { - const htmlElementTagNames: string[] = [ - 'a', 'area', 'audio', 'base', 'basefont', 'blockquote', 'br', - 'button', 'canvas', 'caption', 'col', 'colgroup', 'data', 'datalist', - 'del', 'dir', 'div', 'dl', 'embed', 'fieldset', 'font', - 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', - 'h5', 'h6', 'head', 'hr', 'html', 'iframe', 'img', - 'input', 'ins', 'isindex', 'label', 'legend', 'li', 'link', - 'listing', 'map', 'marquee', 'menu', 'meta', 'meter', 'nextid', - 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'picture', - 'pre', 'progress', 'q', 'script', 'select', 'source', 'span', - 'style', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', - 'th', 'thead', 'time', 'title', 'tr', 'track', 'ul', - 'video' - ]; - htmlElementTagNames.forEach(tagName => { - checkIsOnPropertiesPatched( - document.createElement(tagName), eventNames, ['onorientationchange']); - }); - }); + it('should patch all possible on properties on svg element', function () { + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + checkIsOnPropertiesPatched(svg, eventNames); + }); - it('should patch all possible on properties on svg element', function() { - const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - checkIsOnPropertiesPatched(svg, eventNames); - }); + it('should patch all possible on properties on media element', function () { + const audio = document.createElement('audio'); + checkIsOnPropertiesPatched(audio, mediaElementEventNames); + }); - it('should patch all possible on properties on media element', function() { - const audio = document.createElement('audio'); - checkIsOnPropertiesPatched(audio, mediaElementEventNames); - }); + it('should patch all possible on properties on frameset element', function () { + const frameset = document.createElement('frameset'); + checkIsOnPropertiesPatched(frameset, windowEventNames.concat(frameSetEventNames)); + }); - it('should patch all possible on properties on frameset element', function() { - const frameset = document.createElement('frameset'); - checkIsOnPropertiesPatched(frameset, windowEventNames.concat(frameSetEventNames)); - }); + it('should patch all possible on properties on body', function () { + checkIsOnPropertiesPatched(document.body, windowEventNames.concat(frameSetEventNames)); + }); - it('should patch all possible on properties on body', function() { - checkIsOnPropertiesPatched(document.body, windowEventNames.concat(frameSetEventNames)); - }); + it('should patch all possible on properties on Frame', function () { + const frame = document.createElement('frame'); + checkIsOnPropertiesPatched(frame, frameEventNames); + }); - it('should patch all possible on properties on Frame', function() { - const frame = document.createElement('frame'); - checkIsOnPropertiesPatched(frame, frameEventNames); - }); + it('should patch all possible on properties on marquee element', function () { + const marquee = document.createElement('marquee'); + checkIsOnPropertiesPatched(marquee, marqueeEventNames); + }); - it('should patch all possible on properties on marquee element', function() { - const marquee = document.createElement('marquee'); - checkIsOnPropertiesPatched(marquee, marqueeEventNames); - }); + it('should patch all possible on properties on Window', function () { + checkIsOnPropertiesPatched(window, eventNames.concat(['messageerror'])); + }); + + it('should patch all possible on properties on xhr', function () { + checkIsOnPropertiesPatched(new XMLHttpRequest(), XMLHttpRequestEventNames); + }); + + it('should patch all possible on properties on worker', function () { + checkIsOnPropertiesPatched( + new Worker('/base/angular/packages/zone.js/test/assets/empty-worker.js'), + workerEventNames, + ); + }); + + it('should patch all possible on properties on websocket', function () { + try { + checkIsOnPropertiesPatched(new WebSocket('ws://localhost:8001'), websocketEventNames); + } catch (e) { + console.log('error when creating websocket', e); + } + }); - it('should patch all possible on properties on Window', function() { - checkIsOnPropertiesPatched(window, eventNames.concat(['messageerror'])); + it('should not patch ignored on properties', function () { + const TestTarget: any = (window as any)['TestTarget']; + patchFilteredProperties( + TestTarget.prototype, + ['prop1', 'prop2'], + global['__Zone_ignore_on_properties'], + ); + const testTarget = new TestTarget(); + Zone.current.fork({name: 'test'}).run(() => { + testTarget.onprop1 = function () { + // onprop1 should not be patched + expect(Zone.current.name).toEqual('test1'); + }; + testTarget.onprop2 = function () { + // onprop2 should be patched + expect(Zone.current.name).toEqual('test'); + }; }); - it('should patch all possible on properties on xhr', function() { - checkIsOnPropertiesPatched(new XMLHttpRequest(), XMLHttpRequestEventNames); + Zone.current.fork({name: 'test1'}).run(() => { + testTarget.dispatchEvent('prop1'); + testTarget.dispatchEvent('prop2'); }); + }); + + it('should not patch ignored eventListener', function () { + let scrollEvent = document.createEvent('Event'); + scrollEvent.initEvent('scroll', true, true); + + const zone = Zone.current.fork({name: 'run'}); + const div = document.createElement('div'); + document.body.appendChild(div); - it('should patch all possible on properties on worker', function() { - checkIsOnPropertiesPatched( - new Worker('/base/angular/packages/zone.js/test/assets/empty-worker.js'), - workerEventNames); + Zone.current.fork({name: 'scroll'}).run(() => { + const listener = () => { + expect(Zone.current.name).toEqual(zone.name); + div.removeEventListener('scroll', listener); + }; + div.addEventListener('scroll', listener); }); - it('should patch all possible on properties on websocket', function() { - try { - checkIsOnPropertiesPatched(new WebSocket('ws://localhost:8001'), websocketEventNames); - } catch (e) { - console.log('error when creating websocket', e); - } + zone.run(() => { + div.dispatchEvent(scrollEvent); }); + document.body.removeChild(div); + }); - it('should not patch ignored on properties', function() { - const TestTarget: any = (window as any)['TestTarget']; - patchFilteredProperties( - TestTarget.prototype, ['prop1', 'prop2'], global['__Zone_ignore_on_properties']); - const testTarget = new TestTarget(); - Zone.current.fork({name: 'test'}).run(() => { - testTarget.onprop1 = function() { - // onprop1 should not be patched - expect(Zone.current.name).toEqual('test1'); - }; - testTarget.onprop2 = function() { - // onprop2 should be patched - expect(Zone.current.name).toEqual('test'); - }; - }); + it('non function property starts with on but not event listener should still work as expected', () => { + (window as any).one_two_three = {foo: 'bar'}; - Zone.current.fork({name: 'test1'}).run(() => { - testTarget.dispatchEvent('prop1'); - testTarget.dispatchEvent('prop2'); - }); - }); + expect((window as any).one_two_three).toEqual({foo: 'bar'}); + (window as any).one_two_three = {bar: 'foo'}; + expect((window as any).one_two_three).toEqual({bar: 'foo'}); + (window as any).one_two_three = null; + expect((window as any).one_two_three).toBeNull(); + }); - it('should not patch ignored eventListener', function() { - let scrollEvent = document.createEvent('Event'); - scrollEvent.initEvent('scroll', true, true); + it('function property starts with on but not event listener should still work as expected', () => { + let called = false; + const func = function () { + called = true; + }; + (window as any).one_two_three = func; + + expect((window as any).one_two_three).toEqual(func); + expect(called).toBeFalse(); + (window as any).one_two_three(); + expect(called).toBeTrue(); + (window as any).one_two_three = null; + expect((window as any).one_two_three).toBeNull(); + }); - const zone = Zone.current.fork({name: 'run'}); - const div = document.createElement('div'); - document.body.appendChild(div); + it('should be able to clear on handler added before load zone.js', function () { + const TestTarget: any = (window as any)['TestTarget']; + patchFilteredProperties( + TestTarget.prototype, + ['prop3'], + global['__Zone_ignore_on_properties'], + ); + const testTarget = new TestTarget(); + Zone.current.fork({name: 'test'}).run(() => { + expect(testTarget.onprop3).toBeTruthy(); + const newProp3Handler = function () {}; + testTarget.onprop3 = newProp3Handler; + expect(testTarget.onprop3).toBe(newProp3Handler); + testTarget.onprop3 = null; + expect(!testTarget.onprop3).toBeTruthy(); + testTarget.onprop3 = function () { + // onprop1 should not be patched + expect(Zone.current.name).toEqual('test'); + }; + }); - Zone.current.fork({name: 'scroll'}).run(() => { - const listener = () => { - expect(Zone.current.name).toEqual(zone.name); - div.removeEventListener('scroll', listener); - }; - div.addEventListener('scroll', listener); - }); + Zone.current.fork({name: 'test1'}).run(() => { + testTarget.dispatchEvent('prop3'); + }); + }); - zone.run(() => { - div.dispatchEvent(scrollEvent); - }); - document.body.removeChild(div); - }); - - it('non function property starts with on but not event listener should still work as expected', - () => { - (window as any).one_two_three = {foo: 'bar'}; - - expect((window as any).one_two_three).toEqual({foo: 'bar'}); - (window as any).one_two_three = {bar: 'foo'}; - expect((window as any).one_two_three).toEqual({bar: 'foo'}); - (window as any).one_two_three = null; - expect((window as any).one_two_three).toBeNull(); - }); - - it('function property starts with on but not event listener should still work as expected', - () => { - let called = false; - const func = function() { - called = true; - }; - (window as any).one_two_three = func; - - expect((window as any).one_two_three).toEqual(func); - expect(called).toBeFalse(); - (window as any).one_two_three(); - expect(called).toBeTrue(); - (window as any).one_two_three = null; - expect((window as any).one_two_three).toBeNull(); - }); - - it('should be able to clear on handler added before load zone.js', function() { - const TestTarget: any = (window as any)['TestTarget']; - patchFilteredProperties( - TestTarget.prototype, ['prop3'], global['__Zone_ignore_on_properties']); - const testTarget = new TestTarget(); - Zone.current.fork({name: 'test'}).run(() => { - expect(testTarget.onprop3).toBeTruthy(); - const newProp3Handler = function() {}; - testTarget.onprop3 = newProp3Handler; - expect(testTarget.onprop3).toBe(newProp3Handler); - testTarget.onprop3 = null; - expect(!testTarget.onprop3).toBeTruthy(); - testTarget.onprop3 = function() { - // onprop1 should not be patched - expect(Zone.current.name).toEqual('test'); - }; + it( + 'window onmousedown should be in zone', + ifEnvSupports(canPatchOnProperty(window, 'onmousedown'), function () { + zone.run(function () { + window.onmousedown = eventListenerSpy; }); - Zone.current.fork({name: 'test1'}).run(() => { - testTarget.dispatchEvent('prop3'); + window.dispatchEvent(mouseEvent); + + expect(hookSpy).toHaveBeenCalled(); + expect(eventListenerSpy).toHaveBeenCalled(); + window.removeEventListener('mousedown', eventListenerSpy); + expect((window as any)[zoneSymbol('ON_PROPERTYmousedown')]).toEqual(eventListenerSpy); + window.onmousedown = null; + expect(!!(window as any)[zoneSymbol('ON_PROPERTYmousedown')]).toBeFalsy(); + }), + ); + + it( + 'window onresize should be patched', + ifEnvSupports(canPatchOnProperty(window, 'onmousedown'), function () { + window.onresize = eventListenerSpy; + const innerResizeProp: any = (window as any)[zoneSymbol('ON_PROPERTYresize')]; + expect(innerResizeProp).toBeTruthy(); + innerResizeProp(); + expect(eventListenerSpy).toHaveBeenCalled(); + window.removeEventListener('resize', eventListenerSpy); + expect((window as any)[zoneSymbol('ON_PROPERTYresize')]).toEqual(eventListenerSpy); + window.onresize = null; + expect(!!(window as any)[zoneSymbol('ON_PROPERTYresize')]).toBeFalsy(); + }), + ); + + it( + 'document onmousedown should be in zone', + ifEnvSupports(canPatchOnProperty(Document.prototype, 'onmousedown'), function () { + zone.run(function () { + document.onmousedown = eventListenerSpy; }); - }); - it('window onmousedown should be in zone', - ifEnvSupports(canPatchOnProperty(window, 'onmousedown'), function() { - zone.run(function() { - window.onmousedown = eventListenerSpy; - }); - - window.dispatchEvent(mouseEvent); - - expect(hookSpy).toHaveBeenCalled(); - expect(eventListenerSpy).toHaveBeenCalled(); - window.removeEventListener('mousedown', eventListenerSpy); - expect((window as any)[zoneSymbol('ON_PROPERTYmousedown')]) - .toEqual(eventListenerSpy); - window.onmousedown = null; - expect(!!(window as any)[zoneSymbol('ON_PROPERTYmousedown')]).toBeFalsy(); - })); - - it('window onresize should be patched', - ifEnvSupports(canPatchOnProperty(window, 'onmousedown'), function() { - window.onresize = eventListenerSpy; - const innerResizeProp: any = (window as any)[zoneSymbol('ON_PROPERTYresize')]; - expect(innerResizeProp).toBeTruthy(); - innerResizeProp(); - expect(eventListenerSpy).toHaveBeenCalled(); - window.removeEventListener('resize', eventListenerSpy); - expect((window as any)[zoneSymbol('ON_PROPERTYresize')]).toEqual(eventListenerSpy); - window.onresize = null; - expect(!!(window as any)[zoneSymbol('ON_PROPERTYresize')]).toBeFalsy(); - })); - - it('document onmousedown should be in zone', - ifEnvSupports(canPatchOnProperty(Document.prototype, 'onmousedown'), function() { - zone.run(function() { - document.onmousedown = eventListenerSpy; - }); - - document.dispatchEvent(mouseEvent); - - expect(hookSpy).toHaveBeenCalled(); - expect(eventListenerSpy).toHaveBeenCalled(); - document.removeEventListener('mousedown', eventListenerSpy); - expect((document as any)[zoneSymbol('ON_PROPERTYmousedown')]) - .toEqual(eventListenerSpy); - document.onmousedown = null; - expect(!!(document as any)[zoneSymbol('ON_PROPERTYmousedown')]).toBeFalsy(); - })); - - // TODO: JiaLiPassion, need to find out why the test bundle is not `use strict`. - xit('event handler with null context should use event.target', - ifEnvSupports(canPatchOnProperty(Document.prototype, 'onmousedown'), function() { - const logs: string[] = []; - const EventTarget = (window as any)['EventTarget']; - let oriAddEventListener = EventTarget && EventTarget.prototype ? - (EventTarget.prototype as any)[zoneSymbol('addEventListener')] : - (HTMLSpanElement.prototype as any)[zoneSymbol('addEventListener')]; - - if (!oriAddEventListener) { - // no patched addEventListener found - return; - } - let handler1: Function; - let handler2: Function; + document.dispatchEvent(mouseEvent); + + expect(hookSpy).toHaveBeenCalled(); + expect(eventListenerSpy).toHaveBeenCalled(); + document.removeEventListener('mousedown', eventListenerSpy); + expect((document as any)[zoneSymbol('ON_PROPERTYmousedown')]).toEqual(eventListenerSpy); + document.onmousedown = null; + expect(!!(document as any)[zoneSymbol('ON_PROPERTYmousedown')]).toBeFalsy(); + }), + ); + + // TODO: JiaLiPassion, need to find out why the test bundle is not `use strict`. + xit( + 'event handler with null context should use event.target', + ifEnvSupports(canPatchOnProperty(Document.prototype, 'onmousedown'), function () { + const logs: string[] = []; + const EventTarget = (window as any)['EventTarget']; + let oriAddEventListener = + EventTarget && EventTarget.prototype + ? (EventTarget.prototype as any)[zoneSymbol('addEventListener')] + : (HTMLSpanElement.prototype as any)[zoneSymbol('addEventListener')]; + + if (!oriAddEventListener) { + // no patched addEventListener found + return; + } + let handler1: Function; + let handler2: Function; - const listener = function() { - logs.push('listener1'); - }; + const listener = function () { + logs.push('listener1'); + }; - const listener1 = function() { - logs.push('listener2'); - }; + const listener1 = function () { + logs.push('listener2'); + }; - HTMLSpanElement.prototype.addEventListener = function( - eventName: string, callback: any) { - if (eventName === 'click') { - handler1 = callback; - } else if (eventName === 'mousedown') { - handler2 = callback; - } - return oriAddEventListener.apply(this, arguments); - }; + HTMLSpanElement.prototype.addEventListener = function ( + eventName: string, + callback: any, + ) { + if (eventName === 'click') { + handler1 = callback; + } else if (eventName === 'mousedown') { + handler2 = callback; + } + return oriAddEventListener.apply(this, arguments); + }; - (HTMLSpanElement.prototype as any)[zoneSymbol('addEventListener')] = null; + (HTMLSpanElement.prototype as any)[zoneSymbol('addEventListener')] = null; - patchEventTarget(window, null as any, [HTMLSpanElement.prototype]); + patchEventTarget(window, null as any, [HTMLSpanElement.prototype]); - const span = document.createElement('span'); - document.body.appendChild(span); + const span = document.createElement('span'); + document.body.appendChild(span); - zone.run(function() { - span.addEventListener('click', listener); - span.onmousedown = listener1; - }); + zone.run(function () { + span.addEventListener('click', listener); + span.onmousedown = listener1; + }); - expect(handler1!).toBe(handler2!); + expect(handler1!).toBe(handler2!); - handler1!.apply(null, [{type: 'click', target: span}]); + handler1!.apply(null, [{type: 'click', target: span}]); - handler2!.apply(null, [{type: 'mousedown', target: span}]); + handler2!.apply(null, [{type: 'mousedown', target: span}]); - expect(hookSpy).toHaveBeenCalled(); - expect(logs).toEqual(['listener1', 'listener2']); - document.body.removeChild(span); - if (EventTarget) { - (EventTarget.prototype as any)[zoneSymbol('addEventListener')] = - oriAddEventListener; - } else { - (HTMLSpanElement.prototype as any)[zoneSymbol('addEventListener')] = - oriAddEventListener; - } - })); - - it('SVGElement onmousedown should be in zone', - ifEnvSupports( - canPatchOnProperty(SVGElement && SVGElement.prototype, 'onmousedown'), function() { - const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - document.body.appendChild(svg); - zone.run(function() { - svg.onmousedown = eventListenerSpy; - }); - - svg.dispatchEvent(mouseEvent); - - expect(hookSpy).toHaveBeenCalled(); - expect(eventListenerSpy).toHaveBeenCalled(); - svg.removeEventListener('mouse', eventListenerSpy); - document.body.removeChild(svg); - })); - - it('get window onerror should not throw error', - ifEnvSupports(canPatchOnProperty(window, 'onerror'), function() { - const oriOnError = window.onerror; - const testFn = function() { - try { - let onerror = window.onerror; - window.onerror = function() {}; - onerror = window.onerror; - } finally { - window.onerror = oriOnError; - } - }; - expect(testFn).not.toThrow(); - })); - - it('window.onerror callback signature should be (message, source, lineno, colno, error)', - ifEnvSupportsWithDone(canPatchOnProperty(window, 'onerror'), function(done: DoneFn) { - const oriOnError = window.onerror; - let testError = new Error('testError'); - window.onerror = function( - message: any, source?: string, lineno?: number, colno?: number, error?: any) { - expect(message).toContain('testError'); - if (getEdgeVersion() !== 14) { - // Edge 14, error will be undefined. - expect(error).toBe(testError); - } - (window as any).onerror = oriOnError; - setTimeout(done); - return true; - }; - setTimeout(() => { - throw testError; - }, 100); - })); - })); - - describe('eventListener hooks', function() { + expect(hookSpy).toHaveBeenCalled(); + expect(logs).toEqual(['listener1', 'listener2']); + document.body.removeChild(span); + if (EventTarget) { + (EventTarget.prototype as any)[zoneSymbol('addEventListener')] = oriAddEventListener; + } else { + (HTMLSpanElement.prototype as any)[zoneSymbol('addEventListener')] = + oriAddEventListener; + } + }), + ); + + it( + 'SVGElement onmousedown should be in zone', + ifEnvSupports( + canPatchOnProperty(SVGElement && SVGElement.prototype, 'onmousedown'), + function () { + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + document.body.appendChild(svg); + zone.run(function () { + svg.onmousedown = eventListenerSpy; + }); + + svg.dispatchEvent(mouseEvent); + + expect(hookSpy).toHaveBeenCalled(); + expect(eventListenerSpy).toHaveBeenCalled(); + svg.removeEventListener('mouse', eventListenerSpy); + document.body.removeChild(svg); + }, + ), + ); + + it( + 'get window onerror should not throw error', + ifEnvSupports(canPatchOnProperty(window, 'onerror'), function () { + const oriOnError = window.onerror; + const testFn = function () { + try { + let onerror = window.onerror; + window.onerror = function () {}; + onerror = window.onerror; + } finally { + window.onerror = oriOnError; + } + }; + expect(testFn).not.toThrow(); + }), + ); + + it( + 'window.onerror callback signature should be (message, source, lineno, colno, error)', + ifEnvSupportsWithDone(canPatchOnProperty(window, 'onerror'), function (done: DoneFn) { + const oriOnError = window.onerror; + let testError = new Error('testError'); + window.onerror = function ( + message: any, + source?: string, + lineno?: number, + colno?: number, + error?: any, + ) { + expect(message).toContain('testError'); + if (getEdgeVersion() !== 14) { + // Edge 14, error will be undefined. + expect(error).toBe(testError); + } + (window as any).onerror = oriOnError; + setTimeout(done); + return true; + }; + setTimeout(() => { + throw testError; + }, 100); + }), + ); + }), + ); + + describe('eventListener hooks', function () { let button: HTMLButtonElement; let clickEvent: Event; - beforeEach(function() { + beforeEach(function () { button = document.createElement('button'); clickEvent = document.createEvent('Event'); clickEvent.initEvent('click', true, true); document.body.appendChild(button); }); - afterEach(function() { + afterEach(function () { document.body.removeChild(button); }); - it('should support addEventListener', function() { + it('should support addEventListener', function () { const hookSpy = jasmine.createSpy('hook'); const eventListenerSpy = jasmine.createSpy('eventListener'); const zone = rootZone.fork({ name: 'spy', - onScheduleTask: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - hookSpy(); - return parentZoneDelegate.scheduleTask(targetZone, task); - } + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy(); + return parentZoneDelegate.scheduleTask(targetZone, task); + }, }); - zone.run(function() { + zone.run(function () { button.addEventListener('click', eventListenerSpy); }); @@ -858,28 +1043,31 @@ describe('Zone', function() { expect(eventListenerSpy).toHaveBeenCalled(); }); - it('should be able to access addEventListener information in onScheduleTask', function() { + it('should be able to access addEventListener information in onScheduleTask', function () { const hookSpy = jasmine.createSpy('hook'); const eventListenerSpy = jasmine.createSpy('eventListener'); let scheduleButton; - let scheduleEventName: string|undefined; - let scheduleCapture: boolean|undefined; + let scheduleEventName: string | undefined; + let scheduleCapture: boolean | undefined; let scheduleTask; const zone = rootZone.fork({ name: 'spy', - onScheduleTask: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - hookSpy(); - scheduleButton = (task.data as any).taskData.target; - scheduleEventName = (task.data as any).taskData.eventName; - scheduleCapture = (task.data as any).taskData.capture; - scheduleTask = task; - return parentZoneDelegate.scheduleTask(targetZone, task); - } - }); - - zone.run(function() { + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy(); + scheduleButton = (task.data as any).taskData.target; + scheduleEventName = (task.data as any).taskData.eventName; + scheduleCapture = (task.data as any).taskData.capture; + scheduleTask = task; + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + }); + + zone.run(function () { button.addEventListener('click', eventListenerSpy); }); @@ -893,43 +1081,52 @@ describe('Zone', function() { expect(scheduleTask && (scheduleTask as any).data.taskData).toBe(null as any); }); - it('should support addEventListener on window', ifEnvSupports(windowPrototype, function() { - const hookSpy = jasmine.createSpy('hook'); - const eventListenerSpy = jasmine.createSpy('eventListener'); - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: ( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - hookSpy(); - return parentZoneDelegate.scheduleTask(targetZone, task); - } - }); - - zone.run(function() { - window.addEventListener('click', eventListenerSpy); - }); - - window.dispatchEvent(clickEvent); - - expect(hookSpy).toHaveBeenCalled(); - expect(eventListenerSpy).toHaveBeenCalled(); - })); - - it('should support removeEventListener', function() { + it( + 'should support addEventListener on window', + ifEnvSupports(windowPrototype, function () { + const hookSpy = jasmine.createSpy('hook'); + const eventListenerSpy = jasmine.createSpy('eventListener'); + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy(); + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + }); + + zone.run(function () { + window.addEventListener('click', eventListenerSpy); + }); + + window.dispatchEvent(clickEvent); + + expect(hookSpy).toHaveBeenCalled(); + expect(eventListenerSpy).toHaveBeenCalled(); + }), + ); + + it('should support removeEventListener', function () { const hookSpy = jasmine.createSpy('hook'); const eventListenerSpy = jasmine.createSpy('eventListener'); const zone = rootZone.fork({ name: 'spy', - onCancelTask: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - hookSpy(); - return parentZoneDelegate.cancelTask(targetZone, task); - } + onCancelTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy(); + return parentZoneDelegate.cancelTask(targetZone, task); + }, }); - zone.run(function() { + zone.run(function () { button.addEventListener('click', eventListenerSpy); button.removeEventListener('click', eventListenerSpy); }); @@ -941,503 +1138,590 @@ describe('Zone', function() { }); describe( - 'should support addEventListener/removeEventListener with AddEventListenerOptions with capture setting', - ifEnvSupports(supportEventListenerOptions, function() { - let hookSpy: Spy; - let cancelSpy: Spy; - let logs: string[]; - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - task: Task): any => { - hookSpy(); - return parentZoneDelegate.scheduleTask(targetZone, task); - }, - onCancelTask: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - task: Task): any => { - cancelSpy(); - return parentZoneDelegate.cancelTask(targetZone, task); - } - }); + 'should support addEventListener/removeEventListener with AddEventListenerOptions with capture setting', + ifEnvSupports(supportEventListenerOptions, function () { + let hookSpy: Spy; + let cancelSpy: Spy; + let logs: string[]; + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy(); + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + onCancelTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + cancelSpy(); + return parentZoneDelegate.cancelTask(targetZone, task); + }, + }); - const docListener = () => { - logs.push('document'); - }; - const btnListener = () => { - logs.push('button'); - }; + const docListener = () => { + logs.push('document'); + }; + const btnListener = () => { + logs.push('button'); + }; - beforeEach(() => { - logs = []; - hookSpy = jasmine.createSpy('hook'); - cancelSpy = jasmine.createSpy('cancel'); + beforeEach(() => { + logs = []; + hookSpy = jasmine.createSpy('hook'); + cancelSpy = jasmine.createSpy('cancel'); + }); + + it('should handle child event when addEventListener with capture true', () => { + // test capture true + zone.run(function () { + (document as any).addEventListener('click', docListener, {capture: true}); + button.addEventListener('click', btnListener); }); - it('should handle child event when addEventListener with capture true', () => { - // test capture true - zone.run(function() { - (document as any).addEventListener('click', docListener, {capture: true}); - button.addEventListener('click', btnListener); - }); + button.dispatchEvent(clickEvent); + expect(hookSpy).toHaveBeenCalled(); - button.dispatchEvent(clickEvent); - expect(hookSpy).toHaveBeenCalled(); + expect(logs).toEqual(['document', 'button']); + logs = []; - expect(logs).toEqual(['document', 'button']); - logs = []; + (document as any).removeEventListener('click', docListener, {capture: true}); + button.removeEventListener('click', btnListener); + expect(cancelSpy).toHaveBeenCalled(); - (document as any).removeEventListener('click', docListener, {capture: true}); - button.removeEventListener('click', btnListener); - expect(cancelSpy).toHaveBeenCalled(); + button.dispatchEvent(clickEvent); + expect(logs).toEqual([]); + }); - button.dispatchEvent(clickEvent); - expect(logs).toEqual([]); + it('should handle child event when addEventListener with capture true', () => { + // test capture false + zone.run(function () { + (document as any).addEventListener('click', docListener, {capture: false}); + button.addEventListener('click', btnListener); }); - it('should handle child event when addEventListener with capture true', () => { - // test capture false - zone.run(function() { - (document as any).addEventListener('click', docListener, {capture: false}); - button.addEventListener('click', btnListener); - }); - - button.dispatchEvent(clickEvent); - expect(hookSpy).toHaveBeenCalled(); - expect(logs).toEqual(['button', 'document']); - logs = []; + button.dispatchEvent(clickEvent); + expect(hookSpy).toHaveBeenCalled(); + expect(logs).toEqual(['button', 'document']); + logs = []; - (document as any).removeEventListener('click', docListener, {capture: false}); - button.removeEventListener('click', btnListener); - expect(cancelSpy).toHaveBeenCalled(); + (document as any).removeEventListener('click', docListener, {capture: false}); + button.removeEventListener('click', btnListener); + expect(cancelSpy).toHaveBeenCalled(); - button.dispatchEvent(clickEvent); - expect(logs).toEqual([]); - }); - })); + button.dispatchEvent(clickEvent); + expect(logs).toEqual([]); + }); + }), + ); describe( - 'should ignore duplicate event handler', - ifEnvSupports(supportEventListenerOptions, function() { - let hookSpy: Spy; - let cancelSpy: Spy; - let logs: string[]; - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - task: Task): any => { - hookSpy(); - return parentZoneDelegate.scheduleTask(targetZone, task); - }, - onCancelTask: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - task: Task): any => { - cancelSpy(); - return parentZoneDelegate.cancelTask(targetZone, task); - } - }); - - const docListener = () => { - logs.push('document options'); - }; - - beforeEach(() => { - logs = []; - hookSpy = jasmine.createSpy('hook'); - cancelSpy = jasmine.createSpy('cancel'); - }); - - const testDuplicate = function(args1?: any, args2?: any) { - zone.run(function() { - if (args1) { - (document as any).addEventListener('click', docListener, args1); - } else { - (document as any).addEventListener('click', docListener); - } - if (args2) { - (document as any).addEventListener('click', docListener, args2); - } else { - (document as any).addEventListener('click', docListener); - } - }); + 'should ignore duplicate event handler', + ifEnvSupports(supportEventListenerOptions, function () { + let hookSpy: Spy; + let cancelSpy: Spy; + let logs: string[]; + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy(); + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + onCancelTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + cancelSpy(); + return parentZoneDelegate.cancelTask(targetZone, task); + }, + }); - button.dispatchEvent(clickEvent); - expect(hookSpy).toHaveBeenCalled(); - expect(logs).toEqual(['document options']); - logs = []; + const docListener = () => { + logs.push('document options'); + }; - (document as any).removeEventListener('click', docListener, args1); - expect(cancelSpy).toHaveBeenCalled(); - button.dispatchEvent(clickEvent); - expect(logs).toEqual([]); - }; + beforeEach(() => { + logs = []; + hookSpy = jasmine.createSpy('hook'); + cancelSpy = jasmine.createSpy('cancel'); + }); - it('should ignore duplicate handler', () => { - let captureFalse = [ - undefined, false, {capture: false}, {capture: false, passive: false}, - {passive: false}, {} - ]; - let captureTrue = [true, {capture: true}, {capture: true, passive: false}]; - for (let i = 0; i < captureFalse.length; i++) { - for (let j = 0; j < captureFalse.length; j++) { - testDuplicate(captureFalse[i], captureFalse[j]); - } + const testDuplicate = function (args1?: any, args2?: any) { + zone.run(function () { + if (args1) { + (document as any).addEventListener('click', docListener, args1); + } else { + (document as any).addEventListener('click', docListener); } - for (let i = 0; i < captureTrue.length; i++) { - for (let j = 0; j < captureTrue.length; j++) { - testDuplicate(captureTrue[i], captureTrue[j]); - } + if (args2) { + (document as any).addEventListener('click', docListener, args2); + } else { + (document as any).addEventListener('click', docListener); } }); - })); - - describe( - 'should support mix useCapture with AddEventListenerOptions capture', - ifEnvSupports(supportEventListenerOptions, function() { - let hookSpy: Spy; - let cancelSpy: Spy; - let logs: string[]; - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - task: Task): any => { - hookSpy(); - return parentZoneDelegate.scheduleTask(targetZone, task); - }, - onCancelTask: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - task: Task): any => { - cancelSpy(); - return parentZoneDelegate.cancelTask(targetZone, task); - } - }); - const docListener = () => { - logs.push('document options'); - }; - const docListener1 = () => { - logs.push('document useCapture'); - }; - const btnListener = () => { - logs.push('button'); - }; + button.dispatchEvent(clickEvent); + expect(hookSpy).toHaveBeenCalled(); + expect(logs).toEqual(['document options']); + logs = []; - beforeEach(() => { - logs = []; - hookSpy = jasmine.createSpy('hook'); - cancelSpy = jasmine.createSpy('cancel'); - }); + (document as any).removeEventListener('click', docListener, args1); + expect(cancelSpy).toHaveBeenCalled(); + button.dispatchEvent(clickEvent); + expect(logs).toEqual([]); + }; - const testAddRemove = function(args1?: any, args2?: any) { - zone.run(function() { - if (args1) { - (document as any).addEventListener('click', docListener, args1); - } else { - (document as any).addEventListener('click', docListener); - } - if (args2) { - (document as any).removeEventListener('click', docListener, args2); - } else { - (document as any).removeEventListener('click', docListener); - } - }); + it('should ignore duplicate handler', () => { + let captureFalse = [ + undefined, + false, + {capture: false}, + {capture: false, passive: false}, + {passive: false}, + {}, + ]; + let captureTrue = [true, {capture: true}, {capture: true, passive: false}]; + for (let i = 0; i < captureFalse.length; i++) { + for (let j = 0; j < captureFalse.length; j++) { + testDuplicate(captureFalse[i], captureFalse[j]); + } + } + for (let i = 0; i < captureTrue.length; i++) { + for (let j = 0; j < captureTrue.length; j++) { + testDuplicate(captureTrue[i], captureTrue[j]); + } + } + }); + }), + ); - button.dispatchEvent(clickEvent); - expect(cancelSpy).toHaveBeenCalled(); - expect(logs).toEqual([]); - }; + describe( + 'should support mix useCapture with AddEventListenerOptions capture', + ifEnvSupports(supportEventListenerOptions, function () { + let hookSpy: Spy; + let cancelSpy: Spy; + let logs: string[]; + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy(); + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + onCancelTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + cancelSpy(); + return parentZoneDelegate.cancelTask(targetZone, task); + }, + }); - it('should be able to add/remove same handler with mix options and capture', - function() { - let captureFalse = [ - undefined, false, {capture: false}, {capture: false, passive: false}, - {passive: false}, {} - ]; - let captureTrue = [true, {capture: true}, {capture: true, passive: false}]; - for (let i = 0; i < captureFalse.length; i++) { - for (let j = 0; j < captureFalse.length; j++) { - testAddRemove(captureFalse[i], captureFalse[j]); - } - } - for (let i = 0; i < captureTrue.length; i++) { - for (let j = 0; j < captureTrue.length; j++) { - testAddRemove(captureTrue[i], captureTrue[j]); - } - } - }); - - const testDifferent = function(args1?: any, args2?: any) { - zone.run(function() { - if (args1) { - (document as any).addEventListener('click', docListener, args1); - } else { - (document as any).addEventListener('click', docListener); - } - if (args2) { - (document as any).addEventListener('click', docListener1, args2); - } else { - (document as any).addEventListener('click', docListener1); - } - }); + const docListener = () => { + logs.push('document options'); + }; + const docListener1 = () => { + logs.push('document useCapture'); + }; + const btnListener = () => { + logs.push('button'); + }; - button.dispatchEvent(clickEvent); - expect(hookSpy).toHaveBeenCalled(); - expect(logs.sort()).toEqual(['document options', 'document useCapture']); - logs = []; + beforeEach(() => { + logs = []; + hookSpy = jasmine.createSpy('hook'); + cancelSpy = jasmine.createSpy('cancel'); + }); + const testAddRemove = function (args1?: any, args2?: any) { + zone.run(function () { if (args1) { - (document as any).removeEventListener('click', docListener, args1); + (document as any).addEventListener('click', docListener, args1); } else { - (document as any).removeEventListener('click', docListener); + (document as any).addEventListener('click', docListener); } - - button.dispatchEvent(clickEvent); - expect(logs).toEqual(['document useCapture']); - logs = []; - if (args2) { - (document as any).removeEventListener('click', docListener1, args2); + (document as any).removeEventListener('click', docListener, args2); } else { - (document as any).removeEventListener('click', docListener1); + (document as any).removeEventListener('click', docListener); } + }); - button.dispatchEvent(clickEvent); - expect(logs).toEqual([]); - }; + button.dispatchEvent(clickEvent); + expect(cancelSpy).toHaveBeenCalled(); + expect(logs).toEqual([]); + }; - it('should be able to add different handlers for same event', function() { - let captureFalse = [ - undefined, false, {capture: false}, {capture: false, passive: false}, - {passive: false}, {} - ]; - let captureTrue = [true, {capture: true}, {capture: true, passive: false}]; - for (let i = 0; i < captureFalse.length; i++) { - for (let j = 0; j < captureTrue.length; j++) { - testDifferent(captureFalse[i], captureTrue[j]); - } + it('should be able to add/remove same handler with mix options and capture', function () { + let captureFalse = [ + undefined, + false, + {capture: false}, + {capture: false, passive: false}, + {passive: false}, + {}, + ]; + let captureTrue = [true, {capture: true}, {capture: true, passive: false}]; + for (let i = 0; i < captureFalse.length; i++) { + for (let j = 0; j < captureFalse.length; j++) { + testAddRemove(captureFalse[i], captureFalse[j]); } - for (let i = 0; i < captureTrue.length; i++) { - for (let j = 0; j < captureFalse.length; j++) { - testDifferent(captureTrue[i], captureFalse[j]); - } + } + for (let i = 0; i < captureTrue.length; i++) { + for (let j = 0; j < captureTrue.length; j++) { + testAddRemove(captureTrue[i], captureTrue[j]); + } + } + }); + + const testDifferent = function (args1?: any, args2?: any) { + zone.run(function () { + if (args1) { + (document as any).addEventListener('click', docListener, args1); + } else { + (document as any).addEventListener('click', docListener); + } + if (args2) { + (document as any).addEventListener('click', docListener1, args2); + } else { + (document as any).addEventListener('click', docListener1); } }); - it('should handle options.capture true with capture true correctly', function() { - zone.run(function() { - (document as any).addEventListener('click', docListener, {capture: true}); - document.addEventListener('click', docListener1, true); - button.addEventListener('click', btnListener); - }); + button.dispatchEvent(clickEvent); + expect(hookSpy).toHaveBeenCalled(); + expect(logs.sort()).toEqual(['document options', 'document useCapture']); + logs = []; - button.dispatchEvent(clickEvent); - expect(hookSpy).toHaveBeenCalled(); - expect(logs).toEqual(['document options', 'document useCapture', 'button']); - logs = []; + if (args1) { + (document as any).removeEventListener('click', docListener, args1); + } else { + (document as any).removeEventListener('click', docListener); + } - (document as any).removeEventListener('click', docListener, {capture: true}); - button.dispatchEvent(clickEvent); - expect(logs).toEqual(['document useCapture', 'button']); - logs = []; + button.dispatchEvent(clickEvent); + expect(logs).toEqual(['document useCapture']); + logs = []; - document.removeEventListener('click', docListener1, true); - button.dispatchEvent(clickEvent); - expect(logs).toEqual(['button']); - logs = []; + if (args2) { + (document as any).removeEventListener('click', docListener1, args2); + } else { + (document as any).removeEventListener('click', docListener1); + } - button.removeEventListener('click', btnListener); - expect(cancelSpy).toHaveBeenCalled(); + button.dispatchEvent(clickEvent); + expect(logs).toEqual([]); + }; - button.dispatchEvent(clickEvent); - expect(logs).toEqual([]); - (document as any).removeAllListeners('click'); + it('should be able to add different handlers for same event', function () { + let captureFalse = [ + undefined, + false, + {capture: false}, + {capture: false, passive: false}, + {passive: false}, + {}, + ]; + let captureTrue = [true, {capture: true}, {capture: true, passive: false}]; + for (let i = 0; i < captureFalse.length; i++) { + for (let j = 0; j < captureTrue.length; j++) { + testDifferent(captureFalse[i], captureTrue[j]); + } + } + for (let i = 0; i < captureTrue.length; i++) { + for (let j = 0; j < captureFalse.length; j++) { + testDifferent(captureTrue[i], captureFalse[j]); + } + } + }); + + it('should handle options.capture true with capture true correctly', function () { + zone.run(function () { + (document as any).addEventListener('click', docListener, {capture: true}); + document.addEventListener('click', docListener1, true); + button.addEventListener('click', btnListener); }); - })); - - it('should support addEventListener with AddEventListenerOptions once setting', - ifEnvSupports(supportEventListenerOptions, function() { - let hookSpy = jasmine.createSpy('hook'); - let logs: string[] = []; - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: ( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - hookSpy(); - return parentZoneDelegate.scheduleTask(targetZone, task); - } - }); - - zone.run(function() { - (button as any).addEventListener('click', function() { - logs.push('click'); - }, {once: true}); - }); - - button.dispatchEvent(clickEvent); - - expect(hookSpy).toHaveBeenCalled(); - expect(logs.length).toBe(1); - expect(logs).toEqual(['click']); - logs = []; - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(0); - })); - - it('should support addEventListener with AddEventListenerOptions once setting and capture', - ifEnvSupports(supportEventListenerOptions, function() { - let hookSpy = jasmine.createSpy('hook'); - let logs: string[] = []; - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: ( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - hookSpy(); - return parentZoneDelegate.scheduleTask(targetZone, task); - } - }); - - zone.run(function() { - (button as any).addEventListener('click', function() { - logs.push('click'); - }, {once: true, capture: true}); - }); - - button.dispatchEvent(clickEvent); - - expect(hookSpy).toHaveBeenCalled(); - expect(logs.length).toBe(1); - expect(logs).toEqual(['click']); - logs = []; - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(0); - })); - - - it('should support add multiple listeners with AddEventListenerOptions once setting and same capture after normal listener', - ifEnvSupports(supportEventListenerOptions, function() { - let logs: string[] = []; - - button.addEventListener('click', function() { - logs.push('click'); - }, true); - (button as any).addEventListener('click', function() { - logs.push('once click'); - }, {once: true, capture: true}); - - button.dispatchEvent(clickEvent); - - expect(logs.length).toBe(2); - expect(logs).toEqual(['click', 'once click']); - logs = []; - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(logs).toEqual(['click']); - })); - - it('should support add multiple listeners with AddEventListenerOptions once setting and mixed capture after normal listener', - ifEnvSupports(supportEventListenerOptions, function() { - let logs: string[] = []; - - button.addEventListener('click', function() { - logs.push('click'); - }); - (button as any).addEventListener('click', function() { - logs.push('once click'); - }, {once: true, capture: true}); - - button.dispatchEvent(clickEvent); - - expect(logs.length).toBe(2); - expect(logs).toEqual(['once click', 'click']); - logs = []; - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(logs).toEqual(['click']); - })); - - it('should support add multiple listeners with AddEventListenerOptions once setting before normal listener', - ifEnvSupports(supportEventListenerOptions, function() { - let logs: string[] = []; - - (button as any).addEventListener('click', function() { - logs.push('once click'); - }, {once: true}); - - button.addEventListener('click', function() { - logs.push('click'); - }); - - button.dispatchEvent(clickEvent); - - expect(logs.length).toBe(2); - expect(logs).toEqual(['once click', 'click']); - logs = []; - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(logs).toEqual(['click']); - })); - - it('should support add multiple listeners with AddEventListenerOptions once setting with same capture before normal listener', - ifEnvSupports(supportEventListenerOptions, function() { - let logs: string[] = []; - - (button as any).addEventListener('click', function() { - logs.push('once click'); - }, {once: true, capture: true}); - button.addEventListener('click', function() { - logs.push('click'); - }, true); + button.dispatchEvent(clickEvent); + expect(hookSpy).toHaveBeenCalled(); + expect(logs).toEqual(['document options', 'document useCapture', 'button']); + logs = []; + + (document as any).removeEventListener('click', docListener, {capture: true}); + button.dispatchEvent(clickEvent); + expect(logs).toEqual(['document useCapture', 'button']); + logs = []; + + document.removeEventListener('click', docListener1, true); + button.dispatchEvent(clickEvent); + expect(logs).toEqual(['button']); + logs = []; + + button.removeEventListener('click', btnListener); + expect(cancelSpy).toHaveBeenCalled(); + + button.dispatchEvent(clickEvent); + expect(logs).toEqual([]); + (document as any).removeAllListeners('click'); + }); + }), + ); + + it( + 'should support addEventListener with AddEventListenerOptions once setting', + ifEnvSupports(supportEventListenerOptions, function () { + let hookSpy = jasmine.createSpy('hook'); + let logs: string[] = []; + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy(); + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + }); + + zone.run(function () { + (button as any).addEventListener( + 'click', + function () { + logs.push('click'); + }, + {once: true}, + ); + }); + + button.dispatchEvent(clickEvent); + + expect(hookSpy).toHaveBeenCalled(); + expect(logs.length).toBe(1); + expect(logs).toEqual(['click']); + logs = []; + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(0); + }), + ); + + it( + 'should support addEventListener with AddEventListenerOptions once setting and capture', + ifEnvSupports(supportEventListenerOptions, function () { + let hookSpy = jasmine.createSpy('hook'); + let logs: string[] = []; + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy(); + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + }); + + zone.run(function () { + (button as any).addEventListener( + 'click', + function () { + logs.push('click'); + }, + {once: true, capture: true}, + ); + }); + + button.dispatchEvent(clickEvent); + + expect(hookSpy).toHaveBeenCalled(); + expect(logs.length).toBe(1); + expect(logs).toEqual(['click']); + logs = []; + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(0); + }), + ); + + it( + 'should support add multiple listeners with AddEventListenerOptions once setting and same capture after normal listener', + ifEnvSupports(supportEventListenerOptions, function () { + let logs: string[] = []; + + button.addEventListener( + 'click', + function () { + logs.push('click'); + }, + true, + ); + (button as any).addEventListener( + 'click', + function () { + logs.push('once click'); + }, + {once: true, capture: true}, + ); + + button.dispatchEvent(clickEvent); + + expect(logs.length).toBe(2); + expect(logs).toEqual(['click', 'once click']); + logs = []; + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['click']); + }), + ); + + it( + 'should support add multiple listeners with AddEventListenerOptions once setting and mixed capture after normal listener', + ifEnvSupports(supportEventListenerOptions, function () { + let logs: string[] = []; + + button.addEventListener('click', function () { + logs.push('click'); + }); + (button as any).addEventListener( + 'click', + function () { + logs.push('once click'); + }, + {once: true, capture: true}, + ); + + button.dispatchEvent(clickEvent); + + expect(logs.length).toBe(2); + expect(logs).toEqual(['once click', 'click']); + logs = []; + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['click']); + }), + ); + + it( + 'should support add multiple listeners with AddEventListenerOptions once setting before normal listener', + ifEnvSupports(supportEventListenerOptions, function () { + let logs: string[] = []; + + (button as any).addEventListener( + 'click', + function () { + logs.push('once click'); + }, + {once: true}, + ); + + button.addEventListener('click', function () { + logs.push('click'); + }); + + button.dispatchEvent(clickEvent); + + expect(logs.length).toBe(2); + expect(logs).toEqual(['once click', 'click']); + logs = []; + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['click']); + }), + ); + + it( + 'should support add multiple listeners with AddEventListenerOptions once setting with same capture before normal listener', + ifEnvSupports(supportEventListenerOptions, function () { + let logs: string[] = []; + + (button as any).addEventListener( + 'click', + function () { + logs.push('once click'); + }, + {once: true, capture: true}, + ); - button.dispatchEvent(clickEvent); + button.addEventListener( + 'click', + function () { + logs.push('click'); + }, + true, + ); - expect(logs.length).toBe(2); - expect(logs).toEqual(['once click', 'click']); - logs = []; + button.dispatchEvent(clickEvent); - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(logs).toEqual(['click']); - })); + expect(logs.length).toBe(2); + expect(logs).toEqual(['once click', 'click']); + logs = []; - it('should support add multiple listeners with AddEventListenerOptions once setting with mixed capture before normal listener', - ifEnvSupports(supportEventListenerOptions, function() { - let logs: string[] = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['click']); + }), + ); + + it( + 'should support add multiple listeners with AddEventListenerOptions once setting with mixed capture before normal listener', + ifEnvSupports(supportEventListenerOptions, function () { + let logs: string[] = []; - (button as any).addEventListener('click', function() { - logs.push('once click'); - }, {once: true, capture: true}); + (button as any).addEventListener( + 'click', + function () { + logs.push('once click'); + }, + {once: true, capture: true}, + ); - button.addEventListener('click', function() { - logs.push('click'); - }); + button.addEventListener('click', function () { + logs.push('click'); + }); - button.dispatchEvent(clickEvent); + button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['once click', 'click']); - logs = []; + expect(logs.length).toBe(2); + expect(logs).toEqual(['once click', 'click']); + logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(logs).toEqual(['click']); - })); + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['click']); + }), + ); it('should change options to boolean if not support passive', () => { patchEventTarget(window, null as any, [TestEventListener.prototype]); const testEventListener = new TestEventListener(); - const listener = function() {}; + const listener = function () {}; testEventListener.addEventListener('test', listener, {passive: true}); testEventListener.addEventListener('test1', listener, {once: true}); testEventListener.addEventListener('test2', listener, {capture: true}); @@ -1448,8 +1732,12 @@ describe('Zone', function() { expect(testEventListener.logs).toEqual([false, false, true, false, false, false]); } else { expect(testEventListener.logs).toEqual([ - {passive: true}, {once: true}, {capture: true}, {passive: false}, {once: false}, - {capture: false} + {passive: true}, + {once: true}, + {capture: true}, + {passive: false}, + {once: false}, + {capture: false}, ]); } }); @@ -1473,37 +1761,42 @@ describe('Zone', function() { button.removeEventListener('click', listener); }); - it('should support addEventListener with AddEventListenerOptions passive setting', - ifEnvSupports(supportEventListenerOptions, function() { - const hookSpy = jasmine.createSpy('hook'); - const logs: string[] = []; - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: ( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - hookSpy(); - return parentZoneDelegate.scheduleTask(targetZone, task); - } - }); - - const listener = (e: Event) => { - logs.push(e.defaultPrevented.toString()); - e.preventDefault(); - logs.push(e.defaultPrevented.toString()); - }; - - zone.run(function() { - (button as any).addEventListener('click', listener, {passive: true}); - }); - - button.dispatchEvent(clickEvent); - - expect(hookSpy).toHaveBeenCalled(); - expect(logs).toEqual(['false', 'false']); - - button.removeEventListener('click', listener); - })); + it( + 'should support addEventListener with AddEventListenerOptions passive setting', + ifEnvSupports(supportEventListenerOptions, function () { + const hookSpy = jasmine.createSpy('hook'); + const logs: string[] = []; + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy(); + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + }); + + const listener = (e: Event) => { + logs.push(e.defaultPrevented.toString()); + e.preventDefault(); + logs.push(e.defaultPrevented.toString()); + }; + + zone.run(function () { + (button as any).addEventListener('click', listener, {passive: true}); + }); + + button.dispatchEvent(clickEvent); + + expect(hookSpy).toHaveBeenCalled(); + expect(logs).toEqual(['false', 'false']); + + button.removeEventListener('click', listener); + }), + ); describe('passiveEvents by global settings', () => { let logs: string[] = []; @@ -1512,7 +1805,7 @@ describe('Zone', function() { e.preventDefault(); logs.push(e.defaultPrevented ? 'defaultPrevented' : 'default will run'); }; - const testPassive = function(eventName: string, expectedPassiveLog: string, options: any) { + const testPassive = function (eventName: string, expectedPassiveLog: string, options: any) { (button as any).addEventListener(eventName, listener, options); const evt = document.createEvent('Event'); evt.initEvent(eventName, false, true); @@ -1536,10 +1829,9 @@ describe('Zone', function() { it('should be passive with global variable defined even without passive options', () => { testPassive('touchstart', 'default will run', undefined); }); - it('should be passive with global variable defined even without passive options and with capture', - () => { - testPassive('touchstart', 'default will run', {capture: true}); - }); + it('should be passive with global variable defined even without passive options and with capture', () => { + testPassive('touchstart', 'default will run', {capture: true}); + }); it('should be passive with global variable defined with capture option', () => { testPassive('touchstart', 'default will run', true); }); @@ -1554,58 +1846,66 @@ describe('Zone', function() { }); }); - it('should support Event.stopImmediatePropagation', - ifEnvSupports(supportEventListenerOptions, function() { - const hookSpy = jasmine.createSpy('hook'); - const logs: any[] = []; - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: ( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - hookSpy(); - return parentZoneDelegate.scheduleTask(targetZone, task); - } - }); - - const listener1 = (e: Event) => { - logs.push('listener1'); - e.stopImmediatePropagation(); - }; - - const listener2 = (e: Event) => { - logs.push('listener2'); - }; - - zone.run(function() { - (button as any).addEventListener('click', listener1); - (button as any).addEventListener('click', listener2); - }); - - button.dispatchEvent(clickEvent); - - expect(hookSpy).toHaveBeenCalled(); - expect(logs).toEqual(['listener1']); - - button.removeEventListener('click', listener1); - button.removeEventListener('click', listener2); - })); - - it('should support remove event listener by call zone.cancelTask directly', function() { + it( + 'should support Event.stopImmediatePropagation', + ifEnvSupports(supportEventListenerOptions, function () { + const hookSpy = jasmine.createSpy('hook'); + const logs: any[] = []; + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy(); + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + }); + + const listener1 = (e: Event) => { + logs.push('listener1'); + e.stopImmediatePropagation(); + }; + + const listener2 = (e: Event) => { + logs.push('listener2'); + }; + + zone.run(function () { + (button as any).addEventListener('click', listener1); + (button as any).addEventListener('click', listener2); + }); + + button.dispatchEvent(clickEvent); + + expect(hookSpy).toHaveBeenCalled(); + expect(logs).toEqual(['listener1']); + + button.removeEventListener('click', listener1); + button.removeEventListener('click', listener2); + }), + ); + + it('should support remove event listener by call zone.cancelTask directly', function () { let logs: string[] = []; let eventTask: Task; const zone = rootZone.fork({ name: 'spy', - onScheduleTask: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - eventTask = task; - return parentZoneDelegate.scheduleTask(targetZone, task); - } + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + eventTask = task; + return parentZoneDelegate.scheduleTask(targetZone, task); + }, }); zone.run(() => { - button.addEventListener('click', function() { + button.addEventListener('click', function () { logs.push('click'); }); }); @@ -1619,162 +1919,194 @@ describe('Zone', function() { expect(listeners.length).toBe(0); }); - it('should support remove event listener by call zone.cancelTask directly with capture=true', - function() { - let logs: string[] = []; - let eventTask: Task; - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: ( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - eventTask = task; - return parentZoneDelegate.scheduleTask(targetZone, task); - } - }); - - zone.run(() => { - button.addEventListener('click', function() { - logs.push('click'); - }, true); - }); - let listeners = button.eventListeners!('click'); - expect(listeners.length).toBe(1); - eventTask!.zone.cancelTask(eventTask!); - - listeners = button.eventListeners!('click'); - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(0); - expect(listeners.length).toBe(0); - }); - - it('should support remove event listeners by call zone.cancelTask directly with multiple listeners', - function() { - let logs: string[] = []; - let eventTask: Task; - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: ( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - eventTask = task; - return parentZoneDelegate.scheduleTask(targetZone, task); - } - }); - - zone.run(() => { - button.addEventListener('click', function() { - logs.push('click1'); - }); - }); - button.addEventListener('click', function() { - logs.push('click2'); - }); - let listeners = button.eventListeners!('click'); - expect(listeners.length).toBe(2); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['click1', 'click2']); - eventTask!.zone.cancelTask(eventTask!); - logs = []; - - listeners = button.eventListeners!('click'); - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(listeners.length).toBe(1); - expect(logs).toEqual(['click2']); - }); - - it('should support remove event listeners by call zone.cancelTask directly with multiple listeners with same capture=true', - function() { - let logs: string[] = []; - let eventTask: Task; - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: ( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - eventTask = task; - return parentZoneDelegate.scheduleTask(targetZone, task); - } - }); - - zone.run(() => { - button.addEventListener('click', function() { - logs.push('click1'); - }, true); - }); - button.addEventListener('click', function() { - logs.push('click2'); - }, true); - let listeners = button.eventListeners!('click'); - expect(listeners.length).toBe(2); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['click1', 'click2']); - eventTask!.zone.cancelTask(eventTask!); - logs = []; - - listeners = button.eventListeners!('click'); - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(listeners.length).toBe(1); - expect(logs).toEqual(['click2']); - }); - - it('should support remove event listeners by call zone.cancelTask directly with multiple listeners with mixed capture', - function() { - let logs: string[] = []; - let eventTask: Task; - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: ( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - eventTask = task; - return parentZoneDelegate.scheduleTask(targetZone, task); - } - }); - - zone.run(() => { - button.addEventListener('click', function() { - logs.push('click1'); - }, true); - }); - button.addEventListener('click', function() { - logs.push('click2'); - }); - let listeners = button.eventListeners!('click'); - expect(listeners.length).toBe(2); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['click1', 'click2']); - eventTask!.zone.cancelTask(eventTask!); - logs = []; - - listeners = button.eventListeners!('click'); - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(listeners.length).toBe(1); - expect(logs).toEqual(['click2']); - }); - - it('should support remove event listeners via AbortController', function() { + it('should support remove event listener by call zone.cancelTask directly with capture=true', function () { + let logs: string[] = []; + let eventTask: Task; + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + eventTask = task; + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + }); + + zone.run(() => { + button.addEventListener( + 'click', + function () { + logs.push('click'); + }, + true, + ); + }); + let listeners = button.eventListeners!('click'); + expect(listeners.length).toBe(1); + eventTask!.zone.cancelTask(eventTask!); + + listeners = button.eventListeners!('click'); + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(0); + expect(listeners.length).toBe(0); + }); + + it('should support remove event listeners by call zone.cancelTask directly with multiple listeners', function () { + let logs: string[] = []; + let eventTask: Task; + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + eventTask = task; + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + }); + + zone.run(() => { + button.addEventListener('click', function () { + logs.push('click1'); + }); + }); + button.addEventListener('click', function () { + logs.push('click2'); + }); + let listeners = button.eventListeners!('click'); + expect(listeners.length).toBe(2); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['click1', 'click2']); + eventTask!.zone.cancelTask(eventTask!); + logs = []; + + listeners = button.eventListeners!('click'); + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(listeners.length).toBe(1); + expect(logs).toEqual(['click2']); + }); + + it('should support remove event listeners by call zone.cancelTask directly with multiple listeners with same capture=true', function () { + let logs: string[] = []; + let eventTask: Task; + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + eventTask = task; + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + }); + + zone.run(() => { + button.addEventListener( + 'click', + function () { + logs.push('click1'); + }, + true, + ); + }); + button.addEventListener( + 'click', + function () { + logs.push('click2'); + }, + true, + ); + let listeners = button.eventListeners!('click'); + expect(listeners.length).toBe(2); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['click1', 'click2']); + eventTask!.zone.cancelTask(eventTask!); + logs = []; + + listeners = button.eventListeners!('click'); + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(listeners.length).toBe(1); + expect(logs).toEqual(['click2']); + }); + + it('should support remove event listeners by call zone.cancelTask directly with multiple listeners with mixed capture', function () { + let logs: string[] = []; + let eventTask: Task; + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + eventTask = task; + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + }); + + zone.run(() => { + button.addEventListener( + 'click', + function () { + logs.push('click1'); + }, + true, + ); + }); + button.addEventListener('click', function () { + logs.push('click2'); + }); + let listeners = button.eventListeners!('click'); + expect(listeners.length).toBe(2); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['click1', 'click2']); + eventTask!.zone.cancelTask(eventTask!); + logs = []; + + listeners = button.eventListeners!('click'); + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(listeners.length).toBe(1); + expect(logs).toEqual(['click2']); + }); + + it('should support remove event listeners via AbortController', function () { let logs: string[] = []; const ac = new AbortController(); - button.addEventListener('click', function() { - logs.push('click1'); - }, {signal: ac.signal}); - button.addEventListener('click', function() { + button.addEventListener( + 'click', + function () { + logs.push('click1'); + }, + {signal: ac.signal}, + ); + button.addEventListener('click', function () { logs.push('click2'); }); - button.addEventListener('click', function() { - logs.push('click3'); - }, {signal: ac.signal}); + button.addEventListener( + 'click', + function () { + logs.push('click3'); + }, + {signal: ac.signal}, + ); let listeners = button.eventListeners!('click'); expect(listeners.length).toBe(3); @@ -1791,15 +2123,15 @@ describe('Zone', function() { expect(logs).toEqual(['click2']); }); - it('should support remove event listeners with AbortController', function() { + it('should support remove event listeners with AbortController', function () { let logs: string[] = []; const ac = new AbortController(); - const listener1 = function() { + const listener1 = function () { logs.push('click1'); }; button.addEventListener('click', listener1, {signal: ac.signal}); - button.addEventListener('click', function() { + button.addEventListener('click', function () { logs.push('click2'); }); let listeners = button.eventListeners!('click'); @@ -1822,15 +2154,15 @@ describe('Zone', function() { expect(logs).toEqual(['click2']); }); - it('should not break remove event listeners with AbortController', function() { + it('should not break remove event listeners with AbortController', function () { let logs: string[] = []; const ac = new AbortController(); - const listener1 = function() { + const listener1 = function () { logs.push('click1'); }; button.addEventListener('click', listener1, {signal: ac.signal}); - button.addEventListener('click', function() { + button.addEventListener('click', function () { logs.push('click2'); }); let listeners = button.eventListeners!('click'); @@ -1853,200 +2185,234 @@ describe('Zone', function() { expect(logs).toEqual(['click2']); }); - it('should support remove multiple event listeners with the same AbortController', - function() { - let logs: string[] = []; - const ac = new AbortController(); - const button1 = document.createElement('button'); - const keyEvent: any = document.createEvent('KeyboardEvent'); - keyEvent.initKeyboardEvent( - 'keypress', // typeArg, - true, // canBubbleArg, - true, // cancelableArg, - null, // viewArg, Specifies UIEvent.view. This value may be null. - '', - 0, - false, // ctrlKeyArg, - false, // altKeyArg, - false, // shiftKeyArg, - false, // metaKeyArg, - ); - document.body.appendChild(button1); - - const listener1 = function() { - logs.push('click1'); - }; - button.addEventListener('click', listener1, {signal: ac.signal}); - button.addEventListener('click', function() { - logs.push('click2'); - }); - button1.addEventListener('keypress', () => logs.push('click3'), {signal: ac.signal}); - button1.addEventListener('keypress', function() { - logs.push('click4'); - }); - let listeners = button.eventListeners!('click'); - expect(listeners.length).toBe(2); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['click1', 'click2']); - button1.dispatchEvent(keyEvent); - expect(logs.length).toBe(4); - expect(logs).toEqual(['click1', 'click2', 'click3', 'click4']); - - logs = []; - ac.abort(); - listeners = button.eventListeners!('click'); - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(listeners.length).toBe(1); - expect(logs).toEqual(['click2']); - button1.dispatchEvent(keyEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['click2', 'click4']); - }); - - it('should not add event listeners with aborted signal', function() { + it('should support remove multiple event listeners with the same AbortController', function () { let logs: string[] = []; - - button.addEventListener('click', function() { + const ac = new AbortController(); + const button1 = document.createElement('button'); + const keyEvent: any = document.createEvent('KeyboardEvent'); + keyEvent.initKeyboardEvent( + 'keypress', // typeArg, + true, // canBubbleArg, + true, // cancelableArg, + null, // viewArg, Specifies UIEvent.view. This value may be null. + '', + 0, + false, // ctrlKeyArg, + false, // altKeyArg, + false, // shiftKeyArg, + false, // metaKeyArg, + ); + document.body.appendChild(button1); + + const listener1 = function () { logs.push('click1'); - }, {signal: AbortSignal.abort()}); - button.addEventListener('click', function() { + }; + button.addEventListener('click', listener1, {signal: ac.signal}); + button.addEventListener('click', function () { logs.push('click2'); }); + button1.addEventListener('keypress', () => logs.push('click3'), {signal: ac.signal}); + button1.addEventListener('keypress', function () { + logs.push('click4'); + }); let listeners = button.eventListeners!('click'); - expect(listeners.length).toBe(1); + expect(listeners.length).toBe(2); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['click1', 'click2']); + button1.dispatchEvent(keyEvent); + expect(logs.length).toBe(4); + expect(logs).toEqual(['click1', 'click2', 'click3', 'click4']); + logs = []; + ac.abort(); + listeners = button.eventListeners!('click'); button.dispatchEvent(clickEvent); expect(logs.length).toBe(1); + expect(listeners.length).toBe(1); expect(logs).toEqual(['click2']); + button1.dispatchEvent(keyEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['click2', 'click4']); }); - it('should remove event listeners with timeout signal', - ifEnvSupportsWithDone( - () => typeof AbortSignal.timeout === 'function', function(done: DoneFn) { - let logs: string[] = []; - - button.addEventListener('click', function() { - logs.push('click1'); - }, {signal: AbortSignal.timeout(1)}); - button.addEventListener('click', function() { - logs.push('click2'); - }); - let listeners = button.eventListeners!('click'); - expect(listeners.length).toBe(2); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['click1', 'click2']); - - setTimeout(() => { - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(logs).toEqual(['click2']); - done(); - }, 10); - })); - - it('should support reschedule eventTask', - ifEnvSupports(supportEventListenerOptions, function() { - let hookSpy1 = jasmine.createSpy('spy1'); - let hookSpy2 = jasmine.createSpy('spy2'); - let hookSpy3 = jasmine.createSpy('spy3'); - let logs: string[] = []; - const isUnpatchedEvent = function(source: string) { - return source.lastIndexOf('click') !== -1; - }; - const zone1 = Zone.current.fork({ - name: 'zone1', - onScheduleTask: ( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - if ((task.type === 'eventTask' || task.type === 'macroTask') && - isUnpatchedEvent(task.source)) { - task.cancelScheduleRequest(); - - return zone2.scheduleTask(task); - } else { - return parentZoneDelegate.scheduleTask(targetZone, task); - } - }, - onInvokeTask( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, - applyThis: any, applyArgs: any) { - hookSpy1(); - return parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs); - } - }); - const zone2 = Zone.current.fork({ - name: 'zone2', - onScheduleTask: ( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - hookSpy2(); - return parentZoneDelegate.scheduleTask(targetZone, task); - }, - onInvokeTask( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, - applyThis: any, applyArgs: any) { - hookSpy3(); - return parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs); - } - }); - - const listener = function() { - logs.push(Zone.current.name); - }; - zone1.run(() => { - button.addEventListener('click', listener); - button.addEventListener('mouseover', listener); - }); - - const clickEvent = document.createEvent('Event'); - clickEvent.initEvent('click', true, true); - const mouseEvent = document.createEvent('Event'); - mouseEvent.initEvent('mouseover', true, true); - - button.dispatchEvent(clickEvent); - button.removeEventListener('click', listener); - - expect(logs).toEqual(['zone2']); - expect(hookSpy1).not.toHaveBeenCalled(); - expect(hookSpy2).toHaveBeenCalled(); - expect(hookSpy3).toHaveBeenCalled(); - logs = []; - hookSpy2 = jasmine.createSpy('hookSpy2'); - hookSpy3 = jasmine.createSpy('hookSpy3'); - - button.dispatchEvent(mouseEvent); - button.removeEventListener('mouseover', listener); - expect(logs).toEqual(['zone1']); - expect(hookSpy1).toHaveBeenCalled(); - expect(hookSpy2).not.toHaveBeenCalled(); - expect(hookSpy3).not.toHaveBeenCalled(); - })); - - it('should support inline event handler attributes', function() { - const hookSpy = jasmine.createSpy('hook'); - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - hookSpy(); - return parentZoneDelegate.scheduleTask(targetZone, task); - } - }); + it('should not add event listeners with aborted signal', function () { + let logs: string[] = []; - zone.run(function() { - button.setAttribute('onclick', 'return'); - expect(button.onclick).not.toBe(null); + button.addEventListener( + 'click', + function () { + logs.push('click1'); + }, + {signal: AbortSignal.abort()}, + ); + button.addEventListener('click', function () { + logs.push('click2'); }); - }); + let listeners = button.eventListeners!('click'); + expect(listeners.length).toBe(1); - it('should not remove onEventListener when removing capture listener', function() { + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['click2']); + }); + + it( + 'should remove event listeners with timeout signal', + ifEnvSupportsWithDone( + () => typeof AbortSignal.timeout === 'function', + function (done: DoneFn) { + let logs: string[] = []; + + button.addEventListener( + 'click', + function () { + logs.push('click1'); + }, + {signal: AbortSignal.timeout(1)}, + ); + button.addEventListener('click', function () { + logs.push('click2'); + }); + let listeners = button.eventListeners!('click'); + expect(listeners.length).toBe(2); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['click1', 'click2']); + + setTimeout(() => { + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['click2']); + done(); + }, 10); + }, + ), + ); + + it( + 'should support reschedule eventTask', + ifEnvSupports(supportEventListenerOptions, function () { + let hookSpy1 = jasmine.createSpy('spy1'); + let hookSpy2 = jasmine.createSpy('spy2'); + let hookSpy3 = jasmine.createSpy('spy3'); + let logs: string[] = []; + const isUnpatchedEvent = function (source: string) { + return source.lastIndexOf('click') !== -1; + }; + const zone1 = Zone.current.fork({ + name: 'zone1', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + if ( + (task.type === 'eventTask' || task.type === 'macroTask') && + isUnpatchedEvent(task.source) + ) { + task.cancelScheduleRequest(); + + return zone2.scheduleTask(task); + } else { + return parentZoneDelegate.scheduleTask(targetZone, task); + } + }, + onInvokeTask( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + applyThis: any, + applyArgs: any, + ) { + hookSpy1(); + return parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs); + }, + }); + const zone2 = Zone.current.fork({ + name: 'zone2', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy2(); + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + onInvokeTask( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + applyThis: any, + applyArgs: any, + ) { + hookSpy3(); + return parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs); + }, + }); + + const listener = function () { + logs.push(Zone.current.name); + }; + zone1.run(() => { + button.addEventListener('click', listener); + button.addEventListener('mouseover', listener); + }); + + const clickEvent = document.createEvent('Event'); + clickEvent.initEvent('click', true, true); + const mouseEvent = document.createEvent('Event'); + mouseEvent.initEvent('mouseover', true, true); + + button.dispatchEvent(clickEvent); + button.removeEventListener('click', listener); + + expect(logs).toEqual(['zone2']); + expect(hookSpy1).not.toHaveBeenCalled(); + expect(hookSpy2).toHaveBeenCalled(); + expect(hookSpy3).toHaveBeenCalled(); + logs = []; + hookSpy2 = jasmine.createSpy('hookSpy2'); + hookSpy3 = jasmine.createSpy('hookSpy3'); + + button.dispatchEvent(mouseEvent); + button.removeEventListener('mouseover', listener); + expect(logs).toEqual(['zone1']); + expect(hookSpy1).toHaveBeenCalled(); + expect(hookSpy2).not.toHaveBeenCalled(); + expect(hookSpy3).not.toHaveBeenCalled(); + }), + ); + + it('should support inline event handler attributes', function () { + const hookSpy = jasmine.createSpy('hook'); + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy(); + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + }); + + zone.run(function () { + button.setAttribute('onclick', 'return'); + expect(button.onclick).not.toBe(null); + }); + }); + + it('should not remove onEventListener when removing capture listener', function () { const button = document.createElement('button'); document.body.append(button); const createEvt = () => { @@ -2081,20 +2447,20 @@ describe('Zone', function() { document.body.removeChild(button); }); - describe('should be able to remove eventListener during eventListener callback', function() { - it('should be able to remove eventListener during eventListener callback', function() { + describe('should be able to remove eventListener during eventListener callback', function () { + it('should be able to remove eventListener during eventListener callback', function () { let logs: string[] = []; - const listener1 = function() { + const listener1 = function () { button.removeEventListener('click', listener1); logs.push('listener1'); }; - const listener2 = function() { + const listener2 = function () { logs.push('listener2'); }; const listener3 = { - handleEvent: function(event: Event) { + handleEvent: function (event: Event) { logs.push('listener3'); - } + }, }; button.addEventListener('click', listener1); @@ -2114,744 +2480,799 @@ describe('Zone', function() { button.removeEventListener('click', listener3); }); - it('should be able to remove eventListener during eventListener callback with capture=true', - function() { - let logs: string[] = []; - const listener1 = function() { - button.removeEventListener('click', listener1, true); - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - } - }; - - button.addEventListener('click', listener1, true); - button.addEventListener('click', listener2, true); - button.addEventListener('click', listener3, true); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(3); - expect(logs).toEqual(['listener1', 'listener2', 'listener3']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['listener2', 'listener3']); - - button.removeEventListener('click', listener2, true); - button.removeEventListener('click', listener3, true); - }); - - it('should be able to remove handleEvent eventListener during eventListener callback', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - button.removeEventListener('click', listener3); - } - }; - - button.addEventListener('click', listener1); - button.addEventListener('click', listener2); - button.addEventListener('click', listener3); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(3); - expect(logs).toEqual(['listener1', 'listener2', 'listener3']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['listener1', 'listener2']); - - button.removeEventListener('click', listener1); - button.removeEventListener('click', listener2); - }); - - it('should be able to remove handleEvent eventListener during eventListener callback with capture=true', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - button.removeEventListener('click', listener3, true); - } - }; - - button.addEventListener('click', listener1, true); - button.addEventListener('click', listener2, true); - button.addEventListener('click', listener3, true); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(3); - expect(logs).toEqual(['listener1', 'listener2', 'listener3']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['listener1', 'listener2']); - - button.removeEventListener('click', listener1, true); - button.removeEventListener('click', listener2, true); - }); - - it('should be able to remove multiple eventListeners during eventListener callback', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - button.removeEventListener('click', listener2); - button.removeEventListener('click', listener3); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - } - }; - - button.addEventListener('click', listener1); - button.addEventListener('click', listener2); - button.addEventListener('click', listener3); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(logs).toEqual(['listener1']); - - button.removeEventListener('click', listener1); - }); - - it('should be able to remove multiple eventListeners during eventListener callback with capture=true', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - button.removeEventListener('click', listener2, true); - button.removeEventListener('click', listener3, true); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - } - }; - - button.addEventListener('click', listener1, true); - button.addEventListener('click', listener2, true); - button.addEventListener('click', listener3, true); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(logs).toEqual(['listener1']); - - button.removeEventListener('click', listener1, true); - }); - - it('should be able to remove part of other eventListener during eventListener callback', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - button.removeEventListener('click', listener2); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - } - }; - - button.addEventListener('click', listener1); - button.addEventListener('click', listener2); - button.addEventListener('click', listener3); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['listener1', 'listener3']); - - button.removeEventListener('click', listener1); - button.removeEventListener('click', listener3); - }); - - it('should be able to remove part of other eventListener during eventListener callback with capture=true', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - button.removeEventListener('click', listener2, true); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - } - }; - - button.addEventListener('click', listener1, true); - button.addEventListener('click', listener2, true); - button.addEventListener('click', listener3, true); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['listener1', 'listener3']); - - button.removeEventListener('click', listener1, true); - button.removeEventListener('click', listener3, true); - }); - - it('should be able to remove all beforeward and afterward eventListener during eventListener callback', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - button.removeEventListener('click', listener1); - button.removeEventListener('click', listener3); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - } - }; - - button.addEventListener('click', listener1); - button.addEventListener('click', listener2); - button.addEventListener('click', listener3); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['listener1', 'listener2']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(logs).toEqual(['listener2']); - - button.removeEventListener('click', listener2); - }); - - it('should be able to remove all beforeward and afterward eventListener during eventListener callback with capture=true', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - button.removeEventListener('click', listener1, true); - button.removeEventListener('click', listener3, true); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - } - }; - - button.addEventListener('click', listener1, true); - button.addEventListener('click', listener2, true); - button.addEventListener('click', listener3, true); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['listener1', 'listener2']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(logs).toEqual(['listener2']); - - button.removeEventListener('click', listener2, true); - }); - - it('should be able to remove part of beforeward and afterward eventListener during eventListener callback', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - button.removeEventListener('click', listener2); - button.removeEventListener('click', listener4); - } - }; - const listener4 = function() { - logs.push('listener4'); - }; - const listener5 = function() { - logs.push('listener5'); - }; - - button.addEventListener('click', listener1); - button.addEventListener('click', listener2); - button.addEventListener('click', listener3); - button.addEventListener('click', listener4); - button.addEventListener('click', listener5); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(4); - expect(logs).toEqual(['listener1', 'listener2', 'listener3', 'listener5']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(3); - expect(logs).toEqual(['listener1', 'listener3', 'listener5']); - - button.removeEventListener('click', listener1); - button.removeEventListener('click', listener3); - button.removeEventListener('click', listener5); - }); - - it('should be able to remove part of beforeward and afterward eventListener during eventListener callback with capture=true', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - button.removeEventListener('click', listener2, true); - button.removeEventListener('click', listener4, true); - } - }; - const listener4 = function() { - logs.push('listener4'); - }; - const listener5 = function() { - logs.push('listener5'); - }; - - button.addEventListener('click', listener1, true); - button.addEventListener('click', listener2, true); - button.addEventListener('click', listener3, true); - button.addEventListener('click', listener4, true); - button.addEventListener('click', listener5, true); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(4); - expect(logs).toEqual(['listener1', 'listener2', 'listener3', 'listener5']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(3); - expect(logs).toEqual(['listener1', 'listener3', 'listener5']); - - button.removeEventListener('click', listener1, true); - button.removeEventListener('click', listener3, true); - button.removeEventListener('click', listener5, true); - }); - - it('should be able to remove all beforeward eventListener during eventListener callback', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - button.removeEventListener('click', listener1); - button.removeEventListener('click', listener2); - } - }; - - button.addEventListener('click', listener1); - button.addEventListener('click', listener2); - button.addEventListener('click', listener3); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(3); - expect(logs).toEqual(['listener1', 'listener2', 'listener3']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(logs).toEqual(['listener3']); - - button.removeEventListener('click', listener3); - }); - - it('should be able to remove all beforeward eventListener during eventListener callback with capture=true', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - button.removeEventListener('click', listener1, true); - button.removeEventListener('click', listener2, true); - } - }; - - button.addEventListener('click', listener1, true); - button.addEventListener('click', listener2, true); - button.addEventListener('click', listener3, true); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(3); - expect(logs).toEqual(['listener1', 'listener2', 'listener3']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(logs).toEqual(['listener3']); - - button.removeEventListener('click', listener3, true); - }); - - it('should be able to remove part of beforeward eventListener during eventListener callback', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - button.removeEventListener('click', listener1); - } - }; - - button.addEventListener('click', listener1); - button.addEventListener('click', listener2); - button.addEventListener('click', listener3); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(3); - expect(logs).toEqual(['listener1', 'listener2', 'listener3']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['listener2', 'listener3']); - - button.removeEventListener('click', listener2); - button.removeEventListener('click', listener3); - }); - - it('should be able to remove part of beforeward eventListener during eventListener callback with capture=true', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - button.removeEventListener('click', listener1, true); - } - }; - - button.addEventListener('click', listener1, true); - button.addEventListener('click', listener2, true); - button.addEventListener('click', listener3, true); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(3); - expect(logs).toEqual(['listener1', 'listener2', 'listener3']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['listener2', 'listener3']); - - button.removeEventListener('click', listener2, true); - button.removeEventListener('click', listener3, true); - }); - - it('should be able to remove all eventListeners during first eventListener callback', - function() { - let logs: string[] = []; - const listener1 = function() { - button.removeAllListeners!('click'); - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - } - }; - - button.addEventListener('click', listener1); - button.addEventListener('click', listener2); - button.addEventListener('click', listener3); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(logs).toEqual(['listener1']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(0); - }); - - it('should be able to remove all eventListeners during first eventListener callback with capture=true', - function() { - let logs: string[] = []; - const listener1 = function() { - button.removeAllListeners!('click'); - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - } - }; - - button.addEventListener('click', listener1, true); - button.addEventListener('click', listener2, true); - button.addEventListener('click', listener3, true); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(1); - expect(logs).toEqual(['listener1']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(0); - }); - - it('should be able to remove all eventListeners during middle eventListener callback', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - button.removeAllListeners!('click'); - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - } - }; - - button.addEventListener('click', listener1); - button.addEventListener('click', listener2); - button.addEventListener('click', listener3); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['listener1', 'listener2']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(0); - }); - - it('should be able to remove all eventListeners during middle eventListener callback with capture=true', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - button.removeAllListeners!('click'); - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - } - }; - - button.addEventListener('click', listener1, true); - button.addEventListener('click', listener2, true); - button.addEventListener('click', listener3, true); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(2); - expect(logs).toEqual(['listener1', 'listener2']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(0); - }); - - it('should be able to remove all eventListeners during last eventListener callback', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - button.removeAllListeners!('click'); - } - }; - - button.addEventListener('click', listener1); - button.addEventListener('click', listener2); - button.addEventListener('click', listener3); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(3); - expect(logs).toEqual(['listener1', 'listener2', 'listener3']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(0); - }); - - it('should be able to remove all eventListeners during last eventListener callback with capture=true', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - button.removeAllListeners!('click'); - } - }; - - button.addEventListener('click', listener1, true); - button.addEventListener('click', listener2, true); - button.addEventListener('click', listener3, true); - - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(3); - expect(logs).toEqual(['listener1', 'listener2', 'listener3']); - - logs = []; - button.dispatchEvent(clickEvent); - expect(logs.length).toBe(0); - }); - }); + it('should be able to remove eventListener during eventListener callback with capture=true', function () { + let logs: string[] = []; + const listener1 = function () { + button.removeEventListener('click', listener1, true); + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + }, + }; - it('should be able to get eventListeners of specified event form EventTarget', function() { - const listener1 = function() {}; - const listener2 = function() {}; - const listener3 = {handleEvent: function(event: Event) {}}; - const listener4 = function() {}; + button.addEventListener('click', listener1, true); + button.addEventListener('click', listener2, true); + button.addEventListener('click', listener3, true); - button.addEventListener('click', listener1); - button.addEventListener('click', listener2); - button.addEventListener('click', listener3); - button.addEventListener('mouseover', listener4); + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(3); + expect(logs).toEqual(['listener1', 'listener2', 'listener3']); - const listeners = button.eventListeners!('click'); - expect(listeners.length).toBe(3); - expect(listeners).toEqual([listener1, listener2, listener3]); - button.removeEventListener('click', listener1); - button.removeEventListener('click', listener2); - button.removeEventListener('click', listener3); - }); + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['listener2', 'listener3']); + + button.removeEventListener('click', listener2, true); + button.removeEventListener('click', listener3, true); + }); + + it('should be able to remove handleEvent eventListener during eventListener callback', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + button.removeEventListener('click', listener3); + }, + }; + + button.addEventListener('click', listener1); + button.addEventListener('click', listener2); + button.addEventListener('click', listener3); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(3); + expect(logs).toEqual(['listener1', 'listener2', 'listener3']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['listener1', 'listener2']); + + button.removeEventListener('click', listener1); + button.removeEventListener('click', listener2); + }); + + it('should be able to remove handleEvent eventListener during eventListener callback with capture=true', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + button.removeEventListener('click', listener3, true); + }, + }; + + button.addEventListener('click', listener1, true); + button.addEventListener('click', listener2, true); + button.addEventListener('click', listener3, true); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(3); + expect(logs).toEqual(['listener1', 'listener2', 'listener3']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['listener1', 'listener2']); + + button.removeEventListener('click', listener1, true); + button.removeEventListener('click', listener2, true); + }); + + it('should be able to remove multiple eventListeners during eventListener callback', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + button.removeEventListener('click', listener2); + button.removeEventListener('click', listener3); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + }, + }; + + button.addEventListener('click', listener1); + button.addEventListener('click', listener2); + button.addEventListener('click', listener3); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['listener1']); + + button.removeEventListener('click', listener1); + }); + + it('should be able to remove multiple eventListeners during eventListener callback with capture=true', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + button.removeEventListener('click', listener2, true); + button.removeEventListener('click', listener3, true); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + }, + }; + + button.addEventListener('click', listener1, true); + button.addEventListener('click', listener2, true); + button.addEventListener('click', listener3, true); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['listener1']); + + button.removeEventListener('click', listener1, true); + }); + + it('should be able to remove part of other eventListener during eventListener callback', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + button.removeEventListener('click', listener2); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + }, + }; + + button.addEventListener('click', listener1); + button.addEventListener('click', listener2); + button.addEventListener('click', listener3); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['listener1', 'listener3']); + + button.removeEventListener('click', listener1); + button.removeEventListener('click', listener3); + }); + + it('should be able to remove part of other eventListener during eventListener callback with capture=true', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + button.removeEventListener('click', listener2, true); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + }, + }; + + button.addEventListener('click', listener1, true); + button.addEventListener('click', listener2, true); + button.addEventListener('click', listener3, true); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['listener1', 'listener3']); + + button.removeEventListener('click', listener1, true); + button.removeEventListener('click', listener3, true); + }); + + it('should be able to remove all beforeward and afterward eventListener during eventListener callback', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + button.removeEventListener('click', listener1); + button.removeEventListener('click', listener3); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + }, + }; + + button.addEventListener('click', listener1); + button.addEventListener('click', listener2); + button.addEventListener('click', listener3); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['listener1', 'listener2']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['listener2']); + + button.removeEventListener('click', listener2); + }); + + it('should be able to remove all beforeward and afterward eventListener during eventListener callback with capture=true', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + button.removeEventListener('click', listener1, true); + button.removeEventListener('click', listener3, true); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + }, + }; + + button.addEventListener('click', listener1, true); + button.addEventListener('click', listener2, true); + button.addEventListener('click', listener3, true); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['listener1', 'listener2']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['listener2']); + + button.removeEventListener('click', listener2, true); + }); + + it('should be able to remove part of beforeward and afterward eventListener during eventListener callback', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + button.removeEventListener('click', listener2); + button.removeEventListener('click', listener4); + }, + }; + const listener4 = function () { + logs.push('listener4'); + }; + const listener5 = function () { + logs.push('listener5'); + }; + + button.addEventListener('click', listener1); + button.addEventListener('click', listener2); + button.addEventListener('click', listener3); + button.addEventListener('click', listener4); + button.addEventListener('click', listener5); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(4); + expect(logs).toEqual(['listener1', 'listener2', 'listener3', 'listener5']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(3); + expect(logs).toEqual(['listener1', 'listener3', 'listener5']); + + button.removeEventListener('click', listener1); + button.removeEventListener('click', listener3); + button.removeEventListener('click', listener5); + }); + + it('should be able to remove part of beforeward and afterward eventListener during eventListener callback with capture=true', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + button.removeEventListener('click', listener2, true); + button.removeEventListener('click', listener4, true); + }, + }; + const listener4 = function () { + logs.push('listener4'); + }; + const listener5 = function () { + logs.push('listener5'); + }; + + button.addEventListener('click', listener1, true); + button.addEventListener('click', listener2, true); + button.addEventListener('click', listener3, true); + button.addEventListener('click', listener4, true); + button.addEventListener('click', listener5, true); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(4); + expect(logs).toEqual(['listener1', 'listener2', 'listener3', 'listener5']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(3); + expect(logs).toEqual(['listener1', 'listener3', 'listener5']); + + button.removeEventListener('click', listener1, true); + button.removeEventListener('click', listener3, true); + button.removeEventListener('click', listener5, true); + }); + + it('should be able to remove all beforeward eventListener during eventListener callback', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + button.removeEventListener('click', listener1); + button.removeEventListener('click', listener2); + }, + }; + + button.addEventListener('click', listener1); + button.addEventListener('click', listener2); + button.addEventListener('click', listener3); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(3); + expect(logs).toEqual(['listener1', 'listener2', 'listener3']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['listener3']); + + button.removeEventListener('click', listener3); + }); + + it('should be able to remove all beforeward eventListener during eventListener callback with capture=true', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + button.removeEventListener('click', listener1, true); + button.removeEventListener('click', listener2, true); + }, + }; + + button.addEventListener('click', listener1, true); + button.addEventListener('click', listener2, true); + button.addEventListener('click', listener3, true); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(3); + expect(logs).toEqual(['listener1', 'listener2', 'listener3']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['listener3']); + + button.removeEventListener('click', listener3, true); + }); + + it('should be able to remove part of beforeward eventListener during eventListener callback', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + button.removeEventListener('click', listener1); + }, + }; + + button.addEventListener('click', listener1); + button.addEventListener('click', listener2); + button.addEventListener('click', listener3); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(3); + expect(logs).toEqual(['listener1', 'listener2', 'listener3']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['listener2', 'listener3']); + + button.removeEventListener('click', listener2); + button.removeEventListener('click', listener3); + }); + + it('should be able to remove part of beforeward eventListener during eventListener callback with capture=true', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + button.removeEventListener('click', listener1, true); + }, + }; + + button.addEventListener('click', listener1, true); + button.addEventListener('click', listener2, true); + button.addEventListener('click', listener3, true); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(3); + expect(logs).toEqual(['listener1', 'listener2', 'listener3']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['listener2', 'listener3']); + + button.removeEventListener('click', listener2, true); + button.removeEventListener('click', listener3, true); + }); + + it('should be able to remove all eventListeners during first eventListener callback', function () { + let logs: string[] = []; + const listener1 = function () { + button.removeAllListeners!('click'); + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + }, + }; + + button.addEventListener('click', listener1); + button.addEventListener('click', listener2); + button.addEventListener('click', listener3); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['listener1']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(0); + }); + + it('should be able to remove all eventListeners during first eventListener callback with capture=true', function () { + let logs: string[] = []; + const listener1 = function () { + button.removeAllListeners!('click'); + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + }, + }; + + button.addEventListener('click', listener1, true); + button.addEventListener('click', listener2, true); + button.addEventListener('click', listener3, true); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(1); + expect(logs).toEqual(['listener1']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(0); + }); + + it('should be able to remove all eventListeners during middle eventListener callback', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + button.removeAllListeners!('click'); + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + }, + }; + + button.addEventListener('click', listener1); + button.addEventListener('click', listener2); + button.addEventListener('click', listener3); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['listener1', 'listener2']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(0); + }); + + it('should be able to remove all eventListeners during middle eventListener callback with capture=true', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + button.removeAllListeners!('click'); + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + }, + }; + + button.addEventListener('click', listener1, true); + button.addEventListener('click', listener2, true); + button.addEventListener('click', listener3, true); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(2); + expect(logs).toEqual(['listener1', 'listener2']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(0); + }); + + it('should be able to remove all eventListeners during last eventListener callback', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + button.removeAllListeners!('click'); + }, + }; + + button.addEventListener('click', listener1); + button.addEventListener('click', listener2); + button.addEventListener('click', listener3); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(3); + expect(logs).toEqual(['listener1', 'listener2', 'listener3']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(0); + }); + + it('should be able to remove all eventListeners during last eventListener callback with capture=true', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + button.removeAllListeners!('click'); + }, + }; + + button.addEventListener('click', listener1, true); + button.addEventListener('click', listener2, true); + button.addEventListener('click', listener3, true); + + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(3); + expect(logs).toEqual(['listener1', 'listener2', 'listener3']); + + logs = []; + button.dispatchEvent(clickEvent); + expect(logs.length).toBe(0); + }); + }); + + it('should be able to get eventListeners of specified event form EventTarget', function () { + const listener1 = function () {}; + const listener2 = function () {}; + const listener3 = {handleEvent: function (event: Event) {}}; + const listener4 = function () {}; + + button.addEventListener('click', listener1); + button.addEventListener('click', listener2); + button.addEventListener('click', listener3); + button.addEventListener('mouseover', listener4); + + const listeners = button.eventListeners!('click'); + expect(listeners.length).toBe(3); + expect(listeners).toEqual([listener1, listener2, listener3]); + button.removeEventListener('click', listener1); + button.removeEventListener('click', listener2); + button.removeEventListener('click', listener3); + }); + + it('should be able to get all eventListeners form EventTarget without eventName', function () { + const listener1 = function () {}; + const listener2 = function () {}; + const listener3 = {handleEvent: function (event: Event) {}}; + + button.addEventListener('click', listener1); + button.addEventListener('mouseover', listener2); + button.addEventListener('mousehover', listener3); + + const listeners = button.eventListeners!(); + expect(listeners.length).toBe(3); + expect(listeners).toEqual([listener1, listener2, listener3]); + button.removeEventListener('click', listener1); + button.removeEventListener('mouseover', listener2); + button.removeEventListener('mousehover', listener3); + }); + + it('should be able to remove all listeners of specified event form EventTarget', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + }, + }; + const listener4 = function () { + logs.push('listener4'); + }; + const listener5 = function () { + logs.push('listener5'); + }; + + button.addEventListener('mouseover', listener1); + button.addEventListener('mouseover', listener2); + button.addEventListener('mouseover', listener3); + button.addEventListener('click', listener4); + button.onmouseover = listener5; + expect((button as any)[Zone.__symbol__('ON_PROPERTYmouseover')]).toEqual(listener5); + + button.removeAllListeners!('mouseover'); + const listeners = button.eventListeners!('mouseover'); + expect(listeners.length).toBe(0); + expect((button as any)[Zone.__symbol__('ON_PROPERTYmouseover')]).toBeNull(); + expect(!!button.onmouseover).toBeFalsy(); + + const mouseEvent = document.createEvent('Event'); + mouseEvent.initEvent('mouseover', true, true); + + button.dispatchEvent(mouseEvent); + expect(logs).toEqual([]); + + button.dispatchEvent(clickEvent); + expect(logs).toEqual(['listener4']); + + button.removeEventListener('click', listener4); + }); + + it('should be able to remove all listeners of specified event form EventTarget with capture=true', function () { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + logs.push('listener2'); + }; + const listener3 = { + handleEvent: function (event: Event) { + logs.push('listener3'); + }, + }; + const listener4 = function () { + logs.push('listener4'); + }; + + button.addEventListener('mouseover', listener1, true); + button.addEventListener('mouseover', listener2, true); + button.addEventListener('mouseover', listener3, true); + button.addEventListener('click', listener4, true); + + button.removeAllListeners!('mouseover'); + const listeners = button.eventListeners!('mouseover'); + expect(listeners.length).toBe(0); - it('should be able to get all eventListeners form EventTarget without eventName', function() { - const listener1 = function() {}; - const listener2 = function() {}; - const listener3 = {handleEvent: function(event: Event) {}}; + const mouseEvent = document.createEvent('Event'); + mouseEvent.initEvent('mouseover', true, true); - button.addEventListener('click', listener1); - button.addEventListener('mouseover', listener2); - button.addEventListener('mousehover', listener3); + button.dispatchEvent(mouseEvent); + expect(logs).toEqual([]); - const listeners = button.eventListeners!(); - expect(listeners.length).toBe(3); - expect(listeners).toEqual([listener1, listener2, listener3]); - button.removeEventListener('click', listener1); - button.removeEventListener('mouseover', listener2); - button.removeEventListener('mousehover', listener3); + button.dispatchEvent(clickEvent); + expect(logs).toEqual(['listener4']); + + button.removeEventListener('click', listener4); }); - it('should be able to remove all listeners of specified event form EventTarget', function() { + it('should be able to remove all listeners of specified event form EventTarget with mixed capture', function () { let logs: string[] = []; - const listener1 = function() { + const listener1 = function () { logs.push('listener1'); }; - const listener2 = function() { + const listener2 = function () { logs.push('listener2'); }; const listener3 = { - handleEvent: function(event: Event) { + handleEvent: function (event: Event) { logs.push('listener3'); - } + }, }; - const listener4 = function() { + const listener4 = function () { logs.push('listener4'); }; - const listener5 = function() { - logs.push('listener5'); - }; - button.addEventListener('mouseover', listener1); - button.addEventListener('mouseover', listener2); - button.addEventListener('mouseover', listener3); - button.addEventListener('click', listener4); - button.onmouseover = listener5; - expect((button as any)[Zone.__symbol__('ON_PROPERTYmouseover')]).toEqual(listener5); + button.addEventListener('mouseover', listener1, true); + button.addEventListener('mouseover', listener2, false); + button.addEventListener('mouseover', listener3, true); + button.addEventListener('click', listener4, true); button.removeAllListeners!('mouseover'); const listeners = button.eventListeners!('mouseover'); expect(listeners.length).toBe(0); - expect((button as any)[Zone.__symbol__('ON_PROPERTYmouseover')]).toBeNull(); - expect(!!button.onmouseover).toBeFalsy(); const mouseEvent = document.createEvent('Event'); mouseEvent.initEvent('mouseover', true, true); @@ -2865,101 +3286,23 @@ describe('Zone', function() { button.removeEventListener('click', listener4); }); - it('should be able to remove all listeners of specified event form EventTarget with capture=true', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - } - }; - const listener4 = function() { - logs.push('listener4'); - }; - - button.addEventListener('mouseover', listener1, true); - button.addEventListener('mouseover', listener2, true); - button.addEventListener('mouseover', listener3, true); - button.addEventListener('click', listener4, true); - - button.removeAllListeners!('mouseover'); - const listeners = button.eventListeners!('mouseover'); - expect(listeners.length).toBe(0); - - const mouseEvent = document.createEvent('Event'); - mouseEvent.initEvent('mouseover', true, true); - - button.dispatchEvent(mouseEvent); - expect(logs).toEqual([]); - - button.dispatchEvent(clickEvent); - expect(logs).toEqual(['listener4']); - - button.removeEventListener('click', listener4); - }); - - it('should be able to remove all listeners of specified event form EventTarget with mixed capture', - function() { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - logs.push('listener2'); - }; - const listener3 = { - handleEvent: function(event: Event) { - logs.push('listener3'); - } - }; - const listener4 = function() { - logs.push('listener4'); - }; - - button.addEventListener('mouseover', listener1, true); - button.addEventListener('mouseover', listener2, false); - button.addEventListener('mouseover', listener3, true); - button.addEventListener('click', listener4, true); - - button.removeAllListeners!('mouseover'); - const listeners = button.eventListeners!('mouseover'); - expect(listeners.length).toBe(0); - - const mouseEvent = document.createEvent('Event'); - mouseEvent.initEvent('mouseover', true, true); - - button.dispatchEvent(mouseEvent); - expect(logs).toEqual([]); - - button.dispatchEvent(clickEvent); - expect(logs).toEqual(['listener4']); - - button.removeEventListener('click', listener4); - }); - - it('should be able to remove all listeners of all events form EventTarget', function() { + it('should be able to remove all listeners of all events form EventTarget', function () { let logs: string[] = []; - const listener1 = function() { + const listener1 = function () { logs.push('listener1'); }; - const listener2 = function() { + const listener2 = function () { logs.push('listener2'); }; const listener3 = { - handleEvent: function(event: Event) { + handleEvent: function (event: Event) { logs.push('listener3'); - } + }, }; - const listener4 = function() { + const listener4 = function () { logs.push('listener4'); }; - const listener5 = function() { + const listener5 = function () { logs.push('listener5'); }; @@ -2986,20 +3329,20 @@ describe('Zone', function() { expect(logs).toEqual([]); }); - it('should be able to remove listener which was added outside of zone ', function() { + it('should be able to remove listener which was added outside of zone ', function () { let logs: string[] = []; - const listener1 = function() { + const listener1 = function () { logs.push('listener1'); }; - const listener2 = function() { + const listener2 = function () { logs.push('listener2'); }; const listener3 = { - handleEvent: function(event: Event) { + handleEvent: function (event: Event) { logs.push('listener3'); - } + }, }; - const listener4 = function() { + const listener4 = function () { logs.push('listener4'); }; @@ -3025,20 +3368,20 @@ describe('Zone', function() { expect(logs).toEqual([]); }); - it('should be able to remove all listeners which were added inside of zone ', function() { + it('should be able to remove all listeners which were added inside of zone ', function () { let logs: string[] = []; - const listener1 = function() { + const listener1 = function () { logs.push('listener1'); }; - const listener2 = function() { + const listener2 = function () { logs.push('listener2'); }; const listener3 = { - handleEvent: function(event: Event) { + handleEvent: function (event: Event) { logs.push('listener3'); - } + }, }; - const listener4 = function() { + const listener4 = function () { logs.push('listener4'); }; @@ -3061,65 +3404,70 @@ describe('Zone', function() { expect(logs).toEqual(['listener2', 'listener4']); }); - it('should bypass addEventListener of FunctionWrapper and __BROWSERTOOLS_CONSOLE_SAFEFUNC of IE/Edge', - ifEnvSupports(ieOrEdge, function() { - const hookSpy = jasmine.createSpy('hook'); - const zone = rootZone.fork({ - name: 'spy', - onScheduleTask: ( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - hookSpy(); - return parentZoneDelegate.scheduleTask(targetZone, task); - } - }); - let logs: string[] = []; - - const listener1 = function() { - logs.push(Zone.current.name); - }; - - (listener1 as any).toString = function() { - return '[object FunctionWrapper]'; - }; - - const listener2 = function() { - logs.push(Zone.current.name); - }; - - (listener2 as any).toString = function() { - return 'function __BROWSERTOOLS_CONSOLE_SAFEFUNC() { [native code] }'; - }; - - zone.run(() => { - button.addEventListener('click', listener1); - button.addEventListener('click', listener2); - }); - - button.dispatchEvent(clickEvent); - - expect(hookSpy).not.toHaveBeenCalled(); - expect(logs).toEqual(['ProxyZone', 'ProxyZone']); - logs = []; - - button.removeEventListener('click', listener1); - button.removeEventListener('click', listener2); - - button.dispatchEvent(clickEvent); - - expect(hookSpy).not.toHaveBeenCalled(); - expect(logs).toEqual([]); - })); - - xit('should re-throw the error when the only listener throw error', function(done: DoneFn) { + it( + 'should bypass addEventListener of FunctionWrapper and __BROWSERTOOLS_CONSOLE_SAFEFUNC of IE/Edge', + ifEnvSupports(ieOrEdge, function () { + const hookSpy = jasmine.createSpy('hook'); + const zone = rootZone.fork({ + name: 'spy', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + hookSpy(); + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + }); + let logs: string[] = []; + + const listener1 = function () { + logs.push(Zone.current.name); + }; + + (listener1 as any).toString = function () { + return '[object FunctionWrapper]'; + }; + + const listener2 = function () { + logs.push(Zone.current.name); + }; + + (listener2 as any).toString = function () { + return 'function __BROWSERTOOLS_CONSOLE_SAFEFUNC() { [native code] }'; + }; + + zone.run(() => { + button.addEventListener('click', listener1); + button.addEventListener('click', listener2); + }); + + button.dispatchEvent(clickEvent); + + expect(hookSpy).not.toHaveBeenCalled(); + expect(logs).toEqual(['ProxyZone', 'ProxyZone']); + logs = []; + + button.removeEventListener('click', listener1); + button.removeEventListener('click', listener2); + + button.dispatchEvent(clickEvent); + + expect(hookSpy).not.toHaveBeenCalled(); + expect(logs).toEqual([]); + }), + ); + + xit('should re-throw the error when the only listener throw error', function (done: DoneFn) { // override global.onerror to prevent jasmine report error let oriWindowOnError = window.onerror; let logs: string[] = []; - window.onerror = function(err: any) { + window.onerror = function (err: any) { logs.push(err); }; try { - const listener1 = function() { + const listener1 = function () { throw new Error('test1'); }; button.addEventListener('click', listener1); @@ -3139,453 +3487,485 @@ describe('Zone', function() { expect(logs).toEqual(['Uncaught Error: test1']); window.removeEventListener('unhandledrejection', unhandledRejection); window.onerror = oriWindowOnError; - done() + done(); }); } catch (e: any) { window.onerror = oriWindowOnError; } }); - xit('should not re-throw the error when zone onHandleError handled the error and the only listener throw error', - function(done: DoneFn) { - // override global.onerror to prevent jasmine report error - let oriWindowOnError = window.onerror; - window.onerror = function() {}; - try { - let logs: string[] = []; - const listener1 = function() { - throw new Error('test1'); - }; - const zone = Zone.current.fork({ - name: 'error', - onHandleError: (delegate, curr, target, error) => { - logs.push('zone handled ' + target.name + ' ' + error.message); - return false; - } - }); + xit('should not re-throw the error when zone onHandleError handled the error and the only listener throw error', function (done: DoneFn) { + // override global.onerror to prevent jasmine report error + let oriWindowOnError = window.onerror; + window.onerror = function () {}; + try { + let logs: string[] = []; + const listener1 = function () { + throw new Error('test1'); + }; + const zone = Zone.current.fork({ + name: 'error', + onHandleError: (delegate, curr, target, error) => { + logs.push('zone handled ' + target.name + ' ' + error.message); + return false; + }, + }); - zone.runGuarded(() => { - button.addEventListener('click', listener1); - }); + zone.runGuarded(() => { + button.addEventListener('click', listener1); + }); - const mouseEvent = document.createEvent('MouseEvent'); - mouseEvent.initEvent('click', true, true); + const mouseEvent = document.createEvent('MouseEvent'); + mouseEvent.initEvent('click', true, true); - const unhandledRejection = (e: PromiseRejectionEvent) => { - logs.push(e.reason.message); - }; - window.addEventListener('unhandledrejection', unhandledRejection); + const unhandledRejection = (e: PromiseRejectionEvent) => { + logs.push(e.reason.message); + }; + window.addEventListener('unhandledrejection', unhandledRejection); - button.dispatchEvent(mouseEvent); - expect(logs).toEqual(['zone handled error test1']); + button.dispatchEvent(mouseEvent); + expect(logs).toEqual(['zone handled error test1']); - setTimeout(() => { - expect(logs).toEqual(['zone handled error test1']); - window.removeEventListener('unhandledrejection', unhandledRejection); - window.onerror = oriWindowOnError; - done(); - }); - } catch (e: any) { - window.onerror = oriWindowOnError; - } + setTimeout(() => { + expect(logs).toEqual(['zone handled error test1']); + window.removeEventListener('unhandledrejection', unhandledRejection); + window.onerror = oriWindowOnError; + done(); }); + } catch (e: any) { + window.onerror = oriWindowOnError; + } + }); - xit('should be able to continue to invoke remaining listeners even some listener throw error', - async function() { - await jasmine.spyOnGlobalErrorsAsync(async (globalErrorSpy) => { - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - throw new Error('test1'); - }; - const listener3 = function() { - throw new Error('test2'); - }; - const listener4 = { - handleEvent: function() { - logs.push('listener2'); - } - }; + xit('should be able to continue to invoke remaining listeners even some listener throw error', async function () { + await jasmine.spyOnGlobalErrorsAsync(async (globalErrorSpy) => { + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + throw new Error('test1'); + }; + const listener3 = function () { + throw new Error('test2'); + }; + const listener4 = { + handleEvent: function () { + logs.push('listener2'); + }, + }; + + button.addEventListener('click', listener1); + button.addEventListener('click', listener2); + button.addEventListener('click', listener3); + button.addEventListener('click', listener4); + + const mouseEvent = document.createEvent('MouseEvent'); + mouseEvent.initEvent('click', true, true); - button.addEventListener('click', listener1); - button.addEventListener('click', listener2); - button.addEventListener('click', listener3); - button.addEventListener('click', listener4); + button.dispatchEvent(mouseEvent); + expect(logs).toEqual(['listener1', 'listener2']); + }); + }); - const mouseEvent = document.createEvent('MouseEvent'); - mouseEvent.initEvent('click', true, true); + xit('should be able to continue to invoke remaining listeners even some listener throw error with onHandleError zone', function (done: DoneFn) { + // override global.onerror to prevent jasmine report error + try { + const zone = Zone.current.fork({ + name: 'error', + onHandleError: (delegate, curr, target, error) => { + logs.push('zone handled ' + target.name + ' ' + error.message); + return false; + }, + }); + let logs: string[] = []; + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + throw new Error('test1'); + }; + const listener3 = function () { + throw new Error('test2'); + }; + const listener4 = { + handleEvent: function () { + logs.push('listener2'); + }, + }; - button.dispatchEvent(mouseEvent); - expect(logs).toEqual(['listener1', 'listener2']); - }); + zone.runGuarded(() => { + button.addEventListener('click', listener1); + button.addEventListener('click', listener2); + button.addEventListener('click', listener3); + button.addEventListener('click', listener4); }); - xit('should be able to continue to invoke remaining listeners even some listener throw error with onHandleError zone', - function(done: DoneFn) { - // override global.onerror to prevent jasmine report error - try { - const zone = Zone.current.fork({ - name: 'error', - onHandleError: (delegate, curr, target, error) => { - logs.push('zone handled ' + target.name + ' ' + error.message); - return false; - } - }); - let logs: string[] = []; - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - throw new Error('test1'); - }; - const listener3 = function() { - throw new Error('test2'); - }; - const listener4 = { - handleEvent: function() { - logs.push('listener2'); - } - }; + const mouseEvent = document.createEvent('MouseEvent'); + mouseEvent.initEvent('click', true, true); - zone.runGuarded(() => { - button.addEventListener('click', listener1); - button.addEventListener('click', listener2); - button.addEventListener('click', listener3); - button.addEventListener('click', listener4); - }); + const unhandledRejection = (e: PromiseRejectionEvent) => { + fail('should not be here'); + }; + window.addEventListener('unhandledrejection', unhandledRejection); - const mouseEvent = document.createEvent('MouseEvent'); - mouseEvent.initEvent('click', true, true); - - const unhandledRejection = (e: PromiseRejectionEvent) => { - fail('should not be here'); - }; - window.addEventListener('unhandledrejection', unhandledRejection); - - button.dispatchEvent(mouseEvent); - expect(logs).toEqual([ - 'listener1', 'zone handled error test1', 'zone handled error test2', 'listener2' - ]); - - setTimeout(() => { - expect(logs).toEqual([ - 'listener1', 'zone handled error test1', 'zone handled error test2', 'listener2' - ]); - window.removeEventListener('unhandledrejection', unhandledRejection); - done(); - }); - } catch (e: any) { - } + button.dispatchEvent(mouseEvent); + expect(logs).toEqual([ + 'listener1', + 'zone handled error test1', + 'zone handled error test2', + 'listener2', + ]); + + setTimeout(() => { + expect(logs).toEqual([ + 'listener1', + 'zone handled error test1', + 'zone handled error test2', + 'listener2', + ]); + window.removeEventListener('unhandledrejection', unhandledRejection); + done(); }); + } catch (e: any) {} + }); - xit('should be able to continue to invoke remaining listeners even some listener throw error in the different zones', - function(done: DoneFn) { - let logs: string[] = []; - try { - const zone1 = Zone.current.fork({ - name: 'zone1', - onHandleError: (delegate, curr, target, error) => { - logs.push(error.message); - return false; - } - }); - const listener1 = function() { - logs.push('listener1'); - }; - const listener2 = function() { - throw new Error('test1'); - }; - const listener3 = function() { - throw new Error('test2'); - }; - const listener4 = { - handleEvent: function() { - logs.push('listener2'); - } - }; + xit('should be able to continue to invoke remaining listeners even some listener throw error in the different zones', function (done: DoneFn) { + let logs: string[] = []; + try { + const zone1 = Zone.current.fork({ + name: 'zone1', + onHandleError: (delegate, curr, target, error) => { + logs.push(error.message); + return false; + }, + }); + const listener1 = function () { + logs.push('listener1'); + }; + const listener2 = function () { + throw new Error('test1'); + }; + const listener3 = function () { + throw new Error('test2'); + }; + const listener4 = { + handleEvent: function () { + logs.push('listener2'); + }, + }; - button.addEventListener('click', listener1); - zone1.run(() => { - button.addEventListener('click', listener2); - }); - button.addEventListener('click', listener3); - button.addEventListener('click', listener4); + button.addEventListener('click', listener1); + zone1.run(() => { + button.addEventListener('click', listener2); + }); + button.addEventListener('click', listener3); + button.addEventListener('click', listener4); - const mouseEvent = document.createEvent('MouseEvent'); - mouseEvent.initEvent('click', true, true); + const mouseEvent = document.createEvent('MouseEvent'); + mouseEvent.initEvent('click', true, true); - const unhandledRejection = (e: PromiseRejectionEvent) => { - fail('should not be here'); - }; - window.addEventListener('unhandledrejection', unhandledRejection); + const unhandledRejection = (e: PromiseRejectionEvent) => { + fail('should not be here'); + }; + window.addEventListener('unhandledrejection', unhandledRejection); - button.dispatchEvent(mouseEvent); - expect(logs).toEqual(['listener1', 'listener2']); - } catch (e: any) { - } - }); + button.dispatchEvent(mouseEvent); + expect(logs).toEqual(['listener1', 'listener2']); + } catch (e: any) {} + }); }); // TODO: Re-enable via https://github.com/angular/angular/pull/41526 xdescribe('unhandled promise rejection', () => { const AsyncTestZoneSpec = (Zone as any)['AsyncTestZoneSpec']; - const asyncTest = function(testFn: Function) { + const asyncTest = function (testFn: Function) { return (done: Function) => { - let asyncTestZone: Zone = - Zone.current.fork(new AsyncTestZoneSpec(done, (error: Error) => { + let asyncTestZone: Zone = Zone.current.fork( + new AsyncTestZoneSpec( + done, + (error: Error) => { fail(error); - }, 'asyncTest')); + }, + 'asyncTest', + ), + ); asyncTestZone.run(testFn); }; }; - it('should support window.addEventListener(unhandledrejection)', asyncTest(() => { - if (!promiseUnhandleRejectionSupport()) { - return; - } - (Zone as any)[zoneSymbol('ignoreConsoleErrorUncaughtError')] = true; - Zone.root.fork({name: 'promise'}).run(function() { - const listener = (evt: any) => { - window.removeEventListener('unhandledrejection', listener); - expect(evt.type).toEqual('unhandledrejection'); - expect(evt.promise.constructor.name).toEqual('Promise'); - expect(evt.reason.message).toBe('promise error'); - }; - window.addEventListener('unhandledrejection', listener); - new Promise((resolve, reject) => { - throw new Error('promise error'); - }); - }); - })); - - it('should support window.addEventListener(rejectionhandled)', asyncTest(() => { - if (!promiseUnhandleRejectionSupport()) { - return; - } - (Zone as any)[zoneSymbol('ignoreConsoleErrorUncaughtError')] = true; - Zone.root.fork({name: 'promise'}).run(function() { - const listener = (evt: any) => { - window.removeEventListener('unhandledrejection', listener); - p.catch(reason => {}); - }; - window.addEventListener('unhandledrejection', listener); - - const handledListener = (evt: any) => { - window.removeEventListener('rejectionhandled', handledListener); - expect(evt.type).toEqual('rejectionhandled'); - expect(evt.promise.constructor.name).toEqual('Promise'); - expect(evt.reason.message).toBe('promise error'); - }; - - window.addEventListener('rejectionhandled', handledListener); - const p = new Promise((resolve, reject) => { - throw new Error('promise error'); - }); - }); - })); - - it('should support multiple window.addEventListener(unhandledrejection)', asyncTest(() => { - if (!promiseUnhandleRejectionSupport()) { - return; - } - (Zone as any)[zoneSymbol('ignoreConsoleErrorUncaughtError')] = true; - Zone.root.fork({name: 'promise'}).run(function() { - const listener1 = (evt: any) => { - window.removeEventListener('unhandledrejection', listener1); - expect(evt.type).toEqual('unhandledrejection'); - expect(evt.promise.constructor.name).toEqual('Promise'); - expect(evt.reason.message).toBe('promise error'); - }; - const listener2 = (evt: any) => { - window.removeEventListener('unhandledrejection', listener2); - expect(evt.type).toEqual('unhandledrejection'); - expect(evt.promise.constructor.name).toEqual('Promise'); - expect(evt.reason.message).toBe('promise error'); - evt.preventDefault(); - }; - window.addEventListener('unhandledrejection', listener1); - window.addEventListener('unhandledrejection', listener2); - new Promise((resolve, reject) => { - throw new Error('promise error'); - }); - }); - })); + it( + 'should support window.addEventListener(unhandledrejection)', + asyncTest(() => { + if (!promiseUnhandleRejectionSupport()) { + return; + } + (Zone as any)[zoneSymbol('ignoreConsoleErrorUncaughtError')] = true; + Zone.root.fork({name: 'promise'}).run(function () { + const listener = (evt: any) => { + window.removeEventListener('unhandledrejection', listener); + expect(evt.type).toEqual('unhandledrejection'); + expect(evt.promise.constructor.name).toEqual('Promise'); + expect(evt.reason.message).toBe('promise error'); + }; + window.addEventListener('unhandledrejection', listener); + new Promise((resolve, reject) => { + throw new Error('promise error'); + }); + }); + }), + ); + + it( + 'should support window.addEventListener(rejectionhandled)', + asyncTest(() => { + if (!promiseUnhandleRejectionSupport()) { + return; + } + (Zone as any)[zoneSymbol('ignoreConsoleErrorUncaughtError')] = true; + Zone.root.fork({name: 'promise'}).run(function () { + const listener = (evt: any) => { + window.removeEventListener('unhandledrejection', listener); + p.catch((reason) => {}); + }; + window.addEventListener('unhandledrejection', listener); + + const handledListener = (evt: any) => { + window.removeEventListener('rejectionhandled', handledListener); + expect(evt.type).toEqual('rejectionhandled'); + expect(evt.promise.constructor.name).toEqual('Promise'); + expect(evt.reason.message).toBe('promise error'); + }; + + window.addEventListener('rejectionhandled', handledListener); + const p = new Promise((resolve, reject) => { + throw new Error('promise error'); + }); + }); + }), + ); + + it( + 'should support multiple window.addEventListener(unhandledrejection)', + asyncTest(() => { + if (!promiseUnhandleRejectionSupport()) { + return; + } + (Zone as any)[zoneSymbol('ignoreConsoleErrorUncaughtError')] = true; + Zone.root.fork({name: 'promise'}).run(function () { + const listener1 = (evt: any) => { + window.removeEventListener('unhandledrejection', listener1); + expect(evt.type).toEqual('unhandledrejection'); + expect(evt.promise.constructor.name).toEqual('Promise'); + expect(evt.reason.message).toBe('promise error'); + }; + const listener2 = (evt: any) => { + window.removeEventListener('unhandledrejection', listener2); + expect(evt.type).toEqual('unhandledrejection'); + expect(evt.promise.constructor.name).toEqual('Promise'); + expect(evt.reason.message).toBe('promise error'); + evt.preventDefault(); + }; + window.addEventListener('unhandledrejection', listener1); + window.addEventListener('unhandledrejection', listener2); + new Promise((resolve, reject) => { + throw new Error('promise error'); + }); + }); + }), + ); }); // @JiaLiPassion, Edge 15, the behavior is not the same with Chrome // wait for fix. - xit('IntersectionObserver should run callback in zone', - ifEnvSupportsWithDone('IntersectionObserver', (done: Function) => { - const div = document.createElement('div'); - document.body.appendChild(div); - const options: any = {threshold: 0.5}; + xit( + 'IntersectionObserver should run callback in zone', + ifEnvSupportsWithDone('IntersectionObserver', (done: Function) => { + const div = document.createElement('div'); + document.body.appendChild(div); + const options: any = {threshold: 0.5}; - const zone = Zone.current.fork({name: 'intersectionObserverZone'}); + const zone = Zone.current.fork({name: 'intersectionObserverZone'}); - zone.run(() => { - const observer = new IntersectionObserver(() => { - expect(Zone.current.name).toEqual(zone.name); - observer.unobserve(div); + zone.run(() => { + const observer = new IntersectionObserver(() => { + expect(Zone.current.name).toEqual(zone.name); + observer.unobserve(div); + done(); + }, options); + observer.observe(div); + }); + div.style.display = 'none'; + div.style.visibility = 'block'; + }), + ); + + it( + 'HTMLCanvasElement.toBlob should be a ZoneAware MacroTask', + ifEnvSupportsWithDone(supportCanvasTest, (done: Function) => { + const canvas = document.createElement('canvas'); + const d = canvas.width; + const ctx = canvas.getContext('2d')!; + ctx.beginPath(); + ctx.moveTo(d / 2, 0); + ctx.lineTo(d, d); + ctx.lineTo(0, d); + ctx.closePath(); + ctx.fillStyle = 'yellow'; + ctx.fill(); + + const scheduleSpy = jasmine.createSpy('scheduleSpy'); + const zone: Zone = Zone.current.fork({ + name: 'canvas', + onScheduleTask: ( + delegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ) => { + scheduleSpy(); + return delegate.scheduleTask(targetZone, task); + }, + }); + + zone.run(() => { + const canvasData = canvas.toDataURL(); + canvas.toBlob(function (blob) { + expect(Zone.current.name).toEqual('canvas'); + expect(scheduleSpy).toHaveBeenCalled(); + + const reader = new FileReader(); + reader.readAsDataURL(blob!); + reader.onloadend = function () { + const base64data = reader.result; + expect(base64data).toEqual(canvasData); done(); - }, options); - observer.observe(div); + }; }); - div.style.display = 'none'; - div.style.visibility = 'block'; - })); - - it('HTMLCanvasElement.toBlob should be a ZoneAware MacroTask', - ifEnvSupportsWithDone(supportCanvasTest, (done: Function) => { - const canvas = document.createElement('canvas'); - const d = canvas.width; - const ctx = canvas.getContext('2d')!; - ctx.beginPath(); - ctx.moveTo(d / 2, 0); - ctx.lineTo(d, d); - ctx.lineTo(0, d); - ctx.closePath(); - ctx.fillStyle = 'yellow'; - ctx.fill(); - - const scheduleSpy = jasmine.createSpy('scheduleSpy'); - const zone: Zone = Zone.current.fork({ - name: 'canvas', - onScheduleTask: - (delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => { - scheduleSpy(); - return delegate.scheduleTask(targetZone, task); - } - }); - - zone.run(() => { - const canvasData = canvas.toDataURL(); - canvas.toBlob(function(blob) { - expect(Zone.current.name).toEqual('canvas'); - expect(scheduleSpy).toHaveBeenCalled(); - - const reader = new FileReader(); - reader.readAsDataURL(blob!); - reader.onloadend = function() { - const base64data = reader.result; - expect(base64data).toEqual(canvasData); - done(); - }; - }); - }); - })); + }); + }), + ); describe( - 'ResizeObserver', ifEnvSupports('ResizeObserver', () => { - it('ResizeObserver callback should be in zone', (done) => { - const ResizeObserver = (window as any)['ResizeObserver']; - const div = document.createElement('div'); - const zone = Zone.current.fork({name: 'observer'}); - const observer = new ResizeObserver((entries: any, ob: any) => { - expect(Zone.current.name).toEqual(zone.name); + 'ResizeObserver', + ifEnvSupports('ResizeObserver', () => { + it('ResizeObserver callback should be in zone', (done) => { + const ResizeObserver = (window as any)['ResizeObserver']; + const div = document.createElement('div'); + const zone = Zone.current.fork({name: 'observer'}); + const observer = new ResizeObserver((entries: any, ob: any) => { + expect(Zone.current.name).toEqual(zone.name); + + expect(entries.length).toBe(1); + expect(entries[0].target).toBe(div); + observer.disconnect(); + done(); + }); - expect(entries.length).toBe(1); - expect(entries[0].target).toBe(div); - observer.disconnect(); - done(); - }); + zone.run(() => { + observer.observe(div); + }); - zone.run(() => { - observer.observe(div); + document.body.appendChild(div); + }); + + it('ResizeObserver callback should be able to in different zones which when they were observed', (done) => { + const ResizeObserver = (window as any)['ResizeObserver']; + const div1 = document.createElement('div'); + const div2 = document.createElement('div'); + const zone = Zone.current.fork({name: 'observer'}); + let count = 0; + const observer = new ResizeObserver((entries: any, ob: any) => { + entries.forEach((entry: any) => { + if (entry.target === div1) { + expect(Zone.current.name).toEqual(zone.name); + } else { + expect(Zone.current.name).toEqual(''); + } }); + count++; + if (count === 2) { + done(); + } + }); + + zone.run(() => { + observer.observe(div1); + }); + Zone.root.run(() => { + observer.observe(div2); + }); - document.body.appendChild(div); - }); - - it('ResizeObserver callback should be able to in different zones which when they were observed', - (done) => { - const ResizeObserver = (window as any)['ResizeObserver']; - const div1 = document.createElement('div'); - const div2 = document.createElement('div'); - const zone = Zone.current.fork({name: 'observer'}); - let count = 0; - const observer = new ResizeObserver((entries: any, ob: any) => { - entries.forEach((entry: any) => { - if (entry.target === div1) { - expect(Zone.current.name).toEqual(zone.name); - } else { - expect(Zone.current.name).toEqual(''); - } - }); - count++; - if (count === 2) { - done(); - } - }); - - zone.run(() => { - observer.observe(div1); - }); - Zone.root.run(() => { - observer.observe(div2); - }); - - document.body.appendChild(div1); - document.body.appendChild(div2); - }); - })); + document.body.appendChild(div1); + document.body.appendChild(div2); + }); + }), + ); xdescribe('getUserMedia', () => { - it('navigator.mediaDevices.getUserMedia should in zone', - ifEnvSupportsWithDone( - () => { - return !isEdge() && navigator && navigator.mediaDevices && - typeof navigator.mediaDevices.getUserMedia === 'function'; - }, - (done: Function) => { - const zone = Zone.current.fork({name: 'media'}); - zone.run(() => { - const constraints = {audio: true, video: {width: 1280, height: 720}}; - - navigator.mediaDevices.getUserMedia(constraints) - .then(function(mediaStream) { - expect(Zone.current.name).toEqual(zone.name); - done(); - }) - .catch(function(err) { - console.log(err.name + ': ' + err.message); - expect(Zone.current.name).toEqual(zone.name); - done(); - }); - }); - })); + it( + 'navigator.mediaDevices.getUserMedia should in zone', + ifEnvSupportsWithDone( + () => { + return ( + !isEdge() && + navigator && + navigator.mediaDevices && + typeof navigator.mediaDevices.getUserMedia === 'function' + ); + }, + (done: Function) => { + const zone = Zone.current.fork({name: 'media'}); + zone.run(() => { + const constraints = {audio: true, video: {width: 1280, height: 720}}; + + navigator.mediaDevices + .getUserMedia(constraints) + .then(function (mediaStream) { + expect(Zone.current.name).toEqual(zone.name); + done(); + }) + .catch(function (err) { + console.log(err.name + ': ' + err.message); + expect(Zone.current.name).toEqual(zone.name); + done(); + }); + }); + }, + ), + ); // Note: `navigator` is cast to `any` in this test, because the preferred way of accessing // `getUserMedia` is through `navigator.mediaDevices`, however some older browsers still // expose it directly on `navigator`. - it('navigator.getUserMedia should in zone', - ifEnvSupportsWithDone( - () => { - return !isEdge() && navigator && - typeof (navigator as any).getUserMedia === 'function'; - }, - (done: Function) => { - const zone = Zone.current.fork({name: 'media'}); - zone.run(() => { - const constraints = {audio: true, video: {width: 1280, height: 720}}; - (navigator as any) - .getUserMedia( - constraints, - () => { - expect(Zone.current.name).toEqual(zone.name); - done(); - }, - () => { - expect(Zone.current.name).toEqual(zone.name); - done(); - }); - }); - })); + it( + 'navigator.getUserMedia should in zone', + ifEnvSupportsWithDone( + () => { + return !isEdge() && navigator && typeof (navigator as any).getUserMedia === 'function'; + }, + (done: Function) => { + const zone = Zone.current.fork({name: 'media'}); + zone.run(() => { + const constraints = {audio: true, video: {width: 1280, height: 720}}; + (navigator as any).getUserMedia( + constraints, + () => { + expect(Zone.current.name).toEqual(zone.name); + done(); + }, + () => { + expect(Zone.current.name).toEqual(zone.name); + done(); + }, + ); + }); + }, + ), + ); }); }); - if (getIEVersion() === 11) { describe('pointer event in IE', () => { const pointerEventsMap: {[key: string]: string} = { @@ -3597,7 +3977,7 @@ describe('Zone', function() { 'MSPointerMove': 'pointermove', 'MSPointerOut': 'pointerout', 'MSPointerOver': 'pointerover', - 'MSPointerUp': 'pointerup' + 'MSPointerUp': 'pointerup', }; let div: HTMLDivElement; @@ -3608,7 +3988,7 @@ describe('Zone', function() { afterEach(() => { document.body.removeChild(div); }); - Object.keys(pointerEventsMap).forEach(key => { + Object.keys(pointerEventsMap).forEach((key) => { it(`${key} and ${pointerEventsMap[key]} should both be triggered`, (done: DoneFn) => { const logs: string[] = []; div.addEventListener(key, (event: any) => { @@ -3638,87 +4018,84 @@ describe('Zone', function() { setTimeout(done); }); - it(`${key} and ${pointerEventsMap[key]} with same listener should not be triggered twice`, - (done: DoneFn) => { - const logs: string[] = []; - const listener = function(event: any) { - expect(event.type).toEqual(pointerEventsMap[key]); - logs.push(`${key} triggered`); - }; - div.addEventListener(key, listener); - div.addEventListener(pointerEventsMap[key], listener); + it(`${key} and ${pointerEventsMap[key]} with same listener should not be triggered twice`, (done: DoneFn) => { + const logs: string[] = []; + const listener = function (event: any) { + expect(event.type).toEqual(pointerEventsMap[key]); + logs.push(`${key} triggered`); + }; + div.addEventListener(key, listener); + div.addEventListener(pointerEventsMap[key], listener); - const evt1 = document.createEvent('Event'); - evt1.initEvent(key, true, true); - div.dispatchEvent(evt1); + const evt1 = document.createEvent('Event'); + evt1.initEvent(key, true, true); + div.dispatchEvent(evt1); - setTimeout(() => { - expect(logs).toEqual([`${key} triggered`]); - }); + setTimeout(() => { + expect(logs).toEqual([`${key} triggered`]); + }); - const evt2 = document.createEvent('Event'); - evt2.initEvent(pointerEventsMap[key], true, true); - div.dispatchEvent(evt2); + const evt2 = document.createEvent('Event'); + evt2.initEvent(pointerEventsMap[key], true, true); + div.dispatchEvent(evt2); - setTimeout(() => { - expect(logs).toEqual([`${pointerEventsMap[key]} triggered`]); - }); + setTimeout(() => { + expect(logs).toEqual([`${pointerEventsMap[key]} triggered`]); + }); - setTimeout(done); - }); + setTimeout(done); + }); - it(`${key} and ${ - pointerEventsMap[key]} should be able to be removed with removeEventListener`, - (done: DoneFn) => { - const logs: string[] = []; - const listener1 = function(event: any) { - logs.push(`${key} triggered`); - }; - const listener2 = function(event: any) { - logs.push(`${pointerEventsMap[key]} triggered`); - }; - div.addEventListener(key, listener1); - div.addEventListener(pointerEventsMap[key], listener2); + it(`${key} and ${pointerEventsMap[key]} should be able to be removed with removeEventListener`, (done: DoneFn) => { + const logs: string[] = []; + const listener1 = function (event: any) { + logs.push(`${key} triggered`); + }; + const listener2 = function (event: any) { + logs.push(`${pointerEventsMap[key]} triggered`); + }; + div.addEventListener(key, listener1); + div.addEventListener(pointerEventsMap[key], listener2); - div.removeEventListener(key, listener1); - div.removeEventListener(key, listener2); + div.removeEventListener(key, listener1); + div.removeEventListener(key, listener2); - const evt1 = document.createEvent('Event'); - evt1.initEvent(key, true, true); - div.dispatchEvent(evt1); + const evt1 = document.createEvent('Event'); + evt1.initEvent(key, true, true); + div.dispatchEvent(evt1); - setTimeout(() => { - expect(logs).toEqual([]); - }); + setTimeout(() => { + expect(logs).toEqual([]); + }); - const evt2 = document.createEvent('Event'); - evt2.initEvent(pointerEventsMap[key], true, true); - div.dispatchEvent(evt2); + const evt2 = document.createEvent('Event'); + evt2.initEvent(pointerEventsMap[key], true, true); + div.dispatchEvent(evt2); - setTimeout(() => { - expect(logs).toEqual([]); - }); + setTimeout(() => { + expect(logs).toEqual([]); + }); - div.addEventListener(key, listener1); - div.addEventListener(pointerEventsMap[key], listener2); + div.addEventListener(key, listener1); + div.addEventListener(pointerEventsMap[key], listener2); - div.removeEventListener(pointerEventsMap[key], listener1); - div.removeEventListener(pointerEventsMap[key], listener2); + div.removeEventListener(pointerEventsMap[key], listener1); + div.removeEventListener(pointerEventsMap[key], listener2); - div.dispatchEvent(evt1); + div.dispatchEvent(evt1); - setTimeout(() => { - expect(logs).toEqual([]); - }); + setTimeout(() => { + expect(logs).toEqual([]); + }); - div.dispatchEvent(evt2); + div.dispatchEvent(evt2); - setTimeout(() => { - expect(logs).toEqual([]); - }); + setTimeout(() => { + expect(logs).toEqual([]); + }); - setTimeout(done); - }); + setTimeout(done); + }); }); }); } diff --git a/packages/zone.js/test/browser/custom-element.spec.js b/packages/zone.js/test/browser/custom-element.spec.js index 84c848d09717c..ad2edca9a34e8 100644 --- a/packages/zone.js/test/browser/custom-element.spec.js +++ b/packages/zone.js/test/browser/custom-element.spec.js @@ -20,14 +20,14 @@ function supportsFormAssociatedElements() { return 'attachInternals' in HTMLElement.prototype; } -describe('customElements', function() { +describe('customElements', function () { const testZone = Zone.current.fork({name: 'test'}); const bridge = { connectedCallback: () => {}, disconnectedCallback: () => {}, adoptedCallback: () => {}, attributeChangedCallback: () => {}, - formAssociatedCallback: () => {} + formAssociatedCallback: () => {}, }; class TestCustomElement extends HTMLElement { @@ -86,8 +86,8 @@ describe('customElements', function() { } }); - it('should work with connectedCallback', function(done) { - bridge.connectedCallback = function() { + it('should work with connectedCallback', function (done) { + bridge.connectedCallback = function () { expect(Zone.current.name).toBe(testZone.name); done(); }; @@ -96,8 +96,8 @@ describe('customElements', function() { document.body.appendChild(elt); }); - it('should work with disconnectedCallback', function(done) { - bridge.disconnectedCallback = function() { + it('should work with disconnectedCallback', function (done) { + bridge.disconnectedCallback = function () { expect(Zone.current.name).toBe(testZone.name); done(); }; @@ -108,8 +108,8 @@ describe('customElements', function() { elt = null; }); - it('should work with attributeChanged', function(done) { - bridge.attributeChangedCallback = function(attrName, oldVal, newVal) { + it('should work with attributeChanged', function (done) { + bridge.attributeChangedCallback = function (attrName, oldVal, newVal) { expect(Zone.current.name).toBe(testZone.name); expect(attrName).toEqual('attr1'); expect(newVal).toEqual('value1'); @@ -121,12 +121,12 @@ describe('customElements', function() { elt.setAttribute('attr1', 'value1'); }); - it('should work with formAssociatedCallback', function(done) { + it('should work with formAssociatedCallback', function (done) { if (!supportsFormAssociatedElements()) { return; } - bridge.formAssociatedCallback = function() { + bridge.formAssociatedCallback = function () { expect(Zone.current.name).toBe(testZone.name); done(); }; diff --git a/packages/zone.js/test/browser/define-property.spec.ts b/packages/zone.js/test/browser/define-property.spec.ts index 962d3c6cbb960..cf76b60c9c2c4 100644 --- a/packages/zone.js/test/browser/define-property.spec.ts +++ b/packages/zone.js/test/browser/define-property.spec.ts @@ -6,14 +6,15 @@ * found in the LICENSE file at https://angular.io/license */ -describe('defineProperty', function() { - it('should not throw when defining length on an array', function() { +describe('defineProperty', function () { + it('should not throw when defining length on an array', function () { const someArray: any[] = []; - expect(() => Object.defineProperty(someArray, 'length', {value: 2, writable: false})) - .not.toThrow(); + expect(() => + Object.defineProperty(someArray, 'length', {value: 2, writable: false}), + ).not.toThrow(); }); - it('should not be able to change a frozen desc', function() { + it('should not be able to change a frozen desc', function () { const obj = {}; const desc = Object.freeze({value: null, writable: true}); Object.defineProperty(obj, 'prop', desc); @@ -21,19 +22,17 @@ describe('defineProperty', function() { expect(objDesc.writable).toBeTruthy(); try { Object.defineProperty(obj, 'prop', {configurable: true, writable: true, value: 'test'}); - } catch (err) { - } + } catch (err) {} objDesc = Object.getOwnPropertyDescriptor(obj, 'prop'); expect(objDesc.configurable).toBeFalsy(); }); - it('should not throw error when try to defineProperty with a frozen obj', function() { + it('should not throw error when try to defineProperty with a frozen obj', function () { const obj = {}; Object.freeze(obj); try { Object.defineProperty(obj, 'prop', {configurable: true, writable: true, value: 'value'}); - } catch (err) { - } + } catch (err) {} expect((obj as any).prop).toBeFalsy(); }); }); @@ -47,11 +46,11 @@ describe('defineProperties', () => { 'property3': { enumerable: true, get: () => { - return obj.p3 + return obj.p3; }, - set: (val: string) => obj.p3 = val + set: (val: string) => (obj.p3 = val), }, - 'property4': {enumerable: false, writable: true, value: 'hidden'} + 'property4': {enumerable: false, writable: true, value: 'hidden'}, }); expect(Object.keys(obj).sort()).toEqual(['property1', 'property2', 'property3']); expect(obj.property1).toBeTrue(); @@ -60,7 +59,7 @@ describe('defineProperties', () => { expect(obj.property4).toEqual('hidden'); obj.property1 = false; expect(obj.property1).toBeFalse(); - expect(() => obj.property2 = 'new Hello').toThrow(); + expect(() => (obj.property2 = 'new Hello')).toThrow(); obj.property3 = 'property3'; expect(obj.property3).toEqual('property3'); obj.property4 = 'property4'; @@ -72,7 +71,7 @@ describe('defineProperties', () => { const obj: any = {}; Object.defineProperties(obj, { [a]: {value: true, writable: true}, - [b]: {get: () => obj.b1, set: (val: string) => obj.b1 = val} + [b]: {get: () => obj.b1, set: (val: string) => (obj.b1 = val)}, }); expect(Object.keys(obj)).toEqual([]); expect(obj[a]).toBeTrue(); @@ -130,7 +129,7 @@ describe('defineProperties', () => { writable: false, enumerable: false, }); - class Test {}; + class Test {} const obj = new Test(); Object.defineProperties(Test, props); expect(Object.keys(obj)).toEqual([]); diff --git a/packages/zone.js/test/browser/element.spec.ts b/packages/zone.js/test/browser/element.spec.ts index f2dfa7541a0ec..612c81f1145fd 100644 --- a/packages/zone.js/test/browser/element.spec.ts +++ b/packages/zone.js/test/browser/element.spec.ts @@ -8,60 +8,59 @@ import {ifEnvSupports} from '../test-util'; -describe('element', function() { +describe('element', function () { let button: HTMLButtonElement; - beforeEach(function() { + beforeEach(function () { button = document.createElement('button'); document.body.appendChild(button); }); - afterEach(function() { + afterEach(function () { document.body.removeChild(button); }); // https://github.com/angular/zone.js/issues/190 - it('should work when addEventListener / removeEventListener are called in the global context', - function() { - const clickEvent = document.createEvent('Event'); - let callCount = 0; + it('should work when addEventListener / removeEventListener are called in the global context', function () { + const clickEvent = document.createEvent('Event'); + let callCount = 0; - clickEvent.initEvent('click', true, true); + clickEvent.initEvent('click', true, true); - const listener = function(event: Event) { - callCount++; - expect(event).toBe(clickEvent); - }; + const listener = function (event: Event) { + callCount++; + expect(event).toBe(clickEvent); + }; - // `this` would be null inside the method when `addEventListener` is called from strict mode - // it would be `window`: - // - when called from non strict-mode, - // - when `window.addEventListener` is called explicitly. - addEventListener('click', listener); + // `this` would be null inside the method when `addEventListener` is called from strict mode + // it would be `window`: + // - when called from non strict-mode, + // - when `window.addEventListener` is called explicitly. + addEventListener('click', listener); - button.dispatchEvent(clickEvent); - expect(callCount).toEqual(1); + button.dispatchEvent(clickEvent); + expect(callCount).toEqual(1); - removeEventListener('click', listener); - button.dispatchEvent(clickEvent); - expect(callCount).toEqual(1); - }); + removeEventListener('click', listener); + button.dispatchEvent(clickEvent); + expect(callCount).toEqual(1); + }); - it('should work with addEventListener when called with a function listener', function() { + it('should work with addEventListener when called with a function listener', function () { const clickEvent = document.createEvent('Event'); clickEvent.initEvent('click', true, true); - button.addEventListener('click', function(event) { + button.addEventListener('click', function (event) { expect(event).toBe(clickEvent as any); }); button.dispatchEvent(clickEvent); }); - it('should not call microtasks early when an event is invoked', function(done) { + it('should not call microtasks early when an event is invoked', function (done) { let log = ''; button.addEventListener('click', () => { - Zone.current.scheduleMicroTask('test', () => log += 'microtask;'); + Zone.current.scheduleMicroTask('test', () => (log += 'microtask;')); log += 'click;'; }); button.click(); @@ -70,7 +69,7 @@ describe('element', function() { done(); }); - it('should call microtasks early when an event is invoked', function(done) { + it('should call microtasks early when an event is invoked', function (done) { /* * In this test we escape the Zone using unpatched setTimeout. * This way the eventTask invoked from click will think it is the top most @@ -94,7 +93,7 @@ describe('element', function() { (window as any)[(Zone as any).__symbol__('setTimeout')](() => { let log = ''; button.addEventListener('click', () => { - Zone.current.scheduleMicroTask('test', () => log += 'microtask;'); + Zone.current.scheduleMicroTask('test', () => (log += 'microtask;')); log += 'click;'; }); button.click(); @@ -104,27 +103,26 @@ describe('element', function() { }); }); - it('should work with addEventListener when called with an EventListener-implementing listener', - function() { - const eventListener = { - x: 5, - handleEvent: function(event: Event) { - // Test that context is preserved - expect(this.x).toBe(5); + it('should work with addEventListener when called with an EventListener-implementing listener', function () { + const eventListener = { + x: 5, + handleEvent: function (event: Event) { + // Test that context is preserved + expect(this.x).toBe(5); - expect(event).toBe(clickEvent); - } - }; + expect(event).toBe(clickEvent); + }, + }; - const clickEvent = document.createEvent('Event'); - clickEvent.initEvent('click', true, true); + const clickEvent = document.createEvent('Event'); + clickEvent.initEvent('click', true, true); - button.addEventListener('click', eventListener); + button.addEventListener('click', eventListener); - button.dispatchEvent(clickEvent); - }); + button.dispatchEvent(clickEvent); + }); - it('should respect removeEventListener when called with a function listener', function() { + it('should respect removeEventListener when called with a function listener', function () { let log = ''; const logFunction = function logFunction() { log += 'a'; @@ -144,7 +142,7 @@ describe('element', function() { expect(log).toEqual('aa'); }); - it('should respect removeEventListener with an EventListener-implementing listener', function() { + it('should respect removeEventListener with an EventListener-implementing listener', function () { const eventListener = {x: 5, handleEvent: jasmine.createSpy('handleEvent')}; button.addEventListener('click', eventListener); @@ -155,12 +153,14 @@ describe('element', function() { expect(eventListener.handleEvent).not.toHaveBeenCalled(); }); - it('should have no effect while calling addEventListener without listener', function() { + it('should have no effect while calling addEventListener without listener', function () { const onAddEventListenerSpy = jasmine.createSpy('addEventListener'); - const eventListenerZone = - Zone.current.fork({name: 'eventListenerZone', onScheduleTask: onAddEventListenerSpy}); - expect(function() { - eventListenerZone.run(function() { + const eventListenerZone = Zone.current.fork({ + name: 'eventListenerZone', + onScheduleTask: onAddEventListenerSpy, + }); + expect(function () { + eventListenerZone.run(function () { button.addEventListener('click', null as any); button.addEventListener('click', undefined as any); }); @@ -168,12 +168,14 @@ describe('element', function() { expect(onAddEventListenerSpy).not.toHaveBeenCalledWith(); }); - it('should have no effect while calling removeEventListener without listener', function() { + it('should have no effect while calling removeEventListener without listener', function () { const onAddEventListenerSpy = jasmine.createSpy('removeEventListener'); - const eventListenerZone = - Zone.current.fork({name: 'eventListenerZone', onScheduleTask: onAddEventListenerSpy}); - expect(function() { - eventListenerZone.run(function() { + const eventListenerZone = Zone.current.fork({ + name: 'eventListenerZone', + onScheduleTask: onAddEventListenerSpy, + }); + expect(function () { + eventListenerZone.run(function () { button.removeEventListener('click', null as any); button.removeEventListener('click', undefined as any); }); @@ -181,8 +183,7 @@ describe('element', function() { expect(onAddEventListenerSpy).not.toHaveBeenCalledWith(); }); - - it('should only add a listener once for a given set of arguments', function() { + it('should only add a listener once for a given set of arguments', function () { const log: string[] = []; const clickEvent = document.createEvent('Event'); @@ -205,7 +206,7 @@ describe('element', function() { expect(log).toEqual(['listener']); }); - it('should correctly handler capturing versus nonCapturing eventListeners', function() { + it('should correctly handler capturing versus nonCapturing eventListeners', function () { const log: string[] = []; const clickEvent = document.createEvent('Event'); @@ -227,7 +228,7 @@ describe('element', function() { expect(log).toEqual(['capturingListener', 'bubblingListener']); }); - it('should correctly handler a listener that is both capturing and nonCapturing', function() { + it('should correctly handler a listener that is both capturing and nonCapturing', function () { const log: string[] = []; const clickEvent = document.createEvent('Event'); @@ -250,21 +251,23 @@ describe('element', function() { expect(log).toEqual(['listener', 'listener']); }); - describe('onclick', function() { + describe('onclick', function () { function supportsOnClick() { const div = document.createElement('div'); const clickPropDesc = Object.getOwnPropertyDescriptor(div, 'onclick'); return !( - EventTarget && div instanceof EventTarget && clickPropDesc && - clickPropDesc.value === null); + EventTarget && + div instanceof EventTarget && + clickPropDesc && + clickPropDesc.value === null + ); } (supportsOnClick).message = 'Supports Element#onclick patching'; - - ifEnvSupports(supportsOnClick, function() { - it('should spawn new child zones', function() { + ifEnvSupports(supportsOnClick, function () { + it('should spawn new child zones', function () { let run = false; - button.onclick = function() { + button.onclick = function () { run = true; }; @@ -273,13 +276,12 @@ describe('element', function() { }); }); - - it('should only allow one onclick handler', function() { + it('should only allow one onclick handler', function () { let log = ''; - button.onclick = function() { + button.onclick = function () { log += 'a'; }; - button.onclick = function() { + button.onclick = function () { log += 'b'; }; @@ -287,10 +289,9 @@ describe('element', function() { expect(log).toEqual('b'); }); - - it('should handler removing onclick', function() { + it('should handler removing onclick', function () { let log = ''; - button.onclick = function() { + button.onclick = function () { log += 'a'; }; button.onclick = null as any; @@ -299,7 +300,7 @@ describe('element', function() { expect(log).toEqual(''); }); - it('should be able to deregister the same event twice', function() { + it('should be able to deregister the same event twice', function () { const listener = (event: Event) => {}; document.body.addEventListener('click', listener, false); document.body.removeEventListener('click', listener, false); @@ -307,20 +308,20 @@ describe('element', function() { }); }); - describe('onEvent default behavior', function() { + describe('onEvent default behavior', function () { let checkbox: HTMLInputElement; - beforeEach(function() { + beforeEach(function () { checkbox = document.createElement('input'); checkbox.type = 'checkbox'; document.body.appendChild(checkbox); }); - afterEach(function() { + afterEach(function () { document.body.removeChild(checkbox); }); - it('should be possible to prevent default behavior by returning false', function() { - checkbox.onclick = function() { + it('should be possible to prevent default behavior by returning false', function () { + checkbox.onclick = function () { return false; }; @@ -328,8 +329,8 @@ describe('element', function() { expect(checkbox.checked).toBe(false); }); - it('should have no effect on default behavior when not returning anything', function() { - checkbox.onclick = function() {}; + it('should have no effect on default behavior when not returning anything', function () { + checkbox.onclick = function () {}; checkbox.click(); expect(checkbox.checked).toBe(true); diff --git a/packages/zone.js/test/browser/geolocation.spec.manual.ts b/packages/zone.js/test/browser/geolocation.spec.manual.ts index 0ba5f413708ae..190d6d76c203e 100644 --- a/packages/zone.js/test/browser/geolocation.spec.manual.ts +++ b/packages/zone.js/test/browser/geolocation.spec.manual.ts @@ -13,26 +13,29 @@ function supportsGeolocation() { } (supportsGeolocation).message = 'Geolocation'; -describe('Geolocation', ifEnvSupports(supportsGeolocation, function() { - const testZone = Zone.current.fork({name: 'geotest'}); +describe( + 'Geolocation', + ifEnvSupports(supportsGeolocation, function () { + const testZone = Zone.current.fork({name: 'geotest'}); - it('should work for getCurrentPosition', function(done) { - testZone.run(function() { - navigator.geolocation.getCurrentPosition(function(pos) { - expect(Zone.current).toBe(testZone); - done(); - }); - }); - }, 10000); + it('should work for getCurrentPosition', function (done) { + testZone.run(function () { + navigator.geolocation.getCurrentPosition(function (pos) { + expect(Zone.current).toBe(testZone); + done(); + }); + }); + }, 10000); - it('should work for watchPosition', function(done) { - testZone.run(function() { - let watchId: number; - watchId = navigator.geolocation.watchPosition(function(pos) { - expect(Zone.current).toBe(testZone); - navigator.geolocation.clearWatch(watchId); - done(); - }); - }); - }, 10000); - })); + it('should work for watchPosition', function (done) { + testZone.run(function () { + let watchId: number; + watchId = navigator.geolocation.watchPosition(function (pos) { + expect(Zone.current).toBe(testZone); + navigator.geolocation.clearWatch(watchId); + done(); + }); + }); + }, 10000); + }), +); diff --git a/packages/zone.js/test/browser/messageport.spec.ts b/packages/zone.js/test/browser/messageport.spec.ts index c129022ffb744..44f3ade0bcce1 100644 --- a/packages/zone.js/test/browser/messageport.spec.ts +++ b/packages/zone.js/test/browser/messageport.spec.ts @@ -33,9 +33,9 @@ describe('MessagePort onproperties', () => { it('onmessge should in the zone', (done) => { const channel = new MessageChannel(); const zone = Zone.current.fork({name: 'zone'}); - iframe.onload = function() { + iframe.onload = function () { zone.run(() => { - channel.port1.onmessage = function() { + channel.port1.onmessage = function () { expect(Zone.current.name).toBe(zone.name); done(); }; diff --git a/packages/zone.js/test/browser/registerElement.spec.ts b/packages/zone.js/test/browser/registerElement.spec.ts index 8d3d139cffee8..0d08fae4efd16 100644 --- a/packages/zone.js/test/browser/registerElement.spec.ts +++ b/packages/zone.js/test/browser/registerElement.spec.ts @@ -12,30 +12,30 @@ */ function registerElement() { - return ('registerElement' in document) && (typeof customElements === 'undefined'); + return 'registerElement' in document && typeof customElements === 'undefined'; } if (registerElement()) { - describe('document.registerElement', function() { + describe('document.registerElement', function () { // register a custom element for each callback const callbackNames = ['created', 'attached', 'detached', 'attributeChanged']; const callbacks: any = {}; const testZone = Zone.current.fork({name: 'test'}); let customElements; - customElements = testZone.run(function() { - callbackNames.forEach(function(callbackName) { + customElements = testZone.run(function () { + callbackNames.forEach(function (callbackName) { const fullCallbackName = callbackName + 'Callback'; const proto = Object.create(HTMLElement.prototype); - (proto as any)[fullCallbackName] = function(arg: any) { + (proto as any)[fullCallbackName] = function (arg: any) { callbacks[callbackName](arg); }; (document).registerElement('x-' + callbackName.toLowerCase(), {prototype: proto}); }); }); - it('should work with createdCallback', function(done) { - callbacks.created = function() { + it('should work with createdCallback', function (done) { + callbacks.created = function () { expect(Zone.current).toBe(testZone); done(); }; @@ -43,9 +43,8 @@ if (registerElement()) { document.createElement('x-created'); }); - - it('should work with attachedCallback', function(done) { - callbacks.attached = function() { + it('should work with attachedCallback', function (done) { + callbacks.attached = function () { expect(Zone.current).toBe(testZone); done(); }; @@ -55,9 +54,8 @@ if (registerElement()) { document.body.removeChild(elt); }); - - it('should work with detachedCallback', function(done) { - callbacks.detached = function() { + it('should work with detachedCallback', function (done) { + callbacks.detached = function () { expect(Zone.current).toBe(testZone); done(); }; @@ -67,9 +65,8 @@ if (registerElement()) { document.body.removeChild(elt); }); - - it('should work with attributeChanged', function(done) { - callbacks.attributeChanged = function() { + it('should work with attributeChanged', function (done) { + callbacks.attributeChanged = function () { expect(Zone.current).toBe(testZone); done(); }; @@ -78,70 +75,76 @@ if (registerElement()) { elt.id = 'bar'; }); + it('should work with non-writable, non-configurable prototypes created with defineProperty', function (done) { + testZone.run(function () { + const proto = Object.create(HTMLElement.prototype); - it('should work with non-writable, non-configurable prototypes created with defineProperty', - function(done) { - testZone.run(function() { - const proto = Object.create(HTMLElement.prototype); - - Object.defineProperty( - proto, 'createdCallback', - {writable: false, configurable: false, value: checkZone}); - - (document).registerElement('x-prop-desc', {prototype: proto}); - - function checkZone() { - expect(Zone.current).toBe(testZone); - done(); - } - }); - - const elt = document.createElement('x-prop-desc'); - }); + Object.defineProperty(proto, 'createdCallback', { + writable: false, + configurable: false, + value: checkZone, + }); + (document).registerElement('x-prop-desc', {prototype: proto}); - it('should work with non-writable, non-configurable prototypes created with defineProperties', - function(done) { - testZone.run(function() { - const proto = Object.create(HTMLElement.prototype); + function checkZone() { + expect(Zone.current).toBe(testZone); + done(); + } + }); - Object.defineProperties(proto, { - createdCallback: { - writable: false, configurable: false, value: checkZone - } - }); + const elt = document.createElement('x-prop-desc'); + }); - (document).registerElement('x-props-desc', {prototype: proto}); + it('should work with non-writable, non-configurable prototypes created with defineProperties', function (done) { + testZone.run(function () { + const proto = Object.create(HTMLElement.prototype); - function checkZone() { - expect(Zone.current).toBe(testZone); - done(); - } - }); + Object.defineProperties(proto, { + createdCallback: { + writable: false, + configurable: false, + value: checkZone, + }, + }); - const elt = document.createElement('x-props-desc'); - }); + (document).registerElement('x-props-desc', {prototype: proto}); - it('should not throw with frozen prototypes ', function() { - testZone.run(function() { - const proto = Object.create(HTMLElement.prototype, Object.freeze({ - createdCallback: { - value: () => {}, writable: true, configurable: true - } - })); + function checkZone() { + expect(Zone.current).toBe(testZone); + done(); + } + }); - Object.defineProperty( - proto, 'createdCallback', {writable: false, configurable: false}); + const elt = document.createElement('x-props-desc'); + }); - expect(function() { + it('should not throw with frozen prototypes ', function () { + testZone.run(function () { + const proto = Object.create( + HTMLElement.prototype, + Object.freeze({ + createdCallback: { + value: () => {}, + writable: true, + configurable: true, + }, + }), + ); + + Object.defineProperty(proto, 'createdCallback', { + writable: false, + configurable: false, + }); + + expect(function () { (document).registerElement('x-frozen-desc', {prototype: proto}); }).not.toThrow(); }); }); - - it('should check bind callback if not own property', function(done) { - testZone.run(function() { + it('should check bind callback if not own property', function (done) { + testZone.run(function () { const originalProto = {createdCallback: checkZone}; const secondaryProto = Object.create(originalProto); @@ -159,9 +162,8 @@ if (registerElement()) { }); }); - - it('should not throw if no options passed to registerElement', function() { - expect(function() { + it('should not throw if no options passed to registerElement', function () { + expect(function () { (document).registerElement('x-no-opts'); }).not.toThrow(); }); diff --git a/packages/zone.js/test/browser/requestAnimationFrame.spec.ts b/packages/zone.js/test/browser/requestAnimationFrame.spec.ts index b0cdceac00df0..39051c9b98614 100644 --- a/packages/zone.js/test/browser/requestAnimationFrame.spec.ts +++ b/packages/zone.js/test/browser/requestAnimationFrame.spec.ts @@ -6,13 +6,16 @@ * found in the LICENSE file at https://angular.io/license */ -describe('requestAnimationFrame', function() { - const functions = - ['requestAnimationFrame', 'webkitRequestAnimationFrame', 'mozRequestAnimationFrame']; - - functions.forEach(function(fnName) { +describe('requestAnimationFrame', function () { + const functions = [ + 'requestAnimationFrame', + 'webkitRequestAnimationFrame', + 'mozRequestAnimationFrame', + ]; + + functions.forEach(function (fnName) { if ((global as any)[fnName] !== undefined) { - describe(fnName, function() { + describe(fnName, function () { const originalTimeout: number = (jasmine).DEFAULT_TIMEOUT_INTERVAL; beforeEach(() => { (jasmine).DEFAULT_TIMEOUT_INTERVAL = 10000; @@ -23,14 +26,14 @@ describe('requestAnimationFrame', function() { }); const requestAnimationFrameFn = (window as any)[fnName]; - it('should be tolerant of invalid arguments', function() { + it('should be tolerant of invalid arguments', function () { // requestAnimationFrameFn throws an error on invalid arguments, so expect that. - expect(function() { + expect(function () { requestAnimationFrameFn(null); }).toThrow(); }); - it('should bind to same zone when called recursively', function(done) { + it('should bind to same zone when called recursively', function (done) { Zone.current.fork({name: 'TestZone'}).run(() => { let frames = 0; let previousTimeStamp = 0; diff --git a/packages/zone.js/test/browser/shadydom.spec.ts b/packages/zone.js/test/browser/shadydom.spec.ts index 389445094e689..ebc82223e5b83 100644 --- a/packages/zone.js/test/browser/shadydom.spec.ts +++ b/packages/zone.js/test/browser/shadydom.spec.ts @@ -16,9 +16,12 @@ describe('shadydom', () => { document.body.appendChild(span); document.body.appendChild(fragment); const targets = [ - {name: 'window', target: window}, {name: 'div', target: div}, {name: 'text', target: text}, - {name: 'span', target: span}, {name: 'document', target: document}, - {name: 'fragment', target: fragment} + {name: 'window', target: window}, + {name: 'div', target: div}, + {name: 'text', target: text}, + {name: 'span', target: span}, + {name: 'document', target: document}, + {name: 'fragment', target: fragment}, ]; targets.forEach((t: any) => { it(`test for prototype ${t.name}`, () => { diff --git a/packages/zone.js/test/browser_shadydom_setup.ts b/packages/zone.js/test/browser_shadydom_setup.ts index 575d1ebe8c415..af4b0d720cd14 100644 --- a/packages/zone.js/test/browser_shadydom_setup.ts +++ b/packages/zone.js/test/browser_shadydom_setup.ts @@ -8,15 +8,21 @@ function initAddEventListeners() { const HTMLSlotElement = (window as any).HTMLSlotElement; const prototypes = [ - Object.getPrototypeOf(window), Node.prototype, Text.prototype, Element.prototype, - Object.getPrototypeOf(window), HTMLElement.prototype, - HTMLSlotElement && HTMLSlotElement.prototype, DocumentFragment.prototype, Document.prototype + Object.getPrototypeOf(window), + Node.prototype, + Text.prototype, + Element.prototype, + Object.getPrototypeOf(window), + HTMLElement.prototype, + HTMLSlotElement && HTMLSlotElement.prototype, + DocumentFragment.prototype, + Document.prototype, ]; - prototypes.forEach(proto => { - proto.addEventListener = function(eventName: string, callback: any) { + prototypes.forEach((proto) => { + proto.addEventListener = function (eventName: string, callback: any) { this.callback = callback; }; - proto.dispatchEvent = function(event: any) { + proto.dispatchEvent = function (event: any) { this.callback && this.callback.call(this, event); }; }); diff --git a/packages/zone.js/test/closure/zone.closure.ts b/packages/zone.js/test/closure/zone.closure.ts index 35f877d6f2ed7..45432e64fea0a 100644 --- a/packages/zone.js/test/closure/zone.closure.ts +++ b/packages/zone.js/test/closure/zone.closure.ts @@ -12,52 +12,86 @@ const testClosureFunction = () => { const testZoneSpec: ZoneSpec = { name: 'closure', properties: {}, - onFork: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - zoneSpec: ZoneSpec) => { - return parentZoneDelegate.fork(targetZone, zoneSpec); - }, - - onIntercept: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, - source: string) => { - return parentZoneDelegate.intercept(targetZone, delegate, source); - }, - - onInvoke: function( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, - applyThis?: any, applyArgs?: any[], source?: string) { + onFork: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + zoneSpec: ZoneSpec, + ) => { + return parentZoneDelegate.fork(targetZone, zoneSpec); + }, + + onIntercept: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + delegate: Function, + source: string, + ) => { + return parentZoneDelegate.intercept(targetZone, delegate, source); + }, + + onInvoke: function ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + delegate: Function, + applyThis?: any, + applyArgs?: any[], + source?: string, + ) { return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source); }, - onHandleError: function( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any) { + onHandleError: function ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + error: any, + ) { return parentZoneDelegate.handleError(targetZone, error); }, - onScheduleTask: function( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) { + onScheduleTask: function ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ) { return parentZoneDelegate.scheduleTask(targetZone, task); }, - onInvokeTask: function( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, - applyThis?: any, applyArgs?: any[]) { + onInvokeTask: function ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + applyThis?: any, + applyArgs?: any[], + ) { return parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs); }, - onCancelTask: function( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) { + onCancelTask: function ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ) { return parentZoneDelegate.cancelTask(targetZone, task); }, - onHasTask: function( - delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState) { + onHasTask: function ( + delegate: ZoneDelegate, + current: Zone, + target: Zone, + hasTaskState: HasTaskState, + ) { return delegate.hasTask(target, hasTaskState); - } + }, }; - Zone.__load_patch('test_closure_load_patch', function() {}); + Zone.__load_patch('test_closure_load_patch', function () {}); Zone.__symbol__('test_symbol'); const testZone: Zone = Zone.current.fork(testZoneSpec); @@ -86,7 +120,7 @@ const testClosureFunction = () => { 'scheduleEventTask', 'cancelTask', ]; - zonePrototypeKeys.forEach(key => { + zonePrototypeKeys.forEach((key) => { if ((Zone as any).prototype.hasOwnProperty(key)) { logs.push(key); } @@ -104,19 +138,31 @@ const testClosureFunction = () => { 'onCancelTask', 'onHasTask', ]; - zoneSpecKeys.forEach(key => { + zoneSpecKeys.forEach((key) => { if (testZoneSpec.hasOwnProperty(key)) { logs.push(key); } }); const zoneTaskKeys = [ - 'onHasTask', 'runCount', 'type', 'source', 'data', 'scheduleFn', 'cancelFn', 'callback', - 'invoke' + 'onHasTask', + 'runCount', + 'type', + 'source', + 'data', + 'scheduleFn', + 'cancelFn', + 'callback', + 'invoke', ]; - const task = Zone.current.scheduleMicroTask('testTask', () => {}, undefined, () => {}); - zoneTaskKeys.forEach(key => { + const task = Zone.current.scheduleMicroTask( + 'testTask', + () => {}, + undefined, + () => {}, + ); + zoneTaskKeys.forEach((key) => { if (task.hasOwnProperty(key)) { logs.push(key); } @@ -159,7 +205,7 @@ const testClosureFunction = () => { 'scheduleFn', 'cancelFn', 'callback', - 'invoke' + 'invoke', ]; let result: boolean = true; diff --git a/packages/zone.js/test/common/Error.spec.ts b/packages/zone.js/test/common/Error.spec.ts index 0cb95adffd874..33370eb032062 100644 --- a/packages/zone.js/test/common/Error.spec.ts +++ b/packages/zone.js/test/common/Error.spec.ts @@ -49,7 +49,7 @@ class WrappedError extends BaseError { override get stack() { return ((this.originalError instanceof Error ? this.originalError : this._nativeError) as any) - .stack; + .stack; } } @@ -171,7 +171,7 @@ describe('ZoneAwareError', () => { it('should copy customized NativeError properties to ZoneAwareError', () => { const spy = jasmine.createSpy('errorCustomFunction'); const NativeError = (global as any)[(Zone as any).__symbol__('Error')]; - NativeError.customFunction = function(args: any) { + NativeError.customFunction = function (args: any) { spy(args); }; expect((Error as any)['customProperty']).toBe('customProperty'); @@ -288,13 +288,24 @@ describe('ZoneAwareError', () => { }); const zoneAwareFrames = [ - 'Zone.run', 'Zone.runGuarded', 'Zone.scheduleEventTask', 'Zone.scheduleMicroTask', - 'Zone.scheduleMacroTask', 'Zone.runTask', 'ZoneDelegate.scheduleTask', - 'ZoneDelegate.invokeTask', 'zoneAwareAddListener', 'Zone.prototype.run', - 'Zone.prototype.runGuarded', 'Zone.prototype.scheduleEventTask', - 'Zone.prototype.scheduleMicroTask', 'Zone.prototype.scheduleMacroTask', - 'Zone.prototype.runTask', 'ZoneDelegate.prototype.scheduleTask', - 'ZoneDelegate.prototype.invokeTask', 'ZoneTask.invokeTask' + 'Zone.run', + 'Zone.runGuarded', + 'Zone.scheduleEventTask', + 'Zone.scheduleMicroTask', + 'Zone.scheduleMacroTask', + 'Zone.runTask', + 'ZoneDelegate.scheduleTask', + 'ZoneDelegate.invokeTask', + 'zoneAwareAddListener', + 'Zone.prototype.run', + 'Zone.prototype.runGuarded', + 'Zone.prototype.scheduleEventTask', + 'Zone.prototype.scheduleMicroTask', + 'Zone.prototype.scheduleMacroTask', + 'Zone.prototype.runTask', + 'ZoneDelegate.prototype.scheduleTask', + 'ZoneDelegate.prototype.invokeTask', + 'ZoneTask.invokeTask', ]; function assertStackDoesNotContainZoneFrames(err: any) { @@ -305,7 +316,7 @@ describe('ZoneAwareError', () => { if (hasZoneStack) { break; } - hasZoneStack = zoneAwareFrames.filter(f => frames[i].indexOf(f) !== -1).length > 0; + hasZoneStack = zoneAwareFrames.filter((f) => frames[i].indexOf(f) !== -1).length > 0; } if (!hasZoneStack) { console.log('stack', hasZoneStack, frames, err.originalStack); @@ -313,137 +324,181 @@ describe('ZoneAwareError', () => { expect(hasZoneStack).toBe(true); } else { for (let i = 0; i < frames.length; i++) { - expect(zoneAwareFrames.filter(f => frames[i].indexOf(f) !== -1)).toEqual([]); + expect(zoneAwareFrames.filter((f) => frames[i].indexOf(f) !== -1)).toEqual([]); } } - }; + } const errorZoneSpec = { name: 'errorZone', - done: <(() => void)|null>null, - onHandleError: - (parentDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: Error) => { - assertStackDoesNotContainZoneFrames(error); - setTimeout(() => { - errorZoneSpec.done && errorZoneSpec.done(); - }, 0); - return false; - } + done: <(() => void) | null>null, + onHandleError: ( + parentDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + error: Error, + ) => { + assertStackDoesNotContainZoneFrames(error); + setTimeout(() => { + errorZoneSpec.done && errorZoneSpec.done(); + }, 0); + return false; + }, }; const errorZone = Zone.root.fork(errorZoneSpec); - const assertStackDoesNotContainZoneFramesTest = function(testFn: Function) { - return function(done: () => void) { + const assertStackDoesNotContainZoneFramesTest = function (testFn: Function) { + return function (done: () => void) { errorZoneSpec.done = done; errorZone.run(testFn); }; }; describe('Error stack', () => { - it('Error with new which occurs in setTimeout callback should not have zone frames visible', - assertStackDoesNotContainZoneFramesTest(() => { - setTimeout(() => { - throw new Error('timeout test error'); - }, 10); - })); - - it('Error without new which occurs in setTimeout callback should not have zone frames visible', - assertStackDoesNotContainZoneFramesTest(() => { - setTimeout(() => { - throw Error('test error'); - }, 10); - })); - - it('Error with new which cause by promise rejection should not have zone frames visible', - (done) => { - const p = new Promise((resolve, reject) => { - setTimeout(() => { - reject(new Error('test error')); - }); - }); - p.catch(err => { - assertStackDoesNotContainZoneFrames(err); - done(); - }); - }); - - it('Error without new which cause by promise rejection should not have zone frames visible', - (done) => { - const p = new Promise((resolve, reject) => { - setTimeout(() => { - reject(Error('test error')); - }); - }); - p.catch(err => { - assertStackDoesNotContainZoneFrames(err); - done(); - }); - }); - - it('Error with new which occurs in eventTask callback should not have zone frames visible', - assertStackDoesNotContainZoneFramesTest(() => { - const task = Zone.current.scheduleEventTask('errorEvent', () => { - throw new Error('test error'); - }, undefined, () => null, undefined); - task.invoke(); - })); - - it('Error without new which occurs in eventTask callback should not have zone frames visible', - assertStackDoesNotContainZoneFramesTest(() => { - const task = Zone.current.scheduleEventTask('errorEvent', () => { - throw Error('test error'); - }, undefined, () => null, undefined); - task.invoke(); - })); - - it('Error with new which occurs in longStackTraceZone should not have zone frames and longStackTraceZone frames visible', - assertStackDoesNotContainZoneFramesTest(() => { - const task = Zone.current.fork((Zone as any)['longStackTraceZoneSpec']) - .scheduleEventTask('errorEvent', () => { - throw new Error('test error'); - }, undefined, () => null, undefined); - task.invoke(); - })); - - it('Error without new which occurs in longStackTraceZone should not have zone frames and longStackTraceZone frames visible', - assertStackDoesNotContainZoneFramesTest(() => { - const task = Zone.current.fork((Zone as any)['longStackTraceZoneSpec']) - .scheduleEventTask('errorEvent', () => { - throw Error('test error'); - }, undefined, () => null, undefined); - task.invoke(); - })); - - it('stack frames of the callback in user customized zoneSpec should be kept', - assertStackDoesNotContainZoneFramesTest(() => { - const task = Zone.current.fork((Zone as any)['longStackTraceZoneSpec']) - .fork({ - name: 'customZone', - onScheduleTask: (parentDelegate, currentZone, targetZone, task) => { - return parentDelegate.scheduleTask(targetZone, task); - }, - onHandleError: (parentDelegate, currentZone, targetZone, error) => { - parentDelegate.handleError(targetZone, error); - const containsCustomZoneSpecStackTrace = - error.stack.indexOf('onScheduleTask') !== -1; - expect(containsCustomZoneSpecStackTrace).toBeTruthy(); - return false; - } - }) - .scheduleEventTask('errorEvent', () => { - throw new Error('test error'); - }, undefined, () => null, undefined); - task.invoke(); - })); - - it('should be able to generate zone free stack even NativeError stack is readonly', function() { + it( + 'Error with new which occurs in setTimeout callback should not have zone frames visible', + assertStackDoesNotContainZoneFramesTest(() => { + setTimeout(() => { + throw new Error('timeout test error'); + }, 10); + }), + ); + + it( + 'Error without new which occurs in setTimeout callback should not have zone frames visible', + assertStackDoesNotContainZoneFramesTest(() => { + setTimeout(() => { + throw Error('test error'); + }, 10); + }), + ); + + it('Error with new which cause by promise rejection should not have zone frames visible', (done) => { + const p = new Promise((resolve, reject) => { + setTimeout(() => { + reject(new Error('test error')); + }); + }); + p.catch((err) => { + assertStackDoesNotContainZoneFrames(err); + done(); + }); + }); + + it('Error without new which cause by promise rejection should not have zone frames visible', (done) => { + const p = new Promise((resolve, reject) => { + setTimeout(() => { + reject(Error('test error')); + }); + }); + p.catch((err) => { + assertStackDoesNotContainZoneFrames(err); + done(); + }); + }); + + it( + 'Error with new which occurs in eventTask callback should not have zone frames visible', + assertStackDoesNotContainZoneFramesTest(() => { + const task = Zone.current.scheduleEventTask( + 'errorEvent', + () => { + throw new Error('test error'); + }, + undefined, + () => null, + undefined, + ); + task.invoke(); + }), + ); + + it( + 'Error without new which occurs in eventTask callback should not have zone frames visible', + assertStackDoesNotContainZoneFramesTest(() => { + const task = Zone.current.scheduleEventTask( + 'errorEvent', + () => { + throw Error('test error'); + }, + undefined, + () => null, + undefined, + ); + task.invoke(); + }), + ); + + it( + 'Error with new which occurs in longStackTraceZone should not have zone frames and longStackTraceZone frames visible', + assertStackDoesNotContainZoneFramesTest(() => { + const task = Zone.current.fork((Zone as any)['longStackTraceZoneSpec']).scheduleEventTask( + 'errorEvent', + () => { + throw new Error('test error'); + }, + undefined, + () => null, + undefined, + ); + task.invoke(); + }), + ); + + it( + 'Error without new which occurs in longStackTraceZone should not have zone frames and longStackTraceZone frames visible', + assertStackDoesNotContainZoneFramesTest(() => { + const task = Zone.current.fork((Zone as any)['longStackTraceZoneSpec']).scheduleEventTask( + 'errorEvent', + () => { + throw Error('test error'); + }, + undefined, + () => null, + undefined, + ); + task.invoke(); + }), + ); + + it( + 'stack frames of the callback in user customized zoneSpec should be kept', + assertStackDoesNotContainZoneFramesTest(() => { + const task = Zone.current + .fork((Zone as any)['longStackTraceZoneSpec']) + .fork({ + name: 'customZone', + onScheduleTask: (parentDelegate, currentZone, targetZone, task) => { + return parentDelegate.scheduleTask(targetZone, task); + }, + onHandleError: (parentDelegate, currentZone, targetZone, error) => { + parentDelegate.handleError(targetZone, error); + const containsCustomZoneSpecStackTrace = error.stack.indexOf('onScheduleTask') !== -1; + expect(containsCustomZoneSpecStackTrace).toBeTruthy(); + return false; + }, + }) + .scheduleEventTask( + 'errorEvent', + () => { + throw new Error('test error'); + }, + undefined, + () => null, + undefined, + ); + task.invoke(); + }), + ); + + it('should be able to generate zone free stack even NativeError stack is readonly', function () { const _global: any = - typeof window === 'object' && window || typeof self === 'object' && self || global; + (typeof window === 'object' && window) || (typeof self === 'object' && self) || global; const NativeError = _global[zoneSymbol('Error')]; const desc = Object.getOwnPropertyDescriptor(NativeError.prototype, 'stack'); if (desc) { - const originalSet: ((value: any) => void)|undefined = desc.set; + const originalSet: ((value: any) => void) | undefined = desc.set; // make stack readonly desc.set = null as any; diff --git a/packages/zone.js/test/common/Promise.spec.ts b/packages/zone.js/test/common/Promise.spec.ts index 126d8b50524af..9fec6780af06f 100644 --- a/packages/zone.js/test/common/Promise.spec.ts +++ b/packages/zone.js/test/common/Promise.spec.ts @@ -38,897 +38,942 @@ class TestRejection { } describe( - 'Promise', ifEnvSupports('Promise', function() { - if (!global.Promise) return; - let log: string[]; - let queueZone: Zone; - let testZone: Zone; - let pZone: Zone; - - beforeEach(() => { - testZone = Zone.current.fork({name: 'TestZone'}); + 'Promise', + ifEnvSupports('Promise', function () { + if (!global.Promise) return; + let log: string[]; + let queueZone: Zone; + let testZone: Zone; + let pZone: Zone; + + beforeEach(() => { + testZone = Zone.current.fork({name: 'TestZone'}); + + pZone = Zone.current.fork({ + name: 'promise-zone', + onScheduleTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): any => { + log.push('scheduleTask'); + parentZoneDelegate.scheduleTask(targetZone, task); + }, + }); - pZone = Zone.current.fork({ - name: 'promise-zone', - onScheduleTask: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - any => { - log.push('scheduleTask'); - parentZoneDelegate.scheduleTask(targetZone, task); - } - }); + queueZone = Zone.current.fork(new MicroTaskQueueZoneSpec()); - queueZone = Zone.current.fork(new MicroTaskQueueZoneSpec()); + log = []; + }); - log = []; - }); + it('should pretend to be a native code', () => { + expect(String(Promise).indexOf('[native code]') >= 0).toBe(true); + }); - it('should pretend to be a native code', () => { - expect(String(Promise).indexOf('[native code]') >= 0).toBe(true); - }); + it('should use native toString for promise instance', () => { + expect(Object.prototype.toString.call(Promise.resolve())).toEqual('[object Promise]'); + }); - it('should use native toString for promise instance', () => { - expect(Object.prototype.toString.call(Promise.resolve())).toEqual('[object Promise]'); - }); + it('should make sure that new Promise is instance of Promise', () => { + expect(Promise.resolve(123) instanceof Promise).toBe(true); + expect(new Promise(() => null) instanceof Promise).toBe(true); + }); - it('should make sure that new Promise is instance of Promise', () => { - expect(Promise.resolve(123) instanceof Promise).toBe(true); - expect(new Promise(() => null) instanceof Promise).toBe(true); - }); + it('Promise.resolve(subPromise) should equal to subPromise', () => { + const p1 = Promise.resolve(1); + const p2 = Promise.resolve(p1); + expect(p1).toBe(p2); + }); - it('Promise.resolve(subPromise) should equal to subPromise', () => { - const p1 = Promise.resolve(1); - const p2 = Promise.resolve(p1); - expect(p1).toBe(p2); - }); + xit('should ensure that Promise this is instanceof Promise', () => { + expect(() => { + Promise.call({} as any, () => null); + }).toThrowError('Must be an instanceof Promise.'); + }); - xit('should ensure that Promise this is instanceof Promise', () => { - expect(() => { - Promise.call({} as any, () => null); - }).toThrowError('Must be an instanceof Promise.'); + it('should allow subclassing without Symbol.species', () => { + class MyPromise extends Promise { + constructor(fn: any) { + super(fn); + } + } + expect(new MyPromise(() => {}).then(() => null) instanceof MyPromise).toBe(true); + }); + + it('should allow subclassing without Symbol.species if properties are copied (SystemJS case)', () => { + let value: any = null; + const promise = Promise.resolve(); + const systemjsModule = Object.create(null); + + // We only copy properties from the `promise` instance onto the `systemjsModule` object. + // This is what SystemJS is doing internally: + // https://github.com/systemjs/systemjs/blob/main/src/system-core.js#L107-L113 + for (const property in promise) { + const value: any = promise[property as keyof typeof promise]; + if (!(value in systemjsModule) || systemjsModule[property] !== value) { + systemjsModule[property] = value; + } + } + + queueZone.run(() => { + Promise.resolve() + .then(() => systemjsModule) + .then((v) => (value = v)); + flushMicrotasks(); + // Note: we want to ensure that the promise has been resolved. In this specific case + // the promise may resolve to different values in the browser and on the Node.js side. + // SystemJS runs only in the browser and it only needs the promise to be resolved. + expect(value).not.toEqual(null); }); + }); - it('should allow subclassing without Symbol.species', () => { - class MyPromise extends Promise { - constructor(fn: any) { - super(fn); - } + it('should allow subclassing with Symbol.species', () => { + class MyPromise extends Promise { + constructor(fn: any) { + super(fn); } - expect(new MyPromise(() => {}).then(() => null) instanceof MyPromise).toBe(true); - }); - - it('should allow subclassing without Symbol.species if properties are copied (SystemJS case)', - () => { - let value: any = null; - const promise = Promise.resolve(); - const systemjsModule = Object.create(null); - - // We only copy properties from the `promise` instance onto the `systemjsModule` object. - // This is what SystemJS is doing internally: - // https://github.com/systemjs/systemjs/blob/main/src/system-core.js#L107-L113 - for (const property in promise) { - const value: any = promise[property as keyof typeof promise]; - if (!(value in systemjsModule) || systemjsModule[property] !== value) { - systemjsModule[property] = value; - } - } - - queueZone.run(() => { - Promise.resolve().then(() => systemjsModule).then((v) => (value = v)); - flushMicrotasks(); - // Note: we want to ensure that the promise has been resolved. In this specific case - // the promise may resolve to different values in the browser and on the Node.js side. - // SystemJS runs only in the browser and it only needs the promise to be resolved. - expect(value).not.toEqual(null); - }); - }); - - it('should allow subclassing with Symbol.species', () => { - class MyPromise extends Promise { - constructor(fn: any) { - super(fn); - } - - static override get[Symbol.species]() { - return MyPromise; - } + + static override get [Symbol.species]() { + return MyPromise; } - expect(new MyPromise(() => {}).then(() => null) instanceof MyPromise).toBe(true); - }); + } + expect(new MyPromise(() => {}).then(() => null) instanceof MyPromise).toBe(true); + }); - it('should allow subclassing with own then', (done: DoneFn) => { - class MyPromise extends Promise { - constructor(private sub: Promise) { - super((resolve) => {resolve(null)}); - } + it('should allow subclassing with own then', (done: DoneFn) => { + class MyPromise extends Promise { + constructor(private sub: Promise) { + super((resolve) => { + resolve(null); + }); + } - override then(onFulfilled: any, onRejected: any) { - return this.sub.then(onFulfilled, onRejected); - } + override then(onFulfilled: any, onRejected: any) { + return this.sub.then(onFulfilled, onRejected); } - const p = Promise.resolve(1); - new MyPromise(p).then((v: any) => { + } + const p = Promise.resolve(1); + new MyPromise(p).then( + (v: any) => { expect(v).toBe(1); done(); - }, () => done()); + }, + () => done(), + ); + }); + + it('Symbol.species should return ZoneAwarePromise', () => { + const empty = function () {}; + const promise = Promise.resolve(1); + const FakePromise = (((promise.constructor = {} as any) as any)[Symbol.species] = function ( + exec: any, + ) { + exec(empty, empty); }); - - it('Symbol.species should return ZoneAwarePromise', () => { - const empty = function() {}; - const promise = Promise.resolve(1); - const FakePromise = - ((promise.constructor = {} as any) as any)[Symbol.species] = function(exec: any) { - exec(empty, empty); - }; - expect(promise.then(empty) instanceof FakePromise).toBe(true); + expect(promise.then(empty) instanceof FakePromise).toBe(true); + }); + + it('should intercept scheduling of resolution and then', (done) => { + pZone.run(() => { + let p: Promise = new Promise(function (resolve, reject) { + expect(resolve('RValue')).toBe(undefined); + }); + expect(log).toEqual([]); + expect(p instanceof Promise).toBe(true); + p = p.then((v) => { + log.push(v); + expect(v).toBe('RValue'); + expect(log).toEqual(['scheduleTask', 'RValue']); + return 'second value'; + }); + expect(p instanceof Promise).toBe(true); + expect(log).toEqual(['scheduleTask']); + p = p.then((v) => { + log.push(v); + expect(log).toEqual(['scheduleTask', 'RValue', 'scheduleTask', 'second value']); + done(); + }); + expect(p instanceof Promise).toBe(true); + expect(log).toEqual(['scheduleTask']); }); - - it('should intercept scheduling of resolution and then', (done) => { - pZone.run(() => { - let p: Promise = new Promise(function(resolve, reject) { - expect(resolve('RValue')).toBe(undefined); - }); - expect(log).toEqual([]); - expect(p instanceof Promise).toBe(true); - p = p.then((v) => { + }); + + it('should allow sync resolution of promises', () => { + queueZone.run(() => { + const flush = Zone.current.get('flush'); + const queue = Zone.current.get('queue'); + const p = new Promise(function (resolve, reject) { + resolve('RValue'); + }) + .then((v: string) => { log.push(v); - expect(v).toBe('RValue'); - expect(log).toEqual(['scheduleTask', 'RValue']); return 'second value'; + }) + .then((v: string) => { + log.push(v); }); - expect(p instanceof Promise).toBe(true); - expect(log).toEqual(['scheduleTask']); - p = p.then((v) => { + expect(queue.length).toEqual(1); + expect(log).toEqual([]); + flush(); + expect(log).toEqual(['RValue', 'second value']); + }); + }); + + it('should allow sync resolution of promises returning promises', () => { + queueZone.run(() => { + const flush = Zone.current.get('flush'); + const queue = Zone.current.get('queue'); + const p = new Promise(function (resolve, reject) { + resolve(Promise.resolve('RValue')); + }) + .then((v: string) => { + log.push(v); + return Promise.resolve('second value'); + }) + .then((v: string) => { log.push(v); - expect(log).toEqual(['scheduleTask', 'RValue', 'scheduleTask', 'second value']); + }); + expect(queue.length).toEqual(1); + expect(log).toEqual([]); + flush(); + expect(log).toEqual(['RValue', 'second value']); + }); + }); + + describe('Promise API', function () { + it('should work with .then', function (done) { + let resolve: Function | null = null; + + testZone.run(function () { + new Promise(function (resolveFn) { + resolve = resolveFn; + }).then(function () { + expect(Zone.current).toBe(testZone); done(); }); - expect(p instanceof Promise).toBe(true); - expect(log).toEqual(['scheduleTask']); }); + + resolve!(); }); - it('should allow sync resolution of promises', () => { - queueZone.run(() => { - const flush = Zone.current.get('flush'); - const queue = Zone.current.get('queue'); - const p = new Promise(function(resolve, reject) { - resolve('RValue'); - }) - .then((v: string) => { - log.push(v); - return 'second value'; - }) - .then((v: string) => { - log.push(v); - }); - expect(queue.length).toEqual(1); - expect(log).toEqual([]); - flush(); - expect(log).toEqual(['RValue', 'second value']); - }); - }); - - it('should allow sync resolution of promises returning promises', () => { - queueZone.run(() => { - const flush = Zone.current.get('flush'); - const queue = Zone.current.get('queue'); - const p = new Promise(function(resolve, reject) { - resolve(Promise.resolve('RValue')); - }) - .then((v: string) => { - log.push(v); - return Promise.resolve('second value'); - }) - .then((v: string) => { - log.push(v); - }); - expect(queue.length).toEqual(1); - expect(log).toEqual([]); - flush(); - expect(log).toEqual(['RValue', 'second value']); - }); - }); - - describe('Promise API', function() { - it('should work with .then', function(done) { - let resolve: Function|null = null; - - testZone.run(function() { - new Promise(function(resolveFn) { - resolve = resolveFn; - }).then(function() { - expect(Zone.current).toBe(testZone); - done(); - }); + it('should work with .catch', function (done) { + let reject: (() => void) | null = null; + + testZone.run(function () { + new Promise(function (resolveFn, rejectFn) { + reject = rejectFn; + })['catch'](function () { + expect(Zone.current).toBe(testZone); + done(); }); + }); + + expect(reject!()).toBe(undefined); + }); - resolve!(); + it('should work with .finally with resolved promise', function (done) { + let resolve: Function | null = null; + + testZone.run(function () { + ( + new Promise(function (resolveFn) { + resolve = resolveFn; + }) as any + ).finally(function () { + expect(arguments.length).toBe(0); + expect(Zone.current).toBe(testZone); + done(); + }); }); - it('should work with .catch', function(done) { - let reject: (() => void)|null = null; + resolve!('value'); + }); + + it('should work with .finally with rejected promise', function (done) { + let reject: Function | null = null; - testZone.run(function() { - new Promise(function(resolveFn, rejectFn) { + testZone.run(function () { + ( + new Promise(function (_, rejectFn) { reject = rejectFn; - })['catch'](function() { - expect(Zone.current).toBe(testZone); - done(); - }); + }) as any + ).finally(function () { + expect(arguments.length).toBe(0); + expect(Zone.current).toBe(testZone); + done(); }); + }); + reject!('error'); + }); - expect(reject!()).toBe(undefined); + it('should work with Promise.resolve', () => { + queueZone.run(() => { + let value: any = null; + Promise.resolve('resolveValue').then((v) => (value = v)); + expect(Zone.current.get('queue').length).toEqual(1); + flushMicrotasks(); + expect(value).toEqual('resolveValue'); }); + }); - it('should work with .finally with resolved promise', function(done) { - let resolve: Function|null = null; + it('should work with Promise.reject', () => { + queueZone.run(() => { + let value: any = null; + Promise.reject('rejectReason')['catch']((v) => (value = v)); + expect(Zone.current.get('queue').length).toEqual(1); + flushMicrotasks(); + expect(value).toEqual('rejectReason'); + }); + }); - testZone.run(function() { - (new Promise(function(resolveFn) { - resolve = resolveFn; - }) as any) - .finally(function() { - expect(arguments.length).toBe(0); - expect(Zone.current).toBe(testZone); - done(); - }); + describe('reject', () => { + it('should reject promise', () => { + queueZone.run(() => { + let value: any = null; + Promise.reject('rejectReason')['catch']((v) => (value = v)); + flushMicrotasks(); + expect(value).toEqual('rejectReason'); }); - - resolve!('value'); }); - it('should work with .finally with rejected promise', function(done) { - let reject: Function|null = null; - - testZone.run(function() { - (new Promise(function(_, rejectFn) { - reject = rejectFn; - }) as any) - .finally(function() { - expect(arguments.length).toBe(0); - expect(Zone.current).toBe(testZone); - done(); - }); + it('should re-reject promise', () => { + queueZone.run(() => { + let value: any = null; + Promise.reject('rejectReason') + ['catch']((v) => { + throw v; + }) + ['catch']((v) => (value = v)); + flushMicrotasks(); + expect(value).toEqual('rejectReason'); }); - - reject!('error'); }); - it('should work with Promise.resolve', () => { + it('should reject and recover promise', () => { queueZone.run(() => { let value: any = null; - Promise.resolve('resolveValue').then((v) => value = v); - expect(Zone.current.get('queue').length).toEqual(1); + Promise.reject('rejectReason') + ['catch']((v) => v) + .then((v) => (value = v)); flushMicrotasks(); - expect(value).toEqual('resolveValue'); + expect(value).toEqual('rejectReason'); }); }); - it('should work with Promise.reject', () => { + it('should reject if chained promise does not catch promise', () => { queueZone.run(() => { let value: any = null; - Promise.reject('rejectReason')['catch']((v) => value = v); - expect(Zone.current.get('queue').length).toEqual(1); + Promise.reject('rejectReason') + .then((v) => fail('should not get here')) + .then(null, (v) => (value = v)); flushMicrotasks(); expect(value).toEqual('rejectReason'); }); }); - describe('reject', () => { - it('should reject promise', () => { - queueZone.run(() => { - let value: any = null; - Promise.reject('rejectReason')['catch']((v) => value = v); - flushMicrotasks(); - expect(value).toEqual('rejectReason'); + it('should output error to console if ignoreConsoleErrorUncaughtError is false', async () => { + await jasmine.spyOnGlobalErrorsAsync(() => { + const originalConsoleError = console.error; + Zone.current.fork({name: 'promise-error'}).run(() => { + (Zone as any)[Zone.__symbol__('ignoreConsoleErrorUncaughtError')] = false; + console.error = jasmine.createSpy('consoleErr'); + const p = new Promise((resolve, reject) => { + throw new Error('promise error'); + }); }); - }); - - it('should re-reject promise', () => { - queueZone.run(() => { - let value: any = null; - Promise.reject('rejectReason')['catch']((v) => { - throw v; - })['catch']((v) => value = v); - flushMicrotasks(); - expect(value).toEqual('rejectReason'); + return new Promise((res) => { + setTimeout(() => { + expect(console.error).toHaveBeenCalled(); + console.error = originalConsoleError; + res(); + }); }); }); + }); - it('should reject and recover promise', () => { - queueZone.run(() => { - let value: any = null; - Promise.reject('rejectReason')['catch']((v) => v).then((v) => value = v); - flushMicrotasks(); - expect(value).toEqual('rejectReason'); + it('should not output error to console if ignoreConsoleErrorUncaughtError is true', async () => { + await jasmine.spyOnGlobalErrorsAsync(() => { + const originalConsoleError = console.error; + Zone.current.fork({name: 'promise-error'}).run(() => { + (Zone as any)[Zone.__symbol__('ignoreConsoleErrorUncaughtError')] = true; + console.error = jasmine.createSpy('consoleErr'); + const p = new Promise((resolve, reject) => { + throw new Error('promise error'); + }); + }); + return new Promise((res) => { + setTimeout(() => { + expect(console.error).not.toHaveBeenCalled(); + console.error = originalConsoleError; + (Zone as any)[Zone.__symbol__('ignoreConsoleErrorUncaughtError')] = false; + res(); + }); }); }); + }); - it('should reject if chained promise does not catch promise', () => { - queueZone.run(() => { - let value: any = null; - Promise.reject('rejectReason') - .then((v) => fail('should not get here')) - .then(null, (v) => value = v); - flushMicrotasks(); - expect(value).toEqual('rejectReason'); + it('should notify Zone.onHandleError if no one catches promise', (done) => { + let promiseError: Error | null = null; + let zone: Zone | null = null; + let task: Task | null = null; + let error: Error | null = null; + queueZone + .fork({ + name: 'promise-error', + onHandleError: ( + delegate: ZoneDelegate, + current: Zone, + target: Zone, + error: any, + ): boolean => { + promiseError = error; + delegate.handleError(target, error); + return false; + }, + }) + .run(() => { + zone = Zone.current; + task = Zone.currentTask; + error = new Error('rejectedErrorShouldBeHandled'); + try { + // throw so that the stack trace is captured + throw error; + } catch (e) {} + Promise.reject(error); + expect(promiseError).toBe(null); }); + setTimeout((): any => null); + setTimeout(() => { + expect(promiseError!.message).toBe( + 'Uncaught (in promise): ' + error + (error!.stack ? '\n' + error!.stack : ''), + ); + expect((promiseError as any)['rejection']).toBe(error); + expect((promiseError as any)['zone']).toBe(zone); + expect((promiseError as any)['task']).toBe(task); + done(); }); + }); - it('should output error to console if ignoreConsoleErrorUncaughtError is false', - async () => { - await jasmine.spyOnGlobalErrorsAsync(() => { - const originalConsoleError = console.error; - Zone.current.fork({name: 'promise-error'}).run(() => { - (Zone as any)[Zone.__symbol__('ignoreConsoleErrorUncaughtError')] = false; - console.error = jasmine.createSpy('consoleErr'); - const p = new Promise((resolve, reject) => { - throw new Error('promise error'); - }); - }); - return new Promise(res => { - setTimeout(() => { - expect(console.error).toHaveBeenCalled(); - console.error = originalConsoleError; - res(); - }); - }); - }); - }); - - it('should not output error to console if ignoreConsoleErrorUncaughtError is true', - async () => { - await jasmine.spyOnGlobalErrorsAsync(() => { - const originalConsoleError = console.error; - Zone.current.fork({name: 'promise-error'}).run(() => { - (Zone as any)[Zone.__symbol__('ignoreConsoleErrorUncaughtError')] = true; - console.error = jasmine.createSpy('consoleErr'); - const p = new Promise((resolve, reject) => { - throw new Error('promise error'); - }); - }); - return new Promise(res => { - setTimeout(() => { - expect(console.error).not.toHaveBeenCalled(); - console.error = originalConsoleError; - (Zone as any)[Zone.__symbol__('ignoreConsoleErrorUncaughtError')] = false; - res(); - }); - }); - }); - }); - - it('should notify Zone.onHandleError if no one catches promise', (done) => { - let promiseError: Error|null = null; - let zone: Zone|null = null; - let task: Task|null = null; - let error: Error|null = null; - queueZone - .fork({ - name: 'promise-error', - onHandleError: (delegate: ZoneDelegate, current: Zone, target: Zone, error: any): - boolean => { - promiseError = error; - delegate.handleError(target, error); - return false; - } - }) - .run(() => { - zone = Zone.current; - task = Zone.currentTask; - error = new Error('rejectedErrorShouldBeHandled'); - try { - // throw so that the stack trace is captured - throw error; - } catch (e) { - } - Promise.reject(error); - expect(promiseError).toBe(null); - }); - setTimeout((): any => null); - setTimeout(() => { - expect(promiseError!.message) - .toBe( - 'Uncaught (in promise): ' + error + - (error!.stack ? '\n' + error!.stack : '')); - expect((promiseError as any)['rejection']).toBe(error); - expect((promiseError as any)['zone']).toBe(zone); - expect((promiseError as any)['task']).toBe(task); - done(); + it('should print readable information when throw a not error object', (done) => { + let promiseError: Error | null = null; + let zone: Zone | null = null; + let task: Task | null = null; + let rejectObj: TestRejection; + queueZone + .fork({ + name: 'promise-error', + onHandleError: ( + delegate: ZoneDelegate, + current: Zone, + target: Zone, + error: any, + ): boolean => { + promiseError = error; + delegate.handleError(target, error); + return false; + }, + }) + .run(() => { + zone = Zone.current; + task = Zone.currentTask; + rejectObj = new TestRejection(); + rejectObj.prop1 = 'value1'; + rejectObj.prop2 = 'value2'; + Promise.reject(rejectObj); + expect(promiseError).toBe(null); }); + setTimeout((): any => null); + setTimeout(() => { + expect(promiseError!.message).toMatch( + /Uncaught \(in promise\):.*: {"prop1":"value1","prop2":"value2"}/, + ); + done(); }); + }); + }); - it('should print readable information when throw a not error object', (done) => { - let promiseError: Error|null = null; - let zone: Zone|null = null; - let task: Task|null = null; - let rejectObj: TestRejection; - queueZone - .fork({ - name: 'promise-error', - onHandleError: (delegate: ZoneDelegate, current: Zone, target: Zone, error: any): - boolean => { - promiseError = error; - delegate.handleError(target, error); - return false; - } - }) - .run(() => { - zone = Zone.current; - task = Zone.currentTask; - rejectObj = new TestRejection(); - rejectObj.prop1 = 'value1'; - rejectObj.prop2 = 'value2'; - Promise.reject(rejectObj); - expect(promiseError).toBe(null); - }); - setTimeout((): any => null); - setTimeout(() => { - expect(promiseError!.message) - .toMatch(/Uncaught \(in promise\):.*: {"prop1":"value1","prop2":"value2"}/); - done(); - }); + describe('Promise.race', () => { + it('should reject the value', () => { + queueZone.run(() => { + let value: any = null; + (Promise as any) + .race([Promise.reject('rejection1'), 'v1']) + ['catch']((v: any) => (value = v)); + // expect(Zone.current.get('queue').length).toEqual(2); + flushMicrotasks(); + expect(value).toEqual('rejection1'); }); }); - describe('Promise.race', () => { - it('should reject the value', () => { - queueZone.run(() => { - let value: any = null; - (Promise as any).race([ - Promise.reject('rejection1'), 'v1' - ])['catch']((v: any) => value = v); - // expect(Zone.current.get('queue').length).toEqual(2); - flushMicrotasks(); - expect(value).toEqual('rejection1'); - }); + it('should resolve the value', () => { + queueZone.run(() => { + let value: any = null; + (Promise as any) + .race([Promise.resolve('resolution'), 'v1']) + .then((v: any) => (value = v)); + // expect(Zone.current.get('queue').length).toEqual(2); + flushMicrotasks(); + expect(value).toEqual('resolution'); }); + }); + }); - it('should resolve the value', () => { - queueZone.run(() => { - let value: any = null; - (Promise as any) - .race([Promise.resolve('resolution'), 'v1']) - .then((v: any) => value = v); - // expect(Zone.current.get('queue').length).toEqual(2); - flushMicrotasks(); - expect(value).toEqual('resolution'); - }); + describe('Promise.all', () => { + it('should reject the value', () => { + queueZone.run(() => { + let value: any = null; + Promise.all([Promise.reject('rejection'), 'v1'])['catch']((v: any) => (value = v)); + // expect(Zone.current.get('queue').length).toEqual(2); + flushMicrotasks(); + expect(value).toEqual('rejection'); }); }); - describe('Promise.all', () => { - it('should reject the value', () => { - queueZone.run(() => { - let value: any = null; - Promise.all([Promise.reject('rejection'), 'v1'])['catch']((v: any) => value = v); - // expect(Zone.current.get('queue').length).toEqual(2); - flushMicrotasks(); - expect(value).toEqual('rejection'); - }); + it('should resolve the value', () => { + queueZone.run(() => { + let value: any = null; + Promise.all([Promise.resolve('resolution'), 'v1']).then((v: any) => (value = v)); + // expect(Zone.current.get('queue').length).toEqual(2); + flushMicrotasks(); + expect(value).toEqual(['resolution', 'v1']); }); + }); - it('should resolve the value', () => { - queueZone.run(() => { - let value: any = null; - Promise.all([Promise.resolve('resolution'), 'v1']).then((v: any) => value = v); - // expect(Zone.current.get('queue').length).toEqual(2); - flushMicrotasks(); - expect(value).toEqual(['resolution', 'v1']); - }); + it('should resolve with the sync then operation', () => { + queueZone.run(() => { + let value: any = null; + const p1 = { + then: function (thenCallback: Function) { + return thenCallback('p1'); + }, + }; + const p2 = { + then: function (thenCallback: Function) { + return thenCallback('p2'); + }, + }; + Promise.all([p1, 'v1', p2]).then((v: any) => (value = v)); + // expect(Zone.current.get('queue').length).toEqual(2); + flushMicrotasks(); + expect(value).toEqual(['p1', 'v1', 'p2']); }); + }); - it('should resolve with the sync then operation', () => { - queueZone.run(() => { - let value: any = null; - const p1 = { - then: function(thenCallback: Function) { - return thenCallback('p1'); - } + it( + 'should resolve generators', + ifEnvSupports( + () => { + return isNode; + }, + () => { + const generators: any = function* () { + yield Promise.resolve(1); + yield Promise.resolve(2); + return; }; - const p2 = { - then: function(thenCallback: Function) { - return thenCallback('p2'); - } - }; - Promise.all([p1, 'v1', p2]).then((v: any) => value = v); - // expect(Zone.current.get('queue').length).toEqual(2); - flushMicrotasks(); - expect(value).toEqual(['p1', 'v1', 'p2']); - }); - }); + queueZone.run(() => { + let value: any = null; + Promise.all(generators()).then((val) => { + value = val; + }); + // expect(Zone.current.get('queue').length).toEqual(2); + flushMicrotasks(); + expect(value).toEqual([1, 2]); + }); + }, + ), + ); + }); + }); + + describe('Promise subclasses', function () { + class MyPromise { + private _promise: Promise; + constructor(init: any) { + this._promise = new Promise(init); + } - it('should resolve generators', - ifEnvSupports( - () => { - return isNode; - }, - () => { - const generators: any = function*() { - yield Promise.resolve(1); - yield Promise.resolve(2); - return; - }; - queueZone.run(() => { - let value: any = null; - Promise.all(generators()).then(val => { - value = val; - }); - // expect(Zone.current.get('queue').length).toEqual(2); - flushMicrotasks(); - expect(value).toEqual([1, 2]); - }); - })); - }); - }); - - describe('Promise subclasses', function() { - class MyPromise { - private _promise: Promise; - constructor(init: any) { - this._promise = new Promise(init); - } - - catch(onrejected?: ((reason: any) => TResult | PromiseLike)| - undefined|null): Promise { - return this._promise.catch.call(this._promise, onrejected); - }; - - then( - onfulfilled?: ((value: T) => TResult1 | PromiseLike)|undefined|null, - onrejected?: ((reason: any) => TResult2 | PromiseLike)|undefined| - null): Promise { - return this._promise.then.call(this._promise, onfulfilled, onrejected); - }; + catch( + onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null, + ): Promise { + return this._promise.catch.call(this._promise, onrejected); } - const setPrototypeOf = (Object as any).setPrototypeOf || function(obj: any, proto: any) { + then( + onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, + onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, + ): Promise { + return this._promise.then.call(this._promise, onfulfilled, onrejected); + } + } + + const setPrototypeOf = + (Object as any).setPrototypeOf || + function (obj: any, proto: any) { obj.__proto__ = proto; return obj; }; - setPrototypeOf(MyPromise.prototype, Promise.prototype); - - it('should reject if the Promise subclass rejects', function() { - const myPromise = new MyPromise(function(resolve: any, reject: any): void { - reject('foo'); - }); - - return Promise.resolve() - .then(function() { - return myPromise; - }) - .then( - function() { - throw new Error('Unexpected resolution'); - }, - function(result) { - expect(result).toBe('foo'); - }); - }); - - function testPromiseSubClass(done?: Function) { - const myPromise = new MyPromise(function(resolve: any, reject: Function) { - resolve('foo'); - }); - - return Promise.resolve() - .then(function() { - return myPromise; - }) - .then(function(result) { - expect(result).toBe('foo'); - done && done(); - }); - } - - it('should resolve if the Promise subclass resolves', jasmine ? function(done) { - testPromiseSubClass(done); - } : function() { - testPromiseSubClass(); - }); + setPrototypeOf(MyPromise.prototype, Promise.prototype); + + it('should reject if the Promise subclass rejects', function () { + const myPromise = new MyPromise(function (resolve: any, reject: any): void { + reject('foo'); + }); + + return Promise.resolve() + .then(function () { + return myPromise; + }) + .then( + function () { + throw new Error('Unexpected resolution'); + }, + function (result) { + expect(result).toBe('foo'); + }, + ); }); - describe('Promise.any', () => { - const any = (Promise as any).any; - it('undefined parameters', (done: DoneFn) => { - any().then( - () => { - fail('should not get a resolved promise.'); - }, - (err: any) => { - expect(err.message).toEqual('All promises were rejected'); - expect(err.errors).toEqual([]); - done(); - }); - }); - it('invalid iterable', (done: DoneFn) => { - const invalidIterable: any = {}; - invalidIterable[Symbol.iterator] = () => 2; - any(invalidIterable) - .then( - () => { - fail('should not get a resolved promise.'); - }, - (err: any) => { - expect(err.message).toEqual('All promises were rejected'); - expect(err.errors).toEqual([]); - done(); - }); - }); - it('empty parameters', (done: DoneFn) => { - any([]).then( - () => { - fail('should not get a resolved promise.'); - }, - (err: any) => { - expect(err.message).toEqual('All promises were rejected'); - expect(err.errors).toEqual([]); - done(); - }); - }); - it('non promises parameters', (done: DoneFn) => { - any([1, 'test']) - .then( - (v: any) => { - expect(v).toBe(1); - done(); - }, - (err: any) => { - fail('should not get a rejected promise.'); - }); - }); - it('mixed parameters, non promise first', (done: DoneFn) => { - any([1, Promise.resolve(2)]) - .then( - (v: any) => { - expect(v).toBe(1); - done(); - }, - (err: any) => { - fail('should not get a rejected promise.'); - }); - }); - it('mixed parameters, promise first', (done: DoneFn) => { - any([Promise.resolve(1), 2]) - .then( - (v: any) => { - expect(v).toBe(1); - done(); - }, - (err: any) => { - fail('should not get a rejected promise.'); - }); - }); - it('all ok promises', (done: DoneFn) => { - any([Promise.resolve(1), Promise.resolve(2)]) - .then( - (v: any) => { - expect(v).toBe(1); - done(); - }, - (err: any) => { - fail('should not get a rejected promise.'); - }); - }); - it('all promises, first rejected', (done: DoneFn) => { - any([Promise.reject('error'), Promise.resolve(2)]) - .then( - (v: any) => { - expect(v).toBe(2); - done(); - }, - (err: any) => { - fail('should not get a rejected promise.'); - }); - }); - it('all promises, second rejected', (done: DoneFn) => { - any([Promise.resolve(1), Promise.reject('error')]) - .then( - (v: any) => { - expect(v).toBe(1); - done(); - }, - (err: any) => { - fail('should not get a rejected promise.'); - }); - }); - it('all rejected promises', (done: DoneFn) => { - any([ - Promise.reject('error1'), Promise.reject('error2') - ]).then((v: any) => {fail('should not get a resolved promise.')}, (err: any) => { + function testPromiseSubClass(done?: Function) { + const myPromise = new MyPromise(function (resolve: any, reject: Function) { + resolve('foo'); + }); + + return Promise.resolve() + .then(function () { + return myPromise; + }) + .then(function (result) { + expect(result).toBe('foo'); + done && done(); + }); + } + + it( + 'should resolve if the Promise subclass resolves', + jasmine + ? function (done) { + testPromiseSubClass(done); + } + : function () { + testPromiseSubClass(); + }, + ); + }); + + describe('Promise.any', () => { + const any = (Promise as any).any; + it('undefined parameters', (done: DoneFn) => { + any().then( + () => { + fail('should not get a resolved promise.'); + }, + (err: any) => { expect(err.message).toEqual('All promises were rejected'); - expect(err.errors).toEqual(['error1', 'error2']); + expect(err.errors).toEqual([]); done(); - }); - }); + }, + ); }); - - describe('Promise.allSettled', () => { - const yes = function makeFulfilledResult(value: any) { - return {status: 'fulfilled', value: value}; - }; - const no = function makeRejectedResult(reason: any) { - return {status: 'rejected', reason: reason}; - }; - const a = {}; - const b = {}; - const c = {}; - const allSettled = (Promise as any).allSettled; - it('no promise values', (done: DoneFn) => { - allSettled([a, b, c]).then((results: any[]) => { - expect(results).toEqual([yes(a), yes(b), yes(c)]); + it('invalid iterable', (done: DoneFn) => { + const invalidIterable: any = {}; + invalidIterable[Symbol.iterator] = () => 2; + any(invalidIterable).then( + () => { + fail('should not get a resolved promise.'); + }, + (err: any) => { + expect(err.message).toEqual('All promises were rejected'); + expect(err.errors).toEqual([]); done(); - }); + }, + ); + }); + it('empty parameters', (done: DoneFn) => { + any([]).then( + () => { + fail('should not get a resolved promise.'); + }, + (err: any) => { + expect(err.message).toEqual('All promises were rejected'); + expect(err.errors).toEqual([]); + done(); + }, + ); + }); + it('non promises parameters', (done: DoneFn) => { + any([1, 'test']).then( + (v: any) => { + expect(v).toBe(1); + done(); + }, + (err: any) => { + fail('should not get a rejected promise.'); + }, + ); + }); + it('mixed parameters, non promise first', (done: DoneFn) => { + any([1, Promise.resolve(2)]).then( + (v: any) => { + expect(v).toBe(1); + done(); + }, + (err: any) => { + fail('should not get a rejected promise.'); + }, + ); + }); + it('mixed parameters, promise first', (done: DoneFn) => { + any([Promise.resolve(1), 2]).then( + (v: any) => { + expect(v).toBe(1); + done(); + }, + (err: any) => { + fail('should not get a rejected promise.'); + }, + ); + }); + it('all ok promises', (done: DoneFn) => { + any([Promise.resolve(1), Promise.resolve(2)]).then( + (v: any) => { + expect(v).toBe(1); + done(); + }, + (err: any) => { + fail('should not get a rejected promise.'); + }, + ); + }); + it('all promises, first rejected', (done: DoneFn) => { + any([Promise.reject('error'), Promise.resolve(2)]).then( + (v: any) => { + expect(v).toBe(2); + done(); + }, + (err: any) => { + fail('should not get a rejected promise.'); + }, + ); + }); + it('all promises, second rejected', (done: DoneFn) => { + any([Promise.resolve(1), Promise.reject('error')]).then( + (v: any) => { + expect(v).toBe(1); + done(); + }, + (err: any) => { + fail('should not get a rejected promise.'); + }, + ); + }); + it('all rejected promises', (done: DoneFn) => { + any([Promise.reject('error1'), Promise.reject('error2')]).then( + (v: any) => { + fail('should not get a resolved promise.'); + }, + (err: any) => { + expect(err.message).toEqual('All promises were rejected'); + expect(err.errors).toEqual(['error1', 'error2']); + done(); + }, + ); + }); + }); + + describe('Promise.allSettled', () => { + const yes = function makeFulfilledResult(value: any) { + return {status: 'fulfilled', value: value}; + }; + const no = function makeRejectedResult(reason: any) { + return {status: 'rejected', reason: reason}; + }; + const a = {}; + const b = {}; + const c = {}; + const allSettled = (Promise as any).allSettled; + it('no promise values', (done: DoneFn) => { + allSettled([a, b, c]).then((results: any[]) => { + expect(results).toEqual([yes(a), yes(b), yes(c)]); + done(); }); - it('all fulfilled', (done: DoneFn) => { - allSettled([ - Promise.resolve(a), Promise.resolve(b), Promise.resolve(c) - ]).then((results: any[]) => { + }); + it('all fulfilled', (done: DoneFn) => { + allSettled([Promise.resolve(a), Promise.resolve(b), Promise.resolve(c)]).then( + (results: any[]) => { expect(results).toEqual([yes(a), yes(b), yes(c)]); done(); - }); - }); - it('all rejected', (done: DoneFn) => { - allSettled([ - Promise.reject(a), Promise.reject(b), Promise.reject(c) - ]).then((results: any[]) => { + }, + ); + }); + it('all rejected', (done: DoneFn) => { + allSettled([Promise.reject(a), Promise.reject(b), Promise.reject(c)]).then( + (results: any[]) => { expect(results).toEqual([no(a), no(b), no(c)]); done(); - }); + }, + ); + }); + it('mixed', (done: DoneFn) => { + allSettled([a, Promise.resolve(b), Promise.reject(c)]).then((results: any[]) => { + expect(results).toEqual([yes(a), yes(b), no(c)]); + done(); }); - it('mixed', (done: DoneFn) => { - allSettled([a, Promise.resolve(b), Promise.reject(c)]).then((results: any[]) => { + }); + it('mixed should in zone', (done: DoneFn) => { + const zone = Zone.current.fork({name: 'settled'}); + const bPromise = Promise.resolve(b); + const cPromise = Promise.reject(c); + zone.run(() => { + allSettled([a, bPromise, cPromise]).then((results: any[]) => { expect(results).toEqual([yes(a), yes(b), no(c)]); + expect(Zone.current.name).toEqual(zone.name); done(); }); }); - it('mixed should in zone', (done: DoneFn) => { - const zone = Zone.current.fork({name: 'settled'}); - const bPromise = Promise.resolve(b); - const cPromise = Promise.reject(c); - zone.run(() => { - allSettled([a, bPromise, cPromise]).then((results: any[]) => { - expect(results).toEqual([yes(a), yes(b), no(c)]); - expect(Zone.current.name).toEqual(zone.name); - done(); - }); - }); - }); - it('poisoned .then', (done: DoneFn) => { - const promise = new Promise(function() {}); - promise.then = function() { - throw new EvalError(); - }; - allSettled([promise]).then( - () => { - fail('should not reach here'); - }, - (reason: any) => { - expect(reason instanceof EvalError).toBe(true); - done(); - }); + }); + it('poisoned .then', (done: DoneFn) => { + const promise = new Promise(function () {}); + promise.then = function () { + throw new EvalError(); + }; + allSettled([promise]).then( + () => { + fail('should not reach here'); + }, + (reason: any) => { + expect(reason instanceof EvalError).toBe(true); + done(); + }, + ); + }); + const Subclass = (function () { + try { + // eslint-disable-next-line no-new-func + return Function( + 'class Subclass extends Promise { constructor(...args) { super(...args); this.thenArgs = []; } then(...args) { Subclass.thenArgs.push(args); this.thenArgs.push(args); return super.then(...args); } } Subclass.thenArgs = []; return Subclass;', + )(); + } catch (e) { + /**/ + } + + return false; + })(); + + describe('inheritance', () => { + it('preserves correct subclass', () => { + const promise = allSettled.call(Subclass, [1]); + expect(promise instanceof Subclass).toBe(true); + expect(promise.constructor).toEqual(Subclass); }); - const Subclass = (function() { - try { - // eslint-disable-next-line no-new-func - return Function( - 'class Subclass extends Promise { constructor(...args) { super(...args); this.thenArgs = []; } then(...args) { Subclass.thenArgs.push(args); this.thenArgs.push(args); return super.then(...args); } } Subclass.thenArgs = []; return Subclass;')(); - } catch (e) { /**/ - } - - return false; - }()); - - describe('inheritance', () => { - it('preserves correct subclass', () => { - const promise = allSettled.call(Subclass, [1]); - expect(promise instanceof Subclass).toBe(true); - expect(promise.constructor).toEqual(Subclass); - }); - it('invoke the subclass', () => { - Subclass.thenArgs.length = 0; + it('invoke the subclass', () => { + Subclass.thenArgs.length = 0; - const original = Subclass.resolve(); - expect(Subclass.thenArgs.length).toBe(0); - expect(original.thenArgs.length).toBe(0); + const original = Subclass.resolve(); + expect(Subclass.thenArgs.length).toBe(0); + expect(original.thenArgs.length).toBe(0); - allSettled.call(Subclass, [original]); + allSettled.call(Subclass, [original]); - expect(original.thenArgs.length).toBe(1); - expect(Subclass.thenArgs.length).toBe(1); - }); + expect(original.thenArgs.length).toBe(1); + expect(Subclass.thenArgs.length).toBe(1); }); + }); - describe('resolve/reject multiple times', () => { - it('should ignore second resolve', (done) => { - const nested = new Promise(res => setTimeout(() => res('nested'))); - const p = new Promise(res => { - res(nested); - res(1); - }); - p.then(v => { - expect(v).toBe('nested'); - done(); - }); + describe('resolve/reject multiple times', () => { + it('should ignore second resolve', (done) => { + const nested = new Promise((res) => setTimeout(() => res('nested'))); + const p = new Promise((res) => { + res(nested); + res(1); }); - it('should ignore second resolve', (done) => { - const nested = new Promise(res => setTimeout(() => res('nested'))); - const p = new Promise(res => { - res(1); - res(nested); - }); - p.then(v => { - expect(v).toBe(1); - done(); - }); + p.then((v) => { + expect(v).toBe('nested'); + done(); }); - it('should ignore second reject', (done) => { - const p = new Promise((res, rej) => { - rej(1); - rej(2); - }); - p.then( - v => { - fail('should not get here'); - }, - err => { - expect(err).toBe(1); - done(); - }); + }); + it('should ignore second resolve', (done) => { + const nested = new Promise((res) => setTimeout(() => res('nested'))); + const p = new Promise((res) => { + res(1); + res(nested); }); - it('should ignore resolve after reject', (done) => { - const p = new Promise((res, rej) => { - rej(1); - res(2); - }); - p.then( - v => { - fail('should not get here'); - }, - err => { - expect(err).toBe(1); - done(); - }); + p.then((v) => { + expect(v).toBe(1); + done(); }); - it('should ignore reject after resolve', (done) => { - const nested = new Promise(res => setTimeout(() => res('nested'))); - const p = new Promise((res, rej) => { - res(nested); - rej(1); - }); - p.then( - v => { - expect(v).toBe('nested'); - done(); - }, - err => { - fail('should not be here'); - }); + }); + it('should ignore second reject', (done) => { + const p = new Promise((res, rej) => { + rej(1); + rej(2); }); + p.then( + (v) => { + fail('should not get here'); + }, + (err) => { + expect(err).toBe(1); + done(); + }, + ); + }); + it('should ignore resolve after reject', (done) => { + const p = new Promise((res, rej) => { + rej(1); + res(2); + }); + p.then( + (v) => { + fail('should not get here'); + }, + (err) => { + expect(err).toBe(1); + done(); + }, + ); + }); + it('should ignore reject after resolve', (done) => { + const nested = new Promise((res) => setTimeout(() => res('nested'))); + const p = new Promise((res, rej) => { + res(nested); + rej(1); + }); + p.then( + (v) => { + expect(v).toBe('nested'); + done(); + }, + (err) => { + fail('should not be here'); + }, + ); }); }); + }); - describe('Promise.withResolvers', () => { - it('should resolve', (done: DoneFn) => { - const {promise, resolve, reject} = (Promise as any).withResolvers(); - promise.then((v: any) => { - expect(v).toBe(1); - done(); - }); - resolve(1); + describe('Promise.withResolvers', () => { + it('should resolve', (done: DoneFn) => { + const {promise, resolve, reject} = (Promise as any).withResolvers(); + promise.then((v: any) => { + expect(v).toBe(1); + done(); }); - it('should reject', (done: DoneFn) => { - const {promise, resolve, reject} = (Promise as any).withResolvers(); - const error = new Error('test'); - promise.catch((e: any) => { - expect(e).toBe(error); - done(); - }); - reject(error); + resolve(1); + }); + it('should reject', (done: DoneFn) => { + const {promise, resolve, reject} = (Promise as any).withResolvers(); + const error = new Error('test'); + promise.catch((e: any) => { + expect(e).toBe(error); + done(); }); + reject(error); }); - })); + }); + }), +); diff --git a/packages/zone.js/test/common/fetch.spec.ts b/packages/zone.js/test/common/fetch.spec.ts index c2d37c54910fa..d6228e1dc9808 100644 --- a/packages/zone.js/test/common/fetch.spec.ts +++ b/packages/zone.js/test/common/fetch.spec.ts @@ -11,243 +11,289 @@ import {ifEnvSupports, ifEnvSupportsWithDone, isFirefox, isSafari} from '../test declare const global: any; describe( - 'fetch', isNode ? () => { - it('is untested for node as the fetch implementation is experimental', () => {}); - } : ifEnvSupports('fetch', function() { - let testZone: Zone; - beforeEach(() => { - testZone = Zone.current.fork({name: 'TestZone'}); - }); - it('should work for text response', function(done) { - testZone.run(function() { - global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json') - .then(function(response: any) { - const fetchZone = Zone.current; - expect(fetchZone.name).toBe(testZone.name); - - response.text().then(function(text: string) { - expect(Zone.current.name).toBe(fetchZone.name); - expect(text.trim()).toEqual('{"hello": "world"}'); - done(); - }); - }); - }); - }); - - it('should work for json response', function(done) { - testZone.run(function() { - global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json') - .then(function(response: any) { - const fetchZone = Zone.current; - expect(fetchZone.name).toBe(testZone.name); - - response.json().then(function(obj: any) { - expect(Zone.current.name).toBe(fetchZone.name); - expect(obj.hello).toEqual('world'); - done(); - }); - }); - }); - }); - - it('should work for blob response', function(done) { - testZone.run(function() { - global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json') - .then(function(response: any) { - const fetchZone = Zone.current; - expect(fetchZone.name).toBe(testZone.name); - - // Android 4.3- doesn't support response.blob() - if (response.blob) { - response.blob().then(function(blob: any) { + 'fetch', + isNode + ? () => { + it('is untested for node as the fetch implementation is experimental', () => {}); + } + : ifEnvSupports( + 'fetch', + function () { + let testZone: Zone; + beforeEach(() => { + testZone = Zone.current.fork({name: 'TestZone'}); + }); + it('should work for text response', function (done) { + testZone.run(function () { + global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json').then( + function (response: any) { + const fetchZone = Zone.current; + expect(fetchZone.name).toBe(testZone.name); + + response.text().then(function (text: string) { expect(Zone.current.name).toBe(fetchZone.name); - expect(blob instanceof Blob).toEqual(true); + expect(text.trim()).toEqual('{"hello": "world"}'); done(); }); - } else { - done(); - } - }); - }); - }); - - it('should work for arrayBuffer response', function(done) { - testZone.run(function() { - global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json') - .then(function(response: any) { - const fetchZone = Zone.current; - expect(fetchZone.name).toBe(testZone.name); - - // Android 4.3- doesn't support response.arrayBuffer() - if (response.arrayBuffer) { - response.arrayBuffer().then(function(blob: any) { - expect(Zone.current).toBe(fetchZone); - expect(blob instanceof ArrayBuffer).toEqual(true); + }, + ); + }); + }); + + it('should work for json response', function (done) { + testZone.run(function () { + global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json').then( + function (response: any) { + const fetchZone = Zone.current; + expect(fetchZone.name).toBe(testZone.name); + + response.json().then(function (obj: any) { + expect(Zone.current.name).toBe(fetchZone.name); + expect(obj.hello).toEqual('world'); done(); }); - } else { - done(); - } + }, + ); + }); + }); + + it('should work for blob response', function (done) { + testZone.run(function () { + global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json').then( + function (response: any) { + const fetchZone = Zone.current; + expect(fetchZone.name).toBe(testZone.name); + + // Android 4.3- doesn't support response.blob() + if (response.blob) { + response.blob().then(function (blob: any) { + expect(Zone.current.name).toBe(fetchZone.name); + expect(blob instanceof Blob).toEqual(true); + done(); + }); + } else { + done(); + } + }, + ); + }); + }); + + it('should work for arrayBuffer response', function (done) { + testZone.run(function () { + global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json').then( + function (response: any) { + const fetchZone = Zone.current; + expect(fetchZone.name).toBe(testZone.name); + + // Android 4.3- doesn't support response.arrayBuffer() + if (response.arrayBuffer) { + response.arrayBuffer().then(function (blob: any) { + expect(Zone.current).toBe(fetchZone); + expect(blob instanceof ArrayBuffer).toEqual(true); + done(); + }); + } else { + done(); + } + }, + ); + }); + }); + + it( + 'should throw error when send crendential', + ifEnvSupportsWithDone(isFirefox, function (done: DoneFn) { + testZone.run(function () { + global['fetch']('http://user:password@example.com').then( + function (response: any) { + fail('should not success'); + }, + (error: any) => { + expect(Zone.current.name).toEqual(testZone.name); + expect(error.constructor.name).toEqual('TypeError'); + done(); + }, + ); }); - }); - }); - - it('should throw error when send crendential', - ifEnvSupportsWithDone(isFirefox, function(done: DoneFn) { - testZone.run(function() { - global['fetch']('http://user:password@example.com') - .then( - function(response: any) { - fail('should not success'); - }, - (error: any) => { - expect(Zone.current.name).toEqual(testZone.name); - expect(error.constructor.name).toEqual('TypeError'); - done(); - }); - }); - })); - - describe('macroTask', () => { - const logs: string[] = []; - let fetchZone: Zone; - let fetchTask: any = null; - beforeEach(() => { - logs.splice(0); - fetchZone = Zone.current.fork({ - name: 'fetch', - onScheduleTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task) => { - if (task.type !== 'eventTask') { - logs.push(`scheduleTask:${task.source}:${task.type}`); - } - if (task.source === 'fetch') { - fetchTask = task; - } - return delegate.scheduleTask(target, task); - }, - onInvokeTask: - (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task, applyThis: any, - applyArgs: any) => { + }), + ); + + describe('macroTask', () => { + const logs: string[] = []; + let fetchZone: Zone; + let fetchTask: any = null; + beforeEach(() => { + logs.splice(0); + fetchZone = Zone.current.fork({ + name: 'fetch', + onScheduleTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task) => { + if (task.type !== 'eventTask') { + logs.push(`scheduleTask:${task.source}:${task.type}`); + } + if (task.source === 'fetch') { + fetchTask = task; + } + return delegate.scheduleTask(target, task); + }, + onInvokeTask: ( + delegate: ZoneDelegate, + curr: Zone, + target: Zone, + task: Task, + applyThis: any, + applyArgs: any, + ) => { if (task.type !== 'eventTask') { logs.push(`invokeTask:${task.source}:${task.type}`); } return delegate.invokeTask(target, task, applyThis, applyArgs); }, - onCancelTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task) => { - if (task.type !== 'eventTask') { - logs.push(`cancelTask:${task.source}:${task.type}`); - } - return delegate.cancelTask(target, task); - } - }); - }); - it('fetch should be considered as macroTask', (done: DoneFn) => { - fetchZone.run(() => { - global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json') - .then(function(response: any) { - expect(Zone.current.name).toBe(fetchZone.name); - expect(logs).toEqual([ - 'scheduleTask:fetch:macroTask', 'scheduleTask:Promise.then:microTask', - 'invokeTask:Promise.then:microTask', 'invokeTask:fetch:macroTask', - 'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask' - ]); + onCancelTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task) => { + if (task.type !== 'eventTask') { + logs.push(`cancelTask:${task.source}:${task.type}`); + } + return delegate.cancelTask(target, task); + }, + }); + }); + it('fetch should be considered as macroTask', (done: DoneFn) => { + fetchZone.run(() => { + global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json').then( + function (response: any) { + expect(Zone.current.name).toBe(fetchZone.name); + expect(logs).toEqual([ + 'scheduleTask:fetch:macroTask', + 'scheduleTask:Promise.then:microTask', + 'invokeTask:Promise.then:microTask', + 'invokeTask:fetch:macroTask', + 'scheduleTask:Promise.then:microTask', + 'invokeTask:Promise.then:microTask', + ]); + done(); + }, + ); + }); + }); + + // https://github.com/angular/angular/issues/50327 + it('Response.json() should be considered as macroTask', (done) => { + fetchZone.run(() => { + global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json') + .then((response: any) => { + const promise = response.json(); + // Ensure it's a `ZoneAwarePromise`. + expect(promise).toBeInstanceOf(global.Promise); + return promise; + }) + .then(() => { + expect(logs).toEqual([ + 'scheduleTask:fetch:macroTask', + 'scheduleTask:Promise.then:microTask', + 'invokeTask:Promise.then:microTask', + 'invokeTask:fetch:macroTask', + 'scheduleTask:Promise.then:microTask', + 'invokeTask:Promise.then:microTask', + // Please refer to the issue link above. Previously, `Response` methods were not + // patched by zone.js, and their return values were considered only as + // microtasks (not macrotasks). The Angular zone stabilized prematurely, + // occurring before the resolution of the `response.json()` promise due to the + // falsy value of `zone.hasPendingMacrotasks`. We are now ensuring that + // `Response` methods are treated as macrotasks, similar to the behavior of + // `fetch`. + 'scheduleTask:Response.json:macroTask', + 'scheduleTask:Promise.then:microTask', + 'invokeTask:Promise.then:microTask', + 'invokeTask:Response.json:macroTask', + 'scheduleTask:Promise.then:microTask', + 'invokeTask:Promise.then:microTask', + 'scheduleTask:Promise.then:microTask', + 'invokeTask:Promise.then:microTask', + ]); + + done(); + }); + }); + }); + + it( + 'cancel fetch should invoke onCancelTask', + ifEnvSupportsWithDone('AbortController', (done: DoneFn) => { + if (isSafari()) { + // safari not work with AbortController done(); + return; + } + fetchZone.run(() => { + const AbortController = global['AbortController']; + const abort = new AbortController(); + const signal = abort.signal; + global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json', { + signal, + }) + .then(function (response: any) { + fail('should not get response'); + }) + .catch(function (error: any) { + expect(error.name).toEqual('AbortError'); + expect(logs).toEqual([ + 'scheduleTask:fetch:macroTask', + 'cancelTask:fetch:macroTask', + 'scheduleTask:Promise.then:microTask', + 'invokeTask:Promise.then:microTask', + 'scheduleTask:Promise.then:microTask', + 'invokeTask:Promise.then:microTask', + 'scheduleTask:Promise.then:microTask', + 'invokeTask:Promise.then:microTask', + ]); + done(); + }); + abort.abort(); }); - }); - }); - - // https://github.com/angular/angular/issues/50327 - it('Response.json() should be considered as macroTask', done => { - fetchZone.run(() => { - global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json') - .then((response: any) => { - const promise = response.json(); - // Ensure it's a `ZoneAwarePromise`. - expect(promise).toBeInstanceOf(global.Promise); - return promise; - }) - .then(() => { - expect(logs).toEqual([ - 'scheduleTask:fetch:macroTask', 'scheduleTask:Promise.then:microTask', - 'invokeTask:Promise.then:microTask', 'invokeTask:fetch:macroTask', - 'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask', - // Please refer to the issue link above. Previously, `Response` methods were not - // patched by zone.js, and their return values were considered only as - // microtasks (not macrotasks). The Angular zone stabilized prematurely, - // occurring before the resolution of the `response.json()` promise due to the - // falsy value of `zone.hasPendingMacrotasks`. We are now ensuring that - // `Response` methods are treated as macrotasks, similar to the behavior of - // `fetch`. - 'scheduleTask:Response.json:macroTask', 'scheduleTask:Promise.then:microTask', - 'invokeTask:Promise.then:microTask', 'invokeTask:Response.json:macroTask', - 'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask', - 'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask' - ]); + }), + ); + it( + 'cancel fetchTask should trigger abort', + ifEnvSupportsWithDone('AbortController', (done: DoneFn) => { + if (isSafari()) { + // safari not work with AbortController done(); + return; + } + fetchZone.run(() => { + const AbortController = global['AbortController']; + const abort = new AbortController(); + const signal = abort.signal; + global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json', { + signal, + }) + .then(function (response: any) { + fail('should not get response'); + }) + .catch(function (error: any) { + expect(error.name).toEqual('AbortError'); + expect(logs).toEqual([ + 'scheduleTask:fetch:macroTask', + 'cancelTask:fetch:macroTask', + 'scheduleTask:Promise.then:microTask', + 'invokeTask:Promise.then:microTask', + 'scheduleTask:Promise.then:microTask', + 'invokeTask:Promise.then:microTask', + 'scheduleTask:Promise.then:microTask', + 'invokeTask:Promise.then:microTask', + ]); + done(); + }); + fetchTask.zone.cancelTask(fetchTask); }); + }), + ); }); - }); - - it('cancel fetch should invoke onCancelTask', - ifEnvSupportsWithDone('AbortController', (done: DoneFn) => { - if (isSafari()) { - // safari not work with AbortController - done(); - return; - } - fetchZone.run(() => { - const AbortController = global['AbortController']; - const abort = new AbortController(); - const signal = abort.signal; - global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json', {signal}) - .then(function(response: any) { - fail('should not get response'); - }) - .catch(function(error: any) { - expect(error.name).toEqual('AbortError'); - expect(logs).toEqual([ - 'scheduleTask:fetch:macroTask', 'cancelTask:fetch:macroTask', - 'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask', - 'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask', - 'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask' - ]); - done(); - }); - abort.abort(); - }); - })); - - it('cancel fetchTask should trigger abort', - ifEnvSupportsWithDone('AbortController', (done: DoneFn) => { - if (isSafari()) { - // safari not work with AbortController - done(); - return; - } - fetchZone.run(() => { - const AbortController = global['AbortController']; - const abort = new AbortController(); - const signal = abort.signal; - global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json', {signal}) - .then(function(response: any) { - fail('should not get response'); - }) - .catch(function(error: any) { - expect(error.name).toEqual('AbortError'); - expect(logs).toEqual([ - 'scheduleTask:fetch:macroTask', 'cancelTask:fetch:macroTask', - 'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask', - 'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask', - 'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask' - ]); - done(); - }); - fetchTask.zone.cancelTask(fetchTask); - }); - })); - }); - }, emptyRun)); + }, + emptyRun, + ), +); function emptyRun() { // Jasmine will throw if there are no tests. diff --git a/packages/zone.js/test/common/microtasks.spec.ts b/packages/zone.js/test/common/microtasks.spec.ts index df6682167b524..c787f6e706fa7 100644 --- a/packages/zone.js/test/common/microtasks.spec.ts +++ b/packages/zone.js/test/common/microtasks.spec.ts @@ -6,42 +6,42 @@ * found in the LICENSE file at https://angular.io/license */ -describe('Microtasks', function() { +describe('Microtasks', function () { if (!global.Promise) return; function scheduleFn(task: Task) { Promise.resolve().then(task.invoke); } - it('should execute microtasks enqueued in the root zone', function(done) { + it('should execute microtasks enqueued in the root zone', function (done) { const log: number[] = []; Zone.current.scheduleMicroTask('test', () => log.push(1), undefined, scheduleFn); Zone.current.scheduleMicroTask('test', () => log.push(2), undefined, scheduleFn); Zone.current.scheduleMicroTask('test', () => log.push(3), undefined, scheduleFn); - setTimeout(function() { + setTimeout(function () { expect(log).toEqual([1, 2, 3]); done(); }, 10); }); - it('should correctly scheduleMacroTask microtasks vs macrotasks', function(done) { + it('should correctly scheduleMacroTask microtasks vs macrotasks', function (done) { const log = ['+root']; Zone.current.scheduleMicroTask('test', () => log.push('root.mit'), undefined, scheduleFn); - setTimeout(function() { + setTimeout(function () { log.push('+mat1'); Zone.current.scheduleMicroTask('test', () => log.push('mat1.mit'), undefined, scheduleFn); log.push('-mat1'); }, 10); - setTimeout(function() { + setTimeout(function () { log.push('mat2'); }, 30); - setTimeout(function() { + setTimeout(function () { expect(log).toEqual(['+root', '-root', 'root.mit', '+mat1', '-mat1', 'mat1.mit', 'mat2']); done(); }, 40); @@ -49,56 +49,62 @@ describe('Microtasks', function() { log.push('-root'); }); - it('should execute Promise wrapCallback in the zone where they are scheduled', function(done) { + it('should execute Promise wrapCallback in the zone where they are scheduled', function (done) { const resolvedPromise = Promise.resolve(null); const testZone = Zone.current.fork({name: ''}); - testZone.run(function() { - resolvedPromise.then(function() { + testZone.run(function () { + resolvedPromise.then(function () { expect(Zone.current.name).toBe(testZone.name); done(); }); }); }); - it('should execute Promise wrapCallback in the zone where they are scheduled even if resolved ' + - 'in different zone.', - function(done) { - let resolve: Function; - const promise = new Promise(function(rs) { - resolve = rs; - }); - - const testZone = Zone.current.fork({name: 'test'}); - - testZone.run(function() { - promise.then(function() { - expect(Zone.current).toBe(testZone); - done(); - }); - }); - - Zone.current.fork({name: 'test'}).run(function() { - resolve(null); - }); - }); - - describe('Promise', function() { - it('should go through scheduleTask', function(done) { + it( + 'should execute Promise wrapCallback in the zone where they are scheduled even if resolved ' + + 'in different zone.', + function (done) { + let resolve: Function; + const promise = new Promise(function (rs) { + resolve = rs; + }); + + const testZone = Zone.current.fork({name: 'test'}); + + testZone.run(function () { + promise.then(function () { + expect(Zone.current).toBe(testZone); + done(); + }); + }); + + Zone.current.fork({name: 'test'}).run(function () { + resolve(null); + }); + }, + ); + + describe('Promise', function () { + it('should go through scheduleTask', function (done) { let called = false; const testZone = Zone.current.fork({ name: 'test', - onScheduleTask: function(delegate: ZoneDelegate, current: Zone, target: Zone, task: Task): - Task { - called = true; - delegate.scheduleTask(target, task); - return task; - } + onScheduleTask: function ( + delegate: ZoneDelegate, + current: Zone, + target: Zone, + task: Task, + ): Task { + called = true; + delegate.scheduleTask(target, task); + return task; + }, }); - testZone.run(function() { - Promise.resolve('value').then(function() { + testZone.run(function () { + Promise.resolve('value').then(function () { expect(called).toEqual(true); done(); }); diff --git a/packages/zone.js/test/common/promise-disable-wrap-uncaught-promise-rejection.spec.ts b/packages/zone.js/test/common/promise-disable-wrap-uncaught-promise-rejection.spec.ts index c6f88f265e751..ad55d45832429 100644 --- a/packages/zone.js/test/common/promise-disable-wrap-uncaught-promise-rejection.spec.ts +++ b/packages/zone.js/test/common/promise-disable-wrap-uncaught-promise-rejection.spec.ts @@ -13,32 +13,35 @@ class TestRejection { describe('disable wrap uncaught promise rejection', () => { it('should notify Zone.onHandleError if promise is uncaught', (done) => { - let promiseError: Error|null = null; - let zone: Zone|null = null; - let task: Task|null = null; - let error: Error|null = null; + let promiseError: Error | null = null; + let zone: Zone | null = null; + let task: Task | null = null; + let error: Error | null = null; Zone.current - .fork({ - name: 'promise-error', - onHandleError: (delegate: ZoneDelegate, current: Zone, target: Zone, error: any): - boolean => { - promiseError = error; - delegate.handleError(target, error); - return false; - } - }) - .run(() => { - zone = Zone.current; - task = Zone.currentTask; - error = new Error('rejectedErrorShouldBeHandled'); - try { - // throw so that the stack trace is captured - throw error; - } catch (e) { - } - Promise.reject(error); - expect(promiseError).toBe(null); - }); + .fork({ + name: 'promise-error', + onHandleError: ( + delegate: ZoneDelegate, + current: Zone, + target: Zone, + error: any, + ): boolean => { + promiseError = error; + delegate.handleError(target, error); + return false; + }, + }) + .run(() => { + zone = Zone.current; + task = Zone.currentTask; + error = new Error('rejectedErrorShouldBeHandled'); + try { + // throw so that the stack trace is captured + throw error; + } catch (e) {} + Promise.reject(error); + expect(promiseError).toBe(null); + }); setTimeout((): any => null); setTimeout(() => { expect(promiseError).toBe(error); @@ -50,26 +53,30 @@ describe('disable wrap uncaught promise rejection', () => { }); it('should print original information when a non-Error object is used for rejection', (done) => { - let promiseError: Error|null = null; + let promiseError: Error | null = null; let rejectObj: TestRejection; Zone.current - .fork({ - name: 'promise-error', - onHandleError: (delegate: ZoneDelegate, current: Zone, target: Zone, error: any): - boolean => { - promiseError = error; - delegate.handleError(target, error); - return false; - } - }) - .run(() => { - rejectObj = new TestRejection(); - rejectObj.prop1 = 'value1'; - rejectObj.prop2 = 'value2'; - (rejectObj as any).message = 'rejectMessage'; - Promise.reject(rejectObj); - expect(promiseError).toBe(null); - }); + .fork({ + name: 'promise-error', + onHandleError: ( + delegate: ZoneDelegate, + current: Zone, + target: Zone, + error: any, + ): boolean => { + promiseError = error; + delegate.handleError(target, error); + return false; + }, + }) + .run(() => { + rejectObj = new TestRejection(); + rejectObj.prop1 = 'value1'; + rejectObj.prop2 = 'value2'; + (rejectObj as any).message = 'rejectMessage'; + Promise.reject(rejectObj); + expect(promiseError).toBe(null); + }); setTimeout((): any => null); setTimeout(() => { expect(promiseError).toEqual(rejectObj as any); @@ -78,21 +85,25 @@ describe('disable wrap uncaught promise rejection', () => { }); it('should print original information when a primitive value is used for rejection', (done) => { - let promiseError: number|null = null; + let promiseError: number | null = null; Zone.current - .fork({ - name: 'promise-error', - onHandleError: (delegate: ZoneDelegate, current: Zone, target: Zone, error: any): - boolean => { - promiseError = error; - delegate.handleError(target, error); - return false; - } - }) - .run(() => { - Promise.reject(42); - expect(promiseError).toBe(null); - }); + .fork({ + name: 'promise-error', + onHandleError: ( + delegate: ZoneDelegate, + current: Zone, + target: Zone, + error: any, + ): boolean => { + promiseError = error; + delegate.handleError(target, error); + return false; + }, + }) + .run(() => { + Promise.reject(42); + expect(promiseError).toBe(null); + }); setTimeout((): any => null); setTimeout(() => { expect(promiseError).toBe(42); diff --git a/packages/zone.js/test/common/queue-microtask.spec.ts b/packages/zone.js/test/common/queue-microtask.spec.ts index da8101a59a8fe..466ccf78382c8 100644 --- a/packages/zone.js/test/common/queue-microtask.spec.ts +++ b/packages/zone.js/test/common/queue-microtask.spec.ts @@ -9,25 +9,26 @@ import {ifEnvSupports} from '../test-util'; describe( - 'queueMicrotask', ifEnvSupports('queueMicrotask', function() { - it('callback in the queueMicrotask should be scheduled as microTask in the zone', - (done: DoneFn) => { - const logs: string[] = []; - Zone.current - .fork({ - name: 'queueMicrotask', - onScheduleTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task) => { - logs.push(task.type); - logs.push(task.source); - return delegate.scheduleTask(target, task); - } - }) - .run(() => { - queueMicrotask(() => { - expect(logs).toEqual(['microTask', 'queueMicrotask']); - expect(Zone.current.name).toEqual('queueMicrotask'); - done(); - }); - }); - }); - })); + 'queueMicrotask', + ifEnvSupports('queueMicrotask', function () { + it('callback in the queueMicrotask should be scheduled as microTask in the zone', (done: DoneFn) => { + const logs: string[] = []; + Zone.current + .fork({ + name: 'queueMicrotask', + onScheduleTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task) => { + logs.push(task.type); + logs.push(task.source); + return delegate.scheduleTask(target, task); + }, + }) + .run(() => { + queueMicrotask(() => { + expect(logs).toEqual(['microTask', 'queueMicrotask']); + expect(Zone.current.name).toEqual('queueMicrotask'); + done(); + }); + }); + }); + }), +); diff --git a/packages/zone.js/test/common/setInterval.spec.ts b/packages/zone.js/test/common/setInterval.spec.ts index cdd4187ccc994..c2452499b6004 100644 --- a/packages/zone.js/test/common/setInterval.spec.ts +++ b/packages/zone.js/test/common/setInterval.spec.ts @@ -11,76 +11,90 @@ import {isNode, zoneSymbol} from '../../lib/common/utils'; declare const global: any; const wtfMock = global.wtfMock; -describe('setInterval', function() { - it('should work with setInterval', function(done) { +describe('setInterval', function () { + it('should work with setInterval', function (done) { let cancelId: any; const testZone = Zone.current.fork((Zone as any)['wtfZoneSpec']).fork({name: 'TestZone'}); - testZone.run(() => { - let intervalCount = 0; - let timeoutRunning = false; - const intervalFn = function() { - intervalCount++; - expect(Zone.current.name).toEqual(('TestZone')); - if (timeoutRunning) { - return; - } - timeoutRunning = true; - global[zoneSymbol('setTimeout')](function() { - const intervalUnitLog = [ - '> Zone:invokeTask:setInterval("::ProxyZone::WTF::TestZone")', - '< Zone:invokeTask:setInterval' - ]; - let intervalLog: string[] = []; - for (let i = 0; i < intervalCount; i++) { - intervalLog = intervalLog.concat(intervalUnitLog); + testZone.run( + () => { + let intervalCount = 0; + let timeoutRunning = false; + const intervalFn = function () { + intervalCount++; + expect(Zone.current.name).toEqual('TestZone'); + if (timeoutRunning) { + return; } - expect(wtfMock.log[0]).toEqual('# Zone:fork("::ProxyZone::WTF", "TestZone")'); - expect(wtfMock.log[1]) - .toEqual('> Zone:invoke:unit-test("::ProxyZone::WTF::TestZone")'); - expect(wtfMock.log[2]) - .toContain( - '# Zone:schedule:macroTask:setInterval("::ProxyZone::WTF::TestZone"'); - expect(wtfMock.log[3]).toEqual('< Zone:invoke:unit-test'); - expect(wtfMock.log.splice(4)).toEqual(intervalLog); - clearInterval(cancelId); - done(); - }); - }; - expect(Zone.current.name).toEqual(('TestZone')); - cancelId = setInterval(intervalFn, 10); - if (isNode) { - expect(typeof cancelId.ref).toEqual(('function')); - expect(typeof cancelId.unref).toEqual(('function')); - } + timeoutRunning = true; + global[zoneSymbol('setTimeout')](function () { + const intervalUnitLog = [ + '> Zone:invokeTask:setInterval("::ProxyZone::WTF::TestZone")', + '< Zone:invokeTask:setInterval', + ]; + let intervalLog: string[] = []; + for (let i = 0; i < intervalCount; i++) { + intervalLog = intervalLog.concat(intervalUnitLog); + } + expect(wtfMock.log[0]).toEqual('# Zone:fork("::ProxyZone::WTF", "TestZone")'); + expect(wtfMock.log[1]).toEqual( + '> Zone:invoke:unit-test("::ProxyZone::WTF::TestZone")', + ); + expect(wtfMock.log[2]).toContain( + '# Zone:schedule:macroTask:setInterval("::ProxyZone::WTF::TestZone"', + ); + expect(wtfMock.log[3]).toEqual('< Zone:invoke:unit-test'); + expect(wtfMock.log.splice(4)).toEqual(intervalLog); + clearInterval(cancelId); + done(); + }); + }; + expect(Zone.current.name).toEqual('TestZone'); + cancelId = setInterval(intervalFn, 10); + if (isNode) { + expect(typeof cancelId.ref).toEqual('function'); + expect(typeof cancelId.unref).toEqual('function'); + } - expect(wtfMock.log[0]).toEqual('# Zone:fork("::ProxyZone::WTF", "TestZone")'); - expect(wtfMock.log[1]).toEqual('> Zone:invoke:unit-test("::ProxyZone::WTF::TestZone")'); - expect(wtfMock.log[2]) - .toContain('# Zone:schedule:macroTask:setInterval("::ProxyZone::WTF::TestZone"'); - }, null, undefined, 'unit-test'); + expect(wtfMock.log[0]).toEqual('# Zone:fork("::ProxyZone::WTF", "TestZone")'); + expect(wtfMock.log[1]).toEqual( + '> Zone:invoke:unit-test("::ProxyZone::WTF::TestZone")', + ); + expect(wtfMock.log[2]).toContain( + '# Zone:schedule:macroTask:setInterval("::ProxyZone::WTF::TestZone"', + ); + }, + null, + undefined, + 'unit-test', + ); }); it('should not cancel the task after invoke the setInterval callback', (done) => { const logs: HasTaskState[] = []; const zone = Zone.current.fork({ name: 'interval', - onHasTask: - (delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, hasTask: HasTaskState) => { - logs.push(hasTask); - return delegate.hasTask(targetZone, hasTask); - } + onHasTask: ( + delegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + hasTask: HasTaskState, + ) => { + logs.push(hasTask); + return delegate.hasTask(targetZone, hasTask); + }, }); zone.run(() => { const timerId = setInterval(() => {}, 100); (global as any)[Zone.__symbol__('setTimeout')](() => { expect(logs.length > 0).toBeTruthy(); - expect(logs).toEqual( - [{microTask: false, macroTask: true, eventTask: false, change: 'macroTask'}]); + expect(logs).toEqual([ + {microTask: false, macroTask: true, eventTask: false, change: 'macroTask'}, + ]); clearInterval(timerId); expect(logs).toEqual([ {microTask: false, macroTask: true, eventTask: false, change: 'macroTask'}, - {microTask: false, macroTask: false, eventTask: false, change: 'macroTask'} + {microTask: false, macroTask: false, eventTask: false, change: 'macroTask'}, ]); done(); }, 300); diff --git a/packages/zone.js/test/common/setTimeout.spec.ts b/packages/zone.js/test/common/setTimeout.spec.ts index 7d4f31eb6a916..e40b0cace817d 100644 --- a/packages/zone.js/test/common/setTimeout.spec.ts +++ b/packages/zone.js/test/common/setTimeout.spec.ts @@ -12,79 +12,90 @@ import {isNode, zoneSymbol} from '../../lib/common/utils'; declare const global: any; const wtfMock = global.wtfMock; -describe('setTimeout', function() { - it('should intercept setTimeout', function(done) { +describe('setTimeout', function () { + it('should intercept setTimeout', function (done) { let cancelId: any; const testZone = Zone.current.fork((Zone as any)['wtfZoneSpec']).fork({name: 'TestZone'}); - testZone.run(() => { - const timeoutFn = function() { - expect(Zone.current.name).toEqual(('TestZone')); - global[zoneSymbol('setTimeout')](function() { - expect(wtfMock.log[0]).toEqual('# Zone:fork("::ProxyZone::WTF", "TestZone")'); - expect(wtfMock.log[1]) - .toEqual('> Zone:invoke:unit-test("::ProxyZone::WTF::TestZone")'); - expect(wtfMock.log[2]) - .toContain('# Zone:schedule:macroTask:setTimeout("::ProxyZone::WTF::TestZone"'); - expect(wtfMock.log[3]).toEqual('< Zone:invoke:unit-test'); - expect(wtfMock.log[4]) - .toEqual('> Zone:invokeTask:setTimeout("::ProxyZone::WTF::TestZone")'); - expect(wtfMock.log[5]).toEqual('< Zone:invokeTask:setTimeout'); - done(); - }); - }; - expect(Zone.current.name).toEqual(('TestZone')); - cancelId = setTimeout(timeoutFn, 3); - if (isNode) { - expect(typeof cancelId.ref).toEqual(('function')); - expect(typeof cancelId.unref).toEqual(('function')); - } - expect(wtfMock.log[0]).toEqual('# Zone:fork("::ProxyZone::WTF", "TestZone")'); - expect(wtfMock.log[1]).toEqual('> Zone:invoke:unit-test("::ProxyZone::WTF::TestZone")'); - expect(wtfMock.log[2]) - .toContain('# Zone:schedule:macroTask:setTimeout("::ProxyZone::WTF::TestZone"'); - }, null, undefined, 'unit-test'); + testZone.run( + () => { + const timeoutFn = function () { + expect(Zone.current.name).toEqual('TestZone'); + global[zoneSymbol('setTimeout')](function () { + expect(wtfMock.log[0]).toEqual('# Zone:fork("::ProxyZone::WTF", "TestZone")'); + expect(wtfMock.log[1]).toEqual( + '> Zone:invoke:unit-test("::ProxyZone::WTF::TestZone")', + ); + expect(wtfMock.log[2]).toContain( + '# Zone:schedule:macroTask:setTimeout("::ProxyZone::WTF::TestZone"', + ); + expect(wtfMock.log[3]).toEqual('< Zone:invoke:unit-test'); + expect(wtfMock.log[4]).toEqual( + '> Zone:invokeTask:setTimeout("::ProxyZone::WTF::TestZone")', + ); + expect(wtfMock.log[5]).toEqual('< Zone:invokeTask:setTimeout'); + done(); + }); + }; + expect(Zone.current.name).toEqual('TestZone'); + cancelId = setTimeout(timeoutFn, 3); + if (isNode) { + expect(typeof cancelId.ref).toEqual('function'); + expect(typeof cancelId.unref).toEqual('function'); + } + expect(wtfMock.log[0]).toEqual('# Zone:fork("::ProxyZone::WTF", "TestZone")'); + expect(wtfMock.log[1]).toEqual( + '> Zone:invoke:unit-test("::ProxyZone::WTF::TestZone")', + ); + expect(wtfMock.log[2]).toContain( + '# Zone:schedule:macroTask:setTimeout("::ProxyZone::WTF::TestZone"', + ); + }, + null, + undefined, + 'unit-test', + ); }); - it('should allow canceling of fns registered with setTimeout', function(done) { + it('should allow canceling of fns registered with setTimeout', function (done) { const testZone = Zone.current.fork((Zone as any)['wtfZoneSpec']).fork({name: 'TestZone'}); testZone.run(() => { const spy = jasmine.createSpy('spy'); const cancelId = setTimeout(spy, 0); clearTimeout(cancelId); - setTimeout(function() { + setTimeout(function () { expect(spy).not.toHaveBeenCalled(); done(); }, 1); }); }); - it('should call native clearTimeout with the correct context', function() { + it('should call native clearTimeout with the correct context', function () { // since clearTimeout has been patched already, we can not test `clearTimeout` directly // we will fake another API patch to test let context: any = null; const fakeGlobal = { - setTimeout: function() { + setTimeout: function () { return 1; }, - clearTimeout: function(id: number) { + clearTimeout: function (id: number) { context = this; - } + }, }; - patchTimer(fakeGlobal, 'set', 'clear', 'Timeout') + patchTimer(fakeGlobal, 'set', 'clear', 'Timeout'); const cancelId = fakeGlobal.setTimeout(); const m = fakeGlobal.clearTimeout; m.call({}, cancelId); expect(context).toBe(fakeGlobal); }); - it('should allow cancelation of fns registered with setTimeout after invocation', function(done) { + it('should allow cancelation of fns registered with setTimeout after invocation', function (done) { const testZone = Zone.current.fork((Zone as any)['wtfZoneSpec']).fork({name: 'TestZone'}); testZone.run(() => { const spy = jasmine.createSpy('spy'); const cancelId = setTimeout(spy, 0); - setTimeout(function() { + setTimeout(function () { expect(spy).toHaveBeenCalled(); - setTimeout(function() { + setTimeout(function () { clearTimeout(cancelId); done(); }); @@ -92,7 +103,7 @@ describe('setTimeout', function() { }); }); - it('should allow cancelation of fns while the task is being executed', function(done) { + it('should allow cancelation of fns while the task is being executed', function (done) { const spy = jasmine.createSpy('spy'); const cancelId = setTimeout(() => { clearTimeout(cancelId); @@ -100,25 +111,24 @@ describe('setTimeout', function() { }, 0); }); - it('should allow cancelation of fns registered with setTimeout during invocation', - function(done) { - const testZone = Zone.current.fork((Zone as any)['wtfZoneSpec']).fork({name: 'TestZone'}); - testZone.run(() => { - const cancelId = setTimeout(function() { - clearTimeout(cancelId); - done(); - }, 0); - }); - }); + it('should allow cancelation of fns registered with setTimeout during invocation', function (done) { + const testZone = Zone.current.fork((Zone as any)['wtfZoneSpec']).fork({name: 'TestZone'}); + testZone.run(() => { + const cancelId = setTimeout(function () { + clearTimeout(cancelId); + done(); + }, 0); + }); + }); - it('should return the original timeout Id', function() { + it('should return the original timeout Id', function () { // Node returns complex object from setTimeout, ignore this test. if (isNode) return; const cancelId = setTimeout(() => {}, 0); expect(typeof cancelId).toEqual('number'); }); - it('should allow cancelation by numeric timeout Id', function(done) { + it('should allow cancelation by numeric timeout Id', function (done) { // Node returns complex object from setTimeout, ignore this test. if (isNode) { done(); @@ -130,14 +140,14 @@ describe('setTimeout', function() { const spy = jasmine.createSpy('spy'); const cancelId = setTimeout(spy, 0); clearTimeout(cancelId); - setTimeout(function() { + setTimeout(function () { expect(spy).not.toHaveBeenCalled(); done(); }, 1); }); }); - it('should pass invalid values through', function() { + it('should pass invalid values through', function () { clearTimeout(null as any); clearTimeout({}); }); diff --git a/packages/zone.js/test/common/task.spec.ts b/packages/zone.js/test/common/task.spec.ts index afd06239d1059..eadce03f39f48 100644 --- a/packages/zone.js/test/common/task.spec.ts +++ b/packages/zone.js/test/common/task.spec.ts @@ -6,26 +6,29 @@ * found in the LICENSE file at https://angular.io/license */ -const noop = function() {}; -let log: {zone: string, taskZone: undefined|string, toState: TaskState, fromState: TaskState}[] = - []; +const noop = function () {}; +let log: {zone: string; taskZone: undefined | string; toState: TaskState; fromState: TaskState}[] = + []; const detectTask = Zone.current.scheduleMacroTask('detectTask', noop, undefined, noop, noop); const originalTransitionTo = detectTask.constructor.prototype._transitionTo; // patch _transitionTo of ZoneTask to add log for test -const logTransitionTo: Function = function( - this: Task&{_state: TaskState}, toState: TaskState, fromState1: TaskState, - fromState2?: TaskState) { +const logTransitionTo: Function = function ( + this: Task & {_state: TaskState}, + toState: TaskState, + fromState1: TaskState, + fromState2?: TaskState, +) { log.push({ zone: Zone.current.name, taskZone: this.zone && this.zone.name, toState: toState, - fromState: this._state + fromState: this._state, }); originalTransitionTo.apply(this, arguments); }; function testFnWithLoggedTransitionTo(testFn: Function) { - return function(this: unknown) { + return function (this: unknown) { detectTask.constructor.prototype._transitionTo = logTransitionTo; testFn.apply(this, arguments); detectTask.constructor.prototype._transitionTo = originalTransitionTo; @@ -38,222 +41,265 @@ describe('task lifecycle', () => { log = []; }); - it('task should transit from notScheduled to scheduling then to scheduled state when scheduleTask', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testEventTaskZone'}).run(() => { - Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'} - ]); - })); + it( + 'task should transit from notScheduled to scheduling then to scheduled state when scheduleTask', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testEventTaskZone'}).run(() => { + Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + ]); + }), + ); - it('task should transit from scheduling to unknown when zoneSpec onScheduleTask callback throw error', - testFnWithLoggedTransitionTo(() => { - Zone.current - .fork({ - name: 'testEventTaskZone', - onScheduleTask: (delegate, currZone, targetZone, task) => { - throw Error('error in onScheduleTask'); - } - }) - .run(() => { - try { - Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'unknown', fromState: 'scheduling'} - ]); - })); + it( + 'task should transit from scheduling to unknown when zoneSpec onScheduleTask callback throw error', + testFnWithLoggedTransitionTo(() => { + Zone.current + .fork({ + name: 'testEventTaskZone', + onScheduleTask: (delegate, currZone, targetZone, task) => { + throw Error('error in onScheduleTask'); + }, + }) + .run(() => { + try { + Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'unknown', fromState: 'scheduling'}, + ]); + }), + ); - it('task should transit from scheduled to running when task is invoked then from running to scheduled after invoke', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testEventTaskZone'}).run(() => { - const task = - Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); - task.invoke(); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'running', fromState: 'scheduled'}, - {toState: 'scheduled', fromState: 'running'} - ]); - })); + it( + 'task should transit from scheduled to running when task is invoked then from running to scheduled after invoke', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testEventTaskZone'}).run(() => { + const task = Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); + task.invoke(); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'running', fromState: 'scheduled'}, + {toState: 'scheduled', fromState: 'running'}, + ]); + }), + ); - it('task should transit from scheduled to canceling then from canceling to notScheduled when task is canceled before running', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testEventTaskZone'}).run(() => { - const task = - Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); - Zone.current.cancelTask(task); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'canceling', fromState: 'scheduled'}, - {toState: 'notScheduled', fromState: 'canceling'} - ]); - })); + it( + 'task should transit from scheduled to canceling then from canceling to notScheduled when task is canceled before running', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testEventTaskZone'}).run(() => { + const task = Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); + Zone.current.cancelTask(task); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'canceling', fromState: 'scheduled'}, + {toState: 'notScheduled', fromState: 'canceling'}, + ]); + }), + ); - it('task should transit from running to canceling then from canceling to notScheduled when task is canceled in running state', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testEventTaskZone'}).run(() => { - const task = Zone.current.scheduleEventTask('testEventTask', () => { - Zone.current.cancelTask(task); - }, undefined, noop, noop); - task.invoke(); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'running', fromState: 'scheduled'}, - {toState: 'canceling', fromState: 'running'}, - {toState: 'notScheduled', fromState: 'canceling'} - ]); - })); + it( + 'task should transit from running to canceling then from canceling to notScheduled when task is canceled in running state', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testEventTaskZone'}).run(() => { + const task = Zone.current.scheduleEventTask( + 'testEventTask', + () => { + Zone.current.cancelTask(task); + }, + undefined, + noop, + noop, + ); + task.invoke(); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'running', fromState: 'scheduled'}, + {toState: 'canceling', fromState: 'running'}, + {toState: 'notScheduled', fromState: 'canceling'}, + ]); + }), + ); - it('task should transit from running to scheduled when task.callback throw error', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testEventTaskZone'}).run(() => { - const task = Zone.current.scheduleEventTask('testEventTask', () => { - throw Error('invoke error'); - }, undefined, noop, noop); - try { - task.invoke(); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'running', fromState: 'scheduled'}, - {toState: 'scheduled', fromState: 'running'} - ]); - })); + it( + 'task should transit from running to scheduled when task.callback throw error', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testEventTaskZone'}).run(() => { + const task = Zone.current.scheduleEventTask( + 'testEventTask', + () => { + throw Error('invoke error'); + }, + undefined, + noop, + noop, + ); + try { + task.invoke(); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'running', fromState: 'scheduled'}, + {toState: 'scheduled', fromState: 'running'}, + ]); + }), + ); - it('task should transit from canceling to unknown when zoneSpec.onCancelTask throw error before task running', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testEventTaskZone'}).run(() => { - const task = - Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, () => { - throw Error('cancel task'); - }); - try { - Zone.current.cancelTask(task); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'canceling', fromState: 'scheduled'}, - {toState: 'unknown', fromState: 'canceling'} - ]); - })); + it( + 'task should transit from canceling to unknown when zoneSpec.onCancelTask throw error before task running', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testEventTaskZone'}).run(() => { + const task = Zone.current.scheduleEventTask( + 'testEventTask', + noop, + undefined, + noop, + () => { + throw Error('cancel task'); + }, + ); + try { + Zone.current.cancelTask(task); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'canceling', fromState: 'scheduled'}, + {toState: 'unknown', fromState: 'canceling'}, + ]); + }), + ); - it('task should transit from canceling to unknown when zoneSpec.onCancelTask throw error in running state', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testEventTaskZone'}).run(() => { - const task = - Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, () => { - throw Error('cancel task'); - }); - try { - Zone.current.cancelTask(task); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'canceling', fromState: 'scheduled'}, - {toState: 'unknown', fromState: 'canceling'} - ]); - })); + it( + 'task should transit from canceling to unknown when zoneSpec.onCancelTask throw error in running state', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testEventTaskZone'}).run(() => { + const task = Zone.current.scheduleEventTask( + 'testEventTask', + noop, + undefined, + noop, + () => { + throw Error('cancel task'); + }, + ); + try { + Zone.current.cancelTask(task); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'canceling', fromState: 'scheduled'}, + {toState: 'unknown', fromState: 'canceling'}, + ]); + }), + ); - it('task should transit from notScheduled to scheduled if zoneSpec.onHasTask throw error when scheduleTask', - testFnWithLoggedTransitionTo(() => { - Zone.current - .fork({ - name: 'testEventTaskZone', - onHasTask: (delegate, currZone, targetZone, hasTaskState) => { - throw Error('hasTask Error'); - } - }) - .run(() => { - try { - Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'} - ]); - })); + it( + 'task should transit from notScheduled to scheduled if zoneSpec.onHasTask throw error when scheduleTask', + testFnWithLoggedTransitionTo(() => { + Zone.current + .fork({ + name: 'testEventTaskZone', + onHasTask: (delegate, currZone, targetZone, hasTaskState) => { + throw Error('hasTask Error'); + }, + }) + .run(() => { + try { + Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + ]); + }), + ); - it('task should transit to notScheduled state if zoneSpec.onHasTask throw error when task is canceled', - testFnWithLoggedTransitionTo(() => { - let task: Task; - Zone.current - .fork({ - name: 'testEventTaskZone', - onHasTask: (delegate, currZone, targetZone, hasTaskState) => { - if (task && task.state === 'canceling') { - throw Error('hasTask Error'); - } - } - }) - .run(() => { - try { - task = - Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); - Zone.current.cancelTask(task); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'canceling', fromState: 'scheduled'}, - {toState: 'notScheduled', fromState: 'canceling'} - ]); - })); + it( + 'task should transit to notScheduled state if zoneSpec.onHasTask throw error when task is canceled', + testFnWithLoggedTransitionTo(() => { + let task: Task; + Zone.current + .fork({ + name: 'testEventTaskZone', + onHasTask: (delegate, currZone, targetZone, hasTaskState) => { + if (task && task.state === 'canceling') { + throw Error('hasTask Error'); + } + }, + }) + .run(() => { + try { + task = Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); + Zone.current.cancelTask(task); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'canceling', fromState: 'scheduled'}, + {toState: 'notScheduled', fromState: 'canceling'}, + ]); + }), + ); }); describe('non periodical macroTask lifecycle', () => { @@ -261,484 +307,607 @@ describe('task lifecycle', () => { log = []; }); - it('task should transit from notScheduled to scheduling then to scheduled state when scheduleTask', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testMacroTaskZone'}).run(() => { - Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, noop); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'} - ]); - })); + it( + 'task should transit from notScheduled to scheduling then to scheduled state when scheduleTask', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testMacroTaskZone'}).run(() => { + Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, noop); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + ]); + }), + ); - it('task should transit from scheduling to unknown when zoneSpec onScheduleTask callback throw error', - testFnWithLoggedTransitionTo(() => { - Zone.current - .fork({ - name: 'testMacroTaskZone', - onScheduleTask: (delegate, currZone, targetZone, task) => { - throw Error('error in onScheduleTask'); - } - }) - .run(() => { - try { - Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, noop); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'unknown', fromState: 'scheduling'} - ]); - })); + it( + 'task should transit from scheduling to unknown when zoneSpec onScheduleTask callback throw error', + testFnWithLoggedTransitionTo(() => { + Zone.current + .fork({ + name: 'testMacroTaskZone', + onScheduleTask: (delegate, currZone, targetZone, task) => { + throw Error('error in onScheduleTask'); + }, + }) + .run(() => { + try { + Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, noop); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'unknown', fromState: 'scheduling'}, + ]); + }), + ); - it('task should transit from scheduled to running when task is invoked then from running to noScheduled after invoke', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testMacroTaskZone'}).run(() => { - const task = - Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, noop); - task.invoke(); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'running', fromState: 'scheduled'}, - {toState: 'notScheduled', fromState: 'running'} - ]); - })); + it( + 'task should transit from scheduled to running when task is invoked then from running to noScheduled after invoke', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testMacroTaskZone'}).run(() => { + const task = Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, noop); + task.invoke(); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'running', fromState: 'scheduled'}, + {toState: 'notScheduled', fromState: 'running'}, + ]); + }), + ); - it('task should transit from scheduled to canceling then from canceling to notScheduled when task is canceled before running', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testMacroTaskZone'}).run(() => { - const task = - Zone.current.scheduleMacroTask('testMacrotask', noop, undefined, noop, noop); - Zone.current.cancelTask(task); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'canceling', fromState: 'scheduled'}, - {toState: 'notScheduled', fromState: 'canceling'} - ]); - })); + it( + 'task should transit from scheduled to canceling then from canceling to notScheduled when task is canceled before running', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testMacroTaskZone'}).run(() => { + const task = Zone.current.scheduleMacroTask('testMacrotask', noop, undefined, noop, noop); + Zone.current.cancelTask(task); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'canceling', fromState: 'scheduled'}, + {toState: 'notScheduled', fromState: 'canceling'}, + ]); + }), + ); - it('task should transit from running to canceling then from canceling to notScheduled when task is canceled in running state', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testMacroTaskZone'}).run(() => { - const task = Zone.current.scheduleMacroTask('testMacroTask', () => { - Zone.current.cancelTask(task); - }, undefined, noop, noop); - task.invoke(); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'running', fromState: 'scheduled'}, - {toState: 'canceling', fromState: 'running'}, - {toState: 'notScheduled', fromState: 'canceling'} - ]); - })); + it( + 'task should transit from running to canceling then from canceling to notScheduled when task is canceled in running state', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testMacroTaskZone'}).run(() => { + const task = Zone.current.scheduleMacroTask( + 'testMacroTask', + () => { + Zone.current.cancelTask(task); + }, + undefined, + noop, + noop, + ); + task.invoke(); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'running', fromState: 'scheduled'}, + {toState: 'canceling', fromState: 'running'}, + {toState: 'notScheduled', fromState: 'canceling'}, + ]); + }), + ); - it('task should transit from running to noScheduled when task.callback throw error', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testMacroTaskZone'}).run(() => { - const task = Zone.current.scheduleMacroTask('testMacroTask', () => { - throw Error('invoke error'); - }, undefined, noop, noop); - try { - task.invoke(); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'running', fromState: 'scheduled'}, - {toState: 'notScheduled', fromState: 'running'} - ]); - })); + it( + 'task should transit from running to noScheduled when task.callback throw error', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testMacroTaskZone'}).run(() => { + const task = Zone.current.scheduleMacroTask( + 'testMacroTask', + () => { + throw Error('invoke error'); + }, + undefined, + noop, + noop, + ); + try { + task.invoke(); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'running', fromState: 'scheduled'}, + {toState: 'notScheduled', fromState: 'running'}, + ]); + }), + ); - it('task should transit from canceling to unknown when zoneSpec.onCancelTask throw error before task running', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testMacroTaskZone'}).run(() => { - const task = - Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, () => { - throw Error('cancel task'); - }); - try { - Zone.current.cancelTask(task); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'canceling', fromState: 'scheduled'}, - {toState: 'unknown', fromState: 'canceling'} - ]); - })); + it( + 'task should transit from canceling to unknown when zoneSpec.onCancelTask throw error before task running', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testMacroTaskZone'}).run(() => { + const task = Zone.current.scheduleMacroTask( + 'testMacroTask', + noop, + undefined, + noop, + () => { + throw Error('cancel task'); + }, + ); + try { + Zone.current.cancelTask(task); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'canceling', fromState: 'scheduled'}, + {toState: 'unknown', fromState: 'canceling'}, + ]); + }), + ); - it('task should transit from canceling to unknown when zoneSpec.onCancelTask throw error in running state', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testMacroTaskZone'}).run(() => { - const task = - Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, () => { - throw Error('cancel task'); - }); - try { - Zone.current.cancelTask(task); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'canceling', fromState: 'scheduled'}, - {toState: 'unknown', fromState: 'canceling'} - ]); - })); + it( + 'task should transit from canceling to unknown when zoneSpec.onCancelTask throw error in running state', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testMacroTaskZone'}).run(() => { + const task = Zone.current.scheduleMacroTask( + 'testMacroTask', + noop, + undefined, + noop, + () => { + throw Error('cancel task'); + }, + ); + try { + Zone.current.cancelTask(task); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'canceling', fromState: 'scheduled'}, + {toState: 'unknown', fromState: 'canceling'}, + ]); + }), + ); - it('task should transit from notScheduled to scheduling then to scheduled if zoneSpec.onHasTask throw error when scheduleTask', - testFnWithLoggedTransitionTo(() => { - Zone.current - .fork({ - name: 'testMacroTaskZone', - onHasTask: (delegate, currZone, targetZone, hasTaskState) => { - throw Error('hasTask Error'); - } - }) - .run(() => { - try { - Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, noop); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'} - ]); - })); + it( + 'task should transit from notScheduled to scheduling then to scheduled if zoneSpec.onHasTask throw error when scheduleTask', + testFnWithLoggedTransitionTo(() => { + Zone.current + .fork({ + name: 'testMacroTaskZone', + onHasTask: (delegate, currZone, targetZone, hasTaskState) => { + throw Error('hasTask Error'); + }, + }) + .run(() => { + try { + Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, noop); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + ]); + }), + ); - it('task should transit to notScheduled state if zoneSpec.onHasTask throw error after task.callback being invoked', - testFnWithLoggedTransitionTo(() => { - let task: Task; - Zone.current - .fork({ - name: 'testMacroTaskZone', - onHasTask: (delegate, currZone, targetZone, hasTaskState) => { - if (task && task.state === 'running') { - throw Error('hasTask Error'); - } - } - }) - .run(() => { - try { - task = - Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, noop); - task.invoke(); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'running', fromState: 'scheduled'}, - {toState: 'notScheduled', fromState: 'running'} - ]); - })); + it( + 'task should transit to notScheduled state if zoneSpec.onHasTask throw error after task.callback being invoked', + testFnWithLoggedTransitionTo(() => { + let task: Task; + Zone.current + .fork({ + name: 'testMacroTaskZone', + onHasTask: (delegate, currZone, targetZone, hasTaskState) => { + if (task && task.state === 'running') { + throw Error('hasTask Error'); + } + }, + }) + .run(() => { + try { + task = Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, noop); + task.invoke(); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'running', fromState: 'scheduled'}, + {toState: 'notScheduled', fromState: 'running'}, + ]); + }), + ); - it('task should transit to notScheduled state if zoneSpec.onHasTask throw error when task is canceled before running', - testFnWithLoggedTransitionTo(() => { - let task: Task; - Zone.current - .fork({ - name: 'testMacroTaskZone', - onHasTask: (delegate, currZone, targetZone, hasTaskState) => { - if (task && task.state === 'canceling') { - throw Error('hasTask Error'); - } - } - }) - .run(() => { - try { - task = - Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, noop); - Zone.current.cancelTask(task); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'canceling', fromState: 'scheduled'}, - {toState: 'notScheduled', fromState: 'canceling'} - ]); - })); + it( + 'task should transit to notScheduled state if zoneSpec.onHasTask throw error when task is canceled before running', + testFnWithLoggedTransitionTo(() => { + let task: Task; + Zone.current + .fork({ + name: 'testMacroTaskZone', + onHasTask: (delegate, currZone, targetZone, hasTaskState) => { + if (task && task.state === 'canceling') { + throw Error('hasTask Error'); + } + }, + }) + .run(() => { + try { + task = Zone.current.scheduleMacroTask('testMacroTask', noop, undefined, noop, noop); + Zone.current.cancelTask(task); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'canceling', fromState: 'scheduled'}, + {toState: 'notScheduled', fromState: 'canceling'}, + ]); + }), + ); }); describe('periodical macroTask lifecycle', () => { - let task: Task|null; + let task: Task | null; beforeEach(() => { log = []; task = null; }); afterEach(() => { - task && task.state !== 'notScheduled' && task.state !== 'canceling' && - task.state !== 'unknown' && task.zone.cancelTask(task); + task && + task.state !== 'notScheduled' && + task.state !== 'canceling' && + task.state !== 'unknown' && + task.zone.cancelTask(task); }); - it('task should transit from notScheduled to scheduling then to scheduled state when scheduleTask', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => { - task = Zone.current.scheduleMacroTask( - 'testPeriodicalTask', noop, {isPeriodic: true}, noop, noop); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'} - ]); - })); + it( + 'task should transit from notScheduled to scheduling then to scheduled state when scheduleTask', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => { + task = Zone.current.scheduleMacroTask( + 'testPeriodicalTask', + noop, + {isPeriodic: true}, + noop, + noop, + ); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + ]); + }), + ); - it('task should transit from scheduling to unknown when zoneSpec onScheduleTask callback throw error', - testFnWithLoggedTransitionTo(() => { - Zone.current - .fork({ - name: 'testPeriodicalTaskZone', - onScheduleTask: (delegate, currZone, targetZone, task) => { - throw Error('error in onScheduleTask'); - } - }) - .run(() => { - try { - task = Zone.current.scheduleMacroTask( - 'testPeriodicalTask', noop, {isPeriodic: true}, noop, noop); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'unknown', fromState: 'scheduling'} - ]); - })); + it( + 'task should transit from scheduling to unknown when zoneSpec onScheduleTask callback throw error', + testFnWithLoggedTransitionTo(() => { + Zone.current + .fork({ + name: 'testPeriodicalTaskZone', + onScheduleTask: (delegate, currZone, targetZone, task) => { + throw Error('error in onScheduleTask'); + }, + }) + .run(() => { + try { + task = Zone.current.scheduleMacroTask( + 'testPeriodicalTask', + noop, + {isPeriodic: true}, + noop, + noop, + ); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'unknown', fromState: 'scheduling'}, + ]); + }), + ); - it('task should transit from scheduled to running when task is invoked then from running to scheduled after invoke', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => { - task = Zone.current.scheduleMacroTask( - 'testPeriodicalTask', noop, {isPeriodic: true}, noop, noop); - task.invoke(); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'running', fromState: 'scheduled'}, - {toState: 'scheduled', fromState: 'running'} - ]); - })); + it( + 'task should transit from scheduled to running when task is invoked then from running to scheduled after invoke', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => { + task = Zone.current.scheduleMacroTask( + 'testPeriodicalTask', + noop, + {isPeriodic: true}, + noop, + noop, + ); + task.invoke(); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'running', fromState: 'scheduled'}, + {toState: 'scheduled', fromState: 'running'}, + ]); + }), + ); - it('task should transit from scheduled to canceling then from canceling to notScheduled when task is canceled before running', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => { - task = Zone.current.scheduleMacroTask( - 'testPeriodicalTask', noop, {isPeriodic: true}, noop, noop); - Zone.current.cancelTask(task); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'canceling', fromState: 'scheduled'}, - {toState: 'notScheduled', fromState: 'canceling'} - ]); - })); + it( + 'task should transit from scheduled to canceling then from canceling to notScheduled when task is canceled before running', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => { + task = Zone.current.scheduleMacroTask( + 'testPeriodicalTask', + noop, + {isPeriodic: true}, + noop, + noop, + ); + Zone.current.cancelTask(task); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'canceling', fromState: 'scheduled'}, + {toState: 'notScheduled', fromState: 'canceling'}, + ]); + }), + ); - it('task should transit from running to canceling then from canceling to notScheduled when task is canceled in running state', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => { - task = Zone.current.scheduleMacroTask('testPeriodicalTask', () => { - Zone.current.cancelTask(task!); - }, {isPeriodic: true}, noop, noop); - task.invoke(); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'running', fromState: 'scheduled'}, - {toState: 'canceling', fromState: 'running'}, - {toState: 'notScheduled', fromState: 'canceling'} - ]); - })); + it( + 'task should transit from running to canceling then from canceling to notScheduled when task is canceled in running state', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => { + task = Zone.current.scheduleMacroTask( + 'testPeriodicalTask', + () => { + Zone.current.cancelTask(task!); + }, + {isPeriodic: true}, + noop, + noop, + ); + task.invoke(); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'running', fromState: 'scheduled'}, + {toState: 'canceling', fromState: 'running'}, + {toState: 'notScheduled', fromState: 'canceling'}, + ]); + }), + ); - it('task should transit from running to scheduled when task.callback throw error', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => { - task = Zone.current.scheduleMacroTask('testPeriodicalTask', () => { - throw Error('invoke error'); - }, {isPeriodic: true}, noop, noop); - try { - task.invoke(); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'running', fromState: 'scheduled'}, - {toState: 'scheduled', fromState: 'running'} - ]); - })); + it( + 'task should transit from running to scheduled when task.callback throw error', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => { + task = Zone.current.scheduleMacroTask( + 'testPeriodicalTask', + () => { + throw Error('invoke error'); + }, + {isPeriodic: true}, + noop, + noop, + ); + try { + task.invoke(); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'running', fromState: 'scheduled'}, + {toState: 'scheduled', fromState: 'running'}, + ]); + }), + ); - it('task should transit from canceling to unknown when zoneSpec.onCancelTask throw error before task running', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => { - task = Zone.current.scheduleMacroTask( - 'testPeriodicalTask', noop, {isPeriodic: true}, noop, () => { - throw Error('cancel task'); - }); - try { - Zone.current.cancelTask(task); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'canceling', fromState: 'scheduled'}, - {toState: 'unknown', fromState: 'canceling'} - ]); - })); + it( + 'task should transit from canceling to unknown when zoneSpec.onCancelTask throw error before task running', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => { + task = Zone.current.scheduleMacroTask( + 'testPeriodicalTask', + noop, + {isPeriodic: true}, + noop, + () => { + throw Error('cancel task'); + }, + ); + try { + Zone.current.cancelTask(task); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'canceling', fromState: 'scheduled'}, + {toState: 'unknown', fromState: 'canceling'}, + ]); + }), + ); - it('task should transit from canceling to unknown when zoneSpec.onCancelTask throw error in running state', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => { - task = Zone.current.scheduleMacroTask( - 'testPeriodicalTask', noop, {isPeriodic: true}, noop, () => { - throw Error('cancel task'); - }); - try { - Zone.current.cancelTask(task); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'canceling', fromState: 'scheduled'}, - {toState: 'unknown', fromState: 'canceling'} - ]); - })); + it( + 'task should transit from canceling to unknown when zoneSpec.onCancelTask throw error in running state', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testPeriodicalTaskZone'}).run(() => { + task = Zone.current.scheduleMacroTask( + 'testPeriodicalTask', + noop, + {isPeriodic: true}, + noop, + () => { + throw Error('cancel task'); + }, + ); + try { + Zone.current.cancelTask(task); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'canceling', fromState: 'scheduled'}, + {toState: 'unknown', fromState: 'canceling'}, + ]); + }), + ); - it('task should transit from notScheduled to scheduled if zoneSpec.onHasTask throw error when scheduleTask', - testFnWithLoggedTransitionTo(() => { - Zone.current - .fork({ - name: 'testPeriodicalTaskZone', - onHasTask: (delegate, currZone, targetZone, hasTaskState) => { - throw Error('hasTask Error'); - } - }) - .run(() => { - try { - task = Zone.current.scheduleMacroTask( - 'testPeriodicalTask', noop, {isPeriodic: true}, noop, noop); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'} - ]); - })); + it( + 'task should transit from notScheduled to scheduled if zoneSpec.onHasTask throw error when scheduleTask', + testFnWithLoggedTransitionTo(() => { + Zone.current + .fork({ + name: 'testPeriodicalTaskZone', + onHasTask: (delegate, currZone, targetZone, hasTaskState) => { + throw Error('hasTask Error'); + }, + }) + .run(() => { + try { + task = Zone.current.scheduleMacroTask( + 'testPeriodicalTask', + noop, + {isPeriodic: true}, + noop, + noop, + ); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + ]); + }), + ); - it('task should transit to notScheduled state if zoneSpec.onHasTask throw error when task is canceled', - testFnWithLoggedTransitionTo(() => { - Zone.current - .fork({ - name: 'testPeriodicalTaskZone', - onHasTask: (delegate, currZone, targetZone, hasTaskState) => { - if (task && task.state === 'canceling') { - throw Error('hasTask Error'); - } - } - }) - .run(() => { - try { - task = Zone.current.scheduleMacroTask( - 'testPeriodicalTask', noop, {isPeriodic: true}, noop, noop); - Zone.current.cancelTask(task); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'canceling', fromState: 'scheduled'}, - {toState: 'notScheduled', fromState: 'canceling'} - ]); - })); + it( + 'task should transit to notScheduled state if zoneSpec.onHasTask throw error when task is canceled', + testFnWithLoggedTransitionTo(() => { + Zone.current + .fork({ + name: 'testPeriodicalTaskZone', + onHasTask: (delegate, currZone, targetZone, hasTaskState) => { + if (task && task.state === 'canceling') { + throw Error('hasTask Error'); + } + }, + }) + .run(() => { + try { + task = Zone.current.scheduleMacroTask( + 'testPeriodicalTask', + noop, + {isPeriodic: true}, + noop, + noop, + ); + Zone.current.cancelTask(task); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'canceling', fromState: 'scheduled'}, + {toState: 'notScheduled', fromState: 'canceling'}, + ]); + }), + ); }); describe('microTask lifecycle', () => { @@ -746,345 +915,428 @@ describe('task lifecycle', () => { log = []; }); - it('task should transit from notScheduled to scheduling then to scheduled state when scheduleTask', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testMicroTaskZone'}).run(() => { - Zone.current.scheduleMicroTask('testMicroTask', noop, undefined, noop); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'} - ]); - })); + it( + 'task should transit from notScheduled to scheduling then to scheduled state when scheduleTask', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testMicroTaskZone'}).run(() => { + Zone.current.scheduleMicroTask('testMicroTask', noop, undefined, noop); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + ]); + }), + ); - it('task should transit from scheduling to unknown when zoneSpec onScheduleTask callback throw error', - testFnWithLoggedTransitionTo(() => { - Zone.current - .fork({ - name: 'testMicroTaskZone', - onScheduleTask: (delegate, currZone, targetZone, task) => { - throw Error('error in onScheduleTask'); - } - }) - .run(() => { - try { - Zone.current.scheduleMicroTask('testMicroTask', noop, undefined, noop); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'unknown', fromState: 'scheduling'} - ]); - })); + it( + 'task should transit from scheduling to unknown when zoneSpec onScheduleTask callback throw error', + testFnWithLoggedTransitionTo(() => { + Zone.current + .fork({ + name: 'testMicroTaskZone', + onScheduleTask: (delegate, currZone, targetZone, task) => { + throw Error('error in onScheduleTask'); + }, + }) + .run(() => { + try { + Zone.current.scheduleMicroTask('testMicroTask', noop, undefined, noop); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'unknown', fromState: 'scheduling'}, + ]); + }), + ); - it('task should transit from scheduled to running when task is invoked then from running to noScheduled after invoke', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testMicroTaskZone'}).run(() => { - const task = Zone.current.scheduleMicroTask('testMicroTask', noop, undefined, noop); - task.invoke(); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'running', fromState: 'scheduled'}, - {toState: 'notScheduled', fromState: 'running'} - ]); - })); + it( + 'task should transit from scheduled to running when task is invoked then from running to noScheduled after invoke', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testMicroTaskZone'}).run(() => { + const task = Zone.current.scheduleMicroTask('testMicroTask', noop, undefined, noop); + task.invoke(); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'running', fromState: 'scheduled'}, + {toState: 'notScheduled', fromState: 'running'}, + ]); + }), + ); - it('should throw error when try to cancel a microTask', testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testMicroTaskZone'}).run(() => { - const task = Zone.current.scheduleMicroTask('testMicroTask', () => {}, undefined, noop); - expect(() => { - Zone.current.cancelTask(task); - }).toThrowError('Task is not cancelable'); - }); - })); + it( + 'should throw error when try to cancel a microTask', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testMicroTaskZone'}).run(() => { + const task = Zone.current.scheduleMicroTask('testMicroTask', () => {}, undefined, noop); + expect(() => { + Zone.current.cancelTask(task); + }).toThrowError('Task is not cancelable'); + }); + }), + ); - it('task should transit from running to notScheduled when task.callback throw error', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testMicroTaskZone'}).run(() => { - const task = Zone.current.scheduleMicroTask('testMicroTask', () => { - throw Error('invoke error'); - }, undefined, noop); - try { - task.invoke(); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'running', fromState: 'scheduled'}, - {toState: 'notScheduled', fromState: 'running'} - ]); - })); + it( + 'task should transit from running to notScheduled when task.callback throw error', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testMicroTaskZone'}).run(() => { + const task = Zone.current.scheduleMicroTask( + 'testMicroTask', + () => { + throw Error('invoke error'); + }, + undefined, + noop, + ); + try { + task.invoke(); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'running', fromState: 'scheduled'}, + {toState: 'notScheduled', fromState: 'running'}, + ]); + }), + ); - it('task should transit from notScheduled to scheduling then to scheduled if zoneSpec.onHasTask throw error when scheduleTask', - testFnWithLoggedTransitionTo(() => { - Zone.current - .fork({ - name: 'testMicroTaskZone', - onHasTask: (delegate, currZone, targetZone, hasTaskState) => { - throw Error('hasTask Error'); - } - }) - .run(() => { - try { - Zone.current.scheduleMicroTask('testMicroTask', noop, undefined, noop); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'} - ]); - })); + it( + 'task should transit from notScheduled to scheduling then to scheduled if zoneSpec.onHasTask throw error when scheduleTask', + testFnWithLoggedTransitionTo(() => { + Zone.current + .fork({ + name: 'testMicroTaskZone', + onHasTask: (delegate, currZone, targetZone, hasTaskState) => { + throw Error('hasTask Error'); + }, + }) + .run(() => { + try { + Zone.current.scheduleMicroTask('testMicroTask', noop, undefined, noop); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + ]); + }), + ); - it('task should transit to notScheduled state if zoneSpec.onHasTask throw error after task.callback being invoked', - testFnWithLoggedTransitionTo(() => { - let task: Task; - Zone.current - .fork({ - name: 'testMicroTaskZone', - onHasTask: (delegate, currZone, targetZone, hasTaskState) => { - if (task && task.state === 'running') { - throw Error('hasTask Error'); - } - } - }) - .run(() => { - try { - task = Zone.current.scheduleMicroTask('testMicroTask', noop, undefined, noop); - task.invoke(); - } catch (err) { - } - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'running', fromState: 'scheduled'}, - {toState: 'notScheduled', fromState: 'running'} - ]); - })); + it( + 'task should transit to notScheduled state if zoneSpec.onHasTask throw error after task.callback being invoked', + testFnWithLoggedTransitionTo(() => { + let task: Task; + Zone.current + .fork({ + name: 'testMicroTaskZone', + onHasTask: (delegate, currZone, targetZone, hasTaskState) => { + if (task && task.state === 'running') { + throw Error('hasTask Error'); + } + }, + }) + .run(() => { + try { + task = Zone.current.scheduleMicroTask('testMicroTask', noop, undefined, noop); + task.invoke(); + } catch (err) {} + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'running', fromState: 'scheduled'}, + {toState: 'notScheduled', fromState: 'running'}, + ]); + }), + ); - it('task should not run if task transite to notScheduled state which was canceled', - testFnWithLoggedTransitionTo(() => { - let task: Task; - Zone.current.fork({name: 'testCancelZone'}).run(() => { - const task = - Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); - Zone.current.cancelTask(task); - task.invoke(); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'canceling', fromState: 'scheduled'}, - {toState: 'notScheduled', fromState: 'canceling'} - ]); - })); + it( + 'task should not run if task transite to notScheduled state which was canceled', + testFnWithLoggedTransitionTo(() => { + let task: Task; + Zone.current.fork({name: 'testCancelZone'}).run(() => { + const task = Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); + Zone.current.cancelTask(task); + task.invoke(); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'canceling', fromState: 'scheduled'}, + {toState: 'notScheduled', fromState: 'canceling'}, + ]); + }), + ); }); // Test specific to https://github.com/angular/angular/issues/45711 - it('should not throw an error when the task has been canceled previously and is attempted to be canceled again', - () => { - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'testCancelZone'}).run(() => { - const task = - Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); - Zone.current.cancelTask(task); - Zone.current.cancelTask(task); - }); - expect(log.map(item => { - return {toState: item.toState, fromState: item.fromState}; - })) - .toEqual([ - {toState: 'scheduling', fromState: 'notScheduled'}, - {toState: 'scheduled', fromState: 'scheduling'}, - {toState: 'canceling', fromState: 'scheduled'}, - {toState: 'notScheduled', fromState: 'canceling'} - ]); - }); - }); + it('should not throw an error when the task has been canceled previously and is attempted to be canceled again', () => { + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'testCancelZone'}).run(() => { + const task = Zone.current.scheduleEventTask('testEventTask', noop, undefined, noop, noop); + Zone.current.cancelTask(task); + Zone.current.cancelTask(task); + }); + expect( + log.map((item) => { + return {toState: item.toState, fromState: item.fromState}; + }), + ).toEqual([ + {toState: 'scheduling', fromState: 'notScheduled'}, + {toState: 'scheduled', fromState: 'scheduling'}, + {toState: 'canceling', fromState: 'scheduled'}, + {toState: 'notScheduled', fromState: 'canceling'}, + ]); + }); + }); describe('reschedule zone', () => { - let callbackLogs: ({pos: string, method: string, zone: string, task: string}|HasTaskState)[]; + let callbackLogs: ({pos: string; method: string; zone: string; task: string} | HasTaskState)[]; const newZone = Zone.root.fork({ name: 'new', onScheduleTask: (delegate, currZone, targetZone, task) => { - callbackLogs.push( - {pos: 'before', method: 'onScheduleTask', zone: currZone.name, task: task.zone.name}); + callbackLogs.push({ + pos: 'before', + method: 'onScheduleTask', + zone: currZone.name, + task: task.zone.name, + }); return delegate.scheduleTask(targetZone, task); }, onInvokeTask: (delegate, currZone, targetZone, task, applyThis, applyArgs) => { - callbackLogs.push( - {pos: 'before', method: 'onInvokeTask', zone: currZone.name, task: task.zone.name}); + callbackLogs.push({ + pos: 'before', + method: 'onInvokeTask', + zone: currZone.name, + task: task.zone.name, + }); return delegate.invokeTask(targetZone, task, applyThis, applyArgs); }, onCancelTask: (delegate, currZone, targetZone, task) => { - callbackLogs.push( - {pos: 'before', method: 'onCancelTask', zone: currZone.name, task: task.zone.name}); + callbackLogs.push({ + pos: 'before', + method: 'onCancelTask', + zone: currZone.name, + task: task.zone.name, + }); return delegate.cancelTask(targetZone, task); }, onHasTask: (delegate, currZone, targetZone, hasTaskState) => { (hasTaskState as any)['zone'] = targetZone.name; callbackLogs.push(hasTaskState); return delegate.hasTask(targetZone, hasTaskState); - } + }, }); const zone = Zone.root.fork({ name: 'original', onScheduleTask: (delegate, currZone, targetZone, task) => { - callbackLogs.push( - {pos: 'before', method: 'onScheduleTask', zone: currZone.name, task: task.zone.name}); + callbackLogs.push({ + pos: 'before', + method: 'onScheduleTask', + zone: currZone.name, + task: task.zone.name, + }); task.cancelScheduleRequest(); task = newZone.scheduleTask(task); - callbackLogs.push( - {pos: 'after', method: 'onScheduleTask', zone: currZone.name, task: task.zone.name}); + callbackLogs.push({ + pos: 'after', + method: 'onScheduleTask', + zone: currZone.name, + task: task.zone.name, + }); return task; }, onInvokeTask: (delegate, currZone, targetZone, task, applyThis, applyArgs) => { - callbackLogs.push( - {pos: 'before', method: 'onInvokeTask', zone: currZone.name, task: task.zone.name}); + callbackLogs.push({ + pos: 'before', + method: 'onInvokeTask', + zone: currZone.name, + task: task.zone.name, + }); return delegate.invokeTask(targetZone, task, applyThis, applyArgs); }, onCancelTask: (delegate, currZone, targetZone, task) => { - callbackLogs.push( - {pos: 'before', method: 'onCancelTask', zone: currZone.name, task: task.zone.name}); + callbackLogs.push({ + pos: 'before', + method: 'onCancelTask', + zone: currZone.name, + task: task.zone.name, + }); return delegate.cancelTask(targetZone, task); }, onHasTask: (delegate, currZone, targetZone, hasTaskState) => { (hasTaskState)['zone'] = targetZone.name; callbackLogs.push(hasTaskState); return delegate.hasTask(targetZone, hasTaskState); - } + }, }); beforeEach(() => { callbackLogs = []; }); - it('should be able to reschedule zone when in scheduling state, after that, task will completely go to new zone, has nothing to do with original one', - testFnWithLoggedTransitionTo(() => { - zone.run(() => { - const t = Zone.current.scheduleMacroTask( - 'testRescheduleZoneTask', noop, undefined, noop, noop); - t.invoke(); - }); + it( + 'should be able to reschedule zone when in scheduling state, after that, task will completely go to new zone, has nothing to do with original one', + testFnWithLoggedTransitionTo(() => { + zone.run(() => { + const t = Zone.current.scheduleMacroTask( + 'testRescheduleZoneTask', + noop, + undefined, + noop, + noop, + ); + t.invoke(); + }); - expect(callbackLogs).toEqual([ - {pos: 'before', method: 'onScheduleTask', zone: 'original', task: 'original'}, - {pos: 'before', method: 'onScheduleTask', zone: 'new', task: 'new'}, - {microTask: false, macroTask: true, eventTask: false, change: 'macroTask', zone: 'new'}, - {pos: 'after', method: 'onScheduleTask', zone: 'original', task: 'new'}, - {pos: 'before', method: 'onInvokeTask', zone: 'new', task: 'new'}, - {microTask: false, macroTask: false, eventTask: false, change: 'macroTask', zone: 'new'} - ]); - })); + expect(callbackLogs).toEqual([ + {pos: 'before', method: 'onScheduleTask', zone: 'original', task: 'original'}, + {pos: 'before', method: 'onScheduleTask', zone: 'new', task: 'new'}, + {microTask: false, macroTask: true, eventTask: false, change: 'macroTask', zone: 'new'}, + {pos: 'after', method: 'onScheduleTask', zone: 'original', task: 'new'}, + {pos: 'before', method: 'onInvokeTask', zone: 'new', task: 'new'}, + {microTask: false, macroTask: false, eventTask: false, change: 'macroTask', zone: 'new'}, + ]); + }), + ); - it('should not be able to reschedule task in notScheduled / running / canceling state', - testFnWithLoggedTransitionTo(() => { - Zone.current.fork({name: 'rescheduleNotScheduled'}).run(() => { - const t = Zone.current.scheduleMacroTask( - 'testRescheduleZoneTask', noop, undefined, noop, noop); - Zone.current.cancelTask(t); - expect(() => { - t.cancelScheduleRequest(); - }) - .toThrow(Error( - `macroTask 'testRescheduleZoneTask': can not transition to ` + - `'notScheduled', expecting state 'scheduling', was 'notScheduled'.`)); - }); + it( + 'should not be able to reschedule task in notScheduled / running / canceling state', + testFnWithLoggedTransitionTo(() => { + Zone.current.fork({name: 'rescheduleNotScheduled'}).run(() => { + const t = Zone.current.scheduleMacroTask( + 'testRescheduleZoneTask', + noop, + undefined, + noop, + noop, + ); + Zone.current.cancelTask(t); + expect(() => { + t.cancelScheduleRequest(); + }).toThrow( + Error( + `macroTask 'testRescheduleZoneTask': can not transition to ` + + `'notScheduled', expecting state 'scheduling', was 'notScheduled'.`, + ), + ); + }); - Zone.current - .fork({ - name: 'rescheduleRunning', - onInvokeTask: (delegate, currZone, targetZone, task, applyThis, applyArgs) => { - expect(() => { - task.cancelScheduleRequest(); - }) - .toThrow(Error( - `macroTask 'testRescheduleZoneTask': can not transition to ` + - `'notScheduled', expecting state 'scheduling', was 'running'.`)); - } - }) - .run(() => { - const t = Zone.current.scheduleMacroTask( - 'testRescheduleZoneTask', noop, undefined, noop, noop); - t.invoke(); - }); + Zone.current + .fork({ + name: 'rescheduleRunning', + onInvokeTask: (delegate, currZone, targetZone, task, applyThis, applyArgs) => { + expect(() => { + task.cancelScheduleRequest(); + }).toThrow( + Error( + `macroTask 'testRescheduleZoneTask': can not transition to ` + + `'notScheduled', expecting state 'scheduling', was 'running'.`, + ), + ); + }, + }) + .run(() => { + const t = Zone.current.scheduleMacroTask( + 'testRescheduleZoneTask', + noop, + undefined, + noop, + noop, + ); + t.invoke(); + }); - Zone.current - .fork({ - name: 'rescheduleCanceling', - onCancelTask: (delegate, currZone, targetZone, task) => { - expect(() => { - task.cancelScheduleRequest(); - }) - .toThrow(Error( - `macroTask 'testRescheduleZoneTask': can not transition to ` + - `'notScheduled', expecting state 'scheduling', was 'canceling'.`)); - } - }) - .run(() => { - const t = Zone.current.scheduleMacroTask( - 'testRescheduleZoneTask', noop, undefined, noop, noop); - Zone.current.cancelTask(t); - }); - })); + Zone.current + .fork({ + name: 'rescheduleCanceling', + onCancelTask: (delegate, currZone, targetZone, task) => { + expect(() => { + task.cancelScheduleRequest(); + }).toThrow( + Error( + `macroTask 'testRescheduleZoneTask': can not transition to ` + + `'notScheduled', expecting state 'scheduling', was 'canceling'.`, + ), + ); + }, + }) + .run(() => { + const t = Zone.current.scheduleMacroTask( + 'testRescheduleZoneTask', + noop, + undefined, + noop, + noop, + ); + Zone.current.cancelTask(t); + }); + }), + ); - it('can not reschedule a task to a zone which is the descendants of the original zone', - testFnWithLoggedTransitionTo(() => { - const originalZone = Zone.root.fork({ - name: 'originalZone', - onScheduleTask: (delegate, currZone, targetZone, task) => { - callbackLogs.push({ - pos: 'before', - method: 'onScheduleTask', - zone: currZone.name, - task: task.zone.name - }); - task.cancelScheduleRequest(); - task = rescheduleZone.scheduleTask(task); - callbackLogs.push({ - pos: 'after', - method: 'onScheduleTask', - zone: currZone.name, - task: task.zone.name - }); - return task; - } - }); - const rescheduleZone = originalZone.fork({name: 'rescheduleZone'}); - expect(() => { - originalZone.run(() => { - Zone.current.scheduleMacroTask('testRescheduleZoneTask', noop, undefined, noop, noop); - }); - }) - .toThrowError( - 'can not reschedule task to rescheduleZone which is descendants of the original zone originalZone'); - })); + it( + 'can not reschedule a task to a zone which is the descendants of the original zone', + testFnWithLoggedTransitionTo(() => { + const originalZone = Zone.root.fork({ + name: 'originalZone', + onScheduleTask: (delegate, currZone, targetZone, task) => { + callbackLogs.push({ + pos: 'before', + method: 'onScheduleTask', + zone: currZone.name, + task: task.zone.name, + }); + task.cancelScheduleRequest(); + task = rescheduleZone.scheduleTask(task); + callbackLogs.push({ + pos: 'after', + method: 'onScheduleTask', + zone: currZone.name, + task: task.zone.name, + }); + return task; + }, + }); + const rescheduleZone = originalZone.fork({name: 'rescheduleZone'}); + expect(() => { + originalZone.run(() => { + Zone.current.scheduleMacroTask('testRescheduleZoneTask', noop, undefined, noop, noop); + }); + }).toThrowError( + 'can not reschedule task to rescheduleZone which is descendants of the original zone originalZone', + ); + }), + ); }); }); diff --git a/packages/zone.js/test/common/toString.spec.ts b/packages/zone.js/test/common/toString.spec.ts index d1f0320726532..a4da33adc9ca4 100644 --- a/packages/zone.js/test/common/toString.spec.ts +++ b/packages/zone.js/test/common/toString.spec.ts @@ -10,12 +10,13 @@ import {zoneSymbol} from '../../lib/common/utils'; import {ifEnvSupports} from '../test-util'; const g: any = - typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global; + (typeof window !== 'undefined' && window) || (typeof self !== 'undefined' && self) || global; describe('global function patch', () => { describe('isOriginal', () => { it('setTimeout toString should be the same with non patched setTimeout', () => { - expect(Function.prototype.toString.call(setTimeout)) - .toEqual(Function.prototype.toString.call(g[zoneSymbol('setTimeout')])); + expect(Function.prototype.toString.call(setTimeout)).toEqual( + Function.prototype.toString.call(g[zoneSymbol('setTimeout')]), + ); }); it('should not throw error if Promise is not a function', () => { @@ -30,17 +31,21 @@ describe('global function patch', () => { } }); - it('MutationObserver toString should be the same with native version', - ifEnvSupports('MutationObserver', () => { - const nativeMutationObserver = g[zoneSymbol('MutationObserver')]; - if (typeof nativeMutationObserver === 'function') { - expect(Function.prototype.toString.call(g['MutationObserver'])) - .toEqual(Function.prototype.toString.call(nativeMutationObserver)); - } else { - expect(Function.prototype.toString.call(g['MutationObserver'])) - .toEqual(Object.prototype.toString.call(nativeMutationObserver)); - } - })); + it( + 'MutationObserver toString should be the same with native version', + ifEnvSupports('MutationObserver', () => { + const nativeMutationObserver = g[zoneSymbol('MutationObserver')]; + if (typeof nativeMutationObserver === 'function') { + expect(Function.prototype.toString.call(g['MutationObserver'])).toEqual( + Function.prototype.toString.call(nativeMutationObserver), + ); + } else { + expect(Function.prototype.toString.call(g['MutationObserver'])).toEqual( + Object.prototype.toString.call(nativeMutationObserver), + ); + } + }), + ); }); describe('isNative', () => { @@ -49,14 +54,19 @@ describe('global function patch', () => { }); it('Function toString should look like native', () => { - expect(Function.prototype.toString.call(Function.prototype.toString)) - .toContain('[native code]'); + expect(Function.prototype.toString.call(Function.prototype.toString)).toContain( + '[native code]', + ); }); - it('EventTarget addEventListener should look like native', ifEnvSupports('HTMLElement', () => { - expect(Function.prototype.toString.call(HTMLElement.prototype.addEventListener)) - .toContain('[native code]'); - })); + it( + 'EventTarget addEventListener should look like native', + ifEnvSupports('HTMLElement', () => { + expect(Function.prototype.toString.call(HTMLElement.prototype.addEventListener)).toContain( + '[native code]', + ); + }), + ); }); }); @@ -78,7 +88,7 @@ describe('ZoneTask', () => { microTask = task; } return task; - } + }, }); zone.run(() => { const id1 = setTimeout(() => {}); diff --git a/packages/zone.js/test/common/util.spec.ts b/packages/zone.js/test/common/util.spec.ts index 727e5454cb25d..6d051e698c77a 100644 --- a/packages/zone.js/test/common/util.spec.ts +++ b/packages/zone.js/test/common/util.spec.ts @@ -8,10 +8,10 @@ import {patchMethod, patchProperty, patchPrototype, zoneSymbol} from '../../lib/common/utils'; -describe('utils', function() { +describe('utils', function () { describe('patchMethod', () => { it('should patch target where the method is defined', () => { - let args: any[]|undefined; + let args: any[] | undefined; let self: any; class Type { method(..._args: any[]) { @@ -25,14 +25,16 @@ describe('utils', function() { let delegateSymbol: string; const instance = new Type(); - expect(patchMethod(instance, 'method', (delegate: Function, symbol: string, name: string) => { - expect(name).toEqual('method'); - delegateMethod = delegate; - delegateSymbol = symbol; - return function(self, args) { - return delegate.apply(self, ['patch', args[0]]); - }; - })).toBe(delegateMethod!); + expect( + patchMethod(instance, 'method', (delegate: Function, symbol: string, name: string) => { + expect(name).toEqual('method'); + delegateMethod = delegate; + delegateSymbol = symbol; + return function (self, args) { + return delegate.apply(self, ['patch', args[0]]); + }; + }), + ).toBe(delegateMethod!); expect(instance.method('a0')).toEqual('OK'); expect(args).toEqual(['patch', 'a0']); @@ -43,17 +45,17 @@ describe('utils', function() { }); it('should not double patch', () => { - const Type = function() {}; - const method = Type.prototype.method = function() {}; + const Type = function () {}; + const method = (Type.prototype.method = function () {}); patchMethod(Type.prototype, 'method', (delegate) => { - return function(self, args: any[]) { + return function (self, args: any[]) { return delegate.apply(self, ['patch', ...args]); }; }); const pMethod = Type.prototype.method; expect(pMethod).not.toBe(method); patchMethod(Type.prototype, 'method', (delegate) => { - return function(self, args) { + return function (self, args) { return delegate.apply(self, ['patch', ...args]); }; }); @@ -61,16 +63,20 @@ describe('utils', function() { }); it('should not patch property which is not configurable', () => { - const TestType = function() {}; + const TestType = function () {}; const originalDefineProperty = (Object as any)[zoneSymbol('defineProperty')]; if (originalDefineProperty) { - originalDefineProperty( - TestType.prototype, 'nonConfigurableProperty', - {configurable: false, writable: true, value: 'test'}); + originalDefineProperty(TestType.prototype, 'nonConfigurableProperty', { + configurable: false, + writable: true, + value: 'test', + }); } else { - Object.defineProperty( - TestType.prototype, 'nonConfigurableProperty', - {configurable: false, writable: true, value: 'test'}); + Object.defineProperty(TestType.prototype, 'nonConfigurableProperty', { + configurable: false, + writable: true, + value: 'test', + }); } patchProperty(TestType.prototype, 'nonConfigurableProperty'); const desc = Object.getOwnPropertyDescriptor(TestType.prototype, 'nonConfigurableProperty'); @@ -79,8 +85,8 @@ describe('utils', function() { }); it('should patch target if it overrides a patched method', () => { - let args: any[]|undefined; - let childArgs: any[]|undefined; + let args: any[] | undefined; + let childArgs: any[] | undefined; let self: any; let childSelf: any; class Type { @@ -107,29 +113,35 @@ describe('utils', function() { const typeInstance = new Type(); const childTypeInstance = new ChildType(); - expect(patchMethod( - Type.prototype, 'method', - (delegate: Function, symbol: string, name: string) => { - expect(name).toEqual('method'); - delegateMethod = delegate; - delegateSymbol = symbol; - return function(self, args) { - return delegate.apply(self, ['patch', args[0]]); - }; - })) - .toBe(delegateMethod!); - - expect(patchMethod( - ChildType.prototype, 'method', - (delegate: Function, symbol: string, name: string) => { - expect(name).toEqual('method'); - childDelegateMethod = delegate; - childDelegateSymbol = symbol; - return function(self, args) { - return delegate.apply(self, ['child patch', args[0]]); - }; - })) - .toBe(childDelegateMethod!); + expect( + patchMethod( + Type.prototype, + 'method', + (delegate: Function, symbol: string, name: string) => { + expect(name).toEqual('method'); + delegateMethod = delegate; + delegateSymbol = symbol; + return function (self, args) { + return delegate.apply(self, ['patch', args[0]]); + }; + }, + ), + ).toBe(delegateMethod!); + + expect( + patchMethod( + ChildType.prototype, + 'method', + (delegate: Function, symbol: string, name: string) => { + expect(name).toEqual('method'); + childDelegateMethod = delegate; + childDelegateSymbol = symbol; + return function (self, args) { + return delegate.apply(self, ['child patch', args[0]]); + }; + }, + ), + ).toBe(childDelegateMethod!); expect(typeInstance.method('a0')).toEqual('OK'); expect(childTypeInstance.method('a0')).toEqual('ChildOK'); @@ -146,7 +158,7 @@ describe('utils', function() { }); it('should not patch target if does not override a patched method', () => { - let args: any[]|undefined; + let args: any[] | undefined; let self: any; class Type { method(..._args: any[]) { @@ -163,27 +175,33 @@ describe('utils', function() { const typeInstance = new Type(); const childTypeInstance = new ChildType(); - expect(patchMethod( - Type.prototype, 'method', - (delegate: Function, symbol: string, name: string) => { - expect(name).toEqual('method'); - delegateMethod = delegate; - delegateSymbol = symbol; - return function(self, args) { - return delegate.apply(self, ['patch', args[0]]); - }; - })) - .toBe(delegateMethod!); - - expect(patchMethod( - ChildType.prototype, 'method', - (delegate: Function, symbol: string, name: string) => { - childPatched = true; - return function(self, args) { - return delegate.apply(self, ['child patch', args[0]]); - }; - })) - .toBe(delegateMethod!); + expect( + patchMethod( + Type.prototype, + 'method', + (delegate: Function, symbol: string, name: string) => { + expect(name).toEqual('method'); + delegateMethod = delegate; + delegateSymbol = symbol; + return function (self, args) { + return delegate.apply(self, ['patch', args[0]]); + }; + }, + ), + ).toBe(delegateMethod!); + + expect( + patchMethod( + ChildType.prototype, + 'method', + (delegate: Function, symbol: string, name: string) => { + childPatched = true; + return function (self, args) { + return delegate.apply(self, ['child patch', args[0]]); + }; + }, + ), + ).toBe(delegateMethod!); expect(childPatched).toBe(false); expect(typeInstance.method('a0')).toEqual('OK'); @@ -202,7 +220,7 @@ describe('utils', function() { describe('patchPrototype', () => { it('non configurable property desc should be patched', () => { 'use strict'; - const TestFunction: any = function() {}; + const TestFunction: any = function () {}; const log: string[] = []; Object.defineProperties(TestFunction.prototype, { 'property1': { @@ -211,7 +229,7 @@ describe('utils', function() { }, writable: true, configurable: true, - enumerable: true + enumerable: true, }, 'property2': { value: function Property2(callback: Function) { @@ -219,8 +237,8 @@ describe('utils', function() { }, writable: true, configurable: false, - enumerable: true - } + enumerable: true, + }, }); const zone = Zone.current.fork({name: 'patch'}); @@ -253,7 +271,7 @@ describe('utils', function() { it('non writable property desc should not be patched', () => { 'use strict'; - const TestFunction: any = function() {}; + const TestFunction: any = function () {}; const log: string[] = []; Object.defineProperties(TestFunction.prototype, { 'property1': { @@ -262,7 +280,7 @@ describe('utils', function() { }, writable: true, configurable: true, - enumerable: true + enumerable: true, }, 'property2': { value: function Property2(callback: Function) { @@ -270,8 +288,8 @@ describe('utils', function() { }, writable: false, configurable: true, - enumerable: true - } + enumerable: true, + }, }); const zone = Zone.current.fork({name: 'patch'}); @@ -304,11 +322,11 @@ describe('utils', function() { it('readonly property desc should not be patched', () => { 'use strict'; - const TestFunction: any = function() {}; + const TestFunction: any = function () {}; const log: string[] = []; Object.defineProperties(TestFunction.prototype, { 'property1': { - get: function() { + get: function () { if (!this._property1) { this._property1 = function Property2(callback: Function) { Zone.root.run(callback); @@ -316,21 +334,21 @@ describe('utils', function() { } return this._property1; }, - set: function(func: Function) { + set: function (func: Function) { this._property1 = func; }, configurable: true, - enumerable: true + enumerable: true, }, 'property2': { - get: function() { + get: function () { return function Property2(callback: Function) { Zone.root.run(callback); }; }, configurable: true, - enumerable: true - } + enumerable: true, + }, }); const zone = Zone.current.fork({name: 'patch'}); @@ -363,7 +381,7 @@ describe('utils', function() { it('non writable method should not be patched', () => { 'use strict'; - const TestFunction: any = function() {}; + const TestFunction: any = function () {}; const log: string[] = []; Object.defineProperties(TestFunction.prototype, { 'property2': { @@ -372,8 +390,8 @@ describe('utils', function() { }, writable: false, configurable: true, - enumerable: true - } + enumerable: true, + }, }); const zone = Zone.current.fork({name: 'patch'}); @@ -388,12 +406,14 @@ describe('utils', function() { log.length = 0; patchMethod( - TestFunction.prototype, 'property2', - function(delegate: Function, delegateName: string, name: string) { - return function(self: any, args: any) { - log.push('patched property2'); - }; - }); + TestFunction.prototype, + 'property2', + function (delegate: Function, delegateName: string, name: string) { + return function (self: any, args: any) { + log.push('patched property2'); + }; + }, + ); zone.run(() => { const instance = new TestFunction(); @@ -406,18 +426,18 @@ describe('utils', function() { it('readonly method should not be patched', () => { 'use strict'; - const TestFunction: any = function() {}; + const TestFunction: any = function () {}; const log: string[] = []; Object.defineProperties(TestFunction.prototype, { 'property2': { - get: function() { + get: function () { return function Property2(callback: Function) { Zone.root.run(callback); }; }, configurable: true, - enumerable: true - } + enumerable: true, + }, }); const zone = Zone.current.fork({name: 'patch'}); @@ -432,12 +452,14 @@ describe('utils', function() { log.length = 0; patchMethod( - TestFunction.prototype, 'property2', - function(delegate: Function, delegateName: string, name: string) { - return function(self: any, args: any) { - log.push('patched property2'); - }; - }); + TestFunction.prototype, + 'property2', + function (delegate: Function, delegateName: string, name: string) { + return function (self: any, args: any) { + log.push('patched property2'); + }; + }, + ); zone.run(() => { const instance = new TestFunction(); diff --git a/packages/zone.js/test/common/zone.spec.ts b/packages/zone.js/test/common/zone.spec.ts index e88f2db254b1b..ba3575074c679 100644 --- a/packages/zone.js/test/common/zone.spec.ts +++ b/packages/zone.js/test/common/zone.spec.ts @@ -7,80 +7,99 @@ */ import {zoneSymbol} from '../../lib/common/utils'; -describe('Zone', function() { +describe('Zone', function () { const rootZone = Zone.current; - it('should have a name', function() { + it('should have a name', function () { expect(Zone.current.name).toBeDefined(); }); - describe('hooks', function() { - it('should throw if onError is not defined', function() { - expect(function() { + describe('hooks', function () { + it('should throw if onError is not defined', function () { + expect(function () { Zone.current.run(throwError); }).toThrow(); }); - - it('should fire onError if a function run by a zone throws', function() { + it('should fire onError if a function run by a zone throws', function () { const errorSpy = jasmine.createSpy('error'); const myZone = Zone.current.fork({name: 'spy', onHandleError: errorSpy}); expect(errorSpy).not.toHaveBeenCalled(); - expect(function() { + expect(function () { myZone.runGuarded(throwError); }).not.toThrow(); expect(errorSpy).toHaveBeenCalled(); }); - it('should send correct currentZone in hook method when in nested zone', function() { + it('should send correct currentZone in hook method when in nested zone', function () { const zone = Zone.current; const zoneA = zone.fork({ name: 'A', - onInvoke: function( - parentDelegate, currentZone, targetZone, callback, applyThis, applyArgs, source) { + onInvoke: function ( + parentDelegate, + currentZone, + targetZone, + callback, + applyThis, + applyArgs, + source, + ) { expect(currentZone.name).toEqual('A'); return parentDelegate.invoke(targetZone, callback, applyThis, applyArgs, source); - } + }, }); const zoneB = zoneA.fork({ name: 'B', - onInvoke: function( - parentDelegate, currentZone, targetZone, callback, applyThis, applyArgs, source) { + onInvoke: function ( + parentDelegate, + currentZone, + targetZone, + callback, + applyThis, + applyArgs, + source, + ) { expect(currentZone.name).toEqual('B'); return parentDelegate.invoke(targetZone, callback, applyThis, applyArgs, source); - } + }, }); const zoneC = zoneB.fork({name: 'C'}); - zoneC.run(function() {}); + zoneC.run(function () {}); }); - it('should send correct currentZone in hook method when in nested zone with empty implementation', - function() { - const zone = Zone.current; - const zoneA = zone.fork({ - name: 'A', - onInvoke: function( - parentDelegate, currentZone, targetZone, callback, applyThis, applyArgs, source) { - expect(currentZone.name).toEqual('A'); - return parentDelegate.invoke(targetZone, callback, applyThis, applyArgs, source); - } - }); - const zoneB = zoneA.fork({name: 'B'}); - const zoneC = zoneB.fork({name: 'C'}); - zoneC.run(function() {}); - }); + it('should send correct currentZone in hook method when in nested zone with empty implementation', function () { + const zone = Zone.current; + const zoneA = zone.fork({ + name: 'A', + onInvoke: function ( + parentDelegate, + currentZone, + targetZone, + callback, + applyThis, + applyArgs, + source, + ) { + expect(currentZone.name).toEqual('A'); + return parentDelegate.invoke(targetZone, callback, applyThis, applyArgs, source); + }, + }); + const zoneB = zoneA.fork({name: 'B'}); + const zoneC = zoneB.fork({name: 'C'}); + zoneC.run(function () {}); + }); }); - it('should allow zones to be run from within another zone', function() { + it('should allow zones to be run from within another zone', function () { const zone = Zone.current; const zoneA = zone.fork({name: 'A'}); const zoneB = zone.fork({name: 'B'}); - zoneA.run(function() { - zoneB.run(function() { + zoneA.run(function () { + zoneB.run(function () { expect(Zone.current).toBe(zoneB); }); expect(Zone.current).toBe(zoneA); @@ -88,32 +107,31 @@ describe('Zone', function() { expect(Zone.current).toBe(zone); }); - - describe('wrap', function() { - it('should throw if argument is not a function', function() { - expect(function() { + describe('wrap', function () { + it('should throw if argument is not a function', function () { + expect(function () { (Zone.current.wrap)(11); }).toThrowError('Expecting function got: 11'); }); }); - describe('run out side of current zone', function() { - it('should be able to get root zone', function() { - Zone.current.fork({name: 'testZone'}).run(function() { + describe('run out side of current zone', function () { + it('should be able to get root zone', function () { + Zone.current.fork({name: 'testZone'}).run(function () { expect(Zone.root.name).toEqual(''); }); }); - it('should be able to get run under rootZone', function() { - Zone.current.fork({name: 'testZone'}).run(function() { + it('should be able to get run under rootZone', function () { + Zone.current.fork({name: 'testZone'}).run(function () { Zone.root.run(() => { expect(Zone.current.name).toEqual(''); }); }); }); - it('should be able to get run outside of current zone', function() { - Zone.current.fork({name: 'testZone'}).run(function() { + it('should be able to get run outside of current zone', function () { + Zone.current.fork({name: 'testZone'}).run(function () { Zone.root.fork({name: 'newTestZone'}).run(() => { expect(Zone.current.name).toEqual('newTestZone'); expect(Zone.current.parent!.name).toEqual(''); @@ -122,8 +140,8 @@ describe('Zone', function() { }); }); - describe('get', function() { - it('should store properties', function() { + describe('get', function () { + it('should store properties', function () { const testZone = Zone.current.fork({name: 'A', properties: {key: 'value'}}); expect(testZone.get('key')).toEqual('value'); expect(testZone.getZoneWith('key')).toEqual(testZone); @@ -140,16 +158,20 @@ describe('Zone', function() { let log: any[]; const zone: Zone = Zone.current.fork({ name: 'parent', - onHasTask: (delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState): - void => { - (hasTaskState as any)['zone'] = target.name; - log.push(hasTaskState); - }, + onHasTask: ( + delegate: ZoneDelegate, + current: Zone, + target: Zone, + hasTaskState: HasTaskState, + ): void => { + (hasTaskState as any)['zone'] = target.name; + log.push(hasTaskState); + }, onScheduleTask: (delegate: ZoneDelegate, current: Zone, target: Zone, task: Task) => { // Do nothing to prevent tasks from being run on VM turn; // Tests run task explicitly. return task; - } + }, }); beforeEach(() => { @@ -157,52 +179,65 @@ describe('Zone', function() { }); it('task can only run in the zone of creation', () => { - const task = - zone.fork({name: 'createZone'}).scheduleMacroTask('test', noop, undefined, noop, noop); + const task = zone + .fork({name: 'createZone'}) + .scheduleMacroTask('test', noop, undefined, noop, noop); expect(() => { Zone.current.fork({name: 'anotherZone'}).runTask(task); - }) - .toThrowError( - 'A task can only be run in the zone of creation! (Creation: createZone; Execution: anotherZone)'); + }).toThrowError( + 'A task can only be run in the zone of creation! (Creation: createZone; Execution: anotherZone)', + ); task.zone.cancelTask(task); }); it('task can only cancel in the zone of creation', () => { - const task = - zone.fork({name: 'createZone'}).scheduleMacroTask('test', noop, undefined, noop, noop); + const task = zone + .fork({name: 'createZone'}) + .scheduleMacroTask('test', noop, undefined, noop, noop); expect(() => { Zone.current.fork({name: 'anotherZone'}).cancelTask(task); - }) - .toThrowError( - 'A task can only be cancelled in the zone of creation! (Creation: createZone; Execution: anotherZone)'); + }).toThrowError( + 'A task can only be cancelled in the zone of creation! (Creation: createZone; Execution: anotherZone)', + ); task.zone.cancelTask(task); }); it('should prevent double cancellation', () => { - const task = - zone.scheduleMacroTask('test', () => log.push('macroTask'), undefined, noop, noop); + const task = zone.scheduleMacroTask( + 'test', + () => log.push('macroTask'), + undefined, + noop, + noop, + ); zone.cancelTask(task); try { zone.cancelTask(task); } catch (e) { - expect((e as Error).message) - .toContain( - 'macroTask \'test\': can not transition to \'canceling\', expecting state \'scheduled\' or \'running\', was \'notScheduled\'.'); + expect((e as Error).message).toContain( + "macroTask 'test': can not transition to 'canceling', expecting state 'scheduled' or 'running', was 'notScheduled'.", + ); } }); it('should not decrement counters on periodic tasks', () => { zone.run(() => { const task = zone.scheduleMacroTask( - 'test', () => log.push('macroTask'), {isPeriodic: true}, noop, noop); + 'test', + () => log.push('macroTask'), + {isPeriodic: true}, + noop, + noop, + ); zone.runTask(task); zone.runTask(task); zone.cancelTask(task); }); expect(log).toEqual([ {microTask: false, macroTask: true, eventTask: false, change: 'macroTask', zone: 'parent'}, - 'macroTask', 'macroTask', - {microTask: false, macroTask: false, eventTask: false, change: 'macroTask', zone: 'parent'} + 'macroTask', + 'macroTask', + {microTask: false, macroTask: false, eventTask: false, change: 'macroTask', zone: 'parent'}, ]); }); @@ -211,9 +246,11 @@ describe('Zone', function() { const z = Zone.current; z.runTask(z.scheduleMicroTask('test', () => log.push('microTask'))); z.cancelTask( - z.scheduleMacroTask('test', () => log.push('macroTask'), undefined, noop, noop)); + z.scheduleMacroTask('test', () => log.push('macroTask'), undefined, noop, noop), + ); z.cancelTask( - z.scheduleEventTask('test', () => log.push('eventTask'), undefined, noop, noop)); + z.scheduleEventTask('test', () => log.push('eventTask'), undefined, noop, noop), + ); }); expect(log).toEqual([ {microTask: true, macroTask: false, eventTask: false, change: 'microTask', zone: 'parent'}, @@ -222,7 +259,7 @@ describe('Zone', function() { {microTask: false, macroTask: true, eventTask: false, change: 'macroTask', zone: 'parent'}, {microTask: false, macroTask: false, eventTask: false, change: 'macroTask', zone: 'parent'}, {microTask: false, macroTask: false, eventTask: true, change: 'eventTask', zone: 'parent'}, - {microTask: false, macroTask: false, eventTask: false, change: 'eventTask', zone: 'parent'} + {microTask: false, macroTask: false, eventTask: false, change: 'eventTask', zone: 'parent'}, ]); }); @@ -244,40 +281,62 @@ describe('Zone', function() { const log: any[] = []; const zone = Zone.current.fork({ name: 'test-root', - onHasTask: - (delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState) => { - (hasTaskState as any)['zone'] = target.name; - log.push(hasTaskState); - } + onHasTask: ( + delegate: ZoneDelegate, + current: Zone, + target: Zone, + hasTaskState: HasTaskState, + ) => { + (hasTaskState as any)['zone'] = target.name; + log.push(hasTaskState); + }, }); const left = zone.fork({name: 'left'}); const right = zone.fork({ name: 'right', onScheduleTask: (delegate: ZoneDelegate, current: Zone, target: Zone, task: Task): Task => { - log.push( - {pos: 'before', method: 'onScheduleTask', zone: current.name, task: task.zone.name}); + log.push({ + pos: 'before', + method: 'onScheduleTask', + zone: current.name, + task: task.zone.name, + }); // Cancel the current scheduling of the task task.cancelScheduleRequest(); // reschedule on a different zone. task = left.scheduleTask(task); - log.push( - {pos: 'after', method: 'onScheduleTask', zone: current.name, task: task.zone.name}); + log.push({ + pos: 'after', + method: 'onScheduleTask', + zone: current.name, + task: task.zone.name, + }); return task; - } + }, }); const rchild = right.fork({ name: 'rchild', onScheduleTask: (delegate: ZoneDelegate, current: Zone, target: Zone, task: Task): Task => { - log.push( - {pos: 'before', method: 'onScheduleTask', zone: current.name, task: task.zone.name}); + log.push({ + pos: 'before', + method: 'onScheduleTask', + zone: current.name, + task: task.zone.name, + }); task = delegate.scheduleTask(target, task); - log.push( - {pos: 'after', method: 'onScheduleTask', zone: current.name, task: task.zone.name}); + log.push({ + pos: 'after', + method: 'onScheduleTask', + zone: current.name, + task: task.zone.name, + }); expect((task as any)._zoneDelegates.map((zd: ZoneDelegate) => zd.zone.name)).toEqual([ - 'left', 'test-root', 'ProxyZone' + 'left', + 'test-root', + 'ProxyZone', ]); return task; - } + }, }); const task = rchild.scheduleMacroTask('testTask', () => log.push('WORK'), {}, noop, noop); @@ -287,48 +346,62 @@ describe('Zone', function() { expect(log).toEqual([ {pos: 'before', method: 'onScheduleTask', zone: 'rchild', task: 'rchild'}, {pos: 'before', method: 'onScheduleTask', zone: 'right', task: 'rchild'}, - {microTask: false, macroTask: true, eventTask: false, change: 'macroTask', zone: 'left'}, { + {microTask: false, macroTask: true, eventTask: false, change: 'macroTask', zone: 'left'}, + { microTask: false, macroTask: true, eventTask: false, change: 'macroTask', - zone: 'test-root' + zone: 'test-root', }, {pos: 'after', method: 'onScheduleTask', zone: 'right', task: 'left'}, - {pos: 'after', method: 'onScheduleTask', zone: 'rchild', task: 'left'}, 'left', 'WORK', - {microTask: false, macroTask: false, eventTask: false, change: 'macroTask', zone: 'left'}, { + {pos: 'after', method: 'onScheduleTask', zone: 'rchild', task: 'left'}, + 'left', + 'WORK', + {microTask: false, macroTask: false, eventTask: false, change: 'macroTask', zone: 'left'}, + { microTask: false, macroTask: false, eventTask: false, change: 'macroTask', - zone: 'test-root' - } + zone: 'test-root', + }, ]); }); - it('period task should not transit to scheduled state after being cancelled in running state', - () => { - const zone = Zone.current.fork({name: 'testZone'}); + it('period task should not transit to scheduled state after being cancelled in running state', () => { + const zone = Zone.current.fork({name: 'testZone'}); - const task = zone.scheduleMacroTask('testPeriodTask', () => { - zone.cancelTask(task); - }, {isPeriodic: true}, () => {}, () => {}); + const task = zone.scheduleMacroTask( + 'testPeriodTask', + () => { + zone.cancelTask(task); + }, + {isPeriodic: true}, + () => {}, + () => {}, + ); - task.invoke(); - expect(task.state).toBe('notScheduled'); - }); + task.invoke(); + expect(task.state).toBe('notScheduled'); + }); - it('event task should not transit to scheduled state after being cancelled in running state', - () => { - const zone = Zone.current.fork({name: 'testZone'}); + it('event task should not transit to scheduled state after being cancelled in running state', () => { + const zone = Zone.current.fork({name: 'testZone'}); - const task = zone.scheduleEventTask('testEventTask', () => { - zone.cancelTask(task); - }, undefined, () => {}, () => {}); + const task = zone.scheduleEventTask( + 'testEventTask', + () => { + zone.cancelTask(task); + }, + undefined, + () => {}, + () => {}, + ); - task.invoke(); - expect(task.state).toBe('notScheduled'); - }); + task.invoke(); + expect(task.state).toBe('notScheduled'); + }); describe('assert ZoneAwarePromise', () => { it('should not throw when all is OK', () => { @@ -359,7 +432,6 @@ describe('Zone', function() { let log: string[]; function noop() {} - beforeEach(() => { log = []; }); @@ -370,11 +442,17 @@ describe('Zone', function() { z.scheduleMicroTask('test', () => log.push('microTask')); - const macro = z.scheduleMacroTask('test', () => { - event.invoke(); - // At this point, we should not have invoked the microtask. - expect(log).toEqual(['eventTask']); - }, undefined, noop, noop); + const macro = z.scheduleMacroTask( + 'test', + () => { + event.invoke(); + // At this point, we should not have invoked the microtask. + expect(log).toEqual(['eventTask']); + }, + undefined, + noop, + noop, + ); macro.invoke(); }); @@ -384,13 +462,13 @@ describe('Zone', function() { const event = z.scheduleEventTask('test', () => {}, undefined, noop, noop); const micro = z.scheduleMicroTask('test', () => {}); const macro = z.scheduleMacroTask('test', () => {}, undefined, noop, noop); - expect(function() { + expect(function () { JSON.stringify(event); }).not.toThrow(); - expect(function() { + expect(function () { JSON.stringify(micro); }).not.toThrow(); - expect(function() { + expect(function () { JSON.stringify(macro); }).not.toThrow(); }); @@ -399,19 +477,31 @@ describe('Zone', function() { const spy = jasmine.createSpy('error'); const hasTaskZone = Zone.current.fork({ name: 'hasTask', - onHasTask: - (delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - hasTasState: HasTaskState) => { - throw new Error('onHasTask Error'); - }, - onHandleError: - (delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: Error) => { - spy(error.message); - return delegate.handleError(targetZone, error); - } + onHasTask: ( + delegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + hasTasState: HasTaskState, + ) => { + throw new Error('onHasTask Error'); + }, + onHandleError: ( + delegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + error: Error, + ) => { + spy(error.message); + return delegate.handleError(targetZone, error); + }, }); - const microTask = hasTaskZone.scheduleMicroTask('test', () => {}, undefined, () => {}); + const microTask = hasTaskZone.scheduleMicroTask( + 'test', + () => {}, + undefined, + () => {}, + ); expect(spy).toHaveBeenCalledWith('onHasTask Error'); }); }); diff --git a/packages/zone.js/test/extra/bluebird.spec.ts b/packages/zone.js/test/extra/bluebird.spec.ts index 2aa15be2a2fd1..1fecb1af3a5f0 100644 --- a/packages/zone.js/test/extra/bluebird.spec.ts +++ b/packages/zone.js/test/extra/bluebird.spec.ts @@ -37,7 +37,7 @@ describe('bluebird promise', () => { onInvokeTask: (delegate, curr, target, task, applyThis, applyArgs) => { log.push('invoke bluebird task ' + task.source); return delegate.invokeTask(target, task, applyThis, applyArgs); - } + }, }); beforeEach(() => { @@ -53,8 +53,8 @@ describe('bluebird promise', () => { }); p.then(() => { expect(Zone.current.name).toEqual('bluebird'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length).toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); done(); }); }); @@ -68,8 +68,8 @@ describe('bluebird promise', () => { }, 0); }); p.catch(() => { - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length).toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); expect(Zone.current.name).toEqual('bluebird'); done(); }); @@ -78,16 +78,17 @@ describe('bluebird promise', () => { it('bluebird promise spread method should be in zone', (done) => { zone.run(() => { - BluebirdPromise.all([BluebirdPromise.resolve('test1'), BluebirdPromise.resolve('test2')]) - .spread((r1: string, r2: string) => { - expect(r1).toEqual('test1'); - expect(r2).toEqual('test2'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.all([ + BluebirdPromise.resolve('test1'), + BluebirdPromise.resolve('test2'), + ]).spread((r1: string, r2: string) => { + expect(r1).toEqual('test1'); + expect(r2).toEqual('test2'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); @@ -99,8 +100,8 @@ describe('bluebird promise', () => { }, 0); }); p.finally(() => { - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length).toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); expect(Zone.current.name).toEqual('bluebird'); done(); }); @@ -109,63 +110,56 @@ describe('bluebird promise', () => { it('bluebird promise join method should be in zone', (done) => { zone.run(() => { - BluebirdPromise - .join( - BluebirdPromise.resolve('test1'), BluebirdPromise.resolve('test2'), - (r1: string, r2: string) => { - expect(r1).toEqual('test1'); - expect(r2).toEqual('test2'); - expect(Zone.current.name).toEqual('bluebird'); - }) - .then(() => { - expect(Zone.current.name).toEqual('bluebird'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - done(); - }); + BluebirdPromise.join( + BluebirdPromise.resolve('test1'), + BluebirdPromise.resolve('test2'), + (r1: string, r2: string) => { + expect(r1).toEqual('test1'); + expect(r2).toEqual('test2'); + expect(Zone.current.name).toEqual('bluebird'); + }, + ).then(() => { + expect(Zone.current.name).toEqual('bluebird'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + done(); + }); }); }); it('bluebird promise try method should be in zone', (done) => { zone.run(() => { - BluebirdPromise - .try(() => { - throw new Error('promise error'); - }) - .catch((err: Error) => { - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - expect(err.message).toEqual('promise error'); - done(); - }); + BluebirdPromise.try(() => { + throw new Error('promise error'); + }).catch((err: Error) => { + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + expect(err.message).toEqual('promise error'); + done(); + }); }); }); it('bluebird promise method method should be in zone', (done) => { zone.run(() => { - BluebirdPromise - .method(() => { - return 'test'; - })() - .then((result: string) => { - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - expect(result).toEqual('test'); - done(); - }); + BluebirdPromise.method(() => { + return 'test'; + })().then((result: string) => { + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + expect(result).toEqual('test'); + done(); + }); }); }); it('bluebird promise resolve method should be in zone', (done) => { zone.run(() => { BluebirdPromise.resolve('test').then((result: string) => { - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length).toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); expect(Zone.current.name).toEqual('bluebird'); expect(result).toEqual('test'); done(); @@ -176,8 +170,8 @@ describe('bluebird promise', () => { it('bluebird promise reject method should be in zone', (done) => { zone.run(() => { BluebirdPromise.reject('error').catch((error: any) => { - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length).toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); expect(Zone.current.name).toEqual('bluebird'); expect(error).toEqual('error'); done(); @@ -187,179 +181,171 @@ describe('bluebird promise', () => { it('bluebird promise all method should be in zone', (done) => { zone.run(() => { - BluebirdPromise.all([BluebirdPromise.resolve('test1'), BluebirdPromise.resolve('test2')]) - .then((r: string[]) => { - expect(r[0]).toEqual('test1'); - expect(r[1]).toEqual('test2'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.all([ + BluebirdPromise.resolve('test1'), + BluebirdPromise.resolve('test2'), + ]).then((r: string[]) => { + expect(r[0]).toEqual('test1'); + expect(r[1]).toEqual('test2'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise props method should be in zone', (done) => { zone.run(() => { - BluebirdPromise - .props({test1: BluebirdPromise.resolve('test1'), test2: BluebirdPromise.resolve('test2')}) - .then((r: any) => { - expect(r.test1).toEqual('test1'); - expect(r.test2).toEqual('test2'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.props({ + test1: BluebirdPromise.resolve('test1'), + test2: BluebirdPromise.resolve('test2'), + }).then((r: any) => { + expect(r.test1).toEqual('test1'); + expect(r.test2).toEqual('test2'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise any method should be in zone', (done) => { zone.run(() => { - BluebirdPromise.any([BluebirdPromise.resolve('test1'), BluebirdPromise.resolve('test2')]) - .then((r: any) => { - expect(r).toEqual('test1'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.any([ + BluebirdPromise.resolve('test1'), + BluebirdPromise.resolve('test2'), + ]).then((r: any) => { + expect(r).toEqual('test1'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise some method should be in zone', (done) => { zone.run(() => { - BluebirdPromise.some([BluebirdPromise.resolve('test1'), BluebirdPromise.resolve('test2')], 1) - .then((r: any) => { - expect(r.length).toBe(1); - expect(r[0]).toEqual('test1'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.some( + [BluebirdPromise.resolve('test1'), BluebirdPromise.resolve('test2')], + 1, + ).then((r: any) => { + expect(r.length).toBe(1); + expect(r[0]).toEqual('test1'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise map method should be in zone', (done) => { zone.run(() => { - BluebirdPromise - .map( - ['test1', 'test2'], - (value: any) => { - return BluebirdPromise.resolve(value); - }) - .then((r: string[]) => { - expect(r.length).toBe(2); - expect(r[0]).toEqual('test1'); - expect(r[1]).toEqual('test2'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.map(['test1', 'test2'], (value: any) => { + return BluebirdPromise.resolve(value); + }).then((r: string[]) => { + expect(r.length).toBe(2); + expect(r[0]).toEqual('test1'); + expect(r[1]).toEqual('test2'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise reduce method should be in zone', (done) => { zone.run(() => { - BluebirdPromise - .reduce( - [1, 2], - (total: string, value: string) => { - return BluebirdPromise.resolve(total + value); - }) - .then((r: number) => { - expect(r).toBe(3); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBeTruthy(); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length) - .toBeTruthy(); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.reduce([1, 2], (total: string, value: string) => { + return BluebirdPromise.resolve(total + value); + }).then((r: number) => { + expect(r).toBe(3); + expect( + log.filter((item) => item === 'schedule bluebird task Promise.then').length, + ).toBeTruthy(); + expect( + log.filter((item) => item === 'invoke bluebird task Promise.then').length, + ).toBeTruthy(); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise filter method should be in zone', (done) => { zone.run(() => { - BluebirdPromise - .filter( - [1, 2, 3], - (value: number) => { - return value % 2 === 0 ? BluebirdPromise.resolve(true) : - BluebirdPromise.resolve(false); - }) - .then((r: number[]) => { - expect(r[0]).toBe(2); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.filter([1, 2, 3], (value: number) => { + return value % 2 === 0 ? BluebirdPromise.resolve(true) : BluebirdPromise.resolve(false); + }).then((r: number[]) => { + expect(r[0]).toBe(2); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise each method should be in zone', (done) => { zone.run(() => { const arr = [1, 2, 3]; - BluebirdPromise - .each( - BluebirdPromise.map(arr, (item: number) => BluebirdPromise.resolve(item)), - (r: number, idx: number) => { - expect(r).toBe(arr[idx]); - expect(Zone.current.name).toEqual('bluebird'); - }) - .then((r: any) => { - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBeTruthy(); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length) - .toBeTruthy(); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.each( + BluebirdPromise.map(arr, (item: number) => BluebirdPromise.resolve(item)), + (r: number, idx: number) => { + expect(r).toBe(arr[idx]); + expect(Zone.current.name).toEqual('bluebird'); + }, + ).then((r: any) => { + expect( + log.filter((item) => item === 'schedule bluebird task Promise.then').length, + ).toBeTruthy(); + expect( + log.filter((item) => item === 'invoke bluebird task Promise.then').length, + ).toBeTruthy(); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise mapSeries method should be in zone', (done) => { zone.run(() => { const arr = [1, 2, 3]; - BluebirdPromise - .mapSeries( - BluebirdPromise.map(arr, (item: number) => BluebirdPromise.resolve(item)), - (r: number, idx: number) => { - expect(r).toBe(arr[idx]); - expect(Zone.current.name).toEqual('bluebird'); - }) - .then((r: any) => { - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBeTruthy(); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length) - .toBeTruthy(); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); - ; + BluebirdPromise.mapSeries( + BluebirdPromise.map(arr, (item: number) => BluebirdPromise.resolve(item)), + (r: number, idx: number) => { + expect(r).toBe(arr[idx]); + expect(Zone.current.name).toEqual('bluebird'); + }, + ).then((r: any) => { + expect( + log.filter((item) => item === 'schedule bluebird task Promise.then').length, + ).toBeTruthy(); + expect( + log.filter((item) => item === 'invoke bluebird task Promise.then').length, + ).toBeTruthy(); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise race method should be in zone', (done) => { zone.run(() => { - BluebirdPromise.race([BluebirdPromise.resolve('test1'), BluebirdPromise.resolve('test2')]) - .then((r: string) => { - expect(r).toEqual('test1'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.race([ + BluebirdPromise.resolve('test1'), + BluebirdPromise.resolve('test2'), + ]).then((r: string) => { + expect(r).toEqual('test1'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); @@ -374,22 +360,20 @@ describe('bluebird promise', () => { const disposer = p.disposer(() => { p.leakObj = null; }); - BluebirdPromise - .using( - disposer, - (v: string) => { - p.leakObj.push(v); - }) - .then(() => { - expect(Zone.current.name).toEqual('bluebird'); - expect(p.leakObj).toBe(null); - // using will generate several promise inside bluebird - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBeTruthy(); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length) - .toBeTruthy(); - done(); - }); + BluebirdPromise.using(disposer, (v: string) => { + p.leakObj.push(v); + }).then(() => { + expect(Zone.current.name).toEqual('bluebird'); + expect(p.leakObj).toBe(null); + // using will generate several promise inside bluebird + expect( + log.filter((item) => item === 'schedule bluebird task Promise.then').length, + ).toBeTruthy(); + expect( + log.filter((item) => item === 'invoke bluebird task Promise.then').length, + ).toBeTruthy(); + done(); + }); }); }); @@ -405,8 +389,8 @@ describe('bluebird promise', () => { promiseFunc().then((r: string) => { expect(Zone.current.name).toEqual('bluebird'); expect(r).toBe('test'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length).toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); done(); }); }); @@ -428,17 +412,19 @@ describe('bluebird promise', () => { const promiseObj = BluebirdPromise.promisifyAll(obj); zone.run(() => { - BluebirdPromise.all([promiseObj.func1Async(), promiseObj.func2Async()]) - .then((r: string[]) => { - expect(Zone.current.name).toEqual('bluebird'); - expect(r[0]).toBe('test1'); - expect(r[1]).toBe('test2'); - // using will generate several promise inside - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - done(); - }); + BluebirdPromise.all([promiseObj.func1Async(), promiseObj.func2Async()]).then( + (r: string[]) => { + expect(Zone.current.name).toEqual('bluebird'); + expect(r[0]).toBe('test1'); + expect(r[1]).toBe('test2'); + // using will generate several promise inside + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe( + 1, + ); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + done(); + }, + ); }); }); @@ -453,8 +439,8 @@ describe('bluebird promise', () => { BluebirdPromise.fromCallback(resolver).then((r: string) => { expect(Zone.current.name).toEqual('bluebird'); expect(r).toBe('test'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length).toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); done(); }); }); @@ -472,13 +458,17 @@ describe('bluebird promise', () => { it('bluebird promise delay method should be in zone', (done) => { zone.run(() => { - BluebirdPromise.resolve('test').delay(10).then((r: string) => { - expect(Zone.current.name).toEqual('bluebird'); - expect(r).toBe('test'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length).toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - done(); - }); + BluebirdPromise.resolve('test') + .delay(10) + .then((r: string) => { + expect(Zone.current.name).toEqual('bluebird'); + expect(r).toBe('test'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe( + 1, + ); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + done(); + }); }); }); @@ -489,15 +479,16 @@ describe('bluebird promise', () => { resolve('test'); }, 10); }) - .timeout(100) - .then((r: string) => { - expect(Zone.current.name).toEqual('bluebird'); - expect(r).toBe('test'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - done(); - }); + .timeout(100) + .then((r: string) => { + expect(Zone.current.name).toEqual('bluebird'); + expect(r).toBe('test'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe( + 1, + ); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + done(); + }); }); }); @@ -509,10 +500,10 @@ describe('bluebird promise', () => { }, 0); }); p.tap(() => { - expect(Zone.current.name).toEqual('bluebird'); - }).then(() => { - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length).toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + }).then(() => { + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe(1); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); expect(Zone.current.name).toEqual('bluebird'); done(); }); @@ -521,104 +512,120 @@ describe('bluebird promise', () => { it('bluebird promise call method should be in zone', (done) => { zone.run(() => { - BluebirdPromise - .map( - ['test1', 'test2'], - (value: any) => { - return BluebirdPromise.resolve(value); - }) - .call( - 'shift', - (value: any) => { - return value; - }) - .then((r: string) => { - expect(r).toEqual('test1'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length) - .toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.map(['test1', 'test2'], (value: any) => { + return BluebirdPromise.resolve(value); + }) + .call('shift', (value: any) => { + return value; + }) + .then((r: string) => { + expect(r).toEqual('test1'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe( + 1, + ); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise get method should be in zone', (done) => { zone.run(() => { - BluebirdPromise.resolve(['test1', 'test2']).get(-1).then((r: string) => { - expect(r).toEqual('test2'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length).toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.resolve(['test1', 'test2']) + .get(-1) + .then((r: string) => { + expect(r).toEqual('test2'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe( + 1, + ); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise return method should be in zone', (done) => { zone.run(() => { - BluebirdPromise.resolve().return('test1').then((r: string) => { - expect(r).toEqual('test1'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length).toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.resolve() + .return('test1') + .then((r: string) => { + expect(r).toEqual('test1'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe( + 1, + ); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise throw method should be in zone', (done) => { zone.run(() => { - BluebirdPromise.resolve().throw('test1').catch((r: string) => { - expect(r).toEqual('test1'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length).toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.resolve() + .throw('test1') + .catch((r: string) => { + expect(r).toEqual('test1'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe( + 1, + ); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise catchReturn method should be in zone', (done) => { zone.run(() => { - BluebirdPromise.reject().catchReturn('test1').then((r: string) => { - expect(r).toEqual('test1'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length).toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.reject() + .catchReturn('test1') + .then((r: string) => { + expect(r).toEqual('test1'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe( + 1, + ); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise catchThrow method should be in zone', (done) => { zone.run(() => { - BluebirdPromise.reject().catchThrow('test1').catch((r: string) => { - expect(r).toEqual('test1'); - expect(log.filter(item => item === 'schedule bluebird task Promise.then').length).toBe(1); - expect(log.filter(item => item === 'invoke bluebird task Promise.then').length).toBe(1); - expect(Zone.current.name).toEqual('bluebird'); - done(); - }); + BluebirdPromise.reject() + .catchThrow('test1') + .catch((r: string) => { + expect(r).toEqual('test1'); + expect(log.filter((item) => item === 'schedule bluebird task Promise.then').length).toBe( + 1, + ); + expect(log.filter((item) => item === 'invoke bluebird task Promise.then').length).toBe(1); + expect(Zone.current.name).toEqual('bluebird'); + done(); + }); }); }); it('bluebird promise reflect method should be in zone', (done) => { zone.run(() => { const promises = [BluebirdPromise.resolve('test1'), BluebirdPromise.reject('test2')]; - BluebirdPromise - .all(promises.map(promise => { - return promise.reflect(); - })) - .each((r: any) => { - if (r.isFulfilled()) { - expect(r.value()).toEqual('test1'); - } else { - expect(r.reason()).toEqual('test2'); - done(); - } - expect(Zone.current.name).toEqual('bluebird'); - }); + BluebirdPromise.all( + promises.map((promise) => { + return promise.reflect(); + }), + ).each((r: any) => { + if (r.isFulfilled()) { + expect(r.value()).toEqual('test1'); + } else { + expect(r.reason()).toEqual('test2'); + done(); + } + expect(Zone.current.name).toEqual('bluebird'); + }); }); }); @@ -649,35 +656,36 @@ describe('bluebird promise', () => { expect(Zone.current.name).toEqual('zone_A'); resolve(1); }) - .then((r: any) => { - expect(r).toBe(1); - expect(Zone.current.name).toEqual('zone_A'); - return Promise.resolve(2); - }) - .then((r: any) => { - expect(r).toBe(2); - expect(Zone.current.name).toEqual('zone_A'); - }); + .then((r: any) => { + expect(r).toBe(1); + expect(Zone.current.name).toEqual('zone_A'); + return Promise.resolve(2); + }) + .then((r: any) => { + expect(r).toBe(2); + expect(Zone.current.name).toEqual('zone_A'); + }); }); Zone.current.fork({name: 'zone_B'}).run(() => { new BluebirdPromise((resolve: any, reject: any) => { expect(Zone.current.name).toEqual('zone_B'); reject(1); }) - .then( - () => { - fail('should not be here.'); - }, - (r: any) => { - expect(r).toBe(1); - expect(Zone.current.name).toEqual('zone_B'); - return Promise.resolve(2); - }) - .then((r: any) => { - expect(r).toBe(2); + .then( + () => { + fail('should not be here.'); + }, + (r: any) => { + expect(r).toBe(1); expect(Zone.current.name).toEqual('zone_B'); - done(); - }); + return Promise.resolve(2); + }, + ) + .then((r: any) => { + expect(r).toBe(2); + expect(Zone.current.name).toEqual('zone_B'); + done(); + }); }); }); @@ -685,22 +693,22 @@ describe('bluebird promise', () => { const logs: string[] = []; const zone = Zone.current.fork({ name: 'testErrorHandling', - onHandleError: function() { + onHandleError: function () { // should not get here logs.push('onHandleError'); return true; - } + }, }); zone.runGuarded(() => { return BluebirdPromise.resolve() - .then(() => { - throw new Error('test error'); - }) - .catch(() => { - expect(logs).toEqual([]); - done(); - }); + .then(() => { + throw new Error('test error'); + }) + .catch(() => { + expect(logs).toEqual([]); + done(); + }); }); }); @@ -708,22 +716,22 @@ describe('bluebird promise', () => { const logs: string[] = []; const zone = Zone.current.fork({ name: 'testErrorHandling', - onHandleError: function() { + onHandleError: function () { // should not get here logs.push('onHandleError'); return true; - } + }, }); zone.runGuarded(() => { return Promise.resolve() - .then(() => { - throw new Error('test error'); - }) - .catch(() => { - expect(logs).toEqual([]); - done(); - }); + .then(() => { + throw new Error('test error'); + }) + .catch(() => { + expect(logs).toEqual([]); + done(); + }); }); }); @@ -731,11 +739,11 @@ describe('bluebird promise', () => { const logs: string[] = []; const zone = Zone.current.fork({ name: 'testErrorHandling', - onHandleError: function() { + onHandleError: function () { // should not get here logs.push('onHandleError'); return true; - } + }, }); zone.runGuarded(() => { @@ -750,11 +758,11 @@ describe('bluebird promise', () => { const logs: string[] = []; const zone = Zone.current.fork({ name: 'testErrorHandling', - onHandleError: function() { + onHandleError: function () { // should not get here logs.push('onHandleError'); return true; - } + }, }); zone.runGuarded(() => { @@ -768,10 +776,10 @@ describe('bluebird promise', () => { xit('should trigger onHandleError when unhandledRejection', (done: DoneFn) => { const zone = Zone.current.fork({ name: 'testErrorHandling', - onHandleError: function() { + onHandleError: function () { setTimeout(done, 100); return true; - } + }, }); zone.runGuarded(() => { @@ -782,10 +790,10 @@ describe('bluebird promise', () => { xit('should trigger onHandleError when unhandledRejection in chained Promise', (done: DoneFn) => { const zone = Zone.current.fork({ name: 'testErrorHandling', - onHandleError: function() { + onHandleError: function () { setTimeout(done, 100); return true; - } + }, }); zone.runGuarded(() => { @@ -795,42 +803,41 @@ describe('bluebird promise', () => { }); }); - xit('should not trigger unhandledrejection if zone.onHandleError return false', - (done: DoneFn) => { - const listener = function() { - fail('should not be here'); - }; + xit('should not trigger unhandledrejection if zone.onHandleError return false', (done: DoneFn) => { + const listener = function () { + fail('should not be here'); + }; - if (typeof window !== 'undefined') { - window.addEventListener('unhandledrejection', listener); - } else if (typeof process !== 'undefined') { - process.on('unhandledRejection', listener); - } + if (typeof window !== 'undefined') { + window.addEventListener('unhandledrejection', listener); + } else if (typeof process !== 'undefined') { + process.on('unhandledRejection', listener); + } - const zone = Zone.current.fork({ - name: 'testErrorHandling', - onHandleError: function() { - setTimeout(() => { - if (typeof window !== 'undefined') { - window.removeEventListener('unhandledrejection', listener); - } else if (typeof process !== 'undefined') { - process.removeListener('unhandledRejection', listener); - } - done(); - }, 500); - return false; + const zone = Zone.current.fork({ + name: 'testErrorHandling', + onHandleError: function () { + setTimeout(() => { + if (typeof window !== 'undefined') { + window.removeEventListener('unhandledrejection', listener); + } else if (typeof process !== 'undefined') { + process.removeListener('unhandledRejection', listener); } - }); + done(); + }, 500); + return false; + }, + }); - zone.runGuarded(() => { - return Promise.resolve().then(() => { - throw new Error('test'); - }); - }); + zone.runGuarded(() => { + return Promise.resolve().then(() => { + throw new Error('test'); }); + }); + }); xit('should trigger unhandledrejection if zone.onHandleError return true', (done: DoneFn) => { - const listener = function(event: any) { + const listener = function (event: any) { if (typeof window !== 'undefined') { expect(event.detail.reason.message).toEqual('test'); } else if (typeof process !== 'undefined') { @@ -851,9 +858,9 @@ describe('bluebird promise', () => { const zone = Zone.current.fork({ name: 'testErrorHandling', - onHandleError: function() { + onHandleError: function () { return true; - } + }, }); zone.runGuarded(() => { diff --git a/packages/zone.js/test/extra/cordova.spec.ts b/packages/zone.js/test/extra/cordova.spec.ts index 52cfd65ccd7c5..21d1a1f047dc2 100644 --- a/packages/zone.js/test/extra/cordova.spec.ts +++ b/packages/zone.js/test/extra/cordova.spec.ts @@ -17,23 +17,29 @@ describe('cordova test', () => { zone.run(() => { cordova.exec( - () => { - expect(Zone.current.name).toEqual('cordova'); - }, - () => { - fail('should not fail'); - }, - 'service', 'successAction', ['arg0', 'arg1']); + () => { + expect(Zone.current.name).toEqual('cordova'); + }, + () => { + fail('should not fail'); + }, + 'service', + 'successAction', + ['arg0', 'arg1'], + ); cordova.exec( - () => { - fail('should not success'); - }, - () => { - expect(Zone.current.name).toEqual('cordova'); - done(); - }, - 'service', 'failAction', ['arg0', 'arg1']); + () => { + fail('should not success'); + }, + () => { + expect(Zone.current.name).toEqual('cordova'); + done(); + }, + 'service', + 'failAction', + ['arg0', 'arg1'], + ); }); }); }); diff --git a/packages/zone.js/test/extra/electron.js b/packages/zone.js/test/extra/electron.js index f5a43912ece92..8588fd526b0d7 100644 --- a/packages/zone.js/test/extra/electron.js +++ b/packages/zone.js/test/extra/electron.js @@ -11,37 +11,37 @@ var nativeTimeout = setTimeout; require('./zone-mix.umd'); mockRequire('electron', { desktopCapturer: { - getSources: function(callback) { + getSources: function (callback) { nativeTimeout(callback); - } + }, }, shell: { - openExternal: function(callback) { + openExternal: function (callback) { nativeTimeout(callback); - } + }, }, ipcRenderer: { - on: function(callback) { + on: function (callback) { nativeTimeout(callback); - } + }, }, }); require('./zone-patch-electron.umd'); var electron = require('electron'); var zone = Zone.current.fork({name: 'zone'}); -zone.run(function() { - electron.desktopCapturer.getSources(function() { +zone.run(function () { + electron.desktopCapturer.getSources(function () { if (Zone.current.name !== 'zone') { process.exit(1); } }); - electron.shell.openExternal(function() { + electron.shell.openExternal(function () { console.log('shell', Zone.current.name); if (Zone.current.name !== 'zone') { process.exit(1); } }); - electron.ipcRenderer.on(function() { + electron.ipcRenderer.on(function () { if (Zone.current.name !== 'zone') { process.exit(1); } diff --git a/packages/zone.js/test/jasmine-patch.spec.ts b/packages/zone.js/test/jasmine-patch.spec.ts index 804c195d8003c..c4d4e43f3f3ba 100644 --- a/packages/zone.js/test/jasmine-patch.spec.ts +++ b/packages/zone.js/test/jasmine-patch.spec.ts @@ -22,9 +22,9 @@ ifEnvSupports(supportJasmineSpec, () => { describe('jasmine', () => { let throwOnAsync = false; - let beforeEachZone: Zone|null = null; - let beforeAllZone: Zone|null = null; - let itZone: Zone|null = null; + let beforeEachZone: Zone | null = null; + let beforeAllZone: Zone | null = null; + let itZone: Zone | null = null; const syncZone = Zone.current; try { Zone.current.scheduleMicroTask('dontallow', (): any => null); @@ -32,9 +32,9 @@ ifEnvSupports(supportJasmineSpec, () => { throwOnAsync = true; } - beforeAll(() => beforeAllZone = Zone.current); + beforeAll(() => (beforeAllZone = Zone.current)); - beforeEach(() => beforeEachZone = Zone.current); + beforeEach(() => (beforeEachZone = Zone.current)); it('should throw on async in describe', () => { expect(throwOnAsync).toBe(true); diff --git a/packages/zone.js/test/jest/jest-zone-patch-fake-timer.js b/packages/zone.js/test/jest/jest-zone-patch-fake-timer.js index e69790b542ac0..a9bb92009751f 100644 --- a/packages/zone.js/test/jest/jest-zone-patch-fake-timer.js +++ b/packages/zone.js/test/jest/jest-zone-patch-fake-timer.js @@ -1,4 +1,4 @@ -const exportFakeTimersToSandboxGlobal = function(jestEnv) { +const exportFakeTimersToSandboxGlobal = function (jestEnv) { jestEnv.global.legacyFakeTimers = jestEnv.fakeTimers; jestEnv.global.modernFakeTimers = jestEnv.fakeTimersModern; }; diff --git a/packages/zone.js/test/jest/jest.config.js b/packages/zone.js/test/jest/jest.config.js index 265fc1e021d72..4c29c16641bf8 100644 --- a/packages/zone.js/test/jest/jest.config.js +++ b/packages/zone.js/test/jest/jest.config.js @@ -1,4 +1,4 @@ module.exports = { setupFilesAfterEnv: ['./jest-zone.js'], - testEnvironment: './zone-jsdom-environment.js' + testEnvironment: './zone-jsdom-environment.js', }; diff --git a/packages/zone.js/test/jest/jest.node.config.js b/packages/zone.js/test/jest/jest.node.config.js index f4ea114aaaba3..e0bbf957751b0 100644 --- a/packages/zone.js/test/jest/jest.node.config.js +++ b/packages/zone.js/test/jest/jest.node.config.js @@ -1,4 +1,4 @@ module.exports = { setupFilesAfterEnv: ['./jest-zone.js'], - testEnvironment: './zone-node-environment.js' + testEnvironment: './zone-node-environment.js', }; diff --git a/packages/zone.js/test/jest/jest.spec.js b/packages/zone.js/test/jest/jest.spec.js index bb9fbfd60557b..7a888fc69b111 100644 --- a/packages/zone.js/test/jest/jest.spec.js +++ b/packages/zone.js/test/jest/jest.spec.js @@ -113,7 +113,7 @@ function disableJestPatch() { global[Zone.__symbol__('fakeAsyncDisablePatchingFakeTimer')] = false; } const {resetFakeAsyncZone, flushMicrotasks, discardPeriodicTasks, tick, flush, fakeAsync} = - Zone[Zone.__symbol__('fakeAsyncTest')]; + Zone[Zone.__symbol__('fakeAsyncTest')]; describe('jest modern fakeTimers with zone.js fakeAsync', () => { beforeEach(() => { @@ -134,8 +134,7 @@ describe('jest modern fakeTimers with zone.js fakeAsync', () => { let d = fakeAsyncZoneSpec.getRealSystemTime(); jest.setSystemTime(d); expect(Date.now()).toEqual(d); - for (let i = 0; i < 100000; i++) { - } + for (let i = 0; i < 100000; i++) {} expect(fakeAsyncZoneSpec.getRealSystemTime()).not.toEqual(d); d = fakeAsyncZoneSpec.getRealSystemTime(); let timeoutTriggered = false; @@ -379,8 +378,7 @@ describe('jest fakeTimers inside test should call native delegate', () => { expect(fakeAsyncZoneSpec).toBeFalsy(); const d = Date.now(); jest.setSystemTime(d); - for (let i = 0; i < 100000; i++) { - } + for (let i = 0; i < 100000; i++) {} expect(jest.getRealSystemTime()).not.toEqual(d); jest.useRealTimers(); }); diff --git a/packages/zone.js/test/main.ts b/packages/zone.js/test/main.ts index c5cf9c9f78138..80e318c12a756 100644 --- a/packages/zone.js/test/main.ts +++ b/packages/zone.js/test/main.ts @@ -9,18 +9,19 @@ /// declare const __karma__: { - loaded: Function, - start: Function, - error: Function, + loaded: Function; + start: Function; + error: Function; }; -__karma__.loaded = function() {}; +__karma__.loaded = function () {}; let entryPoint = 'browser_entry_point'; if (typeof __karma__ !== 'undefined') { - (window as any)['__Zone_Error_ZoneJsInternalStackFrames_policy'] = - (__karma__ as any).config.errorpolicy; + (window as any)['__Zone_Error_ZoneJsInternalStackFrames_policy'] = ( + __karma__ as any + ).config.errorpolicy; if ((__karma__ as any).config.entrypoint) { entryPoint = (__karma__ as any).config.entrypoint; } @@ -39,7 +40,7 @@ System.config({ 'rxjs/operators': 'base/npm/node_modules/rxjs/operators/index', 'core-js/features/set': 'base/npm/node_modules/core-js/es6/set', 'core-js/features/map': 'base/npm/node_modules/core-js/es6/map', - 'es6-promise': 'base/npm/node_modules/es6-promise/dist/es6-promise' + 'es6-promise': 'base/npm/node_modules/es6-promise/dist/es6-promise', }, }); @@ -49,30 +50,33 @@ if ((window as any)[(Zone as any).__symbol__('setTimeout')]) { } else { // this means that Zone has not patched the browser yet, which means we must be running in // build mode and need to load the browser patch. - browserPatchedPromise = - System.import('/base/angular/packages/zone.js/test/browser-zone-setup').then(() => { - let testFrameworkPatch = typeof (window as any).Mocha !== 'undefined' ? - '/base/angular/packages/zone.js/lib/mocha/mocha' : - '/base/angular/packages/zone.js/lib/jasmine/jasmine'; - return System.import(testFrameworkPatch); - }); + browserPatchedPromise = System.import( + '/base/angular/packages/zone.js/test/browser-zone-setup', + ).then(() => { + let testFrameworkPatch = + typeof (window as any).Mocha !== 'undefined' + ? '/base/angular/packages/zone.js/lib/mocha/mocha' + : '/base/angular/packages/zone.js/lib/jasmine/jasmine'; + return System.import(testFrameworkPatch); + }); } browserPatchedPromise.then(() => { - let testFrameworkPatch = typeof (window as any).Mocha !== 'undefined' ? - '/base/angular/packages/zone.js/test/test-env-setup-mocha' : - '/base/angular/packages/zone.js/test/test-env-setup-jasmine'; + let testFrameworkPatch = + typeof (window as any).Mocha !== 'undefined' + ? '/base/angular/packages/zone.js/test/test-env-setup-mocha' + : '/base/angular/packages/zone.js/test/test-env-setup-jasmine'; // Setup test environment System.import(testFrameworkPatch).then(() => { System.import('/base/angular/packages/zone.js/lib/common/error-rewrite').then(() => { - System.import(`/base/angular/packages/zone.js/test/${entryPoint}`) - .then( - () => { - __karma__.start(); - }, - (error: any) => { - console.error(error.stack || error); - }); + System.import(`/base/angular/packages/zone.js/test/${entryPoint}`).then( + () => { + __karma__.start(); + }, + (error: any) => { + console.error(error.stack || error); + }, + ); }); }); }); diff --git a/packages/zone.js/test/mocha-patch.spec.ts b/packages/zone.js/test/mocha-patch.spec.ts index 54f759a3bb8f4..4c24e5185fc92 100644 --- a/packages/zone.js/test/mocha-patch.spec.ts +++ b/packages/zone.js/test/mocha-patch.spec.ts @@ -21,13 +21,13 @@ declare function after(fn: () => void): void; import {ifEnvSupports} from './test-util'; -ifEnvSupports('Mocha', function() { +ifEnvSupports('Mocha', function () { describe('Mocha BDD-style', () => { let throwOnAsync = false; - let beforeEachZone: Zone|null = null; - let itZone: Zone|null = null; + let beforeEachZone: Zone | null = null; + let itZone: Zone | null = null; const syncZone = Zone.current; - let beforeZone: Zone|null = null; + let beforeZone: Zone | null = null; before(() => { beforeZone = Zone.current; @@ -39,7 +39,7 @@ ifEnvSupports('Mocha', function() { throwOnAsync = true; } - beforeEach(() => beforeEachZone = Zone.current); + beforeEach(() => (beforeEachZone = Zone.current)); it('should throw on async in describe', () => { expect(Zone.currentTask).toBeTruthy(); @@ -67,9 +67,9 @@ ifEnvSupports('Mocha', function() { }); suite('Mocha TDD-style', () => { - let testZone: Zone|null = null; - let beforeEachZone: Zone|null = null; - let suiteSetupZone: Zone|null = null; + let testZone: Zone | null = null; + let beforeEachZone: Zone | null = null; + let suiteSetupZone: Zone | null = null; suiteSetup(() => { suiteSetupZone = Zone.current; diff --git a/packages/zone.js/test/node/Error.spec.ts b/packages/zone.js/test/node/Error.spec.ts index d981e177b45d4..cb86bd1ffbb86 100644 --- a/packages/zone.js/test/node/Error.spec.ts +++ b/packages/zone.js/test/node/Error.spec.ts @@ -23,7 +23,7 @@ describe('ZoneAwareError', () => { it('should support prepareStackTrace', () => { const originalPrepareStackTrace = (Error).prepareStackTrace; - (Error).prepareStackTrace = function(error: Error, stack: string) { + (Error).prepareStackTrace = function (error: Error, stack: string) { return stack; }; let obj: any = new Object(); @@ -34,13 +34,13 @@ describe('ZoneAwareError', () => { it('should not add additional stacktrace from Zone when use prepareStackTrace', () => { const originalPrepareStackTrace = (Error).prepareStackTrace; - (Error).prepareStackTrace = function(error: Error, stack: string) { + (Error).prepareStackTrace = function (error: Error, stack: string) { return stack; }; let obj: any = new Object(); Error.captureStackTrace(obj); expect(obj.stack.length).not.toBe(0); - obj.stack.forEach(function(st: any) { + obj.stack.forEach(function (st: any) { expect(st.getFunctionName()).not.toEqual('zoneCaptureStackTrace'); }); (Error).prepareStackTrace = originalPrepareStackTrace; diff --git a/packages/zone.js/test/node/console.spec.ts b/packages/zone.js/test/node/console.spec.ts index 809eb63dee85b..b179de829f604 100644 --- a/packages/zone.js/test/node/console.spec.ts +++ b/packages/zone.js/test/node/console.spec.ts @@ -9,11 +9,15 @@ describe('node console', () => { const log: string[] = []; const zone = Zone.current.fork({ name: 'console', - onScheduleTask: function( - delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) { + onScheduleTask: function ( + delegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ) { log.push(task.source); return delegate.scheduleTask(targetZone, task); - } + }, }); beforeEach(() => { @@ -29,8 +33,7 @@ describe('node console', () => { console.trace('test'); try { console.assert(false, 'test'); - } catch (error) { - } + } catch (error) {} console.dir('.'); console.time('start'); console.timeEnd('start'); diff --git a/packages/zone.js/test/node/crypto.spec.ts b/packages/zone.js/test/node/crypto.spec.ts index 6834cab380bc6..b98f2cca2d3ba 100644 --- a/packages/zone.js/test/node/crypto.spec.ts +++ b/packages/zone.js/test/node/crypto.spec.ts @@ -10,8 +10,7 @@ describe('crypto test', () => { try { crypto = require('crypto'); - } catch (err) { - } + } catch (err) {} it('crypto randomBytes method should be patched as tasks', (done) => { if (!crypto) { @@ -20,10 +19,14 @@ describe('crypto test', () => { } const zoneASpec = { name: 'A', - onScheduleTask: (delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - Task => { - return delegate.scheduleTask(targetZone, task); - } + onScheduleTask: ( + delegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): Task => { + return delegate.scheduleTask(targetZone, task); + }, }; const zoneA = Zone.current.fork(zoneASpec); spyOn(zoneASpec, 'onScheduleTask').and.callThrough(); @@ -45,10 +48,14 @@ describe('crypto test', () => { } const zoneASpec = { name: 'A', - onScheduleTask: (delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - Task => { - return delegate.scheduleTask(targetZone, task); - } + onScheduleTask: ( + delegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): Task => { + return delegate.scheduleTask(targetZone, task); + }, }; const zoneA = Zone.current.fork(zoneASpec); spyOn(zoneASpec, 'onScheduleTask').and.callThrough(); @@ -56,9 +63,9 @@ describe('crypto test', () => { crypto.pbkdf2('secret', 'salt', 100000, 512, 'sha512', (err: Error, key: any) => { expect(err).toBeFalsy(); expect(zoneASpec.onScheduleTask).toHaveBeenCalled(); - expect(key.toString('hex')) - .toEqual( - '3745e482c6e0ade35da10139e797157f4a5da669dad7d5da88ef87e47471cc47ed941c7ad618e827304f083f8707f12b7cfdd5f489b782f10cc269e3c08d59ae04919ee902c99dba309cde75569fbe8e6d5c341d6f2576f6618c589e77911a261ee964e242797e64aeca9a134de5ced37fe2521d35d87303edb55a844c8cf11e3b42b18dbd7add0739ea9b172dc3810f911396fa3956f499415db35b79488d74926cdc0c15c3910bf2e4918f5a8efd7de3d4c314bace50c7a95150339eccd32dda2e15d961ea2c91eddd8b03110135a72b3562f189c2d15568854f9a1844cfa62fb77214f2810a2277fd21be95a794cde78e0fe5267a2c1b0894c7729fc4be378156aeb1cff8a215bb4df12312ba676fe2f270dfc3e2b54d8f9c74dfb531530042a09b226fafbcef45368a1ec75f9224a80f2280f75258ff74a2b9a864d857ede49af6a23af837a1f502a6c32e3537402280bef200d847d8fee42649e6d9a00df952ab2fbefc84ba8927f73137fdfbea81f86088edd4cf329edf3f6982429797143cbd43128777c2da269fadd55d18c7921308c7ad7a5bb85ef8d614e2e8461ea3b7fc2edcf72b85da6828a4198c46000953afb1f3a19ecac0df0d660848a0f89ed3d0e0a82115347c9918bdf16fad479c1de16a6b9798437622acff245e6cf80c9ee9d56cada8523ebb6ff348c73c836e5828761f8dda1dd5ab1633caa39b34'); + expect(key.toString('hex')).toEqual( + '3745e482c6e0ade35da10139e797157f4a5da669dad7d5da88ef87e47471cc47ed941c7ad618e827304f083f8707f12b7cfdd5f489b782f10cc269e3c08d59ae04919ee902c99dba309cde75569fbe8e6d5c341d6f2576f6618c589e77911a261ee964e242797e64aeca9a134de5ced37fe2521d35d87303edb55a844c8cf11e3b42b18dbd7add0739ea9b172dc3810f911396fa3956f499415db35b79488d74926cdc0c15c3910bf2e4918f5a8efd7de3d4c314bace50c7a95150339eccd32dda2e15d961ea2c91eddd8b03110135a72b3562f189c2d15568854f9a1844cfa62fb77214f2810a2277fd21be95a794cde78e0fe5267a2c1b0894c7729fc4be378156aeb1cff8a215bb4df12312ba676fe2f270dfc3e2b54d8f9c74dfb531530042a09b226fafbcef45368a1ec75f9224a80f2280f75258ff74a2b9a864d857ede49af6a23af837a1f502a6c32e3537402280bef200d847d8fee42649e6d9a00df952ab2fbefc84ba8927f73137fdfbea81f86088edd4cf329edf3f6982429797143cbd43128777c2da269fadd55d18c7921308c7ad7a5bb85ef8d614e2e8461ea3b7fc2edcf72b85da6828a4198c46000953afb1f3a19ecac0df0d660848a0f89ed3d0e0a82115347c9918bdf16fad479c1de16a6b9798437622acff245e6cf80c9ee9d56cada8523ebb6ff348c73c836e5828761f8dda1dd5ab1633caa39b34', + ); expect(Zone.current.name).toEqual('A'); done(); }); diff --git a/packages/zone.js/test/node/events.spec.ts b/packages/zone.js/test/node/events.spec.ts index 9cab424169c5a..ec8b768312325 100644 --- a/packages/zone.js/test/node/events.spec.ts +++ b/packages/zone.js/test/node/events.spec.ts @@ -9,8 +9,12 @@ import {EventEmitter} from 'events'; describe('nodejs EventEmitter', () => { - let zone: Zone, zoneA: Zone, zoneB: Zone, emitter: EventEmitter, expectZoneACount: number, - zoneResults: string[]; + let zone: Zone, + zoneA: Zone, + zoneB: Zone, + emitter: EventEmitter, + expectZoneACount: number, + zoneResults: string[]; beforeEach(() => { zone = Zone.current; zoneA = zone.fork({name: 'A'}); @@ -158,10 +162,10 @@ describe('nodejs EventEmitter', () => { }); it('should trigger removeListener when remove listener', () => { zoneA.run(() => { - emitter.on('removeListener', function(type: string, handler: any) { + emitter.on('removeListener', function (type: string, handler: any) { zoneResults.push('remove' + type); }); - emitter.on('newListener', function(type: string, handler: any) { + emitter.on('newListener', function (type: string, handler: any) { zoneResults.push('new' + type); }); emitter.on('test', shouldNotRun); @@ -171,7 +175,7 @@ describe('nodejs EventEmitter', () => { }); it('should trigger removeListener when remove all listeners with eventname ', () => { zoneA.run(() => { - emitter.on('removeListener', function(type: string, handler: any) { + emitter.on('removeListener', function (type: string, handler: any) { zoneResults.push('remove' + type); }); emitter.on('test', shouldNotRun); @@ -183,7 +187,7 @@ describe('nodejs EventEmitter', () => { }); it('should trigger removeListener when remove all listeners without eventname', () => { zoneA.run(() => { - emitter.on('removeListener', function(type: string, handler: any) { + emitter.on('removeListener', function (type: string, handler: any) { zoneResults.push('remove' + type); }); emitter.on('test', shouldNotRun); @@ -198,7 +202,7 @@ describe('nodejs EventEmitter', () => { it('should not enter endless loop when register uncaughtException to process', () => { require('domain'); zoneA.run(() => { - process.on('uncaughtException', function() {}); + process.on('uncaughtException', function () {}); }); }); it('should be able to addEventListener with symbol eventName', () => { diff --git a/packages/zone.js/test/node/fs.spec.ts b/packages/zone.js/test/node/fs.spec.ts index 0830e574b14ea..8768652fc0c0c 100644 --- a/packages/zone.js/test/node/fs.spec.ts +++ b/packages/zone.js/test/node/fs.spec.ts @@ -6,7 +6,21 @@ * found in the LICENSE file at https://angular.io/license */ -import {closeSync, exists, fstatSync, openSync, read, realpath, unlink, unlinkSync, unwatchFile, watch, watchFile, write, writeFile} from 'fs'; +import { + closeSync, + exists, + fstatSync, + openSync, + read, + realpath, + unlink, + unlinkSync, + unwatchFile, + watch, + watchFile, + write, + writeFile, +} from 'fs'; import url from 'url'; import util from 'util'; @@ -27,10 +41,14 @@ describe('nodejs file system', () => { it('has patched exists as macroTask', (done) => { const zoneASpec = { name: 'A', - onScheduleTask: (delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - Task => { - return delegate.scheduleTask(targetZone, task); - } + onScheduleTask: ( + delegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): Task => { + return delegate.scheduleTask(targetZone, task); + }, }; const zoneA = Zone.current.fork(zoneASpec); spyOn(zoneASpec, 'onScheduleTask').and.callThrough(); @@ -45,10 +63,14 @@ describe('nodejs file system', () => { it('has patched realpath as macroTask', (done) => { const testZoneSpec = { name: 'test', - onScheduleTask: (delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - Task => { - return delegate.scheduleTask(targetZone, task); - } + onScheduleTask: ( + delegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): Task => { + return delegate.scheduleTask(targetZone, task); + }, }; const testZone = Zone.current.fork(testZoneSpec); spyOn(testZoneSpec, 'onScheduleTask').and.callThrough(); @@ -70,10 +92,14 @@ describe('nodejs file system', () => { xit('has patched realpath.native as macroTask', (done) => { const testZoneSpec = { name: 'test', - onScheduleTask: (delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - Task => { - return delegate.scheduleTask(targetZone, task); - } + onScheduleTask: ( + delegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): Task => { + return delegate.scheduleTask(targetZone, task); + }, }; const testZone = Zone.current.fork(testZoneSpec); spyOn(testZoneSpec, 'onScheduleTask').and.callThrough(); @@ -90,10 +116,14 @@ describe('nodejs file system', () => { describe('watcher related methods test', () => { const zoneASpec = { name: 'A', - onScheduleTask: (delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - Task => { - return delegate.scheduleTask(targetZone, task); - } + onScheduleTask: ( + delegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): Task => { + return delegate.scheduleTask(targetZone, task); + }, }; it('fs.watch has been patched as eventTask', (done) => { @@ -141,41 +171,41 @@ describe('nodejs file system', () => { describe('util.promisify', () => { it('fs.exists should work with util.promisify', (done: DoneFn) => { const promisifyExists = util.promisify(exists); - promisifyExists(currentFile) - .then( - r => { - expect(r).toBe(true); - done(); - }, - err => { - fail(`should not be here with error: ${err}`); - }); + promisifyExists(currentFile).then( + (r) => { + expect(r).toBe(true); + done(); + }, + (err) => { + fail(`should not be here with error: ${err}`); + }, + ); }); it('fs.realpath should work with util.promisify', (done: DoneFn) => { const promisifyRealpath = util.promisify(realpath); - promisifyRealpath(currentFile) - .then( - r => { - expect(r).toBeDefined(); - done(); - }, - err => { - fail(`should not be here with error: ${err}`); - }); + promisifyRealpath(currentFile).then( + (r) => { + expect(r).toBeDefined(); + done(); + }, + (err) => { + fail(`should not be here with error: ${err}`); + }, + ); }); it('fs.realpath.native should work with util.promisify', (done: DoneFn) => { const promisifyRealpathNative = util.promisify(realpath.native); - promisifyRealpathNative(currentFile) - .then( - r => { - expect(r).toBeDefined(); - done(); - }, - err => { - fail(`should not be here with error: ${err}`); - }); + promisifyRealpathNative(currentFile).then( + (r) => { + expect(r).toBeDefined(); + done(); + }, + (err) => { + fail(`should not be here with error: ${err}`); + }, + ); }); it('fs.read should work with util.promisify', (done: DoneFn) => { @@ -187,17 +217,17 @@ describe('util.promisify', () => { const buffer = new Buffer(bufferSize); let bytesRead = 0; // fd, buffer, offset, length, position, callback - promisifyRead(fd, buffer, bytesRead, chunkSize, bytesRead) - .then( - (value) => { - expect(value.bytesRead).toBe(chunkSize); - closeSync(fd); - done(); - }, - err => { - closeSync(fd); - fail(`should not be here with error: ${err}.`); - }); + promisifyRead(fd, buffer, bytesRead, chunkSize, bytesRead).then( + (value) => { + expect(value.bytesRead).toBe(chunkSize); + closeSync(fd); + done(); + }, + (err) => { + closeSync(fd); + fail(`should not be here with error: ${err}.`); + }, + ); }); it('fs.write should work with util.promisify', (done: DoneFn) => { @@ -211,18 +241,18 @@ describe('util.promisify', () => { buffer[i] = 0; } // fd, buffer, offset, length, position, callback - promisifyWrite(fd, buffer, 0, chunkSize, 0) - .then( - (value) => { - expect(value.bytesWritten).toBe(chunkSize); - closeSync(fd); - unlinkSync(dest); - done(); - }, - err => { - closeSync(fd); - unlinkSync(dest); - fail(`should not be here with error: ${err}.`); - }); + promisifyWrite(fd, buffer, 0, chunkSize, 0).then( + (value) => { + expect(value.bytesWritten).toBe(chunkSize); + closeSync(fd); + unlinkSync(dest); + done(); + }, + (err) => { + closeSync(fd); + unlinkSync(dest); + fail(`should not be here with error: ${err}.`); + }, + ); }); }); diff --git a/packages/zone.js/test/node/http.spec.ts b/packages/zone.js/test/node/http.spec.ts index 848bf3957a08f..1c24dc37795e7 100644 --- a/packages/zone.js/test/node/http.spec.ts +++ b/packages/zone.js/test/node/http.spec.ts @@ -15,22 +15,28 @@ describe('http test', () => { server.listen(9999, () => { const zoneASpec = { name: 'A', - onScheduleTask: (delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - Task => { - return delegate.scheduleTask(targetZone, task); - } + onScheduleTask: ( + delegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): Task => { + return delegate.scheduleTask(targetZone, task); + }, }; const zoneA = Zone.current.fork(zoneASpec); spyOn(zoneASpec, 'onScheduleTask').and.callThrough(); zoneA.run(() => { - const req = - http.request({hostname: 'localhost', port: '9999', method: 'GET'}, (res: any) => { - expect(Zone.current.name).toEqual('A'); - expect(zoneASpec.onScheduleTask).toHaveBeenCalled(); - server.close(() => { - done(); - }); + const req = http.request( + {hostname: 'localhost', port: '9999', method: 'GET'}, + (res: any) => { + expect(Zone.current.name).toEqual('A'); + expect(zoneASpec.onScheduleTask).toHaveBeenCalled(); + server.close(() => { + done(); }); + }, + ); req.end(); }); }); diff --git a/packages/zone.js/test/node/process.spec.ts b/packages/zone.js/test/node/process.spec.ts index 4324ca798b332..30a119489d3bd 100644 --- a/packages/zone.js/test/node/process.spec.ts +++ b/packages/zone.js/test/node/process.spec.ts @@ -15,7 +15,7 @@ describe('process related test', () => { result = []; }); it('process.nextTick callback should in zone', (done) => { - zoneA.run(function() { + zoneA.run(function () { process.nextTick(() => { expect(Zone.current.name).toEqual('zoneA'); done(); @@ -23,7 +23,7 @@ describe('process related test', () => { }); }); it('process.nextTick should be executed before macroTask and promise', (done) => { - zoneA.run(function() { + zoneA.run(function () { setTimeout(() => { result.push('timeout'); }, 0); @@ -40,17 +40,25 @@ describe('process related test', () => { let zoneTick = Zone.current.fork({ name: 'zoneTick', onScheduleTask: ( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): - Task => { - result.push({callback: 'scheduleTask', targetZone: targetZone.name, task: task.source}); - return parentZoneDelegate.scheduleTask(targetZone, task); - }, - onInvokeTask: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, - applyThis?: any, applyArgs?: any): any => { - result.push({callback: 'invokeTask', targetZone: targetZone.name, task: task.source}); - return parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs); - } + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + ): Task => { + result.push({callback: 'scheduleTask', targetZone: targetZone.name, task: task.source}); + return parentZoneDelegate.scheduleTask(targetZone, task); + }, + onInvokeTask: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + task: Task, + applyThis?: any, + applyArgs?: any, + ): any => { + result.push({callback: 'invokeTask', targetZone: targetZone.name, task: task.source}); + return parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs); + }, }); zoneTick.run(() => { process.nextTick(() => { @@ -59,21 +67,27 @@ describe('process related test', () => { }); setTimeout(() => { expect(result.length).toBe(3); - expect(result[0]).toEqual( - {callback: 'scheduleTask', targetZone: 'zoneTick', task: 'process.nextTick'}); - expect(result[1]).toEqual( - {callback: 'invokeTask', targetZone: 'zoneTick', task: 'process.nextTick'}); + expect(result[0]).toEqual({ + callback: 'scheduleTask', + targetZone: 'zoneTick', + task: 'process.nextTick', + }); + expect(result[1]).toEqual({ + callback: 'invokeTask', + targetZone: 'zoneTick', + task: 'process.nextTick', + }); done(); }); }); - it('should support process.on(unhandledRejection)', async function() { + it('should support process.on(unhandledRejection)', async function () { return await jasmine.spyOnGlobalErrorsAsync(async () => { const hookSpy = jasmine.createSpy('hook'); let p: any = null; (Zone as any)[zoneSymbol('ignoreConsoleErrorUncaughtError')] = true; - Zone.current.fork({name: 'promise'}).run(function() { - const listener = function(reason: any, promise: any) { + Zone.current.fork({name: 'promise'}).run(function () { + const listener = function (reason: any, promise: any) { hookSpy(promise, reason.message); process.removeListener('unhandledRejection', listener); }; @@ -82,8 +96,8 @@ describe('process related test', () => { throw new Error('promise error'); }); }); - return new Promise(res => { - setTimeout(function() { + return new Promise((res) => { + setTimeout(function () { expect(hookSpy).toHaveBeenCalledWith(p, 'promise error'); res(); }); @@ -91,16 +105,16 @@ describe('process related test', () => { }); }); - it('should support process.on(rejectionHandled)', async function() { + it('should support process.on(rejectionHandled)', async function () { return await jasmine.spyOnGlobalErrorsAsync(async () => { let p: any = null; (Zone as any)[zoneSymbol('ignoreConsoleErrorUncaughtError')] = true; let r: any = null; - let p1: any = new Promise(res => { + let p1: any = new Promise((res) => { r = res; }); - Zone.current.fork({name: 'promise'}).run(function() { - const listener = function(promise: any) { + Zone.current.fork({name: 'promise'}).run(function () { + const listener = function (promise: any) { expect(promise).toEqual(p); process.removeListener('rejectionHandled', listener); r(); @@ -110,24 +124,24 @@ describe('process related test', () => { throw new Error('promise error'); }); }); - setTimeout(function() { + setTimeout(function () { p.catch((reason: any) => {}); }); return p1; }); }); - it('should support multiple process.on(unhandledRejection)', async function() { + it('should support multiple process.on(unhandledRejection)', async function () { await jasmine.spyOnGlobalErrorsAsync(async () => { const hookSpy = jasmine.createSpy('hook'); (Zone as any)[zoneSymbol('ignoreConsoleErrorUncaughtError')] = true; let p: any = null; - Zone.current.fork({name: 'promise'}).run(function() { - const listener1 = function(reason: any, promise: any) { + Zone.current.fork({name: 'promise'}).run(function () { + const listener1 = function (reason: any, promise: any) { hookSpy(promise, reason.message); process.removeListener('unhandledRejection', listener1); }; - const listener2 = function(reason: any, promise: any) { + const listener2 = function (reason: any, promise: any) { hookSpy(promise, reason.message); process.removeListener('unhandledRejection', listener2); }; @@ -137,12 +151,16 @@ describe('process related test', () => { throw new Error('promise error'); }); }); - return new Promise( - res => setTimeout(function() { - expect(hookSpy.calls.count()).toBe(2); - expect(hookSpy.calls.allArgs()).toEqual([[p, 'promise error'], [p, 'promise error']]); - res(); - })); + return new Promise((res) => + setTimeout(function () { + expect(hookSpy.calls.count()).toBe(2); + expect(hookSpy.calls.allArgs()).toEqual([ + [p, 'promise error'], + [p, 'promise error'], + ]); + res(); + }), + ); }); }); }); diff --git a/packages/zone.js/test/node/timer.spec.ts b/packages/zone.js/test/node/timer.spec.ts index c04a7e4441ae5..fd46ec3704757 100644 --- a/packages/zone.js/test/node/timer.spec.ts +++ b/packages/zone.js/test/node/timer.spec.ts @@ -10,26 +10,27 @@ import {promisify} from 'util'; describe('node timer', () => { it('util.promisify should work with setTimeout', (done: DoneFn) => { const setTimeoutPromise = promisify(setTimeout); - setTimeoutPromise(50, 'value') - .then( - value => { - expect(value).toEqual('value'); - done(); - }, - error => { - fail(`should not be here with error: ${error}.`); - }); + setTimeoutPromise(50, 'value').then( + (value) => { + expect(value).toEqual('value'); + done(); + }, + (error) => { + fail(`should not be here with error: ${error}.`); + }, + ); }); it('util.promisify should work with setImmediate', (done: DoneFn) => { const setImmediatePromise = promisify(setImmediate); setImmediatePromise('value').then( - value => { - expect(value).toEqual('value'); - done(); - }, - error => { - fail(`should not be here with error: ${error}.`); - }); + (value) => { + expect(value).toEqual('value'); + done(); + }, + (error) => { + fail(`should not be here with error: ${error}.`); + }, + ); }); }); diff --git a/packages/zone.js/test/node_bluebird_entry_point.init.ts b/packages/zone.js/test/node_bluebird_entry_point.init.ts index 6fa603b3c08e4..a68d6a44398b5 100644 --- a/packages/zone.js/test/node_bluebird_entry_point.init.ts +++ b/packages/zone.js/test/node_bluebird_entry_point.init.ts @@ -48,17 +48,17 @@ const globalErrors = (jasmine as any).GlobalErrors; const symbol = Zone.__symbol__; if (globalErrors && !(jasmine as any)[symbol('GlobalErrors')]) { (jasmine as any)[symbol('GlobalErrors')] = globalErrors; - (jasmine as any).GlobalErrors = function() { + (jasmine as any).GlobalErrors = function () { const instance = new globalErrors(); const originalInstall = instance.install; if (originalInstall && !instance[symbol('install')]) { instance[symbol('install')] = originalInstall; - instance.install = function() { + instance.install = function () { const originalHandlers = process.listeners('unhandledRejection'); const r = originalInstall.apply(this, arguments); process.removeAllListeners('unhandledRejection'); if (originalHandlers) { - originalHandlers.forEach(h => process.on('unhandledRejection', h)); + originalHandlers.forEach((h) => process.on('unhandledRejection', h)); } return r; }; diff --git a/packages/zone.js/test/node_error_disable_policy.ts b/packages/zone.js/test/node_error_disable_policy.ts index 43a512b6d347a..cbd322c952b99 100644 --- a/packages/zone.js/test/node_error_disable_policy.ts +++ b/packages/zone.js/test/node_error_disable_policy.ts @@ -7,4 +7,4 @@ */ process.env['errorpolicy'] = (global as any)['__Zone_Error_ZoneJsInternalStackFrames_policy'] = - 'disable'; + 'disable'; diff --git a/packages/zone.js/test/node_error_lazy_policy.ts b/packages/zone.js/test/node_error_lazy_policy.ts index 0031c78480ca1..bbf7263363dbd 100644 --- a/packages/zone.js/test/node_error_lazy_policy.ts +++ b/packages/zone.js/test/node_error_lazy_policy.ts @@ -7,4 +7,4 @@ */ process.env['errorpolicy'] = (global as any)['__Zone_Error_ZoneJsInternalStackFrames_policy'] = - 'lazy'; + 'lazy'; diff --git a/packages/zone.js/test/npm_package/npm_package.spec.ts b/packages/zone.js/test/npm_package/npm_package.spec.ts index 90392970471fe..a45bd6b65c075 100644 --- a/packages/zone.js/test/npm_package/npm_package.spec.ts +++ b/packages/zone.js/test/npm_package/npm_package.spec.ts @@ -68,12 +68,14 @@ describe('Zone.js npm_package', () => { describe('rxjs patch', () => { it('should not contain rxjs source', () => { checkInSubFolder('./bundles', () => { - expect(shx.cat('zone-patch-rxjs.umd.js')) - .not.toContain('_enable_super_gross_mode_that_will_cause_bad_things'); + expect(shx.cat('zone-patch-rxjs.umd.js')).not.toContain( + '_enable_super_gross_mode_that_will_cause_bad_things', + ); }); checkInSubFolder('./fesm2015', () => { - expect(shx.cat('zone-patch-rxjs.js')) - .not.toContain('_enable_super_gross_mode_that_will_cause_bad_things'); + expect(shx.cat('zone-patch-rxjs.js')).not.toContain( + '_enable_super_gross_mode_that_will_cause_bad_things', + ); }); }); }); diff --git a/packages/zone.js/test/patch/IndexedDB.spec.js b/packages/zone.js/test/patch/IndexedDB.spec.js index 7305587277370..6869189ec6ec7 100644 --- a/packages/zone.js/test/patch/IndexedDB.spec.js +++ b/packages/zone.js/test/patch/IndexedDB.spec.js @@ -9,89 +9,73 @@ 'use strict'; describe( - 'IndexedDB', ifEnvSupports('IDBDatabase', function() { - var testZone = zone.fork(); - var db; + 'IndexedDB', + ifEnvSupports('IDBDatabase', function () { + var testZone = zone.fork(); + var db; - beforeEach(function(done) { - var openRequest = indexedDB.open('_zone_testdb'); - openRequest.onupgradeneeded = function(event) { - db = event.target.result; - var objectStore = db.createObjectStore('test-object-store', {keyPath: 'key'}); - objectStore.createIndex('key', 'key', {unique: true}); - objectStore.createIndex('data', 'data', {unique: false}); + beforeEach(function (done) { + var openRequest = indexedDB.open('_zone_testdb'); + openRequest.onupgradeneeded = function (event) { + db = event.target.result; + var objectStore = db.createObjectStore('test-object-store', {keyPath: 'key'}); + objectStore.createIndex('key', 'key', {unique: true}); + objectStore.createIndex('data', 'data', {unique: false}); - objectStore.transaction.oncomplete = function() { - var testStore = - db.transaction('test-object-store', 'readwrite').objectStore('test-object-store'); - testStore.add({key: 1, data: 'Test data'}); - testStore.transaction.oncomplete = function() { - done(); - } + objectStore.transaction.oncomplete = function () { + var testStore = db + .transaction('test-object-store', 'readwrite') + .objectStore('test-object-store'); + testStore.add({key: 1, data: 'Test data'}); + testStore.transaction.oncomplete = function () { + done(); }; }; - }); + }; + }); - afterEach(function(done) { - db.close(); + afterEach(function (done) { + db.close(); - var openRequest = indexedDB.deleteDatabase('_zone_testdb'); - openRequest.onsuccess = function(event) { - done(); - }; - }); + var openRequest = indexedDB.deleteDatabase('_zone_testdb'); + openRequest.onsuccess = function (event) { + done(); + }; + }); - describe('IDBRequest', function() { - it('should bind EventTarget.addEventListener', function(done) { - testZone.run(function() { - db.transaction('test-object-store') - .objectStore('test-object-store') - .get(1) - .addEventListener('success', function(event) { - expect(zone).toBeDirectChildOf(testZone); - expect(event.target.result.data).toBe('Test data'); - done(); - }); - }); + describe('IDBRequest', function () { + it('should bind EventTarget.addEventListener', function (done) { + testZone.run(function () { + db.transaction('test-object-store') + .objectStore('test-object-store') + .get(1) + .addEventListener('success', function (event) { + expect(zone).toBeDirectChildOf(testZone); + expect(event.target.result.data).toBe('Test data'); + done(); + }); }); + }); - it('should bind onEventType listeners', function(done) { - testZone.run(function() { - db.transaction('test-object-store').objectStore('test-object-store').get(1).onsuccess = - function(event) { + it('should bind onEventType listeners', function (done) { + testZone.run(function () { + db.transaction('test-object-store').objectStore('test-object-store').get(1).onsuccess = + function (event) { expect(zone).toBeDirectChildOf(testZone); expect(event.target.result.data).toBe('Test data'); done(); }; - }); }); }); + }); - describe('IDBCursor', function() { - it('should bind EventTarget.addEventListener', function(done) { - testZone.run(function() { - db.transaction('test-object-store') - .objectStore('test-object-store') - .openCursor() - .addEventListener('success', function(event) { - var cursor = event.target.result; - if (cursor) { - expect(zone).toBeDirectChildOf(testZone); - expect(cursor.value.data).toBe('Test data'); - done(); - } else { - throw 'Error while reading cursor!'; - } - }); - }); - }); - - it('should bind onEventType listeners', function(done) { - testZone.run(function() { - db.transaction('test-object-store') - .objectStore('test-object-store') - .openCursor() - .onsuccess = function(event) { + describe('IDBCursor', function () { + it('should bind EventTarget.addEventListener', function (done) { + testZone.run(function () { + db.transaction('test-object-store') + .objectStore('test-object-store') + .openCursor() + .addEventListener('success', function (event) { var cursor = event.target.result; if (cursor) { expect(zone).toBeDirectChildOf(testZone); @@ -100,38 +84,57 @@ describe( } else { throw 'Error while reading cursor!'; } - }; - }); + }); }); }); - describe('IDBIndex', function() { - it('should bind EventTarget.addEventListener', function(done) { - testZone.run(function() { - db.transaction('test-object-store') - .objectStore('test-object-store') - .index('data') - .get('Test data') - .addEventListener('success', function(event) { - expect(zone).toBeDirectChildOf(testZone); - expect(event.target.result.key).toBe(1); - done(); - }); - }); + it('should bind onEventType listeners', function (done) { + testZone.run(function () { + db + .transaction('test-object-store') + .objectStore('test-object-store') + .openCursor().onsuccess = function (event) { + var cursor = event.target.result; + if (cursor) { + expect(zone).toBeDirectChildOf(testZone); + expect(cursor.value.data).toBe('Test data'); + done(); + } else { + throw 'Error while reading cursor!'; + } + }; }); + }); + }); - it('should bind onEventType listeners', function(done) { - testZone.run(function() { - db.transaction('test-object-store') - .objectStore('test-object-store') - .index('data') - .get('Test data') - .onsuccess = function(event) { + describe('IDBIndex', function () { + it('should bind EventTarget.addEventListener', function (done) { + testZone.run(function () { + db.transaction('test-object-store') + .objectStore('test-object-store') + .index('data') + .get('Test data') + .addEventListener('success', function (event) { expect(zone).toBeDirectChildOf(testZone); expect(event.target.result.key).toBe(1); done(); - }; - }); + }); + }); + }); + + it('should bind onEventType listeners', function (done) { + testZone.run(function () { + db + .transaction('test-object-store') + .objectStore('test-object-store') + .index('data') + .get('Test data').onsuccess = function (event) { + expect(zone).toBeDirectChildOf(testZone); + expect(event.target.result.key).toBe(1); + done(); + }; }); }); - })); + }); + }), +); diff --git a/packages/zone.js/test/performance/eventTarget.js b/packages/zone.js/test/performance/eventTarget.js index a70254550f297..8624305a81223 100644 --- a/packages/zone.js/test/performance/eventTarget.js +++ b/packages/zone.js/test/performance/eventTarget.js @@ -5,80 +5,80 @@ * 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) { -var testRunner = _global['__zone_symbol__testRunner']; -var mark = _global['__zone_symbol__mark']; -var measure = _global['__zone_symbol__measure']; -var zone = _global['__zone_symbol__callbackZone']; -var button; -var testTarget = { - title: 'addEventListener', - times: 10, - before: function() { - button = document.createElement('button'); - document.body.appendChild(button); - _global['__zone_symbol__callbackContext'].measureName = 'addEventListener_callback'; - _global['__zone_symbol__callbackContext'].type = 'eventTask'; - _global['__zone_symbol__callbackContext'].source = 'addEventListener'; - }, - after: function() { - document.body.removeChild(button); - button = null; - }, - apis: [ - { - supportClear: true, - method: 'addEventListener', - nativeMethod: '__zone_symbol__addEventListener', - clearMethod: 'removeEventListener', - nativeClearMethod: '__zone_symbol__removeEventListener', - run: function() { - var listener = function() {}; - button.addEventListener('click', listener); - return listener; - }, - runClear: function(timerId) { - return button.removeEventListener('click', timerId); - }, - nativeRun: function() { - var listener = function() {}; - button['__zone_symbol__addEventListener']('click', listener); - return listener; - }, - nativeRunClear: function(timerId) { - return button['__zone_symbol__removeEventListener']('click', timerId); - } +(function (_global) { + var testRunner = _global['__zone_symbol__testRunner']; + var mark = _global['__zone_symbol__mark']; + var measure = _global['__zone_symbol__measure']; + var zone = _global['__zone_symbol__callbackZone']; + var button; + var testTarget = { + title: 'addEventListener', + times: 10, + before: function () { + button = document.createElement('button'); + document.body.appendChild(button); + _global['__zone_symbol__callbackContext'].measureName = 'addEventListener_callback'; + _global['__zone_symbol__callbackContext'].type = 'eventTask'; + _global['__zone_symbol__callbackContext'].source = 'addEventListener'; }, - { - isCallback: true, - supportClear: false, - method: 'addEventListener_callback', - nativeMethod: 'native_addEventListener_callback', - run: function() { - var listener = function() {}; - zone.run(function() { + after: function () { + document.body.removeChild(button); + button = null; + }, + apis: [ + { + supportClear: true, + method: 'addEventListener', + nativeMethod: '__zone_symbol__addEventListener', + clearMethod: 'removeEventListener', + nativeClearMethod: '__zone_symbol__removeEventListener', + run: function () { + var listener = function () {}; button.addEventListener('click', listener); - }); - var event = document.createEvent('Event'); - event.initEvent('click', true, true); - button.dispatchEvent(event); - button.removeEventListener('click', listener); + return listener; + }, + runClear: function (timerId) { + return button.removeEventListener('click', timerId); + }, + nativeRun: function () { + var listener = function () {}; + button['__zone_symbol__addEventListener']('click', listener); + return listener; + }, + nativeRunClear: function (timerId) { + return button['__zone_symbol__removeEventListener']('click', timerId); + }, + }, + { + isCallback: true, + supportClear: false, + method: 'addEventListener_callback', + nativeMethod: 'native_addEventListener_callback', + run: function () { + var listener = function () {}; + zone.run(function () { + button.addEventListener('click', listener); + }); + var event = document.createEvent('Event'); + event.initEvent('click', true, true); + button.dispatchEvent(event); + button.removeEventListener('click', listener); + }, + nativeRun: function () { + var func = function () {}; + var listener = function () { + mark('native_addEventListener_callback'); + func.apply(this, arguments); + measure('native_addEventListener_callback', 'native_addEventListener_callback'); + }; + button['__zone_symbol__addEventListener']('click', listener); + var event = document.createEvent('Event'); + event.initEvent('click', true, true); + button.dispatchEvent(event); + button['__zone_symbol__removeEventListener']('click', listener); + }, }, - nativeRun: function() { - var func = function() {}; - var listener = function() { - mark('native_addEventListener_callback'); - func.apply(this, arguments); - measure('native_addEventListener_callback', 'native_addEventListener_callback'); - }; - button['__zone_symbol__addEventListener']('click', listener); - var event = document.createEvent('Event'); - event.initEvent('click', true, true); - button.dispatchEvent(event); - button['__zone_symbol__removeEventListener']('click', listener); - } - } - ], -}; -return testRunner(testTarget); -}(typeof window === 'undefined' ? global : window)); + ], + }; + return testRunner(testTarget); +})(typeof window === 'undefined' ? global : window); diff --git a/packages/zone.js/test/performance/performance_setup.js b/packages/zone.js/test/performance/performance_setup.js index ac6c0e1579f46..17d00dc70aded 100644 --- a/packages/zone.js/test/performance/performance_setup.js +++ b/packages/zone.js/test/performance/performance_setup.js @@ -5,291 +5,297 @@ * 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) { -var allTasks = _global['__zone_symbol__performance_tasks']; -if (!allTasks) { - allTasks = _global['__zone_symbol__performance_tasks'] = []; -} - -var mark = _global['__zone_symbol__mark'] = function(name) { - performance && performance['mark'] && performance['mark'](name); -}; +(function (_global) { + var allTasks = _global['__zone_symbol__performance_tasks']; + if (!allTasks) { + allTasks = _global['__zone_symbol__performance_tasks'] = []; + } -var measure = _global['__zone_symbol__measure'] = function(name, label) { - performance && performance['measure'] && performance['measure'](name, label); -}; + var mark = (_global['__zone_symbol__mark'] = function (name) { + performance && performance['mark'] && performance['mark'](name); + }); -var getEntries = _global['__zone_symbol__getEntries'] = function() { - performance && performance['getEntries'] && performance['getEntries'](); -}; + var measure = (_global['__zone_symbol__measure'] = function (name, label) { + performance && performance['measure'] && performance['measure'](name, label); + }); -var getEntriesByName = _global['__zone_symbol__getEntriesByName'] = function(name) { - return performance && performance['getEntriesByName'] && performance['getEntriesByName'](name); -}; + var getEntries = (_global['__zone_symbol__getEntries'] = function () { + performance && performance['getEntries'] && performance['getEntries'](); + }); -var clearMarks = _global['__zone_symbol__clearMarks'] = function(name) { - return performance && performance['clearMarks'] && performance['clearMarks'](name); -}; + var getEntriesByName = (_global['__zone_symbol__getEntriesByName'] = function (name) { + return performance && performance['getEntriesByName'] && performance['getEntriesByName'](name); + }); -var clearMeasures = _global['__zone_symbol__clearMeasures'] = function(name) { - return performance && performance['clearMeasures'] && performance['clearMeasures'](name); -}; + var clearMarks = (_global['__zone_symbol__clearMarks'] = function (name) { + return performance && performance['clearMarks'] && performance['clearMarks'](name); + }); -var averageMeasures = _global['__zone_symbol__averageMeasures'] = function(name, times) { - var sum = _global['__zone_symbol__getEntriesByName'](name) - .filter(function(m) { - return m.entryType === 'measure'; - }) - .map(function(m) { - return m.duration - }) - .reduce(function(sum, d) { - return sum + d; - }); - return sum / times; -}; + var clearMeasures = (_global['__zone_symbol__clearMeasures'] = function (name) { + return performance && performance['clearMeasures'] && performance['clearMeasures'](name); + }); -var serialPromise = _global['__zone_symbol__serialPromise'] = - function(promiseFactories) { - let lastPromise; - for (var i = 0; i < promiseFactories.length; i++) { - var promiseFactory = promiseFactories[i]; - if (!lastPromise) { - lastPromise = promiseFactory.factory(promiseFactory.context).then(function(value) { - return {value, idx: 0}; + var averageMeasures = (_global['__zone_symbol__averageMeasures'] = function (name, times) { + var sum = _global['__zone_symbol__getEntriesByName'](name) + .filter(function (m) { + return m.entryType === 'measure'; + }) + .map(function (m) { + return m.duration; + }) + .reduce(function (sum, d) { + return sum + d; }); - } else { - lastPromise = lastPromise.then(function(ctx) { - var idx = ctx.idx + 1; - var promiseFactory = promiseFactories[idx]; - return promiseFactory.factory(promiseFactory.context).then(function(value) { - return {value, idx}; + return sum / times; + }); + + var serialPromise = (_global['__zone_symbol__serialPromise'] = function (promiseFactories) { + let lastPromise; + for (var i = 0; i < promiseFactories.length; i++) { + var promiseFactory = promiseFactories[i]; + if (!lastPromise) { + lastPromise = promiseFactory.factory(promiseFactory.context).then(function (value) { + return {value, idx: 0}; }); - }); + } else { + lastPromise = lastPromise.then(function (ctx) { + var idx = ctx.idx + 1; + var promiseFactory = promiseFactories[idx]; + return promiseFactory.factory(promiseFactory.context).then(function (value) { + return {value, idx}; + }); + }); + } } - } - return lastPromise; -} + return lastPromise; + }); -var callbackContext = _global['__zone_symbol__callbackContext'] = {}; -var zone = _global['__zone_symbol__callbackZone'] = Zone.current.fork({ - name: 'callback', - onScheduleTask: function(delegate, curr, target, task) { - delegate.scheduleTask(target, task); - if (task.type === callbackContext.type && task.source.indexOf(callbackContext.source) !== -1) { - if (task.type === 'macroTask' || task.type === 'eventTask') { - var invoke = task.invoke; - task.invoke = function() { - mark(callbackContext.measureName); - var result = invoke.apply(this, arguments); - measure(callbackContext.measureName, callbackContext.measureName); - return result; - }; - } else if (task.type === 'microTask') { - var callback = task.callback; - task.callback = function() { - mark(callbackContext.measureName); - var result = callback.apply(this, arguments); - measure(callbackContext.measureName, callbackContext.measureName); - return result; - }; + var callbackContext = (_global['__zone_symbol__callbackContext'] = {}); + var zone = (_global['__zone_symbol__callbackZone'] = Zone.current.fork({ + name: 'callback', + onScheduleTask: function (delegate, curr, target, task) { + delegate.scheduleTask(target, task); + if ( + task.type === callbackContext.type && + task.source.indexOf(callbackContext.source) !== -1 + ) { + if (task.type === 'macroTask' || task.type === 'eventTask') { + var invoke = task.invoke; + task.invoke = function () { + mark(callbackContext.measureName); + var result = invoke.apply(this, arguments); + measure(callbackContext.measureName, callbackContext.measureName); + return result; + }; + } else if (task.type === 'microTask') { + var callback = task.callback; + task.callback = function () { + mark(callbackContext.measureName); + var result = callback.apply(this, arguments); + measure(callbackContext.measureName, callbackContext.measureName); + return result; + }; + } } + return task; + }, + })); + + var runAsync = (_global['__zone_symbol__runAsync'] = function (testFn, times, _delay) { + var delay = _delay | 100; + const fnPromise = function () { + return new Promise(function (res, rej) { + // run test with a setTimeout + // several times to decrease measurement error + setTimeout(function () { + testFn().then(function () { + res(); + }); + }, delay); + }); + }; + var promiseFactories = []; + for (var i = 0; i < times; i++) { + promiseFactories.push({factory: fnPromise, context: {}}); } - return task; - } -}); -var runAsync = _global['__zone_symbol__runAsync'] = function(testFn, times, _delay) { - var delay = _delay | 100; - const fnPromise = function() { - return new Promise(function(res, rej) { - // run test with a setTimeout - // several times to decrease measurement error - setTimeout(function() { - testFn().then(function() { - res(); - }); - }, delay); - }); + return serialPromise(promiseFactories); + }); + + var getNativeMethodName = function (nativeWithSymbol) { + return nativeWithSymbol.replace('__zone_symbol__', 'native_'); }; - var promiseFactories = []; - for (var i = 0; i < times; i++) { - promiseFactories.push({factory: fnPromise, context: {}}); - } - return serialPromise(promiseFactories); -}; + function testAddRemove(api, count) { + var timerId = []; -var getNativeMethodName = function(nativeWithSymbol) { - return nativeWithSymbol.replace('__zone_symbol__', 'native_'); -}; + var name = api.method; + mark(name); + for (var i = 0; i < count; i++) { + timerId.push(api.run()); + } + measure(name, name); -function testAddRemove(api, count) { - var timerId = []; + if (api.supportClear) { + var clearName = api.clearMethod; + mark(clearName); + for (var i = 0; i < count; i++) { + api.runClear(timerId[i]); + } + measure(clearName, clearName); + } - var name = api.method; - mark(name); - for (var i = 0; i < count; i++) { - timerId.push(api.run()); - } - measure(name, name); + timerId = []; - if (api.supportClear) { - var clearName = api.clearMethod; - mark(clearName); + var nativeName = getNativeMethodName(api.nativeMethod); + mark(nativeName); for (var i = 0; i < count; i++) { - api.runClear(timerId[i]); + timerId.push(api.nativeRun()); } - measure(clearName, clearName); - } + measure(nativeName, nativeName); - timerId = []; + if (api.supportClear) { + var nativeClearName = getNativeMethodName(api.nativeClearMethod); + mark(nativeClearName); + for (var i = 0; i < count; i++) { + api.nativeRunClear(timerId[i]); + } + measure(nativeClearName, nativeClearName); + } - var nativeName = getNativeMethodName(api.nativeMethod); - mark(nativeName); - for (var i = 0; i < count; i++) { - timerId.push(api.nativeRun()); + return Promise.resolve(1); } - measure(nativeName, nativeName); - if (api.supportClear) { - var nativeClearName = getNativeMethodName(api.nativeClearMethod); - mark(nativeClearName); + function testCallback(api, count) { + var promises = [Promise.resolve(1)]; for (var i = 0; i < count; i++) { - api.nativeRunClear(timerId[i]); - } - measure(nativeClearName, nativeClearName); - } - - return Promise.resolve(1); -} - -function testCallback(api, count) { - var promises = [Promise.resolve(1)]; - for (var i = 0; i < count; i++) { - var r = api.run(); - if (api.isAsync) { - promises.push(r); + var r = api.run(); + if (api.isAsync) { + promises.push(r); + } } - } - for (var i = 0; i < count; i++) { - var r = api.nativeRun(); - if (api.isAsync) { - promises.push(r); + for (var i = 0; i < count; i++) { + var r = api.nativeRun(); + if (api.isAsync) { + promises.push(r); + } } + return Promise.all(promises); } - return Promise.all(promises); -} -function measureCallback(api, ops) { - var times = ops.times; - var displayText = ops.displayText; - var rawData = ops.rawData; - var summary = ops.summary; + function measureCallback(api, ops) { + var times = ops.times; + var displayText = ops.displayText; + var rawData = ops.rawData; + var summary = ops.summary; - var name = api.method; - var nativeName = getNativeMethodName(api.nativeMethod); - var measure = averageMeasures(name, times); - var nativeMeasure = averageMeasures(nativeName, times); - displayText += `- ${name} costs ${measure} ms\n`; - displayText += `- ${nativeName} costs ${nativeMeasure} ms\n`; - var absolute = Math.floor(1000 * (measure - nativeMeasure)) / 1000; - displayText += `# ${name} is ${absolute}ms slower than ${nativeName}\n`; - rawData[name + '_measure'] = measure; - rawData[nativeName + '_measure'] = nativeMeasure; - summary[name] = absolute + 'ms'; -} + var name = api.method; + var nativeName = getNativeMethodName(api.nativeMethod); + var measure = averageMeasures(name, times); + var nativeMeasure = averageMeasures(nativeName, times); + displayText += `- ${name} costs ${measure} ms\n`; + displayText += `- ${nativeName} costs ${nativeMeasure} ms\n`; + var absolute = Math.floor(1000 * (measure - nativeMeasure)) / 1000; + displayText += `# ${name} is ${absolute}ms slower than ${nativeName}\n`; + rawData[name + '_measure'] = measure; + rawData[nativeName + '_measure'] = nativeMeasure; + summary[name] = absolute + 'ms'; + } -function measureAddRemove(api, ops) { - var times = ops.times; - var displayText = ops.displayText; - var rawData = ops.rawData; - var summary = ops.summary; + function measureAddRemove(api, ops) { + var times = ops.times; + var displayText = ops.displayText; + var rawData = ops.rawData; + var summary = ops.summary; - var name = api.method; - var nativeName = getNativeMethodName(api.nativeMethod); + var name = api.method; + var nativeName = getNativeMethodName(api.nativeMethod); - var measure = averageMeasures(name, times); - var nativeMeasure = averageMeasures(nativeName, times); - displayText += `- ${name} costs ${measure} ms\n`; - displayText += `- ${nativeName} costs ${nativeMeasure} ms\n`; - var percent = Math.floor(100 * (measure - nativeMeasure) / nativeMeasure); - displayText += `# ${name} is ${percent}% slower than ${nativeName}\n`; - rawData[name + '_measure'] = measure; - rawData[nativeName + '_measure'] = nativeMeasure; - summary[name] = percent + '%'; - if (api.supportClear) { - var clearName = api.clearMethod; - var nativeClearName = getNativeMethodName(api.nativeClearMethod); - var clearMeasure = averageMeasures(clearName, times); - var nativeClearMeasure = averageMeasures(nativeClearName, times); - var clearPercent = Math.floor(100 * (clearMeasure - nativeClearMeasure) / nativeClearMeasure); - displayText += `- ${clearName} costs ${clearMeasure} ms\n`; - displayText += `- ${nativeClearName} costs ${nativeClearMeasure} ms\n`; - displayText += `# ${clearName} is ${clearPercent}% slower than ${nativeClearName}\n`; - rawData[clearName + '_measure'] = clearMeasure; - rawData[nativeClearName + '_measure'] = nativeClearMeasure; - summary[clearName] = clearPercent + '%'; + var measure = averageMeasures(name, times); + var nativeMeasure = averageMeasures(nativeName, times); + displayText += `- ${name} costs ${measure} ms\n`; + displayText += `- ${nativeName} costs ${nativeMeasure} ms\n`; + var percent = Math.floor((100 * (measure - nativeMeasure)) / nativeMeasure); + displayText += `# ${name} is ${percent}% slower than ${nativeName}\n`; + rawData[name + '_measure'] = measure; + rawData[nativeName + '_measure'] = nativeMeasure; + summary[name] = percent + '%'; + if (api.supportClear) { + var clearName = api.clearMethod; + var nativeClearName = getNativeMethodName(api.nativeClearMethod); + var clearMeasure = averageMeasures(clearName, times); + var nativeClearMeasure = averageMeasures(nativeClearName, times); + var clearPercent = Math.floor( + (100 * (clearMeasure - nativeClearMeasure)) / nativeClearMeasure, + ); + displayText += `- ${clearName} costs ${clearMeasure} ms\n`; + displayText += `- ${nativeClearName} costs ${nativeClearMeasure} ms\n`; + displayText += `# ${clearName} is ${clearPercent}% slower than ${nativeClearName}\n`; + rawData[clearName + '_measure'] = clearMeasure; + rawData[nativeClearName + '_measure'] = nativeClearMeasure; + summary[clearName] = clearPercent + '%'; + } } -} -var testRunner = _global['__zone_symbol__testRunner'] = function(testTarget) { - var title = testTarget.title; - var apis = testTarget.apis; - var methods = apis.reduce(function(acc, api) { - return acc.concat([api.method, api.nativeMethod] - .concat(api.supportClear ? [api.clearMethod, api.nativeClearMethod] : []) - .concat[api.method + '_callback', api.nativeMethod + '_callback']); - }, []); - var times = testTarget.times; + var testRunner = (_global['__zone_symbol__testRunner'] = function (testTarget) { + var title = testTarget.title; + var apis = testTarget.apis; + var methods = apis.reduce(function (acc, api) { + return acc.concat( + [api.method, api.nativeMethod].concat( + api.supportClear ? [api.clearMethod, api.nativeClearMethod] : [], + ).concat[(api.method + '_callback', api.nativeMethod + '_callback')], + ); + }, []); + var times = testTarget.times; - allTasks.push({ - title: title, - cleanFn: function() { - methods.forEach(function(m) { - clearMarks(m); - clearMeasures(m); - }); - }, - before: function() { - testTarget.before && testTarget.before(); - }, - after: function() { - testTarget.after && testTarget.after(); - }, - testFn: function() { - var count = typeof testTarget.count === 'number' ? testTarget.count : 10000; - var times = typeof testTarget.times === 'number' ? testTarget.times : 5; - - var testFunction = function() { - var promises = []; - apis.forEach(function(api) { - if (api.isCallback) { - var r = testCallback(api, count / 100); - promises.push(api.isAsync ? r : Promise.resolve(1)); - } else { - var r = testAddRemove(api, count); - promises.push[api.isAsync ? r : Promise.resolve(1)]; - } + allTasks.push({ + title: title, + cleanFn: function () { + methods.forEach(function (m) { + clearMarks(m); + clearMeasures(m); }); - return Promise.all(promises); - }; + }, + before: function () { + testTarget.before && testTarget.before(); + }, + after: function () { + testTarget.after && testTarget.after(); + }, + testFn: function () { + var count = typeof testTarget.count === 'number' ? testTarget.count : 10000; + var times = typeof testTarget.times === 'number' ? testTarget.times : 5; + + var testFunction = function () { + var promises = []; + apis.forEach(function (api) { + if (api.isCallback) { + var r = testCallback(api, count / 100); + promises.push(api.isAsync ? r : Promise.resolve(1)); + } else { + var r = testAddRemove(api, count); + promises.push[api.isAsync ? r : Promise.resolve(1)]; + } + }); + return Promise.all(promises); + }; - return runAsync(testFunction, times).then(function() { - var displayText = `running ${count} times\n`; - var rawData = {}; - var summary = {}; - apis.forEach(function(api) { - if (api.isCallback) { - measureCallback(api, {times, displayText, rawData, summary}); - } else { - measureAddRemove(api, {times, displayText, rawData, summary}); - } + return runAsync(testFunction, times).then(function () { + var displayText = `running ${count} times\n`; + var rawData = {}; + var summary = {}; + apis.forEach(function (api) { + if (api.isCallback) { + measureCallback(api, {times, displayText, rawData, summary}); + } else { + measureAddRemove(api, {times, displayText, rawData, summary}); + } + }); + return Promise.resolve({displayText: displayText, rawData: rawData, summary: summary}); }); - return Promise.resolve({displayText: displayText, rawData: rawData, summary: summary}); - }); - } + }, + }); }); -}; -}(typeof window === 'undefined' ? global : window)); +})(typeof window === 'undefined' ? global : window); diff --git a/packages/zone.js/test/performance/performance_ui.js b/packages/zone.js/test/performance/performance_ui.js index fbae46323a240..ce620adea121e 100644 --- a/packages/zone.js/test/performance/performance_ui.js +++ b/packages/zone.js/test/performance/performance_ui.js @@ -5,158 +5,158 @@ * 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) { -var options; +(function (_global) { + var options; -function setAttributes(elem, attrs) { - if (!attrs) { - return; - } - Object.keys(attrs).forEach(function(key) { - elem.setAttribute(key, attrs[key]); - }); -} - -function createLi(attrs) { - var li = document.createElement('li'); - setAttributes(li, attrs); - return li; -} - -function createLabel(attrs) { - var label = document.createElement('label'); - setAttributes(label, attrs); - return label; -} - -function createButton(attrs, innerHtml) { - var button = document.createElement('button'); - button.innerHTML = innerHtml; - setAttributes(button, attrs); - return button; -} - -function createTextNode(text) { - return document.createTextNode(text); -} - -function createCheckbox(attrs, checked) { - var checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - checkbox.checked = !!checked; - setAttributes(checkbox, attrs); - return checkbox; -} - -function createUl(attrs) { - var ul = document.createElement('ul'); - setAttributes(ul, attrs); - return ul; -} - -var serailPromise = _global['__zone_symbol__serialPromise']; - -_global['__zone_symbol__testTargetsUIBuild'] = function(_options) { - options = _options; - var allButton = createButton({}, 'test selected'); - allButton.addEventListener('click', function() { - var promiseFactories = []; - for (var i = 0; i < options.tests.length; i++) { - var checkbox = document.getElementById('testcheck' + i); - if (checkbox.checked) { - var test = options.tests[i]; - promiseFactories.push({ - factory: function(context) { - return doTest(context.test, context.idx); - }, - context: {test: test, idx: i} - }); - } + function setAttributes(elem, attrs) { + if (!attrs) { + return; } - serailPromise(promiseFactories); - }); - options.targetContainer.appendChild(allButton); + Object.keys(attrs).forEach(function (key) { + elem.setAttribute(key, attrs[key]); + }); + } - var ul = createUl(); - options.targetContainer.appendChild(ul); + function createLi(attrs) { + var li = document.createElement('li'); + setAttributes(li, attrs); + return li; + } + + function createLabel(attrs) { + var label = document.createElement('label'); + setAttributes(label, attrs); + return label; + } - for (var i = 0; i < options.tests.length; i++) { - buildTestItemUI(ul, options.tests[i], i); + function createButton(attrs, innerHtml) { + var button = document.createElement('button'); + button.innerHTML = innerHtml; + setAttributes(button, attrs); + return button; } -}; -function buildTestItemUI(ul, testItem, idx) { - var li = createLi({'id': 'test' + idx}); + function createTextNode(text) { + return document.createTextNode(text); + } - var button = createButton({'id': 'buttontest' + idx}, 'begin test'); - buildButtonClickHandler(button); + function createCheckbox(attrs, checked) { + var checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.checked = !!checked; + setAttributes(checkbox, attrs); + return checkbox; + } - var title = createTextNode(options.tests[idx].title); - var checkbox = createCheckbox({'id': 'testcheck' + idx}, true); - var label = createLabel({'id': 'label' + idx}); + function createUl(attrs) { + var ul = document.createElement('ul'); + setAttributes(ul, attrs); + return ul; + } - li.appendChild(checkbox); - li.appendChild(title); - li.appendChild(button); - li.appendChild(label); + var serailPromise = _global['__zone_symbol__serialPromise']; + + _global['__zone_symbol__testTargetsUIBuild'] = function (_options) { + options = _options; + var allButton = createButton({}, 'test selected'); + allButton.addEventListener('click', function () { + var promiseFactories = []; + for (var i = 0; i < options.tests.length; i++) { + var checkbox = document.getElementById('testcheck' + i); + if (checkbox.checked) { + var test = options.tests[i]; + promiseFactories.push({ + factory: function (context) { + return doTest(context.test, context.idx); + }, + context: {test: test, idx: i}, + }); + } + } + serailPromise(promiseFactories); + }); + options.targetContainer.appendChild(allButton); - ul.appendChild(li); -} + var ul = createUl(); + options.targetContainer.appendChild(ul); -function processTestResult(test, result, id) { - var split = result.displayText.split('\n'); - options.jsonResult[test.title] = result.rawData; - options.jsonContainer.innerHTML = + for (var i = 0; i < options.tests.length; i++) { + buildTestItemUI(ul, options.tests[i], i); + } + }; + + function buildTestItemUI(ul, testItem, idx) { + var li = createLi({'id': 'test' + idx}); + + var button = createButton({'id': 'buttontest' + idx}, 'begin test'); + buildButtonClickHandler(button); + + var title = createTextNode(options.tests[idx].title); + var checkbox = createCheckbox({'id': 'testcheck' + idx}, true); + var label = createLabel({'id': 'label' + idx}); + + li.appendChild(checkbox); + li.appendChild(title); + li.appendChild(button); + li.appendChild(label); + + ul.appendChild(li); + } + + function processTestResult(test, result, id) { + var split = result.displayText.split('\n'); + options.jsonResult[test.title] = result.rawData; + options.jsonContainer.innerHTML = '
' + JSON.stringify(options.jsonResult) + '
'; - var summary = result.summary; - var row = options.resultsContainer.insertRow(); - var cell = row.insertCell(); - cell.innerHTML = test.title; - cell.rowSpan = Object.keys(summary).length; - var idx = 0; - Object.keys(summary).forEach(function(key) { - var tableRow = row; - if (idx !== 0) { - tableRow = options.resultsContainer.insertRow(); + var summary = result.summary; + var row = options.resultsContainer.insertRow(); + var cell = row.insertCell(); + cell.innerHTML = test.title; + cell.rowSpan = Object.keys(summary).length; + var idx = 0; + Object.keys(summary).forEach(function (key) { + var tableRow = row; + if (idx !== 0) { + tableRow = options.resultsContainer.insertRow(); + } + var keyCell = tableRow.insertCell(); + keyCell.innerHTML = key; + var valueCell = tableRow.insertCell(); + valueCell.innerHTML = summary[key]; + idx++; + }); + + var testLi = document.getElementById('test' + id); + for (var j = 0; j < split.length; j++) { + var br = document.createElement('br'); + var s = document.createTextNode(split[j]); + testLi.appendChild(br); + testLi.appendChild(s); } - var keyCell = tableRow.insertCell(); - keyCell.innerHTML = key; - var valueCell = tableRow.insertCell(); - valueCell.innerHTML = summary[key]; - idx++; - }); - - var testLi = document.getElementById('test' + id); - for (var j = 0; j < split.length; j++) { - var br = document.createElement('br'); - var s = document.createTextNode(split[j]); - testLi.appendChild(br); - testLi.appendChild(s); } -} - -function doTest(test, id) { - test.cleanFn(); - test.before(); - var button = document.getElementById('buttontest' + id); - button.setAttribute('enabled', 'false'); - var label = document.getElementById('label' + id); - label.innerHTML = 'Testing'; - return test.testFn().then(function(result) { - processTestResult(test, result, id); - test.after(); - label.innerHTML = 'Finished'; - button.setAttribute('enabled', 'true'); - }); -} - -function buildButtonClickHandler(button) { - button.onclick = function(event) { - var target = event.target; - var id = target.getAttribute('id').substring(10); - var test = options.tests[id]; - doTest(test, id); - }; -} -}(typeof window === 'undefined' ? global : window)); + + function doTest(test, id) { + test.cleanFn(); + test.before(); + var button = document.getElementById('buttontest' + id); + button.setAttribute('enabled', 'false'); + var label = document.getElementById('label' + id); + label.innerHTML = 'Testing'; + return test.testFn().then(function (result) { + processTestResult(test, result, id); + test.after(); + label.innerHTML = 'Finished'; + button.setAttribute('enabled', 'true'); + }); + } + + function buildButtonClickHandler(button) { + button.onclick = function (event) { + var target = event.target; + var id = target.getAttribute('id').substring(10); + var test = options.tests[id]; + doTest(test, id); + }; + } +})(typeof window === 'undefined' ? global : window); diff --git a/packages/zone.js/test/performance/promise.js b/packages/zone.js/test/performance/promise.js index 4ca3a2ae93c5c..666f404078ee7 100644 --- a/packages/zone.js/test/performance/promise.js +++ b/packages/zone.js/test/performance/promise.js @@ -5,59 +5,59 @@ * 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) { -var mark = _global['__zone_symbol__mark']; -var measure = _global['__zone_symbol__measure']; -var testRunner = _global['__zone_symbol__testRunner']; -var zone = _global['__zone_symbol__callbackZone']; -var nativePromise = _global['__zone_symbol__Promise']; -var resolved = Promise.resolve(1); -var nativeResolved = nativePromise.resolve(1); -var testTarget = { - title: 'Promise', - times: 10, - before: function() { - _global['__zone_symbol__callbackContext'].measureName = 'Promise_callback'; - _global['__zone_symbol__callbackContext'].type = 'microTask'; - _global['__zone_symbol__callbackContext'].source = 'Promise.then'; - }, - apis: [ - { - supportClear: false, - isAsync: true, - method: 'Promise', - nativeMethod: 'native_Promise', - run: function() { - return resolved.then(function() {}); - }, - nativeRun: function() { - return nativeResolved['__zone_symbol__then'](function() {}); - }, +(function (_global) { + var mark = _global['__zone_symbol__mark']; + var measure = _global['__zone_symbol__measure']; + var testRunner = _global['__zone_symbol__testRunner']; + var zone = _global['__zone_symbol__callbackZone']; + var nativePromise = _global['__zone_symbol__Promise']; + var resolved = Promise.resolve(1); + var nativeResolved = nativePromise.resolve(1); + var testTarget = { + title: 'Promise', + times: 10, + before: function () { + _global['__zone_symbol__callbackContext'].measureName = 'Promise_callback'; + _global['__zone_symbol__callbackContext'].type = 'microTask'; + _global['__zone_symbol__callbackContext'].source = 'Promise.then'; }, - { - isCallback: true, - isAsync: true, - supportClear: false, - method: 'Promise_callback', - nativeMethod: 'native_Promise_callback', - run: function() { - return zone.run(function() { - return Promise.resolve(1).then(function(v) { - return v; + apis: [ + { + supportClear: false, + isAsync: true, + method: 'Promise', + nativeMethod: 'native_Promise', + run: function () { + return resolved.then(function () {}); + }, + nativeRun: function () { + return nativeResolved['__zone_symbol__then'](function () {}); + }, + }, + { + isCallback: true, + isAsync: true, + supportClear: false, + method: 'Promise_callback', + nativeMethod: 'native_Promise_callback', + run: function () { + return zone.run(function () { + return Promise.resolve(1).then(function (v) { + return v; + }); + }); + }, + nativeRun: function () { + var func = function () {}; + return _global['__zone_symbol__Promise'].resolve(1)['__zone_symbol__then'](function () { + mark('native_Promise_callback'); + var result = func.apply(this, arguments); + measure('native_Promise_callback', 'native_Promise_callback'); + return result; }); - }); + }, }, - nativeRun: function() { - var func = function() {}; - return _global['__zone_symbol__Promise'].resolve(1)['__zone_symbol__then'](function() { - mark('native_Promise_callback'); - var result = func.apply(this, arguments); - measure('native_Promise_callback', 'native_Promise_callback'); - return result; - }); - } - } - ], -}; -return testRunner(testTarget); -}(typeof window === 'undefined' ? global : window)); + ], + }; + return testRunner(testTarget); +})(typeof window === 'undefined' ? global : window); diff --git a/packages/zone.js/test/performance/requestAnimationFrame.js b/packages/zone.js/test/performance/requestAnimationFrame.js index 290fddb9a9e1f..4e91b2ddf6bc9 100644 --- a/packages/zone.js/test/performance/requestAnimationFrame.js +++ b/packages/zone.js/test/performance/requestAnimationFrame.js @@ -5,63 +5,66 @@ * 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) { -var mark = _global['__zone_symbol__mark']; -var measure = _global['__zone_symbol__measure']; -var zone = _global['__zone_symbol__callbackZone']; -var testRunner = _global['__zone_symbol__testRunner']; -var raf = _global['requestAnimationFrame']; -var cancel = _global['cancelAnimationFrame']; -var nativeRaf = _global['__zone_symbol__requestAnimationFrame']; -var nativeCancel = _global['__zone_symbol__cancelAnimationFrame']; -var testTarget = { - title: 'requestAnimationFrame', - times: 10, - before: function() { - _global['__zone_symbol__callbackContext'].measureName = 'requestAnimationFrame_callback'; - _global['__zone_symbol__callbackContext'].type = 'macroTask'; - _global['__zone_symbol__callbackContext'].source = 'requestAnimationFrame'; - }, - apis: [ - { - supportClear: true, - method: 'requestAnimationFrame', - nativeMethod: '__zone_symbol__requestAnimationFrame', - clearMethod: 'cancelAnimationFrame', - nativeClearMethod: '__zone_symbol__cancelAnimationFrame', - run: function() { - return raf(function() {}); - }, - runClear: function(timerId) { - return cancel(timerId); - }, - nativeRun: function() { - return nativeRaf(function() {}); - }, - nativeRunClear: function(timerId) { - return nativeCancel(timerId); - } +(function (_global) { + var mark = _global['__zone_symbol__mark']; + var measure = _global['__zone_symbol__measure']; + var zone = _global['__zone_symbol__callbackZone']; + var testRunner = _global['__zone_symbol__testRunner']; + var raf = _global['requestAnimationFrame']; + var cancel = _global['cancelAnimationFrame']; + var nativeRaf = _global['__zone_symbol__requestAnimationFrame']; + var nativeCancel = _global['__zone_symbol__cancelAnimationFrame']; + var testTarget = { + title: 'requestAnimationFrame', + times: 10, + before: function () { + _global['__zone_symbol__callbackContext'].measureName = 'requestAnimationFrame_callback'; + _global['__zone_symbol__callbackContext'].type = 'macroTask'; + _global['__zone_symbol__callbackContext'].source = 'requestAnimationFrame'; }, - { - isCallback: true, - supportClear: false, - method: 'requestAnimationFrame_callback', - nativeMethod: 'native_requestAnimationFrame_callback', - run: function() { - zone.run(function() { - raf(function() {}); - }); + apis: [ + { + supportClear: true, + method: 'requestAnimationFrame', + nativeMethod: '__zone_symbol__requestAnimationFrame', + clearMethod: 'cancelAnimationFrame', + nativeClearMethod: '__zone_symbol__cancelAnimationFrame', + run: function () { + return raf(function () {}); + }, + runClear: function (timerId) { + return cancel(timerId); + }, + nativeRun: function () { + return nativeRaf(function () {}); + }, + nativeRunClear: function (timerId) { + return nativeCancel(timerId); + }, + }, + { + isCallback: true, + supportClear: false, + method: 'requestAnimationFrame_callback', + nativeMethod: 'native_requestAnimationFrame_callback', + run: function () { + zone.run(function () { + raf(function () {}); + }); + }, + nativeRun: function () { + var func = function () {}; + nativeRaf(function () { + mark('native_requestAnimationFrame_callback'); + func.apply(this, arguments); + measure( + 'native_requestAnimationFrame_callback', + 'native_requestAnimationFrame_callback', + ); + }); + }, }, - nativeRun: function() { - var func = function() {}; - nativeRaf(function() { - mark('native_requestAnimationFrame_callback'); - func.apply(this, arguments); - measure('native_requestAnimationFrame_callback', 'native_requestAnimationFrame_callback'); - }); - } - } - ], -}; -return testRunner(testTarget); -}(typeof window === 'undefined' ? global : window)); + ], + }; + return testRunner(testTarget); +})(typeof window === 'undefined' ? global : window); diff --git a/packages/zone.js/test/performance/timeout.js b/packages/zone.js/test/performance/timeout.js index 7bedd0badbab8..92b1293e692a6 100644 --- a/packages/zone.js/test/performance/timeout.js +++ b/packages/zone.js/test/performance/timeout.js @@ -5,63 +5,63 @@ * 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) { -var mark = _global['__zone_symbol__mark']; -var measure = _global['__zone_symbol__measure']; -var testRunner = _global['__zone_symbol__testRunner']; -var setTimeout = _global['setTimeout']; -var clearTimeout = _global['clearTimeout']; -var nativeSetTimeout = _global['__zone_symbol__setTimeout']; -var nativeClearTimeout = _global['__zone_symbol__clearTimeout']; -var zone = _global['__zone_symbol__callbackZone']; -var testTarget = { - title: 'timer', - times: 10, - before: function() { - _global['__zone_symbol__callbackContext'].measureName = 'setTimeout_callback'; - _global['__zone_symbol__callbackContext'].type = 'macroTask'; - _global['__zone_symbol__callbackContext'].source = 'setTimeout'; - }, - apis: [ - { - supportClear: true, - method: 'setTimeout', - nativeMethod: '__zone_symbol__setTimeout', - clearMethod: 'clearTimeout', - nativeClearMethod: '__zone_symbol__clearTimeout', - run: function() { - return setTimeout(function() {}); - }, - runClear: function(timerId) { - return clearTimeout(timerId); - }, - nativeRun: function() { - return nativeSetTimeout(function() {}); - }, - nativeRunClear: function(timerId) { - return nativeClearTimeout(timerId); - } +(function (_global) { + var mark = _global['__zone_symbol__mark']; + var measure = _global['__zone_symbol__measure']; + var testRunner = _global['__zone_symbol__testRunner']; + var setTimeout = _global['setTimeout']; + var clearTimeout = _global['clearTimeout']; + var nativeSetTimeout = _global['__zone_symbol__setTimeout']; + var nativeClearTimeout = _global['__zone_symbol__clearTimeout']; + var zone = _global['__zone_symbol__callbackZone']; + var testTarget = { + title: 'timer', + times: 10, + before: function () { + _global['__zone_symbol__callbackContext'].measureName = 'setTimeout_callback'; + _global['__zone_symbol__callbackContext'].type = 'macroTask'; + _global['__zone_symbol__callbackContext'].source = 'setTimeout'; }, - { - isCallback: true, - supportClear: false, - method: 'setTimeout_callback', - nativeMethod: 'native_setTimeout_callback', - run: function() { - zone.run(function() { - setTimeout(function() {}); - }); + apis: [ + { + supportClear: true, + method: 'setTimeout', + nativeMethod: '__zone_symbol__setTimeout', + clearMethod: 'clearTimeout', + nativeClearMethod: '__zone_symbol__clearTimeout', + run: function () { + return setTimeout(function () {}); + }, + runClear: function (timerId) { + return clearTimeout(timerId); + }, + nativeRun: function () { + return nativeSetTimeout(function () {}); + }, + nativeRunClear: function (timerId) { + return nativeClearTimeout(timerId); + }, + }, + { + isCallback: true, + supportClear: false, + method: 'setTimeout_callback', + nativeMethod: 'native_setTimeout_callback', + run: function () { + zone.run(function () { + setTimeout(function () {}); + }); + }, + nativeRun: function () { + var func = function () {}; + nativeSetTimeout(function () { + mark('native_setTimeout_callback'); + func.apply(this, arguments); + measure('native_setTimeout_callback', 'native_setTimeout_callback'); + }); + }, }, - nativeRun: function() { - var func = function() {}; - nativeSetTimeout(function() { - mark('native_setTimeout_callback'); - func.apply(this, arguments); - measure('native_setTimeout_callback', 'native_setTimeout_callback'); - }); - } - } - ], -}; -return testRunner(testTarget); -}(typeof window === 'undefined' ? global : window)); + ], + }; + return testRunner(testTarget); +})(typeof window === 'undefined' ? global : window); diff --git a/packages/zone.js/test/performance/xhr.js b/packages/zone.js/test/performance/xhr.js index b49dee81a6cf2..02ac1e3fc508d 100644 --- a/packages/zone.js/test/performance/xhr.js +++ b/packages/zone.js/test/performance/xhr.js @@ -5,47 +5,47 @@ * 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) { -var mark = _global['__zone_symbol__mark']; -var measure = _global['__zone_symbol__measure']; -var testRunner = _global['__zone_symbol__testRunner']; -var zone = _global['__zone_symbol__callbackZone']; -var testTarget = { - title: 'xhr', - times: 3, - count: 1000, - before: function() { - _global['__zone_symbol__callbackContext'].measureName = 'xhr_callback'; - _global['__zone_symbol__callbackContext'].type = 'macroTask'; - _global['__zone_symbol__callbackContext'].source = 'send'; - }, - apis: [ - { - supportClear: true, - method: 'XHR.send', - nativeMethod: 'native.XHR.send', - clearMethod: 'XHR.abort', - nativeClearMethod: 'native.XHR.abort', - run: function() { - var xhr = new XMLHttpRequest(); - xhr.open('get', 'http://localhost:8080', true); - xhr.send(); - return xhr; - }, - runClear: function(xhr) { - xhr.abort(); - }, - nativeRun: function() { - var xhr = new XMLHttpRequest(); - xhr['__zone_symbol__open']('get', 'http://localhost:8080', true); - xhr['__zone_symbol__send'](); - return xhr; - }, - nativeRunClear: function(xhr) { - xhr['__zone_symbol__abort'](); - } +(function (_global) { + var mark = _global['__zone_symbol__mark']; + var measure = _global['__zone_symbol__measure']; + var testRunner = _global['__zone_symbol__testRunner']; + var zone = _global['__zone_symbol__callbackZone']; + var testTarget = { + title: 'xhr', + times: 3, + count: 1000, + before: function () { + _global['__zone_symbol__callbackContext'].measureName = 'xhr_callback'; + _global['__zone_symbol__callbackContext'].type = 'macroTask'; + _global['__zone_symbol__callbackContext'].source = 'send'; }, - ], -}; -return testRunner(testTarget); -}(typeof window === 'undefined' ? global : window)); + apis: [ + { + supportClear: true, + method: 'XHR.send', + nativeMethod: 'native.XHR.send', + clearMethod: 'XHR.abort', + nativeClearMethod: 'native.XHR.abort', + run: function () { + var xhr = new XMLHttpRequest(); + xhr.open('get', 'http://localhost:8080', true); + xhr.send(); + return xhr; + }, + runClear: function (xhr) { + xhr.abort(); + }, + nativeRun: function () { + var xhr = new XMLHttpRequest(); + xhr['__zone_symbol__open']('get', 'http://localhost:8080', true); + xhr['__zone_symbol__send'](); + return xhr; + }, + nativeRunClear: function (xhr) { + xhr['__zone_symbol__abort'](); + }, + }, + ], + }; + return testRunner(testTarget); +})(typeof window === 'undefined' ? global : window); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.audit.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.audit.spec.ts index 2e5e2ad4f2b1d..61b18fede286c 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.audit.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.audit.spec.ts @@ -18,68 +18,78 @@ xdescribe('Observable.audit', () => { log = []; }); - it('audit func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - const source = interval(100); - return source.pipe(audit(ev => { - expect(Zone.current.name).toEqual(constructorZone1.name); - return interval(150); - })); - }); + it( + 'audit func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + const source = interval(100); + return source.pipe( + audit((ev) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + return interval(150); + }), + ); + }); - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - if (result >= 3) { - subscriber.unsubscribe(); - } - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([1, 3, 'completed']); - done(); - }); - }); + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + if (result >= 3) { + subscriber.unsubscribe(); + } + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([1, 3, 'completed']); + done(); + }, + ); + }); - expect(log).toEqual([]); - }, Zone.root)); + expect(log).toEqual([]); + }, Zone.root), + ); - xit('auditTime func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - const source = interval(100); - return source.pipe(auditTime(360)); - }); + xit( + 'auditTime func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + const source = interval(100); + return source.pipe(auditTime(360)); + }); - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - if (result >= 7) { - subscriber.unsubscribe(); - } - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([3, 7, 'completed']); - done(); - }); - }); + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + if (result >= 7) { + subscriber.unsubscribe(); + } + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([3, 7, 'completed']); + done(); + }, + ); + }); - expect(log).toEqual([]); - }, Zone.root)); + expect(log).toEqual([]); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.buffer.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.buffer.spec.ts index 545bafc486db8..89e0650400a6b 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.buffer.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.buffer.spec.ts @@ -19,167 +19,189 @@ xdescribe('Observable.buffer', () => { log = []; }); - it('buffer func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - const source = interval(350); - const iv = interval(100); - return iv.pipe(buffer(source)); - }); - - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - if (result[0] >= 3) { - subscriber.unsubscribe(); - } - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([[0, 1, 2], [3, 4, 5], 'completed']); - done(); - }); - }); - - expect(log).toEqual([]); - }, Zone.root)); - - it('bufferCount func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - const iv = interval(100); - return iv.pipe(bufferCount(3)); - }); - - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - if (result[0] >= 3) { - subscriber.unsubscribe(); - } - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([[0, 1, 2], [3, 4, 5], 'completed']); - done(); - }); - }); - - expect(log).toEqual([]); - }, Zone.root)); - - it('bufferTime func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - const iv = interval(100); - return iv.pipe(bufferTime(350)); - }); - - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - if (result[0] >= 3) { - subscriber.unsubscribe(); - } - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([[0, 1, 2], [3, 4, 5], 'completed']); - done(); - }); - }); - - expect(log).toEqual([]); - }, Zone.root)); - - it('bufferToggle func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - const source = interval(10); - const opening = interval(25); - const closingSelector = (v: any) => { - expect(Zone.current.name).toEqual(constructorZone1.name); - return v % 2 === 0 ? of(v) : empty(); - }; - return source.pipe(bufferToggle(opening, closingSelector)); - }); - - let i = 0; - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - subscriber.unsubscribe(); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([[], 'completed']); - done(); - }); - }); - - expect(log).toEqual([]); - }, Zone.root)); - - it('bufferWhen func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - const source = interval(100); - return source.pipe(bufferWhen(() => { - expect(Zone.current.name).toEqual(constructorZone1.name); - return interval(220); - })); - }); - - let i = 0; - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - if (i++ >= 3) { - subscriber.unsubscribe(); - } - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([[0, 1], [2, 3], [4, 5], [6, 7], 'completed']); - done(); - }); - }); - - expect(log).toEqual([]); - }, Zone.root)); + it( + 'buffer func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + const source = interval(350); + const iv = interval(100); + return iv.pipe(buffer(source)); + }); + + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + if (result[0] >= 3) { + subscriber.unsubscribe(); + } + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([[0, 1, 2], [3, 4, 5], 'completed']); + done(); + }, + ); + }); + + expect(log).toEqual([]); + }, Zone.root), + ); + + it( + 'bufferCount func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + const iv = interval(100); + return iv.pipe(bufferCount(3)); + }); + + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + if (result[0] >= 3) { + subscriber.unsubscribe(); + } + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([[0, 1, 2], [3, 4, 5], 'completed']); + done(); + }, + ); + }); + + expect(log).toEqual([]); + }, Zone.root), + ); + + it( + 'bufferTime func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + const iv = interval(100); + return iv.pipe(bufferTime(350)); + }); + + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + if (result[0] >= 3) { + subscriber.unsubscribe(); + } + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([[0, 1, 2], [3, 4, 5], 'completed']); + done(); + }, + ); + }); + + expect(log).toEqual([]); + }, Zone.root), + ); + + it( + 'bufferToggle func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + const source = interval(10); + const opening = interval(25); + const closingSelector = (v: any) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + return v % 2 === 0 ? of(v) : empty(); + }; + return source.pipe(bufferToggle(opening, closingSelector)); + }); + + let i = 0; + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + subscriber.unsubscribe(); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([[], 'completed']); + done(); + }, + ); + }); + + expect(log).toEqual([]); + }, Zone.root), + ); + + it( + 'bufferWhen func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + const source = interval(100); + return source.pipe( + bufferWhen(() => { + expect(Zone.current.name).toEqual(constructorZone1.name); + return interval(220); + }), + ); + }); + + let i = 0; + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + if (i++ >= 3) { + subscriber.unsubscribe(); + } + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([[0, 1], [2, 3], [4, 5], [6, 7], 'completed']); + done(); + }, + ); + }); + + expect(log).toEqual([]); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.catch.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.catch.spec.ts index a4a8190bf915a..a1d04ab2d778f 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.catch.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.catch.spec.ts @@ -21,32 +21,37 @@ describe('Observable.catch', () => { const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); observable1 = constructorZone1.run(() => { const error = new Error('test'); - const source = of(1, 2, 3).pipe(map((n: number) => { - expect(Zone.current.name).toEqual(constructorZone1.name); - if (n === 2) { - throw error; - } - return n; - })); - return source.pipe(catchError((err: any) => { - expect(Zone.current.name).toEqual(constructorZone1.name); - return of('error1', 'error2'); - })); + const source = of(1, 2, 3).pipe( + map((n: number) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + if (n === 2) { + throw error; + } + return n; + }), + ); + return source.pipe( + catchError((err: any) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + return of('error1', 'error2'); + }), + ); }); subscriptionZone.run(() => { const subscriber = observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }); + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + ); }); expect(log).toEqual([1, 'error1', 'error2', 'completed']); }); @@ -57,30 +62,32 @@ describe('Observable.catch', () => { const error = new Error('test'); observable1 = constructorZone1.run(() => { return of(1, 2, 3).pipe( - map((n: number) => { - expect(Zone.current.name).toEqual(constructorZone1.name); - if (n === 2) { - throw error; - } - return n; - }), - retry(1)); + map((n: number) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + if (n === 2) { + throw error; + } + return n; + }), + retry(1), + ); }); subscriptionZone.run(() => { const subscriber = observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - (error: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(error); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }); + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + (error: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(error); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + ); }); expect(log).toEqual([1, 1, error]); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.collection.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.collection.spec.ts index 88e4215ce9125..227fa196d1262 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.collection.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.collection.spec.ts @@ -6,7 +6,31 @@ * found in the LICENSE file at https://angular.io/license */ import {from, interval, Observable, of} from 'rxjs'; -import {elementAt, every, filter, find, findIndex, first, flatMap, groupBy, ignoreElements, isEmpty, last, map, mapTo, max, min, reduce, repeat, scan, single, skip, skipUntil, skipWhile, startWith} from 'rxjs/operators'; +import { + elementAt, + every, + filter, + find, + findIndex, + first, + flatMap, + groupBy, + ignoreElements, + isEmpty, + last, + map, + mapTo, + max, + min, + reduce, + repeat, + scan, + single, + skip, + skipUntil, + skipWhile, + startWith, +} from 'rxjs/operators'; import {asyncTest, isPhantomJS} from '../test-util'; @@ -20,7 +44,7 @@ describe('Observable.collection', () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; }); - afterEach(function() { + afterEach(function () { jasmine.DEFAULT_TIMEOUT_INTERVAL = defaultTimeout; }); @@ -34,18 +58,19 @@ describe('Observable.collection', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([2, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([2, 'completed']); + }, + ); }); }); @@ -59,26 +84,29 @@ describe('Observable.collection', () => { }); observable1 = everyZone1.run(() => { - return observable1.pipe(every((v: any) => { - expect(Zone.current.name).toEqual(everyZone1.name); - return v % 2 === 0; - })); + return observable1.pipe( + every((v: any) => { + expect(Zone.current.name).toEqual(everyZone1.name); + return v % 2 === 0; + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([false, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([false, 'completed']); + }, + ); }); }); @@ -92,26 +120,29 @@ describe('Observable.collection', () => { }); observable1 = filterZone1.run(() => { - return observable1.pipe(filter((v: any) => { - expect(Zone.current.name).toEqual(filterZone1.name); - return v % 2 === 0; - })); + return observable1.pipe( + filter((v: any) => { + expect(Zone.current.name).toEqual(filterZone1.name); + return v % 2 === 0; + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([2, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([2, 'completed']); + }, + ); }); }); @@ -125,26 +156,29 @@ describe('Observable.collection', () => { }); observable1 = findZone1.run(() => { - return observable1.pipe(find((v: any) => { - expect(Zone.current.name).toEqual(findZone1.name); - return v === 2; - })); + return observable1.pipe( + find((v: any) => { + expect(Zone.current.name).toEqual(findZone1.name); + return v === 2; + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([2, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([2, 'completed']); + }, + ); }); }); @@ -158,26 +192,29 @@ describe('Observable.collection', () => { }); observable1 = findZone1.run(() => { - return observable1.pipe(findIndex((v: any) => { - expect(Zone.current.name).toEqual(findZone1.name); - return v === 2; - })); + return observable1.pipe( + findIndex((v: any) => { + expect(Zone.current.name).toEqual(findZone1.name); + return v === 2; + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([1, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([1, 'completed']); + }, + ); }); }); @@ -191,26 +228,29 @@ describe('Observable.collection', () => { }); observable1 = firstZone1.run(() => { - return observable1.pipe(first((v: any) => { - expect(Zone.current.name).toEqual(firstZone1.name); - return v === 2; - })); + return observable1.pipe( + first((v: any) => { + expect(Zone.current.name).toEqual(firstZone1.name); + return v === 2; + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([2, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([2, 'completed']); + }, + ); }); }); @@ -223,41 +263,50 @@ describe('Observable.collection', () => { const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); observable1 = constructorZone1.run(() => { const people = [ - {name: 'Sue', age: 25}, {name: 'Joe', age: 30}, {name: 'Frank', age: 25}, - {name: 'Sarah', age: 35} + {name: 'Sue', age: 25}, + {name: 'Joe', age: 30}, + {name: 'Frank', age: 25}, + {name: 'Sarah', age: 35}, ]; return from(people); }); observable1 = groupByZone1.run(() => { return observable1.pipe( - groupBy((person: any) => { - expect(Zone.current.name).toEqual(groupByZone1.name); - return person.age; - }), - // return as array of each group - flatMap((group: any) => { - return group.pipe(reduce((acc: any, curr: any) => [...acc, curr], [])); - })); + groupBy((person: any) => { + expect(Zone.current.name).toEqual(groupByZone1.name); + return person.age; + }), + // return as array of each group + flatMap((group: any) => { + return group.pipe(reduce((acc: any, curr: any) => [...acc, curr], [])); + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error' + err); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([ - [{age: 25, name: 'Sue'}, {age: 25, name: 'Frank'}], [{age: 30, name: 'Joe'}], - [{age: 35, name: 'Sarah'}], 'completed' - ]); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error' + err); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([ + [ + {age: 25, name: 'Sue'}, + {age: 25, name: 'Frank'}, + ], + [{age: 30, name: 'Joe'}], + [{age: 35, name: 'Sarah'}], + 'completed', + ]); + }, + ); }); }); @@ -272,17 +321,18 @@ describe('Observable.collection', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - fail('should not call next'); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual(['completed']); - }); + (result: any) => { + fail('should not call next'); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual(['completed']); + }, + ); }); }); @@ -297,18 +347,19 @@ describe('Observable.collection', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([false, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([false, 'completed']); + }, + ); }); }); @@ -323,18 +374,19 @@ describe('Observable.collection', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([3, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([3, 'completed']); + }, + ); }); }); @@ -348,26 +400,29 @@ describe('Observable.collection', () => { }); observable1 = mapZone1.run(() => { - return observable1.pipe(map((v: any) => { - expect(Zone.current.name).toEqual(mapZone1.name); - return v + 1; - })); + return observable1.pipe( + map((v: any) => { + expect(Zone.current.name).toEqual(mapZone1.name); + return v + 1; + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([2, 3, 4, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([2, 3, 4, 'completed']); + }, + ); }); }); @@ -386,18 +441,19 @@ describe('Observable.collection', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual(['a', 'a', 'a', 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual(['a', 'a', 'a', 'completed']); + }, + ); }); }); @@ -411,18 +467,19 @@ describe('Observable.collection', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([4, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([4, 'completed']); + }, + ); }); }); @@ -436,26 +493,29 @@ describe('Observable.collection', () => { }); observable1 = maxZone1.run(() => { - return observable1.pipe(max((x: number, y: number) => { - expect(Zone.current.name).toEqual(maxZone1.name); - return x < y ? -1 : 1; - })); + return observable1.pipe( + max((x: number, y: number) => { + expect(Zone.current.name).toEqual(maxZone1.name); + return x < y ? -1 : 1; + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([4, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([4, 'completed']); + }, + ); }); }); @@ -469,18 +529,19 @@ describe('Observable.collection', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([2, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([2, 'completed']); + }, + ); }); }); @@ -494,26 +555,29 @@ describe('Observable.collection', () => { }); observable1 = minZone1.run(() => { - return observable1.pipe(max((x: number, y: number) => { - expect(Zone.current.name).toEqual(minZone1.name); - return x < y ? 1 : -1; - })); + return observable1.pipe( + max((x: number, y: number) => { + expect(Zone.current.name).toEqual(minZone1.name); + return x < y ? 1 : -1; + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([2, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([2, 'completed']); + }, + ); }); }); @@ -526,26 +590,29 @@ describe('Observable.collection', () => { }); observable1 = reduceZone1.run(() => { - return observable1.pipe(reduce((acc: number, one: number) => { - expect(Zone.current.name).toEqual(reduceZone1.name); - return acc + one; - })); + return observable1.pipe( + reduce((acc: number, one: number) => { + expect(Zone.current.name).toEqual(reduceZone1.name); + return acc + one; + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([9, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([9, 'completed']); + }, + ); }); }); @@ -558,26 +625,29 @@ describe('Observable.collection', () => { }); observable1 = scanZone1.run(() => { - return observable1.pipe(scan((acc: number, one: number) => { - expect(Zone.current.name).toEqual(scanZone1.name); - return acc + one; - })); + return observable1.pipe( + scan((acc: number, one: number) => { + expect(Zone.current.name).toEqual(scanZone1.name); + return acc + one; + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([4, 6, 9, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([4, 6, 9, 'completed']); + }, + ); }); }); @@ -590,18 +660,19 @@ describe('Observable.collection', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([1, 1, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([1, 1, 'completed']); + }, + ); }); }); @@ -614,26 +685,29 @@ describe('Observable.collection', () => { }); observable1 = singleZone1.run(() => { - return observable1.pipe(single((val: any) => { - expect(Zone.current.name).toEqual(singleZone1.name); - return val === 4; - })); + return observable1.pipe( + single((val: any) => { + expect(Zone.current.name).toEqual(singleZone1.name); + return val === 4; + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([4, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([4, 'completed']); + }, + ); }); }); @@ -646,9 +720,37 @@ describe('Observable.collection', () => { subscriptionZone.run(() => { observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([4, 5, 'completed']); + }, + ); + }); + }); + + xit( + 'skipUntil func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return interval(10).pipe(skipUntil(interval(25))); + }); + + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( (result: any) => { log.push(result); expect(Zone.current.name).toEqual(subscriptionZone.name); + subscriber.unsubscribe(); }, (err: any) => { fail('should not call error'); @@ -656,65 +758,48 @@ describe('Observable.collection', () => { () => { log.push('completed'); expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([4, 5, 'completed']); - }); - }); - }); + expect(log).toEqual([2, 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); + + it( + 'skipWhile func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const skipZone1: Zone = Zone.current.fork({name: 'Skip Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return interval(10); + }); + + observable1 = skipZone1.run(() => { + return observable1.pipe( + skipWhile((val: any) => { + expect(Zone.current.name).toEqual(skipZone1.name); + return val < 2; + }), + ); + }); - xit('skipUntil func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return interval(10).pipe(skipUntil(interval(25))); - }); - - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - subscriber.unsubscribe(); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([2, 'completed']); - done(); - }); - }); - }, Zone.root)); - - it('skipWhile func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const skipZone1: Zone = Zone.current.fork({name: 'Skip Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return interval(10); - }); - - observable1 = skipZone1.run(() => { - return observable1.pipe(skipWhile((val: any) => { - expect(Zone.current.name).toEqual(skipZone1.name); - return val < 2; - })); - }); - - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - subscriber.unsubscribe(); - expect(result).toEqual(2); - done(); - }, - (err: any) => { - fail('should not call error'); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + subscriber.unsubscribe(); + expect(result).toEqual(2); + done(); + }, + (err: any) => { + fail('should not call error'); + }, + ); + }); + }, Zone.root), + ); it('startWith func callback should run in the correct zone', () => { const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); @@ -725,18 +810,19 @@ describe('Observable.collection', () => { subscriptionZone.run(() => { const subscriber = observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([3, 1, 2, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([3, 1, 2, 'completed']); + }, + ); }); }); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.combine.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.combine.spec.ts index 1edf8bc283c46..4af33ffd398cc 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.combine.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.combine.spec.ts @@ -18,69 +18,82 @@ describe('Observable.combine', () => { log = []; }); - it('combineAll func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - const source = of(1, 2); - const highOrder = source.pipe(map((src: any) => { - expect(Zone.current.name).toEqual(constructorZone1.name); - return of(src); - })); - return highOrder.pipe(combineAll()); - }); + it( + 'combineAll func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + const source = of(1, 2); + const highOrder = source.pipe( + map((src: any) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + return of(src); + }), + ); + return highOrder.pipe(combineAll()); + }); - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([[1, 2], 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([[1, 2], 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); - it('combineAll func callback should run in the correct zone with project function', - asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - const source = of(1, 2, 3); - const highOrder = source.pipe(map((src: any) => { - expect(Zone.current.name).toEqual(constructorZone1.name); - return of(src); - })); - return highOrder.pipe(combineAll((x: any, y: any) => { - expect(Zone.current.name).toEqual(constructorZone1.name); - return {x: x, y: y}; - })); - }); + it( + 'combineAll func callback should run in the correct zone with project function', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + const source = of(1, 2, 3); + const highOrder = source.pipe( + map((src: any) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + return of(src); + }), + ); + return highOrder.pipe( + combineAll((x: any, y: any) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + return {x: x, y: y}; + }), + ); + }); - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([{x: 1, y: 2}, 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([{x: 1, y: 2}, 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); it('combineLatest func callback should run in the correct zone', () => { const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); @@ -93,17 +106,18 @@ describe('Observable.combine', () => { subscriptionZone.run(() => { const subscriber = observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }); + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + ); }); expect(log).toEqual([[3, 4], [3, 5], [3, 6], 'completed']); @@ -122,17 +136,18 @@ describe('Observable.combine', () => { subscriptionZone.run(() => { const subscriber = observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }); + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + ); }); expect(log).toEqual([7, 8, 9, 'completed']); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.concat.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.concat.spec.ts index a7678b6a2c033..5b69e993fee17 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.concat.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.concat.spec.ts @@ -28,7 +28,7 @@ describe('Observable instance method concat', () => { it('concat func callback should run in the correct zone', () => { observable1 = constructorZone1.run(() => { - return new Observable(subscriber => { + return new Observable((subscriber) => { expect(Zone.current.name).toEqual(constructorZone1.name); subscriber.next(1); subscriber.next(2); @@ -54,148 +54,167 @@ describe('Observable instance method concat', () => { expect(log).toEqual([1, 2, 3, 4, 5, 6]); }); - xit('concat func callback should run in the correct zone with scheduler', - asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const constructorZone2: Zone = Zone.current.fork({name: 'Constructor Zone2'}); - const constructorZone3: Zone = Zone.current.fork({name: 'Constructor Zone3'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return of(1, 2); - }); + xit( + 'concat func callback should run in the correct zone with scheduler', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const constructorZone2: Zone = Zone.current.fork({name: 'Constructor Zone2'}); + const constructorZone3: Zone = Zone.current.fork({name: 'Constructor Zone3'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return of(1, 2); + }); - observable2 = constructorZone2.run(() => { - return range(3, 4); - }); + observable2 = constructorZone2.run(() => { + return range(3, 4); + }); + + constructorZone3.run(() => { + concatObservable = concat(observable1, observable2, asapScheduler); + }); - constructorZone3.run(() => { - concatObservable = concat(observable1, observable2, asapScheduler); + subscriptionZone.run(() => { + concatObservable.subscribe( + (concat: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(concat); + }, + (error: any) => { + fail('subscribe failed' + error); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([1, 2, 3, 4, 5, 6]); + done(); + }, + ); + }); + + expect(log).toEqual([]); + }, Zone.root), + ); + + it( + 'concatAll func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const constructorZone2: Zone = Zone.current.fork({name: 'Constructor Zone2'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return of(0, 1, 2); + }); + + constructorZone2.run(() => { + const highOrder = observable1.pipe( + map((v: any) => { + expect(Zone.current.name).toEqual(constructorZone2.name); + return of(v + 1); + }), + ); + concatObservable = highOrder.pipe(concatAll()); + }); + + subscriptionZone.run(() => { + concatObservable.subscribe( + (concat: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(concat); + }, + (error: any) => { + fail('subscribe failed' + error); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([1, 2, 3]); + done(); + }, + ); + }); + }, Zone.root), + ); + + it( + 'concatMap func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const constructorZone2: Zone = Zone.current.fork({name: 'Constructor Zone2'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return new Observable((subscriber) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + subscriber.next(1); + subscriber.next(2); + subscriber.next(3); + subscriber.next(4); + subscriber.complete(); }); + }); + + constructorZone2.run(() => { + concatObservable = observable1.pipe( + concatMap((v: any) => { + expect(Zone.current.name).toEqual(constructorZone2.name); + return of(0, 1); + }), + ); + }); - subscriptionZone.run(() => { - concatObservable.subscribe( - (concat: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(concat); - }, - (error: any) => { - fail('subscribe failed' + error); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([1, 2, 3, 4, 5, 6]); - done(); - }); + subscriptionZone.run(() => { + concatObservable.subscribe( + (concat: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(concat); + }, + (error: any) => { + fail('subscribe failed' + error); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([0, 1, 0, 1, 0, 1, 0, 1]); + done(); + }, + ); + }); + }, Zone.root), + ); + + it( + 'concatMapTo func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const constructorZone2: Zone = Zone.current.fork({name: 'Constructor Zone2'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return new Observable((subscriber) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + subscriber.next(1); + subscriber.next(2); + subscriber.next(3); + subscriber.next(4); + subscriber.complete(); }); + }); - expect(log).toEqual([]); - }, Zone.root)); - - it('concatAll func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const constructorZone2: Zone = Zone.current.fork({name: 'Constructor Zone2'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return of(0, 1, 2); - }); - - constructorZone2.run(() => { - const highOrder = observable1.pipe(map((v: any) => { - expect(Zone.current.name).toEqual(constructorZone2.name); - return of(v + 1); - })); - concatObservable = highOrder.pipe(concatAll()); - }); - - subscriptionZone.run(() => { - concatObservable.subscribe( - (concat: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(concat); - }, - (error: any) => { - fail('subscribe failed' + error); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([1, 2, 3]); - done(); - }); - }); - }, Zone.root)); - - it('concatMap func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const constructorZone2: Zone = Zone.current.fork({name: 'Constructor Zone2'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return new Observable(subscriber => { - expect(Zone.current.name).toEqual(constructorZone1.name); - subscriber.next(1); - subscriber.next(2); - subscriber.next(3); - subscriber.next(4); - subscriber.complete(); - }); - }); - - constructorZone2.run(() => { - concatObservable = observable1.pipe(concatMap((v: any) => { - expect(Zone.current.name).toEqual(constructorZone2.name); - return of(0, 1); - })); - }); - - subscriptionZone.run(() => { - concatObservable.subscribe( - (concat: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(concat); - }, - (error: any) => { - fail('subscribe failed' + error); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([0, 1, 0, 1, 0, 1, 0, 1]); - done(); - }); - }); - }, Zone.root)); - - it('concatMapTo func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const constructorZone2: Zone = Zone.current.fork({name: 'Constructor Zone2'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return new Observable(subscriber => { - expect(Zone.current.name).toEqual(constructorZone1.name); - subscriber.next(1); - subscriber.next(2); - subscriber.next(3); - subscriber.next(4); - subscriber.complete(); - }); - }); - - constructorZone2.run(() => { - concatObservable = observable1.pipe(concatMapTo(of(0, 1))); - }); - - subscriptionZone.run(() => { - concatObservable.subscribe( - (concat: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(concat); - }, - (error: any) => { - fail('subscribe failed' + error); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([0, 1, 0, 1, 0, 1, 0, 1]); - done(); - }); - }); - }, Zone.root)); + constructorZone2.run(() => { + concatObservable = observable1.pipe(concatMapTo(of(0, 1))); + }); + + subscriptionZone.run(() => { + concatObservable.subscribe( + (concat: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(concat); + }, + (error: any) => { + fail('subscribe failed' + error); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([0, 1, 0, 1, 0, 1, 0, 1]); + done(); + }, + ); + }); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.count.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.count.spec.ts index f087f594b0f97..884846b79a9da 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.count.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.count.spec.ts @@ -20,25 +20,28 @@ describe('Observable.count', () => { it('count func callback should run in the correct zone', () => { observable1 = constructorZone1.run(() => { - return range(1, 3).pipe(count((i: number) => { - expect(Zone.current.name).toEqual(constructorZone1.name); - return i % 2 === 0; - })); + return range(1, 3).pipe( + count((i: number) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + return i % 2 === 0; + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + ); }); expect(log).toEqual([1, 'completed']); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.debounce.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.debounce.spec.ts index 15889e008a971..d434b23752b24 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.debounce.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.debounce.spec.ts @@ -18,56 +18,66 @@ describe('Observable.debounce', () => { log = []; }); - it('debounce func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return of(1, 2, 3).pipe(debounce(() => { - expect(Zone.current.name).toEqual(constructorZone1.name); - return timer(100); - })); - }); + it( + 'debounce func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return of(1, 2, 3).pipe( + debounce(() => { + expect(Zone.current.name).toEqual(constructorZone1.name); + return timer(100); + }), + ); + }); - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - done(); - }); - }); - expect(log).toEqual([3, 'completed']); - }, Zone.root)); + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + done(); + }, + ); + }); + expect(log).toEqual([3, 'completed']); + }, Zone.root), + ); - it('debounceTime func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return of(1, 2, 3).pipe(debounceTime(100)); - }); + it( + 'debounceTime func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return of(1, 2, 3).pipe(debounceTime(100)); + }); - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - done(); - }); - }); - expect(log).toEqual([3, 'completed']); - }, Zone.root)); + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + done(); + }, + ); + }); + expect(log).toEqual([3, 'completed']); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.default.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.default.spec.ts index 477e35afcd0b5..28ed0a237d49b 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.default.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.default.spec.ts @@ -18,28 +18,32 @@ describe('Observable.defaultIfEmpty', () => { log = []; }); - it('defaultIfEmpty func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return of().pipe(defaultIfEmpty('empty' as any)); - }); + it( + 'defaultIfEmpty func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return of().pipe(defaultIfEmpty('empty' as any)); + }); - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual(['empty', 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual(['empty', 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.delay.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.delay.spec.ts index 2254510c1f30a..dc24c76a08677 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.delay.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.delay.spec.ts @@ -19,55 +19,65 @@ describe('Observable.delay', () => { log = []; }); - it('delay func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return of(1, 2, 3).pipe(delay(100)); - }); + it( + 'delay func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return of(1, 2, 3).pipe(delay(100)); + }); - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([1, 2, 3, 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([1, 2, 3, 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); - it('delayWhen func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return of(1, 2, 3).pipe(delayWhen((v: any) => { - return timer(v * 10); - })); - }); + it( + 'delayWhen func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return of(1, 2, 3).pipe( + delayWhen((v: any) => { + return timer(v * 10); + }), + ); + }); - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([1, 2, 3, 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([1, 2, 3, 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.distinct.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.distinct.spec.ts index bc804c3217c89..4e0cae0781faf 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.distinct.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.distinct.spec.ts @@ -27,17 +27,18 @@ describe('Observable.distinct', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + ); }); expect(log).toEqual([1, 2, 3, 4, 'completed']); }); @@ -52,17 +53,18 @@ describe('Observable.distinct', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + ); }); expect(log).toEqual([1, 2, 1, 2, 3, 4, 'completed']); }); @@ -72,26 +74,34 @@ describe('Observable.distinct', () => { const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); const error = new Error('test'); observable1 = constructorZone1.run(() => { - return of({age: 4, name: 'Foo'}, {age: 7, name: 'Bar'}, {age: 5, name: 'Foo'}, - {age: 6, name: 'Foo'}) - .pipe(distinctUntilKeyChanged('name')); + return of( + {age: 4, name: 'Foo'}, + {age: 7, name: 'Bar'}, + {age: 5, name: 'Foo'}, + {age: 6, name: 'Foo'}, + ).pipe(distinctUntilKeyChanged('name')); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + ); }); - expect(log).toEqual( - [{age: 4, name: 'Foo'}, {age: 7, name: 'Bar'}, {age: 5, name: 'Foo'}, 'completed']); + expect(log).toEqual([ + {age: 4, name: 'Foo'}, + {age: 7, name: 'Bar'}, + {age: 5, name: 'Foo'}, + 'completed', + ]); }); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.do.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.do.spec.ts index 247954f2fa15c..d4a2155fb5603 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.do.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.do.spec.ts @@ -26,26 +26,29 @@ describe('Observable.tap', () => { }); observable1 = doZone1.run(() => { - return observable1.pipe(tap((v: any) => { - log.push(v); - expect(Zone.current.name).toEqual(doZone1.name); - })); + return observable1.pipe( + tap((v: any) => { + log.push(v); + expect(Zone.current.name).toEqual(doZone1.name); + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push('result' + result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([1, 'result1', 'completed']); - }); + (result: any) => { + log.push('result' + result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([1, 'result1', 'completed']); + }, + ); }); }); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.map.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.map.spec.ts index da4a2859a94b5..6c86fa991858a 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.map.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.map.spec.ts @@ -29,17 +29,18 @@ describe('Observable.map', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('completed'); - }); + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('completed'); + }, + ); }); expect(log).toEqual([[1, 2], [2, 3], 'completed']); @@ -52,38 +53,42 @@ describe('Observable.map', () => { }); const part: any = partitionZone.run(() => { - return observable1.pipe(partition((val: any) => { - expect(Zone.current.name).toEqual(partitionZone.name); - return val % 2 === 0; - })); + return observable1.pipe( + partition((val: any) => { + expect(Zone.current.name).toEqual(partitionZone.name); + return val % 2 === 0; + }), + ); }); subscriptionZone.run(() => { part[0].subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('first' + result); - }, - () => { - fail('should not call error'); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('completed'); - }); + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('first' + result); + }, + () => { + fail('should not call error'); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('completed'); + }, + ); part[1].subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('second' + result); - }, - () => { - fail('should not call error'); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('completed'); - }); + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('second' + result); + }, + () => { + fail('should not call error'); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('completed'); + }, + ); }); expect(log).toEqual(['first2', 'completed', 'second1', 'second3', 'completed']); @@ -96,17 +101,18 @@ describe('Observable.map', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('completed'); - }); + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('completed'); + }, + ); }); expect(log).toEqual([1, 3, 'completed']); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.merge.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.merge.spec.ts index 55b8d80d5192f..38c1b58dde35f 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.merge.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.merge.spec.ts @@ -6,7 +6,17 @@ * found in the LICENSE file at https://angular.io/license */ import {interval, merge, Observable, of, range} from 'rxjs'; -import {expand, map, mergeAll, mergeMap, mergeMapTo, switchAll, switchMap, switchMapTo, take} from 'rxjs/operators'; +import { + expand, + map, + mergeAll, + mergeMap, + mergeMapTo, + switchAll, + switchMap, + switchMapTo, + take, +} from 'rxjs/operators'; import {asyncTest, ifEnvSupports} from '../test-util'; @@ -37,15 +47,44 @@ describe('Observable.merge', () => { observable1 = expandZone1.run(() => { return observable1.pipe( - expand((val: any) => { - expect(Zone.current.name).toEqual(expandZone1.name); - return of(1 + val); - }), - take(2)); + expand((val: any) => { + expect(Zone.current.name).toEqual(expandZone1.name); + return of(1 + val); + }), + take(2), + ); }); subscriptionZone.run(() => { observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + ); + }); + expect(log).toEqual([2, 3, 'completed']); + }); + + it( + 'merge func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + const error = new Error('test'); + observable1 = constructorZone1.run(() => { + return merge(interval(10).pipe(take(2)), interval(15).pipe(take(1))); + }); + + subscriptionZone.run(() => { + observable1.subscribe( (result: any) => { log.push(result); expect(Zone.current.name).toEqual(subscriptionZone.name); @@ -56,79 +95,31 @@ describe('Observable.merge', () => { () => { log.push('completed'); expect(Zone.current.name).toEqual(subscriptionZone.name); - }); - }); - expect(log).toEqual([2, 3, 'completed']); - }); - - it('merge func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - const error = new Error('test'); - observable1 = constructorZone1.run(() => { - return merge(interval(10).pipe(take(2)), interval(15).pipe(take(1))); - }); - - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([0, 0, 1, 'completed']); - done(); - }); - }); - }, Zone.root)); - - it('mergeAll func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - const error = new Error('test'); - observable1 = constructorZone1.run(() => { - return of(1, 2).pipe( - map((v: any) => { - return of(v + 1); - }), - mergeAll()); - }); - - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([2, 3, 'completed']); - done(); - }); - }); - }, Zone.root)); + expect(log).toEqual([0, 0, 1, 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); - it('mergeMap func callback should run in the correct zone', () => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - const error = new Error('test'); - observable1 = constructorZone1.run(() => { - return of(1, 2).pipe(mergeMap((v: any) => { - return of(v + 1); - })); - }); + it( + 'mergeAll func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + const error = new Error('test'); + observable1 = constructorZone1.run(() => { + return of(1, 2).pipe( + map((v: any) => { + return of(v + 1); + }), + mergeAll(), + ); + }); - subscriptionZone.run(() => { - observable1.subscribe( + subscriptionZone.run(() => { + observable1.subscribe( (result: any) => { log.push(result); expect(Zone.current.name).toEqual(subscriptionZone.name); @@ -140,7 +131,40 @@ describe('Observable.merge', () => { log.push('completed'); expect(Zone.current.name).toEqual(subscriptionZone.name); expect(log).toEqual([2, 3, 'completed']); - }); + done(); + }, + ); + }); + }, Zone.root), + ); + + it('mergeMap func callback should run in the correct zone', () => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + const error = new Error('test'); + observable1 = constructorZone1.run(() => { + return of(1, 2).pipe( + mergeMap((v: any) => { + return of(v + 1); + }), + ); + }); + + subscriptionZone.run(() => { + observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([2, 3, 'completed']); + }, + ); }); }); @@ -154,18 +178,19 @@ describe('Observable.merge', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([10, 10, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([10, 10, 'completed']); + }, + ); }); }); @@ -174,26 +199,28 @@ describe('Observable.merge', () => { const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); observable1 = constructorZone1.run(() => { return range(0, 3).pipe( - map(function(x: any) { - return range(x, 3); - }), - switchAll()); + map(function (x: any) { + return range(x, 3); + }), + switchAll(), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([0, 1, 2, 1, 2, 3, 2, 3, 4, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([0, 1, 2, 1, 2, 3, 2, 3, 4, 'completed']); + }, + ); }); }); @@ -201,25 +228,28 @@ describe('Observable.merge', () => { const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); observable1 = constructorZone1.run(() => { - return range(0, 3).pipe(switchMap(function(x: any) { - return range(x, 3); - })); + return range(0, 3).pipe( + switchMap(function (x: any) { + return range(x, 3); + }), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([0, 1, 2, 1, 2, 3, 2, 3, 4, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([0, 1, 2, 1, 2, 3, 2, 3, 4, 'completed']); + }, + ); }); }); @@ -232,18 +262,19 @@ describe('Observable.merge', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual(['a', 'a', 'a', 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual(['a', 'a', 'a', 'completed']); + }, + ); }); }); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.multicast.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.multicast.spec.ts index 4a4d06e9c6144..e1602ac719071 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.multicast.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.multicast.spec.ts @@ -8,7 +8,6 @@ import {Observable, of, Subject} from 'rxjs'; import {mapTo, multicast, tap} from 'rxjs/operators'; - // TODO: @JiaLiPassion, Observable.prototype.multicast return a readonly _subscribe // should find another way to patch subscribe describe('Observable.multicast', () => { @@ -30,10 +29,12 @@ describe('Observable.multicast', () => { }); observable1 = doZone1.run(() => { - return observable1.pipe(tap((v: any) => { - expect(Zone.current.name).toEqual(doZone1.name); - log.push('do' + v); - })); + return observable1.pipe( + tap((v: any) => { + expect(Zone.current.name).toEqual(doZone1.name); + log.push('do' + v); + }), + ); }); observable1 = mapZone1.run(() => { @@ -41,10 +42,12 @@ describe('Observable.multicast', () => { }); const multi: any = multicastZone1.run(() => { - return observable1.pipe(multicast(() => { - expect(Zone.current.name).toEqual(multicastZone1.name); - return new Subject(); - })); + return observable1.pipe( + multicast(() => { + expect(Zone.current.name).toEqual(multicastZone1.name); + return new Subject(); + }), + ); }); multi.subscribe((val: any) => { @@ -59,22 +62,37 @@ describe('Observable.multicast', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }); + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + ); }); expect(log).toEqual([ - 'do1', 'onetest', 'twotest', 'do2', 'onetest', 'twotest', 'do3', 'onetest', 'twotest', 'do1', - 'test', 'do2', 'test', 'do3', 'test', 'completed' + 'do1', + 'onetest', + 'twotest', + 'do2', + 'onetest', + 'twotest', + 'do3', + 'onetest', + 'twotest', + 'do1', + 'test', + 'do2', + 'test', + 'do3', + 'test', + 'completed', ]); }); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.notification.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.notification.spec.ts index 4a4b830223752..adfba8cc6719b 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.notification.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.notification.spec.ts @@ -10,47 +10,51 @@ import {dematerialize} from 'rxjs/operators'; import {asyncTest, ifEnvSupports} from '../test-util'; -const supportNotification = function() { +const supportNotification = function () { return typeof Notification !== 'undefined'; }; (supportNotification as any).message = 'RxNotification'; -describe('Observable.notification', ifEnvSupports(supportNotification, () => { - let log: any[]; - let observable1: Observable; +describe( + 'Observable.notification', + ifEnvSupports(supportNotification, () => { + let log: any[]; + let observable1: Observable; - beforeEach(() => { - log = []; - }); + beforeEach(() => { + log = []; + }); - it('notification func callback should run in the correct zone', () => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - const error = new Error('test'); - observable1 = constructorZone1.run(() => { - const notifA = new Notification('N' as any, 'A'); - const notifB = new Notification('N' as any, 'B'); - const notifE = new Notification('E' as any, void 0, error); - const materialized = of(notifA, notifB, notifE as any); - return materialized.pipe(dematerialize()); - }); + it('notification func callback should run in the correct zone', () => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + const error = new Error('test'); + observable1 = constructorZone1.run(() => { + const notifA = new Notification('N' as any, 'A'); + const notifB = new Notification('N' as any, 'B'); + const notifE = new Notification('E' as any, void 0, error); + const materialized = of(notifA, notifB, notifE as any); + return materialized.pipe(dematerialize()); + }); - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - log.push(err); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual(['A', 'B', error]); - }); - }); - }); - })); + subscriptionZone.run(() => { + observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + log.push(err); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual(['A', 'B', error]); + }, + ); + }); + }); + }), +); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.race.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.race.spec.ts index a8656a845a29b..73535316a4b2c 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.race.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.race.spec.ts @@ -18,29 +18,33 @@ describe('Observable.race', () => { log = []; }); - it('race func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return race(interval(10).pipe(mapTo('a')), interval(15).pipe(mapTo('b'))); - }); + it( + 'race func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return race(interval(10).pipe(mapTo('a')), interval(15).pipe(mapTo('b'))); + }); - subscriptionZone.run(() => { - const subscriber: any = observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - subscriber.complete(); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual(['a', 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + const subscriber: any = observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + subscriber.complete(); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual(['a', 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.retry.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.retry.spec.ts index feb08d3e9f10a..27b03aadee22f 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.retry.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.retry.spec.ts @@ -28,31 +28,33 @@ describe('Observable.retryWhen', () => { let isErrorHandled = false; observable1 = constructorZone1.run(() => { return of(1, 2, 3).pipe( - map(v => { - if (v > 2 && !isErrorHandled) { - isErrorHandled = true; - throw v; - } - return v; - }), - retryWhen(err => err.pipe(delayWhen(v => timer(v))))); + map((v) => { + if (v > 2 && !isErrorHandled) { + isErrorHandled = true; + throw v; + } + return v; + }), + retryWhen((err) => err.pipe(delayWhen((v) => timer(v)))), + ); }); subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([1, 2, 1, 2, 3, 'completed']); - done(); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([1, 2, 1, 2, 3, 'completed']); + done(); + }, + ); }); }); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.sample.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.sample.spec.ts index a05a94724b613..23c5bac898177 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.sample.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.sample.spec.ts @@ -18,57 +18,68 @@ describe('Observable.sample', () => { log = []; }); - it('sample func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return interval(10).pipe(sample(interval(15))); - }); + it( + 'sample func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return interval(10).pipe(sample(interval(15))); + }); - subscriptionZone.run(() => { - const subscriber: any = observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - subscriber.complete(); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([0, 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + const subscriber: any = observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + subscriber.complete(); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([0, 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); - xit('throttle func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return interval(10).pipe(take(5), throttle((val: any) => { - expect(Zone.current.name).toEqual(constructorZone1.name); - return interval(20); - })); - }); + xit( + 'throttle func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return interval(10).pipe( + take(5), + throttle((val: any) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + return interval(20); + }), + ); + }); - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([0, 2, 4, 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([0, 2, 4, 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.take.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.take.spec.ts index 979f38319a0ef..59ea9f65d7c5e 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.take.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.take.spec.ts @@ -33,18 +33,19 @@ describe('Observable.take', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([1, 'completed']); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([1, 'completed']); + }, + ); }); }); @@ -57,6 +58,33 @@ describe('Observable.take', () => { subscriptionZone.run(() => { observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([3, 'completed']); + }, + ); + }); + }); + + xit( + 'takeUntil func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return interval(10).pipe(takeUntil(interval(25))); + }); + + subscriptionZone.run(() => { + observable1.subscribe( (result: any) => { log.push(result); expect(Zone.current.name).toEqual(subscriptionZone.name); @@ -67,66 +95,50 @@ describe('Observable.take', () => { () => { log.push('completed'); expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([3, 'completed']); - }); - }); - }); - - xit('takeUntil func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return interval(10).pipe(takeUntil(interval(25))); - }); - - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([0, 1, 'completed']); - done(); - }); - }); - }, Zone.root)); + expect(log).toEqual([0, 1, 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); - it('takeWhile func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const takeZone1: Zone = Zone.current.fork({name: 'Take Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return interval(10); - }); + it( + 'takeWhile func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const takeZone1: Zone = Zone.current.fork({name: 'Take Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return interval(10); + }); - observable1 = takeZone1.run(() => { - return observable1.pipe(takeWhile((val: any) => { - expect(Zone.current.name).toEqual(takeZone1.name); - return val < 2; - })); - }); + observable1 = takeZone1.run(() => { + return observable1.pipe( + takeWhile((val: any) => { + expect(Zone.current.name).toEqual(takeZone1.name); + return val < 2; + }), + ); + }); - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([0, 1, 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([0, 1, 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.timeout.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.timeout.spec.ts index 589ddf592ccbd..9f75c1773e1ed 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.timeout.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.timeout.spec.ts @@ -18,52 +18,60 @@ describe('Observable.timeout', () => { log = []; }); - it('timeout func callback should run in the correct zone', asyncTest((done: any) => { - if (isPhantomJS()) { - done(); - return; - } - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return of(1).pipe(timeout(10)); - }); + it( + 'timeout func callback should run in the correct zone', + asyncTest((done: any) => { + if (isPhantomJS()) { + done(); + return; + } + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return of(1).pipe(timeout(10)); + }); - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([1, 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([1, 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); - it('promise should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - const promise: any = constructorZone1.run(() => { - return of(1).toPromise(); - }); + it( + 'promise should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + const promise: any = constructorZone1.run(() => { + return of(1).toPromise(); + }); - subscriptionZone.run(() => { - promise.then( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(result).toEqual(1); - done(); - }, - (err: any) => { - fail('should not call error'); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + promise.then( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(result).toEqual(1); + done(); + }, + (err: any) => { + fail('should not call error'); + }, + ); + }); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.Observable.window.spec.ts b/packages/zone.js/test/rxjs/rxjs.Observable.window.spec.ts index 8af748f053b94..83c62b26e9821 100644 --- a/packages/zone.js/test/rxjs/rxjs.Observable.window.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.Observable.window.spec.ts @@ -10,7 +10,6 @@ import {mergeAll, take, window, windowCount, windowToggle, windowWhen} from 'rxj import {asyncTest} from '../test-util'; - // @JiaLiPassion, in Safari 9(iOS 9), the case is not // stable because of the timer, try to fix it later xdescribe('Observable.window', () => { @@ -21,129 +20,149 @@ xdescribe('Observable.window', () => { log = []; }); - it('window func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - const error = new Error('test'); - observable1 = constructorZone1.run(() => { - const source = timer(0, 10).pipe(take(6)); - const w = source.pipe(window(interval(30))); - return w.pipe(mergeAll()); - }); + it( + 'window func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + const error = new Error('test'); + observable1 = constructorZone1.run(() => { + const source = timer(0, 10).pipe(take(6)); + const w = source.pipe(window(interval(30))); + return w.pipe(mergeAll()); + }); - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([0, 1, 2, 3, 4, 5, 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([0, 1, 2, 3, 4, 5, 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); - it('windowCount func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - const error = new Error('test'); - observable1 = constructorZone1.run(() => { - const source = timer(0, 10).pipe(take(10)); - const window = source.pipe(windowCount(4)); - return window.pipe(mergeAll()); - }); + it( + 'windowCount func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + const error = new Error('test'); + observable1 = constructorZone1.run(() => { + const source = timer(0, 10).pipe(take(10)); + const window = source.pipe(windowCount(4)); + return window.pipe(mergeAll()); + }); - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); - it('windowToggle func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const windowZone1: Zone = Zone.current.fork({name: 'Window Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - const error = new Error('test'); - observable1 = constructorZone1.run(() => { - return timer(0, 10).pipe(take(10)); - }); + it( + 'windowToggle func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const windowZone1: Zone = Zone.current.fork({name: 'Window Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + const error = new Error('test'); + observable1 = constructorZone1.run(() => { + return timer(0, 10).pipe(take(10)); + }); - windowZone1.run(() => { - return observable1.pipe(windowToggle(interval(30), (val: any) => { - expect(Zone.current.name).toEqual(windowZone1.name); - return interval(15); - }), mergeAll()); - }); + windowZone1.run(() => { + return observable1.pipe( + windowToggle(interval(30), (val: any) => { + expect(Zone.current.name).toEqual(windowZone1.name); + return interval(15); + }), + mergeAll(), + ); + }); - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); - it('windowWhen func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const windowZone1: Zone = Zone.current.fork({name: 'Window Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - const error = new Error('test'); - observable1 = constructorZone1.run(() => { - return timer(0, 10).pipe(take(10)); - }); + it( + 'windowWhen func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const windowZone1: Zone = Zone.current.fork({name: 'Window Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + const error = new Error('test'); + observable1 = constructorZone1.run(() => { + return timer(0, 10).pipe(take(10)); + }); - windowZone1.run(() => { - return observable1.pipe( - windowWhen(() => { - expect(Zone.current.name).toEqual(windowZone1.name); - return interval(15); - }), - mergeAll()); - }); + windowZone1.run(() => { + return observable1.pipe( + windowWhen(() => { + expect(Zone.current.name).toEqual(windowZone1.name); + return interval(15); + }), + mergeAll(), + ); + }); - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - (err: any) => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + (err: any) => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.asap.spec.ts b/packages/zone.js/test/rxjs/rxjs.asap.spec.ts index 18176ee9c5d74..627d6ac7d9258 100644 --- a/packages/zone.js/test/rxjs/rxjs.asap.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.asap.spec.ts @@ -20,51 +20,65 @@ describe('Scheduler.asap', () => { log = []; }); - it('scheduler asap should run in correct zone', asyncTest((done: any) => { - let observable: any; - constructorZone.run(() => { - observable = of(1, 2, 3).pipe(observeOn(asapScheduler)); - }); + it( + 'scheduler asap should run in correct zone', + asyncTest((done: any) => { + let observable: any; + constructorZone.run(() => { + observable = of(1, 2, 3).pipe(observeOn(asapScheduler)); + }); - const zone = Zone.current.fork({name: 'subscribeZone'}); + const zone = Zone.current.fork({name: 'subscribeZone'}); - zone.run(() => { - observable - .pipe(map((value: number) => { - return value; - })) - .subscribe( - (value: number) => { - expect(Zone.current.name).toEqual(zone.name); - if (value === 3) { - setTimeout(done); - } - }, - (err: any) => { - fail('should not be here'); - }); - }); - }, Zone.root)); + zone.run(() => { + observable + .pipe( + map((value: number) => { + return value; + }), + ) + .subscribe( + (value: number) => { + expect(Zone.current.name).toEqual(zone.name); + if (value === 3) { + setTimeout(done); + } + }, + (err: any) => { + fail('should not be here'); + }, + ); + }); + }, Zone.root), + ); - it('scheduler asap error should run in correct zone', asyncTest((done: any) => { - let observable: any; - constructorZone.run(() => { - observable = of(1, 2, 3).pipe(observeOn(asapScheduler)); - }); + it( + 'scheduler asap error should run in correct zone', + asyncTest((done: any) => { + let observable: any; + constructorZone.run(() => { + observable = of(1, 2, 3).pipe(observeOn(asapScheduler)); + }); - Zone.root.run(() => { - observable - .pipe(map((value: number) => { - if (value === 3) { - throw new Error('oops'); - } - return value; - })) - .subscribe((value: number) => {}, (err: any) => { - expect(err.message).toEqual('oops'); - expect(Zone.current.name).toEqual(''); - done(); - }); - }); - }, Zone.root)); + Zone.root.run(() => { + observable + .pipe( + map((value: number) => { + if (value === 3) { + throw new Error('oops'); + } + return value; + }), + ) + .subscribe( + (value: number) => {}, + (err: any) => { + expect(err.message).toEqual('oops'); + expect(Zone.current.name).toEqual(''); + done(); + }, + ); + }); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.bindCallback.spec.ts b/packages/zone.js/test/rxjs/rxjs.bindCallback.spec.ts index 1ddf6a9b1596e..ac76cc39f9bff 100644 --- a/packages/zone.js/test/rxjs/rxjs.bindCallback.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.bindCallback.spec.ts @@ -24,7 +24,7 @@ describe('Observable.bindCallback', () => { it('bindCallback func callback should run in the correct zone', () => { constructorZone.run(() => { - func = function(arg0: any, callback: Function) { + func = function (arg0: any, callback: Function) { expect(Zone.current.name).toEqual(constructorZone.name); callback(arg0); }; @@ -44,7 +44,7 @@ describe('Observable.bindCallback', () => { it('bindCallback with selector should run in correct zone', () => { constructorZone.run(() => { - func = function(arg0: any, callback: Function) { + func = function (arg0: any, callback: Function) { expect(Zone.current.name).toEqual(constructorZone.name); callback(arg0); }; @@ -65,24 +65,27 @@ describe('Observable.bindCallback', () => { expect(log).toEqual(['nextselectortest']); }); - it('bindCallback with async scheduler should run in correct zone', asyncTest((done: any) => { - constructorZone.run(() => { - func = function(arg0: any, callback: Function) { - expect(Zone.current.name).toEqual(constructorZone.name); - callback(arg0); - }; - boundFunc = bindCallback(func, () => true, asapScheduler); - observable = boundFunc('test'); - }); + it( + 'bindCallback with async scheduler should run in correct zone', + asyncTest((done: any) => { + constructorZone.run(() => { + func = function (arg0: any, callback: Function) { + expect(Zone.current.name).toEqual(constructorZone.name); + callback(arg0); + }; + boundFunc = bindCallback(func, () => true, asapScheduler); + observable = boundFunc('test'); + }); - subscriptionZone.run(() => { - observable.subscribe((arg: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('next' + arg); - done(); - }); - }); + subscriptionZone.run(() => { + observable.subscribe((arg: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('next' + arg); + done(); + }); + }); - expect(log).toEqual([]); - }, Zone.root)); + expect(log).toEqual([]); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.bindNodeCallback.spec.ts b/packages/zone.js/test/rxjs/rxjs.bindNodeCallback.spec.ts index fb1b9e0991124..d6bc2970e1e67 100644 --- a/packages/zone.js/test/rxjs/rxjs.bindNodeCallback.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.bindNodeCallback.spec.ts @@ -24,7 +24,7 @@ describe('Observable.bindNodeCallback', () => { it('bindNodeCallback func callback should run in the correct zone', () => { constructorZone.run(() => { - func = function(arg: any, callback: (error: any, result: any) => any) { + func = function (arg: any, callback: (error: any, result: any) => any) { expect(Zone.current.name).toEqual(constructorZone.name); callback(null, arg); }; @@ -44,7 +44,7 @@ describe('Observable.bindNodeCallback', () => { it('bindNodeCallback with selector should run in correct zone', () => { constructorZone.run(() => { - func = function(arg: any, callback: (error: any, result: any) => any) { + func = function (arg: any, callback: (error: any, result: any) => any) { expect(Zone.current.name).toEqual(constructorZone.name); callback(null, arg); }; @@ -65,30 +65,33 @@ describe('Observable.bindNodeCallback', () => { expect(log).toEqual(['nextselectortest']); }); - it('bindNodeCallback with async scheduler should run in correct zone', asyncTest((done: any) => { - constructorZone.run(() => { - func = function(arg: any, callback: (error: any, result: any) => any) { - expect(Zone.current.name).toEqual(constructorZone.name); - callback(null, arg); - }; - boundFunc = bindCallback(func, () => true, asapScheduler); - observable = boundFunc('test'); - }); - - subscriptionZone.run(() => { - observable.subscribe((arg: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('next' + arg); - done(); - }); - }); - - expect(log).toEqual([]); - })); + it( + 'bindNodeCallback with async scheduler should run in correct zone', + asyncTest((done: any) => { + constructorZone.run(() => { + func = function (arg: any, callback: (error: any, result: any) => any) { + expect(Zone.current.name).toEqual(constructorZone.name); + callback(null, arg); + }; + boundFunc = bindCallback(func, () => true, asapScheduler); + observable = boundFunc('test'); + }); + + subscriptionZone.run(() => { + observable.subscribe((arg: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('next' + arg); + done(); + }); + }); + + expect(log).toEqual([]); + }), + ); it('bindNodeCallback call with error should run in correct zone', () => { constructorZone.run(() => { - func = function(arg: any, callback: (error: any, result: any) => any) { + func = function (arg: any, callback: (error: any, result: any) => any) { expect(Zone.current.name).toEqual(constructorZone.name); callback(arg, null); }; @@ -98,13 +101,14 @@ describe('Observable.bindNodeCallback', () => { subscriptionZone.run(() => { observable.subscribe( - (arg: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('next' + arg); - }, - (error: any) => { - log.push('error' + error); - }); + (arg: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('next' + arg); + }, + (error: any) => { + log.push('error' + error); + }, + ); }); expect(log).toEqual(['nexttest,']); diff --git a/packages/zone.js/test/rxjs/rxjs.combineLatest.spec.ts b/packages/zone.js/test/rxjs/rxjs.combineLatest.spec.ts index 5f7e5bcbf3b9f..8b776779076c0 100644 --- a/packages/zone.js/test/rxjs/rxjs.combineLatest.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.combineLatest.spec.ts @@ -26,16 +26,22 @@ describe('Observable.combineLatest', () => { }); it('combineLatest func should run in the correct zone', () => { - observable1 = constructorZone1.run(() => new Observable((_subscriber) => { - subscriber1 = _subscriber; - expect(Zone.current.name).toEqual(constructorZone1.name); - log.push('setup1'); - })); - observable2 = constructorZone2.run(() => new Observable((_subscriber) => { - subscriber2 = _subscriber; - expect(Zone.current.name).toEqual(constructorZone2.name); - log.push('setup2'); - })); + observable1 = constructorZone1.run( + () => + new Observable((_subscriber) => { + subscriber1 = _subscriber; + expect(Zone.current.name).toEqual(constructorZone1.name); + log.push('setup1'); + }), + ); + observable2 = constructorZone2.run( + () => + new Observable((_subscriber) => { + subscriber2 = _subscriber; + expect(Zone.current.name).toEqual(constructorZone2.name); + log.push('setup2'); + }), + ); constructorZone3.run(() => { combinedObservable = combineLatest(observable1, observable2); @@ -56,16 +62,22 @@ describe('Observable.combineLatest', () => { }); it('combineLatest func with project function should run in the correct zone', () => { - observable1 = constructorZone1.run(() => new Observable((_subscriber) => { - subscriber1 = _subscriber; - expect(Zone.current.name).toEqual(constructorZone1.name); - log.push('setup1'); - })); - observable2 = constructorZone2.run(() => new Observable((_subscriber) => { - subscriber2 = _subscriber; - expect(Zone.current.name).toEqual(constructorZone2.name); - log.push('setup2'); - })); + observable1 = constructorZone1.run( + () => + new Observable((_subscriber) => { + subscriber1 = _subscriber; + expect(Zone.current.name).toEqual(constructorZone1.name); + log.push('setup1'); + }), + ); + observable2 = constructorZone2.run( + () => + new Observable((_subscriber) => { + subscriber2 = _subscriber; + expect(Zone.current.name).toEqual(constructorZone2.name); + log.push('setup2'); + }), + ); constructorZone3.run(() => { combinedObservable = combineLatest(observable1, observable2, (x: number, y: number) => { diff --git a/packages/zone.js/test/rxjs/rxjs.common.spec.ts b/packages/zone.js/test/rxjs/rxjs.common.spec.ts index f1601996c730a..a158f2cf72b58 100644 --- a/packages/zone.js/test/rxjs/rxjs.common.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.common.spec.ts @@ -27,37 +27,47 @@ describe('Zone interaction', () => { const constructorZone: Zone = Zone.current.fork({name: 'Constructor Zone'}); const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); let subscriber: any = null; - const observable: any = - constructorZone.run(() => new Observable((_subscriber: any) => { - subscriber = _subscriber; - log.push('setup'); - expect(Zone.current.name).toEqual(constructorZone.name); - return () => { - expect(Zone.current.name).toEqual(constructorZone.name); - log.push('cleanup'); - }; - })); - subscriptionZone.run( - () => observable.subscribe( - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('next'); - }, - (): any => null, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('complete'); - })); + const observable: any = constructorZone.run( + () => + new Observable((_subscriber: any) => { + subscriber = _subscriber; + log.push('setup'); + expect(Zone.current.name).toEqual(constructorZone.name); + return () => { + expect(Zone.current.name).toEqual(constructorZone.name); + log.push('cleanup'); + }; + }), + ); + subscriptionZone.run(() => + observable.subscribe( + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('next'); + }, + (): any => null, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('complete'); + }, + ), + ); subscriber.next('MyValue'); subscriber.complete(); expect(log).toEqual(['setup', 'next', 'complete', 'cleanup']); log.length = 0; - subscriptionZone.run(() => observable.subscribe((): any => null, () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('error'); - }, (): any => null)); + subscriptionZone.run(() => + observable.subscribe( + (): any => null, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('error'); + }, + (): any => null, + ), + ); subscriber.next('MyValue'); subscriber.error('MyError'); @@ -69,32 +79,36 @@ describe('Zone interaction', () => { const rootZone: Zone = Zone.current; const constructorZone: Zone = Zone.current.fork({name: 'Constructor Zone'}); const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - const observable: any = - constructorZone.run(() => new Observable((subscriber: any) => { - // Execute the `next`/`complete` in different zone, and assert that - // correct zone - // is restored. - rootZone.run(() => { - subscriber.next('MyValue'); - subscriber.complete(); - }); - return () => { - expect(Zone.current.name).toEqual(constructorZone.name); - log.push('cleanup'); - }; - })); - - subscriptionZone.run( - () => observable.subscribe( - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('next'); - }, - (): any => null, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('complete'); - })); + const observable: any = constructorZone.run( + () => + new Observable((subscriber: any) => { + // Execute the `next`/`complete` in different zone, and assert that + // correct zone + // is restored. + rootZone.run(() => { + subscriber.next('MyValue'); + subscriber.complete(); + }); + return () => { + expect(Zone.current.name).toEqual(constructorZone.name); + log.push('cleanup'); + }; + }), + ); + + subscriptionZone.run(() => + observable.subscribe( + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('next'); + }, + (): any => null, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('complete'); + }, + ), + ); expect(log).toEqual(['next', 'complete', 'cleanup']); }); @@ -105,41 +119,49 @@ describe('Zone interaction', () => { const constructorZone: Zone = Zone.current.fork({name: 'Constructor Zone'}); const operatorZone: Zone = Zone.current.fork({name: 'Operator Zone'}); const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - let observable: any = - constructorZone.run(() => new Observable((subscriber: any) => { - // Execute the `next`/`complete` in different zone, and assert that - // correct zone - // is restored. - rootZone.run(() => { - subscriber.next('MyValue'); - subscriber.complete(); - }); - return () => { - expect(Zone.current.name).toEqual(constructorZone.name); - log.push('cleanup'); - }; - })); - - observable = operatorZone.run(() => observable.pipe(map((value: any) => { - expect(Zone.current.name).toEqual(operatorZone.name); - log.push('map: ' + value); - return value; - }))); - - subscriptionZone.run( - () => observable.subscribe( - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('next'); - }, - (e: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('error: ' + e); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('complete'); - })); + let observable: any = constructorZone.run( + () => + new Observable((subscriber: any) => { + // Execute the `next`/`complete` in different zone, and assert that + // correct zone + // is restored. + rootZone.run(() => { + subscriber.next('MyValue'); + subscriber.complete(); + }); + return () => { + expect(Zone.current.name).toEqual(constructorZone.name); + log.push('cleanup'); + }; + }), + ); + + observable = operatorZone.run(() => + observable.pipe( + map((value: any) => { + expect(Zone.current.name).toEqual(operatorZone.name); + log.push('map: ' + value); + return value; + }), + ), + ); + + subscriptionZone.run(() => + observable.subscribe( + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('next'); + }, + (e: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('error: ' + e); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('complete'); + }, + ), + ); expect(log).toEqual(['map: MyValue', 'next', 'complete', 'cleanup']); }); @@ -147,15 +169,17 @@ describe('Zone interaction', () => { it('should run subscribe in zone of declaration with Observable.create', () => { const log: any[] = []; const constructorZone: Zone = Zone.current.fork({name: 'Constructor Zone'}); - let observable: any = constructorZone.run(() => Observable.create((subscriber: any) => { - expect(Zone.current.name).toEqual(constructorZone.name); - subscriber.next(1); - subscriber.complete(); - return () => { + let observable: any = constructorZone.run(() => + Observable.create((subscriber: any) => { expect(Zone.current.name).toEqual(constructorZone.name); - log.push('cleanup'); - }; - })); + subscriber.next(1); + subscriber.complete(); + return () => { + expect(Zone.current.name).toEqual(constructorZone.name); + log.push('cleanup'); + }; + }), + ); observable.subscribe(() => { log.push('next'); @@ -181,28 +205,30 @@ describe('Zone interaction', () => { subscriptionZone1.run(() => { subscription1 = subject.subscribe( - () => { - expect(Zone.current.name).toEqual(subscriptionZone1.name); - log.push('next1'); - }, - () => {}, - () => { - expect(Zone.current.name).toEqual(subscriptionZone1.name); - log.push('complete1'); - }); + () => { + expect(Zone.current.name).toEqual(subscriptionZone1.name); + log.push('next1'); + }, + () => {}, + () => { + expect(Zone.current.name).toEqual(subscriptionZone1.name); + log.push('complete1'); + }, + ); }); subscriptionZone2.run(() => { subscription2 = subject.subscribe( - () => { - expect(Zone.current.name).toEqual(subscriptionZone2.name); - log.push('next2'); - }, - () => {}, - () => { - expect(Zone.current.name).toEqual(subscriptionZone2.name); - log.push('complete2'); - }); + () => { + expect(Zone.current.name).toEqual(subscriptionZone2.name); + log.push('next2'); + }, + () => {}, + () => { + expect(Zone.current.name).toEqual(subscriptionZone2.name); + log.push('complete2'); + }, + ); }); subject.next(1); diff --git a/packages/zone.js/test/rxjs/rxjs.concat.spec.ts b/packages/zone.js/test/rxjs/rxjs.concat.spec.ts index 14e39159dd56f..ef7dcd00c230a 100644 --- a/packages/zone.js/test/rxjs/rxjs.concat.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.concat.spec.ts @@ -27,7 +27,7 @@ describe('Observable.concat', () => { it('concat func callback should run in the correct zone', () => { observable1 = constructorZone1.run(() => { - return new Observable(subscriber => { + return new Observable((subscriber) => { expect(Zone.current.name).toEqual(constructorZone1.name); subscriber.next(1); subscriber.next(2); @@ -53,45 +53,48 @@ describe('Observable.concat', () => { expect(log).toEqual([1, 2, 3, 4, 5, 6]); }); - it('concat func callback should run in the correct zone with scheduler', - asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const constructorZone2: Zone = Zone.current.fork({name: 'Constructor Zone2'}); - const constructorZone3: Zone = Zone.current.fork({name: 'Constructor Zone3'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return new Observable(subscriber => { - expect(Zone.current.name).toEqual(constructorZone1.name); - subscriber.next(1); - subscriber.next(2); - subscriber.complete(); - }); - }); + it( + 'concat func callback should run in the correct zone with scheduler', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const constructorZone2: Zone = Zone.current.fork({name: 'Constructor Zone2'}); + const constructorZone3: Zone = Zone.current.fork({name: 'Constructor Zone3'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return new Observable((subscriber) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + subscriber.next(1); + subscriber.next(2); + subscriber.complete(); + }); + }); - observable2 = constructorZone2.run(() => { - return range(3, 4); - }); + observable2 = constructorZone2.run(() => { + return range(3, 4); + }); - constructorZone3.run(() => { - concatObservable = concat(observable1, observable2, asapScheduler); - }); + constructorZone3.run(() => { + concatObservable = concat(observable1, observable2, asapScheduler); + }); - subscriptionZone.run(() => { - concatObservable.subscribe( - (concat: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(concat); - }, - (error: any) => { - fail('subscribe failed' + error); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([1, 2, 3, 4, 5, 6]); - done(); - }); - }); + subscriptionZone.run(() => { + concatObservable.subscribe( + (concat: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(concat); + }, + (error: any) => { + fail('subscribe failed' + error); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([1, 2, 3, 4, 5, 6]); + done(); + }, + ); + }); - expect(log).toEqual([]); - }, Zone.root)); + expect(log).toEqual([]); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.defer.spec.ts b/packages/zone.js/test/rxjs/rxjs.defer.spec.ts index 7f46ed938f6dd..f9bc5b85c8aaf 100644 --- a/packages/zone.js/test/rxjs/rxjs.defer.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.defer.spec.ts @@ -21,7 +21,7 @@ describe('Observable.defer', () => { it('defer func callback should run in the correct zone', () => { observable1 = constructorZone1.run(() => { return defer(() => { - return new Observable(subscribe => { + return new Observable((subscribe) => { log.push('setup'); expect(Zone.current.name).toEqual(constructorZone1.name); subscribe.next(1); diff --git a/packages/zone.js/test/rxjs/rxjs.empty.spec.ts b/packages/zone.js/test/rxjs/rxjs.empty.spec.ts index 1775aff11952e..07e3b38c2aaab 100644 --- a/packages/zone.js/test/rxjs/rxjs.empty.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.empty.spec.ts @@ -24,15 +24,16 @@ describe('Observable.empty', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - fail('should not call next'); - }, - () => { - fail('should not call error'); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - }); + (result: any) => { + fail('should not call next'); + }, + () => { + fail('should not call error'); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + ); }); }); }); diff --git a/packages/zone.js/test/rxjs/rxjs.forkjoin.spec.ts b/packages/zone.js/test/rxjs/rxjs.forkjoin.spec.ts index 4c4416988705e..f301e3a71f412 100644 --- a/packages/zone.js/test/rxjs/rxjs.forkjoin.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.forkjoin.spec.ts @@ -25,17 +25,18 @@ describe('Observable.forkjoin', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('completed'); - }); + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('completed'); + }, + ); }); expect(log).toEqual([[2, 5], 'completed']); @@ -51,17 +52,18 @@ describe('Observable.forkjoin', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('completed'); - }); + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('completed'); + }, + ); }); expect(log).toEqual([7, 'completed']); diff --git a/packages/zone.js/test/rxjs/rxjs.from.spec.ts b/packages/zone.js/test/rxjs/rxjs.from.spec.ts index dad532d35f302..e7f0f9fe3dedd 100644 --- a/packages/zone.js/test/rxjs/rxjs.from.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.from.spec.ts @@ -26,17 +26,18 @@ describe('Observable.from', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('completed'); - }); + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('completed'); + }, + ); }); expect(log).toEqual([1, 2, 'completed']); @@ -49,48 +50,55 @@ describe('Observable.from', () => { subscriptionZone.run(() => { observable1.subscribe( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('completed'); + }, + ); + }); + + expect(log).toEqual(['f', 'o', 'o', 'completed']); + }); + + it( + 'from promise object should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return from( + new Promise((resolve, reject) => { + resolve(1); + }), + ); + }); + + subscriptionZone.run(() => { + observable1.subscribe( (result: any) => { expect(Zone.current.name).toEqual(subscriptionZone.name); log.push(result); }, - () => { - fail('should not call error'); + (error: any) => { + fail('should not call error' + error); }, () => { expect(Zone.current.name).toEqual(subscriptionZone.name); log.push('completed'); - }); - }); - - expect(log).toEqual(['f', 'o', 'o', 'completed']); - }); - - it('from promise object should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return from(new Promise((resolve, reject) => { - resolve(1); - })); - }); - - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - (error: any) => { - fail('should not call error' + error); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('completed'); - expect(log).toEqual([1, 'completed']); - done(); - }); - }); + expect(log).toEqual([1, 'completed']); + done(); + }, + ); + }); - expect(log).toEqual([]); - }, Zone.root)); + expect(log).toEqual([]); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.fromEvent.spec.ts b/packages/zone.js/test/rxjs/rxjs.fromEvent.spec.ts index 6061fa948c243..ca08129336666 100644 --- a/packages/zone.js/test/rxjs/rxjs.fromEvent.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.fromEvent.spec.ts @@ -28,78 +28,85 @@ describe('Observable.fromEvent', () => { log = []; }); - it('fromEvent EventTarget func callback should run in the correct zone', - ifEnvSupports(isEventTarget, () => { - observable1 = constructorZone1.run(() => { - return fromEvent(document, 'click'); - }); + it( + 'fromEvent EventTarget func callback should run in the correct zone', + ifEnvSupports(isEventTarget, () => { + observable1 = constructorZone1.run(() => { + return fromEvent(document, 'click'); + }); - const clickEvent = document.createEvent('Event'); - clickEvent.initEvent('click', true, true); + const clickEvent = document.createEvent('Event'); + clickEvent.initEvent('click', true, true); - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('completed'); - }); - }); + subscriptionZone.run(() => { + observable1.subscribe( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('completed'); + }, + ); + }); - triggerZone.run(() => { - document.dispatchEvent(clickEvent); - }); + triggerZone.run(() => { + document.dispatchEvent(clickEvent); + }); - expect(log).toEqual([clickEvent]); - })); + expect(log).toEqual([clickEvent]); + }), + ); - it('fromEventPattern EventTarget func callback should run in the correct zone', - ifEnvSupports(isEventTarget, () => { - const button = document.createElement('button'); - document.body.appendChild(button); - observable1 = constructorZone1.run(() => { - return fromEventPattern( - (handler: any) => { - expect(Zone.current.name).toEqual(constructorZone1.name); - button.addEventListener('click', handler); - log.push('addListener'); - }, - (handler: any) => { - expect(Zone.current.name).toEqual(constructorZone1.name); - button.removeEventListener('click', handler); - document.body.removeChild(button); - log.push('removeListener'); - }); - }); + it( + 'fromEventPattern EventTarget func callback should run in the correct zone', + ifEnvSupports(isEventTarget, () => { + const button = document.createElement('button'); + document.body.appendChild(button); + observable1 = constructorZone1.run(() => { + return fromEventPattern( + (handler: any) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + button.addEventListener('click', handler); + log.push('addListener'); + }, + (handler: any) => { + expect(Zone.current.name).toEqual(constructorZone1.name); + button.removeEventListener('click', handler); + document.body.removeChild(button); + log.push('removeListener'); + }, + ); + }); - const clickEvent = document.createEvent('Event'); - clickEvent.initEvent('click', false, false); + const clickEvent = document.createEvent('Event'); + clickEvent.initEvent('click', false, false); - const subscriper: any = subscriptionZone.run(() => { - return observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('completed'); - }); - }); + const subscriper: any = subscriptionZone.run(() => { + return observable1.subscribe( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('completed'); + }, + ); + }); - triggerZone.run(() => { - button.dispatchEvent(clickEvent); - subscriper.complete(); - }); - expect(log).toEqual(['addListener', clickEvent, 'completed', 'removeListener']); - })); + triggerZone.run(() => { + button.dispatchEvent(clickEvent); + subscriper.complete(); + }); + expect(log).toEqual(['addListener', clickEvent, 'completed', 'removeListener']); + }), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.fromPromise.spec.ts b/packages/zone.js/test/rxjs/rxjs.fromPromise.spec.ts index b04c2ef6b7783..9568d231774c3 100644 --- a/packages/zone.js/test/rxjs/rxjs.fromPromise.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.fromPromise.spec.ts @@ -17,35 +17,39 @@ describe('Observable.fromPromise', () => { log = []; }); - it('fromPromise func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const promiseZone1: Zone = Zone.current.fork({name: 'Promise Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - let res: any; - let promise: any = promiseZone1.run(() => { - return new Promise((resolve, reject) => { - res = resolve; - }); - }); - observable1 = constructorZone1.run(() => { - return from(promise); - }); + it( + 'fromPromise func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const promiseZone1: Zone = Zone.current.fork({name: 'Promise Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + let res: any; + let promise: any = promiseZone1.run(() => { + return new Promise((resolve, reject) => { + res = resolve; + }); + }); + observable1 = constructorZone1.run(() => { + return from(promise); + }); - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - expect(log).toEqual([1]); - done(); - }, - () => { - fail('should not call error'); - }, - () => {}); - }); - res(1); + subscriptionZone.run(() => { + observable1.subscribe( + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + expect(log).toEqual([1]); + done(); + }, + () => { + fail('should not call error'); + }, + () => {}, + ); + }); + res(1); - expect(log).toEqual([]); - }, Zone.root)); + expect(log).toEqual([]); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.interval.spec.ts b/packages/zone.js/test/rxjs/rxjs.interval.spec.ts index ac61ea5eedbab..de24d35df931d 100644 --- a/packages/zone.js/test/rxjs/rxjs.interval.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.interval.spec.ts @@ -17,28 +17,32 @@ describe('Observable.interval', () => { log = []; }); - it('interval func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return interval(10); - }); + it( + 'interval func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return interval(10); + }); - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - if (result >= 3) { - subscriber.unsubscribe(); - expect(log).toEqual([0, 1, 2, 3]); - done(); - } - }, - () => { - fail('should not call error'); - }, - () => {}); - }); - }, Zone.root)); + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + if (result >= 3) { + subscriber.unsubscribe(); + expect(log).toEqual([0, 1, 2, 3]); + done(); + } + }, + () => { + fail('should not call error'); + }, + () => {}, + ); + }); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.merge.spec.ts b/packages/zone.js/test/rxjs/rxjs.merge.spec.ts index 2a77f06b56d07..275c5d61d5376 100644 --- a/packages/zone.js/test/rxjs/rxjs.merge.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.merge.spec.ts @@ -17,38 +17,48 @@ describe('Observable.merge', () => { log = []; }); - it('merge func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const constructorZone2: Zone = Zone.current.fork({name: 'Constructor Zone2'}); - const constructorZone3: Zone = Zone.current.fork({name: 'Constructor Zone3'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - const observable1: any = constructorZone1.run(() => { - return interval(8).pipe(map(v => 'observable1' + v), take(1)); - }); + it( + 'merge func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const constructorZone2: Zone = Zone.current.fork({name: 'Constructor Zone2'}); + const constructorZone3: Zone = Zone.current.fork({name: 'Constructor Zone3'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + const observable1: any = constructorZone1.run(() => { + return interval(8).pipe( + map((v) => 'observable1' + v), + take(1), + ); + }); - const observable2: any = constructorZone2.run(() => { - return interval(10).pipe(map(v => 'observable2' + v), take(1)); - }); + const observable2: any = constructorZone2.run(() => { + return interval(10).pipe( + map((v) => 'observable2' + v), + take(1), + ); + }); - const observable3: any = constructorZone3.run(() => { - return merge(observable1, observable2); - }); + const observable3: any = constructorZone3.run(() => { + return merge(observable1, observable2); + }); - subscriptionZone.run(() => { - const subscriber = observable3.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual(['observable10', 'observable20', 'completed']); - done(); - }); - }); - }, Zone.root)); + subscriptionZone.run(() => { + const subscriber = observable3.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual(['observable10', 'observable20', 'completed']); + done(); + }, + ); + }); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.never.spec.ts b/packages/zone.js/test/rxjs/rxjs.never.spec.ts index 6ede4b68a9677..daf8fc88597d4 100644 --- a/packages/zone.js/test/rxjs/rxjs.never.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.never.spec.ts @@ -25,16 +25,17 @@ describe('Observable.never', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - fail('should not call complete'); - }); + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + fail('should not call complete'); + }, + ); }); expect(log).toEqual([7]); diff --git a/packages/zone.js/test/rxjs/rxjs.of.spec.ts b/packages/zone.js/test/rxjs/rxjs.of.spec.ts index d257dd913c01e..93c6f50ee667a 100644 --- a/packages/zone.js/test/rxjs/rxjs.of.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.of.spec.ts @@ -24,17 +24,18 @@ describe('Observable.of', () => { subscriptionZone.run(() => { observable1.subscribe( - (result: any) => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push(result); - }, - () => { - fail('should not call error'); - }, - () => { - expect(Zone.current.name).toEqual(subscriptionZone.name); - log.push('completed'); - }); + (result: any) => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push(result); + }, + () => { + fail('should not call error'); + }, + () => { + expect(Zone.current.name).toEqual(subscriptionZone.name); + log.push('completed'); + }, + ); }); expect(log).toEqual([1, 2, 3, 'completed']); diff --git a/packages/zone.js/test/rxjs/rxjs.range.spec.ts b/packages/zone.js/test/rxjs/rxjs.range.spec.ts index 62baea2cc9dbf..e0e187dab3ddb 100644 --- a/packages/zone.js/test/rxjs/rxjs.range.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.range.spec.ts @@ -26,6 +26,34 @@ describe('Observable.range', () => { subscriptionZone.run(() => { observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + ); + }); + + expect(log).toEqual([1, 2, 3, 'completed']); + }); + + it( + 'range func callback should run in the correct zone with scheduler', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return range(1, 3, asapScheduler); + }); + + subscriptionZone.run(() => { + observable1.subscribe( (result: any) => { log.push(result); expect(Zone.current.name).toEqual(subscriptionZone.name); @@ -36,36 +64,13 @@ describe('Observable.range', () => { () => { log.push('completed'); expect(Zone.current.name).toEqual(subscriptionZone.name); - }); - }); - - expect(log).toEqual([1, 2, 3, 'completed']); - }); - - it('range func callback should run in the correct zone with scheduler', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return range(1, 3, asapScheduler); - }); - - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([1, 2, 3, 'completed']); - done(); - }); - }); + expect(log).toEqual([1, 2, 3, 'completed']); + done(); + }, + ); + }); - expect(log).toEqual([]); - }, Zone.root)); + expect(log).toEqual([]); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.retry.spec.ts b/packages/zone.js/test/rxjs/rxjs.retry.spec.ts index 28501f222def4..f7b97e62f4d4f 100644 --- a/packages/zone.js/test/rxjs/rxjs.retry.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.retry.spec.ts @@ -11,16 +11,17 @@ import {catchError, finalize, mergeMap, retryWhen} from 'rxjs/operators'; describe('retryWhen', () => { let log: any[]; const genericRetryStrategy = (finalizer: () => void) => (attempts: Observable) => - attempts.pipe( - mergeMap((error, i) => { - const retryAttempt = i + 1; - if (retryAttempt > 3) { - return throwError(error); - } - log.push(error); - return timer(retryAttempt * 1); - }), - finalize(() => finalizer())); + attempts.pipe( + mergeMap((error, i) => { + const retryAttempt = i + 1; + if (retryAttempt > 3) { + return throwError(error); + } + log.push(error); + return timer(retryAttempt * 1); + }), + finalize(() => finalizer()), + ); const errorGenerator = () => { return throwError(new Error('error emit')); @@ -29,13 +30,17 @@ describe('retryWhen', () => { log = []; }); - it('should retry max 3 times', - (done: DoneFn) => {errorGenerator() - .pipe( - retryWhen(genericRetryStrategy(() => { - expect(log.length).toBe(3); - done(); - })), - catchError(error => of(error))) - .subscribe()}); + it('should retry max 3 times', (done: DoneFn) => { + errorGenerator() + .pipe( + retryWhen( + genericRetryStrategy(() => { + expect(log.length).toBe(3); + done(); + }), + ), + catchError((error) => of(error)), + ) + .subscribe(); + }); }); diff --git a/packages/zone.js/test/rxjs/rxjs.spec.ts b/packages/zone.js/test/rxjs/rxjs.spec.ts index e00e3386e6661..dd2abf7799b43 100644 --- a/packages/zone.js/test/rxjs/rxjs.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.spec.ts @@ -5,10 +5,12 @@ * 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 */ -(Object as any).setPrototypeOf = (Object as any).setPrototypeOf || function(obj: any, proto: any) { - obj.__proto__ = proto; - return obj; -}; +(Object as any).setPrototypeOf = + (Object as any).setPrototypeOf || + function (obj: any, proto: any) { + obj.__proto__ = proto; + return obj; + }; import '../../lib/rxjs/rxjs'; import './rxjs.common.spec'; import './rxjs.asap.spec'; diff --git a/packages/zone.js/test/rxjs/rxjs.throw.spec.ts b/packages/zone.js/test/rxjs/rxjs.throw.spec.ts index bdafe0fc2c8c0..47e2db9099520 100644 --- a/packages/zone.js/test/rxjs/rxjs.throw.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.throw.spec.ts @@ -27,45 +27,50 @@ describe('Observable.throw', () => { subscriptionZone.run(() => { observable1.subscribe( + (result: any) => { + fail('should not call next'); + }, + (error: any) => { + log.push(error); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + () => { + fail('should not call complete'); + }, + ); + }); + + expect(log).toEqual([error]); + }); + + it( + 'throw func callback should run in the correct zone with scheduler', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + let error = new Error('test'); + observable1 = constructorZone1.run(() => { + return throwError(error, asapScheduler); + }); + + subscriptionZone.run(() => { + observable1.subscribe( (result: any) => { fail('should not call next'); }, (error: any) => { log.push(error); expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([error]); + done(); }, () => { fail('should not call complete'); - }); - }); - - expect(log).toEqual([error]); - }); - - it('throw func callback should run in the correct zone with scheduler', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - let error = new Error('test'); - observable1 = constructorZone1.run(() => { - return throwError(error, asapScheduler); - }); - - subscriptionZone.run(() => { - observable1.subscribe( - (result: any) => { - fail('should not call next'); - }, - (error: any) => { - log.push(error); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([error]); - done(); - }, - () => { - fail('should not call complete'); - }); - }); + }, + ); + }); - expect(log).toEqual([]); - }, Zone.root)); + expect(log).toEqual([]); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.timer.spec.ts b/packages/zone.js/test/rxjs/rxjs.timer.spec.ts index 7c46a8e845413..f355712acb036 100644 --- a/packages/zone.js/test/rxjs/rxjs.timer.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.timer.spec.ts @@ -16,31 +16,35 @@ describe('Observable.timer', () => { log = []; }); - it('timer func callback should run in the correct zone', asyncTest((done: any) => { - const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); - const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); - observable1 = constructorZone1.run(() => { - return timer(10, 20); - }); + it( + 'timer func callback should run in the correct zone', + asyncTest((done: any) => { + const constructorZone1: Zone = Zone.current.fork({name: 'Constructor Zone1'}); + const subscriptionZone: Zone = Zone.current.fork({name: 'Subscription Zone'}); + observable1 = constructorZone1.run(() => { + return timer(10, 20); + }); - subscriptionZone.run(() => { - const subscriber = observable1.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - if (result >= 3) { - // subscriber.complete(); - subscriber.unsubscribe(); - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - expect(log).toEqual([0, 1, 2, 3, 'completed']); - done(); - } - }, - () => { - fail('should not call error'); - }); - expect(log).toEqual([]); - }); - }, Zone.root)); + subscriptionZone.run(() => { + const subscriber = observable1.subscribe( + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + if (result >= 3) { + // subscriber.complete(); + subscriber.unsubscribe(); + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + expect(log).toEqual([0, 1, 2, 3, 'completed']); + done(); + } + }, + () => { + fail('should not call error'); + }, + ); + expect(log).toEqual([]); + }); + }, Zone.root), + ); }); diff --git a/packages/zone.js/test/rxjs/rxjs.util.ts b/packages/zone.js/test/rxjs/rxjs.util.ts index a98972258f096..772326ccf847b 100644 --- a/packages/zone.js/test/rxjs/rxjs.util.ts +++ b/packages/zone.js/test/rxjs/rxjs.util.ts @@ -7,7 +7,7 @@ */ export function supportFeature(Observable: any, method: string) { - const func = function() { + const func = function () { return !!Observable.prototype[method]; }; (func as any).message = `Observable.${method} not support`; diff --git a/packages/zone.js/test/rxjs/rxjs.zip.spec.ts b/packages/zone.js/test/rxjs/rxjs.zip.spec.ts index 3bb64496e14f5..8ff2d958c3cc9 100644 --- a/packages/zone.js/test/rxjs/rxjs.zip.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.zip.spec.ts @@ -26,7 +26,7 @@ describe('Observable.zip', () => { }); const observable3: any = constructorZone1.run(() => { - return zip(observable1, observable2, function(n: number, str: string) { + return zip(observable1, observable2, function (n: number, str: string) { expect(Zone.current.name).toEqual(constructorZone1.name); return {n: n, str: str}; }); @@ -34,17 +34,18 @@ describe('Observable.zip', () => { subscriptionZone.run(() => { observable3.subscribe( - (result: any) => { - log.push(result); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }, - () => { - fail('should not call error'); - }, - () => { - log.push('completed'); - expect(Zone.current.name).toEqual(subscriptionZone.name); - }); + (result: any) => { + log.push(result); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + () => { + fail('should not call error'); + }, + () => { + log.push('completed'); + expect(Zone.current.name).toEqual(subscriptionZone.name); + }, + ); }); expect(log).toEqual([{n: 1, str: 'foo'}, {n: 2, str: 'bar'}, {n: 3, str: 'beer'}, 'completed']); diff --git a/packages/zone.js/test/test-env-setup-mocha.ts b/packages/zone.js/test/test-env-setup-mocha.ts index 3b51dcd68bd7f..8e85281df1980 100644 --- a/packages/zone.js/test/test-env-setup-mocha.ts +++ b/packages/zone.js/test/test-env-setup-mocha.ts @@ -11,8 +11,8 @@ declare const global: any; ((context: any) => { context['jasmine'] = context['jasmine'] || {}; - context['jasmine'].createSpy = function(spyName: string) { - let spy: any = function(...params: any[]) { + context['jasmine'].createSpy = function (spyName: string) { + let spy: any = function (...params: any[]) { spy.countCall++; spy.callArgs = params; }; @@ -64,34 +64,34 @@ declare const global: any; return false; } - context['expect'] = function(expected: any) { + context['expect'] = function (expected: any) { return { - toBe: function(actual: any) { + toBe: function (actual: any) { if (expected !== actual) { throw new Error(`Expected ${expected} to be ${actual}`); } }, - toEqual: function(actual: any) { + toEqual: function (actual: any) { if (!eq(expected, actual)) { throw new Error(`Expected ${expected} to be ${actual}`); } }, - toBeGreaterThan: function(actual: number) { + toBeGreaterThan: function (actual: number) { if (expected <= actual) { throw new Error(`Expected ${expected} to be greater than ${actual}`); } }, - toBeLessThan: function(actual: number) { + toBeLessThan: function (actual: number) { if (expected >= actual) { throw new Error(`Expected ${expected} to be lesser than ${actual}`); } }, - toBeDefined: function() { + toBeDefined: function () { if (!expected) { throw new Error(`Expected ${expected} to be defined`); } }, - toThrow: function() { + toThrow: function () { try { expected(); } catch (error) { @@ -100,7 +100,7 @@ declare const global: any; throw new Error(`Expected ${expected} to throw`); }, - toThrowError: function(errorToBeThrow: any) { + toThrowError: function (errorToBeThrow: any) { try { expected(); } catch (error) { @@ -109,78 +109,79 @@ declare const global: any; throw Error(`Expected ${expected} to throw: ${errorToBeThrow}`); }, - toBeTruthy: function() { + toBeTruthy: function () { if (!expected) { throw new Error(`Expected ${expected} to be truthy`); } }, - toBeFalsy: function(actual: any) { + toBeFalsy: function (actual: any) { if (!!actual) { throw new Error(`Expected ${actual} to be falsy`); } }, - toContain: function(actual: any) { + toContain: function (actual: any) { if (expected.indexOf(actual) === -1) { throw new Error(`Expected ${expected} to contain ${actual}`); } }, - toHaveBeenCalled: function() { + toHaveBeenCalled: function () { if (expected.countCall === 0) { throw new Error(`Expected ${expected} to been called`); } }, - toHaveBeenCalledWith: function(...params: any[]) { + toHaveBeenCalledWith: function (...params: any[]) { if (!eq(expected.callArgs, params)) { - throw new Error(`Expected ${expected} to been called with ${ - expected.callArgs}, called with: ${params}`); + throw new Error( + `Expected ${expected} to been called with ${expected.callArgs}, called with: ${params}`, + ); } }, - toMatch: function(actual: any) { + toMatch: function (actual: any) { if (!new RegExp(actual).test(expected)) { throw new Error(`Expected ${expected} to match ${actual}`); } }, not: { - toBe: function(actual: any) { + toBe: function (actual: any) { if (expected === actual) { throw new Error(`Expected ${expected} not to be ${actual}`); } }, - toHaveBeenCalled: function() { + toHaveBeenCalled: function () { if (expected.countCall > 0) { throw new Error(`Expected ${expected} to not been called`); } }, - toThrow: function() { + toThrow: function () { try { expected(); } catch (error) { throw new Error(`Expected ${expected} to not throw`); } }, - toThrowError: function() { + toThrowError: function () { try { expected(); } catch (error) { throw Error(`Expected ${expected} to not throw error`); } }, - toBeGreaterThan: function(actual: number) { + toBeGreaterThan: function (actual: number) { if (expected > actual) { throw new Error(`Expected ${expected} not to be greater than ${actual}`); } }, - toBeLessThan: function(actual: number) { + toBeLessThan: function (actual: number) { if (expected < actual) { throw new Error(`Expected ${expected} not to be lesser than ${actual}`); } }, - toHaveBeenCalledWith: function(params: any[]) { + toHaveBeenCalledWith: function (params: any[]) { if (!eq(expected.callArgs, params)) { throw new Error(`Expected ${expected} to not been called with ${params}`); } - } - } + }, + }, }; }; })(globalThis); diff --git a/packages/zone.js/test/test-util.ts b/packages/zone.js/test/test-util.ts index 1b01a5d25f65d..2e3156c6f9e95 100644 --- a/packages/zone.js/test/test-util.ts +++ b/packages/zone.js/test/test-util.ts @@ -32,24 +32,27 @@ export function ifEnvSupports(test: any, block: Function, otherwise?: Function): } export function ifEnvSupportsWithDone( - test: any, block: Function, otherwise?: Function): (done: Function) => void { + test: any, + block: Function, + otherwise?: Function, +): (done: Function) => void { return _ifEnvSupports(test, block, otherwise, true); } function _ifEnvSupports(test: any, block: Function, otherwise?: Function, withDone = false) { if (withDone) { - return function(done?: Function) { + return function (done?: Function) { _runTest(test, block, otherwise, done); }; } else { - return function() { + return function () { _runTest(test, block, otherwise, undefined); }; } } function _runTest(test: any, block: Function, otherwise?: Function, done?: Function) { - const message = (test.message || test.name || test); + const message = test.message || test.name || test; if (typeof test === 'string' ? !!global[test] : test()) { if (done) { block(done); @@ -95,9 +98,15 @@ export function isSupportSetErrorStack() { export function asyncTest(this: unknown, testFn: Function, zone: Zone = Zone.current) { const AsyncTestZoneSpec = (Zone as any)['AsyncTestZoneSpec']; return (done: Function) => { - let asyncTestZone: Zone = zone.fork(new AsyncTestZoneSpec(() => {}, (error: Error) => { - fail(error); - }, 'asyncTest')); + let asyncTestZone: Zone = zone.fork( + new AsyncTestZoneSpec( + () => {}, + (error: Error) => { + fail(error); + }, + 'asyncTest', + ), + ); asyncTestZone.run(testFn, this, [done]); }; } diff --git a/packages/zone.js/test/test_fake_polyfill.ts b/packages/zone.js/test/test_fake_polyfill.ts index 4f92b613b6708..83f4ea84436e4 100644 --- a/packages/zone.js/test/test_fake_polyfill.ts +++ b/packages/zone.js/test/test_fake_polyfill.ts @@ -15,13 +15,18 @@ export function setupFakePolyfill(): void { // add custom properties to Native Error const NativeError = global['Error']; NativeError.customProperty = 'customProperty'; - NativeError.customFunction = function() {}; + NativeError.customFunction = function () {}; // add fake cordova polyfill for test - const fakeCordova = function() {}; + const fakeCordova = function () {}; - (fakeCordova as any).exec = function( - success: Function, error: Function, service: string, action: string, args: any[]) { + (fakeCordova as any).exec = function ( + success: Function, + error: Function, + service: string, + action: string, + args: any[], + ) { if (action === 'successAction') { success(); } else { @@ -31,58 +36,59 @@ export function setupFakePolyfill(): void { global.cordova = fakeCordova; - const TestTarget = global.TestTarget = function() {}; + const TestTarget = (global.TestTarget = function () {}); Object.defineProperties(TestTarget.prototype, { 'onprop1': {configurable: true, writable: true}, 'onprop2': {configurable: true, writable: true}, 'onprop3': { configurable: true, - get: function() { + get: function () { return this._onprop3; }, - set: function(_value) { + set: function (_value) { this._onprop3 = _value; - } + }, }, - '_onprop3': {configurable: true, writable: true, value: function() {}}, + '_onprop3': {configurable: true, writable: true, value: function () {}}, 'addEventListener': { configurable: true, writable: true, - value: function(eventName: string, callback: Function) { + value: function (eventName: string, callback: Function) { if (!this.events) { this.events = {}; } const Zone = global.Zone; this.events.eventName = {zone: Zone.current, callback: callback}; - } + }, }, 'removeEventListener': { configurable: true, writable: true, - value: function(eventName: string, callback: Function) { + value: function (eventName: string, callback: Function) { if (!this.events) { return; } this.events.eventName = null; - } + }, }, 'dispatchEvent': { configurable: true, writable: true, - value: function(eventName: string) { + value: function (eventName: string) { const zoneCallback = this.events && this.events.eventName; zoneCallback && zoneCallback.zone.run(zoneCallback.callback, this, [{type: eventName}]); - } - } + }, + }, }); // Zone symbol prefix may be set in *-env-setup.ts (browser & node), // but this file is used in multiple scenarios, and Zone isn't loaded at this point yet. const zoneSymbolPrefix = global['__Zone_symbol_prefix'] || '__zone_symbol__'; - global['__Zone_ignore_on_properties'] = - [{target: TestTarget.prototype, ignoreProperties: ['prop1']}]; + global['__Zone_ignore_on_properties'] = [ + {target: TestTarget.prototype, ignoreProperties: ['prop1']}, + ]; global[zoneSymbolPrefix + 'FakeAsyncTestMacroTask'] = [{source: 'TestClass.myTimeout'}]; // will not monkey patch scroll and wheel event. global[zoneSymbolPrefix + 'UNPATCHED_EVENTS'] = ['scroll', 'wheel']; diff --git a/packages/zone.js/test/webdriver/test.js b/packages/zone.js/test/webdriver/test.js index 5601b75b911d4..b90d243ec13a1 100644 --- a/packages/zone.js/test/webdriver/test.js +++ b/packages/zone.js/test/webdriver/test.js @@ -18,15 +18,18 @@ const webdriver = require('selenium-webdriver'); const capabilities = webdriver.Capabilities.firefox(); const driver = new webdriver.Builder() - .usingServer('http://localhost:4444/wd/hub') - .withCapabilities(capabilities) - .build(); + .usingServer('http://localhost:4444/wd/hub') + .withCapabilities(capabilities) + .build(); driver.get('http://localhost:8080/test.html'); driver.executeAsyncScript((cb) => { window.setTimeout(cb, 1000); }); // test case2 addEventHandler in firefox cross site context -driver.findElement(webdriver.By.css('#thetext')).getText().then(function(text) { - console.log(text); -}); +driver + .findElement(webdriver.By.css('#thetext')) + .getText() + .then(function (text) { + console.log(text); + }); diff --git a/packages/zone.js/test/webdriver/test.sauce.es2015.js b/packages/zone.js/test/webdriver/test.sauce.es2015.js index 3bc4e478f8d0d..32d06bfb31eff 100644 --- a/packages/zone.js/test/webdriver/test.sauce.es2015.js +++ b/packages/zone.js/test/webdriver/test.sauce.es2015.js @@ -14,7 +14,7 @@ const desiredCapabilities = { platformName: 'Android', platformVersion: '6.0', deviceOrientation: 'portrait', - appiumVersion: '1.12.1' + appiumVersion: '1.12.1', }, android71: { deviceName: 'Android GoogleAPI Emulator', @@ -22,8 +22,8 @@ const desiredCapabilities = { platformName: 'Android', platformVersion: '7.1', deviceOrientation: 'portrait', - appiumVersion: '1.12.1' - } + appiumVersion: '1.12.1', + }, }; const errors = []; @@ -33,7 +33,7 @@ if (process.env.TRAVIS) { process.env.SAUCE_ACCESS_KEY = process.env.SAUCE_ACCESS_KEY.split('').reverse().join(''); } -Object.keys(desiredCapabilities).forEach(key => { +Object.keys(desiredCapabilities).forEach((key) => { console.log('begin webdriver test', key); if (process.env.TRAVIS) { desiredCapabilities[key]['tunnel-identifier'] = process.env.TRAVIS_JOB_NUMBER; @@ -43,42 +43,44 @@ Object.keys(desiredCapabilities).forEach(key => { key: process.env.SAUCE_ACCESS_KEY, host: 'localhost', port: 4445, - desiredCapabilities: desiredCapabilities[key] + desiredCapabilities: desiredCapabilities[key], }); - const p = client.init() - .timeouts('script', 60000) - .url('http://localhost:8080/test/webdriver/test-es2015.html') - .executeAsync(function(done) { - window.setTimeout(done, 1000) - }) - .execute(function() { - const elem = document.getElementById('thetext'); - const zone = window['Zone'] ? Zone.current.fork({name: 'webdriver'}) : null; - if (zone) { - zone.run(function() { - elem.addEventListener('click', function(e) { - e.target.innerText = 'clicked' + Zone.current.name; - }); - }); - } else { - elem.addEventListener('click', function(e) { - e.target.innerText = 'clicked'; - }); - } - }) - .click('#thetext') - .getText('#thetext') - .then( - (text => { - if (text !== 'clickedwebdriver') { - errors.push(`Env: ${key}, expected clickedwebdriver, get ${text}`); - } - }), - (error) => { - errors.push(`Env: ${key}, error occurs: ${error}`); - }) - .end(); + const p = client + .init() + .timeouts('script', 60000) + .url('http://localhost:8080/test/webdriver/test-es2015.html') + .executeAsync(function (done) { + window.setTimeout(done, 1000); + }) + .execute(function () { + const elem = document.getElementById('thetext'); + const zone = window['Zone'] ? Zone.current.fork({name: 'webdriver'}) : null; + if (zone) { + zone.run(function () { + elem.addEventListener('click', function (e) { + e.target.innerText = 'clicked' + Zone.current.name; + }); + }); + } else { + elem.addEventListener('click', function (e) { + e.target.innerText = 'clicked'; + }); + } + }) + .click('#thetext') + .getText('#thetext') + .then( + (text) => { + if (text !== 'clickedwebdriver') { + errors.push(`Env: ${key}, expected clickedwebdriver, get ${text}`); + } + }, + (error) => { + errors.push(`Env: ${key}, error occurs: ${error}`); + }, + ) + .end(); tasks.push(p); }); @@ -92,7 +94,7 @@ function exit(exitCode) { Promise.all(tasks).then(() => { if (errors.length > 0) { let nonTimeoutError = false; - errors.forEach(error => { + errors.forEach((error) => { console.log(error); if (error.toString().lastIndexOf('timeout') === -1) { nonTimeoutError = true; diff --git a/packages/zone.js/test/webdriver/test.sauce.js b/packages/zone.js/test/webdriver/test.sauce.js index b485f56b6f381..e3e9c005c252f 100644 --- a/packages/zone.js/test/webdriver/test.sauce.js +++ b/packages/zone.js/test/webdriver/test.sauce.js @@ -30,7 +30,7 @@ if (process.env.TRAVIS) { process.env.SAUCE_ACCESS_KEY = process.env.SAUCE_ACCESS_KEY.split('').reverse().join(''); } -Object.keys(desiredCapabilities).forEach(key => { +Object.keys(desiredCapabilities).forEach((key) => { console.log('begin webdriver test', key); if (process.env.TRAVIS) { desiredCapabilities[key]['tunnel-identifier'] = process.env.TRAVIS_JOB_NUMBER; @@ -40,42 +40,44 @@ Object.keys(desiredCapabilities).forEach(key => { key: process.env.SAUCE_ACCESS_KEY, host: 'localhost', port: 4445, - desiredCapabilities: desiredCapabilities[key] + desiredCapabilities: desiredCapabilities[key], }); - const p = client.init() - .timeouts('script', 60000) - .url('http://localhost:8080/test/webdriver/test.html') - .executeAsync(function(done) { - window.setTimeout(done, 1000) - }) - .execute(function() { - const elem = document.getElementById('thetext'); - const zone = window['Zone'] ? Zone.current.fork({name: 'webdriver'}) : null; - if (zone) { - zone.run(function() { - elem.addEventListener('click', function(e) { - e.target.innerText = 'clicked' + Zone.current.name; - }); - }); - } else { - elem.addEventListener('click', function(e) { - e.target.innerText = 'clicked'; - }); - } - }) - .click('#thetext') - .getText('#thetext') - .then( - (text => { - if (text !== 'clickedwebdriver') { - errors.push(`Env: ${key}, expected clickedwebdriver, get ${text}`); - } - }), - (error) => { - errors.push(`Env: ${key}, error occurs: ${error}`); - }) - .end(); + const p = client + .init() + .timeouts('script', 60000) + .url('http://localhost:8080/test/webdriver/test.html') + .executeAsync(function (done) { + window.setTimeout(done, 1000); + }) + .execute(function () { + const elem = document.getElementById('thetext'); + const zone = window['Zone'] ? Zone.current.fork({name: 'webdriver'}) : null; + if (zone) { + zone.run(function () { + elem.addEventListener('click', function (e) { + e.target.innerText = 'clicked' + Zone.current.name; + }); + }); + } else { + elem.addEventListener('click', function (e) { + e.target.innerText = 'clicked'; + }); + } + }) + .click('#thetext') + .getText('#thetext') + .then( + (text) => { + if (text !== 'clickedwebdriver') { + errors.push(`Env: ${key}, expected clickedwebdriver, get ${text}`); + } + }, + (error) => { + errors.push(`Env: ${key}, error occurs: ${error}`); + }, + ) + .end(); tasks.push(p); }); @@ -89,7 +91,7 @@ function exit(exitCode) { Promise.all(tasks).then(() => { if (errors.length > 0) { let nonTimeoutError = false; - errors.forEach(error => { + errors.forEach((error) => { console.log(error); if (error.toString().lastIndexOf('timeout') === -1) { nonTimeoutError = true; diff --git a/packages/zone.js/test/ws-server.js b/packages/zone.js/test/ws-server.js index 45165a9cb41fa..d4daa664b47e6 100644 --- a/packages/zone.js/test/ws-server.js +++ b/packages/zone.js/test/ws-server.js @@ -10,10 +10,12 @@ const {WebSocketServer} = require('ws'); // simple echo server const wss = new WebSocketServer({port: 8001}); -wss.on('connection', (ws) => {ws.on('message', (data) => { - if (data.toString() === 'close') { - wss.close(); - return; - } - ws.send(data); - })}); +wss.on('connection', (ws) => { + ws.on('message', (data) => { + if (data.toString() === 'close') { + wss.close(); + return; + } + ws.send(data); + }); +}); diff --git a/packages/zone.js/test/wtf_mock.ts b/packages/zone.js/test/wtf_mock.ts index 8e0753fb40d37..e67ceaa1a7b84 100644 --- a/packages/zone.js/test/wtf_mock.ts +++ b/packages/zone.js/test/wtf_mock.ts @@ -9,87 +9,87 @@ /// 'use strict'; -(function(global) { -const log: string[] = []; -const logArgs: any[][] = []; -const wtfMock = { - log: log, - logArgs: logArgs, - reset: function() { - log.length = 0; - logArgs.length = 0; - }, - trace: { - leaveScope: function(scope: any, returnValue: any) { - return scope(returnValue); +(function (global) { + const log: string[] = []; + const logArgs: any[][] = []; + const wtfMock = { + log: log, + logArgs: logArgs, + reset: function () { + log.length = 0; + logArgs.length = 0; }, - beginTimeRange: function(type: any, action: any) { - logArgs.push([]); - log.push('>>> ' + type + '[' + action + ']'); - return function() { + trace: { + leaveScope: function (scope: any, returnValue: any) { + return scope(returnValue); + }, + beginTimeRange: function (type: any, action: any) { logArgs.push([]); - log.push('<<< ' + type); - }; - }, - endTimeRange: function(range: Function) { - range(); - }, - events: { - createScope: function(signature: string, flags: any) { - const parts = signature.split('('); - const name = parts[0]; - return function scopeFn() { - const args = []; - for (let i = arguments.length - 1; i >= 0; i--) { - const arg = arguments[i]; - if (arg !== undefined) { - args.unshift(__stringify(arg)); - } - } - log.push('> ' + name + '(' + args.join(', ') + ')'); - logArgs.push(args); - return function(retValue: any) { - log.push('< ' + name + (retValue == undefined ? '' : ' => ' + retValue)); - logArgs.push(retValue); - return retValue; - }; + log.push('>>> ' + type + '[' + action + ']'); + return function () { + logArgs.push([]); + log.push('<<< ' + type); }; }, - createInstance: function(signature: string, flags: any) { - const parts = signature.split('('); - const name = parts[0]; - return function eventFn() { - const args = []; - for (let i = arguments.length - 1; i >= 0; i--) { - const arg = arguments[i]; - if (arg !== undefined) { - args.unshift(__stringify(arg)); + endTimeRange: function (range: Function) { + range(); + }, + events: { + createScope: function (signature: string, flags: any) { + const parts = signature.split('('); + const name = parts[0]; + return function scopeFn() { + const args = []; + for (let i = arguments.length - 1; i >= 0; i--) { + const arg = arguments[i]; + if (arg !== undefined) { + args.unshift(__stringify(arg)); + } } - } - log.push('# ' + name + '(' + args.join(', ') + ')'); - logArgs.push(args); - }; - } - } - } -}; + log.push('> ' + name + '(' + args.join(', ') + ')'); + logArgs.push(args); + return function (retValue: any) { + log.push('< ' + name + (retValue == undefined ? '' : ' => ' + retValue)); + logArgs.push(retValue); + return retValue; + }; + }; + }, + createInstance: function (signature: string, flags: any) { + const parts = signature.split('('); + const name = parts[0]; + return function eventFn() { + const args = []; + for (let i = arguments.length - 1; i >= 0; i--) { + const arg = arguments[i]; + if (arg !== undefined) { + args.unshift(__stringify(arg)); + } + } + log.push('# ' + name + '(' + args.join(', ') + ')'); + logArgs.push(args); + }; + }, + }, + }, + }; -function __stringify(obj: any): string { - let str = typeof obj == 'string' || !obj ? JSON.stringify(obj) : obj.toString(); - if (str == '[object Arguments]') { - str = JSON.stringify(Array.prototype.slice.call(obj)); - } else if (str == '[object Object]') { - str = JSON.stringify(obj); + function __stringify(obj: any): string { + let str = typeof obj == 'string' || !obj ? JSON.stringify(obj) : obj.toString(); + if (str == '[object Arguments]') { + str = JSON.stringify(Array.prototype.slice.call(obj)); + } else if (str == '[object Object]') { + str = JSON.stringify(obj); + } + return str; } - return str; -} -beforeEach(function() { - wtfMock.reset(); -}); + beforeEach(function () { + wtfMock.reset(); + }); -(global).wtfMock = wtfMock; -(global).wtf = wtfMock; + (global).wtfMock = wtfMock; + (global).wtf = wtfMock; })(globalThis); declare const wtfMock: any; diff --git a/packages/zone.js/test/zone-spec/async-test.spec.ts b/packages/zone.js/test/zone-spec/async-test.spec.ts index d39d9a62fb864..ee35e82a8a626 100644 --- a/packages/zone.js/test/zone-spec/async-test.spec.ts +++ b/packages/zone.js/test/zone-spec/async-test.spec.ts @@ -9,7 +9,7 @@ import {ProxyZoneSpec} from '../../lib/zone-spec/proxy'; import {ifEnvSupports} from '../test-util'; -describe('AsyncTestZoneSpec', function() { +describe('AsyncTestZoneSpec', function () { let log: string[]; const AsyncTestZoneSpec = (Zone as any)['AsyncTestZoneSpec']; @@ -32,14 +32,18 @@ describe('AsyncTestZoneSpec', function() { it('should call finish after zone is run in sync call', (done) => { let finished = false; - const testZoneSpec = new AsyncTestZoneSpec(() => { - expect(finished).toBe(true); - done(); - }, failCallback, 'name'); + const testZoneSpec = new AsyncTestZoneSpec( + () => { + expect(finished).toBe(true); + done(); + }, + failCallback, + 'name', + ); const atz = Zone.current.fork(testZoneSpec); - atz.run(function() { + atz.run(function () { finished = true; }); }); @@ -48,18 +52,19 @@ describe('AsyncTestZoneSpec', function() { let finished = false; const testZoneSpec = new AsyncTestZoneSpec( - () => { - expect(finished).toBe(true); - done(); - }, - () => { - done.fail('async zone called failCallback unexpectedly'); - }, - 'name'); + () => { + expect(finished).toBe(true); + done(); + }, + () => { + done.fail('async zone called failCallback unexpectedly'); + }, + 'name', + ); const atz = Zone.current.fork(testZoneSpec); - atz.run(function() { + atz.run(function () { setTimeout(() => { finished = true; }, 10); @@ -70,18 +75,19 @@ describe('AsyncTestZoneSpec', function() { let finished = false; const testZoneSpec = new AsyncTestZoneSpec( - () => { - expect(finished).toBe(true); - done(); - }, - () => { - done.fail('async zone called failCallback unexpectedly'); - }, - 'name'); + () => { + expect(finished).toBe(true); + done(); + }, + () => { + done.fail('async zone called failCallback unexpectedly'); + }, + 'name', + ); const atz = Zone.current.fork(testZoneSpec); - atz.run(function() { + atz.run(function () { Promise.resolve().then(() => { finished = true; }); @@ -92,18 +98,19 @@ describe('AsyncTestZoneSpec', function() { let finished = false; const testZoneSpec = new AsyncTestZoneSpec( - () => { - expect(finished).toBe(true); - done(); - }, - () => { - done.fail('async zone called failCallback unexpectedly'); - }, - 'name'); + () => { + expect(finished).toBe(true); + done(); + }, + () => { + done.fail('async zone called failCallback unexpectedly'); + }, + 'name', + ); const atz = Zone.current.fork(testZoneSpec); - atz.run(function() { + atz.run(function () { new Promise((resolve) => { setTimeout(() => { resolve(); @@ -118,18 +125,19 @@ describe('AsyncTestZoneSpec', function() { let finished = false; const testZoneSpec = new AsyncTestZoneSpec( - () => { - expect(finished).toBe(true); - done(); - }, - () => { - done.fail('async zone called failCallback unexpectedly'); - }, - 'name'); + () => { + expect(finished).toBe(true); + done(); + }, + () => { + done.fail('async zone called failCallback unexpectedly'); + }, + 'name', + ); const atz = Zone.current.fork(testZoneSpec); - atz.run(function() { + atz.run(function () { Promise.resolve().then(() => { setTimeout(() => { finished = true; @@ -144,9 +152,13 @@ describe('AsyncTestZoneSpec', function() { Zone.current.run(() => {}); }; let doneCalledCount = 0; - const testZoneSpec = new AsyncTestZoneSpec(() => { - doneCalledCount++; - }, () => {}, 'name'); + const testZoneSpec = new AsyncTestZoneSpec( + () => { + doneCalledCount++; + }, + () => {}, + 'name', + ); const atz = Zone.current.fork(testZoneSpec); @@ -162,22 +174,26 @@ describe('AsyncTestZoneSpec', function() { Promise.resolve(1).then(() => {}); }; let doneCalledCount = 0; - const testZoneSpec = new AsyncTestZoneSpec(() => { - doneCalledCount++; - }, () => {}, 'name'); + const testZoneSpec = new AsyncTestZoneSpec( + () => { + doneCalledCount++; + }, + () => {}, + 'name', + ); const atz = Zone.current.fork(testZoneSpec); const c1 = atz.fork({ name: 'child1', onHasTask: (delegate, current, target, hasTaskState) => { return delegate.hasTask(target, hasTaskState); - } + }, }); const c2 = c1.fork({ name: 'child2', onHasTask: (delegate, current, target, hasTaskState) => { return delegate.hasTask(target, hasTaskState); - } + }, }); c2.run(testFn); @@ -187,190 +203,214 @@ describe('AsyncTestZoneSpec', function() { }, 50); }); - it('should not call done multiple times when proxy zone captures previously ' + - 'captured microtasks', - (done) => { - const ProxyZoneSpec = (Zone as any)['ProxyZoneSpec']; - const proxyZoneSpec = new ProxyZoneSpec(null) as ProxyZoneSpec; - const proxyZone = Zone.current.fork(proxyZoneSpec); - - // This simulates a simple `beforeEach` patched, running in the proxy zone, - // but not necessarily waiting for the promise to be resolved. This can - // be the case e.g. in the AngularJS upgrade tests where the bootstrap is - // performed in the before each, but the waiting is done in the actual `it` specs. - proxyZone.run(() => { - Promise.resolve().then(() => {}); - }); - - let doneCalledCount = 0; - const testFn = () => { - // When a test executes with `waitForAsync`, the proxy zone delegates to the async - // test zone, potentially also capturing tasks leaking from `beforeEach`. - proxyZoneSpec.setDelegate(testZoneSpec); - }; - - const testZoneSpec = new AsyncTestZoneSpec(() => { - // reset the proxy zone delegate after test completion. - proxyZoneSpec.setDelegate(null); - doneCalledCount++; - }, () => done.fail('Error occurred in the async test zone.'), 'name'); - - const atz = Zone.current.fork(testZoneSpec); - atz.run(testFn); - - setTimeout(() => { - expect(doneCalledCount).toBe(1); - done(); - }, 50); - }); - - - describe('event tasks', ifEnvSupports('document', () => { - let button: HTMLButtonElement; - beforeEach(function() { - button = document.createElement('button'); - document.body.appendChild(button); - }); - afterEach(function() { - document.body.removeChild(button); - }); - - it('should call finish because an event task is considered as sync', (done) => { - let finished = false; - - const testZoneSpec = new AsyncTestZoneSpec( - () => { - expect(finished).toBe(true); - done(); - }, - () => { - done.fail('async zone called failCallback unexpectedly'); - }, - 'name'); - - const atz = Zone.current.fork(testZoneSpec); - - atz.run(function() { - const listener = () => { - finished = true; - }; - button.addEventListener('click', listener); - - const clickEvent = document.createEvent('Event'); - clickEvent.initEvent('click', true, true); - - button.dispatchEvent(clickEvent); - }); - }); - - it('should call finish after an event task is done asynchronously', (done) => { - let finished = false; - - const testZoneSpec = new AsyncTestZoneSpec( - () => { - expect(finished).toBe(true); - done(); - }, - () => { - done.fail('async zone called failCallback unexpectedly'); - }, - 'name'); - - const atz = Zone.current.fork(testZoneSpec); - - atz.run(function() { - button.addEventListener('click', () => { - setTimeout(() => { - finished = true; - }, 10); - }); - - const clickEvent = document.createEvent('Event'); - clickEvent.initEvent('click', true, true); - - button.dispatchEvent(clickEvent); - }); - }); - }, emptyRun)); - - describe('XHRs', ifEnvSupports('XMLHttpRequest', () => { - beforeEach(() => { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 200000; - }); - beforeEach(() => { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 50000; - }); - it('should wait for XHRs to complete', function(done) { - let req: XMLHttpRequest; - let finished = false; - - const testZoneSpec = new AsyncTestZoneSpec( - () => { - expect(finished).toBe(true); - done(); - }, - (err: Error) => { - done.fail('async zone called failCallback unexpectedly'); - }, - 'name'); - - const atz = Zone.current.fork(testZoneSpec); - - atz.run(function() { - req = new XMLHttpRequest(); - - req.onreadystatechange = () => { - if (req.readyState === XMLHttpRequest.DONE) { - finished = true; - } - }; - - req.open('get', '/', true); - req.send(); - }); - }); - - it('should fail if an xhr fails', function(done) { - let req: XMLHttpRequest; - - const testZoneSpec = new AsyncTestZoneSpec( - () => { - done.fail('expected failCallback to be called'); - }, - (err: Error) => { - expect(err.message).toEqual('bad url failure'); - done(); - }, - 'name'); - - const atz = Zone.current.fork(testZoneSpec); - - atz.run(function() { - req = new XMLHttpRequest(); - req.onload = () => { - if (req.status != 200) { - throw new Error('bad url failure'); - } - }; - req.open('get', '/bad-url', true); - req.send(); - }); - }); - }, emptyRun)); + it( + 'should not call done multiple times when proxy zone captures previously ' + + 'captured microtasks', + (done) => { + const ProxyZoneSpec = (Zone as any)['ProxyZoneSpec']; + const proxyZoneSpec = new ProxyZoneSpec(null) as ProxyZoneSpec; + const proxyZone = Zone.current.fork(proxyZoneSpec); + + // This simulates a simple `beforeEach` patched, running in the proxy zone, + // but not necessarily waiting for the promise to be resolved. This can + // be the case e.g. in the AngularJS upgrade tests where the bootstrap is + // performed in the before each, but the waiting is done in the actual `it` specs. + proxyZone.run(() => { + Promise.resolve().then(() => {}); + }); - it('should not fail if setInterval is used and canceled', (done) => { - const testZoneSpec = new AsyncTestZoneSpec( + let doneCalledCount = 0; + const testFn = () => { + // When a test executes with `waitForAsync`, the proxy zone delegates to the async + // test zone, potentially also capturing tasks leaking from `beforeEach`. + proxyZoneSpec.setDelegate(testZoneSpec); + }; + + const testZoneSpec = new AsyncTestZoneSpec( () => { - done(); - }, - (err: Error) => { - done.fail('async zone called failCallback unexpectedly'); + // reset the proxy zone delegate after test completion. + proxyZoneSpec.setDelegate(null); + doneCalledCount++; }, - 'name'); + () => done.fail('Error occurred in the async test zone.'), + 'name', + ); + + const atz = Zone.current.fork(testZoneSpec); + atz.run(testFn); + + setTimeout(() => { + expect(doneCalledCount).toBe(1); + done(); + }, 50); + }, + ); + + describe( + 'event tasks', + ifEnvSupports( + 'document', + () => { + let button: HTMLButtonElement; + beforeEach(function () { + button = document.createElement('button'); + document.body.appendChild(button); + }); + afterEach(function () { + document.body.removeChild(button); + }); + + it('should call finish because an event task is considered as sync', (done) => { + let finished = false; + + const testZoneSpec = new AsyncTestZoneSpec( + () => { + expect(finished).toBe(true); + done(); + }, + () => { + done.fail('async zone called failCallback unexpectedly'); + }, + 'name', + ); + + const atz = Zone.current.fork(testZoneSpec); + + atz.run(function () { + const listener = () => { + finished = true; + }; + button.addEventListener('click', listener); + + const clickEvent = document.createEvent('Event'); + clickEvent.initEvent('click', true, true); + + button.dispatchEvent(clickEvent); + }); + }); + + it('should call finish after an event task is done asynchronously', (done) => { + let finished = false; + + const testZoneSpec = new AsyncTestZoneSpec( + () => { + expect(finished).toBe(true); + done(); + }, + () => { + done.fail('async zone called failCallback unexpectedly'); + }, + 'name', + ); + + const atz = Zone.current.fork(testZoneSpec); + + atz.run(function () { + button.addEventListener('click', () => { + setTimeout(() => { + finished = true; + }, 10); + }); + + const clickEvent = document.createEvent('Event'); + clickEvent.initEvent('click', true, true); + + button.dispatchEvent(clickEvent); + }); + }); + }, + emptyRun, + ), + ); + + describe( + 'XHRs', + ifEnvSupports( + 'XMLHttpRequest', + () => { + beforeEach(() => { + jasmine.DEFAULT_TIMEOUT_INTERVAL = 200000; + }); + beforeEach(() => { + jasmine.DEFAULT_TIMEOUT_INTERVAL = 50000; + }); + it('should wait for XHRs to complete', function (done) { + let req: XMLHttpRequest; + let finished = false; + + const testZoneSpec = new AsyncTestZoneSpec( + () => { + expect(finished).toBe(true); + done(); + }, + (err: Error) => { + done.fail('async zone called failCallback unexpectedly'); + }, + 'name', + ); + + const atz = Zone.current.fork(testZoneSpec); + + atz.run(function () { + req = new XMLHttpRequest(); + + req.onreadystatechange = () => { + if (req.readyState === XMLHttpRequest.DONE) { + finished = true; + } + }; + + req.open('get', '/', true); + req.send(); + }); + }); + + it('should fail if an xhr fails', function (done) { + let req: XMLHttpRequest; + + const testZoneSpec = new AsyncTestZoneSpec( + () => { + done.fail('expected failCallback to be called'); + }, + (err: Error) => { + expect(err.message).toEqual('bad url failure'); + done(); + }, + 'name', + ); + + const atz = Zone.current.fork(testZoneSpec); + + atz.run(function () { + req = new XMLHttpRequest(); + req.onload = () => { + if (req.status != 200) { + throw new Error('bad url failure'); + } + }; + req.open('get', '/bad-url', true); + req.send(); + }); + }); + }, + emptyRun, + ), + ); + + it('should not fail if setInterval is used and canceled', (done) => { + const testZoneSpec = new AsyncTestZoneSpec( + () => { + done(); + }, + (err: Error) => { + done.fail('async zone called failCallback unexpectedly'); + }, + 'name', + ); const atz = Zone.current.fork(testZoneSpec); - atz.run(function() { + atz.run(function () { let id = setInterval(() => { clearInterval(id); }, 100); @@ -379,18 +419,19 @@ describe('AsyncTestZoneSpec', function() { it('should fail if an error is thrown asynchronously', (done) => { const testZoneSpec = new AsyncTestZoneSpec( - () => { - done.fail('expected failCallback to be called'); - }, - (err: Error) => { - expect(err.message).toEqual('my error'); - done(); - }, - 'name'); + () => { + done.fail('expected failCallback to be called'); + }, + (err: Error) => { + expect(err.message).toEqual('my error'); + done(); + }, + 'name', + ); const atz = Zone.current.fork(testZoneSpec); - atz.run(function() { + atz.run(function () { setTimeout(() => { throw new Error('my error'); }, 10); @@ -399,21 +440,22 @@ describe('AsyncTestZoneSpec', function() { it('should fail if a promise rejection is unhandled', (done) => { const testZoneSpec = new AsyncTestZoneSpec( - () => { - done.fail('expected failCallback to be called'); - }, - (err: Error) => { - expect(err.message).toEqual('Uncaught (in promise): my reason'); - // Without the `runInTestZone` function, the callback continues to execute - // in the async test zone. We don't want to trigger new tasks upon - // the failure callback already being invoked (`jasmine.done` schedules tasks) - Zone.root.run(() => done()); - }, - 'name'); + () => { + done.fail('expected failCallback to be called'); + }, + (err: Error) => { + expect(err.message).toEqual('Uncaught (in promise): my reason'); + // Without the `runInTestZone` function, the callback continues to execute + // in the async test zone. We don't want to trigger new tasks upon + // the failure callback already being invoked (`jasmine.done` schedules tasks) + Zone.root.run(() => done()); + }, + 'name', + ); const atz = Zone.current.fork(testZoneSpec); - atz.run(function() { + atz.run(function () { Promise.reject('my reason'); }); }); @@ -421,14 +463,16 @@ describe('AsyncTestZoneSpec', function() { const asyncTest: any = (Zone as any)[Zone.__symbol__('asyncTest')]; function wrapAsyncTest(fn: Function, doneFn?: Function) { - return function(this: unknown, done: Function) { + return function (this: unknown, done: Function) { const asyncWrapper = asyncTest(fn); - return asyncWrapper.apply(this, [function(this: unknown) { - if (doneFn) { - doneFn(); - } - return done.apply(this, arguments); - }]); + return asyncWrapper.apply(this, [ + function (this: unknown) { + if (doneFn) { + doneFn(); + } + return done.apply(this, arguments); + }, + ]); }; } @@ -436,73 +480,86 @@ describe('AsyncTestZoneSpec', function() { describe('non zone aware async task in promise should be detected', () => { let finished = false; const _global: any = - typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global; + (typeof window !== 'undefined' && window) || + (typeof self !== 'undefined' && self) || + global; beforeEach(() => { _global[Zone.__symbol__('supportWaitUnResolvedChainedPromise')] = true; }); afterEach(() => { _global[Zone.__symbol__('supportWaitUnResolvedChainedPromise')] = false; }); - it('should be able to detect non zone aware async task in promise', - wrapAsyncTest( - () => { - new Promise((res, rej) => { - const g: any = typeof window === 'undefined' ? global : window; - g[Zone.__symbol__('setTimeout')](res, 100); - }).then(() => { - finished = true; - }); - }, - () => { - expect(finished).toBe(true); - })); + it( + 'should be able to detect non zone aware async task in promise', + wrapAsyncTest( + () => { + new Promise((res, rej) => { + const g: any = typeof window === 'undefined' ? global : window; + g[Zone.__symbol__('setTimeout')](res, 100); + }).then(() => { + finished = true; + }); + }, + () => { + expect(finished).toBe(true); + }, + ), + ); }); - describe('test without beforeEach', () => { const logs: string[] = []; - it('should automatically done after async tasks finished', - wrapAsyncTest( - () => { - setTimeout(() => { - logs.push('timeout'); - }, 100); - }, - () => { - expect(logs).toEqual(['timeout']); - logs.splice(0); - })); - - it('should automatically done after all nested async tasks finished', - wrapAsyncTest( - () => { - setTimeout(() => { - logs.push('timeout'); - setTimeout(() => { - logs.push('nested timeout'); - }, 100); - }, 100); - }, - () => { - expect(logs).toEqual(['timeout', 'nested timeout']); - logs.splice(0); - })); - - it('should automatically done after multiple async tasks finished', - wrapAsyncTest( - () => { - setTimeout(() => { - logs.push('1st timeout'); - }, 100); - - setTimeout(() => { - logs.push('2nd timeout'); - }, 100); - }, - () => { - expect(logs).toEqual(['1st timeout', '2nd timeout']); - logs.splice(0); - })); + it( + 'should automatically done after async tasks finished', + wrapAsyncTest( + () => { + setTimeout(() => { + logs.push('timeout'); + }, 100); + }, + () => { + expect(logs).toEqual(['timeout']); + logs.splice(0); + }, + ), + ); + + it( + 'should automatically done after all nested async tasks finished', + wrapAsyncTest( + () => { + setTimeout(() => { + logs.push('timeout'); + setTimeout(() => { + logs.push('nested timeout'); + }, 100); + }, 100); + }, + () => { + expect(logs).toEqual(['timeout', 'nested timeout']); + logs.splice(0); + }, + ), + ); + + it( + 'should automatically done after multiple async tasks finished', + wrapAsyncTest( + () => { + setTimeout(() => { + logs.push('1st timeout'); + }, 100); + + setTimeout(() => { + logs.push('2nd timeout'); + }, 100); + }, + () => { + expect(logs).toEqual(['1st timeout', '2nd timeout']); + logs.splice(0); + }, + ), + ); }); describe('test with sync beforeEach', () => { @@ -513,121 +570,147 @@ describe('AsyncTestZoneSpec', function() { logs.push('beforeEach'); }); - it('should automatically done after async tasks finished', - wrapAsyncTest( - () => { - setTimeout(() => { - logs.push('timeout'); - }, 100); - }, - () => { - expect(logs).toEqual(['beforeEach', 'timeout']); - })); + it( + 'should automatically done after async tasks finished', + wrapAsyncTest( + () => { + setTimeout(() => { + logs.push('timeout'); + }, 100); + }, + () => { + expect(logs).toEqual(['beforeEach', 'timeout']); + }, + ), + ); }); describe('test with async beforeEach', () => { const logs: string[] = []; - beforeEach(wrapAsyncTest(() => { - setTimeout(() => { - logs.splice(0); - logs.push('beforeEach'); - }, 100); - })); - - it('should automatically done after async tasks finished', - wrapAsyncTest( - () => { - setTimeout(() => { - logs.push('timeout'); - }, 100); - }, - () => { - expect(logs).toEqual(['beforeEach', 'timeout']); - })); - - it('should automatically done after all nested async tasks finished', - wrapAsyncTest( - () => { - setTimeout(() => { - logs.push('timeout'); - setTimeout(() => { - logs.push('nested timeout'); - }, 100); - }, 100); - }, - () => { - expect(logs).toEqual(['beforeEach', 'timeout', 'nested timeout']); - })); - - it('should automatically done after multiple async tasks finished', - wrapAsyncTest( - () => { - setTimeout(() => { - logs.push('1st timeout'); - }, 100); - - setTimeout(() => { - logs.push('2nd timeout'); - }, 100); - }, - () => { - expect(logs).toEqual(['beforeEach', '1st timeout', '2nd timeout']); - })); + beforeEach( + wrapAsyncTest(() => { + setTimeout(() => { + logs.splice(0); + logs.push('beforeEach'); + }, 100); + }), + ); + + it( + 'should automatically done after async tasks finished', + wrapAsyncTest( + () => { + setTimeout(() => { + logs.push('timeout'); + }, 100); + }, + () => { + expect(logs).toEqual(['beforeEach', 'timeout']); + }, + ), + ); + + it( + 'should automatically done after all nested async tasks finished', + wrapAsyncTest( + () => { + setTimeout(() => { + logs.push('timeout'); + setTimeout(() => { + logs.push('nested timeout'); + }, 100); + }, 100); + }, + () => { + expect(logs).toEqual(['beforeEach', 'timeout', 'nested timeout']); + }, + ), + ); + + it( + 'should automatically done after multiple async tasks finished', + wrapAsyncTest( + () => { + setTimeout(() => { + logs.push('1st timeout'); + }, 100); + + setTimeout(() => { + logs.push('2nd timeout'); + }, 100); + }, + () => { + expect(logs).toEqual(['beforeEach', '1st timeout', '2nd timeout']); + }, + ), + ); }); describe('test with async beforeEach and sync afterEach', () => { const logs: string[] = []; - beforeEach(wrapAsyncTest(() => { - setTimeout(() => { - expect(logs).toEqual([]); - logs.push('beforeEach'); - }, 100); - })); + beforeEach( + wrapAsyncTest(() => { + setTimeout(() => { + expect(logs).toEqual([]); + logs.push('beforeEach'); + }, 100); + }), + ); afterEach(() => { logs.splice(0); }); - it('should automatically done after async tasks finished', - wrapAsyncTest( - () => { - setTimeout(() => { - logs.push('timeout'); - }, 100); - }, - () => { - expect(logs).toEqual(['beforeEach', 'timeout']); - })); + it( + 'should automatically done after async tasks finished', + wrapAsyncTest( + () => { + setTimeout(() => { + logs.push('timeout'); + }, 100); + }, + () => { + expect(logs).toEqual(['beforeEach', 'timeout']); + }, + ), + ); }); describe('test with async beforeEach and async afterEach', () => { const logs: string[] = []; - beforeEach(wrapAsyncTest(() => { - setTimeout(() => { - expect(logs).toEqual([]); - logs.push('beforeEach'); - }, 100); - })); - - afterEach(wrapAsyncTest(() => { - setTimeout(() => { - logs.splice(0); - }, 100); - })); - - it('should automatically done after async tasks finished', - wrapAsyncTest( - () => { - setTimeout(() => { - logs.push('timeout'); - }, 100); - }, - () => { - expect(logs).toEqual(['beforeEach', 'timeout']); - })); + beforeEach( + wrapAsyncTest(() => { + setTimeout(() => { + expect(logs).toEqual([]); + logs.push('beforeEach'); + }, 100); + }), + ); + + afterEach( + wrapAsyncTest(() => { + setTimeout(() => { + logs.splice(0); + }, 100); + }), + ); + + it( + 'should automatically done after async tasks finished', + wrapAsyncTest( + () => { + setTimeout(() => { + logs.push('timeout'); + }, 100); + }, + () => { + expect(logs).toEqual(['beforeEach', 'timeout']); + }, + ), + ); }); }); }); diff --git a/packages/zone.js/test/zone-spec/clock-tests/fake-async-patched-clock.spec.ts b/packages/zone.js/test/zone-spec/clock-tests/fake-async-patched-clock.spec.ts index 2c142c9be8d57..312788e44c395 100644 --- a/packages/zone.js/test/zone-spec/clock-tests/fake-async-patched-clock.spec.ts +++ b/packages/zone.js/test/zone-spec/clock-tests/fake-async-patched-clock.spec.ts @@ -64,4 +64,4 @@ describe('fake async unpatched clock tests', () => { jasmine.clock().tick(100); expect(spy).toHaveBeenCalled(); }); -}) +}); diff --git a/packages/zone.js/test/zone-spec/clock-tests/fake-async-unpatched-clock.spec.ts b/packages/zone.js/test/zone-spec/clock-tests/fake-async-unpatched-clock.spec.ts index dbf5d73b9b1bf..2390844c3ed6a 100644 --- a/packages/zone.js/test/zone-spec/clock-tests/fake-async-unpatched-clock.spec.ts +++ b/packages/zone.js/test/zone-spec/clock-tests/fake-async-unpatched-clock.spec.ts @@ -28,9 +28,9 @@ describe('fake async unpatched clock tests', () => { }); it('should check date type correctly', fakeAsync(() => { - const d: any = new Date(); - expect(d instanceof Date).toBe(true); - })); + const d: any = new Date(); + expect(d instanceof Date).toBe(true); + })); it('should check date type correctly without fakeAsync', () => { const d: any = new Date(); @@ -38,12 +38,12 @@ describe('fake async unpatched clock tests', () => { }); it('should tick correctly', fakeAsync(() => { - jasmine.clock().mockDate(); - const start = Date.now(); - jasmine.clock().tick(100); - const end = Date.now(); - expect(end - start).toBe(100); - })); + jasmine.clock().mockDate(); + const start = Date.now(); + jasmine.clock().tick(100); + const end = Date.now(); + expect(end - start).toBe(100); + })); it('should tick correctly without fakeAsync', () => { jasmine.clock().mockDate(); @@ -54,16 +54,16 @@ describe('fake async unpatched clock tests', () => { }); it('should mock date correctly', fakeAsync(() => { - const baseTime = new Date(2013, 9, 23); - jasmine.clock().mockDate(baseTime); - const start = Date.now(); - expect(start).toBe(baseTime.getTime()); - jasmine.clock().tick(100); - const end = Date.now(); - expect(end - start).toBe(100); - expect(end).toBe(baseTime.getTime() + 100); - expect(new Date().getFullYear()).toEqual(2013); - })); + const baseTime = new Date(2013, 9, 23); + jasmine.clock().mockDate(baseTime); + const start = Date.now(); + expect(start).toBe(baseTime.getTime()); + jasmine.clock().tick(100); + const end = Date.now(); + expect(end - start).toBe(100); + expect(end).toBe(baseTime.getTime() + 100); + expect(new Date().getFullYear()).toEqual(2013); + })); it('should mock date correctly without fakeAsync', () => { const baseTime = new Date(2013, 9, 23); @@ -78,15 +78,15 @@ describe('fake async unpatched clock tests', () => { }); it('should handle new Date correctly', fakeAsync(() => { - const baseTime = new Date(2013, 9, 23); - jasmine.clock().mockDate(baseTime); - const start = new Date(); - expect(start.getTime()).toBe(baseTime.getTime()); - jasmine.clock().tick(100); - const end = new Date(); - expect(end.getTime() - start.getTime()).toBe(100); - expect(end.getTime()).toBe(baseTime.getTime() + 100); - })); + const baseTime = new Date(2013, 9, 23); + jasmine.clock().mockDate(baseTime); + const start = new Date(); + expect(start.getTime()).toBe(baseTime.getTime()); + jasmine.clock().tick(100); + const end = new Date(); + expect(end.getTime() - start.getTime()).toBe(100); + expect(end.getTime()).toBe(baseTime.getTime() + 100); + })); it('should handle new Date correctly without fakeAsync', () => { const baseTime = new Date(2013, 9, 23); @@ -100,11 +100,11 @@ describe('fake async unpatched clock tests', () => { }); it('should handle setTimeout correctly', fakeAsync(() => { - setTimeout(spy, 100); - expect(spy).not.toHaveBeenCalled(); - jasmine.clock().tick(100); - expect(spy).toHaveBeenCalled(); - })); + setTimeout(spy, 100); + expect(spy).not.toHaveBeenCalled(); + jasmine.clock().tick(100); + expect(spy).toHaveBeenCalled(); + })); it('should handle setTimeout correctly without fakeAsync', () => { setTimeout(spy, 100); @@ -112,4 +112,4 @@ describe('fake async unpatched clock tests', () => { jasmine.clock().tick(100); expect(spy).toHaveBeenCalled(); }); -}) +}); diff --git a/packages/zone.js/test/zone-spec/fake-async-test.spec.ts b/packages/zone.js/test/zone-spec/fake-async-test.spec.ts index c72a29575fbe5..b60b87ca9e571 100644 --- a/packages/zone.js/test/zone-spec/fake-async-test.spec.ts +++ b/packages/zone.js/test/zone-spec/fake-async-test.spec.ts @@ -25,7 +25,6 @@ function emptyRun() { (supportNode as any).message = 'support node'; - describe('FakeAsyncTestZoneSpec', () => { let FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; let testZoneSpec: any; @@ -85,23 +84,24 @@ describe('FakeAsyncTestZoneSpec', () => { }); }); - it('should rethrow the exception on flushMicroTasks for error thrown in Promise callback', - () => { - fakeAsyncTestZone.run(() => { - Promise.resolve(null).then((_) => { - throw new Error('async'); - }); - expect(() => { - testZoneSpec.flushMicrotasks(); - }).toThrowError(/Uncaught \(in promise\): Error: async/); - }); - }); + it('should rethrow the exception on flushMicroTasks for error thrown in Promise callback', () => { + fakeAsyncTestZone.run(() => { + Promise.resolve(null).then((_) => { + throw new Error('async'); + }); + expect(() => { + testZoneSpec.flushMicrotasks(); + }).toThrowError(/Uncaught \(in promise\): Error: async/); + }); + }); it('should run chained thens', () => { fakeAsyncTestZone.run(() => { let log: number[] = []; - Promise.resolve(null).then((_) => log.push(1)).then((_) => log.push(2)); + Promise.resolve(null) + .then((_) => log.push(1)) + .then((_) => log.push(2)); expect(log).toEqual([]); @@ -142,19 +142,22 @@ describe('FakeAsyncTestZoneSpec', () => { }); }); - it('should run queued immediate timer on zero tick', ifEnvSupports('setImmediate', () => { - fakeAsyncTestZone.run(() => { - let ran = false; - setImmediate(() => { - ran = true; - }); + it( + 'should run queued immediate timer on zero tick', + ifEnvSupports('setImmediate', () => { + fakeAsyncTestZone.run(() => { + let ran = false; + setImmediate(() => { + ran = true; + }); - expect(ran).toEqual(false); + expect(ran).toEqual(false); - testZoneSpec.tick(); - expect(ran).toEqual(true); - }); - })); + testZoneSpec.tick(); + expect(ran).toEqual(true); + }); + }), + ); it('should default to processNewMacroTasksSynchronously if providing other flags', () => { function nestedTimer(callback: () => any): void { @@ -169,22 +172,20 @@ describe('FakeAsyncTestZoneSpec', () => { }); }); - - it('should not queue new macro task on tick with processNewMacroTasksSynchronously=false', - () => { - function nestedTimer(callback: () => any): void { - setTimeout(() => setTimeout(() => callback())); - } - fakeAsyncTestZone.run(() => { - const callback = jasmine.createSpy('callback'); - nestedTimer(callback); - expect(callback).not.toHaveBeenCalled(); - testZoneSpec.tick(0, null, {processNewMacroTasksSynchronously: false}); - expect(callback).not.toHaveBeenCalled(); - testZoneSpec.flush(); - expect(callback).toHaveBeenCalled(); - }); - }); + it('should not queue new macro task on tick with processNewMacroTasksSynchronously=false', () => { + function nestedTimer(callback: () => any): void { + setTimeout(() => setTimeout(() => callback())); + } + fakeAsyncTestZone.run(() => { + const callback = jasmine.createSpy('callback'); + nestedTimer(callback); + expect(callback).not.toHaveBeenCalled(); + testZoneSpec.tick(0, null, {processNewMacroTasksSynchronously: false}); + expect(callback).not.toHaveBeenCalled(); + testZoneSpec.flush(); + expect(callback).toHaveBeenCalled(); + }); + }); it('should run queued timer after sufficient clock ticks', () => { fakeAsyncTestZone.run(() => { @@ -278,9 +279,14 @@ describe('FakeAsyncTestZoneSpec', () => { it('should pass arguments to times', () => { fakeAsyncTestZone.run(() => { let value = 'genuine value'; - let id = setTimeout((arg1, arg2) => { - value = arg1 + arg2; - }, 0, 'expected', ' value'); + let id = setTimeout( + (arg1, arg2) => { + value = arg1 + arg2; + }, + 0, + 'expected', + ' value', + ); testZoneSpec.tick(); expect(value).toEqual('expected value'); @@ -290,48 +296,55 @@ describe('FakeAsyncTestZoneSpec', () => { it('should clear internal timerId cache', () => { let taskSpy: jasmine.Spy = jasmine.createSpy('taskGetState'); fakeAsyncTestZone - .fork({ - name: 'scheduleZone', - onScheduleTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task) => { - (task as any)._state = task.state; - Object.defineProperty(task, 'state', { - configurable: true, - enumerable: true, - get: () => { - taskSpy(); - return (task as any)._state; - }, - set: (newState: string) => { - (task as any)._state = newState; - } - }); - return delegate.scheduleTask(target, task); - } - }) - .run(() => { - const id = setTimeout(() => {}, 0); - testZoneSpec.tick(); - clearTimeout(id); - // This is a hack way to test the timerId cache is cleaned or not - // since the tasksByHandleId cache is an internal variable held by - // zone.js timer patch, if the cache is not cleared, the code in `timer.ts` - // will call `task.state` one more time to check whether to clear the - // task or not, so here we use this count to check the issue is fixed or not - // For details, please refer to https://github.com/angular/angular/issues/40387 - expect(taskSpy.calls.count()).toEqual(5); - }); + .fork({ + name: 'scheduleZone', + onScheduleTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task) => { + (task as any)._state = task.state; + Object.defineProperty(task, 'state', { + configurable: true, + enumerable: true, + get: () => { + taskSpy(); + return (task as any)._state; + }, + set: (newState: string) => { + (task as any)._state = newState; + }, + }); + return delegate.scheduleTask(target, task); + }, + }) + .run(() => { + const id = setTimeout(() => {}, 0); + testZoneSpec.tick(); + clearTimeout(id); + // This is a hack way to test the timerId cache is cleaned or not + // since the tasksByHandleId cache is an internal variable held by + // zone.js timer patch, if the cache is not cleared, the code in `timer.ts` + // will call `task.state` one more time to check whether to clear the + // task or not, so here we use this count to check the issue is fixed or not + // For details, please refer to https://github.com/angular/angular/issues/40387 + expect(taskSpy.calls.count()).toEqual(5); + }); }); - it('should pass arguments to setImmediate', ifEnvSupports('setImmediate', () => { - fakeAsyncTestZone.run(() => { - let value = 'genuine value'; - let id = setImmediate((arg1, arg2) => { - value = arg1 + arg2; - }, 'expected', ' value'); - - testZoneSpec.tick(); - expect(value).toEqual('expected value'); - }); - })); + it( + 'should pass arguments to setImmediate', + ifEnvSupports('setImmediate', () => { + fakeAsyncTestZone.run(() => { + let value = 'genuine value'; + let id = setImmediate( + (arg1, arg2) => { + value = arg1 + arg2; + }, + 'expected', + ' value', + ); + + testZoneSpec.tick(); + expect(value).toEqual('expected value'); + }); + }), + ); it('should run periodic timers', () => { fakeAsyncTestZone.run(() => { @@ -359,9 +372,14 @@ describe('FakeAsyncTestZoneSpec', () => { it('should pass arguments to periodic timers', () => { fakeAsyncTestZone.run(() => { let value = 'genuine value'; - let id = setInterval((arg1, arg2) => { - value = arg1 + arg2; - }, 10, 'expected', ' value'); + let id = setInterval( + (arg1, arg2) => { + value = arg1 + arg2; + }, + 10, + 'expected', + ' value', + ); testZoneSpec.tick(10); expect(value).toEqual('expected value'); @@ -391,9 +409,9 @@ describe('FakeAsyncTestZoneSpec', () => { let id: number; id = setInterval(() => { - cycles++; - clearInterval(id); - }, 10) as any as number; + cycles++; + clearInterval(id); + }, 10) as any as number; testZoneSpec.tick(10); expect(cycles).toEqual(1); @@ -437,13 +455,23 @@ describe('FakeAsyncTestZoneSpec', () => { }, 10); testZoneSpec.tick(10); - expect(log).toEqual( - ['microtask', 'timer', 't microtask', 'periodic timer', 'pt microtask']); + expect(log).toEqual([ + 'microtask', + 'timer', + 't microtask', + 'periodic timer', + 'pt microtask', + ]); testZoneSpec.tick(10); expect(log).toEqual([ - 'microtask', 'timer', 't microtask', 'periodic timer', 'pt microtask', 'periodic timer', - 'pt microtask' + 'microtask', + 'timer', + 't microtask', + 'periodic timer', + 'pt microtask', + 'periodic timer', + 'pt microtask', ]); }); }); @@ -590,7 +618,6 @@ describe('FakeAsyncTestZoneSpec', () => { }); }); - it('should process micro-tasks created in timers before next timers', () => { fakeAsyncTestZone.run(() => { let log: string[] = []; @@ -608,8 +635,13 @@ describe('FakeAsyncTestZoneSpec', () => { }, 10); testZoneSpec.flush(); - expect(log).toEqual( - ['microtask', 'periodic timer', 'pt microtask', 'timer', 't microtask']); + expect(log).toEqual([ + 'microtask', + 'periodic timer', + 'pt microtask', + 'timer', + 't microtask', + ]); }); }); @@ -641,9 +673,9 @@ describe('FakeAsyncTestZoneSpec', () => { poll(); testZoneSpec.flush(); }); - }) - .toThrowError( - 'flush failed after reaching the limit of 20 tasks. Does your code use a polling timeout?'); + }).toThrowError( + 'flush failed after reaching the limit of 20 tasks. Does your code use a polling timeout?', + ); }); it('accepts a custom limit', () => { @@ -661,9 +693,9 @@ describe('FakeAsyncTestZoneSpec', () => { poll(); testZoneSpec.flush(10); }); - }) - .toThrowError( - 'flush failed after reaching the limit of 10 tasks. Does your code use a polling timeout?'); + }).toThrowError( + 'flush failed after reaching the limit of 10 tasks. Does your code use a polling timeout?', + ); }); it('can flush periodic timers if flushPeriodic is true', () => { @@ -747,102 +779,110 @@ describe('FakeAsyncTestZoneSpec', () => { ['mozRequestAnimationFrame', 'mozCancelAnimationFrame'], ]; - const availableAnimationFrameFns = - animationFrameFns - .map(([fnName, - cancelFnName]) => [fnName, (global as any)[fnName], (global as any)[cancelFnName]]) - .filter( - ([_, fn]) => fn !== - undefined) as [string, typeof requestAnimationFrame, typeof cancelAnimationFrame][]; + const availableAnimationFrameFns = animationFrameFns + .map(([fnName, cancelFnName]) => [ + fnName, + (global as any)[fnName], + (global as any)[cancelFnName], + ]) + .filter(([_, fn]) => fn !== undefined) as [ + string, + typeof requestAnimationFrame, + typeof cancelAnimationFrame, + ][]; if (availableAnimationFrameFns.length > 0) { describe('requestAnimationFrame', () => { availableAnimationFrameFns.forEach( - ([name, requestAnimationFrameFn, cancelAnimationFrameFn]) => { - describe(name, () => { - it('should schedule a requestAnimationFrame with timeout of 16ms', () => { - fakeAsyncTestZone.run(() => { - let ran = false; - requestAnimationFrameFn(() => { - ran = true; - }); + ([name, requestAnimationFrameFn, cancelAnimationFrameFn]) => { + describe(name, () => { + it('should schedule a requestAnimationFrame with timeout of 16ms', () => { + fakeAsyncTestZone.run(() => { + let ran = false; + requestAnimationFrameFn(() => { + ran = true; + }); - testZoneSpec.tick(6); - expect(ran).toEqual(false); + testZoneSpec.tick(6); + expect(ran).toEqual(false); - testZoneSpec.tick(10); - expect(ran).toEqual(true); - }); + testZoneSpec.tick(10); + expect(ran).toEqual(true); }); - it('does not count as a pending timer', () => { - fakeAsyncTestZone.run(() => { - requestAnimationFrameFn(() => {}); - }); - expect(testZoneSpec.pendingTimers.length).toBe(0); - expect(testZoneSpec.pendingPeriodicTimers.length).toBe(0); + }); + it('does not count as a pending timer', () => { + fakeAsyncTestZone.run(() => { + requestAnimationFrameFn(() => {}); }); - it('should cancel a scheduled requestAnimationFrame', () => { - fakeAsyncTestZone.run(() => { - let ran = false; - const id = requestAnimationFrameFn(() => { - ran = true; - }); + expect(testZoneSpec.pendingTimers.length).toBe(0); + expect(testZoneSpec.pendingPeriodicTimers.length).toBe(0); + }); + it('should cancel a scheduled requestAnimationFrame', () => { + fakeAsyncTestZone.run(() => { + let ran = false; + const id = requestAnimationFrameFn(() => { + ran = true; + }); - testZoneSpec.tick(6); - expect(ran).toEqual(false); + testZoneSpec.tick(6); + expect(ran).toEqual(false); - cancelAnimationFrameFn(id); + cancelAnimationFrameFn(id); - testZoneSpec.tick(10); - expect(ran).toEqual(false); - }); + testZoneSpec.tick(10); + expect(ran).toEqual(false); }); - it('is not flushed when flushPeriodic is false', () => { - let ran = false; - fakeAsyncTestZone.run(() => { - requestAnimationFrameFn(() => { - ran = true; - }); - testZoneSpec.flush(20); - expect(ran).toEqual(false); + }); + it('is not flushed when flushPeriodic is false', () => { + let ran = false; + fakeAsyncTestZone.run(() => { + requestAnimationFrameFn(() => { + ran = true; }); + testZoneSpec.flush(20); + expect(ran).toEqual(false); }); - it('is flushed when flushPeriodic is true', () => { - let ran = false; - fakeAsyncTestZone.run(() => { - requestAnimationFrameFn(() => { - ran = true; - }); - const elapsed = testZoneSpec.flush(20, true); - expect(elapsed).toEqual(16); - expect(ran).toEqual(true); + }); + it('is flushed when flushPeriodic is true', () => { + let ran = false; + fakeAsyncTestZone.run(() => { + requestAnimationFrameFn(() => { + ran = true; }); + const elapsed = testZoneSpec.flush(20, true); + expect(elapsed).toEqual(16); + expect(ran).toEqual(true); }); - it('should pass timestamp as parameter', () => { - let timestamp = 0; - let timestamp1 = 0; - fakeAsyncTestZone.run(() => { - requestAnimationFrameFn((ts) => { - timestamp = ts; - requestAnimationFrameFn(ts1 => { - timestamp1 = ts1; - }); + }); + it('should pass timestamp as parameter', () => { + let timestamp = 0; + let timestamp1 = 0; + fakeAsyncTestZone.run(() => { + requestAnimationFrameFn((ts) => { + timestamp = ts; + requestAnimationFrameFn((ts1) => { + timestamp1 = ts1; }); - const elapsed = testZoneSpec.flush(20, true); - const elapsed1 = testZoneSpec.flush(20, true); - expect(elapsed).toEqual(16); - expect(elapsed1).toEqual(16); - expect(timestamp).toEqual(16); - expect(timestamp1).toEqual(32); }); + const elapsed = testZoneSpec.flush(20, true); + const elapsed1 = testZoneSpec.flush(20, true); + expect(elapsed).toEqual(16); + expect(elapsed1).toEqual(16); + expect(timestamp).toEqual(16); + expect(timestamp1).toEqual(32); }); }); }); + }, + ); }); } describe( - 'XHRs', ifEnvSupports('XMLHttpRequest', () => { + 'XHRs', + ifEnvSupports( + 'XMLHttpRequest', + () => { it('should throw an exception if an XHR is initiated in the zone', () => { expect(() => { fakeAsyncTestZone.run(() => { @@ -860,58 +900,72 @@ describe('FakeAsyncTestZoneSpec', () => { }); }).toThrowError('Cannot make XHRs from within a fake async test. Request URL: /test'); }); - }, emptyRun)); - - describe('node process', ifEnvSupports(supportNode, () => { - it('should be able to schedule microTask with additional arguments', () => { - const process = global['process']; - const nextTick = process && process['nextTick']; - if (!nextTick) { - return; - } - fakeAsyncTestZone.run(() => { - let tickRun = false; - let cbArgRun = false; - nextTick( - (strArg: string, cbArg: Function) => { - tickRun = true; - expect(strArg).toEqual('stringArg'); - cbArg(); - }, - 'stringArg', - () => { - cbArgRun = true; - }); - - expect(tickRun).toEqual(false); - - testZoneSpec.flushMicrotasks(); - expect(tickRun).toEqual(true); - expect(cbArgRun).toEqual(true); - }); - }); - }, emptyRun)); + }, + emptyRun, + ), + ); + + describe( + 'node process', + ifEnvSupports( + supportNode, + () => { + it('should be able to schedule microTask with additional arguments', () => { + const process = global['process']; + const nextTick = process && process['nextTick']; + if (!nextTick) { + return; + } + fakeAsyncTestZone.run(() => { + let tickRun = false; + let cbArgRun = false; + nextTick( + (strArg: string, cbArg: Function) => { + tickRun = true; + expect(strArg).toEqual('stringArg'); + cbArg(); + }, + 'stringArg', + () => { + cbArgRun = true; + }, + ); + + expect(tickRun).toEqual(false); + + testZoneSpec.flushMicrotasks(); + expect(tickRun).toEqual(true); + expect(cbArgRun).toEqual(true); + }); + }); + }, + emptyRun, + ), + ); describe('should allow user define which macroTask fakeAsyncTest', () => { let FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; let testZoneSpec: any; let fakeAsyncTestZone: Zone; it('should support custom non perodic macroTask', () => { - testZoneSpec = new FakeAsyncTestZoneSpec( - 'name', false, [{source: 'TestClass.myTimeout', callbackArgs: ['test']}]); + testZoneSpec = new FakeAsyncTestZoneSpec('name', false, [ + {source: 'TestClass.myTimeout', callbackArgs: ['test']}, + ]); class TestClass { myTimeout(callback: Function) {} } fakeAsyncTestZone = Zone.current.fork(testZoneSpec); fakeAsyncTestZone.run(() => { let ran = false; - patchMacroTask( - TestClass.prototype, 'myTimeout', - (self: any, args: any[]) => - ({name: 'TestClass.myTimeout', target: self, cbIdx: 0, args: args})); + patchMacroTask(TestClass.prototype, 'myTimeout', (self: any, args: any[]) => ({ + name: 'TestClass.myTimeout', + target: self, + cbIdx: 0, + args: args, + })); const testClass = new TestClass(); - testClass.myTimeout(function(callbackArgs: any) { + testClass.myTimeout(function (callbackArgs: any) { ran = true; expect(callbackArgs).toEqual('test'); }); @@ -931,10 +985,12 @@ describe('FakeAsyncTestZoneSpec', () => { fakeAsyncTestZone = Zone.current.fork(testZoneSpec); fakeAsyncTestZone.run(() => { let ran = false; - patchMacroTask( - TestClass.prototype, 'myTimeout', - (self: any, args: any[]) => - ({name: 'TestClass.myTimeout', target: self, cbIdx: 0, args: args})); + patchMacroTask(TestClass.prototype, 'myTimeout', (self: any, args: any[]) => ({ + name: 'TestClass.myTimeout', + target: self, + cbIdx: 0, + args: args, + })); const testClass = new TestClass(); testClass.myTimeout(() => { @@ -948,10 +1004,10 @@ describe('FakeAsyncTestZoneSpec', () => { }); }); - it('should support custom perodic macroTask', () => { - testZoneSpec = new FakeAsyncTestZoneSpec( - 'name', false, [{source: 'TestClass.myInterval', isPeriodic: true}]); + testZoneSpec = new FakeAsyncTestZoneSpec('name', false, [ + {source: 'TestClass.myInterval', isPeriodic: true}, + ]); fakeAsyncTestZone = Zone.current.fork(testZoneSpec); fakeAsyncTestZone.run(() => { let cycle = 0; @@ -960,10 +1016,12 @@ describe('FakeAsyncTestZoneSpec', () => { return null; } } - patchMacroTask( - TestClass.prototype, 'myInterval', - (self: any, args: any[]) => - ({name: 'TestClass.myInterval', target: self, cbIdx: 0, args: args})); + patchMacroTask(TestClass.prototype, 'myInterval', (self: any, args: any[]) => ({ + name: 'TestClass.myInterval', + target: self, + cbIdx: 0, + args: args, + })); const testClass = new TestClass(); const id = testClass.myInterval(() => { @@ -1060,33 +1118,40 @@ describe('FakeAsyncTestZoneSpec', () => { }); }); - describe('fakeAsyncTest should patch rxjs scheduler', ifEnvSupports(() => isNode, () => { - let FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; - let testZoneSpec: any; - let fakeAsyncTestZone: Zone; - - beforeEach(() => { - testZoneSpec = new FakeAsyncTestZoneSpec('name', false); - fakeAsyncTestZone = Zone.current.fork(testZoneSpec); - }); - - it('should get date diff correctly', (done) => { - fakeAsyncTestZone.run(() => { - let result: any = null; - const observable = new Observable((subscribe: any) => { - subscribe.next('hello'); - subscribe.complete(); - }); - observable.pipe(delay(1000)).subscribe((v: any) => { - result = v; - }); - expect(result).toBe(null); - testZoneSpec.tick(1000); - expect(result).toBe('hello'); - done(); - }); - }); - }, emptyRun)); + describe( + 'fakeAsyncTest should patch rxjs scheduler', + ifEnvSupports( + () => isNode, + () => { + let FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; + let testZoneSpec: any; + let fakeAsyncTestZone: Zone; + + beforeEach(() => { + testZoneSpec = new FakeAsyncTestZoneSpec('name', false); + fakeAsyncTestZone = Zone.current.fork(testZoneSpec); + }); + + it('should get date diff correctly', (done) => { + fakeAsyncTestZone.run(() => { + let result: any = null; + const observable = new Observable((subscribe: any) => { + subscribe.next('hello'); + subscribe.complete(); + }); + observable.pipe(delay(1000)).subscribe((v: any) => { + result = v; + }); + expect(result).toBe(null); + testZoneSpec.tick(1000); + expect(result).toBe('hello'); + done(); + }); + }); + }, + emptyRun, + ), + ); }); class Log { @@ -1131,7 +1196,6 @@ describe('fake async', () => { })('foo', 'bar'); }); - it('should throw on nested calls', () => { expect(() => { fakeAsync(() => { @@ -1144,7 +1208,7 @@ describe('fake async', () => { let thenRan = false; fakeAsync(() => { - resolvedPromise.then(_ => { + resolvedPromise.then((_) => { thenRan = true; }); })(); @@ -1152,48 +1216,47 @@ describe('fake async', () => { expect(thenRan).toEqual(true); }); - it('should propagate the return value', () => { expect(fakeAsync(() => 'foo')()).toEqual('foo'); }); describe('Promise', () => { it('should run asynchronous code', fakeAsync(() => { - let thenRan = false; - resolvedPromise.then((_) => { - thenRan = true; - }); + let thenRan = false; + resolvedPromise.then((_) => { + thenRan = true; + }); - expect(thenRan).toEqual(false); + expect(thenRan).toEqual(false); - flushMicrotasks(); - expect(thenRan).toEqual(true); - })); + flushMicrotasks(); + expect(thenRan).toEqual(true); + })); it('should run chained thens', fakeAsync(() => { - const log = new Log(); + const log = new Log(); - resolvedPromise.then((_) => log.add(1)).then((_) => log.add(2)); + resolvedPromise.then((_) => log.add(1)).then((_) => log.add(2)); - expect(log.result()).toEqual(''); + expect(log.result()).toEqual(''); - flushMicrotasks(); - expect(log.result()).toEqual('1; 2'); - })); + flushMicrotasks(); + expect(log.result()).toEqual('1; 2'); + })); it('should run Promise created in Promise', fakeAsync(() => { - const log = new Log(); + const log = new Log(); - resolvedPromise.then((_) => { - log.add(1); - resolvedPromise.then((_) => log.add(2)); - }); + resolvedPromise.then((_) => { + log.add(1); + resolvedPromise.then((_) => log.add(2)); + }); - expect(log.result()).toEqual(''); + expect(log.result()).toEqual(''); - flushMicrotasks(); - expect(log.result()).toEqual('1; 2'); - })); + flushMicrotasks(); + expect(log.result()).toEqual('1; 2'); + })); it('should complain if the test throws an exception during async calls', () => { expect(() => { @@ -1217,57 +1280,56 @@ describe('fake async', () => { describe('timers', () => { it('should run queued zero duration timer on zero tick', fakeAsync(() => { - let ran = false; - setTimeout(() => { - ran = true; - }, 0); - - expect(ran).toEqual(false); + let ran = false; + setTimeout(() => { + ran = true; + }, 0); - tick(); - expect(ran).toEqual(true); - })); + expect(ran).toEqual(false); + tick(); + expect(ran).toEqual(true); + })); it('should run queued timer after sufficient clock ticks', fakeAsync(() => { - let ran = false; - setTimeout(() => { - ran = true; - }, 10); + let ran = false; + setTimeout(() => { + ran = true; + }, 10); - tick(6); - expect(ran).toEqual(false); + tick(6); + expect(ran).toEqual(false); - tick(6); - expect(ran).toEqual(true); - })); + tick(6); + expect(ran).toEqual(true); + })); it('should run queued timer only once', fakeAsync(() => { - let cycles = 0; - setTimeout(() => { - cycles++; - }, 10); + let cycles = 0; + setTimeout(() => { + cycles++; + }, 10); - tick(10); - expect(cycles).toEqual(1); + tick(10); + expect(cycles).toEqual(1); - tick(10); - expect(cycles).toEqual(1); + tick(10); + expect(cycles).toEqual(1); - tick(10); - expect(cycles).toEqual(1); - })); + tick(10); + expect(cycles).toEqual(1); + })); it('should not run cancelled timer', fakeAsync(() => { - let ran = false; - const id = setTimeout(() => { - ran = true; - }, 10); - clearTimeout(id); + let ran = false; + const id = setTimeout(() => { + ran = true; + }, 10); + clearTimeout(id); - tick(10); - expect(ran).toEqual(false); - })); + tick(10); + expect(ran).toEqual(false); + })); it('should throw an error on dangling timers', () => { expect(() => { @@ -1286,156 +1348,155 @@ describe('fake async', () => { }); it('should run periodic timers', fakeAsync(() => { - let cycles = 0; - const id = setInterval(() => { - cycles++; - }, 10); + let cycles = 0; + const id = setInterval(() => { + cycles++; + }, 10); - tick(10); - expect(cycles).toEqual(1); + tick(10); + expect(cycles).toEqual(1); - tick(10); - expect(cycles).toEqual(2); + tick(10); + expect(cycles).toEqual(2); - tick(10); - expect(cycles).toEqual(3); - clearInterval(id); - })); + tick(10); + expect(cycles).toEqual(3); + clearInterval(id); + })); it('should not run cancelled periodic timer', fakeAsync(() => { - let ran = false; - const id = setInterval(() => { - ran = true; - }, 10); - clearInterval(id); + let ran = false; + const id = setInterval(() => { + ran = true; + }, 10); + clearInterval(id); - tick(10); - expect(ran).toEqual(false); - })); + tick(10); + expect(ran).toEqual(false); + })); it('should be able to cancel periodic timers from a callback', fakeAsync(() => { - let cycles = 0; - let id: NodeJS.Timer; + let cycles = 0; + let id: NodeJS.Timer; - id = setInterval(() => { - cycles++; - clearInterval(id); - }, 10); + id = setInterval(() => { + cycles++; + clearInterval(id); + }, 10); - tick(10); - expect(cycles).toEqual(1); + tick(10); + expect(cycles).toEqual(1); - tick(10); - expect(cycles).toEqual(1); - })); + tick(10); + expect(cycles).toEqual(1); + })); it('should clear periodic timers', fakeAsync(() => { - let cycles = 0; - const id = setInterval(() => { - cycles++; - }, 10); + let cycles = 0; + const id = setInterval(() => { + cycles++; + }, 10); - tick(10); - expect(cycles).toEqual(1); + tick(10); + expect(cycles).toEqual(1); - discardPeriodicTasks(); + discardPeriodicTasks(); - // Tick once to clear out the timer which already started. - tick(10); - expect(cycles).toEqual(2); + // Tick once to clear out the timer which already started. + tick(10); + expect(cycles).toEqual(2); - tick(10); - // Nothing should change - expect(cycles).toEqual(2); - })); + tick(10); + // Nothing should change + expect(cycles).toEqual(2); + })); it('should process microtasks before timers', fakeAsync(() => { - const log = new Log(); + const log = new Log(); - resolvedPromise.then((_) => log.add('microtask')); + resolvedPromise.then((_) => log.add('microtask')); - setTimeout(() => log.add('timer'), 9); + setTimeout(() => log.add('timer'), 9); - const id = setInterval(() => log.add('periodic timer'), 10); + const id = setInterval(() => log.add('periodic timer'), 10); - expect(log.result()).toEqual(''); + expect(log.result()).toEqual(''); - tick(10); - expect(log.result()).toEqual('microtask; timer; periodic timer'); - clearInterval(id); - })); + tick(10); + expect(log.result()).toEqual('microtask; timer; periodic timer'); + clearInterval(id); + })); it('should process micro-tasks created in timers before next timers', fakeAsync(() => { - const log = new Log(); + const log = new Log(); - resolvedPromise.then((_) => log.add('microtask')); + resolvedPromise.then((_) => log.add('microtask')); - setTimeout(() => { - log.add('timer'); - resolvedPromise.then((_) => log.add('t microtask')); - }, 9); + setTimeout(() => { + log.add('timer'); + resolvedPromise.then((_) => log.add('t microtask')); + }, 9); - const id = setInterval(() => { - log.add('periodic timer'); - resolvedPromise.then((_) => log.add('pt microtask')); - }, 10); + const id = setInterval(() => { + log.add('periodic timer'); + resolvedPromise.then((_) => log.add('pt microtask')); + }, 10); - tick(10); - expect(log.result()) - .toEqual('microtask; timer; t microtask; periodic timer; pt microtask'); + tick(10); + expect(log.result()).toEqual('microtask; timer; t microtask; periodic timer; pt microtask'); - tick(10); - expect(log.result()) - .toEqual( - 'microtask; timer; t microtask; periodic timer; pt microtask; periodic timer; pt microtask'); - clearInterval(id); - })); + tick(10); + expect(log.result()).toEqual( + 'microtask; timer; t microtask; periodic timer; pt microtask; periodic timer; pt microtask', + ); + clearInterval(id); + })); it('should flush tasks', fakeAsync(() => { - let ran = false; - setTimeout(() => { - ran = true; - }, 10); + let ran = false; + setTimeout(() => { + ran = true; + }, 10); - flush(); - expect(ran).toEqual(true); - })); + flush(); + expect(ran).toEqual(true); + })); it('should flush multiple tasks', fakeAsync(() => { - let ran = false; - let ran2 = false; - setTimeout(() => { - ran = true; - }, 10); - setTimeout(() => { - ran2 = true; - }, 30); - - let elapsed = flush(); - - expect(ran).toEqual(true); - expect(ran2).toEqual(true); - expect(elapsed).toEqual(30); - })); + let ran = false; + let ran2 = false; + setTimeout(() => { + ran = true; + }, 10); + setTimeout(() => { + ran2 = true; + }, 30); + + let elapsed = flush(); + + expect(ran).toEqual(true); + expect(ran2).toEqual(true); + expect(elapsed).toEqual(30); + })); it('should move periodic tasks', fakeAsync(() => { - let ran = false; - let count = 0; - setInterval(() => { - count++; - }, 10); - setTimeout(() => { - ran = true; - }, 35); - - let elapsed = flush(); - - expect(count).toEqual(3); - expect(ran).toEqual(true); - expect(elapsed).toEqual(35); - - discardPeriodicTasks(); - })); + let ran = false; + let count = 0; + setInterval(() => { + count++; + }, 10); + setTimeout(() => { + ran = true; + }, 35); + + let elapsed = flush(); + + expect(count).toEqual(3); + expect(ran).toEqual(true); + expect(elapsed).toEqual(35); + + discardPeriodicTasks(); + })); }); describe('outside of the fakeAsync zone', () => { @@ -1472,47 +1533,47 @@ describe('fake async', () => { })); it('should use the same zone as in beforeEach', fakeAsync(() => { - zoneInTest1 = Zone.current; - expect(zoneInTest1).toBe(zoneInBeforeEach); - })); + zoneInTest1 = Zone.current; + expect(zoneInTest1).toBe(zoneInBeforeEach); + })); }); describe('fakeAsync should work with Date', () => { it('should get date diff correctly', fakeAsync(() => { - const start = Date.now(); - tick(100); - const end = Date.now(); - expect(end - start).toBe(100); - })); + const start = Date.now(); + tick(100); + const end = Date.now(); + expect(end - start).toBe(100); + })); it('should check date type correctly', fakeAsync(() => { - const d: any = new Date(); - expect(d instanceof Date).toBe(true); - })); + const d: any = new Date(); + expect(d instanceof Date).toBe(true); + })); it('should new Date with parameter correctly', fakeAsync(() => { - const d: Date = new Date(0); - expect(d.getFullYear()).toBeLessThan(1971); - const d1: Date = new Date('December 17, 1995 03:24:00'); - expect(d1.getFullYear()).toEqual(1995); - const d2: Date = new Date(1995, 11, 17, 3, 24, 0); - expect(isNaN(d2.getTime())).toBeFalsy(); - expect(d2.getFullYear()).toEqual(1995); - d2.setFullYear(1985); - expect(d2.getFullYear()).toBe(1985); - expect(d2.getMonth()).toBe(11); - expect(d2.getDate()).toBe(17); - })); + const d: Date = new Date(0); + expect(d.getFullYear()).toBeLessThan(1971); + const d1: Date = new Date('December 17, 1995 03:24:00'); + expect(d1.getFullYear()).toEqual(1995); + const d2: Date = new Date(1995, 11, 17, 3, 24, 0); + expect(isNaN(d2.getTime())).toBeFalsy(); + expect(d2.getFullYear()).toEqual(1995); + d2.setFullYear(1985); + expect(d2.getFullYear()).toBe(1985); + expect(d2.getMonth()).toBe(11); + expect(d2.getDate()).toBe(17); + })); it('should get Date.UTC() correctly', fakeAsync(() => { - const utcDate = new Date(Date.UTC(96, 11, 1, 0, 0, 0)); - expect(utcDate.getFullYear()).toBe(1996); - })); + const utcDate = new Date(Date.UTC(96, 11, 1, 0, 0, 0)); + expect(utcDate.getFullYear()).toBe(1996); + })); it('should call Date.parse() correctly', fakeAsync(() => { - const unixTimeZero = Date.parse('01 Jan 1970 00:00:00 GMT'); - expect(unixTimeZero).toBe(0); - })); + const unixTimeZero = Date.parse('01 Jan 1970 00:00:00 GMT'); + expect(unixTimeZero).toBe(0); + })); }); }); @@ -1529,14 +1590,14 @@ describe('ProxyZone', () => { ProxyZoneSpec.assertPresent(); let state: string = 'not run'; const testZone = Zone.current.fork({name: 'test-zone'}); - (fakeAsync(() => { + fakeAsync(() => { testZone.run(() => { - Promise.resolve('works').then((v) => state = v); + Promise.resolve('works').then((v) => (state = v)); expect(state).toEqual('not run'); flushMicrotasks(); expect(state).toEqual('works'); }); - }))(); + })(); expect(state).toEqual('works'); }); }); diff --git a/packages/zone.js/test/zone-spec/long-stack-trace-zone.spec.ts b/packages/zone.js/test/zone-spec/long-stack-trace-zone.spec.ts index 36c5f3d26764a..f9306d96168a2 100644 --- a/packages/zone.js/test/zone-spec/long-stack-trace-zone.spec.ts +++ b/packages/zone.js/test/zone-spec/long-stack-trace-zone.spec.ts @@ -12,193 +12,208 @@ import {ifEnvSupports, isSafari, isSupportSetErrorStack} from '../test-util'; const defineProperty = (Object as any)[zoneSymbol('defineProperty')] || Object.defineProperty; describe( - 'longStackTraceZone', ifEnvSupports(isSupportSetErrorStack, function() { - let log: Error[]; - let lstz: Zone; - let longStackTraceZoneSpec = (Zone as any)['longStackTraceZoneSpec']; - let defaultTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; - - beforeEach(function() { - lstz = Zone.current.fork(longStackTraceZoneSpec).fork({ - name: 'long-stack-trace-zone-test', - onHandleError: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any): - boolean => { - parentZoneDelegate.handleError(targetZone, error); - log.push(error); - return false; - } - }); - - log = []; - jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; + 'longStackTraceZone', + ifEnvSupports(isSupportSetErrorStack, function () { + let log: Error[]; + let lstz: Zone; + let longStackTraceZoneSpec = (Zone as any)['longStackTraceZoneSpec']; + let defaultTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; + + beforeEach(function () { + lstz = Zone.current.fork(longStackTraceZoneSpec).fork({ + name: 'long-stack-trace-zone-test', + onHandleError: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + error: any, + ): boolean => { + parentZoneDelegate.handleError(targetZone, error); + log.push(error); + return false; + }, }); - afterEach(function() { - jasmine.DEFAULT_TIMEOUT_INTERVAL = defaultTimeout; - }); + log = []; + jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; + }); - function expectElapsed(stack: string, expectedCount: number) { - try { - let actualCount = stack.split('_Elapsed_').length; - if (actualCount !== expectedCount) { - expect(actualCount).toEqual(expectedCount); - console.log(stack); - } - } catch (e) { - expect(e).toBe(null); + afterEach(function () { + jasmine.DEFAULT_TIMEOUT_INTERVAL = defaultTimeout; + }); + + function expectElapsed(stack: string, expectedCount: number) { + try { + let actualCount = stack.split('_Elapsed_').length; + if (actualCount !== expectedCount) { + expect(actualCount).toEqual(expectedCount); + console.log(stack); } + } catch (e) { + expect(e).toBe(null); } - - it('should produce long stack traces', function(done) { - lstz.run(function() { - setTimeout(function() { - setTimeout(function() { - setTimeout(function() { - expectElapsed(log[0].stack!, 3); - done(); - }, 0); - throw new Error('Hello'); + } + + it('should produce long stack traces', function (done) { + lstz.run(function () { + setTimeout(function () { + setTimeout(function () { + setTimeout(function () { + expectElapsed(log[0].stack!, 3); + done(); }, 0); + throw new Error('Hello'); }, 0); - }); + }, 0); }); - - it('should produce long stack traces for optimized eventTask', - ifEnvSupports(() => isBrowser, function() { - lstz.run(function() { - const button = document.createElement('button'); - const clickEvent = document.createEvent('Event'); - clickEvent.initEvent('click', true, true); - document.body.appendChild(button); - - button.addEventListener('click', function() { - expectElapsed(log[0].stack!, 1); - }); - - button.dispatchEvent(clickEvent); - - document.body.removeChild(button); - }); - })); - - it('should not overwrite long stack traces data for different optimized eventTasks', - ifEnvSupports(() => isBrowser, function() { - lstz.run(function() { - const button = document.createElement('button'); - const clickEvent = document.createEvent('Event'); - clickEvent.initEvent('click', true, true); - document.body.appendChild(button); - - const div = document.createElement('div'); - const enterEvent = document.createEvent('Event'); - enterEvent.initEvent('mouseenter', true, true); - document.body.appendChild(div); - - button.addEventListener('click', function() { - throw new Error('clickError'); - }); - - div.addEventListener('mouseenter', function() { - throw new Error('enterError'); - }); - - button.dispatchEvent(clickEvent); - div.dispatchEvent(enterEvent); - - expect(log.length).toBe(2); - if (!isSafari() && !isIE()) { - expect(log[0].stack === log[1].stack).toBe(false); - } - - document.body.removeChild(button); - document.body.removeChild(div); - }); - })); - - it('should produce a long stack trace even if stack setter throws', (done) => { - let wasStackAssigned = false; - let error = new Error('Expected error'); - defineProperty(error, 'stack', { - configurable: false, - get: () => 'someStackTrace', - set: (v: any) => { - throw new Error('no writes'); - } - }); - lstz.run(() => { - setTimeout(() => { - throw error; + }); + + it( + 'should produce long stack traces for optimized eventTask', + ifEnvSupports( + () => isBrowser, + function () { + lstz.run(function () { + const button = document.createElement('button'); + const clickEvent = document.createEvent('Event'); + clickEvent.initEvent('click', true, true); + document.body.appendChild(button); + + button.addEventListener('click', function () { + expectElapsed(log[0].stack!, 1); + }); + + button.dispatchEvent(clickEvent); + + document.body.removeChild(button); }); - }); + }, + ), + ); + + it( + 'should not overwrite long stack traces data for different optimized eventTasks', + ifEnvSupports( + () => isBrowser, + function () { + lstz.run(function () { + const button = document.createElement('button'); + const clickEvent = document.createEvent('Event'); + clickEvent.initEvent('click', true, true); + document.body.appendChild(button); + + const div = document.createElement('div'); + const enterEvent = document.createEvent('Event'); + enterEvent.initEvent('mouseenter', true, true); + document.body.appendChild(div); + + button.addEventListener('click', function () { + throw new Error('clickError'); + }); + + div.addEventListener('mouseenter', function () { + throw new Error('enterError'); + }); + + button.dispatchEvent(clickEvent); + div.dispatchEvent(enterEvent); + + expect(log.length).toBe(2); + if (!isSafari() && !isIE()) { + expect(log[0].stack === log[1].stack).toBe(false); + } + + document.body.removeChild(button); + document.body.removeChild(div); + }); + }, + ), + ); + + it('should produce a long stack trace even if stack setter throws', (done) => { + let wasStackAssigned = false; + let error = new Error('Expected error'); + defineProperty(error, 'stack', { + configurable: false, + get: () => 'someStackTrace', + set: (v: any) => { + throw new Error('no writes'); + }, + }); + lstz.run(() => { setTimeout(() => { - const e = log[0]; - expect((e as any).longStack).toBeTruthy(); - done(); + throw error; }); }); - - it('should produce long stack traces when has uncaught error in promise', function(done) { - lstz.runGuarded(function() { - setTimeout(function() { - setTimeout(function() { - let promise = new Promise(function(resolve, reject) { - setTimeout(function() { - reject(new Error('Hello Promise')); - }, 0); - }); - promise.then(function() { - fail('should not get here'); - }); - setTimeout(function() { - expectElapsed(log[0].stack!, 5); - done(); - }, 0); - }, 0); - }, 0); - }); + setTimeout(() => { + const e = log[0]; + expect((e as any).longStack).toBeTruthy(); + done(); }); - - it('should produce long stack traces when handling error in promise', function(done) { - lstz.runGuarded(function() { - setTimeout(function() { - setTimeout(function() { - let promise = new Promise(function(resolve, reject) { - setTimeout(function() { - try { - throw new Error('Hello Promise'); - } catch (err) { - reject(err); - } - }, 0); - }); - promise.catch(function(error) { - // should be able to get long stack trace - const longStackFrames: string = longStackTraceZoneSpec.getLongStackTrace(error); - expectElapsed(longStackFrames, 4); - done(); - }); + }); + + it('should produce long stack traces when has uncaught error in promise', function (done) { + lstz.runGuarded(function () { + setTimeout(function () { + setTimeout(function () { + let promise = new Promise(function (resolve, reject) { + setTimeout(function () { + reject(new Error('Hello Promise')); + }, 0); + }); + promise.then(function () { + fail('should not get here'); + }); + setTimeout(function () { + expectElapsed(log[0].stack!, 5); + done(); }, 0); }, 0); - }); + }, 0); }); - - it('should not produce long stack traces if Error.stackTraceLimit = 0', function(done) { - const originalStackTraceLimit = Error.stackTraceLimit; - lstz.run(function() { - setTimeout(function() { - setTimeout(function() { - setTimeout(function() { - if (log[0].stack) { - expectElapsed(log[0].stack!, 1); + }); + + it('should produce long stack traces when handling error in promise', function (done) { + lstz.runGuarded(function () { + setTimeout(function () { + setTimeout(function () { + let promise = new Promise(function (resolve, reject) { + setTimeout(function () { + try { + throw new Error('Hello Promise'); + } catch (err) { + reject(err); } - Error.stackTraceLimit = originalStackTraceLimit; - done(); }, 0); - Error.stackTraceLimit = 0; - throw new Error('Hello'); + }); + promise.catch(function (error) { + // should be able to get long stack trace + const longStackFrames: string = longStackTraceZoneSpec.getLongStackTrace(error); + expectElapsed(longStackFrames, 4); + done(); + }); + }, 0); + }, 0); + }); + }); + + it('should not produce long stack traces if Error.stackTraceLimit = 0', function (done) { + const originalStackTraceLimit = Error.stackTraceLimit; + lstz.run(function () { + setTimeout(function () { + setTimeout(function () { + setTimeout(function () { + if (log[0].stack) { + expectElapsed(log[0].stack!, 1); + } + Error.stackTraceLimit = originalStackTraceLimit; + done(); }, 0); + Error.stackTraceLimit = 0; + throw new Error('Hello'); }, 0); - }); + }, 0); }); - })); + }); + }), +); diff --git a/packages/zone.js/test/zone-spec/proxy.spec.ts b/packages/zone.js/test/zone-spec/proxy.spec.ts index 39b0478866df1..a11d60e3b49fc 100644 --- a/packages/zone.js/test/zone-spec/proxy.spec.ts +++ b/packages/zone.js/test/zone-spec/proxy.spec.ts @@ -80,13 +80,16 @@ describe('ProxySpec', () => { let called = false; proxyZoneSpec.setDelegate({ name: '.', - onFork: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - zoneSpec: ZoneSpec) => { - expect(currentZone).toBe(proxyZone); - expect(targetZone).toBe(proxyZone), expect(zoneSpec.name).toBe('fork2'); - called = true; - } + onFork: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + zoneSpec: ZoneSpec, + ) => { + expect(currentZone).toBe(proxyZone); + expect(targetZone).toBe(proxyZone), expect(zoneSpec.name).toBe('fork2'); + called = true; + }, }); proxyZone.fork({name: 'fork2'}); expect(called).toBe(true); @@ -97,11 +100,15 @@ describe('ProxySpec', () => { expect(proxyZone.wrap(fn, 'test')('works')).toEqual('works'); proxyZoneSpec.setDelegate({ name: '.', - onIntercept: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - delegate: Function, source: string): Function => { - return () => '(works)'; - } + onIntercept: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + delegate: Function, + source: string, + ): Function => { + return () => '(works)'; + }, }); expect(proxyZone.wrap(fn, 'test')('works')).toEqual('(works)'); }); @@ -111,12 +118,23 @@ describe('ProxySpec', () => { expect(proxyZone.run(fn)).toEqual('works'); proxyZoneSpec.setDelegate({ name: '.', - onInvoke: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - delegate: Function, applyThis: any, applyArgs: any[], source: string) => { - return `(${ - parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source)})`; - } + onInvoke: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + delegate: Function, + applyThis: any, + applyArgs: any[], + source: string, + ) => { + return `(${parentZoneDelegate.invoke( + targetZone, + delegate, + applyThis, + applyArgs, + source, + )})`; + }, }); expect(proxyZone.run(fn)).toEqual('(works)'); }); @@ -129,19 +147,28 @@ describe('ProxySpec', () => { expect(() => proxyZone.run(fn)).toThrow(error); proxyZoneSpec.setDelegate({ name: '.', - onHandleError: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any): - boolean => { - expect(error).toEqual(error); - return false; - } + onHandleError: ( + parentZoneDelegate: ZoneDelegate, + currentZone: Zone, + targetZone: Zone, + error: any, + ): boolean => { + expect(error).toEqual(error); + return false; + }, }); expect(() => proxyZone.runGuarded(fn)).not.toThrow(); }); it('should Task', () => { const fn = (): any => null; - const task = proxyZone.scheduleMacroTask('test', fn, {}, () => null, () => null); + const task = proxyZone.scheduleMacroTask( + 'test', + fn, + {}, + () => null, + () => null, + ); expect(task.source).toEqual('test'); proxyZone.cancelTask(task); }); @@ -158,14 +185,14 @@ describe('ProxySpec', () => { onHasTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, hasTask: HasTaskState) => { log.push(`zoneSpec1 hasTask: ${hasTask.microTask},${hasTask.macroTask}`); return delegate.hasTask(target, hasTask); - } + }, }; const zoneSpec2 = { name: 'zone2', onHasTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, hasTask: HasTaskState) => { log.push(`zoneSpec2 hasTask: ${hasTask.microTask},${hasTask.macroTask}`); return delegate.hasTask(target, hasTask); - } + }, }; proxyZoneSpec.setDelegate(zoneSpec1); proxyZone.run(() => { @@ -194,10 +221,16 @@ describe('ProxySpec', () => { setTimeout(() => { expect(log).toEqual([ - 'zoneSpec1 hasTask: false,true', 'zoneSpec2 hasTask: false,true', - 'zoneSpec2 hasTask: true,true', 'zoneSpec2 hasTask: true,true', 'then in zoneSpec2', - 'then in zoneSpec2', 'zoneSpec2 hasTask: false,true', 'timeout in zoneSpec1', - 'timeout in null spec', 'zoneSpec2 hasTask: false,false' + 'zoneSpec1 hasTask: false,true', + 'zoneSpec2 hasTask: false,true', + 'zoneSpec2 hasTask: true,true', + 'zoneSpec2 hasTask: true,true', + 'then in zoneSpec2', + 'then in zoneSpec2', + 'zoneSpec2 hasTask: false,true', + 'timeout in zoneSpec1', + 'timeout in null spec', + 'zoneSpec2 hasTask: false,false', ]); done(); }, 300); diff --git a/packages/zone.js/test/zone-spec/sync-test.spec.ts b/packages/zone.js/test/zone-spec/sync-test.spec.ts index f94c338552f84..00f02a831a699 100644 --- a/packages/zone.js/test/zone-spec/sync-test.spec.ts +++ b/packages/zone.js/test/zone-spec/sync-test.spec.ts @@ -21,10 +21,10 @@ describe('SyncTestZoneSpec', () => { it('should fail on Promise.then', () => { syncTestZone.run(() => { expect(() => { - Promise.resolve().then(function() {}); - }) - .toThrow(new Error( - 'Cannot call Promise.then from within a sync test (syncTestZone for name).')); + Promise.resolve().then(function () {}); + }).toThrow( + new Error('Cannot call Promise.then from within a sync test (syncTestZone for name).'), + ); }); }); @@ -32,37 +32,43 @@ describe('SyncTestZoneSpec', () => { syncTestZone.run(() => { expect(() => { setTimeout(() => {}, 100); - }) - .toThrow( - new Error('Cannot call setTimeout from within a sync test (syncTestZone for name).')); + }).toThrow( + new Error('Cannot call setTimeout from within a sync test (syncTestZone for name).'), + ); }); }); - describe('event tasks', ifEnvSupports('document', () => { - it('should work with event tasks', () => { - syncTestZone.run(() => { - const button = document.createElement('button'); - document.body.appendChild(button); - let x = 1; - try { - button.addEventListener('click', () => { - x++; - }); + describe( + 'event tasks', + ifEnvSupports( + 'document', + () => { + it('should work with event tasks', () => { + syncTestZone.run(() => { + const button = document.createElement('button'); + document.body.appendChild(button); + let x = 1; + try { + button.addEventListener('click', () => { + x++; + }); - button.click(); - expect(x).toEqual(2); + button.click(); + expect(x).toEqual(2); - button.click(); - expect(x).toEqual(3); - } finally { - document.body.removeChild(button); - } - }); - }); - }, emptyRun)); + button.click(); + expect(x).toEqual(3); + } finally { + document.body.removeChild(button); + } + }); + }); + }, + emptyRun, + ), + ); }); - function emptyRun() { // Jasmine will throw if there are no tests. it('should pass', () => {}); diff --git a/packages/zone.js/test/zone-spec/task-tracking.spec.ts b/packages/zone.js/test/zone-spec/task-tracking.spec.ts index 8cc6111bca2af..294567976cedf 100644 --- a/packages/zone.js/test/zone-spec/task-tracking.spec.ts +++ b/packages/zone.js/test/zone-spec/task-tracking.spec.ts @@ -11,9 +11,9 @@ import {supportPatchXHROnProperty} from '../test-util'; declare const global: any; -describe('TaskTrackingZone', function() { +describe('TaskTrackingZone', function () { let _TaskTrackingZoneSpec: typeof TaskTrackingZoneSpec = (Zone as any)['TaskTrackingZoneSpec']; - let taskTrackingZoneSpec: TaskTrackingZoneSpec|null = null; + let taskTrackingZoneSpec: TaskTrackingZoneSpec | null = null; let taskTrackingZone: Zone; beforeEach(() => { @@ -61,8 +61,9 @@ describe('TaskTrackingZone', function() { expect(taskTrackingZoneSpec!.macroTasks.length).toBe(1); expect(taskTrackingZoneSpec!.macroTasks[0].source).toBe('XMLHttpRequest.send'); if (supportPatchXHROnProperty()) { - expect(taskTrackingZoneSpec!.eventTasks[0].source) - .toMatch(/\.addEventListener:readystatechange/); + expect(taskTrackingZoneSpec!.eventTasks[0].source).toMatch( + /\.addEventListener:readystatechange/, + ); } }); }); diff --git a/packages/zone.js/test/zone_worker_entry_point.ts b/packages/zone.js/test/zone_worker_entry_point.ts index b490fde71912c..6388188eda9ea 100644 --- a/packages/zone.js/test/zone_worker_entry_point.ts +++ b/packages/zone.js/test/zone_worker_entry_point.ts @@ -10,21 +10,24 @@ System.config({defaultJSExtensions: true}); System.import('../lib/browser/api-util').then(() => { System.import('../lib/browser/browser-legacy').then(() => { - System.import('../lib/browser/browser').then(() => { - Zone.current.fork({name: 'webworker'}).run(() => { - const websocket = new WebSocket('ws://localhost:8001'); - websocket.addEventListener('open', () => { - websocket.onmessage = () => { - if ((self).Zone.current.name === 'webworker') { - (self).postMessage('pass'); - } else { - (self).postMessage('fail'); - } - websocket.close(); - }; - websocket.send('text'); + System.import('../lib/browser/browser').then( + () => { + Zone.current.fork({name: 'webworker'}).run(() => { + const websocket = new WebSocket('ws://localhost:8001'); + websocket.addEventListener('open', () => { + websocket.onmessage = () => { + if ((self).Zone.current.name === 'webworker') { + (self).postMessage('pass'); + } else { + (self).postMessage('fail'); + } + websocket.close(); + }; + websocket.send('text'); + }); }); - }); - }, (e: any) => (self).postMessage(`error ${e.message}`)); + }, + (e: any) => (self).postMessage(`error ${e.message}`), + ); }); });