@tickernelz/paperclip-pro-server 2026.1014.1 → 2026.1015.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-info.json +1 -1
- package/dist/services/heartbeat/retries.d.ts.map +1 -1
- package/dist/services/heartbeat/retries.js +33 -20
- package/dist/services/heartbeat/retries.js.map +1 -1
- package/dist/services/heartbeat/workspaces.d.ts +3 -0
- package/dist/services/heartbeat/workspaces.d.ts.map +1 -1
- package/dist/services/heartbeat/workspaces.js +49 -1
- package/dist/services/heartbeat/workspaces.js.map +1 -1
- package/dist/services/heartbeat.d.ts.map +1 -1
- package/dist/services/heartbeat.js +2 -1
- package/dist/services/heartbeat.js.map +1 -1
- package/dist/services/model-fallback.d.ts +40 -24
- package/dist/services/model-fallback.d.ts.map +1 -1
- package/dist/services/model-fallback.js +93 -61
- package/dist/services/model-fallback.js.map +1 -1
- package/dist/services/model-fallback.test.js +42 -56
- package/dist/services/model-fallback.test.js.map +1 -1
- package/node_modules/qs/.github/THREAT_MODEL.md +4 -2
- package/node_modules/qs/CHANGELOG.md +38 -14
- package/node_modules/qs/README.md +31 -3
- package/node_modules/qs/dist/qs.js +20 -20
- package/node_modules/qs/lib/parse.js +94 -4
- package/node_modules/qs/lib/stringify.js +4 -4
- package/node_modules/qs/lib/utils.js +130 -6
- package/node_modules/qs/package.json +4 -4
- package/node_modules/qs/test/parse.js +174 -0
- package/node_modules/qs/test/stringify.js +263 -33
- package/node_modules/qs/test/utils.js +184 -0
- package/package.json +21 -21
- package/ui-dist/assets/{Agents.production-B_gOaRfn.js → Agents.production-BHWznw8y.js} +2 -2
- package/ui-dist/assets/{CompanyActivity.production-CtbE4gxO.js → CompanyActivity.production-8aUIBuOH.js} +1 -1
- package/ui-dist/assets/{CompanyExport-JuOccR7C.js → CompanyExport-wysQLLwi.js} +1 -1
- package/ui-dist/assets/{CompanySkills.production-3LEUQ24r.js → CompanySkills.production-CeGKxxeo.js} +1 -1
- package/ui-dist/assets/{OrgChart.production-B41A6MKK.js → OrgChart.production-Bv25raI7.js} +1 -1
- package/ui-dist/assets/{RoutineDetail.production-rGdQgBL_.js → RoutineDetail.production-BP0s3T7M.js} +1 -1
- package/ui-dist/assets/{Routines.production-BCxCN3wv.js → Routines.production-BQL74XW8.js} +1 -1
- package/ui-dist/assets/{definition-B8BsU-S8.js → definition-CX59WzhL.js} +1 -1
- package/ui-dist/assets/{index-D6WtpzBM.js → index-DvHeLBFO.js} +88 -88
- package/ui-dist/index.html +1 -1
- package/ui-dist/sw.js +1 -1
|
@@ -28,6 +28,23 @@ var setMaxIndex = function setMaxIndex(obj, maxIndex) {
|
|
|
28
28
|
overflowChannel.set(obj, maxIndex);
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
+
// Track containers produced by a `strictMerge` conflict wrap, and their current max numeric index,
|
|
32
|
+
// so repeated conflicts on one path append instead of nesting a new wrapper each time
|
|
33
|
+
var conflictChannel = getSideChannel();
|
|
34
|
+
|
|
35
|
+
var markConflict = function markConflict(obj, maxIndex) {
|
|
36
|
+
conflictChannel.set(obj, maxIndex);
|
|
37
|
+
return obj;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
var isConflict = function isConflict(obj) {
|
|
41
|
+
return conflictChannel.has(obj);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
var getConflictIndex = function getConflictIndex(obj) {
|
|
45
|
+
return conflictChannel.get(obj);
|
|
46
|
+
};
|
|
47
|
+
|
|
31
48
|
var hexTable = (function () {
|
|
32
49
|
var array = [];
|
|
33
50
|
for (var i = 0; i < 256; ++i) {
|
|
@@ -80,6 +97,30 @@ var setProperty = function setProperty(obj, key, value) {
|
|
|
80
97
|
}
|
|
81
98
|
};
|
|
82
99
|
|
|
100
|
+
var maxNumericIndex = function maxNumericIndex(obj, min) {
|
|
101
|
+
var max = min;
|
|
102
|
+
var keys = Object.keys(obj);
|
|
103
|
+
for (var i = 0; i < keys.length; ++i) {
|
|
104
|
+
var num = parseInt(keys[i], 10);
|
|
105
|
+
if (String(num) === keys[i] && num > max) {
|
|
106
|
+
max = num;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return max;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
var limitedPair = function limitedPair(first, second, options) {
|
|
114
|
+
var pair = [first, second];
|
|
115
|
+
if (options && typeof options.arrayLimit === 'number' && pair.length > options.arrayLimit) {
|
|
116
|
+
if (options.throwOnLimitExceeded) {
|
|
117
|
+
throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
|
|
118
|
+
}
|
|
119
|
+
return markOverflow(arrayToObject(pair, options), 1);
|
|
120
|
+
}
|
|
121
|
+
return pair;
|
|
122
|
+
};
|
|
123
|
+
|
|
83
124
|
var merge = function merge(target, source, options) {
|
|
84
125
|
/* eslint no-param-reassign: 0 */
|
|
85
126
|
if (!source) {
|
|
@@ -102,8 +143,20 @@ var merge = function merge(target, source, options) {
|
|
|
102
143
|
var newIndex = getMaxIndex(target) + 1;
|
|
103
144
|
target[newIndex] = source;
|
|
104
145
|
setMaxIndex(target, newIndex);
|
|
146
|
+
} else if (options && options.strictMerge && isConflict(target)) {
|
|
147
|
+
var nextConflict = getConflictIndex(target) + 1;
|
|
148
|
+
if (
|
|
149
|
+
options.throwOnLimitExceeded
|
|
150
|
+
&& typeof options.arrayLimit === 'number'
|
|
151
|
+
&& nextConflict >= options.arrayLimit
|
|
152
|
+
) {
|
|
153
|
+
throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
|
|
154
|
+
}
|
|
155
|
+
target[nextConflict] = source;
|
|
156
|
+
markConflict(target, nextConflict);
|
|
105
157
|
} else if (options && options.strictMerge) {
|
|
106
|
-
|
|
158
|
+
var conflict = limitedPair(target, source, options);
|
|
159
|
+
return isArray(conflict) ? markConflict(conflict, 1) : conflict;
|
|
107
160
|
} else if (
|
|
108
161
|
(options && (options.plainObjects || options.allowPrototypes))
|
|
109
162
|
|| !has.call(Object.prototype, source)
|
|
@@ -111,7 +164,7 @@ var merge = function merge(target, source, options) {
|
|
|
111
164
|
target[source] = true;
|
|
112
165
|
}
|
|
113
166
|
} else {
|
|
114
|
-
return
|
|
167
|
+
return limitedPair(target, source, options);
|
|
115
168
|
}
|
|
116
169
|
|
|
117
170
|
return target;
|
|
@@ -143,6 +196,10 @@ var merge = function merge(target, source, options) {
|
|
|
143
196
|
var mergeTarget = target;
|
|
144
197
|
if (isArray(target) && !isArray(source)) {
|
|
145
198
|
mergeTarget = arrayToObject(target, options);
|
|
199
|
+
if (isConflict(target)) {
|
|
200
|
+
// the array may have grown past its last conflict, so continue after its last index
|
|
201
|
+
markConflict(mergeTarget, target.length - 1);
|
|
202
|
+
}
|
|
146
203
|
}
|
|
147
204
|
|
|
148
205
|
if (isArray(target) && isArray(source)) {
|
|
@@ -177,7 +234,7 @@ var merge = function merge(target, source, options) {
|
|
|
177
234
|
}
|
|
178
235
|
|
|
179
236
|
if (isOverflow(source) && !isOverflow(acc)) {
|
|
180
|
-
markOverflow(acc, getMaxIndex(source));
|
|
237
|
+
markOverflow(acc, maxNumericIndex(acc, getMaxIndex(source)));
|
|
181
238
|
}
|
|
182
239
|
if (isOverflow(acc)) {
|
|
183
240
|
var keyNum = parseInt(key, 10);
|
|
@@ -185,6 +242,12 @@ var merge = function merge(target, source, options) {
|
|
|
185
242
|
setMaxIndex(acc, keyNum);
|
|
186
243
|
}
|
|
187
244
|
}
|
|
245
|
+
if (isConflict(acc)) {
|
|
246
|
+
var conflictKey = parseInt(key, 10);
|
|
247
|
+
if (String(conflictKey) === key && conflictKey > getConflictIndex(acc)) {
|
|
248
|
+
markConflict(acc, conflictKey);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
188
251
|
|
|
189
252
|
return acc;
|
|
190
253
|
}, mergeTarget);
|
|
@@ -198,6 +261,13 @@ var assign = function assignSingleSource(target, source) {
|
|
|
198
261
|
};
|
|
199
262
|
|
|
200
263
|
var decode = function (str, defaultDecoder, charset) {
|
|
264
|
+
// With no `%` there is no escape to expand, in either charset: `unescape` has
|
|
265
|
+
// nothing to match, and `decodeURIComponent` is the identity on such a string
|
|
266
|
+
// (and cannot throw). So only `+` -> ' ' remains, and often not even that.
|
|
267
|
+
if (typeof str === 'string' && str.indexOf('%') === -1) {
|
|
268
|
+
return str.indexOf('+') === -1 ? str : str.replace(/\+/g, ' ');
|
|
269
|
+
}
|
|
270
|
+
|
|
201
271
|
var strWithoutPlus = str.replace(/\+/g, ' ');
|
|
202
272
|
if (charset === 'iso-8859-1') {
|
|
203
273
|
// unescape never throws, no try...catch needed:
|
|
@@ -211,6 +281,57 @@ var decode = function (str, defaultDecoder, charset) {
|
|
|
211
281
|
}
|
|
212
282
|
};
|
|
213
283
|
|
|
284
|
+
var hasToPrimitive = typeof Symbol === 'function' && typeof Symbol.toPrimitive === 'symbol';
|
|
285
|
+
var arrayJoin = Array.prototype.join;
|
|
286
|
+
var arrayToString = Array.prototype.toString;
|
|
287
|
+
var objectToString = Object.prototype.toString;
|
|
288
|
+
|
|
289
|
+
// an object with no callable toString (eg, from JSON, or null-prototype) would make String() or join() throw,
|
|
290
|
+
// so it becomes its primitive valueOf or else Object.prototype.toString; arrays are walked like join walks them,
|
|
291
|
+
// copied only once an element changes, with an array already being joined becoming '' as engines do for cycles
|
|
292
|
+
var toCoercible = function toCoercible(value, joining) {
|
|
293
|
+
if (!value || (typeof value !== 'object' && typeof value !== 'function')) {
|
|
294
|
+
return value;
|
|
295
|
+
}
|
|
296
|
+
if (hasToPrimitive && value[Symbol.toPrimitive] != null) {
|
|
297
|
+
return value;
|
|
298
|
+
}
|
|
299
|
+
if (isArray(value) && value.toString === arrayToString && value.join === arrayJoin) {
|
|
300
|
+
var ancestors = joining || getSideChannel();
|
|
301
|
+
if (ancestors.has(value)) {
|
|
302
|
+
return '';
|
|
303
|
+
}
|
|
304
|
+
ancestors.set(value, true);
|
|
305
|
+
var copy;
|
|
306
|
+
for (var i = 0; i < value.length; i += 1) {
|
|
307
|
+
var item = value[i];
|
|
308
|
+
var coerced = toCoercible(item, ancestors);
|
|
309
|
+
if (!copy && coerced !== item) {
|
|
310
|
+
copy = [];
|
|
311
|
+
for (var j = 0; j < i; j += 1) {
|
|
312
|
+
copy[j] = value[j];
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (copy) {
|
|
316
|
+
copy[i] = coerced;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
ancestors['delete'](value);
|
|
320
|
+
return copy || value;
|
|
321
|
+
}
|
|
322
|
+
if (typeof value.toString === 'function') {
|
|
323
|
+
return value;
|
|
324
|
+
}
|
|
325
|
+
var valueOf = value.valueOf;
|
|
326
|
+
if (typeof valueOf === 'function') {
|
|
327
|
+
var primitive = valueOf.call(value);
|
|
328
|
+
if (!primitive || (typeof primitive !== 'object' && typeof primitive !== 'function')) {
|
|
329
|
+
return String(primitive);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return objectToString.call(value);
|
|
333
|
+
};
|
|
334
|
+
|
|
214
335
|
var limit = 1024;
|
|
215
336
|
|
|
216
337
|
/* eslint operator-linebreak: [2, "before"] */
|
|
@@ -226,13 +347,15 @@ var encode = function encode(str, defaultEncoder, charset, kind, format) {
|
|
|
226
347
|
if (typeof str === 'symbol') {
|
|
227
348
|
string = Symbol.prototype.toString.call(str);
|
|
228
349
|
} else if (typeof str !== 'string') {
|
|
229
|
-
string = String(str);
|
|
350
|
+
string = String(toCoercible(str));
|
|
230
351
|
}
|
|
231
352
|
|
|
232
353
|
if (charset === 'iso-8859-1') {
|
|
354
|
+
// `escape` leaves `+` untouched, but a literal `+` is decoded back to a space,
|
|
355
|
+
// so it must be percent-encoded to round-trip (the utf-8 path already does this).
|
|
233
356
|
return escape(string).replace(/%u[0-9a-f]{4}/gi, function ($0) {
|
|
234
357
|
return '%26%23' + parseInt($0.slice(2), 16) + '%3B';
|
|
235
|
-
});
|
|
358
|
+
}).replace(/\+/g, '%2B');
|
|
236
359
|
}
|
|
237
360
|
|
|
238
361
|
var out = '';
|
|
@@ -384,5 +507,6 @@ module.exports = {
|
|
|
384
507
|
isRegExp: isRegExp,
|
|
385
508
|
markOverflow: markOverflow,
|
|
386
509
|
maybeMap: maybeMap,
|
|
387
|
-
merge: merge
|
|
510
|
+
merge: merge,
|
|
511
|
+
toCoercible: toCoercible
|
|
388
512
|
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "qs",
|
|
3
3
|
"description": "A querystring parser that supports nesting and arrays, with a depth limit",
|
|
4
4
|
"homepage": "https://github.com/ljharb/qs",
|
|
5
|
-
"version": "6.16.
|
|
5
|
+
"version": "6.16.1",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/ljharb/qs.git"
|
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@browserify/envify": "^6.0.0",
|
|
39
39
|
"@browserify/uglifyify": "^6.0.0",
|
|
40
|
-
"@ljharb/eslint-config": "^22.2.
|
|
40
|
+
"@ljharb/eslint-config": "^22.2.5",
|
|
41
41
|
"browserify": "^16.5.2",
|
|
42
42
|
"bundle-collapser": "^1.4.0",
|
|
43
43
|
"common-shakeify": "~1.0.0",
|
|
44
44
|
"eclint": "^2.8.1",
|
|
45
45
|
"es-value-fixtures": "^1.7.1",
|
|
46
|
-
"eslint": "^10.
|
|
46
|
+
"eslint": "^10.12.0",
|
|
47
47
|
"evalmd": "^0.0.22",
|
|
48
48
|
"for-each": "^0.3.5",
|
|
49
49
|
"glob": "=10.3.7",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"qs-iconv": "^1.0.4",
|
|
66
66
|
"safe-publish-latest": "^2.0.0",
|
|
67
67
|
"safer-buffer": "^2.1.2",
|
|
68
|
-
"tape": "^5.10.
|
|
68
|
+
"tape": "^5.10.3",
|
|
69
69
|
"unassertify": "^3.0.1"
|
|
70
70
|
},
|
|
71
71
|
"scripts": {
|
|
@@ -62,10 +62,39 @@ test('parse()', function (t) {
|
|
|
62
62
|
st.end();
|
|
63
63
|
});
|
|
64
64
|
|
|
65
|
+
t.test('comma: `[]=` in a value does not wrap the value in an extra array', function (st) {
|
|
66
|
+
st.deepEqual(qs.parse('a[b]=1,2,3[]=x', { comma: true }), { a: { b: ['1', '2', '3[]=x'] } });
|
|
67
|
+
st.deepEqual(qs.parse('a[b]=1,2[]=3', { comma: true }), { a: { b: ['1', '2[]=3'] } });
|
|
68
|
+
st.deepEqual(qs.parse('a[]=1,2,3', { comma: true }), { a: [['1', '2', '3']] });
|
|
69
|
+
st.end();
|
|
70
|
+
});
|
|
71
|
+
|
|
65
72
|
t.test('allows enabling dot notation', function (st) {
|
|
66
73
|
st.deepEqual(qs.parse('a.b=c'), { 'a.b': 'c' });
|
|
67
74
|
st.deepEqual(qs.parse('a.b=c', { allowDots: true }), { a: { b: 'c' } });
|
|
68
75
|
|
|
76
|
+
// a literal dot inside a bracket segment must not be rewritten by allowDots (#617)
|
|
77
|
+
st.deepEqual(
|
|
78
|
+
qs.parse('outer[a.b]=1', { allowDots: true }),
|
|
79
|
+
{ outer: { 'a.b': '1' } },
|
|
80
|
+
'a dot inside brackets stays part of the key when allowDots is true'
|
|
81
|
+
);
|
|
82
|
+
st.deepEqual(
|
|
83
|
+
qs.parse('outer[a.b]=1', { allowDots: true }),
|
|
84
|
+
qs.parse('outer[a.b]=1', { allowDots: false }),
|
|
85
|
+
'allowDots does not change how a bracket segment containing a dot is parsed'
|
|
86
|
+
);
|
|
87
|
+
st.deepEqual(
|
|
88
|
+
qs.parse('a].b=c', { allowDots: true }),
|
|
89
|
+
{ 'a]': { b: 'c' } },
|
|
90
|
+
'a stray close bracket does not stop a later dot from being converted'
|
|
91
|
+
);
|
|
92
|
+
st.deepEqual(
|
|
93
|
+
qs.parse('a]].b[c.d]=e', { allowDots: true }),
|
|
94
|
+
{ 'a]]': { b: { 'c.d': 'e' } } },
|
|
95
|
+
'stray close brackets do not unbalance a later bracket segment'
|
|
96
|
+
);
|
|
97
|
+
|
|
69
98
|
st.end();
|
|
70
99
|
});
|
|
71
100
|
|
|
@@ -360,6 +389,14 @@ test('parse()', function (t) {
|
|
|
360
389
|
st.end();
|
|
361
390
|
});
|
|
362
391
|
|
|
392
|
+
t.test('currently moves the key/value split to a later `]=` when the first `=` comes before any bracket group', function (st) {
|
|
393
|
+
characterizeParse(st, 'a=b[c]=d', undefined, { 'a=b': { c: 'd' } }, 'literal brackets after the first `=`');
|
|
394
|
+
characterizeParse(st, 'q=%5B1%5D=2', undefined, { 'q=': ['2'] }, 'encoded brackets collapse to an array');
|
|
395
|
+
characterizeParse(st, 'role=guest%5Bx%5Dy%5D=z', undefined, { 'role=guest': { x: 'z' } }, 'group opens after the first `=`, and the text after it is dropped');
|
|
396
|
+
characterizeParse(st, 'role=guest%5D=admin', undefined, { 'role=guest]': 'admin' }, 'encoded `]=` with no bracket group at all');
|
|
397
|
+
st.end();
|
|
398
|
+
});
|
|
399
|
+
|
|
363
400
|
t.test('allows to specify array indices', function (st) {
|
|
364
401
|
st.deepEqual(qs.parse('a[1]=c&a[0]=b&a[2]=d'), { a: ['b', 'c', 'd'] });
|
|
365
402
|
st.deepEqual(qs.parse('a[1]=c&a[0]=b'), { a: ['b', 'c'] });
|
|
@@ -745,6 +782,38 @@ test('parse()', function (t) {
|
|
|
745
782
|
st.end();
|
|
746
783
|
});
|
|
747
784
|
|
|
785
|
+
t.test('does not mutate an object input', function (st) {
|
|
786
|
+
var arr = ['x'];
|
|
787
|
+
st.deepEqual(qs.parse({ a: arr, 'a[]': 'y' }), { a: ['x', 'y'] }, 'appends to a copy of an input array');
|
|
788
|
+
st.deepEqual(arr, ['x'], 'the input array is unchanged');
|
|
789
|
+
|
|
790
|
+
var nested = { b: ['x'] };
|
|
791
|
+
st.deepEqual(qs.parse({ a: nested, 'a[b][]': 'y' }), { a: { b: ['x', 'y'] } }, 'appends to a copy of a nested input array');
|
|
792
|
+
st.deepEqual(nested, { b: ['x'] }, 'the nested input array is unchanged');
|
|
793
|
+
|
|
794
|
+
var obj = { b: 'c' };
|
|
795
|
+
st.deepEqual(qs.parse({ a: obj, 'a[d]': 'e' }), { a: { b: 'c', d: 'e' } }, 'merges into a copy of an input object');
|
|
796
|
+
st.deepEqual(obj, { b: 'c' }, 'the input object is unchanged');
|
|
797
|
+
|
|
798
|
+
var sparse = { b: [1, undefined, 2] };
|
|
799
|
+
st.deepEqual(qs.parse({ a: sparse }), { a: { b: [1, 2] } }, 'compacts a copy of an input array');
|
|
800
|
+
st.deepEqual(sparse, { b: [1, undefined, 2] }, 'the input array is not compacted');
|
|
801
|
+
|
|
802
|
+
var nullProto = { __proto__: null, b: 'c' };
|
|
803
|
+
st.equal(Object.getPrototypeOf(qs.parse({ a: nullProto }).a), null, 'a null-prototype input object stays null-prototype');
|
|
804
|
+
|
|
805
|
+
var date = new Date(0);
|
|
806
|
+
st.equal(qs.parse({ a: date }).a, date, 'a non-plain object is not copied');
|
|
807
|
+
|
|
808
|
+
var cyclic = { b: 'c' };
|
|
809
|
+
cyclic.self = cyclic;
|
|
810
|
+
var result = qs.parse({ a: cyclic });
|
|
811
|
+
st.notEqual(result.a, cyclic, 'a cyclic input object is copied');
|
|
812
|
+
st.equal(result.a.self, result.a, 'the copy keeps the cycle');
|
|
813
|
+
|
|
814
|
+
st.end();
|
|
815
|
+
});
|
|
816
|
+
|
|
748
817
|
t.test('does not blow up when Buffer global is missing', function (st) {
|
|
749
818
|
var restore = mockProperty(global, 'Buffer', { 'delete': true });
|
|
750
819
|
|
|
@@ -962,6 +1031,38 @@ test('parse()', function (t) {
|
|
|
962
1031
|
st.end();
|
|
963
1032
|
});
|
|
964
1033
|
|
|
1034
|
+
t.test('strictMerge conflicts do not overwrite indexed values already at that path', function (st) {
|
|
1035
|
+
st.deepEqual(
|
|
1036
|
+
qs.parse('a[z]=o&a=p&a[y]=q&a[2]=keep&[a]=r'),
|
|
1037
|
+
{ a: { 0: { z: 'o' }, 1: 'p', 2: 'keep', 3: 'r', y: 'q' } },
|
|
1038
|
+
'an indexed key merged into the container is kept'
|
|
1039
|
+
);
|
|
1040
|
+
|
|
1041
|
+
st.deepEqual(
|
|
1042
|
+
qs.parse('a[z]=o&a=p&a[2]=keep&a[y]=q&[a]=r'),
|
|
1043
|
+
{ a: { 0: { z: 'o' }, 1: 'p', 2: 'keep', 3: 'r', y: 'q' } },
|
|
1044
|
+
'an indexed key that extended the container while it was an array is kept'
|
|
1045
|
+
);
|
|
1046
|
+
|
|
1047
|
+
st.end();
|
|
1048
|
+
});
|
|
1049
|
+
|
|
1050
|
+
t.test('strictMerge conflicts do not overwrite values once the container overflows', function (st) {
|
|
1051
|
+
st.deepEqual(
|
|
1052
|
+
qs.parse('a[z]=v0&a=v1&a[y]=v2&[a]=v3&[a]x=v4&a[2]=v5&[a]x1=v6', { arrayLimit: 2 }),
|
|
1053
|
+
{ a: { 0: { z: 'v0' }, 1: 'v1', 2: ['v3', 'v5'], 3: 'v4', 4: 'v6', y: 'v2' } },
|
|
1054
|
+
'a conflict appended after the container overflowed keeps every value'
|
|
1055
|
+
);
|
|
1056
|
+
|
|
1057
|
+
st.deepEqual(
|
|
1058
|
+
qs.parse('a[2]=v1&a=v5&a=v7&[a]x=v9', { parseArrays: false, arrayLimit: 1 }),
|
|
1059
|
+
{ a: { 0: 'v5', 1: 'v7', 2: 'v1', 3: 'v9' } },
|
|
1060
|
+
'an index the container already holds is not reused'
|
|
1061
|
+
);
|
|
1062
|
+
|
|
1063
|
+
st.end();
|
|
1064
|
+
});
|
|
1065
|
+
|
|
965
1066
|
t.test('dunder proto is ignored', function (st) {
|
|
966
1067
|
var payload = 'categories[__proto__]=login&categories[__proto__]&categories[length]=42';
|
|
967
1068
|
var result = qs.parse(payload, { allowPrototypes: true });
|
|
@@ -1463,6 +1564,57 @@ test('parse()', function (t) {
|
|
|
1463
1564
|
sst.end();
|
|
1464
1565
|
});
|
|
1465
1566
|
|
|
1567
|
+
st.test('enforces arrayLimit when a strictMerge conflict appends to its container', function (sst) {
|
|
1568
|
+
var aliased = 'a[z]=o&a=p&a[y]=q&[a]=r';
|
|
1569
|
+
sst['throws'](
|
|
1570
|
+
function () { qs.parse(aliased, { arrayLimit: 2, throwOnLimitExceeded: true }); },
|
|
1571
|
+
new RangeError('Array limit exceeded. Only 2 elements allowed in an array.'),
|
|
1572
|
+
'a third conflicting value throws once the container would exceed arrayLimit'
|
|
1573
|
+
);
|
|
1574
|
+
sst.deepEqual(
|
|
1575
|
+
qs.parse(aliased, { arrayLimit: 3, throwOnLimitExceeded: true }),
|
|
1576
|
+
{ a: { 0: { z: 'o' }, 1: 'p', 2: 'r', y: 'q' } },
|
|
1577
|
+
'appends while the container stays within arrayLimit'
|
|
1578
|
+
);
|
|
1579
|
+
sst.deepEqual(
|
|
1580
|
+
qs.parse(aliased, { arrayLimit: 2 }),
|
|
1581
|
+
{ a: { 0: { z: 'o' }, 1: 'p', 2: 'r', y: 'q' } },
|
|
1582
|
+
'appends without throwing when throwOnLimitExceeded is not set'
|
|
1583
|
+
);
|
|
1584
|
+
|
|
1585
|
+
sst.end();
|
|
1586
|
+
});
|
|
1587
|
+
|
|
1588
|
+
st.test('enforces arrayLimit when differently spelled keys collide', function (sst) {
|
|
1589
|
+
sst['throws'](
|
|
1590
|
+
function () { qs.parse('[a]=x&a=y', { arrayLimit: 1, throwOnLimitExceeded: true }); },
|
|
1591
|
+
new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
|
|
1592
|
+
'two primitives throw, as `a=x&a=y` does'
|
|
1593
|
+
);
|
|
1594
|
+
sst['throws'](
|
|
1595
|
+
function () { qs.parse('a[b]=x&a=y', { arrayLimit: 1, throwOnLimitExceeded: true }); },
|
|
1596
|
+
new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
|
|
1597
|
+
'an object and a primitive throw under strictMerge'
|
|
1598
|
+
);
|
|
1599
|
+
sst.deepEqual(
|
|
1600
|
+
qs.parse('[a]=x&a=y', { arrayLimit: 1 }),
|
|
1601
|
+
{ a: { 0: 'x', 1: 'y' } },
|
|
1602
|
+
'without throwOnLimitExceeded, two primitives convert to an object, as `a=x&a=y` does'
|
|
1603
|
+
);
|
|
1604
|
+
sst.deepEqual(
|
|
1605
|
+
qs.parse('a[b]=x&a=y', { arrayLimit: 1 }),
|
|
1606
|
+
{ a: { 0: { b: 'x' }, 1: 'y' } },
|
|
1607
|
+
'and so do an object and a primitive'
|
|
1608
|
+
);
|
|
1609
|
+
sst.deepEqual(
|
|
1610
|
+
qs.parse('a[b]=x&a=y', { arrayLimit: 2, throwOnLimitExceeded: true }),
|
|
1611
|
+
{ a: [{ b: 'x' }, 'y'] },
|
|
1612
|
+
'a collision within arrayLimit is still an array'
|
|
1613
|
+
);
|
|
1614
|
+
|
|
1615
|
+
sst.end();
|
|
1616
|
+
});
|
|
1617
|
+
|
|
1466
1618
|
st.test('does not throw when cumulative comma combine stays within arrayLimit', function (sst) {
|
|
1467
1619
|
var result = qs.parse('a=1,2,3&a=4', { comma: true, arrayLimit: 5, throwOnLimitExceeded: true });
|
|
1468
1620
|
sst.deepEqual(result, { a: ['1', '2', '3', '4'] }, 'combined array within limit is preserved');
|
|
@@ -1807,6 +1959,28 @@ test('`duplicates` option', function (t) {
|
|
|
1807
1959
|
st.end();
|
|
1808
1960
|
});
|
|
1809
1961
|
|
|
1962
|
+
t.test('`[]=` in a value does not force combining', function (st) {
|
|
1963
|
+
st.deepEqual(
|
|
1964
|
+
qs.parse('a[b]=1&a[b]=2[]=3', { duplicates: 'last' }),
|
|
1965
|
+
{ a: { b: '2[]=3' } },
|
|
1966
|
+
'duplicates last: `[]=` in the value is not a bracketed key'
|
|
1967
|
+
);
|
|
1968
|
+
|
|
1969
|
+
st.deepEqual(
|
|
1970
|
+
qs.parse('a[b]=1&a[b]=2[]=3', { duplicates: 'first' }),
|
|
1971
|
+
{ a: { b: '1' } },
|
|
1972
|
+
'duplicates first: `[]=` in the value is not a bracketed key'
|
|
1973
|
+
);
|
|
1974
|
+
|
|
1975
|
+
st.deepEqual(
|
|
1976
|
+
qs.parse('a[b]=1&a[b]=2[]=3', { duplicates: 'combine' }),
|
|
1977
|
+
{ a: { b: ['1', '2[]=3'] } },
|
|
1978
|
+
'duplicates combine: still combines'
|
|
1979
|
+
);
|
|
1980
|
+
|
|
1981
|
+
st.end();
|
|
1982
|
+
});
|
|
1983
|
+
|
|
1810
1984
|
t.end();
|
|
1811
1985
|
});
|
|
1812
1986
|
|