utils.js
function source(value, indent, limit, offset, visited) {
  var result;
  var names;
  var nestingIndex;
  var isCompact = !isUndefined(limit);

  indent = indent || "    ";
  offset = (offset || "");
  result = "";
  visited = visited || [];

  if (isUndefined(value)) {
    result += "undefined";
  }
  else if (isNull(value)) {
    result += "null";
  }
  else if (isString(value)) {
    result += "\"" + value + "\"";
  }
  else if (isFunction(value)) {
    value = String(value).split("\n");
    if (isCompact && value.length > 2) {
      value = value.splice(0, 2);
      value.push("...}");
    }
    result += value.join("\n" + offset);
  }
  else if (isArray(value)) {
    if ((nestingIndex = (visited.indexOf(value) + 1))) {
      result = "#" + nestingIndex + "#";
    }
    else {
      visited.push(value);

      if (isCompact)
        value = value.slice(0, limit);

      result += "[\n";
      result += value.map(function(value) {
        return offset + indent + source(value, indent, limit, offset + indent,
                                        visited);
      }).join(",\n");
      result += isCompact && value.length > limit ?
                ",\n" + offset + "...]" : "\n" + offset + "]";
    }
  }
  else if (isObject(value)) {
    if ((nestingIndex = (visited.indexOf(value) + 1))) {
      result = "#" + nestingIndex + "#"
    }
    else {
      visited.push(value)

      names = Object.keys(value);

      result += "{ // " + value + "\n";
      result += (isCompact ? names.slice(0, limit) : names).map(function(name) {
        var _limit = isCompact ? limit - 1 : limit;
        var descriptor = Object.getOwnPropertyDescriptor(value, name);
        var result = offset + indent + "// ";
        var accessor;
        if (0 <= name.indexOf(" "))
          name = "\"" + name + "\"";

        if (descriptor.writable)
          result += "writable ";
        if (descriptor.configurable)
          result += "configurable ";
        if (descriptor.enumerable)
          result += "enumerable ";

        result += "\n";
        if ("value" in descriptor) {
          result += offset + indent + name + ": ";
          result += source(descriptor.value, indent, _limit, indent + offset,
                           visited);
        }
        else {

          if (descriptor.get) {
            result += offset + indent + "get " + name + " ";
            accessor = source(descriptor.get, indent, _limit, indent + offset,
                              visited);
            result += accessor.substr(accessor.indexOf("{"));
          }

          if (descriptor.set) {
            if (descriptor.get) result += ",\n";
            result += offset + indent + "set " + name + " ";
            accessor = source(descriptor.set, indent, _limit, indent + offset,
                              visited);
            result += accessor.substr(accessor.indexOf("{"));
          }
        }
        return result;
      }).join(",\n");

      if (isCompact) {
        if (names.length > limit && limit > 0) {
          result += ",\n" + offset  + indent + "//...";
        }
      }
      else {
        if (names.length)
          result += ",";

        result += "\n" + offset + indent + "\"__proto__\": ";
        result += source(Object.getPrototypeOf(value), indent, 0,
                         offset + indent);
      }

      result += "\n" + offset + "}";
    }
  }
  else {
    result += String(value);
  }
  return result;
}
function source(value, indent, limit, offset, visited) {
  var result;
  var names;
  var nestingIndex;
  var isCompact = !isUndefined(limit);

  indent = indent || "    ";
  offset = (offset || "");
  result = "";
  visited = visited || [];

  if (isUndefined(value)) {
    result += "undefined";
  }
  else if (isNull(value)) {
    result += "null";
  }
  else if (isString(value)) {
    result += "\"" + value + "\"";
  }
  else if (isFunction(value)) {
    value = String(value).split("\n");
    if (isCompact && value.length > 2) {
      value = value.splice(0, 2);
      value.push("...}");
    }
    result += value.join("\n" + offset);
  }
  else if (isArray(value)) {
    if ((nestingIndex = (visited.indexOf(value) + 1))) {
      result = "#" + nestingIndex + "#";
    }
    else {
      visited.push(value);

      if (isCompact)
        value = value.slice(0, limit);

      result += "[\n";
      result += value.map(function(value) {
        return offset + indent + source(value, indent, limit, offset + indent,
                                        visited);
      }).join(",\n");
      result += isCompact && value.length > limit ?
                ",\n" + offset + "...]" : "\n" + offset + "]";
    }
  }
  else if (isObject(value)) {
    if ((nestingIndex = (visited.indexOf(value) + 1))) {
      result = "#" + nestingIndex + "#"
    }
    else {
      visited.push(value)

      names = Object.keys(value);

      result += "{ // " + value + "\n";
      result += (isCompact ? names.slice(0, limit) : names).map(function(name) {
        var _limit = isCompact ? limit - 1 : limit;
        var descriptor = Object.getOwnPropertyDescriptor(value, name);
        var result = offset + indent + "// ";
        var accessor;
        if (0 <= name.indexOf(" "))
          name = "\"" + name + "\"";

        if (descriptor.writable)
          result += "writable ";
        if (descriptor.configurable)
          result += "configurable ";
        if (descriptor.enumerable)
          result += "enumerable ";

        result += "\n";
        if ("value" in descriptor) {
          result += offset + indent + name + ": ";
          result += source(descriptor.value, indent, _limit, indent + offset,
                           visited);
        }
        else {

          if (descriptor.get) {
            result += offset + indent + "get " + name + " ";
            accessor = source(descriptor.get, indent, _limit, indent + offset,
                              visited);
            result += accessor.substr(accessor.indexOf("{"));
          }

          if (descriptor.set) {
            if (descriptor.get) result += ",\n";
            result += offset + indent + "set " + name + " ";
            accessor = source(descriptor.set, indent, _limit, indent + offset,
                              visited);
            result += accessor.substr(accessor.indexOf("{"));
          }
        }
        return result;
      }).join(",\n");

      if (isCompact) {
        if (names.length > limit && limit > 0) {
          result += ",\n" + offset  + indent + "//...";
        }
      }
      else {
        if (names.length)
          result += ",";

        result += "\n" + offset + indent + "\"__proto__\": ";
        result += source(Object.getPrototypeOf(value), indent, 0,
                         offset + indent);
      }

      result += "\n" + offset + "}";
    }
  }
  else {
    result += String(value);
  }
  return result;
}
function source ( value , indent , limit , offset , visited ) { var result ; var names ; var nestingIndex ; var isCompact = ! isUndefined ( limit ) ; indent = indent || "    " ; offset = ( offset || "" ) ; result = "" ; visited = visited || [ ] ; if ( isUndefined ( value ) ) { result += "undefined" ; } else if ( isNull ( value ) ) { result += "null" ; } else if ( isString ( value ) ) { result += "\"" + value + "\"" ; } else if ( isFunction ( value ) ) { value = String ( value ) . split ( "\n" ) ; if ( isCompact && value . length > 2 ) { value = value . splice ( 0 , 2 ) ; value . push ( "...}" ) ; } result += value . join ( "\n" + offset ) ; } else if ( isArray ( value ) ) { if ( ( nestingIndex = ( visited . indexOf ( value ) + 1 ) ) ) { result = "#" + nestingIndex + "#" ; } else { visited . push ( value ) ; if ( isCompact ) value = value . slice ( 0 , limit ) ; result += "[\n" ; result += value . map ( function ( value ) { return offset + indent + source ( value , indent , limit , offset + indent , visited ) ; } ) . join ( ",\n" ) ; result += isCompact && value . length > limit ? ",\n" + offset + "...]" : "\n" + offset + "]" ; } } else if ( isObject ( value ) ) { if ( ( nestingIndex = ( visited . indexOf ( value ) + 1 ) ) ) { result = "#" + nestingIndex + "#" } else { visited . push ( value ) names = Object . keys ( value ) ; result += "{ // " + value + "\n" ; result += ( isCompact ? names . slice ( 0 , limit ) : names ) . map ( function ( name ) { var _limit = isCompact ? limit - 1 : limit ; var descriptor = Object . getOwnPropertyDescriptor ( value , name ) ; var result = offset + indent + "// " ; var accessor ; if ( 0 <= name . indexOf ( " " ) ) name = "\"" + name + "\"" ; if ( descriptor . writable ) result += "writable " ; if ( descriptor . configurable ) result += "configurable " ; if ( descriptor . enumerable ) result += "enumerable " ; result += "\n" ; if ( "value" in descriptor ) { result += offset + indent + name + ": " ; result += source ( descriptor . value , indent , _limit , indent + offset , visited ) ; } else { if ( descriptor . get ) { result += offset + indent + "get " + name + " " ; accessor = source ( descriptor . get , indent , _limit , indent + offset , visited ) ; result += accessor . substr ( accessor . indexOf ( "{" ) ) ; } if ( descriptor . set ) { if ( descriptor . get ) result += ",\n" ; result += offset + indent + "set " + name + " " ; accessor = source ( descriptor . set , indent , _limit , indent + offset , visited ) ; result += accessor . substr ( accessor . indexOf ( "{" ) ) ; } } return result ; } ) . join ( ",\n" ) ; if ( isCompact ) { if ( names . length > limit && limit > 0 ) { result += ",\n" + offset + indent + "//..." ; } } else { if ( names . length ) result += "," ; result += "\n" + offset + indent + "\"__proto__\": " ; result += source ( Object . getPrototypeOf ( value ) , indent , 0 , offset + indent ) ; } result += "\n" + offset + "}" ; } } else { result += String ( value ) ; } return result ; }
Function returns textual representation of a value passed to it. Function
takes additional `indent` argument that is used for indentation. Also
optional `limit` argument may be passed to limit amount of detail returned.
@param {Object} value
@param {String} [indent="    "]
@param {Number} [limit]
Function returns textual representation of a value passed to it . Function takes additional indent argument that is used for indentation . Also optional limit argument may be passed to limit amount of detail returned .