Skip to content

Commit 17bb4c2

Browse files
authored
improve perf of asString (#632)
1 parent 8d72614 commit 17bb4c2

File tree

3 files changed

+69
-19
lines changed

3 files changed

+69
-19
lines changed

benchmark/bench.js

+19
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ function getRandomInt (max) {
1818
return Math.floor(Math.random() * max)
1919
}
2020

21+
let longSimpleString = ''
22+
for (let i = 0; i < LONG_STRING_LENGTH; i++) {
23+
longSimpleString += i
24+
}
25+
2126
let longString = ''
2227
for (let i = 0; i < LONG_STRING_LENGTH; i++) {
2328
longString += i
@@ -42,6 +47,20 @@ const benchmarks = [
4247
},
4348
input: 'hello world'
4449
},
50+
{
51+
name: 'short string with double quote',
52+
schema: {
53+
type: 'string'
54+
},
55+
input: 'hello " world'
56+
},
57+
{
58+
name: 'long string without double quotes',
59+
schema: {
60+
type: 'string'
61+
},
62+
input: longSimpleString
63+
},
4564
{
4665
name: 'long string',
4766
schema: {

lib/serializer.js

+17-18
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,10 @@ module.exports = class Serializer {
113113
}
114114
}
115115

116-
// Fast escape chars check
117-
if (!STR_ESCAPE.test(str)) {
118-
return '"' + str + '"'
119-
} else if (str.length < 42) {
116+
if (str.length < 42) {
120117
return this.asStringSmall(str)
118+
} else if (STR_ESCAPE.test(str) === false) {
119+
return '"' + str + '"'
121120
} else {
122121
return JSON.stringify(str)
123122
}
@@ -130,32 +129,32 @@ module.exports = class Serializer {
130129
// 34 and 92 happens all the time, so we
131130
// have a fast case for them
132131
asStringSmall (str) {
133-
const l = str.length
132+
const len = str.length
134133
let result = ''
135-
let last = 0
136-
let found = false
137-
let surrogateFound = false
134+
let last = -1
138135
let point = 255
136+
139137
// eslint-disable-next-line
140-
for (var i = 0; i < l && point >= 32; i++) {
138+
for (var i = 0; i < len; i++) {
141139
point = str.charCodeAt(i)
140+
if (point < 32) {
141+
return JSON.stringify(str)
142+
}
142143
if (point >= 0xD800 && point <= 0xDFFF) {
143144
// The current character is a surrogate.
144-
surrogateFound = true
145+
return JSON.stringify(str)
145146
}
146-
if (point === 34 || point === 92) {
147+
if (
148+
point === 0x22 || // '"'
149+
point === 0x5c // '\'
150+
) {
151+
last === -1 && (last = 0)
147152
result += str.slice(last, i) + '\\'
148153
last = i
149-
found = true
150154
}
151155
}
152156

153-
if (!found) {
154-
result = str
155-
} else {
156-
result += str.slice(last)
157-
}
158-
return ((point < 32) || (surrogateFound === true)) ? JSON.stringify(str) : '"' + result + '"'
157+
return (last === -1 && ('"' + str + '"')) || ('"' + result + str.slice(last) + '"')
159158
}
160159

161160
getState () {

test/basic.test.js

+33-1
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ test('patternProperties - throw on unknown type', (t) => {
344344
}
345345
})
346346

347-
test('render a single quote as JSON', (t) => {
347+
test('render a double quote as JSON /1', (t) => {
348348
t.plan(2)
349349

350350
const schema = {
@@ -360,6 +360,38 @@ test('render a single quote as JSON', (t) => {
360360
t.ok(validate(JSON.parse(output)), 'valid schema')
361361
})
362362

363+
test('render a double quote as JSON /2', (t) => {
364+
t.plan(2)
365+
366+
const schema = {
367+
type: 'string'
368+
}
369+
const toStringify = 'double quote " 2'
370+
371+
const validate = validator(schema)
372+
const stringify = build(schema)
373+
const output = stringify(toStringify)
374+
375+
t.equal(output, JSON.stringify(toStringify))
376+
t.ok(validate(JSON.parse(output)), 'valid schema')
377+
})
378+
379+
test('render a long string', (t) => {
380+
t.plan(2)
381+
382+
const schema = {
383+
type: 'string'
384+
}
385+
const toStringify = 'the Ultimate Question of Life, the Universe, and Everything.'
386+
387+
const validate = validator(schema)
388+
const stringify = build(schema)
389+
const output = stringify(toStringify)
390+
391+
t.equal(output, JSON.stringify(toStringify))
392+
t.ok(validate(JSON.parse(output)), 'valid schema')
393+
})
394+
363395
test('returns JSON.stringify if schema type is boolean', t => {
364396
t.plan(1)
365397

0 commit comments

Comments
 (0)