diff --git a/package.json b/package.json index ff99b43..287cd3f 100644 --- a/package.json +++ b/package.json @@ -41,31 +41,31 @@ "resource-loader": "^1.6.4" }, "devDependencies": { - "browserify": "^11.1.0", + "browserify": "^13.0.1", "browserify-versionify": "^1.0.6", - "chai": "^3.2.0", - "del": "^2.0.2", - "gulp": "^3.9.0", + "chai": "^3.5.0", + "del": "^2.2.0", + "gulp": "^3.9.1", "gulp-cached": "^1.1.0", "gulp-concat": "^2.6.0", - "gulp-debug": "^2.1.0", - "gulp-header": "^1.7.1", - "gulp-jshint": "^2.0.0", + "gulp-debug": "^2.1.2", + "gulp-header": "^1.8.2", + "gulp-jshint": "^2.0.1", "gulp-mirror": "^1.0.0", - "gulp-plumber": "^1.0.1", + "gulp-plumber": "^1.1.0", "gulp-rename": "^1.2.2", - "gulp-sourcemaps": "^1.5.2", - "gulp-uglify": "^1.5.1", - "gulp-util": "^3.0.6", + "gulp-sourcemaps": "^1.6.0", + "gulp-uglify": "^1.5.3", + "gulp-util": "^3.0.7", "jaguarjs-jsdoc": "^1.0.0", "jsdoc": "^3.4.0", - "jshint": "^2.9.1", + "jshint": "^2.9.2", "jshint-summary": "^0.4.0", "minimist": "^1.2.0", - "mocha": "^2.4.5", + "mocha": "^2.5.3", "require-dir": "^0.3.0", - "run-sequence": "^1.1.2", - "testem": "^0.9.4", + "run-sequence": "^1.2.1", + "testem": "^1.8.1", "vinyl-buffer": "^1.0.0", "vinyl-source-stream": "^1.1.0", "watchify": "^3.7.0" diff --git a/package.json b/package.json index ff99b43..287cd3f 100644 --- a/package.json +++ b/package.json @@ -41,31 +41,31 @@ "resource-loader": "^1.6.4" }, "devDependencies": { - "browserify": "^11.1.0", + "browserify": "^13.0.1", "browserify-versionify": "^1.0.6", - "chai": "^3.2.0", - "del": "^2.0.2", - "gulp": "^3.9.0", + "chai": "^3.5.0", + "del": "^2.2.0", + "gulp": "^3.9.1", "gulp-cached": "^1.1.0", "gulp-concat": "^2.6.0", - "gulp-debug": "^2.1.0", - "gulp-header": "^1.7.1", - "gulp-jshint": "^2.0.0", + "gulp-debug": "^2.1.2", + "gulp-header": "^1.8.2", + "gulp-jshint": "^2.0.1", "gulp-mirror": "^1.0.0", - "gulp-plumber": "^1.0.1", + "gulp-plumber": "^1.1.0", "gulp-rename": "^1.2.2", - "gulp-sourcemaps": "^1.5.2", - "gulp-uglify": "^1.5.1", - "gulp-util": "^3.0.6", + "gulp-sourcemaps": "^1.6.0", + "gulp-uglify": "^1.5.3", + "gulp-util": "^3.0.7", "jaguarjs-jsdoc": "^1.0.0", "jsdoc": "^3.4.0", - "jshint": "^2.9.1", + "jshint": "^2.9.2", "jshint-summary": "^0.4.0", "minimist": "^1.2.0", - "mocha": "^2.4.5", + "mocha": "^2.5.3", "require-dir": "^0.3.0", - "run-sequence": "^1.1.2", - "testem": "^0.9.4", + "run-sequence": "^1.2.1", + "testem": "^1.8.1", "vinyl-buffer": "^1.0.0", "vinyl-source-stream": "^1.1.0", "watchify": "^3.7.0" diff --git a/src/core/ticker/Ticker.js b/src/core/ticker/Ticker.js index 0285734..7a80907 100644 --- a/src/core/ticker/Ticker.js +++ b/src/core/ticker/Ticker.js @@ -331,19 +331,42 @@ // Allow calling update directly with default currentTime. currentTime = currentTime || performance.now(); - // Save uncapped elapsedMS for measurement - Math.max(0, elapsedMS = this.elapsedMS = currentTime - this.lastTime); - // cap the milliseconds elapsed used for deltaTime - if (elapsedMS > this._maxElapsedMS) + // If the difference in time is zero or negative, we ignore most of the work done here. + // If there is no valid difference, then should be no reason to let anyone know about it. + // A zero delta, is exactly that, nothing should update. + // + // The difference in time can be negative, and no this does not mean time traveling. + // This can be the result of a race condition between when an animation frame is requested + // on the current JavaScript engine event loop, and when the ticker's start method is invoked + // (which invokes the internal _requestIfNeeded method). If a frame is requested before + // _requestIfNeeded is invoked, then the callback for the animation frame the ticker requests, + // can receive a time argument that can be less than the lastTime value that was set within + // _requestIfNeeded. This difference is in microseconds, but this is enough to cause problems. + // + // This check covers this browser engine timing issue, as well as if consumers pass an invalid + // currentTime value. This may happen if consumers opt-out of the autoStart, and update themselves. + + if (currentTime > this.lastTime) { - elapsedMS = this._maxElapsedMS; + // Save uncapped elapsedMS for measurement + elapsedMS = this.elapsedMS = currentTime - this.lastTime; + + // cap the milliseconds elapsed used for deltaTime + if (elapsedMS > this._maxElapsedMS) + { + elapsedMS = this._maxElapsedMS; + } + + this.deltaTime = elapsedMS * CONST.TARGET_FPMS * this.speed; + + // Invoke listeners added to internal emitter + this._emitter.emit(TICK, this.deltaTime); } - - this.deltaTime = elapsedMS * CONST.TARGET_FPMS * this.speed; - - // Invoke listeners added to internal emitter - this._emitter.emit(TICK, this.deltaTime); + else + { + this.deltaTime = this.elapsedMS = 0; + } this.lastTime = currentTime; }; diff --git a/package.json b/package.json index ff99b43..287cd3f 100644 --- a/package.json +++ b/package.json @@ -41,31 +41,31 @@ "resource-loader": "^1.6.4" }, "devDependencies": { - "browserify": "^11.1.0", + "browserify": "^13.0.1", "browserify-versionify": "^1.0.6", - "chai": "^3.2.0", - "del": "^2.0.2", - "gulp": "^3.9.0", + "chai": "^3.5.0", + "del": "^2.2.0", + "gulp": "^3.9.1", "gulp-cached": "^1.1.0", "gulp-concat": "^2.6.0", - "gulp-debug": "^2.1.0", - "gulp-header": "^1.7.1", - "gulp-jshint": "^2.0.0", + "gulp-debug": "^2.1.2", + "gulp-header": "^1.8.2", + "gulp-jshint": "^2.0.1", "gulp-mirror": "^1.0.0", - "gulp-plumber": "^1.0.1", + "gulp-plumber": "^1.1.0", "gulp-rename": "^1.2.2", - "gulp-sourcemaps": "^1.5.2", - "gulp-uglify": "^1.5.1", - "gulp-util": "^3.0.6", + "gulp-sourcemaps": "^1.6.0", + "gulp-uglify": "^1.5.3", + "gulp-util": "^3.0.7", "jaguarjs-jsdoc": "^1.0.0", "jsdoc": "^3.4.0", - "jshint": "^2.9.1", + "jshint": "^2.9.2", "jshint-summary": "^0.4.0", "minimist": "^1.2.0", - "mocha": "^2.4.5", + "mocha": "^2.5.3", "require-dir": "^0.3.0", - "run-sequence": "^1.1.2", - "testem": "^0.9.4", + "run-sequence": "^1.2.1", + "testem": "^1.8.1", "vinyl-buffer": "^1.0.0", "vinyl-source-stream": "^1.1.0", "watchify": "^3.7.0" diff --git a/src/core/ticker/Ticker.js b/src/core/ticker/Ticker.js index 0285734..7a80907 100644 --- a/src/core/ticker/Ticker.js +++ b/src/core/ticker/Ticker.js @@ -331,19 +331,42 @@ // Allow calling update directly with default currentTime. currentTime = currentTime || performance.now(); - // Save uncapped elapsedMS for measurement - Math.max(0, elapsedMS = this.elapsedMS = currentTime - this.lastTime); - // cap the milliseconds elapsed used for deltaTime - if (elapsedMS > this._maxElapsedMS) + // If the difference in time is zero or negative, we ignore most of the work done here. + // If there is no valid difference, then should be no reason to let anyone know about it. + // A zero delta, is exactly that, nothing should update. + // + // The difference in time can be negative, and no this does not mean time traveling. + // This can be the result of a race condition between when an animation frame is requested + // on the current JavaScript engine event loop, and when the ticker's start method is invoked + // (which invokes the internal _requestIfNeeded method). If a frame is requested before + // _requestIfNeeded is invoked, then the callback for the animation frame the ticker requests, + // can receive a time argument that can be less than the lastTime value that was set within + // _requestIfNeeded. This difference is in microseconds, but this is enough to cause problems. + // + // This check covers this browser engine timing issue, as well as if consumers pass an invalid + // currentTime value. This may happen if consumers opt-out of the autoStart, and update themselves. + + if (currentTime > this.lastTime) { - elapsedMS = this._maxElapsedMS; + // Save uncapped elapsedMS for measurement + elapsedMS = this.elapsedMS = currentTime - this.lastTime; + + // cap the milliseconds elapsed used for deltaTime + if (elapsedMS > this._maxElapsedMS) + { + elapsedMS = this._maxElapsedMS; + } + + this.deltaTime = elapsedMS * CONST.TARGET_FPMS * this.speed; + + // Invoke listeners added to internal emitter + this._emitter.emit(TICK, this.deltaTime); } - - this.deltaTime = elapsedMS * CONST.TARGET_FPMS * this.speed; - - // Invoke listeners added to internal emitter - this._emitter.emit(TICK, this.deltaTime); + else + { + this.deltaTime = this.elapsedMS = 0; + } this.lastTime = currentTime; }; diff --git a/test/unit/core/display/Container.test.js b/test/unit/core/display/Container.test.js index 3534c05..026848e 100644 --- a/test/unit/core/display/Container.test.js +++ b/test/unit/core/display/Container.test.js @@ -26,16 +26,16 @@ child.on('removed', function(from) { triggeredRemoved = true; expect(container.children.length).to.be.equals(0); - expect(child.parent).to.be.null(); + expect(child.parent).to.be.null; expect(container).to.be.equals(from); }); container.addChild(child); - expect(triggeredAdded).to.be.true(); - expect(triggeredRemoved).to.be.false(); + expect(triggeredAdded).to.be.true; + expect(triggeredRemoved).to.be.false; container.removeChild(child); - expect(triggeredRemoved).to.be.true(); + expect(triggeredRemoved).to.be.true; }); });