fast-json-stringify 5.6.2 → 5.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -689,8 +689,7 @@ console.log(stringify({ firstName: 'Foo', surname: 'bar' })) // '{"firstName":"F
689
689
  ### Standalone Mode
690
690
 
691
691
  The standalone mode is used to compile the code that can be directly run by `node`
692
- itself. You need to install `ajv`, `fast-uri` and `ajv-formats` for
693
- the standalone code to work.
692
+ itself. You need to have `fast-json-stringify` installed for the standalone code to work.
694
693
 
695
694
  ```js
696
695
  const fs = require('fs')
package/index.js CHANGED
@@ -170,18 +170,15 @@ function build (schema, options) {
170
170
  }
171
171
  }
172
172
 
173
+ /* eslint no-new-func: "off" */
174
+ const contextFunc = new Function('validator', 'serializer', contextFunctionCode)
175
+
173
176
  if (options.mode === 'standalone') {
174
- // lazy load
175
- const isValidatorUsed = context.validatorSchemasIds.size > 0
176
177
  const buildStandaloneCode = require('./lib/standalone')
177
- return buildStandaloneCode(options, validator, isValidatorUsed, contextFunctionCode)
178
+ return buildStandaloneCode(contextFunc, context, serializer, validator)
178
179
  }
179
180
 
180
- /* eslint no-new-func: "off" */
181
- const contextFunc = new Function('validator', 'serializer', contextFunctionCode)
182
- const stringifyFunc = contextFunc(validator, serializer)
183
-
184
- return stringifyFunc
181
+ return contextFunc(validator, serializer)
185
182
  }
186
183
 
187
184
  const objectKeywords = [
@@ -571,12 +568,8 @@ function buildArray (context, location) {
571
568
  `
572
569
  }
573
570
 
574
- if (largeArrayMechanism !== 'default') {
575
- if (largeArrayMechanism === 'json-stringify') {
576
- functionCode += `if (arrayLength && arrayLength >= ${largeArraySize}) return JSON.stringify(obj)\n`
577
- } else {
578
- throw new Error(`Unsupported large array mechanism ${largeArrayMechanism}`)
579
- }
571
+ if (largeArrayMechanism === 'json-stringify') {
572
+ functionCode += `if (arrayLength && arrayLength >= ${largeArraySize}) return JSON.stringify(obj)\n`
580
573
  }
581
574
 
582
575
  functionCode += `
@@ -663,8 +656,6 @@ function buildArrayTypeCondition (type, accessor) {
663
656
  return buildArrayTypeCondition(subType, accessor)
664
657
  })
665
658
  condition = `(${conditions.join(' || ')})`
666
- } else {
667
- throw new Error(`${type} unsupported`)
668
659
  }
669
660
  }
670
661
  return condition
package/lib/serializer.js CHANGED
@@ -20,6 +20,7 @@ module.exports = class Serializer {
20
20
  this.parseInteger = Math.trunc
21
21
  break
22
22
  }
23
+ this._options = options
23
24
  }
24
25
 
25
26
  asInteger (i) {
@@ -54,7 +55,7 @@ module.exports = class Serializer {
54
55
  if (Number.isNaN(num)) {
55
56
  throw new Error(`The value "${i}" cannot be converted to a number.`)
56
57
  } else if (!Number.isFinite(num)) {
57
- return null
58
+ return 'null'
58
59
  } else {
59
60
  return '' + num
60
61
  }
@@ -156,4 +157,12 @@ module.exports = class Serializer {
156
157
  }
157
158
  return ((point < 32) || (surrogateFound === true)) ? JSON.stringify(str) : '"' + result + '"'
158
159
  }
160
+
161
+ getState () {
162
+ return this._options
163
+ }
164
+
165
+ static restoreFromState (state) {
166
+ return new Serializer(state)
167
+ }
159
168
  }
package/lib/standalone.js CHANGED
@@ -1,42 +1,31 @@
1
- const fs = require('fs')
2
- const path = require('path')
3
-
4
- function buildStandaloneCode (options, validator, isValidatorUsed, contextFunctionCode) {
5
- const serializerCode = fs.readFileSync(path.join(__dirname, 'serializer.js')).toString()
6
- let buildAjvCode = ''
7
- let ajvSchemasCode = ''
8
-
9
- if (isValidatorUsed) {
10
- let defaultAjvSchema = ''
11
- // we need to export the custom json schema
12
- const defaultMeta = validator.ajv.defaultMeta()
13
- if (typeof defaultMeta === 'string') {
14
- defaultAjvSchema = defaultMeta
15
- } else {
16
- defaultAjvSchema = defaultMeta.$id || defaultMeta.id
17
- }
18
-
19
- ajvSchemasCode += `const validator = new Validator(${JSON.stringify(options.ajv || {})})\n`
20
- for (const [id, schema] of Object.entries(validator.ajv.schemas)) {
21
- // should skip ajv default schema
22
- if (id === defaultAjvSchema) continue
23
- ajvSchemasCode += `validator.ajv.addSchema(${JSON.stringify(schema.schema)}, "${id}")\n`
24
- }
25
- buildAjvCode = fs.readFileSync(path.join(__dirname, 'validator.js')).toString()
26
- buildAjvCode = buildAjvCode.replace("'use strict'", '').replace('module.exports = SchemaValidator', '')
1
+ 'use strict'
2
+
3
+ function buildStandaloneCode (contextFunc, context, serializer, validator) {
4
+ let ajvDependencyCode = ''
5
+ if (context.validatorSchemasIds.size > 0) {
6
+ ajvDependencyCode += `const validatorState = ${JSON.stringify(validator.getState())}\n`
7
+ ajvDependencyCode += 'const validator = Validator.restoreFromState(validatorState)\n'
8
+ } else {
9
+ ajvDependencyCode += 'const validator = null\n'
27
10
  }
28
11
 
29
- const serializerOptions = options && options.rounding ? JSON.stringify({ options: options.rounding }) : ''
30
12
  return `
31
13
  'use strict'
32
- ${serializerCode.replace("'use strict'", '').replace('module.exports = ', '')}
33
- ${buildAjvCode}
34
- const serializer = new Serializer(${serializerOptions})
35
- ${ajvSchemasCode}
14
+ const { dependencies } = require('fast-json-stringify/lib/standalone')
15
+
16
+ const { Serializer, Validator } = dependencies
17
+
18
+ const serializerState = ${JSON.stringify(serializer.getState())}
19
+ const serializer = Serializer.restoreFromState(serializerState)
36
20
 
37
- ${contextFunctionCode.replace('return main', '')}
21
+ ${ajvDependencyCode}
38
22
 
39
- module.exports = main`
23
+ module.exports = ${contextFunc.toString()}(validator, serializer)`
40
24
  }
41
25
 
42
26
  module.exports = buildStandaloneCode
27
+
28
+ module.exports.dependencies = {
29
+ Serializer: require('./serializer'),
30
+ Validator: require('./validator')
31
+ }
package/lib/validator.js CHANGED
@@ -25,6 +25,9 @@ class Validator {
25
25
  return date instanceof Date
26
26
  }
27
27
  })
28
+
29
+ this._ajvSchemas = {}
30
+ this._ajvOptions = ajvOptions || {}
28
31
  }
29
32
 
30
33
  addSchema (schema, schemaName) {
@@ -40,6 +43,7 @@ class Validator {
40
43
  const ajvSchema = clone(schema)
41
44
  this.convertSchemaToAjvFormat(ajvSchema)
42
45
  this.ajv.addSchema(ajvSchema, schemaKey)
46
+ this._ajvSchemas[schemaKey] = schema
43
47
  }
44
48
  }
45
49
 
@@ -70,6 +74,21 @@ class Validator {
70
74
  }
71
75
  }
72
76
  }
77
+
78
+ getState () {
79
+ return {
80
+ ajvOptions: this._ajvOptions,
81
+ ajvSchemas: this._ajvSchemas
82
+ }
83
+ }
84
+
85
+ static restoreFromState (state) {
86
+ const validator = new Validator(state.ajvOptions)
87
+ for (const [id, ajvSchema] of Object.entries(state.ajvSchemas)) {
88
+ validator.ajv.addSchema(ajvSchema, id)
89
+ }
90
+ return validator
91
+ }
73
92
  }
74
93
 
75
94
  module.exports = Validator
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fast-json-stringify",
3
- "version": "5.6.2",
3
+ "version": "5.7.0",
4
4
  "description": "Stringify your JSON at max speed",
5
5
  "main": "index.js",
6
6
  "types": "types/index.d.ts",
@@ -34,7 +34,7 @@
34
34
  "homepage": "https://github.com/fastify/fast-json-stringify#readme",
35
35
  "devDependencies": {
36
36
  "@fastify/pre-commit": "^2.0.2",
37
- "@sinclair/typebox": "^0.25.2",
37
+ "@sinclair/typebox": "^0.26.5",
38
38
  "benchmark": "^2.1.4",
39
39
  "cli-select": "^1.1.2",
40
40
  "compile-json-stringify": "^0.1.2",
@@ -42,8 +42,9 @@
42
42
  "simple-git": "^3.7.1",
43
43
  "standard": "^17.0.0",
44
44
  "tap": "^16.0.1",
45
- "tsd": "^0.25.0",
46
- "webpack": "^5.40.0"
45
+ "tsd": "^0.28.0",
46
+ "webpack": "^5.40.0",
47
+ "fast-json-stringify": "."
47
48
  },
48
49
  "dependencies": {
49
50
  "@fastify/deepmerge": "^1.0.0",
@@ -35,6 +35,18 @@ test('render a float as an integer', (t) => {
35
35
  }
36
36
  })
37
37
 
38
+ test('throws on NaN', (t) => {
39
+ t.plan(1)
40
+
41
+ const schema = {
42
+ title: 'integer',
43
+ type: 'integer'
44
+ }
45
+
46
+ const stringify = build(schema)
47
+ t.throws(() => stringify(NaN), new Error('The value "NaN" cannot be converted to an integer.'))
48
+ })
49
+
38
50
  test('render a float as an integer', (t) => {
39
51
  const cases = [
40
52
  { input: Math.PI, output: '3' },
package/test/ref.test.js CHANGED
@@ -2078,3 +2078,42 @@ test('should throw an Error if two non-identical schemas with same id are provid
2078
2078
 
2079
2079
  t.throws(() => build(schema), new Error('There is already another schema with id inner_schema'))
2080
2080
  })
2081
+
2082
+ test('ref internal - throw if schema has definition twice with different shape', (t) => {
2083
+ t.plan(1)
2084
+
2085
+ const schema = {
2086
+ $id: 'test',
2087
+ title: 'object with $ref',
2088
+ definitions: {
2089
+ def: {
2090
+ $id: '#uri',
2091
+ type: 'object',
2092
+ properties: {
2093
+ str: {
2094
+ type: 'string'
2095
+ }
2096
+ },
2097
+ required: ['str']
2098
+ },
2099
+ def2: {
2100
+ $id: '#uri',
2101
+ type: 'object',
2102
+ properties: {
2103
+ num: {
2104
+ type: 'number'
2105
+ }
2106
+ },
2107
+ required: ['num']
2108
+ }
2109
+ },
2110
+ type: 'object',
2111
+ properties: {
2112
+ obj: {
2113
+ $ref: '#uri'
2114
+ }
2115
+ }
2116
+ }
2117
+
2118
+ t.throws(() => build(schema), Error('There is already another schema with id test##uri'))
2119
+ })