// get-constructors.js

this.constructors = function () {
  'use strict';

  // getProto
  var getProto = Object.getPrototypeOf ? Object.getPrototypeOf :
    Object.prototype.__proto__ ?
    function getProto(obj) { return obj.__proto__; } :
    function getProto(obj) {
      var ctor = obj.constructor;
      if (typeof ctor === 'function') {
        if (ctor.prototype !== obj)
          return ctor.prototype;
        if (typeof ctor['super'] === 'function')
          return ctor['super'].prototype;
        if (typeof ctor.super_ === 'function')
          return ctor.super_.prototype;
      }
      return obj.__proto__;
    };

  try {
    Object.name = 'Object';
    Array.name  = 'Array';
    Error.name  = 'Error';
    RegExp.name = 'RegExp';
    String.name = 'String';
    Number.name = 'Number';
    Boolean.name = 'Boolean';
    Function.name = 'Function';
  } catch (err) {}

  // constructors
  function constructors(obj) {
    // supports: getter and normal function
    if (arguments.length === 0) obj = this;

    // convert to object from primitives
    if (obj != null && typeof obj !== 'object' && typeof obj !== 'function')
      obj = Object(obj);

    if (obj === Array) return [Array, Function.prototype];
    if (obj === Error) return [Error, Function.prototype];
    if (obj === RegExp) return [RegExp, Function.prototype];
    if (obj === Object) return [Object, Function.prototype];
    if (obj === String) return [String, Function.prototype];
    if (obj === Number) return [Number, Function.prototype];
    if (obj === Boolean) return [Boolean, Function.prototype];
    if (obj === Function) return [Function, Function.prototype];
    if (obj.constructor === Array) return [Array, Object];
    if (obj.constructor === Error) return [Error, Object];
    if (obj.constructor === RegExp) return [RegExp, Object];
    if (obj.constructor === Object) return [Object];
    if (obj.constructor === String) return [String, Object];
    if (obj.constructor === Number) return [Number, Object];
    if (obj.constructor === Boolean) return [Boolean, Object];

    var classes = [];

    if (obj instanceof Function) {
      // for Class/constructor
      for (; obj; obj = (obj['super'] || obj.super_ || getProto(obj)))
        if (typeof obj === 'function')
          classes.push(obj);

      if (classes.length === 0 ||
          classes[classes.length - 1] !== Function.prototype)
        classes.push(Function.prototype);
    }
    else {
      var saveObj = obj;

      // for instance/object
      for (; obj; obj = getProto(obj)) {
        if (obj.hasOwnProperty) {
          if (obj.hasOwnProperty('constructor'))
            classes.push(obj.constructor);
        }
        else if (obj.constructor) {
          if (classes.length === 0 ||
              classes[classes.length - 1] !== obj.constructor)
            classes.push(obj.constructor);
        }
      }

      if (classes.length === 0 &&
          typeof saveObj.constructor === 'function')
        classes = [saveObj.constructor];

      if (classes.length === 0 ||
          classes[classes.length - 1] !== Object)
        classes.push(Object);
    }

    return classes;
  }

  // extendPrototype
  constructors.extendPrototype = function extendPrototype(ctor) {
    ctor = ctor || Object;

    if (ctor.prototype.constructors !== constructors)
      ctor.prototype.constructors = constructors;

    return this;
  };


  // fnameRegExp: function name regular expression
  var fnameRegExp = /^\s*function\s*\**\s*([^\(\s]*)[\S\s]+$/im;

  // defProp(obj, prop, propDesc)
  var defProp = function (obj) {
    if (!Object.defineProperty) return null;
    try {
      Object.defineProperty(obj, 'prop', {value: 'str'});
      return obj.prop === 'str' ? Object.defineProperty : null;
    } catch (err) { return null; }
  } ({});

  // defGetter(obj, prop, getter)
  var defGetter = 
    Object.prototype.__defineGetter__ ?
    function defGetter(obj, prop, getter) {
      return obj.__defineGetter__(prop, getter); } :
    defProp ?
    function defGetter(obj, prop, getter) {
      return defProp(obj, prop, {get: getter}); } :
    function defGetter(obj, prop, getter) {};

  // Function.prototype.name for ie
  if (!Function.prototype.hasOwnProperty('name'))
    defGetter(Function.prototype, 'name',
      function nameOfFunction() {
        return ('' + this).replace(fnameRegExp, '$1'); });

  // exports
  if (typeof module === 'object' && module.exports)
    module.exports = constructors;

  return constructors;

}();

@@ -635,222 +635,316 @@
 %0A%0A  
-try %7B%0A    Object.name = 'Object';%0A    Array.name  = '
+function names(name, fn) %7B%0A    if (fn.name !== name)%0A      fn.name = name;%0A  %7D%0A%0A  try %7B%0A    names('Object', Object);%0A    names('Array', 
 Array
-'
+)
 ;%0A    
-Error.name  = '
+names('Error', 
 Error
-'
+)
 ;%0A    
-RegExp.name = '
+names('RegExp', 
 RegExp
-'
+)
 ;%0A    
-String.name = '
+names('String', 
 String
-'
+)
 ;%0A    
-Number.name = '
+names('Number', 
 Number
-'
+)
 ;%0A    
-Boolean.name = '
+names('Boolean', 
 Boolean
-'
+)
 ;%0A    
+names('
 Function
 .nam
@@ -943,25 +943,19 @@
 tion
-.name = '
+', 
 Function
 ';%0A 
@@ -950,17 +950,17 @@
 Function
-'
+)
 ;%0A  %7D ca
@@ -3501,125 +3501,8 @@
 ;%0A%0A%0A
-  // fnameRegExp: function name regular expression%0A  var fnameRegExp = /%5E%5Cs*function%5Cs*%5C**%5Cs*(%5B%5E%5C(%5Cs%5D*)%5B%5CS%5Cs%5D+$/im;%0A%0A
   //
@@ -3531,16 +3531,16 @@
 opDesc)%0A
+
   var de
@@ -3839,16 +3839,121 @@
 etter = 
+defProp ?%0A    function defGetter(obj, prop, getter) %7B%0A      return defProp(obj, prop, %7Bget: getter%7D); %7D :
 %0A    Obj
@@ -4086,22 +4086,8 @@
 %7D :%0A
-    defProp ?%0A
     
@@ -4129,105 +4129,126 @@
 r) %7B
-%0A      return defProp(obj, prop, %7Bget: getter%7D); %7D :%0A    function defGetter(obj, prop, getter) %7B%7D
+%7D;%0A%0A  // fnameRegExp: function name regular expression%0A  var fnameRegExp = /%5E%5Cs*function%5Cs*%5C**%5Cs*(%5B%5E%5C(%5Cs%5D*)%5B%5CS%5Cs%5D+$/im
 ;%0A%0A 

support ie9