<commit_before>var inherits        = require('./inherits');
var inheritsDirectly= require('./inheritsDirectly');
var isInheritedFrom = require('./isInheritedFrom');
var isMixinedFrom   = require('./isMixinedFrom');
var newPrototype    = require('./newPrototype');

var getOwnPropertyNames = Object.getOwnPropertyNames;

/**
 *  Mixin multi classes to ctor.
 *  mixin(Class, ParentClass1, ParentClass2, ...)
 *  + __mixin_ctors__ array to keep the mixined super ctors
 *  + anonymous mixin_ctor hook to super_.
 *  inject into methods to implement inherit.
 *
 *  A11 -> A1 -> A -> Root
 *  B11 -> B1 -> B -> Root
 *  C11 -> C1 -> C -> Root
 *  mixin B11, C
 *  clone C.prototype to MixinCtor.prototype
 *  for k,method of C.prototype
 *    originalMethod = MixinCtor.prototype[k]
 *    if isFunction(originalMethod) and originalMethod.__mixin_prototype__
 *      #B11.__super__ is MixinCtor.prototype
 *      method  = ->
 *        B11.__super__ = originalMethod.__mixin_prototype__
 *        method.apply this, arguments
 *        B11.__super__ = MixinCtor
 *      method.__mixin_prototype__ = C.prototype
 *  B11 -> MixinCtor -> B1 -> B -> Root
 *
class Root
   m: -> console.log 'root'
class C
   m: ->
     console.log "c"
     super
class B
class B11
   m: -> 
     console.log 'b11'
     super

mixin B11, C
 *
 */


function isSuperInFunction(aMethod) {
  return ('function' === typeof aMethod) && aMethod.__mixin_super__ && aMethod.toString().indexOf('__super__')>=0;
}

function mixin(ctor, superCtor) {
  function clonePrototype(dest, src) {
    var sp = src.prototype;
    var dp = dest.prototype;
    var names = getOwnPropertyNames(sp);
    for (var i = 1; i < names.length; i++ ) { //i = 1 to skip constructor property
      var k = names[i];
      var method = sp[k];
      var originalMethod = dp[k];
      if (isSuperInFunction(originalMethod) && sp !== originalMethod.__mixin_super__) {
        method = (function(origM, newM, src) {
          var oldSuper = src.__super__;
          return function() {
            src.__super__ = origM.__mixin_super__;
            var result = newM.apply(this, arguments);
            src.__super__ = oldSuper;
            return result;
          };
        })(originalMethod, method, src);
      }<commit_msg>* update doc on mixin.js<commit_after>var inherits        = require('./inherits');
var inheritsDirectly= require('./inheritsDirectly');
var isInheritedFrom = require('./isInheritedFrom');
var isMixinedFrom   = require('./isMixinedFrom');
var newPrototype    = require('./newPrototype');

var getOwnPropertyNames = Object.getOwnPropertyNames;

/**
 *  Mixin multi classes to ctor.
 *  mixin(Class, ParentClass1, ParentClass2, ...)
 *  + __mixin_ctors__ array to keep the mixined super ctors
 *  + anonymous mixin_ctor hook to super_.
 *  inject into methods to implement inherit.
 *
 *  A11 -> A1 -> A -> Root
 *  B11 -> B1 -> B -> Root
 *  C11 -> C1 -> C -> Root
 *  mixin B11, C
 *  clone C.prototype to MixinCtor.prototype
 *  for k,method of C.prototype
 *    originalMethod = MixinCtor.prototype[k]
 *    if isFunction(originalMethod) and originalMethod.__mixin_prototype__
 *      #B11.__super__ is MixinCtor.prototype
 *      method  = ->
 *        B11.__super__ = originalMethod.__mixin_prototype__
 *        method.apply this, arguments
 *        B11.__super__ = MixinCtor
 *      method.__mixin_prototype__ = C.prototype
 *  B11 -> MixinCtor -> B1 -> B -> Root
 *
mixin the exists method: the new mixin method will oerwrite the old one.

```coffee
class Root
  m: ->
    console.log 'root'
    console.log '----'
class C
  inherits C, Root
  m: ->
    console.log "c"
    super
class B
  inherits B, Root
  m: ->
    console.log "b"
    super
class B11
  inherits B11, B
  m: -> 
    console.log 'b11'
    super

b = new B11
b.m()
mixin B11, C
b = new B11
b.m() 

# The console results:
# b11
# b
# root
# ----
# b11
# c
# root
# ----

```


 *
 */


function isSuperInFunction(aMethod) {
  return ('function' === typeof aMethod) && aMethod.__mixin_super__ && aMethod.toString().indexOf('__super__')>=0;
}

function mixin(ctor, superCtor) {
  function clonePrototype(dest, src) {
    var sp = src.prototype;
    var dp = dest.prototype;
    var names = getOwnPropertyNames(sp);
    for (var i = 1; i < names.length; i++ ) { //i = 1 to skip constructor property
      var k = names[i];
      var method = sp[k];
      var originalMethod = dp[k];
      if (isSuperInFunction(originalMethod) && sp !== originalMethod.__mixin_super__) {
        method = (function(origM, newM, src) {
          var oldSuper = src.__super__;
          return function() {
            src.__super__ = origM.__mixin_super__;
            var result = newM.apply(this, arguments);
            src.__super__ = oldSuper;
            return result;
          };
        })(originalMethod, method, src);
      }
{'fraction_non_alphanumeric': 0.12523171987641607, 'fraction_numerical': 0.014830072090628218, 'mean_word_length': 2.6787878787878787, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5059544', 'n_tokens_mistral': 1598, 'n_tokens_neox': 1559, 'n_words': 419}