Skip to content

Commit

Permalink
Simplify big int marker.
Browse files Browse the repository at this point in the history
Signed-off-by: dblock <dblock@amazon.com>
  • Loading branch information
dblock committed Jul 13, 2023
1 parent 97c808a commit 0f85ac1
Showing 1 changed file with 5 additions and 57 deletions.
62 changes: 5 additions & 57 deletions lib/Serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ const bigIntMatcher = new RegExp(
'g'
);

const bigIntMarker = 'L';

class Serializer {
constructor(opts = {}) {
const disable = opts.disablePrototypePoisoningProtection;
Expand All @@ -98,59 +100,7 @@ class Serializer {
};
}

/* The characters with a highly unlikely chance of occurrence in strings, alone or in combination.
*
* ToDo: When support for ancient versions of Node.js are dropped, replace with
* _bigIntMarkChars = ['෴', '߷', '֍'];
*/
get _bigIntMarkChars() {
return ['෴', '߷', '֍'];
}

/* Generates an array of all combinations of `_bigIntMarkChars` with the requested length. */
_bigIntMarkerCombinations(length = 3) {
const results = [];
const arr = this._bigIntMarkChars;
const arrLength = arr.length;
const temp = Array(length);

(function fill(pos, start) {
if (pos === length) return results.push(temp.join(''));

for (let i = start; i < arrLength; i++) {
temp[pos] = arr[i];
fill(pos + 1, i);
}
})(0, 0);

return results;
}

/* Experiments with different combinations of various lengths, until one is found to not be in
* the input string.
*/
_getSuitableBigIntMarker(json) {
let bigIntMarker;
let length = 0;
do {
length++;
this._bigIntMarkerCombinations(length).some((marker) => {
if (json.indexOf(marker) === -1) {
bigIntMarker = marker;
return true;
}
});
} while (!bigIntMarker);

return {
bigIntMarker,
length,
};
}

_parseWithBigInt(json) {
const { bigIntMarker, length } = this._getSuitableBigIntMarker(json);

let hadException;
let markedJSON = json.replace(bigIntMatcher, `$1"${bigIntMarker}$2"$3`);

Expand Down Expand Up @@ -218,15 +168,13 @@ class Serializer {
* The `startsWith` is purely for performance, to avoid running `test` if not needed.
*/
typeof val === 'string' && val.startsWith(bigIntMarker) && bigIntMarkFinder.test(val)
? BigInt(val.substring(length)) // eslint-disable-line no-undef
? BigInt(val.substring(1)) // eslint-disable-line no-undef
: val,
this[kJsonOptions]
);
}

_stringifyWithBigInt(object, candidate) {
const { bigIntMarker } = this._getSuitableBigIntMarker(candidate);

_stringifyWithBigInt(object) {
/* The matcher that looks for "<marker><numerals>"
* Because we have made sure that `bigIntMarker` was never present in the original object, we can
* carelessly assume every "<marker><numerals>" is due to our marking.
Expand Down Expand Up @@ -262,7 +210,7 @@ class Serializer {
json = JSON.stringify(object, isBigIntSupported ? checkForBigInts : null);

if (isBigIntSupported && !numeralsAreNumbers) {
const temp = this._stringifyWithBigInt(object, json);
const temp = this._stringifyWithBigInt(object);
if (temp) json = temp;
}
} catch (err) {
Expand Down

0 comments on commit 0f85ac1

Please sign in to comment.