Skip to content

Commit

Permalink
perf: avoid unnecessary operation for improve performance
Browse files Browse the repository at this point in the history
  • Loading branch information
cesco69 committed Mar 19, 2024
1 parent 7051fe6 commit d5fab3e
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 59 deletions.
96 changes: 41 additions & 55 deletions lib/serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,41 +24,33 @@ module.exports = class Serializer {
}

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) {
if (i === null) {
return '0'
} 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.`)
i = this.parseInteger(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 cannot be converted to an integer.')
}
return '' + i
}
}

asNumber (i) {
const num = Number(i)
// fast cast to number
i = +i
// check if number is NaN
// eslint-disable-next-line no-self-compare
if (num !== num) {
throw new Error(`The value "${i}" cannot be converted to a number.`)
} else if (!Number.isFinite(num)) {
if (i !== i) {
throw new Error('The value cannot be converted to a number.')
} else if (i === Infinity || i === -Infinity) {
return 'null'
} else {
return '' + num
return '' + i
}
}

Expand Down Expand Up @@ -100,9 +92,34 @@ module.exports = class Serializer {
}

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.
return '"' + str + '"'
} else {
Expand All @@ -114,37 +131,6 @@ module.exports = class Serializer {
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 () {
return this._options
}
Expand Down
2 changes: 1 addition & 1 deletion test/fix-604.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ const render = fjs(schema)
try {
render(input)
} catch (err) {
t.equal(err.message, 'The value "phone" cannot be converted to a number.')
t.equal(err.message, 'The value cannot be converted to a number.')
}
2 changes: 1 addition & 1 deletion test/infinity.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ test('Infinite integers', t => {
try {
stringify(v)
} catch (err) {
t.equal(err.message, `The value "${v}" cannot be converted to an integer.`)
t.equal(err.message, 'The value cannot be converted to an integer.')
}
})
})
Expand Down
2 changes: 1 addition & 1 deletion test/integer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ test('throws on NaN', (t) => {
}

const stringify = build(schema)
t.throws(() => stringify(NaN), new Error('The value "NaN" cannot be converted to an integer.'))
t.throws(() => stringify(NaN), new Error('The value cannot be converted to an integer.'))
})

test('render a float as an integer', (t) => {
Expand Down
2 changes: 1 addition & 1 deletion test/required.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ test('required numbers', (t) => {
})
t.fail()
} catch (e) {
t.equal(e.message, 'The value "aaa" cannot be converted to an integer.')
t.equal(e.message, 'The value cannot be converted to an integer.')
t.pass()
}
})

0 comments on commit d5fab3e

Please sign in to comment.