text: /**
   * @module inherit
   * @version 2.2.4
   * @author Filatov Dmitry <dfilatov@yandex-team.ru>
   * @description This module provides some syntax sugar for "class" declarations, constructors, mixins, "super" calls and static members.
   */
  
  (function(global) {
  
  var hasIntrospection = (function(){'_';}).toString().indexOf('_') > -1,
      emptyBase = function() {},
      hasOwnProperty = Object.prototype.hasOwnProperty,
      objCreate = Object.create || function(ptp) {
          var inheritance = function() {};
          inheritance.prototype = ptp;
          return new inheritance();
      },
      objKeys = Object.keys || function(obj) {
          var res = [];
          for(var i in obj) {
              hasOwnProperty.call(obj, i) && res.push(i);
          }
          return res;
      },
      extend = function(o1, o2) {
          for(var i in o2) {
              hasOwnProperty.call(o2, i) && (o1[i] = o2[i]);
          }
  
          return o1;
      },
      toStr = Object.prototype.toString,
      isArray = Array.isArray || function(obj) {
          return toStr.call(obj) === '[object Array]';
      },
      isFunction = function(obj) {
          return toStr.call(obj) === '[object Function]';
      },
      noOp = function() {},
      needCheckProps = true,
      testPropObj = { toString : '' };
  
  for(var i in testPropObj) { // fucking ie hasn't toString, valueOf in for
      testPropObj.hasOwnProperty(i) && (needCheckProps = false);
  }
  
  var specProps = needCheckProps? ['toString', 'valueOf'] : null;
  
  function getPropList(obj) {
      var res = objKeys(obj);
      if(needCheckProps) {
          var specProp, i = 0;
          while(specProp = specProps[i++]) {
              obj.hasOwnProperty(specProp) && res.push(specProp);
          }
      }
  
      return res;
  }
  
  function override(base, res, add) {
      var addList = getPropList(add),
          j = 0, len = addList.length,
          name, prop;
      while(j < len) {
          if((name = addList[j++]) === '__self') {
              continue;
          }
          prop = add[name];
          if(isFunction(prop) &&
                  (!hasIntrospection || prop.toString().indexOf('.__base') > -1)) {
              res[name] = (function(name, prop) {
                  var baseMethod = base[name]?
                          base[name] :
                          name === '__constructor'? // case of inheritance from plain function
                              res.__self.__parent :
                              noOp,
                      result = function() {
                          var baseSaved = this.__base;
  
                          this.__base = result.__base;
                          var res = prop.apply(this, arguments);
                          this.__base = baseSaved;
  
                          return res;
                      };
                  result.__base = baseMethod;
  
                  return result;
              })(name, prop);
          } else {
              res[name] = prop;
          }
      }
  }
  
  function applyMixins(mixins, res) {
      var i = 1, mixin;
      while(mixin = mixins[i++]) {
          res?
              isFunction(mixin)?
                  inherit.self(res, mixin.prototype, mixin) :
                  inherit.self(res, mixin) :
              res = isFunction(mixin)?
                  inherit(mixins[0], mixin.prototype, mixin) :
                  inherit(mixins[0], mixin);
      }
      return res || mixins[0];
  }
  
  /**
  * Creates class
  * @exports
  * @param {Function|Array} [baseClass|baseClassAndMixins] class (or class and mixins) to inherit from
  * @param {Object} prototypeFields
  * @param {Object} [staticFields]
  * @returns {Function} class
  */
  function inherit() {
      var args = arguments,
          withMixins = isArray(args[0]),
          hasBase = withMixins || isFunction(args[0]),
          base = hasBase? withMixins? applyMixins(args[0]) : args[0] : emptyBase,
          props = args[hasBase? 1 : 0] || {},
          staticProps = args[hasBase? 2 : 1],
          res = props.__constructor || (hasBase && base.prototype.__constructor)?
              function() {
                  return this.__constructor.apply(this, arguments);
              } :
              hasBase?
                  function() {
                      return base.apply(this, arguments);
                  } :
                  function() {};
  
      if(!hasBase) {
          res.prototype = props;
          res.prototype.__self = res.prototype.constructor = res;
          return extend(res, staticProps);
      }
  
      extend(res, base);
  
      res.__parent = base;
  
      var basePtp = base.prototype,
          resPtp = res.prototype = objCreate(basePtp);
  
      resPtp.__self = resPtp.constructor = res;
  
      props && override(basePtp, resPtp, props);
      staticProps && override(base, res, staticProps);
  
      return res;
  }
  
  inherit.self = function() {
      var args = arguments,
          withMixins = isArray(args[0]),
          base = withMixins? applyMixins(args[0], args[0][0]) : args[0],
          props = args[1],
          staticProps = args[2],
          basePtp = base.prototype;
  
      props && override(basePtp, basePtp, props);
      staticProps && override(base, base, staticProps);
  
      return base;
  };
  
  var defineAsGlobal = true;
  if(typeof exports === 'object') {
      module.exports = inherit;
      defineAsGlobal = false;
  }
  
  if(typeof modules === 'object' && typeof modules.define === 'function') {
      modules.define('inherit', function(provide) {
          provide(inherit);
      });
      defineAsGlobal = false;
  }
  
  if(typeof define === 'function') {
      define(function(require, exports, module) {
          module.exports = inherit;
      });
      defineAsGlobal = false;
  }
  
  defineAsGlobal && (global.inherit = inherit);
  
  })(this);
  