, classStatics = [ 'instantiate', 'fabricate', 'subclass' ]
, classMagic = [
- '__bases__', '__initialise__', '__class__', 'constructor', 'className',
+ '__bases__', '__initialise__', '__inits__', '__class__', 'constructor', 'className',
'__emitter__', '__static__', '__mixins__', '__id__'
] //.concat(classStatics)
, mixinSkip = [
function createInitialise(cls){
function initialise(){
var instance = this
- , binds = cls.fn.__bind__ // list of names to bind
+ , proto = cls.fn
+ , binds = proto.__bind__ // list of names to bind
+ , init = proto.init
+ , inits = proto.__inits__
+ , args = Y(arguments)
;
if (binds)
Y.bindAll(instance, binds);
- var init = cls.fn.init;
- if ( typeof init == 'function' ) {
- var result = init.apply(instance, arguments);
- if (result) instance = result; // XXX: I think this needs to go away
- }
+ if ( typeof init == 'function' && init !== arguments.callee )
+ init.apply(instance, args);
+
+ if ( inits && inits.length )
+ inits.invoke('apply', instance, args);
instance.emit('init', instance, {
'instance' : instance,
'cls' : cls,
- 'args' : Y(arguments)
+ 'args' : args
}, instance);
return instance;
return Y(initialise);
};
-function notClassMagic(v, k){
- return classMagic.indexOf(k) === -1;
-}
eval(constructor);
// Copy parent methods, then add new instance methods
- for (var k in parentMembers)
+ for (var k in parentMembers) {
if ( hasOwn.call(parentMembers,k) )
setDesc(prototype, k, getDesc(parentMembers,k));
else
prototype[k] = parentMembers[k];
+ }
- if ( prototype.toString === objToString )
+ if ( prototype.toString === objToString ) // check SuperClass.fn.toString
prototype.toString = classToString;
NewClass.className = prototype.className = className;
NewClass.prototype = NewClass.fn = prototype;
+ // Add class emitter
+ var ParentEmitter = (Parent.__emitter__ ? Parent : ClassFactory)
+ , ClassEmitter = NewClass.__emitter__ = new Emitter(NewClass, ParentEmitter)
+ , mixins = members.__mixins__ || []
+ ;
+
// Fix Constructors
NewClass.__super__ = SuperClass; // don't override NewClass.constructor -- it should be Function
- NewClass.__bases__ = NewClass.fn.__bases__ = Y([SuperClass]).concat( SuperClass.__bases__ || [ Class, Object ] );
+ NewClass.__bases__ = NewClass.fn.__bases__ = Y(mixins).concat( [SuperClass], SuperClass.__bases__ || [ Class, Object ] );
prototype.constructor = prototype.__class__ = NewClass;
+ prototype.__inits__ = new Y.YArray();
NewClass.init = prototype.__initialise__ = createInitialise(NewClass);
- // Add class emitter
- var ParentEmitter = (Parent.__emitter__ ? Parent : ClassFactory)
- , ClassEmitter = NewClass.__emitter__ = new Emitter(NewClass, ParentEmitter)
- ;
// Record for metaprogramming
KNOWN_CLASSES[className] = NewClass;
NewClass.__bind__ = prototype.__bind__;
- var mixins = NewClass.__mixins__ = Y([]).concat(members.__mixins__||[], SuperClass.__mixins__||[]).unique()
- , statics = NewClass.__static__ = {}
+ var statics = NewClass.__static__ = {}
, pstatics = SuperClass.__static__
, mstatics = members.__static__
;
}
NewClass.instantiate = instantiate.partial(NewClass);
- NewClass.__bind__ = prototype.__bind__ = Y([]).concat(prototype.__bind__||[], SuperClass.__bind__||[]).unique();
+ NewClass.__bind__ = prototype.__bind__ = Y(prototype.__bind__||[]).concat(SuperClass.__bind__||[]).unique();
// Notify mixins to let them finish up any customization
if (mixins.length)
ParentEmitter.emit('subclass',
NewClass, {
'className' : className,
- 'parent' : Parent,
- 'child' : NewClass,
+ 'super' : Parent,
+ 'cls' : NewClass,
'members' : members,
'prototype' : prototype
}, NewClass);
Class.fn = Class.prototype;
Class.fn.__class__ = Class.fn.constructor = Class;
Class.fn.__bases__ = Class.__bases__ = Y([ Object ]);
-Class.fn.__bind__ = Class.__bind__ = Y([]);
-Class.className = Class.fn.className = "Class";
+Class.fn.__bind__ = Class.__bind__ = Y([]);
+Class.fn.className = Class.className = "Class";
/* Class Methods */
* Mixes a Mixin into another Class.
*/
function mixin(cls, _mxn){
- var proto = cls.fn
- , bases = Y(cls.__bases__ || [])
- , cbinds = Y(cls.__bind__ || [])
+ var proto = (typeof cls === "function") ? cls.prototype : cls
+ , bases = cls.__bases__ = Y(cls.__bases__ || [])
+ , cbinds = cls.__bind__ = proto.__bind__ = Y(cls.__bind__ || [])
+ , cinits = cls.__inits__ = proto.__inits__ = Y(cls.__inits__ || [])
, cstatic = cls.__static__
, mxns = (Y.isArray(_mxn) ? _mxn.slice(0) : Y(arguments, 1))
;
throw new Error('Cannot mix in non-object! '+mxn);
var mproto = (typeof mxn === "function") ? mxn.fn : mxn
- , statics = mxn.__static__
+ , statics = mxn.__static__ || {}
, binds = mxn.__bind__
+ , init = mproto.init
, onCreate = mproto.onCreate
, firstMix = (bases && bases.indexOf(mxn) === -1)
;
core.extend(proto, core.filter(mproto, mixinFilter, mproto));
// Add mixin statics to class constructor
- if (statics){
- for (var k in statics)
- if ( hasOwn.call(statics,k) && classMagic.indexOf(k) === -1 ) {
- var desc = getDesc(statics,k);
- setDesc(cls, k, desc);
- setDesc(cstatic, k, desc);
- }
- }
+ for (var k in statics)
+ if ( hasOwn.call(statics,k) && classMagic.indexOf(k) === -1 ) {
+ var desc = getDesc(statics,k);
+ setDesc(cls, k, desc);
+ setDesc(cstatic, k, desc);
+ }
// Add/ensure the mixin is at the front of bases
bases.remove(mxn).unshift(mxn);
if (binds)
cls.__bind__ = proto.__bind__ = cbinds.concat(binds).unique();
+ // Wrap init call
+ if ( typeof init == 'function' )
+ cinits.remove(init).unshift(init);
+
// Only perform these actions the first time we mix into this class
if (!firstMix)
return;
Mixin.on('subclass',
function onMixinSubclass(evt){
var d = evt.data
- , mxn = d.child
+ , mxn = d.cls
, members = d.members
, onMixin = members.onMixin
;
exports['fabricate'] = Y.fabricate;
exports['lookupClass'] = lookupClass;
exports['mixin'] = mixin;
-exports['aggregate'] = aggregate;
+exports['aggregate'] = aggregate;
\ No newline at end of file