From c253e8d7b83e97d97a3b4103bfaf0308b2e3ceb9 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Mon, 25 Jul 2016 07:16:45 -0700 Subject: [PATCH] Ensure paths with consecutive empty brackets or dots are parsed correctly. --- lodash.js | 10 ++++++++-- test/test.js | 28 ++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/lodash.js b/lodash.js index 8dd467299..fb3c7cfee 100644 --- a/lodash.js +++ b/lodash.js @@ -129,7 +129,8 @@ /** Used to match property names within property paths. */ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, - rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(\.|\[\])(?:\4|$))/g; + reLeadingDot = /^\./, + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; /** * Used to match `RegExp` @@ -6215,8 +6216,13 @@ * @returns {Array} Returns the property path array. */ var stringToPath = memoize(function(string) { + string = toString(string); + var result = []; - toString(string).replace(rePropName, function(match, number, quote, string) { + if (reLeadingDot.test(string)) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, string) { result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); }); return result; diff --git a/test/test.js b/test/test.js index 515795472..487742a7e 100644 --- a/test/test.js +++ b/test/test.js @@ -23531,16 +23531,32 @@ assert.deepEqual(actual, ['a', '-1.23', '["b"]', 'c', "['d']", '\ne\n', 'f', 'g']); }); - QUnit.test('should not ignore consecutive brackets and dots', function(assert) { - assert.expect(4); + QUnit.test('should handle consecutive empty brackets and dots', function(assert) { + assert.expect(12); - var expected = ['a', '']; - assert.deepEqual(_.toPath('a.'), expected); - assert.deepEqual(_.toPath('a[]'), expected); + var expected = ['', 'a']; + assert.deepEqual(_.toPath('.a'), expected); + assert.deepEqual(_.toPath('[].a'), expected); + + expected = ['', '', 'a']; + assert.deepEqual(_.toPath('..a'), expected); + assert.deepEqual(_.toPath('[][].a'), expected); expected = ['a', '', 'b']; assert.deepEqual(_.toPath('a..b'), expected); - assert.deepEqual(_.toPath('a[][]b'), expected); + assert.deepEqual(_.toPath('a[].b'), expected); + + expected = ['a', '', '', 'b']; + assert.deepEqual(_.toPath('a...b'), expected); + assert.deepEqual(_.toPath('a[][].b'), expected); + + expected = ['a', '']; + assert.deepEqual(_.toPath('a.'), expected); + assert.deepEqual(_.toPath('a[]'), expected); + + expected = ['a', '', '']; + assert.deepEqual(_.toPath('a..'), expected); + assert.deepEqual(_.toPath('a[][]'), expected); }); }());