@quantiya/codevibe-claude-plugin 1.0.37 → 1.0.39
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/.claude-plugin/plugin.json +1 -1
- package/bin/codevibe-claude +17 -3
- package/dist/server.js +8 -7
- package/hooks/stop.sh +30 -10
- package/node_modules/@quantiya/codevibe-core/dist/appsync/appsync-client.d.ts +1 -139
- package/node_modules/@quantiya/codevibe-core/dist/appsync/queries.d.ts +0 -5
- package/node_modules/@quantiya/codevibe-core/dist/auth/auth-telemetry.d.ts +64 -29
- package/node_modules/@quantiya/codevibe-core/dist/index.d.ts +0 -4
- package/node_modules/@quantiya/codevibe-core/dist/index.js +33 -194
- package/node_modules/@quantiya/codevibe-core/dist/keychain/keychain-manager.d.ts +16 -2
- package/node_modules/@quantiya/codevibe-core/dist/session/session-rekey.d.ts +40 -0
- package/node_modules/@quantiya/codevibe-core/dist/session/session-resume.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/types/index.d.ts +0 -2
- package/node_modules/@quantiya/codevibe-core/dist/types/session.d.ts +0 -16
- package/node_modules/@quantiya/codevibe-core/package.json +1 -1
- package/node_modules/body-parser/README.md +18 -18
- package/node_modules/body-parser/index.js +6 -15
- package/node_modules/body-parser/lib/read.js +17 -20
- package/node_modules/body-parser/lib/types/json.js +8 -16
- package/node_modules/body-parser/lib/types/raw.js +3 -4
- package/node_modules/body-parser/lib/types/text.js +3 -4
- package/node_modules/body-parser/lib/types/urlencoded.js +8 -8
- package/node_modules/body-parser/lib/utils.js +11 -9
- package/node_modules/body-parser/package.json +2 -2
- package/node_modules/content-disposition/README.md +7 -8
- package/node_modules/content-disposition/index.js +118 -40
- package/node_modules/content-disposition/package.json +8 -11
- package/node_modules/express/Readme.md +39 -29
- package/node_modules/express/lib/application.js +1 -1
- package/node_modules/express/lib/request.js +5 -6
- package/node_modules/express/lib/response.js +14 -0
- package/node_modules/express/lib/utils.js +3 -1
- package/node_modules/express/package.json +6 -5
- package/node_modules/finalhandler/HISTORY.md +6 -0
- package/node_modules/finalhandler/README.md +26 -23
- package/node_modules/finalhandler/package.json +13 -9
- package/node_modules/graphql/execution/execute.d.ts +14 -1
- package/node_modules/graphql/execution/execute.js +63 -13
- package/node_modules/graphql/execution/execute.mjs +63 -13
- package/node_modules/graphql/execution/subscribe.js +1 -0
- package/node_modules/graphql/execution/subscribe.mjs +2 -0
- package/node_modules/graphql/execution/values.js +4 -4
- package/node_modules/graphql/execution/values.mjs +4 -4
- package/node_modules/graphql/index.d.ts +1 -0
- package/node_modules/graphql/language/ast.d.ts +10 -1
- package/node_modules/graphql/language/ast.js +8 -1
- package/node_modules/graphql/language/ast.mjs +8 -1
- package/node_modules/graphql/language/directiveLocation.d.ts +1 -0
- package/node_modules/graphql/language/directiveLocation.js +1 -0
- package/node_modules/graphql/language/directiveLocation.mjs +1 -0
- package/node_modules/graphql/language/index.d.ts +1 -0
- package/node_modules/graphql/language/kinds.d.ts +1 -0
- package/node_modules/graphql/language/kinds.js +1 -0
- package/node_modules/graphql/language/kinds.mjs +1 -0
- package/node_modules/graphql/language/parser.d.ts +14 -0
- package/node_modules/graphql/language/parser.js +33 -0
- package/node_modules/graphql/language/parser.mjs +33 -0
- package/node_modules/graphql/language/predicates.js +3 -1
- package/node_modules/graphql/language/predicates.mjs +5 -1
- package/node_modules/graphql/language/printer.js +13 -1
- package/node_modules/graphql/language/printer.mjs +13 -1
- package/node_modules/graphql/package.json +1 -1
- package/node_modules/graphql/type/directives.d.ts +9 -1
- package/node_modules/graphql/type/directives.js +10 -1
- package/node_modules/graphql/type/directives.mjs +10 -1
- package/node_modules/graphql/type/introspection.js +24 -1
- package/node_modules/graphql/type/introspection.mjs +24 -1
- package/node_modules/graphql/utilities/buildASTSchema.js +4 -0
- package/node_modules/graphql/utilities/buildASTSchema.mjs +4 -0
- package/node_modules/graphql/utilities/buildClientSchema.js +1 -0
- package/node_modules/graphql/utilities/buildClientSchema.mjs +1 -0
- package/node_modules/graphql/utilities/coerceInputValue.js +2 -2
- package/node_modules/graphql/utilities/coerceInputValue.mjs +2 -2
- package/node_modules/graphql/utilities/extendSchema.js +58 -3
- package/node_modules/graphql/utilities/extendSchema.mjs +58 -3
- package/node_modules/graphql/utilities/getIntrospectionQuery.d.ts +16 -0
- package/node_modules/graphql/utilities/getIntrospectionQuery.js +31 -38
- package/node_modules/graphql/utilities/getIntrospectionQuery.mjs +31 -38
- package/node_modules/graphql/utilities/introspectionFromSchema.js +1 -0
- package/node_modules/graphql/utilities/introspectionFromSchema.mjs +1 -0
- package/node_modules/graphql/utilities/printSchema.js +1 -0
- package/node_modules/graphql/utilities/printSchema.mjs +1 -0
- package/node_modules/graphql/utilities/valueFromAST.js +12 -2
- package/node_modules/graphql/utilities/valueFromAST.mjs +12 -2
- package/node_modules/graphql/validation/rules/KnownDirectivesRule.js +4 -0
- package/node_modules/graphql/validation/rules/KnownDirectivesRule.mjs +4 -0
- package/node_modules/graphql/validation/rules/UniqueDirectivesPerLocationRule.js +12 -0
- package/node_modules/graphql/validation/rules/UniqueDirectivesPerLocationRule.mjs +12 -0
- package/node_modules/graphql/validation/rules/ValuesOfCorrectTypeRule.js +5 -11
- package/node_modules/graphql/validation/rules/ValuesOfCorrectTypeRule.mjs +5 -11
- package/node_modules/graphql/validation/validate.js +12 -0
- package/node_modules/graphql/validation/validate.mjs +13 -2
- package/node_modules/graphql/version.js +2 -2
- package/node_modules/graphql/version.mjs +2 -2
- package/node_modules/hasown/CHANGELOG.md +11 -0
- package/node_modules/hasown/eslint.config.mjs +6 -0
- package/node_modules/hasown/index.d.ts +1 -0
- package/node_modules/hasown/package.json +14 -14
- package/node_modules/iconv-lite/lib/index.d.ts +114 -26
- package/node_modules/iconv-lite/lib/index.js +39 -40
- package/node_modules/iconv-lite/package.json +13 -2
- package/node_modules/iconv-lite/types/encodings.d.ts +423 -0
- package/node_modules/node-abi/abi_registry.json +10 -3
- package/node_modules/{semver → node-abi/node_modules/semver}/README.md +19 -4
- package/node_modules/{semver → node-abi/node_modules/semver}/bin/semver.js +14 -10
- package/node_modules/node-abi/node_modules/semver/functions/truncate.js +48 -0
- package/node_modules/{semver → node-abi/node_modules/semver}/index.js +2 -0
- package/node_modules/{semver → node-abi/node_modules/semver}/internal/re.js +1 -1
- package/node_modules/{semver → node-abi/node_modules/semver}/package.json +3 -3
- package/node_modules/{semver → node-abi/node_modules/semver}/range.bnf +5 -4
- package/node_modules/node-abi/package.json +1 -1
- package/node_modules/path-to-regexp/Readme.md +3 -3
- package/node_modules/path-to-regexp/dist/index.d.ts +3 -0
- package/node_modules/path-to-regexp/dist/index.js +215 -193
- package/node_modules/path-to-regexp/dist/index.js.map +1 -1
- package/node_modules/path-to-regexp/package.json +2 -2
- package/node_modules/qs/.editorconfig +1 -1
- package/node_modules/qs/.github/SECURITY.md +11 -0
- package/node_modules/qs/.github/THREAT_MODEL.md +78 -0
- package/node_modules/qs/CHANGELOG.md +190 -0
- package/node_modules/qs/README.md +29 -4
- package/node_modules/qs/dist/qs.js +21 -21
- package/node_modules/qs/eslint.config.mjs +56 -0
- package/node_modules/qs/lib/parse.js +94 -49
- package/node_modules/qs/lib/utils.js +85 -11
- package/node_modules/qs/package.json +10 -9
- package/node_modules/qs/test/parse.js +391 -13
- package/node_modules/qs/test/stringify.js +16 -3
- package/node_modules/qs/test/utils.js +173 -3
- package/node_modules/send/package.json +11 -8
- package/node_modules/serve-static/README.md +23 -23
- package/node_modules/serve-static/package.json +6 -3
- package/node_modules/side-channel-list/CHANGELOG.md +25 -4
- package/node_modules/side-channel-list/index.js +1 -3
- package/node_modules/side-channel-list/package.json +8 -8
- package/node_modules/side-channel-list/test/index.js +50 -0
- package/node_modules/uuid/dist/v35.js +3 -0
- package/node_modules/uuid/dist/v6.js +3 -0
- package/node_modules/uuid/dist-node/v35.js +3 -0
- package/node_modules/uuid/dist-node/v6.js +3 -0
- package/node_modules/uuid/package.json +1 -1
- package/node_modules/ws/index.js +15 -6
- package/node_modules/ws/lib/constants.js +1 -0
- package/node_modules/ws/lib/permessage-deflate.js +6 -6
- package/node_modules/ws/lib/websocket-server.js +10 -6
- package/node_modules/ws/lib/websocket.js +19 -14
- package/node_modules/ws/package.json +4 -3
- package/node_modules/ws/wrapper.mjs +14 -1
- package/package.json +2 -2
- package/node_modules/@quantiya/codevibe-core/dist/appsync/__tests__/appsync-client.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/audit-keys/__tests__/audit-keys-parity.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/audit-keys/index.d.ts +0 -41
- package/node_modules/@quantiya/codevibe-core/dist/auth/__tests__/auth-telemetry.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-bootstrap.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-failure-recourse.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-save.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-seat-picker.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-telemetry.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-test-agents.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-types.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-wizard.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/v1-options.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/detect-agents.d.ts +0 -56
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/index.d.ts +0 -3
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/orchestration-cli.d.ts +0 -12
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-bootstrap.d.ts +0 -146
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-failure-recourse.d.ts +0 -23
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-save.d.ts +0 -47
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-seat-picker.d.ts +0 -72
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-telemetry.d.ts +0 -54
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-test-agents.d.ts +0 -108
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-types.d.ts +0 -140
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-wizard.d.ts +0 -57
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/v1-options.d.ts +0 -108
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/integration.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/mocks.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/output-parser.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/registry.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/subprocess.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/index.d.ts +0 -15
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/mocks.d.ts +0 -80
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/output-parser.d.ts +0 -95
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/provider.d.ts +0 -153
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/claude-live-smoke.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/claude.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/codex-live-smoke.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/codex.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/gemini-live-smoke.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/gemini.test.d.ts +0 -1
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/claude.d.ts +0 -59
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/codex.d.ts +0 -67
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/common.d.ts +0 -25
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/gemini.d.ts +0 -108
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/registry.d.ts +0 -87
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/subprocess.d.ts +0 -117
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/types.d.ts +0 -101
- package/node_modules/@quantiya/codevibe-core/dist/types/orchestration.d.ts +0 -57
- package/node_modules/@quantiya/codevibe-core/dist/types/reviewer.d.ts +0 -67
- package/node_modules/content-disposition/HISTORY.md +0 -72
- package/node_modules/express/History.md +0 -3858
- package/node_modules/hasown/.eslintrc +0 -5
- package/node_modules/iconv-lite/Changelog.md +0 -236
- package/node_modules/qs/.eslintrc +0 -39
- package/node_modules/send/HISTORY.md +0 -580
- package/node_modules/serve-static/HISTORY.md +0 -516
- /package/node_modules/{semver → node-abi/node_modules/semver}/LICENSE +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/classes/comparator.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/classes/index.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/classes/range.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/classes/semver.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/clean.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/cmp.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/coerce.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/compare-build.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/compare-loose.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/compare.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/diff.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/eq.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/gt.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/gte.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/inc.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/lt.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/lte.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/major.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/minor.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/neq.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/parse.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/patch.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/prerelease.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/rcompare.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/rsort.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/satisfies.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/sort.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/functions/valid.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/internal/constants.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/internal/debug.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/internal/identifiers.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/internal/lrucache.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/internal/parse-options.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/preload.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/gtr.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/intersects.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/ltr.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/max-satisfying.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/min-satisfying.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/min-version.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/outside.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/simplify.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/subset.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/to-comparators.js +0 -0
- /package/node_modules/{semver → node-abi/node_modules/semver}/ranges/valid.js +0 -0
- /package/node_modules/{strip-json-comments → rc/node_modules/strip-json-comments}/index.js +0 -0
- /package/node_modules/{strip-json-comments → rc/node_modules/strip-json-comments}/license +0 -0
- /package/node_modules/{strip-json-comments → rc/node_modules/strip-json-comments}/package.json +0 -0
- /package/node_modules/{strip-json-comments → rc/node_modules/strip-json-comments}/readme.md +0 -0
|
@@ -213,6 +213,18 @@ test('parse()', function (t) {
|
|
|
213
213
|
st.end();
|
|
214
214
|
});
|
|
215
215
|
|
|
216
|
+
t.test('ignores prototype keys when depth = 0 and allowPrototypes is false', function (st) {
|
|
217
|
+
st.deepEqual(qs.parse('toString=foo', { depth: 0 }), {});
|
|
218
|
+
st.deepEqual(qs.parse('hasOwnProperty=bar', { depth: 0 }), {});
|
|
219
|
+
st.deepEqual(qs.parse('toString=foo&a=b', { depth: 0 }), { a: 'b' });
|
|
220
|
+
st.end();
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
t.test('allows prototype keys when depth = 0 and allowPrototypes is true', function (st) {
|
|
224
|
+
st.deepEqual(qs.parse('toString=foo', { depth: 0, allowPrototypes: true }), { toString: 'foo' });
|
|
225
|
+
st.end();
|
|
226
|
+
});
|
|
227
|
+
|
|
216
228
|
t.test('uses original key when depth = false', function (st) {
|
|
217
229
|
st.deepEqual(qs.parse('a[0]=b&a[1]=c', { depth: false }), { 'a[0]': 'b', 'a[1]': 'c' });
|
|
218
230
|
st.deepEqual(qs.parse('a[0][0]=b&a[0][1]=c&a[1]=d&e=2', { depth: false }), { 'a[0][0]': 'b', 'a[0][1]': 'c', 'a[1]': 'd', e: '2' });
|
|
@@ -235,11 +247,11 @@ test('parse()', function (t) {
|
|
|
235
247
|
st.deepEqual(qs.parse('a=b&a[0]=c'), { a: ['b', 'c'] });
|
|
236
248
|
|
|
237
249
|
st.deepEqual(qs.parse('a[1]=b&a=c', { arrayLimit: 20 }), { a: ['b', 'c'] });
|
|
238
|
-
st.deepEqual(qs.parse('a[]=b&a=c', { arrayLimit: 0 }), { a:
|
|
250
|
+
st.deepEqual(qs.parse('a[]=b&a=c', { arrayLimit: 0 }), { a: { 0: 'b', 1: 'c' } });
|
|
239
251
|
st.deepEqual(qs.parse('a[]=b&a=c'), { a: ['b', 'c'] });
|
|
240
252
|
|
|
241
253
|
st.deepEqual(qs.parse('a=b&a[1]=c', { arrayLimit: 20 }), { a: ['b', 'c'] });
|
|
242
|
-
st.deepEqual(qs.parse('a=b&a[]=c', { arrayLimit: 0 }), { a:
|
|
254
|
+
st.deepEqual(qs.parse('a=b&a[]=c', { arrayLimit: 0 }), { a: { 0: 'b', 1: 'c' } });
|
|
243
255
|
st.deepEqual(qs.parse('a=b&a[]=c'), { a: ['b', 'c'] });
|
|
244
256
|
|
|
245
257
|
st.end();
|
|
@@ -261,11 +273,11 @@ test('parse()', function (t) {
|
|
|
261
273
|
});
|
|
262
274
|
|
|
263
275
|
t.test('limits specific array indices to arrayLimit', function (st) {
|
|
264
|
-
st.deepEqual(qs.parse('a[
|
|
265
|
-
st.deepEqual(qs.parse('a[
|
|
276
|
+
st.deepEqual(qs.parse('a[19]=a', { arrayLimit: 20 }), { a: ['a'] });
|
|
277
|
+
st.deepEqual(qs.parse('a[20]=a', { arrayLimit: 20 }), { a: { 20: 'a' } });
|
|
266
278
|
|
|
267
|
-
st.deepEqual(qs.parse('a[
|
|
268
|
-
st.deepEqual(qs.parse('a[
|
|
279
|
+
st.deepEqual(qs.parse('a[19]=a'), { a: ['a'] });
|
|
280
|
+
st.deepEqual(qs.parse('a[20]=a'), { a: { 20: 'a' } });
|
|
269
281
|
st.end();
|
|
270
282
|
});
|
|
271
283
|
|
|
@@ -364,7 +376,7 @@ test('parse()', function (t) {
|
|
|
364
376
|
);
|
|
365
377
|
st.deepEqual(
|
|
366
378
|
qs.parse('a[]=b&a[]&a[]=c&a[]=', { strictNullHandling: true, arrayLimit: 0 }),
|
|
367
|
-
{ a:
|
|
379
|
+
{ a: { 0: 'b', 1: null, 2: 'c', 3: '' } },
|
|
368
380
|
'with arrayLimit 0 + array brackets: null then empty string works'
|
|
369
381
|
);
|
|
370
382
|
|
|
@@ -375,7 +387,7 @@ test('parse()', function (t) {
|
|
|
375
387
|
);
|
|
376
388
|
st.deepEqual(
|
|
377
389
|
qs.parse('a[]=b&a[]=&a[]=c&a[]', { strictNullHandling: true, arrayLimit: 0 }),
|
|
378
|
-
{ a:
|
|
390
|
+
{ a: { 0: 'b', 1: '', 2: 'c', 3: null } },
|
|
379
391
|
'with arrayLimit 0 + array brackets: empty string then null works'
|
|
380
392
|
);
|
|
381
393
|
|
|
@@ -483,7 +495,7 @@ test('parse()', function (t) {
|
|
|
483
495
|
|
|
484
496
|
t.test('allows overriding array limit', function (st) {
|
|
485
497
|
st.deepEqual(qs.parse('a[0]=b', { arrayLimit: -1 }), { a: { 0: 'b' } });
|
|
486
|
-
st.deepEqual(qs.parse('a[0]=b', { arrayLimit: 0 }), { a:
|
|
498
|
+
st.deepEqual(qs.parse('a[0]=b', { arrayLimit: 0 }), { a: { 0: 'b' } });
|
|
487
499
|
|
|
488
500
|
st.deepEqual(qs.parse('a[-1]=b', { arrayLimit: -1 }), { a: { '-1': 'b' } });
|
|
489
501
|
st.deepEqual(qs.parse('a[-1]=b', { arrayLimit: 0 }), { a: { '-1': 'b' } });
|
|
@@ -784,25 +796,25 @@ test('parse()', function (t) {
|
|
|
784
796
|
|
|
785
797
|
t.test('add keys to objects', function (st) {
|
|
786
798
|
st.deepEqual(
|
|
787
|
-
qs.parse('a[b]=c&a=d'),
|
|
799
|
+
qs.parse('a[b]=c&a=d', { strictMerge: false }),
|
|
788
800
|
{ a: { b: 'c', d: true } },
|
|
789
801
|
'can add keys to objects'
|
|
790
802
|
);
|
|
791
803
|
|
|
792
804
|
st.deepEqual(
|
|
793
|
-
qs.parse('a[b]=c&a=toString'),
|
|
805
|
+
qs.parse('a[b]=c&a=toString', { strictMerge: false }),
|
|
794
806
|
{ a: { b: 'c' } },
|
|
795
807
|
'can not overwrite prototype'
|
|
796
808
|
);
|
|
797
809
|
|
|
798
810
|
st.deepEqual(
|
|
799
|
-
qs.parse('a[b]=c&a=toString', { allowPrototypes: true }),
|
|
811
|
+
qs.parse('a[b]=c&a=toString', { strictMerge: false, allowPrototypes: true }),
|
|
800
812
|
{ a: { b: 'c', toString: true } },
|
|
801
813
|
'can overwrite prototype with allowPrototypes true'
|
|
802
814
|
);
|
|
803
815
|
|
|
804
816
|
st.deepEqual(
|
|
805
|
-
qs.parse('a[b]=c&a=toString', { plainObjects: true }),
|
|
817
|
+
qs.parse('a[b]=c&a=toString', { strictMerge: false, plainObjects: true }),
|
|
806
818
|
{ __proto__: null, a: { __proto__: null, b: 'c', toString: true } },
|
|
807
819
|
'can overwrite prototype with plainObjects true'
|
|
808
820
|
);
|
|
@@ -810,6 +822,34 @@ test('parse()', function (t) {
|
|
|
810
822
|
st.end();
|
|
811
823
|
});
|
|
812
824
|
|
|
825
|
+
t.test('strictMerge wraps object and primitive into an array', function (st) {
|
|
826
|
+
st.deepEqual(
|
|
827
|
+
qs.parse('a[b]=c&a=d'),
|
|
828
|
+
{ a: [{ b: 'c' }, 'd'] },
|
|
829
|
+
'object then primitive produces array'
|
|
830
|
+
);
|
|
831
|
+
|
|
832
|
+
st.deepEqual(
|
|
833
|
+
qs.parse('a=d&a[b]=c'),
|
|
834
|
+
{ a: ['d', { b: 'c' }] },
|
|
835
|
+
'primitive then object produces array'
|
|
836
|
+
);
|
|
837
|
+
|
|
838
|
+
st.deepEqual(
|
|
839
|
+
qs.parse('a[b]=c&a=toString'),
|
|
840
|
+
{ a: [{ b: 'c' }, 'toString'] },
|
|
841
|
+
'prototype-colliding value is preserved in array'
|
|
842
|
+
);
|
|
843
|
+
|
|
844
|
+
st.deepEqual(
|
|
845
|
+
qs.parse('a[b]=c&a=toString', { plainObjects: true }),
|
|
846
|
+
{ __proto__: null, a: [{ __proto__: null, b: 'c' }, 'toString'] },
|
|
847
|
+
'plainObjects preserved in array wrapping'
|
|
848
|
+
);
|
|
849
|
+
|
|
850
|
+
st.end();
|
|
851
|
+
});
|
|
852
|
+
|
|
813
853
|
t.test('dunder proto is ignored', function (st) {
|
|
814
854
|
var payload = 'categories[__proto__]=login&categories[__proto__]&categories[length]=42';
|
|
815
855
|
var result = qs.parse(payload, { allowPrototypes: true });
|
|
@@ -996,6 +1036,20 @@ test('parse()', function (t) {
|
|
|
996
1036
|
st.end();
|
|
997
1037
|
});
|
|
998
1038
|
|
|
1039
|
+
t.test('handles a custom decoder returning `null`, with a string key of `null`', function (st) {
|
|
1040
|
+
st.deepEqual(
|
|
1041
|
+
qs.parse('null=1&ToNull=2', {
|
|
1042
|
+
decoder: function (str, defaultDecoder, charset) {
|
|
1043
|
+
return str === 'ToNull' ? null : defaultDecoder(str, defaultDecoder, charset);
|
|
1044
|
+
}
|
|
1045
|
+
}),
|
|
1046
|
+
{ 'null': '1' },
|
|
1047
|
+
'"null" key is not overridden by `null` decoder result'
|
|
1048
|
+
);
|
|
1049
|
+
|
|
1050
|
+
st.end();
|
|
1051
|
+
});
|
|
1052
|
+
|
|
999
1053
|
t.test('does not interpret numeric entities in iso-8859-1 when `interpretNumericEntities` is absent', function (st) {
|
|
1000
1054
|
st.deepEqual(qs.parse('foo=' + urlEncodedNumSmiley, { charset: 'iso-8859-1' }), { foo: '☺' });
|
|
1001
1055
|
st.end();
|
|
@@ -1032,6 +1086,15 @@ test('parse()', function (t) {
|
|
|
1032
1086
|
};
|
|
1033
1087
|
|
|
1034
1088
|
st.deepEqual(qs.parse('KeY=vAlUe', { decoder: decoder }), { key: 'VALUE' });
|
|
1089
|
+
|
|
1090
|
+
var noopDecoder = function () { return 'x'; };
|
|
1091
|
+
noopDecoder();
|
|
1092
|
+
st['throws'](
|
|
1093
|
+
function () { decoder('x', noopDecoder, 'utf-8', 'unknown'); },
|
|
1094
|
+
'this should never happen! type: unknown',
|
|
1095
|
+
'decoder throws for unexpected type'
|
|
1096
|
+
);
|
|
1097
|
+
|
|
1035
1098
|
st.end();
|
|
1036
1099
|
});
|
|
1037
1100
|
|
|
@@ -1061,6 +1124,14 @@ test('parse()', function (t) {
|
|
|
1061
1124
|
new RangeError('Parameter limit exceeded. Only 3 parameters allowed.'),
|
|
1062
1125
|
'throws error when parameter limit is exceeded'
|
|
1063
1126
|
);
|
|
1127
|
+
|
|
1128
|
+
sst['throws'](
|
|
1129
|
+
function () {
|
|
1130
|
+
qs.parse('a=1&b=2', { parameterLimit: 1, throwOnLimitExceeded: true });
|
|
1131
|
+
},
|
|
1132
|
+
new RangeError('Parameter limit exceeded. Only 1 parameter allowed.'),
|
|
1133
|
+
'throws error with singular "parameter" when parameterLimit is 1'
|
|
1134
|
+
);
|
|
1064
1135
|
sst.end();
|
|
1065
1136
|
});
|
|
1066
1137
|
|
|
@@ -1082,6 +1153,12 @@ test('parse()', function (t) {
|
|
|
1082
1153
|
sst.end();
|
|
1083
1154
|
});
|
|
1084
1155
|
|
|
1156
|
+
st.test('allows unlimited parameters when parameterLimit is Infinity and throwOnLimitExceeded is true', function (sst) {
|
|
1157
|
+
var result = qs.parse('a=1&b=2&c=3&d=4&e=5&f=6', { parameterLimit: Infinity, throwOnLimitExceeded: true });
|
|
1158
|
+
sst.deepEqual(result, { a: '1', b: '2', c: '3', d: '4', e: '5', f: '6' }, 'parses all parameters without truncation or throwing');
|
|
1159
|
+
sst.end();
|
|
1160
|
+
});
|
|
1161
|
+
|
|
1085
1162
|
st.end();
|
|
1086
1163
|
});
|
|
1087
1164
|
|
|
@@ -1104,6 +1181,7 @@ test('parse()', function (t) {
|
|
|
1104
1181
|
});
|
|
1105
1182
|
|
|
1106
1183
|
st.test('throws error when array limit exceeded', function (sst) {
|
|
1184
|
+
// 4 elements exceeds limit of 3
|
|
1107
1185
|
sst['throws'](
|
|
1108
1186
|
function () {
|
|
1109
1187
|
qs.parse('a[]=1&a[]=2&a[]=3&a[]=4', { arrayLimit: 3, throwOnLimitExceeded: true });
|
|
@@ -1114,6 +1192,14 @@ test('parse()', function (t) {
|
|
|
1114
1192
|
sst.end();
|
|
1115
1193
|
});
|
|
1116
1194
|
|
|
1195
|
+
st.test('does not throw when at limit', function (sst) {
|
|
1196
|
+
// 3 elements = limit of 3, should not throw
|
|
1197
|
+
var result = qs.parse('a[]=1&a[]=2&a[]=3', { arrayLimit: 3, throwOnLimitExceeded: true });
|
|
1198
|
+
sst.ok(Array.isArray(result.a), 'result is an array');
|
|
1199
|
+
sst.deepEqual(result.a, ['1', '2', '3'], 'all values present');
|
|
1200
|
+
sst.end();
|
|
1201
|
+
});
|
|
1202
|
+
|
|
1117
1203
|
st.test('converts array to object if length is greater than limit', function (sst) {
|
|
1118
1204
|
var result = qs.parse('a[1]=1&a[2]=2&a[3]=3&a[4]=4&a[5]=5&a[6]=6', { arrayLimit: 5 });
|
|
1119
1205
|
|
|
@@ -1121,6 +1207,59 @@ test('parse()', function (t) {
|
|
|
1121
1207
|
sst.end();
|
|
1122
1208
|
});
|
|
1123
1209
|
|
|
1210
|
+
st.test('throws error when indexed notation exceeds arrayLimit with throwOnLimitExceeded', function (sst) {
|
|
1211
|
+
sst['throws'](
|
|
1212
|
+
function () {
|
|
1213
|
+
qs.parse('a[1001]=b', { arrayLimit: 1000, throwOnLimitExceeded: true });
|
|
1214
|
+
},
|
|
1215
|
+
new RangeError('Array limit exceeded. Only 1000 elements allowed in an array.'),
|
|
1216
|
+
'throws error for a single index exceeding arrayLimit'
|
|
1217
|
+
);
|
|
1218
|
+
|
|
1219
|
+
sst['throws'](
|
|
1220
|
+
function () {
|
|
1221
|
+
qs.parse('a[0]=1&a[1]=2&a[2]=3&a[10]=4', { arrayLimit: 6, throwOnLimitExceeded: true, allowSparse: true });
|
|
1222
|
+
},
|
|
1223
|
+
new RangeError('Array limit exceeded. Only 6 elements allowed in an array.'),
|
|
1224
|
+
'throws error when a sparse index exceeds arrayLimit'
|
|
1225
|
+
);
|
|
1226
|
+
|
|
1227
|
+
sst['throws'](
|
|
1228
|
+
function () {
|
|
1229
|
+
qs.parse('a[2]=b', { arrayLimit: 1, throwOnLimitExceeded: true });
|
|
1230
|
+
},
|
|
1231
|
+
new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
|
|
1232
|
+
'throws error with singular "element" when arrayLimit is 1'
|
|
1233
|
+
);
|
|
1234
|
+
|
|
1235
|
+
sst.end();
|
|
1236
|
+
});
|
|
1237
|
+
|
|
1238
|
+
st.test('does not throw for indexed notation within arrayLimit with throwOnLimitExceeded', function (sst) {
|
|
1239
|
+
var result = qs.parse('a[4]=b', { arrayLimit: 5, throwOnLimitExceeded: true, allowSparse: true });
|
|
1240
|
+
sst.ok(Array.isArray(result.a), 'result is an array');
|
|
1241
|
+
sst.equal(result.a.length, 5, 'array has correct length');
|
|
1242
|
+
sst.equal(result.a[4], 'b', 'value at index 4 is correct');
|
|
1243
|
+
sst.end();
|
|
1244
|
+
});
|
|
1245
|
+
|
|
1246
|
+
st.test('silently converts to object for indexed notation exceeding arrayLimit without throwOnLimitExceeded', function (sst) {
|
|
1247
|
+
var result = qs.parse('a[1001]=b', { arrayLimit: 1000 });
|
|
1248
|
+
sst.deepEqual(result, { a: { 1001: 'b' } }, 'converts to object without throwing');
|
|
1249
|
+
sst.end();
|
|
1250
|
+
});
|
|
1251
|
+
|
|
1252
|
+
st.test('throws when duplicate bracket keys exceed arrayLimit with throwOnLimitExceeded', function (sst) {
|
|
1253
|
+
sst['throws'](
|
|
1254
|
+
function () {
|
|
1255
|
+
qs.parse('a[]=1&a[]=2&a[]=3&a[]=4&a[]=5&a[]=6', { arrayLimit: 5, throwOnLimitExceeded: true });
|
|
1256
|
+
},
|
|
1257
|
+
new RangeError('Array limit exceeded. Only 5 elements allowed in an array.'),
|
|
1258
|
+
'throws error when duplicate bracket notation exceeds array limit'
|
|
1259
|
+
);
|
|
1260
|
+
sst.end();
|
|
1261
|
+
});
|
|
1262
|
+
|
|
1124
1263
|
st.end();
|
|
1125
1264
|
});
|
|
1126
1265
|
|
|
@@ -1172,6 +1311,34 @@ test('`duplicates` option', function (t) {
|
|
|
1172
1311
|
'duplicates: last'
|
|
1173
1312
|
);
|
|
1174
1313
|
|
|
1314
|
+
t.test('bracket notation always combines regardless of duplicates', function (st) {
|
|
1315
|
+
st.deepEqual(
|
|
1316
|
+
qs.parse('a=1&a=2&b[]=1&b[]=2', { duplicates: 'last' }),
|
|
1317
|
+
{ a: '2', b: ['1', '2'] },
|
|
1318
|
+
'duplicates last: unbracketed takes last, bracketed combines'
|
|
1319
|
+
);
|
|
1320
|
+
|
|
1321
|
+
st.deepEqual(
|
|
1322
|
+
qs.parse('b[]=1&b[]=2', { duplicates: 'last' }),
|
|
1323
|
+
{ b: ['1', '2'] },
|
|
1324
|
+
'duplicates last: bracketed always combines'
|
|
1325
|
+
);
|
|
1326
|
+
|
|
1327
|
+
st.deepEqual(
|
|
1328
|
+
qs.parse('b[]=1&b[]=2', { duplicates: 'first' }),
|
|
1329
|
+
{ b: ['1', '2'] },
|
|
1330
|
+
'duplicates first: bracketed always combines'
|
|
1331
|
+
);
|
|
1332
|
+
|
|
1333
|
+
st.deepEqual(
|
|
1334
|
+
qs.parse('a=1&a=2&b[]=1&b[]=2', { duplicates: 'first' }),
|
|
1335
|
+
{ a: '1', b: ['1', '2'] },
|
|
1336
|
+
'duplicates first: unbracketed takes first, bracketed combines'
|
|
1337
|
+
);
|
|
1338
|
+
|
|
1339
|
+
st.end();
|
|
1340
|
+
});
|
|
1341
|
+
|
|
1175
1342
|
t.end();
|
|
1176
1343
|
});
|
|
1177
1344
|
|
|
@@ -1274,3 +1441,214 @@ test('qs strictDepth option - non-throw cases', function (t) {
|
|
|
1274
1441
|
st.end();
|
|
1275
1442
|
});
|
|
1276
1443
|
});
|
|
1444
|
+
|
|
1445
|
+
test('DOS', function (t) {
|
|
1446
|
+
var arr = [];
|
|
1447
|
+
for (var i = 0; i < 105; i++) {
|
|
1448
|
+
arr[arr.length] = 'x';
|
|
1449
|
+
}
|
|
1450
|
+
var attack = 'a[]=' + arr.join('&a[]=');
|
|
1451
|
+
var result = qs.parse(attack, { arrayLimit: 100 });
|
|
1452
|
+
|
|
1453
|
+
t.notOk(Array.isArray(result.a), 'arrayLimit is respected: result is an object, not an array');
|
|
1454
|
+
t.equal(Object.keys(result.a).length, 105, 'all values are preserved');
|
|
1455
|
+
|
|
1456
|
+
t.end();
|
|
1457
|
+
});
|
|
1458
|
+
|
|
1459
|
+
test('arrayLimit boundary conditions', function (t) {
|
|
1460
|
+
// arrayLimit is the max number of elements allowed in an array
|
|
1461
|
+
t.test('exactly at the limit stays as array', function (st) {
|
|
1462
|
+
// 3 elements = limit of 3
|
|
1463
|
+
var result = qs.parse('a[]=1&a[]=2&a[]=3', { arrayLimit: 3 });
|
|
1464
|
+
st.ok(Array.isArray(result.a), 'result is an array when count equals limit');
|
|
1465
|
+
st.deepEqual(result.a, ['1', '2', '3'], 'all values present');
|
|
1466
|
+
st.end();
|
|
1467
|
+
});
|
|
1468
|
+
|
|
1469
|
+
t.test('one over the limit converts to object', function (st) {
|
|
1470
|
+
// 4 elements exceeds limit of 3
|
|
1471
|
+
var result = qs.parse('a[]=1&a[]=2&a[]=3&a[]=4', { arrayLimit: 3 });
|
|
1472
|
+
st.notOk(Array.isArray(result.a), 'result is not an array when over limit');
|
|
1473
|
+
st.deepEqual(result.a, { 0: '1', 1: '2', 2: '3', 3: '4' }, 'all values preserved as object');
|
|
1474
|
+
st.end();
|
|
1475
|
+
});
|
|
1476
|
+
|
|
1477
|
+
t.test('arrayLimit 1 with one value', function (st) {
|
|
1478
|
+
// 1 element = limit of 1
|
|
1479
|
+
var result = qs.parse('a[]=1', { arrayLimit: 1 });
|
|
1480
|
+
st.ok(Array.isArray(result.a), 'result is an array when count equals limit');
|
|
1481
|
+
st.deepEqual(result.a, ['1'], 'value preserved as array');
|
|
1482
|
+
st.end();
|
|
1483
|
+
});
|
|
1484
|
+
|
|
1485
|
+
t.test('arrayLimit 1 with two values converts to object', function (st) {
|
|
1486
|
+
// 2 elements exceeds limit of 1
|
|
1487
|
+
var result = qs.parse('a[]=1&a[]=2', { arrayLimit: 1 });
|
|
1488
|
+
st.notOk(Array.isArray(result.a), 'result is not an array');
|
|
1489
|
+
st.deepEqual(result.a, { 0: '1', 1: '2' }, 'all values preserved as object');
|
|
1490
|
+
st.end();
|
|
1491
|
+
});
|
|
1492
|
+
|
|
1493
|
+
t.end();
|
|
1494
|
+
});
|
|
1495
|
+
|
|
1496
|
+
test('comma + arrayLimit', function (t) {
|
|
1497
|
+
t.test('comma-separated values within arrayLimit stay as array', function (st) {
|
|
1498
|
+
var result = qs.parse('a=1,2,3', { comma: true, arrayLimit: 5 });
|
|
1499
|
+
st.ok(Array.isArray(result.a), 'result is an array');
|
|
1500
|
+
st.deepEqual(result.a, ['1', '2', '3'], 'all values present');
|
|
1501
|
+
st.end();
|
|
1502
|
+
});
|
|
1503
|
+
|
|
1504
|
+
t.test('comma-separated values exceeding arrayLimit convert to object', function (st) {
|
|
1505
|
+
var result = qs.parse('a=1,2,3,4', { comma: true, arrayLimit: 3 });
|
|
1506
|
+
st.notOk(Array.isArray(result.a), 'result is not an array when over limit');
|
|
1507
|
+
st.deepEqual(result.a, { 0: '1', 1: '2', 2: '3', 3: '4' }, 'all values preserved as object');
|
|
1508
|
+
st.end();
|
|
1509
|
+
});
|
|
1510
|
+
|
|
1511
|
+
t.test('comma-separated values exceeding arrayLimit with throwOnLimitExceeded throws', function (st) {
|
|
1512
|
+
st['throws'](
|
|
1513
|
+
function () {
|
|
1514
|
+
qs.parse('a=1,2,3,4', { comma: true, arrayLimit: 3, throwOnLimitExceeded: true });
|
|
1515
|
+
},
|
|
1516
|
+
new RangeError('Array limit exceeded. Only 3 elements allowed in an array.'),
|
|
1517
|
+
'throws error when comma-split exceeds array limit'
|
|
1518
|
+
);
|
|
1519
|
+
|
|
1520
|
+
st['throws'](
|
|
1521
|
+
function () {
|
|
1522
|
+
qs.parse('a=1,2,3', { comma: true, arrayLimit: 1, throwOnLimitExceeded: true });
|
|
1523
|
+
},
|
|
1524
|
+
new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
|
|
1525
|
+
'throws error with singular "element" when arrayLimit is 1'
|
|
1526
|
+
);
|
|
1527
|
+
st.end();
|
|
1528
|
+
});
|
|
1529
|
+
|
|
1530
|
+
t.test('comma-separated values at exactly arrayLimit stay as array', function (st) {
|
|
1531
|
+
var result = qs.parse('a=1,2,3', { comma: true, arrayLimit: 3 });
|
|
1532
|
+
st.ok(Array.isArray(result.a), 'result is an array when exactly at limit');
|
|
1533
|
+
st.deepEqual(result.a, ['1', '2', '3'], 'all values present');
|
|
1534
|
+
st.end();
|
|
1535
|
+
});
|
|
1536
|
+
|
|
1537
|
+
t.end();
|
|
1538
|
+
});
|
|
1539
|
+
|
|
1540
|
+
test('mixed array and object notation', function (t) {
|
|
1541
|
+
t.test('array brackets with object key - under limit', function (st) {
|
|
1542
|
+
st.deepEqual(
|
|
1543
|
+
qs.parse('a[]=b&a[c]=d'),
|
|
1544
|
+
{ a: { 0: 'b', c: 'd' } },
|
|
1545
|
+
'mixing [] and [key] converts to object'
|
|
1546
|
+
);
|
|
1547
|
+
st.end();
|
|
1548
|
+
});
|
|
1549
|
+
|
|
1550
|
+
t.test('array index with object key - under limit', function (st) {
|
|
1551
|
+
st.deepEqual(
|
|
1552
|
+
qs.parse('a[0]=b&a[c]=d'),
|
|
1553
|
+
{ a: { 0: 'b', c: 'd' } },
|
|
1554
|
+
'mixing [0] and [key] produces object'
|
|
1555
|
+
);
|
|
1556
|
+
st.end();
|
|
1557
|
+
});
|
|
1558
|
+
|
|
1559
|
+
t.test('plain value with array brackets - under limit', function (st) {
|
|
1560
|
+
st.deepEqual(
|
|
1561
|
+
qs.parse('a=b&a[]=c', { arrayLimit: 20 }),
|
|
1562
|
+
{ a: ['b', 'c'] },
|
|
1563
|
+
'plain value combined with [] stays as array under limit'
|
|
1564
|
+
);
|
|
1565
|
+
st.end();
|
|
1566
|
+
});
|
|
1567
|
+
|
|
1568
|
+
t.test('array brackets with plain value - under limit', function (st) {
|
|
1569
|
+
st.deepEqual(
|
|
1570
|
+
qs.parse('a[]=b&a=c', { arrayLimit: 20 }),
|
|
1571
|
+
{ a: ['b', 'c'] },
|
|
1572
|
+
'[] combined with plain value stays as array under limit'
|
|
1573
|
+
);
|
|
1574
|
+
st.end();
|
|
1575
|
+
});
|
|
1576
|
+
|
|
1577
|
+
t.test('plain value with array index - under limit', function (st) {
|
|
1578
|
+
st.deepEqual(
|
|
1579
|
+
qs.parse('a=b&a[0]=c', { arrayLimit: 20 }),
|
|
1580
|
+
{ a: ['b', 'c'] },
|
|
1581
|
+
'plain value combined with [0] stays as array under limit'
|
|
1582
|
+
);
|
|
1583
|
+
st.end();
|
|
1584
|
+
});
|
|
1585
|
+
|
|
1586
|
+
t.test('multiple plain values with duplicates combine', function (st) {
|
|
1587
|
+
st.deepEqual(
|
|
1588
|
+
qs.parse('a=b&a=c&a=d', { arrayLimit: 20 }),
|
|
1589
|
+
{ a: ['b', 'c', 'd'] },
|
|
1590
|
+
'duplicate plain keys combine into array'
|
|
1591
|
+
);
|
|
1592
|
+
st.end();
|
|
1593
|
+
});
|
|
1594
|
+
|
|
1595
|
+
t.test('multiple plain values exceeding limit', function (st) {
|
|
1596
|
+
// 3 elements (indices 0-2), max index 2 > limit 1
|
|
1597
|
+
st.deepEqual(
|
|
1598
|
+
qs.parse('a=b&a=c&a=d', { arrayLimit: 1 }),
|
|
1599
|
+
{ a: { 0: 'b', 1: 'c', 2: 'd' } },
|
|
1600
|
+
'duplicate plain keys convert to object when exceeding limit'
|
|
1601
|
+
);
|
|
1602
|
+
st.end();
|
|
1603
|
+
});
|
|
1604
|
+
|
|
1605
|
+
t.test('mixed notation produces consistent results when arrayLimit is exceeded', function (st) {
|
|
1606
|
+
var expected = { a: { 0: 'b', 1: 'c', 2: 'd' } };
|
|
1607
|
+
|
|
1608
|
+
st.deepEqual(
|
|
1609
|
+
qs.parse('a[]=b&a[1]=c&a=d', { arrayLimit: -1 }),
|
|
1610
|
+
expected,
|
|
1611
|
+
'arrayLimit -1'
|
|
1612
|
+
);
|
|
1613
|
+
|
|
1614
|
+
st.deepEqual(
|
|
1615
|
+
qs.parse('a[]=b&a[1]=c&a=d', { arrayLimit: 0 }),
|
|
1616
|
+
expected,
|
|
1617
|
+
'arrayLimit 0'
|
|
1618
|
+
);
|
|
1619
|
+
|
|
1620
|
+
st.deepEqual(
|
|
1621
|
+
qs.parse('a[]=b&a[1]=c&a=d', { arrayLimit: 1 }),
|
|
1622
|
+
expected,
|
|
1623
|
+
'arrayLimit 1'
|
|
1624
|
+
);
|
|
1625
|
+
|
|
1626
|
+
st.end();
|
|
1627
|
+
});
|
|
1628
|
+
|
|
1629
|
+
t.test('uses existing array length for currentArrayLength when parsing object input with bracket keys', function (st) {
|
|
1630
|
+
var input = {};
|
|
1631
|
+
var arr = ['x', 'y'];
|
|
1632
|
+
arr.a = ['z', 'w'];
|
|
1633
|
+
input['a[]'] = arr;
|
|
1634
|
+
st.deepEqual(qs.parse(input), { a: ['x', 'y'] }, 'parses object input with bracket keys using existing array values');
|
|
1635
|
+
st.end();
|
|
1636
|
+
});
|
|
1637
|
+
|
|
1638
|
+
t.test('throws with singular message when object input bracket key exceeds arrayLimit of 1', function (st) {
|
|
1639
|
+
var input = {};
|
|
1640
|
+
var arr = ['x'];
|
|
1641
|
+
arr.a = ['z', 'w'];
|
|
1642
|
+
input['a[]'] = arr;
|
|
1643
|
+
st['throws'](
|
|
1644
|
+
function () {
|
|
1645
|
+
qs.parse(input, { throwOnLimitExceeded: true, arrayLimit: 1 });
|
|
1646
|
+
},
|
|
1647
|
+
new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
|
|
1648
|
+
'throws singular error for object input exceeding arrayLimit 1'
|
|
1649
|
+
);
|
|
1650
|
+
st.end();
|
|
1651
|
+
});
|
|
1652
|
+
|
|
1653
|
+
t.end();
|
|
1654
|
+
});
|
|
@@ -1188,6 +1188,15 @@ test('stringify()', function (t) {
|
|
|
1188
1188
|
};
|
|
1189
1189
|
|
|
1190
1190
|
st.deepEqual(qs.stringify({ KeY: 'vAlUe' }, { encoder: encoder }), 'key=VALUE');
|
|
1191
|
+
|
|
1192
|
+
var noopEncoder = function () { return 'x'; };
|
|
1193
|
+
noopEncoder();
|
|
1194
|
+
st['throws'](
|
|
1195
|
+
function () { encoder('x', noopEncoder, 'utf-8', 'unknown'); },
|
|
1196
|
+
'this should never happen! type: unknown',
|
|
1197
|
+
'encoder throws for unexpected type'
|
|
1198
|
+
);
|
|
1199
|
+
|
|
1191
1200
|
st.end();
|
|
1192
1201
|
});
|
|
1193
1202
|
|
|
@@ -1293,13 +1302,17 @@ test('stringifies empty keys', function (t) {
|
|
|
1293
1302
|
});
|
|
1294
1303
|
|
|
1295
1304
|
t.test('stringifies non-string keys', function (st) {
|
|
1296
|
-
var
|
|
1297
|
-
|
|
1305
|
+
var S = Object('abc');
|
|
1306
|
+
S.toString = function () {
|
|
1307
|
+
return 'd';
|
|
1308
|
+
};
|
|
1309
|
+
var actual = qs.stringify({ a: 'b', 'false': {}, 1e+22: 'c', d: 'e' }, {
|
|
1310
|
+
filter: ['a', false, null, 10000000000000000000000, S],
|
|
1298
1311
|
allowDots: true,
|
|
1299
1312
|
encodeDotInKeys: true
|
|
1300
1313
|
});
|
|
1301
1314
|
|
|
1302
|
-
st.equal(actual, 'a=b', 'stringifies correctly');
|
|
1315
|
+
st.equal(actual, 'a=b&1e%2B22=c&d=e', 'stringifies correctly');
|
|
1303
1316
|
|
|
1304
1317
|
st.end();
|
|
1305
1318
|
});
|