These are chat archives for canjs/canjs

24th
Jun 2017
Frank Lemanschik
@frank-dspeed
Jun 24 2017 09:19
@matthewp and only for your info i reviewed the meeting if you want to do es6 inharitanze
you get constructors and prototypes and you need to call super(args1, args2)
inside of the constructor that extends a other
super() inside of a class constructor is the constructor of the class it extends
and here only for your reference my master piece of demonstrating inharitance i call it compose i compose objects with it like mixin
'use strict';

function getPrototypeChain(prototype)
{
  var chain = [];

  while(prototype)
  {
    chain.push(prototype);
    prototype = Object.getPrototypeOf(prototype);
  }
  return chain;
}

function commonInChain(chainA, chainB)
{
  return chainA.find(function(aPrototype)
    {
      return chainB.find(function(bPrototype)
      {
        if(aPrototype._copyOf)
          aPrototype = aPrototype._copyOf;
        if(bPrototype._copyOf)
          bPrototype = bPrototype._copyOf;
        return aPrototype == bPrototype;
      });
    });
}

function commonPrototypeReducer(a, b)
{
  var chainA = getPrototypeChain(a);
  var chainB = getPrototypeChain(b);

  return commonInChain(chainA, chainB);
};

function commonPrototype()
{
  var prototypes = Array.prototype.map.call(arguments, function(x) { return x.prototype; });
  return prototypes.reduce(commonPrototypeReducer);
}

/*
Example of compose operations
Suppose there is a hierarchy of constructors whose prototypes are set like this:
A --> B --> Base (--> Object)
      ^       ^
C ----|       |
              |
D ------------
Then the the result of the following operations will be a constructor with a prototype chain like that:
* compose(A, B)
    (A --> B --> Base)
    Comment: The prototype chain already has the specified order
* compose(A, C)
    A new --> C new --> (B --> Base)
* compose(D, A)

    D new --> A new --> (B --> Base)
* compose(A, D)

    A new --> B new --> (D --> Base)
* compose(A, C, D)
    A new --> C new --> B new --> (D --> Base)
* compose(A, D, C)
    A new --> B new --> D new --> (C --> B --> Base)
    Warning: A duplicate clone of the prototype of "B" will be created
    One of the following two constructs will clarify the placement of "B" in the prototype chain
* compose(A, B, D, C)
    A new --> B new --> D new --> C new --> Base
* compose(A, D, C, B)
    A new --> D new --> (C --> B --> Base)
where "new" denotes a copy of the prototype with an altered prototype and () denotes the unaltered part of a prototype chain
*/

function chainToString(chain)
{
  return chain.map(function(C) { return C.test? C.test() : '?'; }).join(" --> ");
}

function filterChain(newChain, chain, prototypes)
{
  var base = commonInChain(newChain, chain);
  //console.log("Base of", chainToString(newChain), "and", chainToString(chain), "is", base.test ? base.test() : '?');
  var baseIndex = newChain.indexOf(base);
  var filteredChain = newChain.slice(0, baseIndex).filter(function(c)
  {
    return c == newChain[0] || prototypes.indexOf(c) == -1;
  });
  return filteredChain;
};

function createChain(chain)
{
  chain = chain.slice();

  var chainHead = chain.pop()

  while(chain.length > 0)
  {
    var current = chain.pop();

    if(Object.getPrototypeOf(current) == chainHead)
    {
      chainHead = current;
    }
    else
    {
      chainHead = Object.create(chainHead);
      Object.assign(chainHead, current);
      chainHead._copyOf = current;
    }
  }

  return chainHead;
};

function createConstructor(constructors)
{
  return function()
  {
    for(var i = constructors.length-1; i >= 0; i--)
    {
      constructors[i].apply(this, arguments);
    }
  };
};

function compose()
{
  var constructors = Array.prototype.slice.call(arguments);
  var prototypes = constructors.map(function(C) { return C.prototype; });

  var chain = [Object.getPrototypeOf({})];
  var previousChain = chain;

  constructors.reverse().forEach(function(C, i)
  {
    var currentChain = getPrototypeChain(C.prototype);

    var newChain = filterChain(currentChain, previousChain, prototypes);

    chain = newChain.concat(chain);
    previousChain = currentChain;
  });

  //console.log(chainToString(chain));

  var prototype = createChain(chain);
  var constructor = createConstructor(constructors);
  constructor.prototype = prototype;

  return constructor;
}

/*
// Test code
function Base()
{
}
Base.prototype =
{
  test: function() { return 'Base'; }
};
function B()
{
}
B.prototype = new Base();
B.prototype.test = function() { return 'B'; };
function A
ah shit sorry
Frank Lemanschik
@frank-dspeed
Jun 24 2017 09:29
i often use that to produce composed drivers i have bus modules device modules and protocol modules that i need to mixin