diff --git a/lib/serializer.js b/lib/serializer.js index 1ad588a1..24917433 100644 --- a/lib/serializer.js +++ b/lib/serializer.js @@ -24,38 +24,29 @@ 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) { - return '0' + if (Number.isInteger(i)) { + return '' + i } 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.`) - } } + /* eslint no-undef: "off" */ + const integer = this.parseInteger(i) + // check if number is Infinity or NaN + // eslint-disable-next-line no-self-compare + if (integer === Infinity || integer === -Infinity || integer !== integer) { + throw new Error(`The value "${i}" cannot be converted to an integer.`) + } + return '' + integer } asNumber (i) { - const num = Number(i) + // fast cast to number + const num = +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)) { + } else if (num === Infinity || num === -Infinity) { return 'null' } else { return '' + num @@ -100,9 +91,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 { @@ -114,37 +130,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 }