From ba181dda9d52fba923552d403796d843ccf61b53 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Wed, 23 Dec 2015 09:48:34 -0600 Subject: [PATCH 1/3] fix(utils.extend): removes merge and makes extend behave --- src/expose.js | 2 +- src/manager.js | 5 +++-- src/recognizer.js | 5 +++-- src/utils.js | 22 +++---------------- ...pagation.js => test_propagation_bubble.js} | 0 tests/unit/test_utils.js | 17 -------------- 6 files changed, 10 insertions(+), 41 deletions(-) rename tests/unit/{test_propagation.js => test_propagation_bubble.js} (100%) diff --git a/src/expose.js b/src/expose.js index ebba4ec4b..e8588bf54 100644 --- a/src/expose.js +++ b/src/expose.js @@ -43,7 +43,7 @@ extend(Hammer, { on: addEventListeners, off: removeEventListeners, each: each, - merge: merge, + merge: extend, extend: extend, inherit: inherit, bindFn: bindFn, diff --git a/src/manager.js b/src/manager.js index 522c3682f..dfc07444d 100644 --- a/src/manager.js +++ b/src/manager.js @@ -8,8 +8,9 @@ var FORCED_STOP = 2; * @constructor */ function Manager(element, options) { - var newOptions = options ? extend({}, options) : {}; - this.options = merge(newOptions, Hammer.defaults); + var defaultOptions = extend({}, Hammer.defaults); + var newOptions = extend({}, options || {}); + this.options = extend(defaultOptions, newOptions); this.options.inputTarget = this.options.inputTarget || element; diff --git a/src/recognizer.js b/src/recognizer.js index 7c159c91e..d24ef789c 100644 --- a/src/recognizer.js +++ b/src/recognizer.js @@ -41,12 +41,13 @@ var STATE_FAILED = 32; */ function Recognizer(options) { // make sure, options are copied over to a new object to prevent leaking it outside - options = extend({}, options || {}); + var defaultOptions = extend({}, this.defaults); + var newOptions = extend({}, options || {}); + this.options = extend(defaultOptions, newOptions); this.id = uniqueId(); this.manager = null; - this.options = merge(options, this.defaults); // default is enable true this.options.enable = ifUndefined(this.options.enable, true); diff --git a/src/utils.js b/src/utils.js index 8697d0b9f..8a84d4091 100644 --- a/src/utils.js +++ b/src/utils.js @@ -68,32 +68,16 @@ function each(obj, iterator, context) { * means that properties in dest will be overwritten by the ones in src. * @param {Object} dest * @param {Object} src - * @param {Boolean} [merge] * @returns {Object} dest */ -function extend(dest, src, merge) { +function extend(dest, src) { var keys = Object.keys(src); - var i = 0; - while (i < keys.length) { - if (!merge || (merge && dest[keys[i]] === undefined)) { - dest[keys[i]] = src[keys[i]]; - } - i++; + for (var i = 0; i < keys.length; i++) { + dest[keys[i]] = src[keys[i]]; } return dest; } -/** - * merge the values from src in the dest. - * means that properties that exist in dest will not be overwritten by src - * @param {Object} dest - * @param {Object} src - * @returns {Object} dest - */ -function merge(dest, src) { - return extend(dest, src, true); -} - /** * simple class inheritance * @param {Function} child diff --git a/tests/unit/test_propagation.js b/tests/unit/test_propagation_bubble.js similarity index 100% rename from tests/unit/test_propagation.js rename to tests/unit/test_propagation_bubble.js diff --git a/tests/unit/test_utils.js b/tests/unit/test_utils.js index 21be58c0e..fe37e0ed1 100644 --- a/tests/unit/test_utils.js +++ b/tests/unit/test_utils.js @@ -147,23 +147,6 @@ test('extend', function() { deepEqual(dest, {foo: true}, 'Clone reference'); }); -test('merge', function() { - expect(2); - deepEqual( - $H.merge( - {a: 1, b: 3}, - {b: 2, c: 3} - ), - {a: 1, b: 3, c: 3}, - 'Simple extend' - ); - - var src = { foo: true }; - var dest = $H.merge({ foo: true }, src); - src.foo = false; - deepEqual(dest, {foo: true}, 'Clone reference'); -}); - test('test add/removeEventListener', function() { function handleEvent() { ok(true, 'triggered event'); From 11679a642309aaa610ca1decd182341450d8f402 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Wed, 23 Dec 2015 11:38:26 -0600 Subject: [PATCH 2/3] fix(extend): adds assign and deprecations so we don't break existing extend/mege api --- src/expose.js | 5 ++- src/manager.js | 6 +-- src/recognizer.js | 9 ++--- src/utils.js | 81 +++++++++++++++++++++++++++++++++++++--- tests/unit/test_utils.js | 6 +-- 5 files changed, 87 insertions(+), 20 deletions(-) diff --git a/src/expose.js b/src/expose.js index e8588bf54..1fe14db25 100644 --- a/src/expose.js +++ b/src/expose.js @@ -1,4 +1,4 @@ -extend(Hammer, { +assign(Hammer, { INPUT_START: INPUT_START, INPUT_MOVE: INPUT_MOVE, INPUT_END: INPUT_END, @@ -43,8 +43,9 @@ extend(Hammer, { on: addEventListeners, off: removeEventListeners, each: each, - merge: extend, + merge: merge, extend: extend, + assign: assign, inherit: inherit, bindFn: bindFn, prefixed: prefixed diff --git a/src/manager.js b/src/manager.js index dfc07444d..175b8947b 100644 --- a/src/manager.js +++ b/src/manager.js @@ -8,9 +8,7 @@ var FORCED_STOP = 2; * @constructor */ function Manager(element, options) { - var defaultOptions = extend({}, Hammer.defaults); - var newOptions = extend({}, options || {}); - this.options = extend(defaultOptions, newOptions); + this.options = assign({}, Hammer.defaults, options || {}); this.options.inputTarget = this.options.inputTarget || element; @@ -38,7 +36,7 @@ Manager.prototype = { * @returns {Manager} */ set: function(options) { - extend(this.options, options); + assign(this.options, options); // Options that need a little more setup if (options.touchAction) { diff --git a/src/recognizer.js b/src/recognizer.js index d24ef789c..b0dd9fa04 100644 --- a/src/recognizer.js +++ b/src/recognizer.js @@ -40,10 +40,7 @@ var STATE_FAILED = 32; * @param {Object} options */ function Recognizer(options) { - // make sure, options are copied over to a new object to prevent leaking it outside - var defaultOptions = extend({}, this.defaults); - var newOptions = extend({}, options || {}); - this.options = extend(defaultOptions, newOptions); + this.options = assign({}, this.defaults, options || {}); this.id = uniqueId(); @@ -71,7 +68,7 @@ Recognizer.prototype = { * @return {Recognizer} */ set: function(options) { - extend(this.options, options); + assign(this.options, options); // also update the touchAction, in case something changed about the directions/enabled state this.manager && this.manager.touchAction.update(); @@ -232,7 +229,7 @@ Recognizer.prototype = { recognize: function(inputData) { // make a new copy of the inputData // so we can change the inputData without messing up the other recognizers - var inputDataClone = extend({}, inputData); + var inputDataClone = assign({}, inputData); // is is enabled and allow recognizing? if (!boolOrFn(this.options.enable, [this, inputDataClone])) { diff --git a/src/utils.js b/src/utils.js index 8a84d4091..103f4fd88 100644 --- a/src/utils.js +++ b/src/utils.js @@ -63,20 +63,91 @@ function each(obj, iterator, context) { } } +/** + * wrap a method with a deprecation warning and stack trace + * @param {Function} method + * @param {String} name + * @param {String} message + * @returns {Function} A new function wrapping the supplied method. + */ +function deprecate(method, name, message) { + var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; + return function() { + var e = new Error('get-stack-trace'); + var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '') + .replace(/^\s+at\s+/gm, '') + .replace(/^Object.\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace'; + + var log = window.console && (window.console.warn || window.console.log); + if (log) { + log.call(window.console, deprecationMessage, stack); + } + return method.apply(this, arguments); + } +} + +/** + * extend object. + * means that properties in dest will be overwritten by the ones in src. + * @param {Object} target + * @param {...Object} objects_to_assign + * @returns {Object} target + */ +var assign; +if (typeof Object.assign !== 'function') { + assign = function assign(target) { + 'use strict'; + if (target === undefined || target === null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + + var output = Object(target); + for (var index = 1; index < arguments.length; index++) { + var source = arguments[index]; + if (source !== undefined && source !== null) { + for (var nextKey in source) { + if (source.hasOwnProperty(nextKey)) { + output[nextKey] = source[nextKey]; + } + } + } + } + return output; + } +} else { + assign = Object.assign; +} + /** * extend object. * means that properties in dest will be overwritten by the ones in src. * @param {Object} dest * @param {Object} src + * @param {Boolean=false} [merge] * @returns {Object} dest */ -function extend(dest, src) { +var extend = deprecate(function extend(dest, src, merge) { var keys = Object.keys(src); - for (var i = 0; i < keys.length; i++) { - dest[keys[i]] = src[keys[i]]; + var i = 0; + while (i < keys.length) { + if (!merge || (merge && dest[keys[i]] === undefined)) { + dest[keys[i]] = src[keys[i]]; + } + i++; } return dest; -} +}, 'extend', 'Use `assign`.'); + +/** + * merge the values from src in the dest. + * means that properties that exist in dest will not be overwritten by src + * @param {Object} dest + * @param {Object} src + * @returns {Object} dest + */ +var merge = deprecate(function merge(dest, src) { + return extend(dest, src, true); +}, 'merge', 'Use `assign`.'); /** * simple class inheritance @@ -93,7 +164,7 @@ function inherit(child, base, properties) { childP._super = baseP; if (properties) { - extend(childP, properties); + assign(childP, properties); } } diff --git a/tests/unit/test_utils.js b/tests/unit/test_utils.js index fe37e0ed1..f9d5f80b3 100644 --- a/tests/unit/test_utils.js +++ b/tests/unit/test_utils.js @@ -130,10 +130,10 @@ test('each', function() { ok(loop == 3, 'array loop without Array.forEach'); }); -test('extend', function() { +test('assign', function() { expect(2); deepEqual( - $H.extend( + $H.assign( {a: 1, b: 3}, {b: 2, c: 3} ), @@ -142,7 +142,7 @@ test('extend', function() { ); var src = { foo: true }; - var dest = $H.extend({}, src); + var dest = $H.assign({}, src); src.foo = false; deepEqual(dest, {foo: true}, 'Clone reference'); }); From 949d57c6224327ea81fd02d7f34979ef6706431e Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Wed, 23 Dec 2015 11:42:14 -0600 Subject: [PATCH 3/3] fix(assing): cleans up jshint errors --- src/utils.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/utils.js b/src/utils.js index 103f4fd88..94d57cf40 100644 --- a/src/utils.js +++ b/src/utils.js @@ -83,7 +83,7 @@ function deprecate(method, name, message) { log.call(window.console, deprecationMessage, stack); } return method.apply(this, arguments); - } + }; } /** @@ -96,7 +96,6 @@ function deprecate(method, name, message) { var assign; if (typeof Object.assign !== 'function') { assign = function assign(target) { - 'use strict'; if (target === undefined || target === null) { throw new TypeError('Cannot convert undefined or null to object'); } @@ -113,7 +112,7 @@ if (typeof Object.assign !== 'function') { } } return output; - } + }; } else { assign = Object.assign; }