From 734e8c714ca505ba301df088d9d9c7f8ee5eec45 Mon Sep 17 00:00:00 2001 From: Ruslan Boliev Date: Mon, 24 Dec 2018 17:28:33 +0300 Subject: [PATCH] Enhanced object literals support (#39) --- index.js | 36 ++++++++++++++++++++++++++++++------ test/unit/serialize.js | 16 ++++++++++++++++ 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 4578984..d778057 100644 --- a/index.js +++ b/index.js @@ -11,8 +11,11 @@ var UID = Math.floor(Math.random() * 0x10000000000).toString(16) var PLACE_HOLDER_REGEXP = new RegExp('"@__(F|R|D)-' + UID + '-(\\d+)__@"', 'g'); var IS_NATIVE_CODE_REGEXP = /\{\s*\[native code\]\s*\}/g; +var IS_PURE_FUNCTION = /function.*?\(/; var UNSAFE_CHARS_REGEXP = /[<>\/\u2028\u2029]/g; +var RESERVED_SYMBOLS = ['*', 'async']; + // Mapping of unsafe HTML and invalid JavaScript line terminator chars to their // Unicode char counterparts which are safe to use in JavaScript strings. var ESCAPED_CHARS = { @@ -68,6 +71,32 @@ module.exports = function serialize(obj, options) { return value; } + function serializeFunc(fn) { + var serializedFn = fn.toString(); + if (IS_NATIVE_CODE_REGEXP.test(serializedFn)) { + throw new TypeError('Serializing native function: ' + fn.name); + } + + // pure functions, example: {key: function() {}} + if(IS_PURE_FUNCTION.test(serializedFn)) { + return serializedFn; + } + + var argsStartsAt = serializedFn.indexOf('('); + var def = serializedFn.substr(0, argsStartsAt).trim().split(' ').filter(val => val.length > 0); + var nonReservedSymbols = def.filter(val => RESERVED_SYMBOLS.indexOf(val) === -1); + + // enhanced literal objects, example: {key() {}} + if(nonReservedSymbols.length > 0) { + return (def.indexOf('async') > -1 ? 'async ' : '') + 'function' + + (def.join('').indexOf('*') > -1 ? '*' : '') + + serializedFn.substr(argsStartsAt); + } + + // arrow functions + return serializedFn; + } + var str; // Creates a JSON string representation of the value. @@ -108,12 +137,7 @@ module.exports = function serialize(obj, options) { } var fn = functions[valueIndex]; - var serializedFn = fn.toString(); - - if (IS_NATIVE_CODE_REGEXP.test(serializedFn)) { - throw new TypeError('Serializing native function: ' + fn.name); - } - return serializedFn; + return serializeFunc(fn); }); } diff --git a/test/unit/serialize.js b/test/unit/serialize.js index bec4dae..e7eeefb 100644 --- a/test/unit/serialize.js +++ b/test/unit/serialize.js @@ -109,6 +109,22 @@ describe('serialize( obj )', function () { try { serialize(Number); } catch (e) { err = e; } expect(err).to.be.an.instanceOf(TypeError); }); + + it('should serialize enhanced literal objects', function () { + var obj = { + foo() { return true; }, + *bar() { return true; } + }; + + expect(serialize(obj)).to.equal('{"foo":function() { return true; },"bar":function*() { return true; }}'); + }); + + it('should deserialize enhanced literal objects', function () { + var obj; + eval('obj = ' + serialize({ hello() { return true; } })); + + expect(obj.hello()).to.equal(true); + }); }); describe('regexps', function () {