Skip to content

Commit

Permalink
Extract refs (yahoo#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
harvey-woo committed Apr 24, 2019
1 parent 423a382 commit 2727b83
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 4 deletions.
34 changes: 30 additions & 4 deletions index.js
Expand Up @@ -8,7 +8,7 @@ See the accompanying LICENSE file for terms.

// Generate an internal UID to make the regexp pattern harder to guess.
var UID = Math.floor(Math.random() * 0x10000000000).toString(16);
var PLACE_HOLDER_REGEXP = new RegExp('"@__(F|R|D|M|S)-' + UID + '-(\\d+)__@"', 'g');
var PLACE_HOLDER_REGEXP = new RegExp('"@__(F|R|D|M|S|O)-' + UID + '-(\\d+)__@"', 'g');

var IS_NATIVE_CODE_REGEXP = /\{\s*\[native code\]\s*\}/g;
var IS_PURE_FUNCTION = /function.*?\(/;
Expand All @@ -30,7 +30,7 @@ function escapeUnsafeChars(unsafeChar) {
return ESCAPED_CHARS[unsafeChar];
}

module.exports = function serialize(obj, options) {
module.exports = function serialize(obj, options, __seems__) {
options || (options = {});

// Backwards-compatibility for `space` as the second argument.
Expand All @@ -43,6 +43,7 @@ module.exports = function serialize(obj, options) {
var dates = [];
var maps = [];
var sets = [];
var seems = __seems__ || new Map();

// Returns placeholders for functions and regexps (identified by index)
// which are later replaced by their string representation.
Expand All @@ -56,6 +57,15 @@ module.exports = function serialize(obj, options) {
var origValue = this[key];
var type = typeof origValue;

if ((type === 'object' || type === 'function') && options.extractRef && origValue !== obj) {
var index = seems.get(origValue);
if (index === undefined) {
index = seems.size
seems.set(origValue, index)
}
return '@__O-' + UID + '-' + index + '__@'
}

if (type === 'object') {
if(origValue instanceof RegExp) {
return '@__R-' + UID + '-' + (regexps.push(origValue) - 1) + '__@';
Expand Down Expand Up @@ -136,14 +146,19 @@ 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) {
if (seems.size === 0 && functions.length === 0 && regexps.length === 0 && dates.length === 0 && maps.length === 0 && sets.length === 0) {
return str;
}

// Replaces all occurrences of function, regexp, date, map and set placeholders in the
// JSON string with their string representations. If the original value can
// not be found, then `undefined` is used.
return str.replace(PLACE_HOLDER_REGEXP, function (match, type, valueIndex) {
str = str.replace(PLACE_HOLDER_REGEXP, function (match, type, valueIndex) {

if (type === 'O') {
return "v" + valueIndex
}

if (type === 'D') {
return "new Date(\"" + dates[valueIndex].toISOString() + "\")";
}
Expand All @@ -164,4 +179,15 @@ module.exports = function serialize(obj, options) {

return serializeFunc(fn);
});

if (seems.size && !__seems__) {
var extractVariables = []

seems.forEach(function(key, obj) {
extractVariables.unshift("var v" + key + "=" + serialize(obj, options, seems) + ';')
})

str = "(function(){" + extractVariables.join('') + "return " + str + "})()"
}
return str
}
9 changes: 9 additions & 0 deletions test/unit/serialize.js
Expand Up @@ -297,6 +297,14 @@ describe('serialize( obj )', function () {
expect(serialize(["<"], {space: 2})).to.equal('[\n "\\u003C"\n]');
expect(serialize(["<"], {unsafe: true, space: 2})).to.equal('[\n "<"\n]');
});

it('should accept a `extractRef` option', function() {
var obj = { foo: 1, bar: 2 }
expect(serialize({ a: obj, b: obj}, { extractRef: true })).to.equal('(function(){var v0={"foo":1,"bar":2};return {"a":v0,"b":v0}})()')
var obj2 = { foo: 3, bar: 4 }
expect(serialize({ a: [obj, obj2], b: obj}, { extractRef: true })).to.equal('(function(){var v2={"foo":3,"bar":4};var v1={"foo":1,"bar":2};var v0=[v1,v2];return {"a":v0,"b":v1}})()')
})

});

describe('backwards-compatability', function () {
Expand All @@ -312,4 +320,5 @@ describe('serialize( obj )', function () {
expect(serialize([1], 2)).to.equal('[\n 1\n]');
});
});

});

0 comments on commit 2727b83

Please sign in to comment.