Skip to content

Commit e528990

Browse files
authored
perf(json): avoid first-char regex for direct JSON bodies (#744)
Skip the RFC 7159 whitespace scan when strict JSON bodies start directly with `{` or `[`. This avoids regex execution on the common valid path while preserving strict-mode handling for leading whitespace and primitive values. Update the first non-whitespace regex to match end-of-string so whitespace-only bodies return `undefined` without relying on a failed match/backtracking path.
1 parent 1c119ae commit e528990

1 file changed

Lines changed: 11 additions & 11 deletions

File tree

lib/types/json.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const { normalizeOptions } = require('../utils')
2323
module.exports = json
2424

2525
/**
26-
* RegExp to match the first non-space in a string.
26+
* RegExp to match the first non-whitespace character in a string.
2727
*
2828
* Allowed whitespace is defined in RFC 7159:
2929
*
@@ -33,7 +33,7 @@ module.exports = json
3333
* %x0A / ; Line feed or New line
3434
* %x0D ) ; Carriage return
3535
*/
36-
const FIRST_CHAR_REGEXP = /^[\x20\x09\x0a\x0d]*([^\x20\x09\x0a\x0d])/ // eslint-disable-line no-control-regex
36+
const FIRST_NON_WHITESPACE_REGEXP = /^[\x20\x09\x0a\x0d]*([^\x20\x09\x0a\x0d]|$)/ // eslint-disable-line no-control-regex
3737

3838
const JSON_SYNTAX_CHAR = '#'
3939
const JSON_SYNTAX_REGEXP = /#+/g
@@ -80,10 +80,12 @@ function createJsonParser (options) {
8080
return {}
8181
}
8282

83-
const first = firstchar(body)
84-
if (first !== '{' && first !== '[') {
85-
debug('strict violation')
86-
throw createStrictSyntaxError(body, first)
83+
if (body[0] !== '{' && body[0] !== '[') {
84+
const first = firstNonWhitespaceChar(body)
85+
if (first !== '{' && first !== '[') {
86+
debug('strict violation')
87+
throw createStrictSyntaxError(body, first)
88+
}
8789
}
8890

8991
try {
@@ -152,12 +154,10 @@ function createStrictSyntaxError (str, char) {
152154
* @returns {string|undefined}
153155
* @private
154156
*/
155-
function firstchar (str) {
156-
const match = FIRST_CHAR_REGEXP.exec(str)
157+
function firstNonWhitespaceChar (str) {
158+
const match = FIRST_NON_WHITESPACE_REGEXP.exec(str)
157159

158-
return match
159-
? match[1]
160-
: undefined
160+
return match && match[1] ? match[1] : undefined
161161
}
162162

163163
/**

0 commit comments

Comments
 (0)