Skip to content

Commit

Permalink
fix(stringToParts): fall back to legacy treatment for square brackets…
Browse files Browse the repository at this point in the history
… if square brackets contents aren't a number

Re: Automattic/mongoose#9640
  • Loading branch information
vkarpov15 committed Dec 30, 2020
1 parent 095573c commit ffed519
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 15 deletions.
41 changes: 29 additions & 12 deletions lib/stringToParts.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,45 @@ module.exports = function stringToParts(str) {
const result = [];

let curPropertyName = '';
let inSquareBrackets = false;
let state = 'DEFAULT';
for (let i = 0; i < str.length; ++i) {
if (inSquareBrackets && !/\d/.test(str[i]) && str[i] !== ']') {
throw new Error('Can only use numbers in square bracket path notation, got ' +
'character "' + str[i] + '" in path "' + str + '"');
// Fall back to treating as property name rather than bracket notation if
// square brackets contains something other than a number.
if (state === 'IN_SQUARE_BRACKETS' && !/\d/.test(str[i]) && str[i] !== ']') {
state = 'DEFAULT';
curPropertyName = result[result.length - 1] + '[' + curPropertyName;
result.splice(result.length - 1, 1);
}

if (str[i] === '.' || str[i] === '[' || str[i] === ']') {
if (str[i] === '[') {
inSquareBrackets = true;
} else if (str[i] === ']') {
inSquareBrackets = false;
if (str[i] === '[') {
if (state !== 'IMMEDIATELY_AFTER_SQUARE_BRACKETS') {
result.push(curPropertyName);
curPropertyName = '';
}
state = 'IN_SQUARE_BRACKETS';
} else if (str[i] === ']') {
if (state === 'IN_SQUARE_BRACKETS') {
state = 'IMMEDIATELY_AFTER_SQUARE_BRACKETS';
result.push(curPropertyName);
curPropertyName = '';
} else {
state = 'DEFAULT';
curPropertyName += str[i];
}
if (curPropertyName.length > 0) {
} else if (str[i] === '.') {
if (state !== 'IMMEDIATELY_AFTER_SQUARE_BRACKETS') {
result.push(curPropertyName);
curPropertyName = '';
}
curPropertyName = '';
state = 'DEFAULT';
} else {
curPropertyName += str[i];
}
}
result.push(curPropertyName);

if (state !== 'IMMEDIATELY_AFTER_SQUARE_BRACKETS') {
result.push(curPropertyName);
}

return result;
};
8 changes: 5 additions & 3 deletions test/stringToParts.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ describe('stringToParts', function() {

it('handles dot notation', function() {
assert.deepEqual(stringToParts('a.b.c'), ['a', 'b', 'c']);
assert.deepEqual(stringToParts('a..b.d'), ['a', 'b', 'd']);
assert.deepEqual(stringToParts('a..b.d'), ['a', '', 'b', 'd']);
});

it('throws for invalid numbers in square brackets', function() {
assert.throws(() => stringToParts('foo[1mystring]'), /1mystring/);
it('ignores invalid numbers in square brackets', function() {
assert.deepEqual(stringToParts('foo[1mystring]'), ['foo[1mystring]']);
assert.deepEqual(stringToParts('foo[1mystring].bar[1]'), ['foo[1mystring]', 'bar', '1']);
assert.deepEqual(stringToParts('foo[1mystring][2]'), ['foo[1mystring]', '2']);
});

it('handles empty string', function() {
Expand Down

0 comments on commit ffed519

Please sign in to comment.