From aa250b8cca73d4b4fec1b56b83b2cffab3a0fe9c Mon Sep 17 00:00:00 2001 From: SidStraw Date: Fri, 17 Dec 2021 01:48:13 +0800 Subject: [PATCH] Add support for Error object (#135) --- README.md | 3 ++- index.js | 13 +++++++++++-- test/unit/serialize.js | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8736fdb..f47b122 100644 --- a/README.md +++ b/README.md @@ -47,13 +47,14 @@ serialize({ fn : function echo(arg) { return arg; }, re : /([^\s]+)/g, big : BigInt(10), + err : new Error('Error message.'), }); ``` The above will produce the following string output: ```js -'{"str":"string","num":0,"obj":{"foo":"foo"},"arr":[1,2,3],"bool":true,"nil":null,"undef":undefined,"inf":Infinity,"date":new Date("2016-04-28T22:02:17.000Z"),"map":new Map([["hello","world"]]),"set":new Set([123,456]),"fn":function echo(arg) { return arg; },"re":new RegExp("([^\\\\s]+)", "g"),"big":BigInt("10")}' +'{"str":"string","num":0,"obj":{"foo":"foo"},"arr":[1,2,3],"bool":true,"nil":null,"undef":undefined,"inf":Infinity,"date":new Date("2016-04-28T22:02:17.000Z"),"map":new Map([["hello","world"]]),"set":new Set([123,456]),"fn":function echo(arg) { return arg; },"re":new RegExp("([^\\\\s]+)", "g"),"big":BigInt("10"),"err":new Error("Error message.")}' ``` Note: to produced a beautified string, you can pass an optional second argument to `serialize()` to define the number of spaces to be used for the indentation. diff --git a/index.js b/index.js index ab82742..f53b6a8 100644 --- a/index.js +++ b/index.js @@ -11,7 +11,7 @@ var randomBytes = require('randombytes'); // Generate an internal UID to make the regexp pattern harder to guess. var UID_LENGTH = 16; var UID = generateUID(); -var PLACE_HOLDER_REGEXP = new RegExp('(\\\\)?"@__(F|R|D|M|S|A|U|I|B|L)-' + UID + '-(\\d+)__@"', 'g'); +var PLACE_HOLDER_REGEXP = new RegExp('(\\\\)?"@__(F|R|D|M|S|A|U|I|B|L|E)-' + UID + '-(\\d+)__@"', 'g'); var IS_NATIVE_CODE_REGEXP = /\{\s*\[native code\]\s*\}/g; var IS_PURE_FUNCTION = /function.*?\(/; @@ -73,6 +73,7 @@ module.exports = function serialize(obj, options) { var infinities= []; var bigInts = []; var urls = []; + var errors = []; // Returns placeholders for functions and regexps (identified by index) // which are later replaced by their string representation. @@ -119,6 +120,10 @@ module.exports = function serialize(obj, options) { if(origValue instanceof URL) { return '@__L-' + UID + '-' + (urls.push(origValue) - 1) + '__@'; } + + if(origValue instanceof Error) { + return '@__E-' + UID + '-' + (errors.push(origValue) - 1) + '__@'; + } } if (type === 'function') { @@ -210,7 +215,7 @@ module.exports = function serialize(obj, options) { str = str.replace(UNSAFE_CHARS_REGEXP, escapeUnsafeChars); } - if (functions.length === 0 && regexps.length === 0 && dates.length === 0 && maps.length === 0 && sets.length === 0 && arrays.length === 0 && undefs.length === 0 && infinities.length === 0 && bigInts.length === 0 && urls.length === 0) { + if (functions.length === 0 && regexps.length === 0 && dates.length === 0 && maps.length === 0 && sets.length === 0 && arrays.length === 0 && undefs.length === 0 && infinities.length === 0 && bigInts.length === 0 && urls.length === 0 && errors.length === 0) { return str; } @@ -261,6 +266,10 @@ module.exports = function serialize(obj, options) { return "new URL(\"" + urls[valueIndex].toString() + "\")"; } + if (type === 'E') { + return "new Error(\"" + errors[valueIndex].message + "\")"; + } + var fn = functions[valueIndex]; return serializeFunc(fn); diff --git a/test/unit/serialize.js b/test/unit/serialize.js index 6510ec2..6130757 100644 --- a/test/unit/serialize.js +++ b/test/unit/serialize.js @@ -466,6 +466,20 @@ describe('serialize( obj )', function () { }); }); + describe('Error', function () { + it('should serialize Error', function () { + var e = new Error('Error message.') + expect(serialize(e)).to.equal('new Error("Error message.")'); + expect(serialize({t: [e]})).to.be.a('string').equal('{"t":[new Error("Error message.")]}'); + }); + + it('should deserialize Error', function () { + var d = eval(serialize(new Error('Error message.'))); + expect(d).to.be.a('Error'); + expect(d.message).to.equal('Error message.'); + }); + }); + describe('XSS', function () { it('should encode unsafe HTML chars to Unicode', function () { expect(serialize('')).to.equal('"\\u003C\\u002Fscript\\u003E"');