fast-json-stringify 6.0.0 → 6.0.1

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.
Files changed (65) hide show
  1. package/.github/dependabot.yml +1 -1
  2. package/.github/workflows/benchmark.yml +3 -3
  3. package/.github/workflows/ci.yml +1 -1
  4. package/README.md +15 -15
  5. package/benchmark/bench-cmp-lib.js +0 -1
  6. package/eslint.config.js +9 -0
  7. package/index.js +4 -8
  8. package/lib/serializer.js +1 -2
  9. package/lib/validator.js +1 -1
  10. package/package.json +40 -16
  11. package/test/additionalProperties.test.js +20 -20
  12. package/test/allof.test.js +36 -40
  13. package/test/any.test.js +28 -28
  14. package/test/anyof.test.js +44 -46
  15. package/test/array.test.js +19 -19
  16. package/test/asNumber.test.js +2 -2
  17. package/test/basic.test.js +20 -32
  18. package/test/bigint.test.js +6 -6
  19. package/test/clean-cache.test.js +9 -7
  20. package/test/const.test.js +35 -35
  21. package/test/date.test.js +77 -77
  22. package/test/debug-mode.test.js +27 -27
  23. package/test/defaults.test.js +2 -2
  24. package/test/enum.test.js +3 -3
  25. package/test/fix-604.test.js +18 -17
  26. package/test/if-then-else.test.js +22 -24
  27. package/test/inferType.test.js +4 -4
  28. package/test/infinity.test.js +4 -4
  29. package/test/integer.test.js +21 -21
  30. package/test/invalidSchema.test.js +4 -8
  31. package/test/issue-479.test.js +2 -2
  32. package/test/json-schema-test-suite/draft4.test.js +3 -3
  33. package/test/json-schema-test-suite/draft6.test.js +3 -3
  34. package/test/json-schema-test-suite/draft7.test.js +3 -3
  35. package/test/json-schema-test-suite/util.js +6 -9
  36. package/test/missing-values.test.js +8 -8
  37. package/test/multi-type-serializer.test.js +2 -2
  38. package/test/nestedObjects.test.js +3 -3
  39. package/test/nullable.test.js +35 -35
  40. package/test/oneof.test.js +27 -29
  41. package/test/patternProperties.test.js +11 -11
  42. package/test/recursion.test.js +6 -6
  43. package/test/ref.test.js +102 -186
  44. package/test/regex.test.js +4 -5
  45. package/test/required.test.js +42 -77
  46. package/test/requiresAjv.test.js +34 -32
  47. package/test/sanitize.test.js +40 -41
  48. package/test/sanitize2.test.js +11 -11
  49. package/test/sanitize3.test.js +13 -11
  50. package/test/sanitize4.test.js +10 -8
  51. package/test/sanitize5.test.js +11 -11
  52. package/test/sanitize6.test.js +14 -14
  53. package/test/sanitize7.test.js +5 -5
  54. package/test/side-effect.test.js +12 -12
  55. package/test/standalone-mode.test.js +29 -26
  56. package/test/string.test.js +12 -12
  57. package/test/surrogate.test.js +9 -9
  58. package/test/toJSON.test.js +9 -9
  59. package/test/typebox.test.js +2 -2
  60. package/test/typesArray.test.js +34 -34
  61. package/test/unknownFormats.test.js +5 -5
  62. package/test/webpack.test.js +2 -2
  63. package/types/index.d.ts +29 -29
  64. package/types/index.test-d.ts +75 -74
  65. package/.taprc +0 -7
@@ -1,10 +1,10 @@
1
1
  'use strict'
2
2
 
3
- const test = require('tap').test
3
+ const { test } = require('node:test')
4
4
  const build = require('..')
5
5
 
6
6
  test('object with required field', (t) => {
7
- t.plan(3)
7
+ t.plan(2)
8
8
 
9
9
  const schema = {
10
10
  title: 'object with required field',
@@ -21,24 +21,21 @@ test('object with required field', (t) => {
21
21
  }
22
22
  const stringify = build(schema)
23
23
 
24
- stringify({
25
- str: 'string'
24
+ t.assert.doesNotThrow(() => {
25
+ stringify({
26
+ str: 'string'
27
+ })
26
28
  })
27
- t.pass()
28
29
 
29
- try {
30
+ t.assert.throws(() => {
30
31
  stringify({
31
32
  num: 42
32
33
  })
33
- t.fail()
34
- } catch (e) {
35
- t.equal(e.message, '"str" is required!')
36
- t.pass()
37
- }
34
+ }, { message: '"str" is required!' })
38
35
  })
39
36
 
40
37
  test('object with required field not in properties schema', (t) => {
41
- t.plan(4)
38
+ t.plan(2)
42
39
 
43
40
  const schema = {
44
41
  title: 'object with required field',
@@ -52,27 +49,19 @@ test('object with required field not in properties schema', (t) => {
52
49
  }
53
50
  const stringify = build(schema)
54
51
 
55
- try {
52
+ t.assert.throws(() => {
56
53
  stringify({})
57
- t.fail()
58
- } catch (e) {
59
- t.equal(e.message, '"str" is required!')
60
- t.pass()
61
- }
54
+ }, { message: '"str" is required!' })
62
55
 
63
- try {
56
+ t.assert.throws(() => {
64
57
  stringify({
65
58
  num: 42
66
59
  })
67
- t.fail()
68
- } catch (e) {
69
- t.equal(e.message, '"str" is required!')
70
- t.pass()
71
- }
60
+ }, { message: '"str" is required!' })
72
61
  })
73
62
 
74
63
  test('object with required field not in properties schema with additional properties true', (t) => {
75
- t.plan(4)
64
+ t.plan(2)
76
65
 
77
66
  const schema = {
78
67
  title: 'object with required field',
@@ -87,27 +76,19 @@ test('object with required field not in properties schema with additional proper
87
76
  }
88
77
  const stringify = build(schema)
89
78
 
90
- try {
79
+ t.assert.throws(() => {
91
80
  stringify({})
92
- t.fail()
93
- } catch (e) {
94
- t.equal(e.message, '"str" is required!')
95
- t.pass()
96
- }
81
+ }, { message: '"str" is required!' })
97
82
 
98
- try {
83
+ t.assert.throws(() => {
99
84
  stringify({
100
85
  num: 42
101
86
  })
102
- t.fail()
103
- } catch (e) {
104
- t.equal(e.message, '"str" is required!')
105
- t.pass()
106
- }
87
+ }, { message: '"str" is required!' })
107
88
  })
108
89
 
109
90
  test('object with multiple required field not in properties schema', (t) => {
110
- t.plan(6)
91
+ t.plan(3)
111
92
 
112
93
  const schema = {
113
94
  title: 'object with required field',
@@ -122,35 +103,23 @@ test('object with multiple required field not in properties schema', (t) => {
122
103
  }
123
104
  const stringify = build(schema)
124
105
 
125
- try {
106
+ t.assert.throws(() => {
126
107
  stringify({})
127
- t.fail()
128
- } catch (e) {
129
- t.equal(e.message, '"key1" is required!')
130
- t.pass()
131
- }
108
+ }, { message: '"key1" is required!' })
132
109
 
133
- try {
110
+ t.assert.throws(() => {
134
111
  stringify({
135
112
  key1: 42,
136
113
  key2: 42
137
114
  })
138
- t.fail()
139
- } catch (e) {
140
- t.equal(e.message, '"num" is required!')
141
- t.pass()
142
- }
115
+ }, { message: '"num" is required!' })
143
116
 
144
- try {
117
+ t.assert.throws(() => {
145
118
  stringify({
146
119
  num: 42,
147
120
  key1: 'some'
148
121
  })
149
- t.fail()
150
- } catch (e) {
151
- t.equal(e.message, '"key2" is required!')
152
- t.pass()
153
- }
122
+ }, { message: '"key2" is required!' })
154
123
  })
155
124
 
156
125
  test('object with required bool', (t) => {
@@ -169,16 +138,14 @@ test('object with required bool', (t) => {
169
138
  }
170
139
  const stringify = build(schema)
171
140
 
172
- try {
141
+ t.assert.throws(() => {
173
142
  stringify({})
174
- t.fail()
175
- } catch (e) {
176
- t.equal(e.message, '"bool" is required!')
177
- t.pass()
178
- }
143
+ }, { message: '"bool" is required!' })
179
144
 
180
- stringify({
181
- bool: false
145
+ t.assert.doesNotThrow(() => {
146
+ stringify({
147
+ bool: false
148
+ })
182
149
  })
183
150
  })
184
151
 
@@ -198,14 +165,15 @@ test('required nullable', (t) => {
198
165
  }
199
166
  const stringify = build(schema)
200
167
 
201
- stringify({
202
- null: null
168
+ t.assert.doesNotThrow(() => {
169
+ stringify({
170
+ null: null
171
+ })
203
172
  })
204
- t.pass()
205
173
  })
206
174
 
207
175
  test('required numbers', (t) => {
208
- t.plan(3)
176
+ t.plan(2)
209
177
 
210
178
  const schema = {
211
179
  title: 'object with required field',
@@ -222,18 +190,15 @@ test('required numbers', (t) => {
222
190
  }
223
191
  const stringify = build(schema)
224
192
 
225
- stringify({
226
- num: 42
193
+ t.assert.doesNotThrow(() => {
194
+ stringify({
195
+ num: 42
196
+ })
227
197
  })
228
- t.pass()
229
198
 
230
- try {
199
+ t.assert.throws(() => {
231
200
  stringify({
232
201
  num: 'aaa'
233
202
  })
234
- t.fail()
235
- } catch (e) {
236
- t.equal(e.message, 'The value "aaa" cannot be converted to an integer.')
237
- t.pass()
238
- }
203
+ }, { message: 'The value "aaa" cannot be converted to an integer.' })
239
204
  })
@@ -1,48 +1,50 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
3
+ const { test } = require('node:test')
4
4
  const build = require('..')
5
5
 
6
- t.test('nested ref requires ajv', async t => {
7
- const schemaA = {
8
- $id: 'urn:schema:a',
9
- definitions: {
10
- foo: { anyOf: [{ type: 'string' }, { type: 'null' }] }
6
+ test('nested ref requires ajv', async t => {
7
+ t.test('nested ref requires ajv', async t => {
8
+ const schemaA = {
9
+ $id: 'urn:schema:a',
10
+ definitions: {
11
+ foo: { anyOf: [{ type: 'string' }, { type: 'null' }] }
12
+ }
11
13
  }
12
- }
13
14
 
14
- const schemaB = {
15
- $id: 'urn:schema:b',
16
- type: 'object',
17
- properties: {
18
- results: {
19
- type: 'object',
20
- properties: {
21
- items: {
22
- type: 'object',
23
- properties: {
24
- bar: {
25
- type: 'array',
26
- items: { $ref: 'urn:schema:a#/definitions/foo' }
15
+ const schemaB = {
16
+ $id: 'urn:schema:b',
17
+ type: 'object',
18
+ properties: {
19
+ results: {
20
+ type: 'object',
21
+ properties: {
22
+ items: {
23
+ type: 'object',
24
+ properties: {
25
+ bar: {
26
+ type: 'array',
27
+ items: { $ref: 'urn:schema:a#/definitions/foo' }
28
+ }
27
29
  }
28
30
  }
29
31
  }
30
32
  }
31
33
  }
32
34
  }
33
- }
34
35
 
35
- const stringify = build(schemaB, {
36
- schema: {
37
- [schemaA.$id]: schemaA
38
- }
39
- })
40
- const result = stringify({
41
- results: {
42
- items: {
43
- bar: ['baz']
36
+ const stringify = build(schemaB, {
37
+ schema: {
38
+ [schemaA.$id]: schemaA
44
39
  }
45
- }
40
+ })
41
+ const result = stringify({
42
+ results: {
43
+ items: {
44
+ bar: ['baz']
45
+ }
46
+ }
47
+ })
48
+ t.assert.equal(result, '{"results":{"items":{"bar":["baz"]}}}')
46
49
  })
47
- t.same(result, '{"results":{"items":{"bar":["baz"]}}}')
48
50
  })
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
3
+ const { test } = require('node:test')
4
4
  const build = require('..')
5
5
 
6
6
  const stringify = build({
@@ -91,52 +91,51 @@ const obj = {
91
91
  notmatchnum: 42
92
92
  }
93
93
 
94
- // pass if it does not crash
95
- const json = stringify(obj)
96
- JSON.parse(json)
94
+ test('sanitize', t => {
95
+ const json = stringify(obj)
96
+ t.assert.doesNotThrow(() => JSON.parse(json))
97
97
 
98
- const stringify2 = build({
99
- title: 'Example Schema',
100
- type: 'object',
101
- patternProperties: {
102
- '"\'w00t.*////': {
103
- type: 'number'
98
+ const stringify2 = build({
99
+ title: 'Example Schema',
100
+ type: 'object',
101
+ patternProperties: {
102
+ '"\'w00t.*////': {
103
+ type: 'number'
104
+ }
104
105
  }
105
- }
106
- })
106
+ })
107
107
 
108
- t.same(JSON.parse(stringify2({
109
- '"\'phra////': 42,
110
- asd: 42
111
- })), {
112
- })
108
+ t.assert.deepStrictEqual(JSON.parse(stringify2({
109
+ '"\'phra////': 42,
110
+ asd: 42
111
+ })), {
112
+ })
113
113
 
114
- const stringify3 = build({
115
- title: 'Example Schema',
116
- type: 'object',
117
- properties: {
118
- "\"phra\\'&&(console.log(42))//||'phra": {}
119
- }
120
- })
114
+ const stringify3 = build({
115
+ title: 'Example Schema',
116
+ type: 'object',
117
+ properties: {
118
+ "\"phra\\'&&(console.log(42))//||'phra": {}
119
+ }
120
+ })
121
121
 
122
- // this verifies the escaping
123
- JSON.parse(stringify3({
124
- '"phra\'&&(console.log(42))//||\'phra': 42
125
- }))
122
+ // this verifies the escaping
123
+ JSON.parse(stringify3({
124
+ '"phra\'&&(console.log(42))//||\'phra': 42
125
+ }))
126
126
 
127
- const stringify4 = build({
128
- title: 'Example Schema',
129
- type: 'object',
130
- properties: {
131
- '"\\\\\\\\\'w00t': {
132
- type: 'string',
133
- default: '"\'w00t'
127
+ const stringify4 = build({
128
+ title: 'Example Schema',
129
+ type: 'object',
130
+ properties: {
131
+ '"\\\\\\\\\'w00t': {
132
+ type: 'string',
133
+ default: '"\'w00t'
134
+ }
134
135
  }
135
- }
136
- })
136
+ })
137
137
 
138
- t.same(JSON.parse(stringify4({})), {
139
- '"\\\\\\\\\'w00t': '"\'w00t'
138
+ t.assert.deepStrictEqual(JSON.parse(stringify4({})), {
139
+ '"\\\\\\\\\'w00t': '"\'w00t'
140
+ })
140
141
  })
141
-
142
- t.pass('no crashes')
@@ -1,18 +1,18 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
3
+ const { test } = require('node:test')
4
4
  const build = require('..')
5
5
 
6
- const payload = '(throw "pwoned")'
6
+ test('sanitize 2', t => {
7
+ const payload = '(throw "pwoned")'
7
8
 
8
- const stringify = build({
9
- properties: {
10
- [`*///\\\\\\']);${payload};{/*`]: {
11
- type: 'number'
9
+ const stringify = build({
10
+ properties: {
11
+ [`*///\\\\\\']);${payload};{/*`]: {
12
+ type: 'number'
13
+ }
12
14
  }
13
- }
14
- })
15
-
16
- stringify({})
15
+ })
17
16
 
18
- t.pass('no crashes')
17
+ t.assert.doesNotThrow(() => stringify({}))
18
+ })
@@ -1,15 +1,17 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
3
+ const { test } = require('node:test')
4
4
  const build = require('..')
5
5
 
6
- t.throws(() => {
7
- build({
8
- $defs: {
9
- type: 'foooo"bar'
10
- },
11
- patternProperties: {
12
- x: { $ref: '#/$defs' }
13
- }
14
- })
15
- }, 'foooo"bar unsupported')
6
+ test('sanitize 3', t => {
7
+ t.assert.throws(() => {
8
+ build({
9
+ $defs: {
10
+ type: 'foooo"bar'
11
+ },
12
+ patternProperties: {
13
+ x: { $ref: '#/$defs' }
14
+ }
15
+ })
16
+ }, { message: 'foooo"bar unsupported' })
17
+ })
@@ -1,14 +1,16 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
3
+ const { test } = require('node:test')
4
4
  const build = require('..')
5
5
 
6
- const payload = '(throw "pwoned")'
6
+ test('sanitize 4', t => {
7
+ const payload = '(throw "pwoned")'
7
8
 
8
- const stringify = build({
9
- required: [`"];${payload}//`]
10
- })
9
+ const stringify = build({
10
+ required: [`"];${payload}//`]
11
+ })
11
12
 
12
- t.throws(() => {
13
- stringify({})
14
- }, 'Error: ""];(throw "pwoned")//" is required!')
13
+ t.assert.throws(() => {
14
+ stringify({})
15
+ }, { message: '""];(throw "pwoned")//" is required!' })
16
+ })
@@ -1,16 +1,16 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
3
+ const { test } = require('node:test')
4
4
  const build = require('..')
5
5
 
6
- const payload = '(throw "pwoned")'
6
+ test('sanitize 5', t => {
7
+ const payload = '(throw "pwoned")'
7
8
 
8
- const expected = 'Error: Invalid regular expression: /*/: Nothing to repeat. Found at * matching {"type":"*/(throw \\"pwoned\\")){//"}'
9
-
10
- t.throws(() => {
11
- build({
12
- patternProperties: {
13
- '*': { type: `*/${payload}){//` }
14
- }
15
- })
16
- }, expected)
9
+ t.assert.throws(() => {
10
+ build({
11
+ patternProperties: {
12
+ '*': { type: `*/${payload}){//` }
13
+ }
14
+ })
15
+ }, { message: 'schema is invalid: data/patternProperties must match format "regex"' })
16
+ })
@@ -1,22 +1,22 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
3
+ const { test } = require('node:test')
4
4
  const build = require('..')
5
5
 
6
- const payload = '(throw "pwoned")'
6
+ test('sanitize 6', t => {
7
+ const payload = '(throw "pwoned")'
7
8
 
8
- const stringify = build({
9
- type: 'object',
10
- properties: {
11
- '/*': { type: 'object' },
12
- x: {
13
- type: 'object',
14
- properties: {
15
- a: { type: 'string', default: `*/}${payload};{//` }
9
+ const stringify = build({
10
+ type: 'object',
11
+ properties: {
12
+ '/*': { type: 'object' },
13
+ x: {
14
+ type: 'object',
15
+ properties: {
16
+ a: { type: 'string', default: `*/}${payload};{//` }
17
+ }
16
18
  }
17
19
  }
18
- }
20
+ })
21
+ t.assert.doesNotThrow(() => { stringify({}) })
19
22
  })
20
- stringify({})
21
-
22
- t.pass('no crashes')
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const test = require('tap').test
3
+ const { test } = require('node:test')
4
4
  const build = require('..')
5
5
 
6
6
  test('required property containing single quote, contains property', (t) => {
@@ -16,7 +16,7 @@ test('required property containing single quote, contains property', (t) => {
16
16
  ]
17
17
  })
18
18
 
19
- t.throws(() => stringify({}), new Error('"\'" is required!'))
19
+ t.assert.throws(() => stringify({}), new Error('"\'" is required!'))
20
20
  })
21
21
 
22
22
  test('required property containing double quote, contains property', (t) => {
@@ -32,7 +32,7 @@ test('required property containing double quote, contains property', (t) => {
32
32
  ]
33
33
  })
34
34
 
35
- t.throws(() => stringify({}), new Error('""" is required!'))
35
+ t.assert.throws(() => stringify({}), new Error('""" is required!'))
36
36
  })
37
37
 
38
38
  test('required property containing single quote, does not contain property', (t) => {
@@ -48,7 +48,7 @@ test('required property containing single quote, does not contain property', (t)
48
48
  ]
49
49
  })
50
50
 
51
- t.throws(() => stringify({}), new Error('"\'" is required!'))
51
+ t.assert.throws(() => stringify({}), new Error('"\'" is required!'))
52
52
  })
53
53
 
54
54
  test('required property containing double quote, does not contain property', (t) => {
@@ -64,5 +64,5 @@ test('required property containing double quote, does not contain property', (t)
64
64
  ]
65
65
  })
66
66
 
67
- t.throws(() => stringify({}), new Error('""" is required!'))
67
+ t.assert.throws(() => stringify({}), new Error('""" is required!'))
68
68
  })
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const { test } = require('tap')
3
+ const { test } = require('node:test')
4
4
  const clone = require('rfdc/default')
5
5
  const build = require('..')
6
6
 
@@ -32,8 +32,8 @@ test('oneOf with $ref should not change the input schema', t => {
32
32
  })
33
33
 
34
34
  const value = stringify({ people: { name: 'hello', foo: 'bar' } })
35
- t.equal(value, '{"people":{"name":"hello"}}')
36
- t.same(schema, clonedSchema)
35
+ t.assert.equal(value, '{"people":{"name":"hello"}}')
36
+ t.assert.deepStrictEqual(schema, clonedSchema)
37
37
  })
38
38
 
39
39
  test('oneOf and anyOf with $ref should not change the input schema', t => {
@@ -75,9 +75,9 @@ test('oneOf and anyOf with $ref should not change the input schema', t => {
75
75
  const valueAny1 = stringify({ people: { name: 'hello', foo: 'bar' }, love: 'music' })
76
76
  const valueAny2 = stringify({ people: { name: 'hello', foo: 'bar' }, love: true })
77
77
 
78
- t.equal(valueAny1, '{"people":{"name":"hello"},"love":"music"}')
79
- t.equal(valueAny2, '{"people":{"name":"hello"},"love":true}')
80
- t.same(schema, clonedSchema)
78
+ t.assert.equal(valueAny1, '{"people":{"name":"hello"},"love":"music"}')
79
+ t.assert.equal(valueAny2, '{"people":{"name":"hello"},"love":true}')
80
+ t.assert.deepStrictEqual(schema, clonedSchema)
81
81
  })
82
82
 
83
83
  test('multiple $ref tree', t => {
@@ -118,8 +118,8 @@ test('multiple $ref tree', t => {
118
118
  })
119
119
 
120
120
  const value = stringify({ people: { name: 'hello', foo: 'bar', age: 42 } })
121
- t.equal(value, '{"people":{"name":"hello","age":42}}')
122
- t.same(schema, clonedSchema)
121
+ t.assert.equal(value, '{"people":{"name":"hello","age":42}}')
122
+ t.assert.deepStrictEqual(schema, clonedSchema)
123
123
  })
124
124
 
125
125
  test('must not mutate items $ref', t => {
@@ -152,8 +152,8 @@ test('must not mutate items $ref', t => {
152
152
  })
153
153
 
154
154
  const value = stringify([{ name: 'foo' }])
155
- t.equal(value, '[{"name":"foo"}]')
156
- t.same(schema, clonedSchema)
155
+ t.assert.equal(value, '[{"name":"foo"}]')
156
+ t.assert.deepStrictEqual(schema, clonedSchema)
157
157
  })
158
158
 
159
159
  test('must not mutate items referred by $ref', t => {
@@ -191,6 +191,6 @@ test('must not mutate items referred by $ref', t => {
191
191
  })
192
192
 
193
193
  const value = stringify({ name: { name: 'foo' } })
194
- t.equal(value, '{"name":{"name":"foo"}}')
195
- t.same(firstSchema, clonedSchema)
194
+ t.assert.equal(value, '{"name":{"name":"foo"}}')
195
+ t.assert.deepStrictEqual(firstSchema, clonedSchema)
196
196
  })