From 12438fa0d7804a0bc1f7e2a81c00781c72aa3a86 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sat, 26 Mar 2016 13:43:39 -0700 Subject: [PATCH] Ensure `_.isEqual` compares promises by reference. --- lodash.js | 18 ++++++++++++------ test/test.js | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/lodash.js b/lodash.js index 3797460cc..aa248e222 100644 --- a/lodash.js +++ b/lodash.js @@ -77,6 +77,7 @@ mapTag = '[object Map]', numberTag = '[object Number]', objectTag = '[object Object]', + promiseTag = '[object Promise]', regexpTag = '[object RegExp]', setTag = '[object Set]', stringTag = '[object String]', @@ -233,9 +234,9 @@ var contextProps = [ 'Array', 'Buffer', 'Date', 'Error', 'Float32Array', 'Float64Array', 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', - 'Reflect', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', - 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', '_', - 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' + 'Promise', 'Reflect', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', + 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' ]; /** Used to make template sourceURLs easier to identify. */ @@ -1424,6 +1425,7 @@ /* Built-in method references that are verified to be native. */ var Map = getNative(context, 'Map'), + Promise = getNative(context, 'Promise'), Set = getNative(context, 'Set'), WeakMap = getNative(context, 'WeakMap'), nativeCreate = getNative(Object, 'create'); @@ -1439,6 +1441,7 @@ /** Used to detect maps, sets, and weakmaps. */ var mapCtorString = Map ? funcToString.call(Map) : '', + promiseCtorString = Promise ? funcToString.call(Promise) : '', setCtorString = Set ? funcToString.call(Set) : '', weakMapCtorString = WeakMap ? funcToString.call(WeakMap) : ''; @@ -5219,10 +5222,12 @@ return objectToString.call(value); } - // Fallback for IE 11 providing `toStringTag` values for maps, sets, and weakmaps. + // Fallback for IE 11 or maps, sets, and weakmaps and Node.js 5 for promises. if ((Map && getTag(new Map) != mapTag) || - (Set && getTag(new Set) != setTag) || - (WeakMap && getTag(new WeakMap) != weakMapTag)) { + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag) + ) { getTag = function(value) { var result = objectToString.call(value), Ctor = result == objectTag ? value.constructor : null, @@ -5231,6 +5236,7 @@ if (ctorString) { switch (ctorString) { case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; case setCtorString: return setTag; case weakMapCtorString: return weakMapTag; } diff --git a/test/test.js b/test/test.js index c596fe2a1..7c8fd7170 100644 --- a/test/test.js +++ b/test/test.js @@ -62,6 +62,7 @@ var ArrayBuffer = root.ArrayBuffer, Buffer = root.Buffer, + Promise = root.Promise, Map = root.Map, Set = root.Set, Symbol = root.Symbol, @@ -71,6 +72,7 @@ var arrayBuffer = ArrayBuffer ? new ArrayBuffer(2) : undefined, map = Map ? new Map : undefined, + promise = Promise ? Promise.resolve() : undefined, set = Set ? new Set : undefined, symbol = Symbol ? Symbol('a') : undefined, weakMap = WeakMap ? new WeakMap : undefined, @@ -588,6 +590,7 @@ " 'null': null,", " 'number': Object(0),", " 'object': { 'a': 1 },", + " 'promise': root.Promise ? Promise.resolve() : undefined,", " 'regexp': /x/,", " 'set': root.Set ? new root.Set : undefined,", " 'string': Object('a'),", @@ -636,6 +639,7 @@ " 'null': null,", " 'number': Object(0),", " 'object': { 'a': 1 },", + " 'promise': root.Promise ? Promise.resolve() : undefined,", " 'regexp': /x/,", " 'set': root.Set ? new root.Set : undefined,", " 'string': Object('a'),", @@ -9296,6 +9300,21 @@ } }); + QUnit.test('should compare promises by reference', function(assert) { + assert.expect(2); + + if (promise) { + var promise1 = Promise.resolve(1), + promise2 = Promise.resolve(1); + + assert.strictEqual(_.isEqual(promise1, promise2), false); + assert.strictEqual(_.isEqual(promise1, promise1), true); + } + else { + skipAssert(assert, 2); + } + }); + QUnit.test('should compare regexes', function(assert) { assert.expect(5);