fast-json-stringify
Advanced tools
Comparing version 5.14.1 to 5.15.0
106
index.js
@@ -143,3 +143,15 @@ 'use strict' | ||
let contextFunctionCode | ||
let contextFunctionCode = ` | ||
const JSON_STR_BEGIN_OBJECT = '{' | ||
const JSON_STR_END_OBJECT = '}' | ||
const JSON_STR_BEGIN_ARRAY = '[' | ||
const JSON_STR_END_ARRAY = ']' | ||
const JSON_STR_COMMA = ',' | ||
const JSON_STR_COLONS = ':' | ||
const JSON_STR_QUOTE = '"' | ||
const JSON_STR_EMPTY_OBJECT = JSON_STR_BEGIN_OBJECT + JSON_STR_END_OBJECT | ||
const JSON_STR_EMPTY_ARRAY = JSON_STR_BEGIN_ARRAY + JSON_STR_END_ARRAY | ||
const JSON_STR_EMPTY_STRING = JSON_STR_QUOTE + JSON_STR_QUOTE | ||
const JSON_STR_NULL = 'null' | ||
` | ||
@@ -152,3 +164,3 @@ // If we have only the invocation of the 'anonymous0' function, we would | ||
if (code === 'json += anonymous0(input)') { | ||
contextFunctionCode = ` | ||
contextFunctionCode += ` | ||
${context.functions.join('\n')} | ||
@@ -159,3 +171,3 @@ const main = anonymous0 | ||
} else { | ||
contextFunctionCode = ` | ||
contextFunctionCode += ` | ||
function main (input) { | ||
@@ -290,3 +302,3 @@ let json = '' | ||
${addComma} | ||
json += serializer.asString(key) + ':' | ||
json += serializer.asString(key) + JSON_STR_COLONS | ||
${buildValue(context, propertyLocation, 'value')} | ||
@@ -306,3 +318,3 @@ continue | ||
${addComma} | ||
json += serializer.asString(key) + ':' + JSON.stringify(value) | ||
json += serializer.asString(key) + JSON_STR_COLONS + JSON.stringify(value) | ||
` | ||
@@ -313,3 +325,3 @@ } else { | ||
${addComma} | ||
json += serializer.asString(key) + ':' | ||
json += serializer.asString(key) + JSON_STR_COLONS | ||
${buildValue(context, propertyLocation, 'value')} | ||
@@ -342,3 +354,3 @@ ` | ||
let code = '' | ||
let code = 'let value\n' | ||
@@ -351,3 +363,3 @@ for (const key of requiredProperties) { | ||
code += 'let json = \'{\'\n' | ||
code += 'let json = JSON_STR_BEGIN_OBJECT\n' | ||
@@ -357,3 +369,3 @@ let addComma = '' | ||
code += 'let addComma = false\n' | ||
addComma = '!addComma && (addComma = true) || (json += \',\')' | ||
addComma = '!addComma && (addComma = true) || (json += JSON_STR_COMMA)' | ||
} | ||
@@ -372,6 +384,7 @@ | ||
code += ` | ||
if (obj[${sanitizedKey}] !== undefined) { | ||
value = obj[${sanitizedKey}] | ||
if (value !== undefined) { | ||
${addComma} | ||
json += ${JSON.stringify(sanitizedKey + ':')} | ||
${buildValue(context, propertyLocation, `obj[${sanitizedKey}]`)} | ||
${buildValue(context, propertyLocation, 'value')} | ||
}` | ||
@@ -404,3 +417,3 @@ | ||
code += ` | ||
return json + '}' | ||
return json + JSON_STR_END_OBJECT | ||
` | ||
@@ -496,3 +509,3 @@ return code | ||
const obj = ${toJSON('input')} | ||
${!nullable ? 'if (obj === null) return \'{}\'' : ''} | ||
${!nullable ? 'if (obj === null) return JSON_STR_EMPTY_OBJECT' : ''} | ||
@@ -538,3 +551,3 @@ ${buildInnerObject(context, location)} | ||
functionCode += ` | ||
${!nullable ? 'if (obj === null) return \'[]\'' : ''} | ||
${!nullable ? 'if (obj === null) return JSON_STR_EMPTY_ARRAY' : ''} | ||
if (!Array.isArray(obj)) { | ||
@@ -555,7 +568,9 @@ throw new TypeError(\`The value of '${schemaRef}' does not match schema definition.\`) | ||
if (largeArrayMechanism === 'json-stringify') { | ||
functionCode += `if (arrayLength && arrayLength >= ${largeArraySize}) return JSON.stringify(obj)\n` | ||
functionCode += `if (arrayLength >= ${largeArraySize}) return JSON.stringify(obj)\n` | ||
} | ||
functionCode += ` | ||
let jsonOutput = '' | ||
const arrayEnd = arrayLength - 1 | ||
let value | ||
let json = '' | ||
` | ||
@@ -566,11 +581,10 @@ | ||
const item = itemsSchema[i] | ||
const tmpRes = buildValue(context, itemsLocation.getPropertyLocation(i), `obj[${i}]`) | ||
functionCode += `value = obj[${i}]` | ||
const tmpRes = buildValue(context, itemsLocation.getPropertyLocation(i), 'value') | ||
functionCode += ` | ||
if (${i} < arrayLength) { | ||
if (${buildArrayTypeCondition(item.type, `[${i}]`)}) { | ||
let json = '' | ||
${tmpRes} | ||
jsonOutput += json | ||
if (${i} < arrayLength - 1) { | ||
jsonOutput += ',' | ||
if (${i} < arrayEnd) { | ||
json += JSON_STR_COMMA | ||
} | ||
@@ -587,5 +601,5 @@ } else { | ||
for (let i = ${itemsSchema.length}; i < arrayLength; i++) { | ||
jsonOutput += JSON.stringify(obj[i]) | ||
if (i < arrayLength - 1) { | ||
jsonOutput += ',' | ||
json += JSON.stringify(obj[i]) | ||
if (i < arrayEnd) { | ||
json += JSON_STR_COMMA | ||
} | ||
@@ -598,7 +612,5 @@ }` | ||
for (let i = 0; i < arrayLength; i++) { | ||
let json = '' | ||
${code} | ||
jsonOutput += json | ||
if (i < arrayLength - 1) { | ||
jsonOutput += ',' | ||
if (i < arrayEnd) { | ||
json += JSON_STR_COMMA | ||
} | ||
@@ -609,3 +621,3 @@ }` | ||
functionCode += ` | ||
return \`[\${jsonOutput}]\` | ||
return JSON_STR_BEGIN_ARRAY + json + JSON_STR_END_ARRAY | ||
}` | ||
@@ -621,29 +633,29 @@ | ||
case 'null': | ||
condition = `obj${accessor} === null` | ||
condition = 'value === null' | ||
break | ||
case 'string': | ||
condition = `typeof obj${accessor} === 'string' || | ||
obj${accessor} === null || | ||
obj${accessor} instanceof Date || | ||
obj${accessor} instanceof RegExp || | ||
condition = `typeof value === 'string' || | ||
value === null || | ||
value instanceof Date || | ||
value instanceof RegExp || | ||
( | ||
typeof obj${accessor} === "object" && | ||
typeof obj${accessor}.toString === "function" && | ||
obj${accessor}.toString !== Object.prototype.toString | ||
typeof value === "object" && | ||
typeof value.toString === "function" && | ||
value.toString !== Object.prototype.toString | ||
)` | ||
break | ||
case 'integer': | ||
condition = `Number.isInteger(obj${accessor})` | ||
condition = 'Number.isInteger(value)' | ||
break | ||
case 'number': | ||
condition = `Number.isFinite(obj${accessor})` | ||
condition = 'Number.isFinite(value)' | ||
break | ||
case 'boolean': | ||
condition = `typeof obj${accessor} === 'boolean'` | ||
condition = 'typeof value === \'boolean\'' | ||
break | ||
case 'object': | ||
condition = `obj${accessor} && typeof obj${accessor} === 'object' && obj${accessor}.constructor === Object` | ||
condition = 'value && typeof value === \'object\' && value.constructor === Object' | ||
break | ||
case 'array': | ||
condition = `Array.isArray(obj${accessor})` | ||
condition = 'Array.isArray(value)' | ||
break | ||
@@ -739,3 +751,3 @@ default: | ||
case 'null': | ||
return 'json += \'null\'' | ||
return 'json += JSON_STR_NULL' | ||
case 'string': { | ||
@@ -754,5 +766,5 @@ if (schema.format === 'date-time') { | ||
if (${input} === null) { | ||
json += '""' | ||
json += JSON_STR_EMPTY_STRING | ||
} else if (${input} instanceof Date) { | ||
json += '"' + ${input}.toISOString() + '"' | ||
json += JSON_STR_QUOTE + ${input}.toISOString() + JSON_STR_QUOTE | ||
} else if (${input} instanceof RegExp) { | ||
@@ -801,3 +813,3 @@ json += serializer.asString(${input}.source) | ||
if (${input} === null) { | ||
json += 'null' | ||
json += JSON_STR_NULL | ||
} else { | ||
@@ -1009,3 +1021,3 @@ ` | ||
if (${input} === null) { | ||
json += 'null' | ||
json += JSON_STR_NULL | ||
} else { | ||
@@ -1012,0 +1024,0 @@ ` |
@@ -27,29 +27,20 @@ 'use strict' | ||
asInteger (i) { | ||
if (typeof i === 'number') { | ||
if (Number.isInteger(i)) { | ||
return '' + i | ||
} | ||
// check if number is Infinity or NaN | ||
// eslint-disable-next-line no-self-compare | ||
if (i === Infinity || i === -Infinity || i !== i) { | ||
throw new Error(`The value "${i}" cannot be converted to an integer.`) | ||
} | ||
return this.parseInteger(i) | ||
} else if (i === null) { | ||
return '0' | ||
if (Number.isInteger(i)) { | ||
return '' + i | ||
} else if (typeof i === 'bigint') { | ||
return i.toString() | ||
} else { | ||
/* eslint no-undef: "off" */ | ||
const integer = this.parseInteger(i) | ||
if (Number.isFinite(integer)) { | ||
return '' + integer | ||
} else { | ||
throw new Error(`The value "${i}" cannot be converted to an integer.`) | ||
} | ||
} | ||
/* eslint no-undef: "off" */ | ||
const integer = this.parseInteger(i) | ||
// check if number is Infinity or NaN | ||
// eslint-disable-next-line no-self-compare | ||
if (integer === Infinity || integer === -Infinity || integer !== integer) { | ||
throw new Error(`The value "${i}" cannot be converted to an integer.`) | ||
} | ||
return '' + integer | ||
} | ||
asNumber (i) { | ||
const num = Number(i) | ||
// fast cast to number | ||
const num = +i | ||
// check if number is NaN | ||
@@ -59,3 +50,3 @@ // eslint-disable-next-line no-self-compare | ||
throw new Error(`The value "${i}" cannot be converted to a number.`) | ||
} else if (!Number.isFinite(num)) { | ||
} else if (num === Infinity || num === -Infinity) { | ||
return 'null' | ||
@@ -105,5 +96,30 @@ } else { | ||
asString (str) { | ||
if (str.length < 42) { | ||
return this.asStringSmall(str) | ||
} else if (str.length < 5000 && STR_ESCAPE.test(str) === false) { | ||
const len = str.length | ||
if (len < 42) { | ||
// magically escape strings for json | ||
// relying on their charCodeAt | ||
// everything below 32 needs JSON.stringify() | ||
// every string that contain surrogate needs JSON.stringify() | ||
// 34 and 92 happens all the time, so we | ||
// have a fast case for them | ||
let result = '' | ||
let last = -1 | ||
let point = 255 | ||
// eslint-disable-next-line | ||
for (var i = 0; i < len; i++) { | ||
point = str.charCodeAt(i) | ||
if ( | ||
point === 0x22 || // '"' | ||
point === 0x5c // '\' | ||
) { | ||
last === -1 && (last = 0) | ||
result += str.slice(last, i) + '\\' | ||
last = i | ||
} else if (point < 32 || (point >= 0xD800 && point <= 0xDFFF)) { | ||
// The current character is non-printable characters or a surrogate. | ||
return JSON.stringify(str) | ||
} | ||
} | ||
return (last === -1 && ('"' + str + '"')) || ('"' + result + str.slice(last) + '"') | ||
} else if (len < 5000 && STR_ESCAPE.test(str) === false) { | ||
// Only use the regular expression for shorter input. The overhead is otherwise too much. | ||
@@ -120,33 +136,2 @@ return '"' + str + '"' | ||
// magically escape strings for json | ||
// relying on their charCodeAt | ||
// everything below 32 needs JSON.stringify() | ||
// every string that contain surrogate needs JSON.stringify() | ||
// 34 and 92 happens all the time, so we | ||
// have a fast case for them | ||
asStringSmall (str) { | ||
const len = str.length | ||
let result = '' | ||
let last = -1 | ||
let point = 255 | ||
// eslint-disable-next-line | ||
for (var i = 0; i < len; i++) { | ||
point = str.charCodeAt(i) | ||
if ( | ||
point === 0x22 || // '"' | ||
point === 0x5c // '\' | ||
) { | ||
last === -1 && (last = 0) | ||
result += str.slice(last, i) + '\\' | ||
last = i | ||
} else if (point < 32 || (point >= 0xD800 && point <= 0xDFFF)) { | ||
// The current character is non-printable characters or a surrogate. | ||
return JSON.stringify(str) | ||
} | ||
} | ||
return (last === -1 && ('"' + str + '"')) || ('"' + result + str.slice(last) + '"') | ||
} | ||
getState () { | ||
@@ -153,0 +138,0 @@ return this._options |
{ | ||
"name": "fast-json-stringify", | ||
"version": "5.14.1", | ||
"version": "5.15.0", | ||
"description": "Stringify your JSON at max speed", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
364493