Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
ref: Use local json-stringify-save package
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilogorek committed Sep 22, 2017
1 parent 4981c06 commit 00b0c83
Show file tree
Hide file tree
Showing 6 changed files with 348 additions and 9 deletions.
2 changes: 1 addition & 1 deletion lib/client.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

var stringify = require('json-stringify-safe');
var stringify = require('../vendor/json-stringify-safe');
var parsers = require('./parsers');
var zlib = require('zlib');
var utils = require('./utils');
Expand Down
2 changes: 1 addition & 1 deletion lib/parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

var cookie = require('cookie');
var urlParser = require('url');
var stringify = require('json-stringify-safe');
var stringify = require('../vendor/json-stringify-safe');

var utils = require('./utils');

Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
},
"dependencies": {
"cookie": "0.3.1",
"json-stringify-safe": "5.0.1",
"lsmod": "1.0.0",
"stack-trace": "0.0.9",
"timed-out": "4.0.1",
Expand All @@ -46,12 +45,12 @@
"glob": "~3.1.13",
"husky": "^0.14.3",
"istanbul": "^0.4.3",
"koa": "*",
"lint-staged": "^4.0.4",
"mocha": "~3.1.2",
"nock": "~9.0.0",
"prettier": "^1.6.1",
"should": "11.2.0"
"should": "11.2.0",
"sinon": "^3.3.0"
},
"prettier": {
"singleQuote": true,
Expand Down
9 changes: 5 additions & 4 deletions test/run.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ path = require('path')

mocha = new Mocha

fs.readdirSync('test').filter (file) ->
return file.substr(-3) == '.js';
.forEach (file) ->
mocha.addFile path.join('test', file)
['test', 'test/vendor'].forEach (dir) ->
fs.readdirSync(dir).filter (file) ->
file.substr(-3) == '.js';
.forEach (file) ->
mocha.addFile path.join(dir, file)

mocha.run (failures) ->
process.on 'exit', () ->
Expand Down
291 changes: 291 additions & 0 deletions test/vendor/json-stringify-safe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
'use strict';

var Sinon = require('sinon');
var assert = require('assert');
var stringify = require('../../vendor/json-stringify-safe');

function jsonify(obj) {
return JSON.stringify(obj, null, 2);
}

describe('Stringify', function() {
it('must stringify circular objects', function() {
var obj = {name: 'Alice'};
obj.self = obj;
var json = stringify(obj, null, 2);
assert.deepEqual(json, jsonify({name: 'Alice', self: '[Circular ~]'}));
});

it('must stringify circular objects with intermediaries', function() {
var obj = {name: 'Alice'};
obj.identity = {self: obj};
var json = stringify(obj, null, 2);
assert.deepEqual(json, jsonify({name: 'Alice', identity: {self: '[Circular ~]'}}));
});

it('must stringify circular objects deeper', function() {
var obj = {name: 'Alice', child: {name: 'Bob'}};
obj.child.self = obj.child;

assert.deepEqual(
stringify(obj, null, 2),
jsonify({
name: 'Alice',
child: {name: 'Bob', self: '[Circular ~.child]'}
})
);
});

it('must stringify circular objects deeper with intermediaries', function() {
var obj = {name: 'Alice', child: {name: 'Bob'}};
obj.child.identity = {self: obj.child};

assert.deepEqual(
stringify(obj, null, 2),
jsonify({
name: 'Alice',
child: {name: 'Bob', identity: {self: '[Circular ~.child]'}}
})
);
});

it('must stringify circular objects in an array', function() {
var obj = {name: 'Alice'};
obj.self = [obj, obj];

assert.deepEqual(
stringify(obj, null, 2),
jsonify({
name: 'Alice',
self: ['[Circular ~]', '[Circular ~]']
})
);
});

it('must stringify circular objects deeper in an array', function() {
var obj = {name: 'Alice', children: [{name: 'Bob'}, {name: 'Eve'}]};
obj.children[0].self = obj.children[0];
obj.children[1].self = obj.children[1];

assert.deepEqual(
stringify(obj, null, 2),
jsonify({
name: 'Alice',
children: [
{name: 'Bob', self: '[Circular ~.children.0]'},
{name: 'Eve', self: '[Circular ~.children.1]'}
]
})
);
});

it('must stringify circular arrays', function() {
var obj = [];
obj.push(obj);
obj.push(obj);
var json = stringify(obj, null, 2);
assert.deepEqual(json, jsonify(['[Circular ~]', '[Circular ~]']));
});

it('must stringify circular arrays with intermediaries', function() {
var obj = [];
obj.push({name: 'Alice', self: obj});
obj.push({name: 'Bob', self: obj});

assert.deepEqual(
stringify(obj, null, 2),
jsonify([
{name: 'Alice', self: '[Circular ~]'},
{name: 'Bob', self: '[Circular ~]'}
])
);
});

it('must stringify repeated objects in objects', function() {
var obj = {};
var alice = {name: 'Alice'};
obj.alice1 = alice;
obj.alice2 = alice;

assert.deepEqual(
stringify(obj, null, 2),
jsonify({
alice1: {name: 'Alice'},
alice2: {name: 'Alice'}
})
);
});

it('must stringify repeated objects in arrays', function() {
var alice = {name: 'Alice'};
var obj = [alice, alice];
var json = stringify(obj, null, 2);
assert.deepEqual(json, jsonify([{name: 'Alice'}, {name: 'Alice'}]));
});

it('must call given decycler and use its output', function() {
var obj = {};
obj.a = obj;
obj.b = obj;

var decycle = Sinon.spy(function() {
return decycle.callCount;
});
var json = stringify(obj, null, 2, decycle);
assert.deepEqual(json, jsonify({a: 1, b: 2}, null, 2));

assert.strictEqual(decycle.callCount, 2);
assert.strictEqual(decycle.thisValues[0], obj);
assert.strictEqual(decycle.args[0][0], 'a');
assert.strictEqual(decycle.args[0][1], obj);
assert.strictEqual(decycle.thisValues[1], obj);
assert.strictEqual(decycle.args[1][0], 'b');
assert.strictEqual(decycle.args[1][1], obj);
});

it('must call replacer and use its output', function() {
var obj = {name: 'Alice', child: {name: 'Bob'}};

var replacer = Sinon.spy(bangString);
var json = stringify(obj, replacer, 2);
assert.deepEqual(json, jsonify({name: 'Alice!', child: {name: 'Bob!'}}));

assert.strictEqual(replacer.callCount, 4);
assert.strictEqual(replacer.args[0][0], '');
assert.strictEqual(replacer.args[0][1], obj);
assert.strictEqual(replacer.thisValues[1], obj);
assert.strictEqual(replacer.args[1][0], 'name');
assert.strictEqual(replacer.args[1][1], 'Alice');
assert.strictEqual(replacer.thisValues[2], obj);
assert.strictEqual(replacer.args[2][0], 'child');
assert.strictEqual(replacer.args[2][1], obj.child);
assert.strictEqual(replacer.thisValues[3], obj.child);
assert.strictEqual(replacer.args[3][0], 'name');
assert.strictEqual(replacer.args[3][1], 'Bob');
});

it('must call replacer after describing circular references', function() {
var obj = {name: 'Alice'};
obj.self = obj;

var replacer = Sinon.spy(bangString);
var json = stringify(obj, replacer, 2);
assert.deepEqual(json, jsonify({name: 'Alice!', self: '[Circular ~]!'}));

assert.strictEqual(replacer.callCount, 3);
assert.strictEqual(replacer.args[0][0], '');
assert.strictEqual(replacer.args[0][1], obj);
assert.strictEqual(replacer.thisValues[1], obj);
assert.strictEqual(replacer.args[1][0], 'name');
assert.strictEqual(replacer.args[1][1], 'Alice');
assert.strictEqual(replacer.thisValues[2], obj);
assert.strictEqual(replacer.args[2][0], 'self');
assert.strictEqual(replacer.args[2][1], '[Circular ~]');
});

it('must call given decycler and use its output for nested objects', function() {
var obj = {};
obj.a = obj;
obj.b = {self: obj};

var decycle = Sinon.spy(function() {
return decycle.callCount;
});
var json = stringify(obj, null, 2, decycle);
assert.deepEqual(json, jsonify({a: 1, b: {self: 2}}));

assert.strictEqual(decycle.callCount, 2);
assert.strictEqual(decycle.args[0][0], 'a');
assert.strictEqual(decycle.args[0][1], obj);
assert.strictEqual(decycle.args[1][0], 'self');
assert.strictEqual(decycle.args[1][1], obj);
});

it("must use decycler's output when it returned null", function() {
var obj = {a: 'b'};
obj.self = obj;
obj.selves = [obj, obj];

function decycle() {
return null;
}
assert.deepEqual(
stringify(obj, null, 2, decycle),
jsonify({
a: 'b',
self: null,
selves: [null, null]
})
);
});

it("must use decycler's output when it returned undefined", function() {
var obj = {a: 'b'};
obj.self = obj;
obj.selves = [obj, obj];

function decycle() {}
assert.deepEqual(
stringify(obj, null, 2, decycle),
jsonify({
a: 'b',
selves: [null, null]
})
);
});

it('must throw given a decycler that returns a cycle', function() {
var obj = {};
obj.self = obj;
var err;
function identity(key, value) {
return value;
}
try {
stringify(obj, null, 2, identity);
} catch (ex) {
err = ex;
}
assert.ok(err instanceof TypeError);
});

describe('.getSerialize', function() {
it('must stringify circular objects', function() {
var obj = {a: 'b'};
obj.circularRef = obj;
obj.list = [obj, obj];

var json = JSON.stringify(obj, stringify.getSerialize(), 2);
assert.deepEqual(
json,
jsonify({
a: 'b',
circularRef: '[Circular ~]',
list: ['[Circular ~]', '[Circular ~]']
})
);
});

// This is the behavior as of Mar 3, 2015.
// The serializer function keeps state inside the returned function and
// so far I'm not sure how to not do that. JSON.stringify's replacer is not
// called _after_ serialization.
xit('must return a function that could be called twice', function() {
var obj = {name: 'Alice'};
obj.self = obj;

var json;
var serializer = stringify.getSerialize();

json = JSON.stringify(obj, serializer, 2);
assert.deepEqual(json, jsonify({name: 'Alice', self: '[Circular ~]'}));

json = JSON.stringify(obj, serializer, 2);
assert.deepEqual(json, jsonify({name: 'Alice', self: '[Circular ~]'}));
});
});
});

function bangString(key, value) {
return typeof value === 'string' ? value + '!' : value;
}
48 changes: 48 additions & 0 deletions vendor/json-stringify-safe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use strict';

/*
json-stringify-safe
Like JSON.stringify, but doesn't throw on circular references.
Originally forked from https://github.com/isaacs/json-stringify-safe
version 5.0.1 on 2017-09-21 and modified to handle Errors serialization.
Tests for this are in test/vendor.
ISC license: https://github.com/isaacs/json-stringify-safe/blob/master/LICENSE
*/

exports = module.exports = stringify;
exports.getSerialize = serializer;

function stringify(obj, replacer, spaces, cycleReplacer) {
return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces);
}

function serializer(replacer, cycleReplacer) {
var stack = [];
var keys = [];

if (cycleReplacer == null) {
cycleReplacer = function(key, value) {
if (stack[0] === value) {
return '[Circular ~]';
}
return '[Circular ~.' + keys.slice(0, stack.indexOf(value)).join('.') + ']';
};
}

return function(key, value) {
if (stack.length > 0) {
var thisPos = stack.indexOf(this);
~thisPos ? stack.splice(thisPos + 1) : stack.push(this);
~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key);
if (~stack.indexOf(value)) {
value = cycleReplacer.call(this, key, value);
}
} else {
stack.push(value);
}

return replacer == null ? value : replacer.call(this, key, value);
};
}

0 comments on commit 00b0c83

Please sign in to comment.