fast-json-stringify 6.0.0 → 6.1.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.
Files changed (68) hide show
  1. package/.github/dependabot.yml +1 -1
  2. package/.github/workflows/ci.yml +7 -2
  3. package/LICENSE +5 -2
  4. package/README.md +50 -45
  5. package/benchmark/bench-cmp-branch.js +1 -1
  6. package/benchmark/bench-cmp-lib.js +29 -1
  7. package/eslint.config.js +9 -0
  8. package/index.js +38 -24
  9. package/lib/serializer.js +5 -7
  10. package/lib/validator.js +1 -1
  11. package/package.json +42 -22
  12. package/test/additionalProperties.test.js +20 -20
  13. package/test/allof.test.js +36 -40
  14. package/test/any.test.js +28 -28
  15. package/test/anyof.test.js +44 -46
  16. package/test/array.test.js +19 -19
  17. package/test/asNumber.test.js +2 -2
  18. package/test/basic.test.js +20 -32
  19. package/test/bigint.test.js +6 -6
  20. package/test/clean-cache.test.js +9 -7
  21. package/test/const.test.js +35 -35
  22. package/test/date.test.js +77 -77
  23. package/test/debug-mode.test.js +27 -27
  24. package/test/defaults.test.js +2 -2
  25. package/test/enum.test.js +3 -3
  26. package/test/fix-604.test.js +18 -17
  27. package/test/if-then-else.test.js +22 -24
  28. package/test/inferType.test.js +4 -4
  29. package/test/infinity.test.js +4 -4
  30. package/test/integer.test.js +21 -21
  31. package/test/invalidSchema.test.js +4 -8
  32. package/test/issue-479.test.js +2 -2
  33. package/test/json-schema-test-suite/README.md +1 -1
  34. package/test/json-schema-test-suite/draft4.test.js +3 -3
  35. package/test/json-schema-test-suite/draft6.test.js +3 -3
  36. package/test/json-schema-test-suite/draft7.test.js +3 -3
  37. package/test/json-schema-test-suite/util.js +6 -9
  38. package/test/missing-values.test.js +8 -8
  39. package/test/multi-type-serializer.test.js +2 -2
  40. package/test/nestedObjects.test.js +3 -3
  41. package/test/nullable.test.js +35 -35
  42. package/test/oneof.test.js +27 -29
  43. package/test/patternProperties.test.js +11 -11
  44. package/test/recursion.test.js +6 -6
  45. package/test/ref.test.js +102 -186
  46. package/test/regex.test.js +4 -5
  47. package/test/required.test.js +42 -77
  48. package/test/requiresAjv.test.js +34 -32
  49. package/test/sanitize.test.js +40 -41
  50. package/test/sanitize2.test.js +11 -11
  51. package/test/sanitize3.test.js +13 -11
  52. package/test/sanitize4.test.js +10 -8
  53. package/test/sanitize5.test.js +11 -11
  54. package/test/sanitize6.test.js +14 -14
  55. package/test/sanitize7.test.js +5 -5
  56. package/test/side-effect.test.js +12 -12
  57. package/test/standalone-mode.test.js +29 -26
  58. package/test/string.test.js +12 -12
  59. package/test/surrogate.test.js +9 -9
  60. package/test/toJSON.test.js +9 -9
  61. package/test/typebox.test.js +2 -2
  62. package/test/typesArray.test.js +34 -34
  63. package/test/unknownFormats.test.js +5 -5
  64. package/test/webpack.test.js +2 -2
  65. package/types/index.d.ts +29 -29
  66. package/types/index.test-d.ts +75 -74
  67. package/.github/workflows/benchmark.yml +0 -85
  68. package/.taprc +0 -7
@@ -9,5 +9,5 @@ updates:
9
9
  - package-ecosystem: "npm"
10
10
  directory: "/"
11
11
  schedule:
12
- interval: "weekly"
12
+ interval: "monthly"
13
13
  open-pull-requests-limit: 10
@@ -4,7 +4,6 @@ on:
4
4
  push:
5
5
  branches:
6
6
  - main
7
- - master
8
7
  - next
9
8
  - 'v*'
10
9
  paths-ignore:
@@ -15,9 +14,15 @@ on:
15
14
  - 'docs/**'
16
15
  - '*.md'
17
16
 
17
+ permissions:
18
+ contents: read
19
+
18
20
  jobs:
19
21
  test:
20
- uses: fastify/workflows/.github/workflows/plugins-ci.yml@v4.1.0
22
+ permissions:
23
+ contents: write
24
+ pull-requests: write
25
+ uses: fastify/workflows/.github/workflows/plugins-ci.yml@v5
21
26
  with:
22
27
  license-check: true
23
28
  lint: true
package/LICENSE CHANGED
@@ -1,6 +1,9 @@
1
- The MIT License (MIT)
1
+ MIT License
2
2
 
3
- Copyright (c) 2016-2018 Matteo Collina
3
+ Copyright (c) 2016-present Matteo Collina
4
+ Copyright (c) 2016-present The Fastify team
5
+
6
+ The Fastify team members are listed at https://github.com/fastify/fastify#team.
4
7
 
5
8
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
9
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,11 +1,10 @@
1
1
  # fast-json-stringify
2
2
 
3
- ![CI](https://github.com/fastify/fast-json-stringify/workflows/CI/badge.svg)
3
+ [![CI](https://github.com/fastify/fast-json-stringify/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/fastify/fast-json-stringify/actions/workflows/ci.yml)
4
4
  [![NPM version](https://img.shields.io/npm/v/fast-json-stringify.svg?style=flat)](https://www.npmjs.com/package/fast-json-stringify)
5
- [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/)
5
+ [![neostandard javascript style](https://img.shields.io/badge/code_style-neostandard-brightgreen?style=flat)](https://github.com/neostandard/neostandard)
6
6
  [![NPM downloads](https://img.shields.io/npm/dm/fast-json-stringify.svg?style=flat)](https://www.npmjs.com/package/fast-json-stringify)
7
7
 
8
-
9
8
  __fast-json-stringify__ is significantly faster than `JSON.stringify()` for small payloads.
10
9
  Its performance advantage shrinks as your payload grows.
11
10
  It pairs well with [__flatstr__](https://www.npmjs.com/package/flatstr), which triggers a V8 optimization that improves performance when eventually converting the string to a `Buffer`.
@@ -18,37 +17,43 @@ fast-json-stringify requires a [JSON Schema Draft 7](https://json-schema.org/spe
18
17
  ##### Benchmarks
19
18
 
20
19
  - Machine: `EX41S-SSD, Intel Core i7, 4Ghz, 64GB RAM, 4C/8T, SSD`.
21
- - Node.js `v18.12.1`
20
+ - Node.js `v22.14.0`
22
21
 
23
22
  ```
24
- FJS creation x 4,129 ops/sec ±0.82% (92 runs sampled)
25
- CJS creation x 184,196 ops/sec ±0.12% (97 runs sampled)
26
- AJV Serialize creation x 61,130,591 ops/sec ±0.40% (92 runs sampled)
27
- JSON.stringify array x 5,057 ops/sec ±0.10% (100 runs sampled)
28
- fast-json-stringify array default x 6,243 ops/sec ±0.14% (98 runs sampled)
29
- fast-json-stringify array json-stringify x 6,261 ops/sec ±0.30% (99 runs sampled)
30
- compile-json-stringify array x 6,842 ops/sec ±0.18% (96 runs sampled)
31
- AJV Serialize array x 6,964 ops/sec ±0.11% (95 runs sampled)
32
- JSON.stringify large array x 248 ops/sec ±0.07% (90 runs sampled)
33
- fast-json-stringify large array default x 99.96 ops/sec ±0.22% (74 runs sampled)
34
- fast-json-stringify large array json-stringify x 248 ops/sec ±0.07% (90 runs sampled)
35
- compile-json-stringify large array x 317 ops/sec ±0.09% (89 runs sampled)
36
- AJV Serialize large array x 111 ops/sec ±0.07% (33 runs sampled)
37
- JSON.stringify long string x 16,002 ops/sec ±0.09% (98 runs sampled)
38
- fast-json-stringify long string x 15,979 ops/sec ±0.09% (96 runs sampled)
39
- compile-json-stringify long string x 15,952 ops/sec ±0.31% (97 runs sampled)
40
- AJV Serialize long string x 21,416 ops/sec ±0.08% (98 runs sampled)
41
- JSON.stringify short string x 12,944,272 ops/sec ±0.09% (96 runs sampled)
42
- fast-json-stringify short string x 30,585,790 ops/sec ±0.27% (97 runs sampled)
43
- compile-json-stringify short string x 30,656,406 ops/sec ±0.12% (96 runs sampled)
44
- AJV Serialize short string x 30,406,785 ops/sec ±0.37% (96 runs sampled)
45
- JSON.stringify obj x 3,153,043 ops/sec ±0.33% (99 runs sampled)
46
- fast-json-stringify obj x 6,866,434 ops/sec ±0.11% (100 runs sampled)
47
- compile-json-stringify obj x 15,886,723 ops/sec ±0.15% (98 runs sampled)
48
- AJV Serialize obj x 8,969,043 ops/sec ±0.36% (97 runs sampled)
49
- JSON stringify date x 1,126,547 ops/sec ±0.09% (97 runs sampled)
50
- fast-json-stringify date format x 1,836,188 ops/sec ±0.12% (99 runs sampled)
51
- compile-json-stringify date format x 1,125,735 ops/sec ±0.19% (98 runs sampled)
23
+ FJS creation x 9,696 ops/sec ±0.77% (94 runs sampled)
24
+ CJS creation x 197,267 ops/sec ±0.22% (95 runs sampled)
25
+ AJV Serialize creation x 48,302,927 ops/sec ±2.09% (90 runs sampled)
26
+ json-accelerator creation x 668,430 ops/sec ±0.43% (95 runs sampled)
27
+ JSON.stringify array x 7,924 ops/sec ±0.11% (98 runs sampled)
28
+ fast-json-stringify array default x 7,183 ops/sec ±0.09% (97 runs sampled)
29
+ json-accelerator array x 5,762 ops/sec ±0.27% (99 runs sampled)
30
+ fast-json-stringify array json-stringify x 7,171 ops/sec ±0.17% (97 runs sampled)
31
+ compile-json-stringify array x 6,889 ops/sec ±0.41% (96 runs sampled)
32
+ AJV Serialize array x 6,945 ops/sec ±0.17% (98 runs sampled)
33
+ JSON.stringify large array x 331 ops/sec ±0.17% (93 runs sampled)
34
+ fast-json-stringify large array default x 208 ops/sec ±0.21% (91 runs sampled)
35
+ fast-json-stringify large array json-stringify x 330 ops/sec ±0.17% (93 runs sampled)
36
+ compile-json-stringify large array x 318 ops/sec ±0.11% (90 runs sampled)
37
+ AJV Serialize large array x 114 ops/sec ±0.27% (74 runs sampled)
38
+ JSON.stringify long string x 13,452 ops/sec ±0.15% (99 runs sampled)
39
+ fast-json-stringify long string x 13,454 ops/sec ±0.10% (99 runs sampled)
40
+ json-accelerator long string x 13,439 ops/sec ±0.09% (98 runs sampled)
41
+ compile-json-stringify long string x 13,380 ops/sec ±0.12% (100 runs sampled)
42
+ AJV Serialize long string x 21,932 ops/sec ±0.06% (99 runs sampled)
43
+ JSON.stringify short string x 12,114,052 ops/sec ±0.59% (97 runs sampled)
44
+ fast-json-stringify short string x 29,408,175 ops/sec ±1.12% (91 runs sampled)
45
+ json-accelerator short string x 29,431,694 ops/sec ±1.05% (93 runs sampled)
46
+ compile-json-stringify short string x 24,740,338 ops/sec ±1.02% (91 runs sampled)
47
+ AJV Serialize short string x 17,841,869 ops/sec ±0.90% (91 runs sampled)
48
+ JSON.stringify obj x 4,577,494 ops/sec ±0.25% (94 runs sampled)
49
+ fast-json-stringify obj x 7,291,157 ops/sec ±0.40% (97 runs sampled)
50
+ json-accelerator obj x 6,473,194 ops/sec ±0.31% (99 runs sampled)
51
+ compile-json-stringify obj x 14,724,935 ops/sec ±0.50% (96 runs sampled)
52
+ AJV Serialize obj x 8,782,944 ops/sec ±0.45% (93 runs sampled)
53
+ JSON stringify date x 803,522 ops/sec ±0.47% (98 runs sampled)
54
+ fast-json-stringify date format x 1,117,776 ops/sec ±0.69% (95 runs sampled)
55
+ json-accelerate date format x 1,122,419 ops/sec ±0.20% (97 runs sampled)
56
+ compile-json-stringify date format x 803,214 ops/sec ±0.23% (97 runs sampled)
52
57
  ```
53
58
 
54
59
  #### Table of contents:
@@ -70,7 +75,7 @@ compile-json-stringify date format x 1,125,735 ops/sec ±0.19% (98 runs sampled)
70
75
  - <a href="#security">`Security Notice`</a>
71
76
  - <a href="#debug">`Debug Mode`</a>
72
77
  - <a href="#standalone">`Standalone Mode`</a>
73
- - <a href="#acknowledgements">`Acknowledgements`</a>
78
+ - <a href="#acknowledgments">`Acknowledgments`</a>
74
79
  - <a href="#license">`License`</a>
75
80
 
76
81
 
@@ -111,7 +116,7 @@ console.log(stringify({
111
116
  <a name="options"></a>
112
117
  ## Options
113
118
 
114
- Optionally, you may provide to `fast-json-stringify` an option object as second parameter:
119
+ Optionally, you may provide to `fast-json-stringify` an option object as the second parameter:
115
120
 
116
121
  ```js
117
122
  const fastJson = require('fast-json-stringify')
@@ -165,7 +170,7 @@ And nested ones, too.
165
170
  | `date` | `2020-04-03` |
166
171
  | `time` | `09:11:08` |
167
172
 
168
- **Note**: In the case of string formatted Date and not Date Object, there will be no manipulation on it. It should be properly formatted.
173
+ **Note**: In the case of a string formatted Date and not Date Object, there will be no manipulation on it. It should be properly formatted.
169
174
 
170
175
  Example with a Date object:
171
176
 
@@ -290,7 +295,7 @@ console.log(stringify(obj)) // '{"matchfoo":"42","otherfoo":"str","matchnum":3,"
290
295
  *additionalProperties* must be an object or a boolean, declared in this way: `{ type: 'type' }`.
291
296
  *additionalProperties* will work only for the properties that are not explicitly listed in the *properties* and *patternProperties* objects.
292
297
 
293
- If *additionalProperties* is not present or is set to `false`, every property that is not explicitly listed in the *properties* and *patternProperties* objects,will be ignored, as described in <a href="#missingFields">Missing fields</a>.
298
+ If *additionalProperties* is not present or is set to `false`, every property that is not explicitly listed in the *properties* and *patternProperties* objects will be ignored, as described in <a href="#missingFields">Missing fields</a>.
294
299
  Missing fields are ignored to avoid having to rewrite objects before serializing. However, other schema rules would throw in similar situations.
295
300
  If *additionalProperties* is set to `true`, it will be used by `JSON.stringify` to stringify the additional properties. If you want to achieve maximum performance, we strongly encourage you to use a fixed schema where possible.
296
301
  The additional properties will always be serialized at the end of the object.
@@ -543,12 +548,12 @@ const stringify = fastJson(schema, { schema: externalSchema })
543
548
 
544
549
  <a name="long"></a>
545
550
  #### Long integers
546
- By default the library will handle automatically [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).
551
+ By default, the library will handle automatically [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).
547
552
 
548
553
  <a name="integer"></a>
549
554
  #### Integers
550
555
  The `type: integer` property will be truncated if a floating point is provided.
551
- You can customize this behaviour with the `rounding` option that will accept [`round`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round), [`ceil`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/ceil), [`floor`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor) or [`trunc`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc). Default is `trunc`:
556
+ You can customize this behavior with the `rounding` option that will accept [`round`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round), [`ceil`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/ceil), [`floor`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor), or [`trunc`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc). Default is `trunc`:
552
557
 
553
558
  ```js
554
559
  const stringify = fastJson(schema, { rounding: 'ceil' })
@@ -650,8 +655,8 @@ const stringify = fastJson({
650
655
 
651
656
  ##### Benchmarks
652
657
 
653
- For reference, here goes some benchmarks for comparison over the three
654
- mechanisms. Benchmarks conducted on an old machine.
658
+ For reference, here are some benchmarks for comparison over the three
659
+ mechanisms. Benchmarks were conducted on an old machine.
655
660
 
656
661
  - Machine: `ST1000LM024 HN-M 1TB HDD, Intel Core i7-3610QM @ 2.3GHz, 12GB RAM, 4C/8T`.
657
662
  - Node.js `v16.13.1`
@@ -678,7 +683,7 @@ expose your application to remote attacks.
678
683
 
679
684
  Users are responsible for sending trusted data. `fast-json-stringify` guarantees that you will get
680
685
  a valid output only if your input matches the schema or can be coerced to the schema. If your input
681
- doesn't match the schema, you will get undefined behavior.
686
+ doesn't match the schema, you will get undefined behavior.
682
687
 
683
688
  <a name="debug"></a>
684
689
  ### Debug Mode
@@ -699,7 +704,7 @@ const debugCompiled = fastJson({
699
704
 
700
705
  console.log(debugCompiled) // it is a object contain code, ajv instance
701
706
  const rawString = debugCompiled.code // it is the generated code
702
- console.log(rawString)
707
+ console.log(rawString)
703
708
 
704
709
  const stringify = fastJson.restore(debugCompiled) // use the generated string to get back the `stringify` function
705
710
  console.log(stringify({ firstName: 'Foo', surname: 'bar' })) // '{"firstName":"Foo"}'
@@ -728,12 +733,12 @@ const stringify = require('stringify.js')
728
733
  console.log(stringify({ firstName: 'Foo', surname: 'bar' })) // '{"firstName":"Foo"}'
729
734
  ```
730
735
 
731
- <a name="acknowledgements"></a>
732
- ## Acknowledgements
736
+ <a name="acknowledgments"></a>
737
+ ## Acknowledgments
733
738
 
734
739
  This project was kindly sponsored by [nearForm](https://nearform.com).
735
740
 
736
741
  <a name="license"></a>
737
742
  ## License
738
743
 
739
- MIT
744
+ Licensed under [MIT](./LICENSE).
@@ -8,7 +8,7 @@ const simpleGit = require('simple-git')
8
8
  const git = simpleGit(process.cwd())
9
9
 
10
10
  const COMMAND = 'npm run bench'
11
- const DEFAULT_BRANCH = 'master'
11
+ const DEFAULT_BRANCH = 'main'
12
12
  const PERCENT_THRESHOLD = 5
13
13
  const greyColor = '\x1b[30m'
14
14
  const redColor = '\x1b[31m'
@@ -118,6 +118,12 @@ const ajvSerialize = ajv.compileSerializer(schemaAJVJTD)
118
118
  const ajvSerializeArray = ajv.compileSerializer(arraySchemaAJVJTD)
119
119
  const ajvSerializeString = ajv.compileSerializer({ type: 'string' })
120
120
 
121
+ const { createAccelerator } = require('json-accelerator')
122
+ const accelStringify = createAccelerator(schema)
123
+ const accelArray = createAccelerator(arraySchema)
124
+ const accelDate = FJS(dateFormatSchema)
125
+ const accelString = FJS({ type: 'string' })
126
+
121
127
  const getRandomString = (length) => {
122
128
  if (!Number.isInteger(length)) {
123
129
  throw new Error('Expected integer length')
@@ -134,7 +140,6 @@ const getRandomString = (length) => {
134
140
  return result[0].toUpperCase() + result.slice(1)
135
141
  }
136
142
 
137
- // eslint-disable-next-line
138
143
  for (let i = 0; i < STR_LEN; i++) {
139
144
  largeArray[i] = {
140
145
  firstName: getRandomString(8),
@@ -171,6 +176,9 @@ suite.add('CJS creation', function () {
171
176
  suite.add('AJV Serialize creation', function () {
172
177
  ajv.compileSerializer(schemaAJVJTD)
173
178
  })
179
+ suite.add('json-accelerator creation', function () {
180
+ createAccelerator(schema)
181
+ })
174
182
 
175
183
  suite.add('JSON.stringify array', function () {
176
184
  JSON.stringify(multiArray)
@@ -180,6 +188,10 @@ suite.add('fast-json-stringify array default', function () {
180
188
  stringifyArrayDefault(multiArray)
181
189
  })
182
190
 
191
+ suite.add('json-accelerator array', function () {
192
+ accelArray(multiArray)
193
+ })
194
+
183
195
  suite.add('fast-json-stringify array json-stringify', function () {
184
196
  stringifyArrayJSONStringify(multiArray)
185
197
  })
@@ -220,6 +232,10 @@ suite.add('fast-json-stringify long string', function () {
220
232
  stringifyString(str)
221
233
  })
222
234
 
235
+ suite.add('json-accelerator long string', function () {
236
+ stringifyString(str)
237
+ })
238
+
223
239
  suite.add('compile-json-stringify long string', function () {
224
240
  CJSStringifyString(str)
225
241
  })
@@ -236,6 +252,10 @@ suite.add('fast-json-stringify short string', function () {
236
252
  stringifyString('hello world')
237
253
  })
238
254
 
255
+ suite.add('json-accelerator short string', function () {
256
+ accelString('hello world')
257
+ })
258
+
239
259
  suite.add('compile-json-stringify short string', function () {
240
260
  CJSStringifyString('hello world')
241
261
  })
@@ -252,6 +272,10 @@ suite.add('fast-json-stringify obj', function () {
252
272
  stringify(obj)
253
273
  })
254
274
 
275
+ suite.add('json-accelerator obj', function () {
276
+ accelStringify(obj)
277
+ })
278
+
255
279
  suite.add('compile-json-stringify obj', function () {
256
280
  CJSStringify(obj)
257
281
  })
@@ -268,6 +292,10 @@ suite.add('fast-json-stringify date format', function () {
268
292
  stringifyDate(date)
269
293
  })
270
294
 
295
+ suite.add('json-accelerate date format', function () {
296
+ accelDate(date)
297
+ })
298
+
271
299
  suite.add('compile-json-stringify date format', function () {
272
300
  CJSStringifyDate(date)
273
301
  })
@@ -0,0 +1,9 @@
1
+ 'use strict'
2
+
3
+ module.exports = require('neostandard')({
4
+ ignores: [
5
+ ...require('neostandard').resolveIgnoresFromGitignore(),
6
+ 'lib/schema-validator.js'
7
+ ],
8
+ ts: true
9
+ })
package/index.js CHANGED
@@ -15,6 +15,21 @@ const SINGLE_TICK = /'/g
15
15
  let largeArraySize = 2e4
16
16
  let largeArrayMechanism = 'default'
17
17
 
18
+ const serializerFns = `
19
+ const {
20
+ asString,
21
+ asNumber,
22
+ asBoolean,
23
+ asDateTime,
24
+ asDate,
25
+ asTime,
26
+ asUnsafeString
27
+ } = serializer
28
+
29
+ const asInteger = serializer.asInteger.bind(serializer)
30
+
31
+ `
32
+
18
33
  const validRoundingMethods = [
19
34
  'floor',
20
35
  'ceil',
@@ -141,6 +156,7 @@ function build (schema, options) {
141
156
  const code = buildValue(context, location, 'input')
142
157
 
143
158
  let contextFunctionCode = `
159
+ ${serializerFns}
144
160
  const JSON_STR_BEGIN_OBJECT = '{'
145
161
  const JSON_STR_END_OBJECT = '}'
146
162
  const JSON_STR_BEGIN_ARRAY = '['
@@ -252,20 +268,16 @@ const numberKeywords = [
252
268
  * https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6
253
269
  */
254
270
  function inferTypeByKeyword (schema) {
255
- // eslint-disable-next-line
256
- for (var keyword of objectKeywords) {
271
+ for (const keyword of objectKeywords) {
257
272
  if (keyword in schema) return 'object'
258
273
  }
259
- // eslint-disable-next-line
260
- for (var keyword of arrayKeywords) {
274
+ for (const keyword of arrayKeywords) {
261
275
  if (keyword in schema) return 'array'
262
276
  }
263
- // eslint-disable-next-line
264
- for (var keyword of stringKeywords) {
277
+ for (const keyword of stringKeywords) {
265
278
  if (keyword in schema) return 'string'
266
279
  }
267
- // eslint-disable-next-line
268
- for (var keyword of numberKeywords) {
280
+ for (const keyword of numberKeywords) {
269
281
  if (keyword in schema) return 'number'
270
282
  }
271
283
  return schema.type
@@ -296,7 +308,7 @@ function buildExtraObjectPropertiesSerializer (context, location, addComma) {
296
308
  code += `
297
309
  if (/${propertyKey.replace(/\\*\//g, '\\/')}/.test(key)) {
298
310
  ${addComma}
299
- json += serializer.asString(key) + JSON_STR_COLONS
311
+ json += asString(key) + JSON_STR_COLONS
300
312
  ${buildValue(context, propertyLocation, 'value')}
301
313
  continue
302
314
  }
@@ -311,13 +323,13 @@ function buildExtraObjectPropertiesSerializer (context, location, addComma) {
311
323
  if (additionalPropertiesSchema === true) {
312
324
  code += `
313
325
  ${addComma}
314
- json += serializer.asString(key) + JSON_STR_COLONS + JSON.stringify(value)
326
+ json += asString(key) + JSON_STR_COLONS + JSON.stringify(value)
315
327
  `
316
328
  } else {
317
329
  const propertyLocation = location.getPropertyLocation('additionalProperties')
318
330
  code += `
319
331
  ${addComma}
320
- json += serializer.asString(key) + JSON_STR_COLONS
332
+ json += asString(key) + JSON_STR_COLONS
321
333
  ${buildValue(context, propertyLocation, 'value')}
322
334
  `
323
335
  }
@@ -569,7 +581,7 @@ function buildArray (context, location) {
569
581
  const tmpRes = buildValue(context, itemsLocation.getPropertyLocation(i), 'value')
570
582
  functionCode += `
571
583
  if (${i} < arrayLength) {
572
- if (${buildArrayTypeCondition(item.type, `[${i}]`)}) {
584
+ if (${buildArrayTypeCondition(item.type, 'value')}) {
573
585
  ${tmpRes}
574
586
  if (${i} < arrayEnd) {
575
587
  json += JSON_STR_COMMA
@@ -584,16 +596,18 @@ function buildArray (context, location) {
584
596
  if (schema.additionalItems) {
585
597
  functionCode += `
586
598
  for (let i = ${itemsSchema.length}; i < arrayLength; i++) {
587
- json += JSON.stringify(obj[i])
599
+ value = obj[i]
600
+ json += JSON.stringify(value)
588
601
  if (i < arrayEnd) {
589
602
  json += JSON_STR_COMMA
590
603
  }
591
604
  }`
592
605
  }
593
606
  } else {
594
- const code = buildValue(context, itemsLocation, 'obj[i]')
607
+ const code = buildValue(context, itemsLocation, 'value')
595
608
  functionCode += `
596
609
  for (let i = 0; i < arrayLength; i++) {
610
+ value = obj[i]
597
611
  ${code}
598
612
  if (i < arrayEnd) {
599
613
  json += JSON_STR_COMMA
@@ -733,13 +747,13 @@ function buildSingleTypeSerializer (context, location, input) {
733
747
  return 'json += JSON_STR_NULL'
734
748
  case 'string': {
735
749
  if (schema.format === 'date-time') {
736
- return `json += serializer.asDateTime(${input})`
750
+ return `json += asDateTime(${input})`
737
751
  } else if (schema.format === 'date') {
738
- return `json += serializer.asDate(${input})`
752
+ return `json += asDate(${input})`
739
753
  } else if (schema.format === 'time') {
740
- return `json += serializer.asTime(${input})`
754
+ return `json += asTime(${input})`
741
755
  } else if (schema.format === 'unsafe') {
742
- return `json += serializer.asUnsafeString(${input})`
756
+ return `json += asUnsafeString(${input})`
743
757
  } else {
744
758
  return `
745
759
  if (typeof ${input} !== 'string') {
@@ -748,22 +762,22 @@ function buildSingleTypeSerializer (context, location, input) {
748
762
  } else if (${input} instanceof Date) {
749
763
  json += JSON_STR_QUOTE + ${input}.toISOString() + JSON_STR_QUOTE
750
764
  } else if (${input} instanceof RegExp) {
751
- json += serializer.asString(${input}.source)
765
+ json += asString(${input}.source)
752
766
  } else {
753
- json += serializer.asString(${input}.toString())
767
+ json += asString(${input}.toString())
754
768
  }
755
769
  } else {
756
- json += serializer.asString(${input})
770
+ json += asString(${input})
757
771
  }
758
772
  `
759
773
  }
760
774
  }
761
775
  case 'integer':
762
- return `json += serializer.asInteger(${input})`
776
+ return `json += asInteger(${input})`
763
777
  case 'number':
764
- return `json += serializer.asNumber(${input})`
778
+ return `json += asNumber(${input})`
765
779
  case 'boolean':
766
- return `json += serializer.asBoolean(${input})`
780
+ return `json += asBoolean(${input})`
767
781
  case 'object': {
768
782
  const funcName = buildObject(context, location)
769
783
  return `json += ${funcName}(${input})`
package/lib/serializer.js CHANGED
@@ -1,8 +1,5 @@
1
1
  'use strict'
2
2
 
3
- // eslint-disable-next-line
4
- const STR_ESCAPE = /[\u0000-\u001f\u0022\u005c\ud800-\udfff]/
5
-
6
3
  module.exports = class Serializer {
7
4
  constructor (options) {
8
5
  switch (options && options.rounding) {
@@ -92,7 +89,9 @@ module.exports = class Serializer {
92
89
 
93
90
  asString (str) {
94
91
  const len = str.length
95
- if (len < 42) {
92
+ if (len === 0) {
93
+ return '""'
94
+ } else if (len < 42) {
96
95
  // magically escape strings for json
97
96
  // relying on their charCodeAt
98
97
  // everything below 32 needs JSON.stringify()
@@ -102,8 +101,7 @@ module.exports = class Serializer {
102
101
  let result = ''
103
102
  let last = -1
104
103
  let point = 255
105
- // eslint-disable-next-line
106
- for (var i = 0; i < len; i++) {
104
+ for (let i = 0; i < len; i++) {
107
105
  point = str.charCodeAt(i)
108
106
  if (
109
107
  point === 0x22 || // '"'
@@ -118,7 +116,7 @@ module.exports = class Serializer {
118
116
  }
119
117
  }
120
118
  return (last === -1 && ('"' + str + '"')) || ('"' + result + str.slice(last) + '"')
121
- } else if (len < 5000 && STR_ESCAPE.test(str) === false) {
119
+ } else if (len < 5000 && str.isWellFormed()) {
122
120
  // Only use the regular expression for shorter input. The overhead is otherwise too much.
123
121
  return '"' + str + '"'
124
122
  } else {
package/lib/validator.js CHANGED
@@ -21,7 +21,7 @@ class Validator {
21
21
  keyword: 'fjs_type',
22
22
  type: 'object',
23
23
  errors: false,
24
- validate: (type, date) => {
24
+ validate: (_type, date) => {
25
25
  return date instanceof Date
26
26
  }
27
27
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fast-json-stringify",
3
- "version": "6.0.0",
3
+ "version": "6.1.0",
4
4
  "description": "Stringify your JSON at max speed",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
@@ -10,16 +10,12 @@
10
10
  "bench:cmp": "node ./benchmark/bench-cmp-branch.js",
11
11
  "bench:cmp:ci": "node ./benchmark/bench-cmp-branch.js --ci",
12
12
  "benchmark": "node ./benchmark/bench-cmp-lib.js",
13
- "lint": "standard",
14
- "lint:fix": "standard --fix",
13
+ "lint": "eslint",
14
+ "lint:fix": "eslint --fix",
15
15
  "test:typescript": "tsd",
16
- "test:unit": "tap",
16
+ "test:unit": "c8 node --test",
17
17
  "test": "npm run test:unit && npm run test:typescript"
18
18
  },
19
- "precommit": [
20
- "lint",
21
- "test"
22
- ],
23
19
  "repository": {
24
20
  "type": "git",
25
21
  "url": "git+https://github.com/fastify/fast-json-stringify.git"
@@ -31,38 +27,62 @@
31
27
  "fast"
32
28
  ],
33
29
  "author": "Matteo Collina <hello@matteocollina.com>",
30
+ "contributors": [
31
+ {
32
+ "name": "Tomas Della Vedova",
33
+ "url": "http://delved.org"
34
+ },
35
+ {
36
+ "name": "Aras Abbasi",
37
+ "email": "aras.abbasi@gmail.com"
38
+ },
39
+ {
40
+ "name": "Manuel Spigolon",
41
+ "email": "behemoth89@gmail.com"
42
+ },
43
+ {
44
+ "name": "Frazer Smith",
45
+ "email": "frazer.dev@icloud.com",
46
+ "url": "https://github.com/fdawgs"
47
+ }
48
+ ],
34
49
  "license": "MIT",
35
50
  "bugs": {
36
51
  "url": "https://github.com/fastify/fast-json-stringify/issues"
37
52
  },
38
53
  "homepage": "https://github.com/fastify/fast-json-stringify#readme",
54
+ "funding": [
55
+ {
56
+ "type": "github",
57
+ "url": "https://github.com/sponsors/fastify"
58
+ },
59
+ {
60
+ "type": "opencollective",
61
+ "url": "https://opencollective.com/fastify"
62
+ }
63
+ ],
39
64
  "devDependencies": {
40
- "@fastify/pre-commit": "^2.1.0",
41
- "@sinclair/typebox": "^0.32.15",
65
+ "@sinclair/typebox": "^0.34.3",
42
66
  "benchmark": "^2.1.4",
67
+ "c8": "^10.1.2",
43
68
  "cli-select": "^1.1.2",
44
69
  "compile-json-stringify": "^0.1.2",
70
+ "eslint": "^9.17.0",
45
71
  "fast-json-stringify": ".",
46
72
  "is-my-json-valid": "^2.20.6",
73
+ "json-accelerator": "^0.0.2",
74
+ "neostandard": "^0.12.0",
47
75
  "simple-git": "^3.23.0",
48
- "standard": "^17.1.0",
49
- "tap": "^19.2.5",
50
- "tsd": "^0.31.0",
76
+ "tsd": "^0.32.0",
51
77
  "webpack": "^5.90.3"
52
78
  },
53
79
  "dependencies": {
54
- "@fastify/merge-json-schemas": "^0.1.1",
80
+ "@fastify/merge-json-schemas": "^0.2.0",
55
81
  "ajv": "^8.12.0",
56
82
  "ajv-formats": "^3.0.1",
57
- "fast-deep-equal": "^3.1.3",
58
- "fast-uri": "^2.3.0",
59
- "json-schema-ref-resolver": "^1.0.1",
83
+ "fast-uri": "^3.0.0",
84
+ "json-schema-ref-resolver": "^3.0.0",
60
85
  "rfdc": "^1.2.0"
61
86
  },
62
- "standard": {
63
- "ignore": [
64
- "schema-validator.js"
65
- ]
66
- },
67
87
  "runkitExampleFilename": "./examples/example.js"
68
88
  }