diff --git a/benchmark/bench.js b/benchmark/bench.js index acb87b94..cd4bda87 100644 --- a/benchmark/bench.js +++ b/benchmark/bench.js @@ -40,6 +40,13 @@ for (let i = 0; i < SHORT_ARRAY_SIZE; i++) { } const benchmarks = [ + { + name: 'empty string', + schema: { + type: 'string' + }, + input: '' + }, { name: 'short string', schema: { diff --git a/lib/serializer.js b/lib/serializer.js index d8ff4b87..eadaa074 100644 --- a/lib/serializer.js +++ b/lib/serializer.js @@ -1,7 +1,7 @@ 'use strict' // eslint-disable-next-line -const STR_ESCAPE = /[\u0000-\u001f\u0022\u005c\ud800-\udfff]/ +const ASCII_ESCAPE = /[\u0000-\u001f\u0022\u005c]/ module.exports = class Serializer { constructor (options) { @@ -92,6 +92,7 @@ module.exports = class Serializer { asString (str) { const len = str.length + if (len === 0) { return '""' } else if (len < 42) { @@ -113,13 +114,13 @@ module.exports = class Serializer { last === -1 && (last = 0) result += str.slice(last, i) + '\\' last = i - } else if (point < 32 || (point >= 0xD800 && point <= 0xDFFF)) { + } 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) { + } else if (len < 5000 && str.isWellFormed() && ASCII_ESCAPE.test(str) === false) { // Only use the regular expression for shorter input. The overhead is otherwise too much. return '"' + str + '"' } else { diff --git a/test/string.test.js b/test/string.test.js index 518513da..0b3a76c8 100644 --- a/test/string.test.js +++ b/test/string.test.js @@ -34,6 +34,21 @@ test('serialize short string', (t) => { t.assert.equal(JSON.parse(output), input) }) +test('serialize medium string', (t) => { + t.plan(2) + + const schema = { + type: 'string' + } + + const input = new Array(150).fill('\x00').join('') + const stringify = build(schema) + const output = stringify(input) + + t.assert.equal(output, `"${new Array(150).fill('\\u0000').join('')}"`) + t.assert.equal(JSON.parse(output), input) +}) + test('serialize long string', (t) => { t.plan(2)