Skip to content

Commit 8401708

Browse files
zalmoxisusblakeembrey
authored andcommitted
Enable maxDepth option for tracking depth
1 parent 4da13e4 commit 8401708

File tree

3 files changed

+54
-14
lines changed

3 files changed

+54
-14
lines changed

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,15 @@ define(function (require, exports, module) {
3737
## Usage
3838

3939
```javascript
40-
javascriptStringify(value[, replacer [, space]])
40+
javascriptStringify(value[, replacer [, space [, options]]])
4141
```
4242

4343
The API is similar to `JSON.stringify`. However, any value returned by the replacer will be used literally. For this reason, the replacer is passed three arguments - `value`, `indentation` and `stringify`. If you need to continue the stringification process inside your replacer, you can call `stringify` with the updated value.
4444

45+
The `options` object allows some additional configuration:
46+
47+
* **maxDepth** The maximum depth to stringify to
48+
4549
### Examples
4650

4751
```javascript
@@ -52,6 +56,8 @@ javascriptStringify('foo'); // "'foo'"
5256
javascriptStringify({ x: 5, y: 6}); // "{x:5,y:6}"
5357
javascriptStringify([1, 2, 3, 'string']); // "[1,2,3,'string']"
5458

59+
javascriptStringify({ a: { b: { c: 1 } } }, null, null, { maxDepth: 2 }); // "{a:{b:{}}}"
60+
5561
/**
5662
* Invalid key names are automatically stringified.
5763
*/

javascript-stringify.js

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -223,46 +223,59 @@
223223
* @param {Object} value
224224
* @param {Function} [replacer]
225225
* @param {(Number|String)} [space]
226+
* @param {Object} [options]
226227
* @return {String}
227228
*/
228-
return function (value, replacer, space) {
229+
return function (value, replacer, space, options) {
230+
options = options || {}
231+
229232
// Convert the spaces into a string.
230233
if (typeof space !== 'string') {
231234
space = new Array(Math.max(0, space|0) + 1).join(' ');
232235
}
233236

237+
var maxDepth = options.maxDepth || 200;
238+
239+
var depth = 0;
240+
var cache = [];
241+
234242
/**
235243
* Handle recursion by checking if we've visited this node every iteration.
236244
*
237245
* @param {*} value
238-
* @param {Array} cache
239246
* @return {String}
240247
*/
241-
var recurse = function (value, cache, next) {
248+
var recurse = function (value, next) {
242249
// If we've already visited this node before, break the recursion.
243-
if (cache.indexOf(value) > -1) {
250+
if (cache.indexOf(value) > -1 || depth > maxDepth) {
244251
return;
245252
}
246253

247254
// Push the value into the values cache to avoid an infinite loop.
255+
depth++;
248256
cache.push(value);
249257

250258
// Stringify the value and fallback to
251259
return next(value, space, function (value) {
252-
return recurse(value, cache.slice(), next);
260+
var result = recurse(value, next);
261+
262+
depth--;
263+
cache.pop();
264+
265+
return result;
253266
});
254267
};
255268

256269
// If the user defined a replacer function, make the recursion function
257270
// a double step process - `replacer -> stringify -> replacer -> etc`.
258271
if (typeof replacer === 'function') {
259-
return recurse(value, [], function (value, space, next) {
272+
return recurse(value, function (value, space, next) {
260273
return replacer(value, space, function (value) {
261274
return stringify(value, space, next);
262275
});
263276
});
264277
}
265278

266-
return recurse(value, [], stringify);
279+
return recurse(value, stringify);
267280
};
268281
});

test.js

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ var expect = require('chai').expect;
22
var stringify = require('./');
33

44
describe('javascript-stringify', function () {
5-
describe('types', function () {
6-
var test = function (input, result, indent) {
7-
return function () {
8-
expect(stringify(input, null, indent)).to.equal(result);
9-
};
5+
var test = function (input, result, indent, options) {
6+
return function () {
7+
expect(stringify(input, null, indent, options)).to.equal(result);
108
};
9+
};
1110

11+
describe('types', function () {
1212
describe('booleans', function () {
1313
it('should be stringified', test(true, 'true'));
1414
});
@@ -106,7 +106,17 @@ describe('javascript-stringify', function () {
106106
var obj = [1, 2, 3];
107107
obj.push(obj);
108108

109-
expect(stringify(obj)).to.equal("[1,2,3,undefined]");
109+
expect(stringify(obj)).to.equal('[1,2,3,undefined]');
110+
});
111+
112+
it('should use multiple references', function () {
113+
var obj = {}
114+
var child = {};
115+
116+
obj.a = child;
117+
obj.b = child;
118+
119+
expect(stringify(obj)).to.equal('{a:{},b:{}}');
110120
});
111121
});
112122

@@ -210,4 +220,15 @@ describe('javascript-stringify', function () {
210220
expect(string).to.equal('[object Object]');
211221
});
212222
});
223+
224+
describe('max depth', function () {
225+
var obj = { a: { b: { c: 1 } } };
226+
227+
it('should get all object', test(obj, '{a:{b:{c:1}}}'));
228+
229+
it(
230+
'should get part of the object',
231+
test(obj, '{a:{b:{}}}', null, { maxDepth: 2 })
232+
);
233+
});
213234
});

0 commit comments

Comments
 (0)