Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

javascript-stringify

Package Overview
Dependencies
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

javascript-stringify - npm Package Compare versions

Comparing version 1.2.0 to 1.3.0

11

javascript-stringify.d.ts

@@ -1,3 +0,10 @@

declare function javascriptStringify (value: any, replacer?: Function, space?: string | number): string;
declare function stringify (value: any, replacer?: Function, space?: string | number, options?: javascriptStringify.Options): string;
export = javascriptStringify;
declare namespace javascriptStringify {
export interface Options {
maxDepth?: number;
references?: boolean;
}
}
export = stringify;

201

javascript-stringify.js

@@ -21,4 +21,2 @@ (function (root, stringify) {

* Source: https://github.com/douglascrockford/JSON-js/blob/master/json2.js
*
* @type {RegExp}
*/

@@ -29,4 +27,2 @@ var ESCAPABLE = /[\\\'\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;

* Map of characters to escape characters.
*
* @type {Object}
*/

@@ -47,6 +43,6 @@ var META_CHARS = {

*
* @param {String} char
* @return {String}
* @param {string} char
* @return {string}
*/
var escapeChar = function (char) {
function escapeChar (char) {
var meta = META_CHARS[char];

@@ -77,10 +73,15 @@

/**
* Test for valid JavaScript identifier.
*/
var IS_VALID_IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
/**
* Check if a variable name is valid.
*
* @param {String} name
* @return {Boolean}
* @param {string} name
* @return {boolean}
*/
var isValidVariableName = function (name) {
return !RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name);
};
function isValidVariableName (name) {
return !RESERVED_WORDS[name] && IS_VALID_IDENTIFIER.test(name);
}

@@ -90,18 +91,36 @@ /**

*
* @return {String}
* @return {string}
*/
var toGlobalVariable = function (value, indent, stringify) {
function toGlobalVariable (value) {
return 'Function(' + stringify('return this;') + ')()';
};
}
/**
* Convert JavaScript objects into strings.
* Serialize the path to a string.
*
* @type {Object}
* @param {Array} path
* @return {string}
*/
function toPath (path) {
var result = '';
for (var i = 0; i < path.length; i++) {
if (isValidVariableName(path[i])) {
result += '.' + path[i];
} else {
result += '[' + stringify(path[i]) + ']';
}
}
return result;
}
/**
* Convert JavaScript objects into strings.
*/
var OBJECT_TYPES = {
'[object Array]': function (array, indent, stringify) {
'[object Array]': function (array, indent, next) {
// Map array values to their stringified values with correct indentation.
var values = array.map(function (value) {
var str = stringify(value);
var values = array.map(function (value, index) {
var str = next(value, index);

@@ -122,3 +141,3 @@ if (str === undefined) {

},
'[object Object]': function (object, indent, stringify) {
'[object Object]': function (object, indent, next) {
if (typeof Buffer === 'function' && Buffer.isBuffer(object)) {

@@ -130,3 +149,3 @@ return 'new Buffer(' + stringify(object.toString()) + ')';

var values = Object.keys(object).reduce(function (values, key) {
var value = stringify(object[key]);
var value = next(object[key], key);

@@ -192,4 +211,2 @@ // Omit `undefined` object values.

* Convert JavaScript primitives into strings.
*
* @type {Object}
*/

@@ -211,10 +228,10 @@ var PRIMITIVE_TYPES = {

* @param {*} value
* @param {String} indent
* @param {Function} stringify
* @return {String}
* @param {string} indent
* @param {Function} next
* @return {string}
*/
var stringify = function (value, indent, stringify) {
function stringify (value, indent, next) {
// Convert primitives into strings.
if (Object(value) !== value) {
return PRIMITIVE_TYPES[typeof value](value, indent, stringify);
return PRIMITIVE_TYPES[typeof value](value, indent, next);
}

@@ -226,4 +243,4 @@

// Convert objects into strings.
return toString && toString(value, indent, stringify);
};
return toString ? toString(value, indent, next) : undefined;
}

@@ -233,7 +250,7 @@ /**

*
* @param {Object} value
* @param {*} value
* @param {Function} [replacer]
* @param {(Number|String)} [space]
* @param {Object} [options]
* @return {String}
* @param {(number|string)} [space]
* @param {Object} [options]
* @return {string}
*/

@@ -248,46 +265,106 @@ return function (value, replacer, space, options) {

var maxDepth = options.maxDepth || 200;
var maxDepth = Number(options.maxDepth) || 100;
var references = !!options.references;
var depth = 0;
var cache = [];
var path = [];
var stack = [];
var encountered = [];
var paths = [];
var restore = [];
/**
* Handle recursion by checking if we've visited this node every iteration.
* Stringify the next value in the stack.
*
* @param {*} value
* @return {String}
* @param {string} key
* @return {string}
*/
var recurse = function (value, next) {
// If we've already visited this node before, break the recursion.
if (cache.indexOf(value) > -1 || depth > maxDepth) {
return;
}
function next (value, key) {
path.push(key);
var result = recurse(value, stringify);
path.pop();
return result;
}
// Push the value into the values cache to avoid an infinite loop.
depth++;
cache.push(value);
/**
* Handle recursion by checking if we've visited this node every iteration.
*
* @param {*} value
* @param {Function} stringify
* @return {string}
*/
var recurse = references ?
function (value, stringify) {
if (value && (typeof value === 'object' || typeof value === 'function')) {
var exists = encountered.indexOf(value);
// Stringify the value and fallback to
return next(value, space, function (value) {
var result = recurse(value, next);
// Track nodes to restore later.
if (exists > -1) {
restore.push(path.slice(), paths[exists]);
return;
}
depth--;
cache.pop();
// Track encountered nodes.
encountered.push(value);
paths.push(path.slice());
}
return result;
});
};
// Stop when we hit the max depth.
if (path.length > maxDepth) {
return;
}
// Stringify the value and fallback to
return stringify(value, space, next);
} :
function (value, stringify) {
var seen = stack.indexOf(value);
if (seen > -1 || path.length > maxDepth) {
return;
}
stack.push(value);
var value = stringify(value, space, next);
stack.pop();
return value;
};
// If the user defined a replacer function, make the recursion function
// a double step process - `replacer -> stringify -> replacer -> etc`.
// a double step process - `recurse -> replacer -> stringify`.
if (typeof replacer === 'function') {
return recurse(value, function (value, space, next) {
return replacer(value, space, function (value) {
return stringify(value, space, next);
var before = recurse
// Intertwine the replacer function with the regular recursion.
recurse = function (value, stringify) {
return before(value, function (value, space, next) {
return replacer(value, space, function (value) {
return stringify(value, space, next);
});
});
});
};
}
return recurse(value, stringify);
var result = recurse(value, stringify);
// Attempt to restore circular references.
if (restore.length) {
var sep = space ? '\n' : '';
var assignment = space ? ' = ' : '=';
var eol = ';' + sep;
var before = space ? '(function () {' : '(function(){'
var after = '}())'
var results = ['var x' + assignment + result];
for (var i = 0; i < restore.length; i += 2) {
results.push('x' + toPath(restore[i]) + assignment + 'x' + toPath(restore[i + 1]));
}
results.push('return x');
return before + sep + results.join(eol) + eol + after
}
return result;
};
});
{
"name": "javascript-stringify",
"version": "1.2.0",
"version": "1.3.0",
"description": "Stringify is to `eval` as `JSON.stringify` is to `JSON.parse`",

@@ -5,0 +5,0 @@ "main": "javascript-stringify.js",

@@ -8,3 +8,3 @@ # JavaScript Stringify

Stringify is to `eval` as `JSON.stringify` is to `JSON.parse`.
> Stringify is to `eval` as `JSON.stringify` is to `JSON.parse`.

@@ -44,7 +44,8 @@ ## Installation

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.
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(value)` with the new value.
The `options` object allows some additional configuration:
* **maxDepth** The maximum depth to stringify to
* **maxDepth** _(number)_ The maximum depth of values to stringify
* **references** _(boolean)_ Restore circular/repeated references in the object (uses IIFE)

@@ -51,0 +52,0 @@ ### Examples

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc