Nickolay - Joose-3.001

Documentation | Source
(function(){

    Joose.Proto = function(){ throw "Modules may not be instantiated." }
    
    
    Joose.Proto.Object = function (){
        throw "Joose.Proto.Object can't be instantiated"
    }
    
    
        
    var findSuperCall = function(startFrom){
        //sufficient for Joose.Proto.Class
        var self = startFrom.caller
        
        if (!self.SUPER) throw "Invalid call to SUPER"
        
        //self._original is always undefined for Joose.Proto.Class
        return self._original || self.SUPER[self.methodName]
    }
    
    var SUPER = function (){
        return findSuperCall(SUPER).apply(this, arguments)
    }
    
    var SUPERARG = function (){
        return findSuperCall(SUPERARG).apply(this, arguments[0])
    }
    
    //XXX switch to closures    
    var INNER = function (){
        //sufficient for augment modifiers and original methods from Joose.Proto.Class
        var self = INNER.caller.caller
        
        //required for original methods from Joose.Managed.Class which can be also 'around' modifiers
        if (self.SUPER || self.AROUND) self = self.caller
        
        var callstack = self.__INNER_STACK__
        if (!callstack) throw "Invalid call to INNER"
        
        var augmentWrapper = function(){
            var innerCall = callstack.pop()
            
            return innerCall ? innerCall.apply(this, arguments) : undefined
        }
        
        augmentWrapper.__INNER_STACK__ = callstack
        
        return augmentWrapper.apply(this, arguments)
    }        
    
    
    Joose.Proto.Object.prototype = {
        
        SUPERARG : SUPERARG,
        SUPER : SUPER,
        INNER : INNER,        
        
        
        initialize: function () {
        },
        
        
        toString: function () {
            return "a " + this.meta.name
        },
        
        
		detach : function() {
			if (this.isDetached()) return this
			
        	var detachedClass = new Joose.Meta.Class.Detached(null, { isa : this.constructor }).c
        	
        	detachedClass.meta.stem.open()
        	
        	detachedClass.prototype = this
        	
        	this.meta = detachedClass.meta
            
        	var original = this.meta.originalClass = this.constructor
        	detachedClass.my = original.my
            
            this.constructor = detachedClass
        	
        	detachedClass.meta.stem.close()
            
            return this
		},
		
		
		attach : function() {
			if (!this.isDetached()) return this
			
			this.meta.stem.open()
			
			this.constructor.prototype = {}
			
			delete this.constructor
			delete this.meta
            
            //XXX hack for metaroles with custom builders
            if (this.builder && this.builder.isDetached()) this.builder.attach()
            if (this.stem && this.stem.isDetached()) this.stem.attach()
            
            return this
		},
        
        
        isDetached : function () {
            return this.meta instanceof Joose.Meta.Class.Detached 
        }
        
    }
        
    
    Joose.Proto.Object.meta = {
    	constructor : Joose.Proto.Object,
    	
        methods : Joose.Proto.Object.prototype,
        attributes : {}
    }
    
    Joose.Proto.Object.prototype.meta = Joose.Proto.Object.meta
    
    
    Joose.Proto.Empty = function(){ throw "Joose.Proto.Empty can't be instantiated" }
    
    Joose.Proto.Empty.meta = {
        methods : {},
        attributes : {}
    }
    

})()