Socket
Socket
Sign inDemoInstall

fast-json-stringify

Package Overview
Dependencies
11
Maintainers
9
Versions
160
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 5.12.0 to 5.13.0

24

benchmark/bench.js

@@ -51,2 +51,10 @@ 'use strict'

{
name: 'unsafe short string',
schema: {
type: 'string',
format: 'unsafe'
},
input: 'hello world'
},
{
name: 'short string with double quote',

@@ -66,2 +74,10 @@ schema: {

{
name: 'unsafe long string without double quotes',
schema: {
type: 'string',
format: 'unsafe'
},
input: longSimpleString
},
{
name: 'long string',

@@ -74,2 +90,10 @@ schema: {

{
name: 'unsafe long string',
schema: {
type: 'string',
format: 'unsafe'
},
input: longString
},
{
name: 'number',

@@ -76,0 +100,0 @@ schema: {

18

index.js

@@ -728,4 +728,20 @@ 'use strict'

return `json += serializer.asTime(${input})`
} else if (schema.format === 'unsafe') {
return `json += serializer.asUnsafeString(${input})`
} else {
return `json += serializer.asString(${input})`
return `
if (typeof ${input} !== 'string') {
if (${input} === null) {
json += '""'
} else if (${input} instanceof Date) {
json += '"' + ${input}.toISOString() + '"'
} else if (${input} instanceof RegExp) {
json += serializer.asString(${input}.source)
} else {
json += serializer.asString(${input}.toString())
}
} else {
json += serializer.asString(${input})
}
`
}

@@ -732,0 +748,0 @@ }

28

lib/serializer.js

@@ -102,19 +102,6 @@ 'use strict'

asString (str) {
if (typeof str !== 'string') {
if (str === null) {
return '""'
}
if (str instanceof Date) {
return '"' + str.toISOString() + '"'
}
if (str instanceof RegExp) {
str = str.source
} else {
str = str.toString()
}
}
if (str.length < 42) {
return this.asStringSmall(str)
} else if (STR_ESCAPE.test(str) === false) {
} else if (str.length < 5000 && STR_ESCAPE.test(str) === false) {
// Only use the regular expression for shorter input. The overhead is otherwise too much.
return '"' + str + '"'

@@ -126,2 +113,6 @@ } else {

asUnsafeString (str) {
return '"' + str + '"'
}
// magically escape strings for json

@@ -142,9 +133,6 @@ // relying on their charCodeAt

point = str.charCodeAt(i)
if (point < 32) {
if (point < 32 || (point >= 0xD800 && point <= 0xDFFF)) {
// The current character is non-printable characters or a surrogate.
return JSON.stringify(str)
}
if (point >= 0xD800 && point <= 0xDFFF) {
// The current character is a surrogate.
return JSON.stringify(str)
}
if (

@@ -151,0 +139,0 @@ point === 0x22 || // '"'

{
"name": "fast-json-stringify",
"version": "5.12.0",
"version": "5.13.0",
"description": "Stringify your JSON at max speed",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -633,2 +633,20 @@ # fast-json-stringify

<a name="unsafe"></a>
#### Unsafe string
By default, the library escapes all strings. With the 'unsafe' format, the string isn't escaped. This has a potentially dangerous security issue. You can use it only if you are sure that your data doesn't need escaping. The advantage is a significant performance improvement.
Example:
```javascript
const stringify = fastJson({
title: 'Example Schema',
type: 'object',
properties: {
'code': {
type: 'string',
format 'unsafe'
}
}
})
```
##### Benchmarks

@@ -635,0 +653,0 @@

@@ -22,2 +22,8 @@ 'use strict'

buildTest({
title: 'string',
type: 'string',
format: 'unsafe'
}, 'hello world')
buildTest({
title: 'basic',

@@ -24,0 +30,0 @@ type: 'object',

@@ -51,1 +51,35 @@ 'use strict'

})
test('unsafe string', (t) => {
t.plan(2)
const schema = {
type: 'string',
format: 'unsafe'
}
const input = 'abcd'
const stringify = build(schema)
const output = stringify(input)
t.equal(output, `"${input}"`)
t.equal(JSON.parse(output), input)
})
test('unsafe unescaped string', (t) => {
t.plan(2)
const schema = {
type: 'string',
format: 'unsafe'
}
const input = 'abcd "abcd"'
const stringify = build(schema)
const output = stringify(input)
t.equal(output, `"${input}"`)
t.throws(function () {
JSON.parse(output)
})
})

@@ -211,2 +211,5 @@ import Ajv, { Options as AjvOptions } from "ajv"

type StringCoercible = string | Date | RegExp;
type IntegerCoercible = number | BigInt;
/**

@@ -221,4 +224,4 @@ * Build a stringify function using a schema of the documents that should be stringified

declare function build(schema: build.AnySchema, options?: build.Options): <TDoc = any>(doc: TDoc) => any;
declare function build(schema: build.StringSchema, options?: build.Options): <TDoc extends string = string>(doc: TDoc) => string;
declare function build(schema: build.IntegerSchema | build.NumberSchema, options?: build.Options): <TDoc extends number = number>(doc: TDoc) => string;
declare function build(schema: build.StringSchema, options?: build.Options): <TDoc extends StringCoercible = StringCoercible>(doc: TDoc) => string;
declare function build(schema: build.IntegerSchema | build.NumberSchema, options?: build.Options): <TDoc extends IntegerCoercible = IntegerCoercible>(doc: TDoc) => string;
declare function build(schema: build.NullSchema, options?: build.Options): <TDoc extends null = null>(doc: TDoc) => "null";

@@ -225,0 +228,0 @@ declare function build(schema: build.BooleanSchema, options?: build.Options): <TDoc extends boolean = boolean>(doc: TDoc) => string;

@@ -6,57 +6,58 @@ import Ajv from 'ajv'

// Number schemas
const schema1: Schema = {
build({
type: 'number'
}
const schema2: Schema = {
})(25)
build({
type: 'integer'
}
})(-5)
build({
type: 'integer'
})(5n)
build(schema1)(25)
build(schema2)(-5)
build({
type: 'number'
}, { rounding: 'ceil' })
build({
type: 'number'
}, { rounding: 'floor' })
build({
type: 'number'
}, { rounding: 'round' })
build({
type: 'number'
}, { rounding: 'trunc' })
expectError(build({
type: 'number'
}, { rounding: 'invalid' }))
build(schema2, { rounding: 'ceil' })
build(schema2, { rounding: 'floor' })
build(schema2, { rounding: 'round' })
build(schema2, { rounding: 'trunc' })
expectError(build(schema2, { rounding: 'invalid' }))
// String schema
const schema3: Schema = {
type: 'string'
}
build({
type: 'string'
})('foobar')
build(schema3)('foobar')
// Boolean schema
const schema4: Schema = {
build({
type: 'boolean'
}
})(true)
build(schema4)(true)
// Null schema
const schema5: Schema = {
build({
type: 'null'
}
})(null)
build(schema5)(null)
// Array schemas
const schema6: Schema = {
build({
type: 'array',
items: { type: 'number' }
}
const schema7: Schema = {
})([25])
build({
type: 'array',
items: [{ type: 'string'}, {type: 'integer'}]
}
})(['hello', 42])
build(schema6)([25])
build(schema7)(['hello', 42])
// Object schemas
const schema8: Schema = {
build({
type: 'object'
}
const schema9: Schema = {
})({})
build({
type: 'object',

@@ -74,10 +75,20 @@ properties: {

}
}
})({ foo: 'bar' })
build({
type: 'object',
properties: {
foo: { type: 'string' },
bar: { type: 'integer' }
},
required: ['foo'],
patternProperties: {
'baz*': { type: 'null' }
},
additionalProperties: {
type: 'boolean'
}
}, { rounding: 'floor' })({ foo: 'bar' })
build(schema8)({})
build(schema9)({ foo: 'bar' })
build(schema9, { rounding: 'floor' })({ foo: 'bar' })
// Reference schemas
const schema10: Schema = {
build({
title: 'Example Schema',

@@ -114,8 +125,6 @@ definitions: {

}
}
})({ nickname: '', num: { int: 5 }, other: null })
build(schema10)({ nickname: '', num: { int: 5 }, other: null })
// Conditional/Combined schemas
const schema11: Schema = {
build({
title: 'Conditional/Combined Schema',

@@ -146,20 +155,33 @@ type: 'object',

}
}
})({ something: 'a string', somethingElse: 42 })
build(schema11)({ something: 'a string', somethingElse: 42 })
// String schema with format
// String schema with format
const schema12: Schema = {
build({
type: 'string',
format: 'date-time'
}
})(new Date())
build(schema12)(new Date())
/*
This overload doesn't work yet -
TypeScript chooses the generic for the schema
before it chooses the overload for the options
parameter.
let str: string, ajv: Ajv
str = build(schema1, { debugMode: true }).code
ajv = build(schema1, { debugMode: true }).ajv
str = build(schema1, { mode: 'debug' }).code
ajv = build(schema1, { mode: 'debug' }).ajv
str = build(schema1, { mode: 'standalone' })
str = build({
type: 'number'
}, { debugMode: true }).code
ajv = build({
type: 'number'
}, { debugMode: true }).ajv
str = build({
type: 'number'
}, { mode: 'debug' }).code
ajv = build({
type: 'number'
}, { mode: 'debug' }).ajv
str = build({
type: 'number'
}, { mode: 'standalone' })
*/

@@ -166,0 +188,0 @@ const debugCompiled = build({

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc