Skip to content

Commit 0fdf19e

Browse files
authored
perf: cache json strings into const (#713)
1 parent 43919dc commit 0fdf19e

File tree

1 file changed

+32
-20
lines changed

1 file changed

+32
-20
lines changed

index.js

+32-20
Original file line numberDiff line numberDiff line change
@@ -140,21 +140,33 @@ function build (schema, options) {
140140
const location = new Location(schema, context.rootSchemaId)
141141
const code = buildValue(context, location, 'input')
142142

143-
let contextFunctionCode
143+
let contextFunctionCode = `
144+
const JSON_STR_BEGIN_OBJECT = '{'
145+
const JSON_STR_END_OBJECT = '}'
146+
const JSON_STR_BEGIN_ARRAY = '['
147+
const JSON_STR_END_ARRAY = ']'
148+
const JSON_STR_COMMA = ','
149+
const JSON_STR_COLONS = ':'
150+
const JSON_STR_QUOTE = '"'
151+
const JSON_STR_EMPTY_OBJECT = JSON_STR_BEGIN_OBJECT + JSON_STR_END_OBJECT
152+
const JSON_STR_EMPTY_ARRAY = JSON_STR_BEGIN_ARRAY + JSON_STR_END_ARRAY
153+
const JSON_STR_EMPTY_STRING = JSON_STR_QUOTE + JSON_STR_QUOTE
154+
const JSON_STR_NULL = 'null'
155+
`
144156

145157
// If we have only the invocation of the 'anonymous0' function, we would
146158
// basically just wrap the 'anonymous0' function in the 'main' function and
147159
// and the overhead of the intermediate variable 'json'. We can avoid the
148160
// wrapping and the unnecessary memory allocation by aliasing 'anonymous0' to
149161
// 'main'
150162
if (code === 'json += anonymous0(input)') {
151-
contextFunctionCode = `
163+
contextFunctionCode += `
152164
${context.functions.join('\n')}
153165
const main = anonymous0
154166
return main
155167
`
156168
} else {
157-
contextFunctionCode = `
169+
contextFunctionCode += `
158170
function main (input) {
159171
let json = ''
160172
${code}
@@ -284,7 +296,7 @@ function buildExtraObjectPropertiesSerializer (context, location, addComma) {
284296
code += `
285297
if (/${propertyKey.replace(/\\*\//g, '\\/')}/.test(key)) {
286298
${addComma}
287-
json += serializer.asString(key) + ':'
299+
json += serializer.asString(key) + JSON_STR_COLONS
288300
${buildValue(context, propertyLocation, 'value')}
289301
continue
290302
}
@@ -299,13 +311,13 @@ function buildExtraObjectPropertiesSerializer (context, location, addComma) {
299311
if (additionalPropertiesSchema === true) {
300312
code += `
301313
${addComma}
302-
json += serializer.asString(key) + ':' + JSON.stringify(value)
314+
json += serializer.asString(key) + JSON_STR_COLONS + JSON.stringify(value)
303315
`
304316
} else {
305317
const propertyLocation = location.getPropertyLocation('additionalProperties')
306318
code += `
307319
${addComma}
308-
json += serializer.asString(key) + ':'
320+
json += serializer.asString(key) + JSON_STR_COLONS
309321
${buildValue(context, propertyLocation, 'value')}
310322
`
311323
}
@@ -341,12 +353,12 @@ function buildInnerObject (context, location) {
341353
}
342354
}
343355

344-
code += 'let json = \'{\'\n'
356+
code += 'let json = JSON_STR_BEGIN_OBJECT\n'
345357

346358
let addComma = ''
347359
if (!hasRequiredProperties) {
348360
code += 'let addComma = false\n'
349-
addComma = '!addComma && (addComma = true) || (json += \',\')'
361+
addComma = '!addComma && (addComma = true) || (json += JSON_STR_COMMA)'
350362
}
351363

352364
for (const key of propertiesKeys) {
@@ -392,7 +404,7 @@ function buildInnerObject (context, location) {
392404
}
393405

394406
code += `
395-
return json + '}'
407+
return json + JSON_STR_END_OBJECT
396408
`
397409
return code
398410
}
@@ -483,7 +495,7 @@ function buildObject (context, location) {
483495
// ${schemaRef}
484496
function ${functionName} (input) {
485497
const obj = ${toJSON('input')}
486-
${!nullable ? 'if (obj === null) return \'{}\'' : ''}
498+
${!nullable ? 'if (obj === null) return JSON_STR_EMPTY_OBJECT' : ''}
487499
488500
${buildInnerObject(context, location)}
489501
}
@@ -524,7 +536,7 @@ function buildArray (context, location) {
524536

525537
const nullable = schema.nullable === true
526538
functionCode += `
527-
${!nullable ? 'if (obj === null) return \'[]\'' : ''}
539+
${!nullable ? 'if (obj === null) return JSON_STR_EMPTY_ARRAY' : ''}
528540
if (!Array.isArray(obj)) {
529541
throw new TypeError(\`The value of '${schemaRef}' does not match schema definition.\`)
530542
}
@@ -559,7 +571,7 @@ function buildArray (context, location) {
559571
if (${buildArrayTypeCondition(item.type, `[${i}]`)}) {
560572
${tmpRes}
561573
if (${i} < arrayEnd) {
562-
json += ','
574+
json += JSON_STR_COMMA
563575
}
564576
} else {
565577
throw new Error(\`Item at ${i} does not match schema definition.\`)
@@ -573,7 +585,7 @@ function buildArray (context, location) {
573585
for (let i = ${itemsSchema.length}; i < arrayLength; i++) {
574586
json += JSON.stringify(obj[i])
575587
if (i < arrayEnd) {
576-
json += ','
588+
json += JSON_STR_COMMA
577589
}
578590
}`
579591
}
@@ -583,13 +595,13 @@ function buildArray (context, location) {
583595
for (let i = 0; i < arrayLength; i++) {
584596
${code}
585597
if (i < arrayEnd) {
586-
json += ','
598+
json += JSON_STR_COMMA
587599
}
588600
}`
589601
}
590602

591603
functionCode += `
592-
return \`[\${json}]\`
604+
return JSON_STR_BEGIN_ARRAY + json + JSON_STR_END_ARRAY
593605
}`
594606

595607
context.functions.push(functionCode)
@@ -717,7 +729,7 @@ function buildSingleTypeSerializer (context, location, input) {
717729

718730
switch (schema.type) {
719731
case 'null':
720-
return 'json += \'null\''
732+
return 'json += JSON_STR_NULL'
721733
case 'string': {
722734
if (schema.format === 'date-time') {
723735
return `json += serializer.asDateTime(${input})`
@@ -731,9 +743,9 @@ function buildSingleTypeSerializer (context, location, input) {
731743
return `
732744
if (typeof ${input} !== 'string') {
733745
if (${input} === null) {
734-
json += '""'
746+
json += JSON_STR_EMPTY_STRING
735747
} else if (${input} instanceof Date) {
736-
json += '"' + ${input}.toISOString() + '"'
748+
json += JSON_STR_QUOTE + ${input}.toISOString() + JSON_STR_QUOTE
737749
} else if (${input} instanceof RegExp) {
738750
json += serializer.asString(${input}.source)
739751
} else {
@@ -777,7 +789,7 @@ function buildConstSerializer (location, input) {
777789
if (hasNullType) {
778790
code += `
779791
if (${input} === null) {
780-
json += 'null'
792+
json += JSON_STR_NULL
781793
} else {
782794
`
783795
}
@@ -984,7 +996,7 @@ function buildValue (context, location, input) {
984996
if (nullable) {
985997
code += `
986998
if (${input} === null) {
987-
json += 'null'
999+
json += JSON_STR_NULL
9881000
} else {
9891001
`
9901002
}

0 commit comments

Comments
 (0)