update
This commit is contained in:
+72
-31
@@ -36,8 +36,19 @@ var interpretNumericEntities = function (str) {
|
||||
});
|
||||
};
|
||||
|
||||
var parseArrayValue = function (val, options, currentArrayLength) {
|
||||
var parseArrayValue = function (val, options, currentArrayLength, isFlatArrayValue) {
|
||||
if (val && typeof val === 'string' && options.comma && val.indexOf(',') > -1) {
|
||||
if (isFlatArrayValue && options.throwOnLimitExceeded) {
|
||||
var commaCount = 0;
|
||||
var commaIndex = val.indexOf(',');
|
||||
while (commaIndex > -1) {
|
||||
commaCount += 1;
|
||||
if (commaCount >= options.arrayLimit) {
|
||||
throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
|
||||
}
|
||||
commaIndex = val.indexOf(',', commaIndex + 1);
|
||||
}
|
||||
}
|
||||
return val.split(',');
|
||||
}
|
||||
|
||||
@@ -67,10 +78,10 @@ var parseValues = function parseQueryStringValues(str, options) {
|
||||
var limit = options.parameterLimit === Infinity ? void undefined : options.parameterLimit;
|
||||
var parts = cleanStr.split(
|
||||
options.delimiter,
|
||||
options.throwOnLimitExceeded ? limit + 1 : limit
|
||||
options.throwOnLimitExceeded && typeof limit !== 'undefined' ? limit + 1 : limit
|
||||
);
|
||||
|
||||
if (options.throwOnLimitExceeded && parts.length > limit) {
|
||||
if (options.throwOnLimitExceeded && typeof limit !== 'undefined' && parts.length > limit) {
|
||||
throw new RangeError('Parameter limit exceeded. Only ' + limit + ' parameter' + (limit === 1 ? '' : 's') + ' allowed.');
|
||||
}
|
||||
|
||||
@@ -114,7 +125,8 @@ var parseValues = function parseQueryStringValues(str, options) {
|
||||
parseArrayValue(
|
||||
part.slice(pos + 1),
|
||||
options,
|
||||
isArray(obj[key]) ? obj[key].length : 0
|
||||
isArray(obj[key]) ? obj[key].length : 0,
|
||||
part.indexOf('[]=') === -1
|
||||
),
|
||||
function (encodedVal) {
|
||||
return options.decoder(encodedVal, defaults.decoder, charset, 'value');
|
||||
@@ -132,10 +144,7 @@ var parseValues = function parseQueryStringValues(str, options) {
|
||||
}
|
||||
|
||||
if (options.comma && isArray(val) && val.length > options.arrayLimit) {
|
||||
if (options.throwOnLimitExceeded) {
|
||||
throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
|
||||
}
|
||||
val = utils.combine([], val, options.arrayLimit, options.plainObjects);
|
||||
val = utils.combine([], val, options.arrayLimit, options.plainObjects, options.throwOnLimitExceeded);
|
||||
}
|
||||
|
||||
if (key !== null) {
|
||||
@@ -145,7 +154,8 @@ var parseValues = function parseQueryStringValues(str, options) {
|
||||
obj[key],
|
||||
val,
|
||||
options.arrayLimit,
|
||||
options.plainObjects
|
||||
options.plainObjects,
|
||||
options.throwOnLimitExceeded
|
||||
);
|
||||
} else if (!existing || options.duplicates === 'last') {
|
||||
obj[key] = val;
|
||||
@@ -180,7 +190,8 @@ var parseObject = function (chain, val, options, valuesParsed) {
|
||||
[],
|
||||
leaf,
|
||||
options.arrayLimit,
|
||||
options.plainObjects
|
||||
options.plainObjects,
|
||||
options.throwOnLimitExceeded
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -214,9 +225,12 @@ var parseObject = function (chain, val, options, valuesParsed) {
|
||||
return leaf;
|
||||
};
|
||||
|
||||
var splitKeyIntoSegments = function splitKeyIntoSegments(givenKey, options) {
|
||||
var key = options.allowDots ? givenKey.replace(/\.([^.[]+)/g, '[$1]') : givenKey;
|
||||
// Split a key like "a[b][c[]]" into ['a', '[b]', '[c[]]'] while preserving
|
||||
// qs parse semantics for depth/prototype guards.
|
||||
var splitKeyIntoSegments = function splitKeyIntoSegments(originalKey, options) {
|
||||
var key = options.allowDots ? originalKey.replace(/\.([^.[]+)/g, '[$1]') : originalKey;
|
||||
|
||||
// depth <= 0 keeps the whole key as one segment
|
||||
if (options.depth <= 0) {
|
||||
if (!options.plainObjects && has.call(Object.prototype, key)) {
|
||||
if (!options.allowPrototypes) {
|
||||
@@ -227,14 +241,11 @@ var splitKeyIntoSegments = function splitKeyIntoSegments(givenKey, options) {
|
||||
return [key];
|
||||
}
|
||||
|
||||
var brackets = /(\[[^[\]]*])/;
|
||||
var child = /(\[[^[\]]*])/g;
|
||||
|
||||
var segment = brackets.exec(key);
|
||||
var parent = segment ? key.slice(0, segment.index) : key;
|
||||
|
||||
var keys = [];
|
||||
var segments = [];
|
||||
|
||||
// parent before the first '[' (may be empty if key starts with '[')
|
||||
var first = key.indexOf('[');
|
||||
var parent = first >= 0 ? key.slice(0, first) : key;
|
||||
if (parent) {
|
||||
if (!options.plainObjects && has.call(Object.prototype, parent)) {
|
||||
if (!options.allowPrototypes) {
|
||||
@@ -242,32 +253,62 @@ var splitKeyIntoSegments = function splitKeyIntoSegments(givenKey, options) {
|
||||
}
|
||||
}
|
||||
|
||||
keys[keys.length] = parent;
|
||||
segments[segments.length] = parent;
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
while ((segment = child.exec(key)) !== null && i < options.depth) {
|
||||
i += 1;
|
||||
var n = key.length;
|
||||
var open = first;
|
||||
var collected = 0;
|
||||
|
||||
var segmentContent = segment[1].slice(1, -1);
|
||||
if (!options.plainObjects && has.call(Object.prototype, segmentContent)) {
|
||||
if (!options.allowPrototypes) {
|
||||
return;
|
||||
while (open >= 0 && collected < options.depth) {
|
||||
var level = 1;
|
||||
var i = open + 1;
|
||||
var close = -1;
|
||||
|
||||
// balance nested '[' and ']' inside this bracket group using a nesting level counter
|
||||
while (i < n && close < 0) {
|
||||
var cu = key.charCodeAt(i);
|
||||
if (cu === 0x5B) { // '['
|
||||
level += 1;
|
||||
} else if (cu === 0x5D) { // ']'
|
||||
level -= 1;
|
||||
if (level === 0) {
|
||||
close = i; // found matching close; loop will exit by condition
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
keys[keys.length] = segment[1];
|
||||
if (close < 0) {
|
||||
// Unterminated group: wrap the raw remainder in one bracket pair so it stays
|
||||
// a single literal segment (e.g. "[[]b" -> "[[]b]"); we do not infer missing ']'.
|
||||
segments[segments.length] = '[' + key.slice(open) + ']';
|
||||
return segments;
|
||||
}
|
||||
|
||||
var seg = key.slice(open, close + 1);
|
||||
// prototype guard for the content of this group
|
||||
var content = seg.slice(1, -1);
|
||||
if (!options.plainObjects && has.call(Object.prototype, content) && !options.allowPrototypes) {
|
||||
return;
|
||||
}
|
||||
|
||||
segments[segments.length] = seg;
|
||||
collected += 1;
|
||||
|
||||
// find the next '[' after this balanced group
|
||||
open = key.indexOf('[', close + 1);
|
||||
}
|
||||
|
||||
if (segment) {
|
||||
if (open >= 0) {
|
||||
if (options.strictDepth === true) {
|
||||
throw new RangeError('Input depth exceeded depth option of ' + options.depth + ' and strictDepth is true');
|
||||
}
|
||||
|
||||
keys[keys.length] = '[' + key.slice(segment.index) + ']';
|
||||
segments[segments.length] = '[' + key.slice(open) + ']';
|
||||
}
|
||||
|
||||
return keys;
|
||||
return segments;
|
||||
};
|
||||
|
||||
var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesParsed) {
|
||||
|
||||
Reference in New Issue
Block a user