diff --git a/lodash.src.js b/lodash.src.js index 7b7e6c9d5..d26b7fa92 100644 --- a/lodash.src.js +++ b/lodash.src.js @@ -89,7 +89,7 @@ /** Used to match property names within property paths. */ var reIsDeepProp = /\.|\[(?:[^[\]]+|(["'])(?:(?!\1)[^\n\\]|\\.)*?)\1\]/, - rePropName = /[^.[\]]+|\[(?:(\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; /** * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special). @@ -102,6 +102,9 @@ /** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */ var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; + /** Used to match backslashes in property paths. */ + var reEscapeChar = /\\(\\)?/g; + /** Used to match [ES template delimiters](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components). */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; @@ -4584,7 +4587,7 @@ } var result = []; baseToString(value).replace(rePropName, function(match, number, quote, string) { - result.push(quote ? string : (number || match)); + result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); }); return result; } diff --git a/test/test.js b/test/test.js index 31c054dd9..2bce9513a 100644 --- a/test/test.js +++ b/test/test.js @@ -13139,6 +13139,14 @@ }); }); + test('`_.' + methodName + '` should handle complex paths', 2, function() { + var object = { 'a': { '-1.23': { '["b"]': { 'c': { "['d']": { 'e': 5 } } } } } }; + + _.each(['a[-1.23]["[\\"b\\"]"].c[\'[\\\'d\\\']\'].e', ['a', '-1.23', '["b"]', 'c', "['d']", 'e']], function(path) { + strictEqual(func(object, path), 5); + }); + }); + test('`_.' + methodName + '` should return `undefined` when `object` is nullish', 4, function() { _.each(['constructor', ['constructor']], function(path) { strictEqual(func(null, path), undefined); @@ -13595,6 +13603,16 @@ }); }); + test('should handle complex paths', 2, function() { + var object = { 'a': { '1.23': { '["b"]': { 'c': { "['d']": { 'e': 5 } } } } } }; + + _.each(['a[-1.23]["[\\"b\\"]"].c[\'[\\\'d\\\']\'].e', ['a', '-1.23', '["b"]', 'c', "['d']", 'e']], function(path) { + _.set(object, path, 6); + strictEqual(object.a[-1.23]['["b"]'].c["['d']"].e, 6); + object.a[-1.23]['["b"]'].c["['d']"].e = 5; + }); + }); + test('should create parts of `path` that are missing', 6, function() { var object = {};