From 7f3ac252d86b802454cb43782820aea2e0f6dc25 Mon Sep 17 00:00:00 2001 From: Ryan Delaney Date: Mon, 21 Jun 2021 06:43:32 -0700 Subject: [PATCH] Add support for URL's (#123) --- index.js | 13 +++++++++++-- test/unit/serialize.js | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 640db8f..ab82742 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)-' + UID + '-(\\d+)__@"', 'g'); +var PLACE_HOLDER_REGEXP = new RegExp('(\\\\)?"@__(F|R|D|M|S|A|U|I|B|L)-' + UID + '-(\\d+)__@"', 'g'); var IS_NATIVE_CODE_REGEXP = /\{\s*\[native code\]\s*\}/g; var IS_PURE_FUNCTION = /function.*?\(/; @@ -72,6 +72,7 @@ module.exports = function serialize(obj, options) { var undefs = []; var infinities= []; var bigInts = []; + var urls = []; // Returns placeholders for functions and regexps (identified by index) // which are later replaced by their string representation. @@ -114,6 +115,10 @@ module.exports = function serialize(obj, options) { return '@__A-' + UID + '-' + (arrays.push(origValue) - 1) + '__@'; } } + + if(origValue instanceof URL) { + return '@__L-' + UID + '-' + (urls.push(origValue) - 1) + '__@'; + } } if (type === 'function') { @@ -205,7 +210,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) { + 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) { return str; } @@ -252,6 +257,10 @@ module.exports = function serialize(obj, options) { return "BigInt(\"" + bigInts[valueIndex] + "\")"; } + if (type === 'L') { + return "new URL(\"" + urls[valueIndex].toString() + "\")"; + } + var fn = functions[valueIndex]; return serializeFunc(fn); diff --git a/test/unit/serialize.js b/test/unit/serialize.js index bd24070..6510ec2 100644 --- a/test/unit/serialize.js +++ b/test/unit/serialize.js @@ -452,6 +452,20 @@ describe('serialize( obj )', function () { }); }); + describe('URL', function () { + it('should serialize URL', function () { + var u = new URL('https://x.com/') + expect(serialize(u)).to.equal('new URL("https://x.com/")'); + expect(serialize({t: [u]})).to.be.a('string').equal('{"t":[new URL("https://x.com/")]}'); + }); + + it('should deserialize URL', function () { + var d = eval(serialize(new URL('https://x.com/'))); + expect(d).to.be.a('URL'); + expect(d.toString()).to.equal('https://x.com/'); + }); + }); + describe('XSS', function () { it('should encode unsafe HTML chars to Unicode', function () { expect(serialize('')).to.equal('"\\u003C\\u002Fscript\\u003E"');