1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 /* Managed JavaScript Inheritance
 27  * Based on John Resig's Simple JavaScript Inheritance http://ejohn.org/blog/simple-javascript-inheritance/
 28  * MIT Licensed.
 29  */
 30 
 31 /**
 32  * @namespace
 33  */
 34 var cc = cc || {};
 35 
 36 //
 37 function ClassManager(){
 38     //tells own name
 39     return arguments.callee.name || (arguments.callee.toString()).match(/^function ([^(]+)/)[1];
 40 }
 41 ClassManager.id=(0|(Math.random()*998));
 42 ClassManager.instanceId=(0|(Math.random()*998));
 43 ClassManager.compileSuper=function(func, name, id){
 44     //make the func to a string
 45     var str = func.toString();
 46     //find parameters
 47     var pstart = str.indexOf('(');
 48     var pend = str.indexOf(')');
 49     var params = str.substring(pstart+1, pend);
 50     params = params.trim();
 51 
 52     //find function body
 53     var bstart = str.indexOf('{');
 54     var bend = str.lastIndexOf('}');
 55     var str = str.substring(bstart+1, bend);
 56 
 57     //now we have the content of the function, replace this._super
 58     //find this._super
 59     while(str.indexOf('this._super')!= -1)
 60     {
 61         var sp = str.indexOf('this._super');
 62         //find the first '(' from this._super)
 63         var bp = str.indexOf('(', sp);
 64 
 65         //find if we are passing params to super
 66         var bbp = str.indexOf(')', bp);
 67         var superParams = str.substring(bp+1, bbp);
 68         superParams = superParams.trim();
 69         var coma = superParams? ',':'';
 70 
 71         //find name of ClassManager
 72         var Cstr = arguments.callee.ClassManager();
 73 
 74         //replace this._super
 75         str = str.substring(0, sp)+  Cstr+'['+id+'].'+name+'.call(this'+coma+str.substring(bp+1);
 76     }
 77     return Function(params, str);
 78 };
 79 ClassManager.compileSuper.ClassManager = ClassManager;
 80 ClassManager.getNewID=function(){
 81     return this.id++;
 82 };
 83 ClassManager.getNewInstanceId=function(){
 84     return this.instanceId++;
 85 };
 86 
 87 (function () {
 88     var initializing = false, fnTest = /\b_super\b/;
 89     var releaseMode = (document['ccConfig'] && document['ccConfig']['CLASS_RELEASE_MODE']) ? document['ccConfig']['CLASS_RELEASE_MODE'] : null;
 90     if(releaseMode) {
 91         console.log("release Mode");
 92     }
 93 
 94     /**
 95      * The base Class implementation (does nothing)
 96      * @class
 97      */
 98     cc.Class = function () {
 99     };
100 
101     /**
102      * Create a new Class that inherits from this Class
103      * @param {object} prop
104      * @return {function}
105      */
106     cc.Class.extend = function (prop) {
107         var _super = this.prototype;
108 
109         // Instantiate a base Class (but only create the instance,
110         // don't run the init constructor)
111         var prototype = Object.create(_super);
112 
113         var classId = ClassManager.getNewID();
114         ClassManager[classId] = _super;
115         // Copy the properties over onto the new prototype. We make function
116         // properties non-eumerable as this makes typeof === 'function' check
117         // unneccessary in the for...in loop used 1) for generating Class()
118         // 2) for cc.clone and perhaps more. It is also required to make
119         // these function properties cacheable in Carakan.
120         var desc = { writable: true, enumerable: false, configurable: true };
121         for (var name in prop) {
122             if(releaseMode && typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])) {
123                 desc.value = ClassManager.compileSuper(prop[name], name, classId);
124                 Object.defineProperty(prototype, name, desc);
125             } else if(typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])){
126                 desc.value = (function (name, fn) {
127                     return function () {
128                         var tmp = this._super;
129 
130                         // Add a new ._super() method that is the same method
131                         // but on the super-Class
132                         this._super = _super[name];
133 
134                         // The method only need to be bound temporarily, so we
135                         // remove it when we're done executing
136                         var ret = fn.apply(this, arguments);
137                         this._super = tmp;
138 
139                         return ret;
140                     };
141                 })(name, prop[name]);
142                 Object.defineProperty(prototype, name, desc);
143             } else if(typeof prop[name] == "function") {
144                 desc.value = prop[name];
145                 Object.defineProperty(prototype, name, desc);
146             } else{
147                 prototype[name] = prop[name];
148             }
149         }
150         prototype.__instanceId = null;
151 
152         // The dummy Class constructor
153         function Class() {
154             this.__instanceId = ClassManager.getNewInstanceId();
155             // All construction is actually done in the init method
156             if (this.ctor)
157                 this.ctor.apply(this, arguments);
158         }
159 
160         Class.id = classId;
161         // desc = { writable: true, enumerable: false, configurable: true,
162         //          value: XXX }; Again, we make this non-enumerable.
163         desc.value = classId;
164         Object.defineProperty(prototype, '__pid', desc);
165 
166         // Populate our constructed prototype object
167         Class.prototype = prototype;
168 
169         // Enforce the constructor to be what we expect
170         desc.value = Class;
171         Object.defineProperty(Class.prototype, 'constructor', desc);
172 
173         // And make this Class extendable
174         Class.extend = arguments.callee;
175 
176         //add implementation method
177         Class.implement = function (prop) {
178             for (var name in prop) {
179                 prototype[name] = prop[name];
180             }
181         };
182         return Class;
183     };
184 
185     Function.prototype.bind = Function.prototype.bind || function (bind) {
186         var self = this;
187         return function () {
188             var args = Array.prototype.slice.call(arguments);
189             return self.apply(bind || null, args);
190         };
191     };
192 
193 })();
194 
195 //
196 // Another way to subclass: Using Google Closure.
197 // The following code was copied + pasted from goog.base / goog.inherits
198 //
199 cc.inherits = function (childCtor, parentCtor) {
200     /** @constructor */
201     function tempCtor() {}
202     tempCtor.prototype = parentCtor.prototype;
203     childCtor.superClass_ = parentCtor.prototype;
204     childCtor.prototype = new tempCtor();
205     childCtor.prototype.constructor = childCtor;
206 
207     // Copy "static" method, but doesn't generate subclasses.
208 //  for( var i in parentCtor ) {
209 //      childCtor[ i ] = parentCtor[ i ];
210 //  }
211 };
212 cc.base = function(me, opt_methodName, var_args) {
213     var caller = arguments.callee.caller;
214     if (caller.superClass_) {
215         // This is a constructor. Call the superclass constructor.
216         ret =  caller.superClass_.constructor.apply( me, Array.prototype.slice.call(arguments, 1));
217         return ret;
218     }
219 
220     var args = Array.prototype.slice.call(arguments, 2);
221     var foundCaller = false;
222     for (var ctor = me.constructor;
223         ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {
224         if (ctor.prototype[opt_methodName] === caller) {
225             foundCaller = true;
226         } else if (foundCaller) {
227             return ctor.prototype[opt_methodName].apply(me, args);
228         }
229     }
230 
231     // If we did not find the caller in the prototype chain,
232     // then one of two things happened:
233     // 1) The caller is an instance method.
234     // 2) This method was not called by the right caller.
235     if (me[opt_methodName] === caller) {
236         return me.constructor.prototype[opt_methodName].apply(me, args);
237     } else {
238         throw Error(
239                     'cc.base called from a method of one name ' +
240                     'to a method of a different name');
241     }
242 };
243 
244 cc.concatObjectProperties = function(dstObject, srcObject){
245     if(!dstObject)
246         dstObject = {};
247 
248     for(var selKey in srcObject){
249         dstObject[selKey] = srcObject[selKey];
250     }
251     return dstObject;
252 };
253 
254