From d963be5eec32018790d1059a28b721265405f149 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Fri, 31 Dec 2021 11:38:01 -0800 Subject: [PATCH] Log a deprecation warning on reentrant calls to Clock#tick See #1929 --- lib/jasmine-core/jasmine.js | 25 +++++++++++++++---- spec/core/integration/EnvSpec.js | 36 ++++++++++++++++++++++++++++ src/core/DelayedFunctionScheduler.js | 26 ++++++++++++++++---- 3 files changed, 79 insertions(+), 8 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index c8374676..72130a80 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -3879,13 +3879,30 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) { var currentTime = 0; var delayedFnCount = 0; var deletedKeys = []; + var ticking = false; self.tick = function(millis, tickDate) { - millis = millis || 0; - var endTime = currentTime + millis; + if (ticking) { + j$.getEnv().deprecated('The behavior of reentrant calls to ' + + 'jasmine.clock().tick() will change in a future version. Either ' + + 'modify the affected spec to not call tick() from within a ' + + 'setTimeout or setInterval handler, or be aware that it may ' + + 'behave differently in the future. See ' + + ' ' + + 'for details.'); + } - runScheduledFunctions(endTime, tickDate); - currentTime = endTime; + ticking = true; + + try { + millis = millis || 0; + var endTime = currentTime + millis; + + runScheduledFunctions(endTime, tickDate); + currentTime = endTime; + } finally { + ticking = false; + } }; self.scheduleFunction = function( diff --git a/spec/core/integration/EnvSpec.js b/spec/core/integration/EnvSpec.js index 73a6c7b4..83002c5b 100644 --- a/spec/core/integration/EnvSpec.js +++ b/spec/core/integration/EnvSpec.js @@ -1259,6 +1259,42 @@ describe('Env integration', function() { }); }); + it('logs a deprecation warning when the mock clock is ticked reentrantly', function(done) { + var ticked = false, + env = jasmineUnderTest.getEnv(); + spyOn(env, 'deprecated'); + + env.beforeEach(function() { + env.clock.install(); + }); + + env.afterEach(function() { + env.clock.uninstall(); + }); + + env.it('ticks inside tick', function() { + setTimeout(function() { + ticked = true; + env.clock.tick(); + }, 1); + + env.clock.tick(1); + }); + + env.execute(null, function() { + expect(ticked).toBeTrue(); + expect(env.deprecated).toHaveBeenCalledWith( + 'The behavior of reentrant calls to jasmine.clock().tick() will ' + + 'change in a future version. Either modify the affected spec to ' + + 'not call tick() from within a setTimeout or setInterval handler, ' + + 'or be aware that it may behave differently in the future. See ' + + ' ' + + 'for details.' + ); + done(); + }); + }); + it('should run async specs in order, waiting for them to complete', function(done) { var mutatedVar; diff --git a/src/core/DelayedFunctionScheduler.js b/src/core/DelayedFunctionScheduler.js index eb84c48a..fe1e2665 100644 --- a/src/core/DelayedFunctionScheduler.js +++ b/src/core/DelayedFunctionScheduler.js @@ -6,13 +6,31 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) { var currentTime = 0; var delayedFnCount = 0; var deletedKeys = []; + var ticking = false; self.tick = function(millis, tickDate) { - millis = millis || 0; - var endTime = currentTime + millis; + if (ticking) { + j$.getEnv().deprecated( + 'The behavior of reentrant calls to jasmine.clock().tick() will ' + + 'change in a future version. Either modify the affected spec to ' + + 'not call tick() from within a setTimeout or setInterval handler, ' + + 'or be aware that it may behave differently in the future. See ' + + ' ' + + 'for details.' + ); + } - runScheduledFunctions(endTime, tickDate); - currentTime = endTime; + ticking = true; + + try { + millis = millis || 0; + var endTime = currentTime + millis; + + runScheduledFunctions(endTime, tickDate); + currentTime = endTime; + } finally { + ticking = false; + } }; self.scheduleFunction = function(