From d38ea15aa672c125442074b936bf9c0d2d77e541 Mon Sep 17 00:00:00 2001 From: Xavier Balloy Date: Mon, 29 Dec 2014 17:32:19 +0100 Subject: [PATCH 1/5] chore(Common): update the Common.now On IE9, perf.now doesn't exists and it throw an error. I updated the function to mach with the gist --- src/core/Common.js | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/core/Common.js b/src/core/Common.js index fbd4c270..f0846ce6 100644 --- a/src/core/Common.js +++ b/src/core/Common.js @@ -201,17 +201,27 @@ var Common = {}; * @return {number} the current timestamp (high-res if avaliable) */ Common.now = function() { - // http://stackoverflow.com/questions/221294/how-do-you-get-a-timestamp-in-javascript // https://gist.github.com/davidwaterston/2982531 - - var perf = window.performance; - if (perf) { - perf.now = perf.now || perf.webkitNow || perf.msNow || perf.oNow || perf.mozNow; - return +(perf.now()); - } - - return +(new Date()); + // Returns the number of milliseconds elapsed since either the browser navigationStart event or + // the UNIX epoch, depending on availability. + // Where the browser supports 'performance' we use that as it is more accurate (microsoeconds + // will be returned in the fractional part) and more reliable as it does not rely on the system time. + // Where 'performance' is not available, we will fall back to Date().getTime(). + // jsFiddle: http://jsfiddle.net/davidwaterston/xCXvJ + + var performance = window.performance || {}; + + performance.now = (function() { + return performance.now || + performance.webkitNow || + performance.msNow || + performance.oNow || + performance.mozNow || + function() { return new Date().getTime(); }; + })(); + + return performance.now(); }; From 5466851356f187bf506c280406c03b3a9b5dfbef Mon Sep 17 00:00:00 2001 From: Xavier Balloy Date: Wed, 21 Jan 2015 19:33:39 +0100 Subject: [PATCH 2/5] chore(Common): use Date.now as first fallback in Common.now If performance is not available we use Date.now If Date.now is not available (IE < 9) we use Date.getTime See commentaries: https://github.com/liabru/matter-js/pull/55 --- src/core/Common.js | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/core/Common.js b/src/core/Common.js index f0846ce6..e5108276 100644 --- a/src/core/Common.js +++ b/src/core/Common.js @@ -51,7 +51,7 @@ var Common = {}; } } } - + return obj; }; @@ -91,7 +91,7 @@ var Common = {}; */ Common.values = function(obj) { var values = []; - + if (Object.keys) { var keys = Object.keys(obj); for (var i = 0; i < keys.length; i++) { @@ -99,7 +99,7 @@ var Common = {}; } return values; } - + // avoid hasOwnProperty for performance for (var key in obj) values.push(obj[key]); @@ -113,15 +113,15 @@ var Common = {}; * @param {number} percent * @return {string} A hex colour string made by lightening or darkening color by percent */ - Common.shadeColor = function(color, percent) { + Common.shadeColor = function(color, percent) { // http://stackoverflow.com/questions/5560248/programmatically-lighten-or-darken-a-hex-color - var colorInteger = parseInt(color.slice(1),16), - amount = Math.round(2.55 * percent), - R = (colorInteger >> 16) + amount, - B = (colorInteger >> 8 & 0x00FF) + amount, + var colorInteger = parseInt(color.slice(1),16), + amount = Math.round(2.55 * percent), + R = (colorInteger >> 16) + amount, + B = (colorInteger >> 8 & 0x00FF) + amount, G = (colorInteger & 0x0000FF) + amount; - return "#" + (0x1000000 + (R < 255 ? R < 1 ? 0 : R :255) * 0x10000 - + (B < 255 ? B < 1 ? 0 : B : 255) * 0x100 + return "#" + (0x1000000 + (R < 255 ? R < 1 ? 0 : R :255) * 0x10000 + + (B < 255 ? B < 1 ? 0 : B : 255) * 0x100 + (G < 255 ? G < 1 ? 0 : G : 255)).toString(16).slice(1); }; @@ -168,7 +168,7 @@ var Common = {}; (typeof obj.ownerDocument ==="object"); } }; - + /** * Description * @method clamp @@ -184,7 +184,7 @@ var Common = {}; return max; return value; }; - + /** * Description * @method sign @@ -194,7 +194,7 @@ var Common = {}; Common.sign = function(value) { return value < 0 ? -1 : 1; }; - + /** * Description * @method now @@ -218,13 +218,15 @@ var Common = {}; performance.msNow || performance.oNow || performance.mozNow || - function() { return new Date().getTime(); }; + function() { + return Date.now && Date.now() || new Date().getTime(); + }; })(); return performance.now(); }; - + /** * Description * @method random @@ -315,4 +317,4 @@ var Common = {}; return Common._seed / 233280; }; -})(); \ No newline at end of file +})(); From 6eea62c22f2fc8de4266545bb2fe4c346ce0682d Mon Sep 17 00:00:00 2001 From: Xavier Balloy Date: Wed, 21 Jan 2015 20:42:11 +0100 Subject: [PATCH 3/5] chore(Tests): add Jasmine as test framework --- Gruntfile.js | 13 ++++++++++--- package.json | 5 +++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 9ef441db..0ca6830c 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -95,6 +95,12 @@ module.exports = function(grunt) { linkNatives: true } } + }, + jasmine : { + src : ['src/**/*.js', '!src/module/*'], + options : { + specs : 'spec/**/*.js' + } } }); @@ -105,9 +111,10 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-yuidoc'); + grunt.loadNpmTasks('grunt-contrib-jasmine'); grunt.registerTask('default', ['test', 'build']); - grunt.registerTask('test', ['jshint']); + grunt.registerTask('test', ['jshint', 'jasmine']); grunt.registerTask('dev', ['build:dev', 'connect:watch', 'watch']); grunt.registerTask('build', function(mode) { @@ -145,11 +152,11 @@ module.exports = function(grunt) { if (isEdge) grunt.config.set('docVersion', 'edge version (master)'); - + grunt.task.run('yuidoc'); }); grunt.registerTask('set_config', 'Set a config property.', function(name, val) { grunt.config.set(name, val); }); -}; \ No newline at end of file +}; diff --git a/package.json b/package.json index 6c7addb7..5dad2910 100644 --- a/package.json +++ b/package.json @@ -21,11 +21,12 @@ ], "devDependencies": { "grunt": "~0.4.2", - "grunt-contrib-jshint": "~0.6.3", - "grunt-contrib-uglify": "~0.2.7", "grunt-contrib-concat": "~0.3.0", "grunt-contrib-connect": "~0.6.0", "grunt-contrib-copy": "~0.5.0", + "grunt-contrib-jasmine": "^0.8.2", + "grunt-contrib-jshint": "~0.6.3", + "grunt-contrib-uglify": "~0.2.7", "grunt-contrib-watch": "~0.5.3", "grunt-contrib-yuidoc": "~0.5.1" }, From 277187381b370787da8ab8ff4df7bad4ebc0470c Mon Sep 17 00:00:00 2001 From: Xavier Balloy Date: Wed, 21 Jan 2015 20:43:06 +0100 Subject: [PATCH 4/5] tests(Common.now): add tests to Common.now --- spec/core/CommonSpec.js | 130 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 spec/core/CommonSpec.js diff --git a/spec/core/CommonSpec.js b/spec/core/CommonSpec.js new file mode 100644 index 00000000..9e23ebcf --- /dev/null +++ b/spec/core/CommonSpec.js @@ -0,0 +1,130 @@ +'use strict'; + +describe('Common', function() { + describe('now', function() { + it('should return performance.now if available', function() { + // We mock window.performance + var performanceMock = { + now: function() { + return 42; + } + }; + window.performance = performanceMock; + spyOn(performanceMock, 'now').and.callThrough();; + + var result = Common.now(); + + expect(performanceMock.now).toHaveBeenCalled(); + expect(result).toBe(42); + }); + + it('should return performance.webkitNow if available and performance.now is not available', function() { + // We mock window.performance + var performanceMock = { + webkitNow: function() { + return 42; + } + }; + window.performance = performanceMock; + spyOn(performanceMock, 'webkitNow').and.callThrough(); + + var result = Common.now(); + + expect(performanceMock.webkitNow).toHaveBeenCalled(); + expect(result).toBe(42); + }); + + it('should return performance.msNow if available and performance.now and performance.webkitNow are not available', function() { + // We mock window.performance + var performanceMock = { + msNow: function() { + return 42; + } + }; + window.performance = performanceMock; + spyOn(performanceMock, 'msNow').and.callThrough(); + + var result = Common.now(); + + expect(performanceMock.msNow).toHaveBeenCalled(); + expect(result).toBe(42); + }); + + it('should return performance.oNow if available and performance.now, performance.webkitNow and performance.msNow are not available', function() { + // We mock window.performance + var performanceMock = { + oNow: function() { + return 42; + } + }; + window.performance = performanceMock; + spyOn(performanceMock, 'oNow').and.callThrough(); + + var result = Common.now(); + + expect(performanceMock.oNow).toHaveBeenCalled(); + expect(result).toBe(42); + }); + + it('should return performance.mozNow if available and performance.now, performance.webkitNow, performance.msNow and performance.oNow are not available', function() { + // We mock window.performance + var performanceMock = { + mozNow: function() { + return 42; + } + }; + window.performance = performanceMock; + spyOn(performanceMock, 'mozNow').and.callThrough(); + + var result = Common.now(); + + expect(performanceMock.mozNow).toHaveBeenCalled(); + expect(result).toBe(42); + }); + + it('should return Date.now if available and performance is not available', function() { + // We mock window.performance + window.performance = undefined; + + // We mock window.Date + function DateMock() { + this.getTime = function() { + return 42; + }; + } + DateMock.now = function() { + return 42; + } + window.Date = DateMock; + var DateMockInstance = new DateMock(); + spyOn(DateMockInstance, 'getTime').and.callThrough(); + spyOn(DateMock, 'now').and.callThrough(); + + var result = Common.now(); + + expect(DateMock.now).toHaveBeenCalled(); + expect(DateMockInstance.getTime).not.toHaveBeenCalled(); + expect(result).toBe(42); + }); + + it('should return Date.getTime if nothing else is available', function() { + // We mock window.performance + window.performance = undefined; + + // We mock window.Date + function DateMock() { + this.getTime = function() { + return 42; + }; + } + window.Date = DateMock; + var DateMockInstance = new DateMock(); + var spy = spyOn(window, 'Date').and.callThrough(); + + var result = Common.now(); + + expect(window.Date).toHaveBeenCalled(); + expect(result).toBe(42); + }); + }); +}); From 6b7d60f641b82ba69e1cf551166cdcd6097b01f6 Mon Sep 17 00:00:00 2001 From: Xavier Balloy Date: Wed, 21 Jan 2015 21:43:27 +0100 Subject: [PATCH 5/5] refactor(Common.now): simplified the way to detect if Date.now is available --- src/core/Common.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/Common.js b/src/core/Common.js index e5108276..349e15a3 100644 --- a/src/core/Common.js +++ b/src/core/Common.js @@ -218,8 +218,9 @@ var Common = {}; performance.msNow || performance.oNow || performance.mozNow || + window.Date.now || function() { - return Date.now && Date.now() || new Date().getTime(); + return new Date().getTime(); }; })();